- This topic has 29 replies, 3 voices, and was last updated 6 years ago by
pharaon.
-
AuthorPosts
-
December 1, 2014 at 7:32 am #65937
Departure
AdministratorDid you add a null termination char at the end of the “buffer”? also make variable for sendmessage which should give you the amount of chars copied and see if that matches correctly, if it does I would guess you need to add a null terminated char at the end of your “buffer”, I also suggest against making a static length buffer and create this dynamically.
show us the whole function you wrote and we can maybe help a little more on what the problem could be.
December 1, 2014 at 1:46 pm #65941pharaon
Memberi didn’t try this yet
but right now when I type 123 in the room I get this 123꧐첼ಬ
December 1, 2014 at 1:50 pm #65942pharaon
MemberThe problem is with marshaling. for ansi the code should be
<div id=”wpshdo_6″ class=”wp-synhighlighter-outer”>
<div id=”wpshdt_6″ class=”wp-synhighlighter-expanded”>
<table border=”0″ width=”100%”>
<tbody>
<tr>
<td align=”left” width=”80%”>Code</td>
<td align=”right”></td>
</tr>
</tbody>
</table>
</div>
<div id=”wpshdi_6″ class=”wp-synhighlighter-inner” style=”display: block;”>
<div class=”vbnet” style=”font-family: monospace;”>strBuffer.<span class=”me1″>Append</span><span class=”br0″>(</span><span class=”kw7″>Chr</span><span class=”br0″>(</span>1024 <span class=”kw5″>And</span> 255<span class=”br0″>)</span><span class=”br0″>)</span> strBuffer.<span class=”me1″>Append</span><span class=”br0″>(</span><span class=”kw7″>Chr</span><span class=”br0″>(</span><span class=”nu0″>1024</span> <span class=”sy0″>/</span> <span class=”nu0″>256</span><span class=”br0″>)</span><span class=”br0″>)</span></div>
</div>
</div>
Because the buffer is marshaled from unicode to anso on it’s way out Char by Char. 1024 fits in a Char which is 2 byte unicode but when marshaled the high byte is lost. or somehow converted I suggest to declare and use SendMessage as follows, since the edit control is unicode anyway
<div id=”wpshdo_7″ class=”wp-synhighlighter-outer”>
<div id=”wpshdt_7″ class=”wp-synhighlighter-expanded”>
<table border=”0″ width=”100%”>
<tbody>
<tr>
<td align=”left” width=”80%”>Code</td>
<td align=”right”></td>
</tr>
</tbody>
</table>
</div>
<div id=”wpshdi_7″ class=”wp-synhighlighter-inner” style=”display: block;”>
<div class=”vbnet” style=”font-family: monospace;”><span class=”kw6″>Declare</span> <span class=”kw1″>Unicode</span> <span class=”kw6″>Function</span> SendMessage Lib <span class=”st0″>”USER32″</span> <span class=”kw1″>Alias</span> <span class=”st0″>”SendMessageW”</span> _ <span class=”br0″>(</span><span class=”kw2″>ByVal</span> hwnd <span class=”kw2″>As</span> IntPtr, <span class=”kw2″>ByVal</span> wMsg <span class=”kw2″>As</span> <span class=”kw4″>Integer</span>, <span class=”kw2″>ByVal</span> wParam <span class=”kw2″>As</span> <span class=”kw4″>Integer</span>, <span class=”kw2″>ByVal</span> lParam <span class=”kw2″>As</span> StringBuilder<span class=”br0″>)</span> <span class=”kw2″>As</span> <span class=”kw4″>Integer</span> strBuffer.<span class=”me1″>Append</span><span class=”br0″>(</span><span class=”kw7″>ChrW</span><span class=”br0″>(</span><span class=”nu0″>1024</span><span class=”br0″>)</span><span class=”br0″>)</span></div>
</div>
</div>it keep showing my symbols at the end of the text like his 머ࢆ洰Հ╈ even after I tried what you said
December 1, 2014 at 2:16 pm #65945Chike
AdministratorDid you copy and paste the code I posted?
Post the code that doesn’t workDecember 1, 2014 at 4:00 pm #65946pharaon
MemberDeclare Auto Function SendMessage Lib "USER32" (ByVal hwnd As IntPtr, ByVal wMsg As Integer, ByVal wParam As Integer, ByVal lParam As StringBuilder) As Integer Dim strBuffer As New StringBuilder(1024) strBuffer.Append(Chr(1024 And 255)) strBuffer.Append(Chr(1024 / 256))
return symbol
Declare Auto Function SendMessage Lib "USER32" (ByVal hwnd As IntPtr, ByVal wMsg As Integer, ByVal wParam As Integer, ByVal lParam As StringBuilder) As Integer Dim strBuffer As New StringBuilder(1024) strBuffer.Append(1024)
return nothing
Declare Unicode Function SendMessage Lib "USER32" Alias "SendMessageW" (ByVal hwnd As IntPtr, ByVal wMsg As Integer, ByVal wParam As Integer, ByVal lParam As StringBuilder) As Integer Dim strBuffer As New StringBuilder(1024) strBuffer.Append(Chr(1024 And 255)) strBuffer.Append(Chr(1024 / 256))
return nothing
Declare Unicode Function SendMessage Lib "USER32" Alias "SendMessageW" (ByVal hwnd As IntPtr, ByVal wMsg As Integer, ByVal wParam As Integer, ByVal lParam As StringBuilder) As Integer Dim strBuffer As New StringBuilder(1024) strBuffer.Append(ChrW(1024))
return symbol
December 1, 2014 at 4:49 pm #65950Chike
AdministratorDeclaring auto will default to unicode so no need to test.
What do you get with this:Declare Ansi Function SendMessage Lib “USER32” Alias “SendMessageA” (ByVal hwnd As IntPtr, ByVal wMsg As Integer, ByVal wParam As Integer, ByVal lParam As StringBuilder) As Integer
Dim strBuffer As New StringBuilder(1024)
strBuffer.Append(Chr(1024 And 255))
strBuffer.Append(Chr(1024 / 256))December 1, 2014 at 5:12 pm #65951pharaon
Memberthis one work fine thanks
December 1, 2014 at 5:28 pm #65952Chike
AdministratorSo shuld have the second and last code you posted. The only time you get garbage is when the biffer first word value is smaller than the line length and in unicode Append(ChrW(1024)) set the buffer first word to 1024
December 1, 2014 at 7:06 pm #65953Departure
Administratori didn’t try this yet but right now when I type 123 in the room I get this 123꧐첼ಬ
you are missing the null termination char, this is why you are getting weird characters, which bring me to this…
Declare Ansi Function SendMessage Lib “USER32” Alias “SendMessageA” (ByVal hwnd As IntPtr, ByVal wMsg As Integer, ByVal wParam As Integer, ByVal lParam As StringBuilder) As Integer
Dim strBuffer As New StringBuilder(1024)
strBuffer.Append(Chr(1024 And 255))
strBuffer.Append(Chr(1024 / 256))the part where you set the first char of the buffer is just stupid and so is the setting of the second char of the buffer, you need to set the buffer length the amount from “EM_LINELENGTH” in which the first char in your buffer must be the amount of chars you are going to receive. setting the buffer to 1024 and then placing (1024 and 256) into the first char of the buffer is incorrect(equals 0 btw). all you are doing now is making a max amount of chars for the buffer which is why you are getting weird text and not terminating with a null char for the last buffer char.
if you watch tutorial #5 I explain why and how this works…
Example
Function TForm1.GetPalText(const HwndIncommingText: Hwnd): String; var iLineCount, iLineLength, iLineIndex: Integer; szBuffer: array of WideChar; begin if isWindow(HwndIncommingText) = True then begin iLineCount := Sendmessage(HwndIncommingText, EM_GETLINECOUNT, 0, 0) - 2; iLineIndex := Sendmessage(HwndIncommingText, EM_LINEINDEX, iLineCount, 0); iLineLength := Sendmessage(HwndIncommingText, EM_LINELENGTH, iLineIndex, 0); if iLineLength = 0 then begin Result := 'Fail Line Length'; Exit; end; SetLength(szBuffer, iLineLength); Word(szBuffer[0]) := iLineLength; Sendmessage(HwndIncommingText, EM_GETLINE, iLineCount, LParam(szBuffer)); szBuffer[iLineLength] := #0; Result := PWidechar(szBuffer); szBuffer := Nil; end else Result := 'Fail Hwnd'; end;
in your case something similar to this should work if vb.net is zero based arrays(if not just +1)
Dim strBuffer As New StringBuilder(iLineLength) // or maybe im strBuffer As New StringBuilder(iLineLength + 1)
strBuffer.Append(Chr(iLineLength))then after you have gotten the text with EM_GETLINE you must add a null termination to the last char in your buffer.
maybe something like strBuffer.Insert(iLineLength,Chr$(0))
December 1, 2014 at 8:07 pm #65954Chike
Administratoryou are missing the null termination char, this is why you are getting weird characters, which bring me to this…
the part where you set the first char of the buffer is just stupid and so is the setting of the second char of the buffer, you need to set the buffer length the amount from “EM_LINELENGTH” in which the first char in your buffer must be the amount of chars you are going to receive. setting the buffer to 1024 and then placing (1024 and 256) into the first char of the buffer is incorrect(equals 0 btw). all you are doing now is making a max amount of chars for the buffer which is why you are getting weird text and not terminating with a null char for the last buffer char.
if you watch tutorial #5 I explain why and how this works…
https://www.imfiles.com/topic/paltalk-programming-tutorial-seriesvideo/
There is no need for no null character, StringBuilder is a .NET framework object and you can believe it was never sent to SendMessage. The framework wrap the SendMessage call to marshal the parameters. Theframework allocate an internal buffer to copy data from the StringBuffer before calling SendMessage and back to the StringBufferafter it return.
The framework is not aware of the exact detail of the EM_GETLINE and just copy StringBuilder.length bytes before the call to the buffer, and after the call copy all charachters from it back to the StringBuilder until it finds a null charachter including garbage that is not relevant.To avoid this problem the first word need to be set to it’s capacity – 1.
strBuffer.Append(Chr(1023 And 255))
strBuffer.Append(Chr(1023 / 256))for SendMessageA, or
strBuffer.Append(ChrW(1023))
For SendMessageW
While getting the length of the line will work most of the time, it isn’t fail proof
December 1, 2014 at 8:42 pm #65956Chike
AdministratorAfter I looked into it a bit more it seems using Chr function is not a good idea, better use always ChrW instead
strBuffer.Append(ChrW(1023 And 255)) strBuffer.Append(ChrW(1023 / 256))
December 2, 2014 at 9:07 pm #65967Chike
AdministratorI checked a bit more, and there is no elegant way to prevent the extra characters, but there is a way
Dim iLineIndex As Integer = SendMessage(hwnd, EM_LINEINDEX, ilastLine, 0)
Dim iLineLength As Integer = SendMessage(hwnd, EM_LINELENGTH, iLineIndex, 0)
if iLineLength = 0 return Nothing ‘ or return “”
Dim sb As StringBuilder = New StringBuilder(iLineLength)
sb.Append(ChrW(iLineLength))
sb.Length = iLineLength
SendMessage(hwnd, EM_GETLINE, ilastLine, sb)sb.Length = iLineLength pads the buffer with null charachters, and setting the the first word of the buffer to the exact length ensures the end of the buffer is not being cluttered (which it is sometimes).
It’s a bit overhead, but may be better than the overhad marshaling may have to do.
Note: ilastLine = number of lines minus 2.
Note 2: use unicode SendMessageWThe declerations if you don’t have them
Const EM_GETLINE As Integer = &HC4 Const EM_LINEINDEX As Integer = &HBB Const EM_LINELENGTH As Integer = &HC1 Declare Unicode Function SendMessage Lib "USER32" Alias "SendMessageW" _ (ByVal hwnd As IntPtr, ByVal wMsg As Integer, ByVal wParam As Integer, ByVal lParam As StringBuilder) As Integer Declare Auto Function SendMessage Lib "USER32" _ (ByVal hwnd As IntPtr, ByVal wMsg As Integer, ByVal wParam As Integer, ByVal lParam As Integer) As Integer
December 3, 2014 at 9:35 pm #65982pharaon
Memberchike what is the use of the two declaration???
Declare Unicode Function SendMessage Lib "USER32" Alias "SendMessageW" _ (ByVal hwnd As IntPtr, ByVal wMsg As Integer, ByVal wParam As Integer, ByVal lParam As StringBuilder) As Integer Declare Auto Function SendMessage Lib "USER32" _ (ByVal hwnd As IntPtr, ByVal wMsg As Integer, ByVal wParam As Integer, ByVal lParam As Integer) As Integer
will I use both or just one of them?
December 3, 2014 at 9:49 pm #65983Chike
AdministratorYou need both, one for EM_GETLINE and the other for EM_LINEINDEX and EM_LINELENGTH.
Maybe you could use just the first one and and send Nothing as StringBuilder, but this works and maybe you will need a call that require integer lParam.
EDIT: I’ve checked and you can use the first one only if you change the last parameter of the two other calls to Nothing.
December 3, 2014 at 10:52 pm #65984pharaon
Memberok
-
AuthorPosts
- You must be logged in to reply to this topic.