Library tutorials & articles

Enum Windows & SendMessage API

SendMessage

Declared as:

Public Declare Function SendMessage Lib "user32" Alias "SendMessageA" (ByVal hwnd As Long, ByVal wMsg As Long, ByVal wParam As Long, lParam As Any) As Long

SendMessage API is a very powerful function and lets you do truly amazing things. To understand SendMessage API you have to understand the concept of ‘window messages’. I’ll try to make it as simple as possible for you. The Windows operating system completely runs with the help of messages. If any job that has to be performed by a window there is a unique message for that job. For instance, in a textbox when you press a key there are two messages that are passed to textbox called WM_KEYDOWN and WM_KEYUP along with further info about the keys pressed. Remember that with every message two more arguments are associated called lParam and wParam called message parameters. The values of lparam and wparam depends upon the message, like for WM_KEYDOWN message the:

wParam specifies the virtual-key code of the nonsystem key, and

lParam specifies the repeat count, scan code, extended-key flag, context code, previous key-state flag, and transition-state flag.

Sometimes its also possible that lParam and wParam parameters may not contain any value and will be null, like WM_COPY message copies any selected data of a given window to the clipboard. Now if you know some window that has a selected text and you know the handle of that window you can copy the selected text of that window with the following single line of code, no matter that window is your own or belongs to some other application:

Public Const WM_COPY = &H301
SendMessage (hwnd, WM_COPY, 0, 0)

Here the hwnd is the handle of the window whose selected text you want.

You can use SendMessage to enhance the features of any object, the editbox does not give you the option of undo but you can do it through WM_UNDO message and for this also the lparam and wparam are null or 0. Similarly you can pass the message WM_LBUTTONDOWN to any command button to simulate mouse click on that command button without actually clicking on it. How will you know what lparam and wparam values to pass along with this message? You have to observe. One way is to consult (go lost) in the MSDN library. Another:I often use the spying tool Spy++ that comes with Visual C++. It is a very useful program especially if you want to ‘learn’ everything about how a window ‘lives’ in a system. I would simply hook a window for its messages in Spy++ and click any of its command buttons and see what messages are involved when I click, and through studying this procedure I will make my own message simulator.

In the above examples your were passing some data along the message in form of lparam and wparam and that data was used or in case of null values it was being ignored. But there are messages for which you pass the variable required and the data is copied into the variable. Read previous sentence again. This is what I’ve done in EnumerationX to get the text of the edit boxes and captions of command buttons that could not be get by GetWindowsText API. First you have to pass the WM_GETTEXTLENGTH which returns the length of whats written inside the window then you create a variable whose length is windowtextlength+1 and fill it with some junk. Now you pass the variable to the SendMessage along with its parameters. In EnumerationX the GetText function (declared in module) was doing the real work and the statement which gets the text looked like this:

Textlen = SendMessage(Ihwnd, WM_GETTEXT, Textlen, ByVal Text)

Here Ihwnd is handles of the window whose text you want

WM_GETTEXT is the message with a constant value of &HD

Textlen is wparam parameter

Text is lparam parameter and must be is pass by value. You always have to take care in APIs of whether the arguments passed requires a by value or by reference, if you mistake there your app will simply crash without letting you save your work!

This is a quite magical statement and to share with you an interesting truth (if you still haven’t discovered it) if you apply the same principle above for a window that has a password field which write asterisks “*******” the WM_GETTEXT message will retrieve the password behind asterisks, which is what EnumerationX can also do. (This applies only to Windows 95/98, text behind password field cannot be retrieved by WM_GETTEXT message in Windows2000).

In EnumerationX I also gave an option of changing (patching) the contents of any window. This was even simpler with the help of WM_SETTEXT, and the statement in the Form2 Command2_Click event of EnumerationX looks like this:

SendMessage Val(Text1.Text), WM_SETTEXT, 0, ByVal Text2.Text

Val(Text1.Text) has got the handle, WM_SETTEXT is the messge , wParam should always be zero in this message as written in the MSDN documentation. Text2.text is what is to be written to the window and should be passed by value. Its that simple ! <and the text is changed>

Comments

  1. 27 Jul 2007 at 10:07

    Hi All,

    I wanna ask about the equivalent of SendKey if I will use SendMessage:

    Ex.

        If ctr2 <= length Then
            myKeys(ctr2) = Mid$(myString, ctr2, 1)
            SendKeys myKeys(ctr2)
            ctr2 = ctr2 + 1
        Else

    I tried converting SendKey with SendMessage but nothing happens:

    myHWnd is the handle I got from Finding the window. What I want to do is to send specific keys to the specified application (myKeys(ctr2)) as if I am using sendKeys.

    SendMessage myHWnd, WM_KEYDOWN, 0, myKeys(ctr2)


    It didn't send keys to notepad.


    I really cannot understand SendMessage and I really need your help guys... I am only a newbie in VB.

    Thank you,

    Gwapo



























  2. 13 Jul 2007 at 08:21

    you said you can't get selected text from html file..etc ,may be you havn't find the right handle of area which can be edit.

  3. 10 Jul 2007 at 00:06

    Hi,

    About this subject, I´m trying to define the size of an image captured from a generic camera.

    I'm using the SendMessage and SetWindowPos functions with the following instructions:

    To initialize the camera:

    Private Sub PreviewVideo(ByVal pbCtrl As PictureBox)

    On Error GoTo treaterror:

                               
            mHwnd = capCreateCaptureWindowA("Teste", WS_VISIBLE Or WS_CHILD, 0, 0, 100, 100, pbCtrl.hwnd, 0)
           
            If SendMessage(mHwnd, WM_CAP_DRIVER_CONNECT, 0, 0) Then
                 SendMessage mHwnd, WM_CAP_SET_SCALE, False, 0
                '---set the preview rate (ms)---
                SendMessage mHwnd, WM_CAP_SET_PREVIEWRATE, 30, 0
                '---start previewing the image---
                SendMessage mHwnd, WM_CAP_SET_PREVIEW, True, 0
                '---resize window to fit in PictureBox control---
                SetWindowPos mHwnd, HWND_BOTTOM, 0, 0, pbCtrl.ScaleWidth, pbCtrl.ScaleHeight, SWP_NOMOVE Or SWP_NOZORDER
               
                    
            Else
                '--error connecting to video source---
                MsgBox "Problema na conexão com a câmera. Contate o suporte!! - " & Err.Description
                DestroyWindow mHwnd
            End If
















            Exit Sub
           
    treaterror:

    MsgBox "Problema na conexão com a câmera. Contate suporte!!!" & Err.Description

       
    End Sub

    To capture the image:

    Private Sub cmdCapturar_Click()

    SendMessage mHwnd, GET_FRAME, 0, 0
    SendMessage mHwnd, COPY, 0, 0
    Picture1.Picture = Clipboard.GetData
    Clipboard.Clear
    'Timer1.Enabled = False



    End Sub

    Please note that I don't want just want to fit the image to the window. I need its real size to be the window's size. (What is happenning is that I see one image on the PictureBox passed as a parameter the sub PreviewVideo but the captured image is much larger than it.)

    Thank you in advance,

  4. 21 Jan 2006 at 17:15

    i'm doing something similar to this thread starter. below is my code:


    Private Sub Timer1_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Timer1.Tick


           prevWindow = 0


           Call GetCursorPos(mousePT)
           X = mousePT.X
           Y = mousePT.Y
           Label2.Text = "(" & X & "," & Y & ")"
           hWnd = WindowFromPoint(X, Y)


           className = Space(255) ' Make room in the string to receive the information.
           retValue = GetClassName(hWnd, className, 255)


           windowText = Space(255)
           GetWindowText(hWnd, windowText, 255)


           Label1.Text = hWnd


       End Sub


    this is a function which will constantly called by timer, and i have 2 labels on my form which is label 1 and and label2
    you can see that i print the handle number (hWnd) using label1, but when i run the program no matter where i point the mouse to but the hwnd value is still the same, why?

  5. 09 Jun 2005 at 11:27

    Quote:
    [1]Posted by arshad on 29 Jun 2004 12:18 PM[/1]
    Hi Riaz,
    Could you plz explain me how did u fetch data from MS-Word.
    I can able to get typed text from notepad using sendmessage API.
    Same API Could not work for MS-word.
    Thanks,
    Arshad.
    Quote:
    [1]Posted by riyazfarz on 3 Sep 2003 02:33 AM[/1]
    Hi,


    Yes I could fetch data from MS- word, Notepad etc. But I am not able to fetch from HTML file. Any idea for getting from this.


    Anyway thanks for your valuable help.


    Regards


    Riaz




    I used SendMessage(hwnd, WM_COPY, 0, 0). And I meet the above problem, too!
    I cann't get selected text for HTML file/VC/PDF file/SourceInsight File......

  6. 13 Oct 2004 at 02:35

    hi, Have u got the solution?
    i m also looking for the same...
    Can you help me some how more ?
    I have developed a dictionary & now I want let user use it with a very simple way.
    I wish to have a word under mouse cursor from any other windows application. my program will search definition for that word & will show at mouse cursor when user press Ctrl key or in any other special window automatically.
    For the same I was searching for, I come across you. I want just any children of any window ( like..notepad, wordpad, word, or explorer or just any edit control.)
    Hopes u got my requirement. Simply I have a definition dictionary & want to synchronize it with text under mouse cursor.
    althogh u have given a nice idea that how to go for it but can u pls show it with a code pls.
    I 'll. be greatly thankful to you, if you can illustrate it with few sample source code (Visual Basic only).


    if u got it pls help me.
    Thanks & have a nice time.


    Sunil.


  7. 13 Oct 2004 at 02:28

    Hi there !
    how are u?


     Can you help me some how more ?
    I have developed a dictionary & now I want let user use it with a very simple way.
    I wish to have a word under mouse cursor from any other windows application. my program will search definition for that word & will show at mouse cursor when user press Ctrl key or in any other special window automatically.
    For the same I was searching for, I come across you. I want just any children of any window ( like..notepad, wordpad, word, or explorer or just any edit control.)
    Hopes u got my requirement. Simply I have a definition dictionary & want to synchronize it with text under mouse cursor.
    althogh u have given a nice idea that how to go for it but can u pls show it with a code pls.
    I 'll. be greatly thankful to you, if you can illustrate it with few sample source code (Visual Basic only).


    Thanks & have a nice time.
    Sunil.

  8. 29 Jun 2004 at 12:18

    Hi Riaz,
    Could you plz explain me how did u fetch data from MS-Word.
    I can able to get typed text from notepad using sendmessage API.
    Same API Could not work for MS-word.
    Thanks,
    Arshad.

    Quote:
    [1]Posted by riyazfarz on 3 Sep 2003 02:33 AM[/1]
    Hi,


    Yes I could fetch data from MS- word, Notepad etc. But I am not able to fetch from HTML file. Any idea for getting from this.


    Anyway thanks for your valuable help.


    Regards


    Riaz

  9. 03 Sep 2003 at 02:33

    Hi,


    Yes I could fetch data from MS- word, Notepad etc. But I am not able to fetch from HTML file. Any idea for getting from this.


    Anyway thanks for your valuable help.


    Regards


    Riaz

  10. 21 Aug 2003 at 15:58

    Quote:
    [1]Posted by koo9 on 11 Jul 2003 03:10 PM[/1]
    like the Gator client, it allow user the hold down a key e.g. ctrl and click on any text in any windows, it will pop up a definition for the clicked text, how do they do it? does it use the WM_GETTEXT as well?


    I was able to do that using the SENDMESSAGE, GETCURSORPOS and WINDOWFROMPOINT functions.
    Basicly what you need to do is first get the cursor's position using GETCURSORPOS which will return the x and y location. Pass those coordibates to WINDOWFROMPOINT and it will return the window handle in which the cursor is currently highlighting the text. Since you now have the correct handle of the window (this window can be anything...notepad...explorer...etc...) you then use the SENDMESSAGE function as such:
    SENDMESSAGE FoundWindow.hWnd, WM_COPY, 0, 0 where 'FoundWindow' is the handle returned by WINDOWFROMPOINT.


    NOTE: This method needs a constant loop to keep checking the mouse cursor position (using a timer control).
    This works when a text is highlighted and the mouse cursor is still above it. If you want to do this using the CTRL key you might have to resort to GETASYNCKEYSTATE also.


    If you succeed in developing a better code i'd be glad to see it

  11. 11 Jul 2003 at 15:10

    like the Gator client, it allow user the hold down a key e.g. ctrl and click on any text in any windows, it will pop up a definition for the clicked text, how do they do it? does it use the WM_GETTEXT as well?

  12. 14 Apr 2003 at 04:28

    I'm using this api to send a custom message between 2 VB exe's.  The called exe is subclassed to listen to the custom message.  In the calling exe, I'm trying to pass a string in the 4th parameter.  At this stage the 2nd exe is already running.  The api call keeps crashing the 2nd exe.  Can it be done across exe's or only within the same exe, thanks.

  13. 15 Mar 2002 at 18:02

    I have the following code:
    The PostMessage function works, while the SendMessage function does not..WHY???


    //**********
       PROCESS_INFORMATION
    pi;
       pi = (PROCESSINFORMATION*)malloc(sizeof(PROCESSINFORMATION));
       STARTUPINFO si;
       si.cb=sizeof(si);
       si.lpReserved=NULL;
       si.lpDesktop=NULL;
       si.lpTitle=NULL,
       si.dwFlags=STARTFFORCEONFEEDBACK;
       si.cbReserved2=0;
       si.lpReserved2=NULL;
       BOOL bres = CreateProcess(NULL, "calc.exe", NULL,NULL,NULL,
                                 CREATE
    NEWCONSOLE | NORMALPRIORITY_CLASS,
                                 NULL,NULL,&si,pi);
       if(!bres)
       {
           return;
       }


       HWND hWnd;
       EnumThreadWindows(pi->dwThreadId, EnumProc, (LPARAM)&hWnd);
       SetFocus(hWnd);
       //LRESULT lr1 = SendMessage(hWnd, WMKEYDOWN, 38, 0);
       //LRESULT lr2 = SendMessage(hWnd, WM
    KEYUP, 38, 1);
       
       BOOL bp = PostMessage(hWnd, 256, 53, 393217);
       LRESULT lr1 = SendMessage(hWnd, 256, 53, 393217);
    //***************

  14. 01 Jan 1999 at 00:00

    This thread is for discussions of Enum Windows & SendMessage API.

Leave a comment

Sign in or Join us (it's free).