- This topic has 19 replies, 4 voices, and was last updated 13 years ago by String.
-
AuthorPosts
-
August 15, 2011 at 7:10 pm #187047autopilotMember
Since Paltalk 10 switched to the RichEdit20W control for room chat, a lot of people have struggled to retrieve incoming chat text. Here is a function I put together to return text from a given line:
Code Removed
See post below for new code.Note:
I don’t know why, but just like before, the line index is still index – 2.
So to read the 5th line, the index would be (5 – 2).August 15, 2011 at 8:07 pm #187066StringMemberWell done, Autopilot.
August 15, 2011 at 8:41 pm #187065autopilotMemberi could probably make the default much lower for the MaxBuffer, but I just set it ridiculously high to make sure it always picked up the whole line.
August 15, 2011 at 9:06 pm #187064ChikeMemberEM_GETLINE needs the available length as a WORD(2 bytes) at the beginning and that definately not what there with the loop.
baText(0) = iCount
baText(1) = iCount / 256
This would be good for CPUs that use little endian byte order.It shouldn’t matter if the text is ANSI or Unicode as the SendMessageA/SendMessageW should convert. How do you see the array in debugger as byte or unicode charachters?
August 15, 2011 at 9:35 pm #187063autopilotMember@Chike wrote:
baText(0) = iCount
baText(1) = iCount / 256
This would be good for CPUs that use little endian byte order.First, baText(0) would fail to get set and throw an exception any time iCount is larger then 255, and second, I would rather see a method that is CPU independent.
My function above may not be perfect, but has worked without fail in all of my testing situations so far.
August 15, 2011 at 9:43 pm #187062autopilotMember@Chike wrote:
EM_GETLINE needs the available length as a WORD(2 bytes) at the beginning and that definately not what there with the loop.
So are you saying that the longest line EM_GETLINE can return is a length as WORD = FFFF?
I have not tested with anything to see if and what the max is, but until I get problems with my function posted above, it is what I will be using.August 15, 2011 at 10:22 pm #187061ChikeMemberYes, longest possible text is 65535 charachters.
Use bSize whatever that is, basically you fill the array with zeros when using default.
Send the function max buffer smaller than actual line length(10, 100) and see what you get.
It is not about perfection it’s about writing code without bugs.
I am not familiar with pointer casting in .NET, little endian should be good enough for paltalk.August 15, 2011 at 11:36 pm #187060autopilotMemberAfter doing some investigation, my BitConverter.GetBytes was returning a 4 byte array = {1, 16, 0, 0}
The integer passed to BitConverter.GetBytes was 4097.
I am not sure why the BitConverter.GetBytes is returning a 4 bite array, but {1, 16} is correct for LittleEndian, so (if I understand it correctly) i need to reverse it to pass WORD {16, 1}. Therefore, I have removed the loop and changed it to:CODE REMOVED
Updated code in post belowNote:
I have tested with many MaxBuffer values and passing the reversed first 2 bytes are always correct for the (MaxBuffer * 2) + 1 value as long as the value is less then 65535. Any time it gets a value greater then 65535, it will then cause problems, so I set a cap of 32767.I also added an If statement to handle a case if the MaxBuffer value was too low (smaller then line length).
August 16, 2011 at 1:02 am #187059ChikeMemberIt returns a 4 byte result because it is sent a 32bit value.
You don’t need to reverse anything, and it’s still not going to be good for big endian machines which would need baText(0) = bSize(2) and baText(1) = bSize(3)
Unlike the x86 which converting from word to byte or double word is trivial, big endian machines need special instructions to do so.
I wouldn’t worry about endianness. Apart from mobile which this code wont work on anyway i am not aware of any other machines that run paltalk other then x86 or x64.August 16, 2011 at 8:13 am #187058ChikeMemberThe result of EM_GETLINE is the number of TCHARs copied, no need for any checking,, it will never be greater than erquested.
The word is the required TCHARs not the size of the buffer in bytes so no need to limit it to 32767, and it’s valu should be just MaxBuffer.
August 16, 2011 at 3:17 pm #187057autopilotMemberThank you Chike for the clarifications. I still dont know why the first byte of the WORD value is the lower half of the WORD, but after removing the byte reversal, my iRetval is never more then my buffer.
So here is the code after making the changes that Chike pointed out:
Private Function ReadLine(ByVal hwnd As IntPtr, ByVal iLine As Integer, Optional ByVal MaxBuffer As Integer = 500) As String Dim iRetval As Integer Dim sAnswer As String = Nothing Dim baText() As Byte ' Cap MaxBuffer so it can never be too large If MaxBuffer > 65535 Then MaxBuffer = 65535 ' Set byte array to max buffer size (times 2 for Wide) + 1 ReDim baText((MaxBuffer * 2) + 1) ' Get bytes for max buffer size Dim bSize() As Byte bSize = BitConverter.GetBytes(MaxBuffer) ' Write max buffer size as WORD to begining of baText array baText(0) = bSize(0) baText(1) = bSize(1) ' Get Line data (iRetval = number of characters in line) iRetval = SendMessage(hwnd, EM_GETLINE, iLine, baText) ' Convert byte buffer to string trimmed to retval size sAnswer = System.Text.Encoding.Unicode.GetString(baText).Substring(0, iRetval) ' Return the retrieved string Return sAnswer End Function
I still cap the buffer, but at the full 65535 size that EM_GETLINE can retrieve.
Also due to the Pal limit on text, i lowered the default MaxBuffer size to 500
August 16, 2011 at 7:42 pm #187056ChikeMemberLittle endian means last significant byte first, that’s why the first byte is the lower part of the WORD, and the word is the lower part of DWORD etc.
Big endian most significant byte first, and would be just the oposite.if iRetval was greater than the buffer it means memory outside the buffer was overriden.
There is also no need to add a null termination byte to the buffer, EM_GETLINE won’t fill the NULL charachter i there is no space for it, and if you do want it than add 2(unicode char size)Now for the other question I had, is the returned array is really unicode or is it just ascii, you can see this quite clear with the debugger before converting.
August 16, 2011 at 8:30 pm #187055autopilotMember@Chike wrote:
Now for the other question I had, is the returned array is really unicode or is it just ascii, you can see this quite clear with the debugger before converting.
I am saying it is unicode as every other byte (alternating) in the array is = 0 and the “System.Text.Encoding.Unicode.GetString” does return the string.
- baText {Length=1001} Byte()
(0) 65 Byte
(1) 0 Byte
(2) 108 Byte
(3) 0 Byte
(4) 101 Byte
(5) 0 Byte
(6) 114 Byte
(7) 0 Byte
(8) 116 Byte
(9) 0 Byte
...August 16, 2011 at 8:45 pm #187054ChikeMemberAnd SendMessage is SendMessageA or SendMessageW?
August 16, 2011 at 8:53 pm #187053 -
AuthorPosts
Related
- You must be logged in to reply to this topic.