problem with SendMessageA

Viewing 15 posts - 16 through 30 (of 30 total)
  • Author
    Posts
  • #190566
    Departure
    Member

    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.

    #190565
    pharaon
    Member

    i didn’t try this yet

    but right now when I type 123 in the room I get this 123꧐첼ಬ

    #190564
    pharaon
    Member

    The 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

    #190563
    Chike
    Member

    Did you copy and paste the code I posted?
    Post the code that doesn’t work

    #190562
    pharaon
    Member
        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(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

     

     

    #190561
    Chike
    Member

    Declaring 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))

    #190560
    pharaon
    Member

    this one work fine thanks

    #190559
    Chike
    Member

    So 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

    #190558
    Departure
    Member

    i 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…

    Paltalk Programming Tutorial Series[Video]

     

    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))

    #190557
    Chike
    Member

    you 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

    #190556
    Chike
    Member

    After 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))
    
    #190555
    Chike
    Member

    I 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 SendMessageW

    The 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
    
    #190554
    pharaon
    Member

    chike 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?

    #190553
    Chike
    Member

    You 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.

    #190552
    pharaon
    Member

    ok

Viewing 15 posts - 16 through 30 (of 30 total)
  • You must be logged in to reply to this topic.