- This topic has 29 replies, 3 voices, and was last updated 9 years ago by Chike.
-
AuthorPosts
-
December 1, 2014 at 7:32 am #190566DepartureMember
Did 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 #190565pharaonMemberi 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 #190564pharaonMemberThe 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 #190563ChikeMemberDid you copy and paste the code I posted?
Post the code that doesn’t workDecember 1, 2014 at 4:00 pm #190562pharaonMemberDeclare 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 #190561ChikeMemberDeclaring 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 #190560pharaonMemberthis one work fine thanks
December 1, 2014 at 5:28 pm #190559ChikeMemberSo 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 #190558DepartureMemberi 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 #190557ChikeMemberyou 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 #190556ChikeMemberAfter 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 #190555ChikeMemberI 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 #190554pharaonMemberchike 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 #190553ChikeMemberYou 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 #190552pharaonMemberok
-
AuthorPosts
Related
- You must be logged in to reply to this topic.