Solved

Use Sendmessage to simulate click on "OK" button

Posted on 2009-06-29
6
1,431 Views
Last Modified: 2012-05-07
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!
0
Comment
Question by:peispud
  • 4
  • 2
6 Comments
 
LVL 85

Expert Comment

by:Mike Tomlinson
ID: 24741428
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

0
 

Author Comment

by:peispud
ID: 24743720
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
0
 
LVL 85

Expert Comment

by:Mike Tomlinson
ID: 24746460
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.
0
How your wiki can always stay up-to-date

Quip doubles as a “living” wiki and a project management tool that evolves with your organization. As you finish projects in Quip, the work remains, easily accessible to all team members, new and old.
- Increase transparency
- Onboard new hires faster
- Access from mobile/offline

 
LVL 85

Accepted Solution

by:
Mike Tomlinson earned 500 total points
ID: 24748156
In this example, I look for the "About Calculator" dialog and, if found, get a handle to the OK button and click it:
Public Class Form1
 

    Private Const WM_LBUTTONDOWN As Integer = &H201

    Private Const BM_SETSTATE As Integer = &HF3

    Private Const BM_CLICK As Integer = &HF5

    Private Const WM_LBUTTONUP As Integer = &H202
 

    Private Declare Function FindWindowEx Lib "user32" Alias "FindWindowExA" _

        (ByVal parent As IntPtr, ByVal child As IntPtr, _

        ByVal className As String, ByVal caption As String) As IntPtr
 

    Private Declare Function SendMessage Lib "user32" Alias "SendMessageA" _

        (ByVal handle As IntPtr, ByVal uMsg As Integer, _

         ByVal wParam As Integer, ByVal lParam As Integer) As Integer
 

    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click

        Dim AboutDialog As IntPtr = FindWindowEx(IntPtr.Zero, IntPtr.Zero, "#32770", "About Calculator")

        If Not AboutDialog.Equals(IntPtr.Zero) Then

            Dim btnOK As IntPtr = FindWindowEx(AboutDialog, IntPtr.Zero, "Button", "OK")

            If Not btnOK.Equals(IntPtr.Zero) Then

                ClickButton(btnOK)

            End If

        End If

    End Sub
 

    Private Sub ClickButton(ByVal handle As IntPtr)

        Call SendMessage(handle, WM_LBUTTONDOWN, 0, 0)

        Call SendMessage(handle, BM_SETSTATE, 1, 0)

        Call SendMessage(handle, BM_CLICK, 0, 0)

        Call SendMessage(handle, WM_LBUTTONUP, 0, 0)

    End Sub
 

End Class

Open in new window

0
 

Author Comment

by:peispud
ID: 24753390
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!
0
 
LVL 85

Expert Comment

by:Mike Tomlinson
ID: 24754379
"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.
0

Featured Post

Free Trending Threat Insights Every Day

Enhance your security with threat intelligence from the web. Get trending threat insights on hackers, exploits, and suspicious IP addresses delivered to your inbox with our free Cyber Daily.

Join & Write a Comment

Microsoft Reports are based on a report definition, which is an XML file that describes data and layout for the report, with a different extension. You can create a client-side report definition language (*.rdlc) file with Visual Studio, and build g…
Creating an analog clock UserControl seems fairly straight forward.  It is, after all, essentially just a circle with several lines in it!  Two common approaches for rendering an analog clock typically involve either manually calculating points with…
This video explains how to create simple products associated to Magento configurable product and offers fast way of their generation with Store Manager for Magento tool.
You have products, that come in variants and want to set different prices for them? Watch this micro tutorial that describes how to configure prices for Magento super attributes. Assigning simple products to configurable: We assigned simple products…

705 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

22 Experts available now in Live!

Get 1:1 Help Now