Solved

Use Sendmessage to simulate click on "OK" button

Posted on 2009-06-29
6
1,452 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
Netscaler Common Configuration How To guides

If you use NetScaler you will want to see these guides. The NetScaler How To Guides show administrators how to get NetScaler up and configured by providing instructions for common scenarios and some not so common ones.

 
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

Problems using Powershell and Active Directory?

Managing Active Directory does not always have to be complicated.  If you are spending more time trying instead of doing, then it's time to look at something else. For nearly 20 years, AD admins around the world have used one tool for day-to-day AD management: Hyena. Discover why

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

A while ago, I was working on a Windows Forms application and I needed a special label control with reflection (glass) effect to show some titles in a stylish way. I've always enjoyed working with graphics, but it's never too clever to re-invent …
Introduction As chip makers focus on adding processor cores over increasing clock speed, developers need to utilize the features of modern CPUs.  One of the ways we can do this is by implementing parallel algorithms in our software.   One recent…
This tutorial gives a high-level tour of the interface of Marketo (a marketing automation tool to help businesses track and engage prospective customers and drive them to purchase). You will see the main areas including Marketing Activities, Design …
Finds all prime numbers in a range requested and places them in a public primes() array. I've demostrated a template size of 30 (2 * 3 * 5) but larger templates can be built such 210  (2 * 3 * 5 * 7) or 2310  (2 * 3 * 5 * 7 * 11). The larger templa…

777 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