Link to home
Start Free TrialLog in
Avatar of peispud
peispudFlag for Canada

asked on

Use Sendmessage to simulate click on "OK" button

Hi.
I am using VB.Net 2005.   I would like to use API Sendmessage to close a dialog popup window that will wait till you close it or click on the OK button to make it go away.
I have enumerated all the windows and know the handle of the "OK" button and the parent window.  I have used spy++ to verify that the info I have in my code is correct.  

Spy++ reports that the class of this window is "Button"  and that the caption is "OK"

I am using this declare statement
Private Declare Function SendMessage Lib "user32" Alias "SendMessageA" _
        (ByVal handle As IntPtr, ByVal wMsg As Integer, ByVal wParam As Integer, _
        ByVal lParam As String) As Integer

I am trying to simulate a click on the "OK" button with the following code.

SendMessage(OK_Button_Handle, &H2, Int(0), "") ' Performs button click

Of course it's not working.   I would appreciate some help.

Thanks!
Avatar of Mike Tomlinson
Mike Tomlinson
Flag of United States of America image

Try...
Private Const BM_CLICK As Integer = &HF5
Private Declare Function SendMessage Lib "user32" (ByVal handle As IntPtr, ByVal wMsg As Integer, ByVal wParam As Integer, ByVal lParam As Integer) As Integer
 
    ...
    SendMessage(OK_Button_Handle, BM_CLICK, 0, 0)

Open in new window

Avatar of peispud

ASKER

Hi
That doesn't seem to work for me.   I must be missing something or perhaps I have not described the problem properly.  Here goes again ...... This time with more detail.  

For simplicity,  I have used Spy++ to get the handle "OK" button in the dialog window.  (See picture)
Again for clarity,  I have included a code snippet that I am trying to use.
This is a dialog window that requires that the user either click on the "OK" button or close the parent window by clicking on the "X"  .
This dialog window prevents focus on the window that I want under it (also shown in the picture).   I am looking forward to this solution



Public Class Form1
 
    Private Const BM_CLICK As Integer = &HF5
    Private Declare Function SendMessage Lib "user32" Alias "SendMessageA" _
            (ByVal handle As IntPtr, ByVal wMsg As Integer, ByVal wParam As Integer, _
            ByVal lParam As String) As Integer
    Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        Dim OK_Button_Handle As Long = &H507F4   '  Got this from spy++
        SendMessage(OK_Button_Handle, BM_CLICK, 0, 0)
 
    End Sub
End Class

Open in new window

CloseThisWindow1.JPG
You've missed a FUNDAMENTAL concept with respect to handles.   =\

A handle is NOT a static value like a Social Security Number sitting in a database.  Instead, handles are dynamically assigned by the Operating System whenever forms/controls are created.  Thus you cannot determine a handle value via Spy++ and then expect it to be the same value the next time the application runs!  You have to determine the handle values at RUN-TIME...

The RELATIONSHIPS between controls, however, IS typically preserved.  So normally you would find the handle to the MAIN window and then use the information gathered about the hierarchy to find your desired value.  If a control is child to another then you first find the parent handle and then ask for the child using the parent value.

To get a handle to the main window you typically use Process.GetProcessesByName(), FindWindow(), or enumerate all open windows with EnumWindows() looking for a match.
ASKER CERTIFIED SOLUTION
Avatar of Mike Tomlinson
Mike Tomlinson
Flag of United States of America image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of peispud

ASKER

Actually,  I am familiar with the concept behind handles.   In fact, I am enumerating all the windows filtering for the appropriate window handle.  I had been using spy++  to verify that I was shooting at the right window.  So,  the handle given in my previous code was valid until such window was destroyed.

Thank you though.   The code that you gave me works perfectly.   One last question...

The following code does work in my code (for now)  ....  The caption on the button says "Connect"

SendMessage(ConnectButton_Handle, BM_CLICK, Int(0), 0)   ' Performs button click

My question...  Should it be coded as follows instead ?

Call SendMessage(ConnectButton_Handle, WM_LBUTTONDOWN, 0, 0)
 Call SendMessage(ConnectButton_Handle, BM_SETSTATE, 1, 0)
 Call SendMessage(ConnectButton_Handle, BM_CLICK, 0, 0)
 Call SendMessage(ConnectButton_Handle, WM_LBUTTONUP, 0, 0)

Thanks for your help!
"Actually,  I am familiar with the concept behind handles."

Whew!  Glad to hear it...I was worried when I saw that post.   =)

I tested on a bunch of different applications and got mixed results.  It probably has to do with what language the app was originally written in and how they handle input.  Some worked with just BM_CLICK while others needed BM_SETSTATE and BMCLICK.  Still others worked with just the LBUTTON constansts...and a few needed ALL four commands.  =\

If you are targeting just one particular app then use what works for your situation.  If you are targeting multiple buttons and want to keep it generic then use the more verbose version to increase your chances of success.