VB.net SendMessage waiting problem - vb.net

I am using the following code to click a button for displaying another form to click on:
Dim hwnd As Integer = FindWindow(vbNullString, "Virtual CDRom Control Panel")
Dim x As Integer = FindWindowEx(hwnd, 0, vbNullString, "Driver Control ...")
SendMessage(x, BM_CLICK, 0&, 0&)
Thread.Sleep(200)
hwnd = FindWindow(vbNullString, "Virtual CD-ROM Driver Control")
Debug.Print(hwnd)
Problems is that when it gets to
SendMessage(x, BM_CLICK, 0&, 0&)
to click the button, it stops the code there until i exit out of the box that pops up. I want to be able to continue without having to exit the box since the next line
hwnd = FindWindow(vbNullString, "Virtual CD-ROM Driver Control")
finds the pop up window and will click on a button inside that box.
Any help would be great! :o)
David
SOLVED
Private Declare Function FindWindow Lib "user32.dll" Alias "FindWindowA" (ByVal lpClassName As String, ByVal lpWindowName As String) As IntPtr
Private Declare Function FindWindowEx Lib "user32.dll" Alias "FindWindowExA" (ByVal hWndParent As IntPtr, ByVal hWndChildAfter As Integer, ByVal lpClassName As String, ByVal lpWindowName As String) As IntPtr
Private Declare Function SendMessage Lib "user32.dll" Alias "SendMessageA" (ByVal hWnd As IntPtr, ByVal wMsg As Integer, ByVal wParam As Integer, ByVal lParam As IntPtr) As IntPtr
Private Declare Function PostMessage Lib "user32.dll" Alias "PostMessageA" (ByVal hwnd As IntPtr, ByVal wMsg As Integer, ByVal wParam As Integer, ByVal lParam As IntPtr) As IntPtr
Dim hwnd As IntPtr = FindWindow(vbNullString, "Virtual CDRom Control Panel")
Dim x As IntPtr = FindWindowEx(hwnd, 0, vbNullString, "Driver Control ...")
PostMessage(x, BM_CLICK, 0&, 0&)
Thread.Sleep(200)
hwnd = FindWindow(vbNullString, "Virtual CD-ROM Driver Control")
Debug.Print(hwnd)

Try changing SendMessage to PostMessage.
Also please note all HWNDs must be declared as IntPtr.
Also wParam and lParam for SendMessage and PostMessage are IntPtrs.
This will make you code compatible with x64 environment.

Related

Call SendMessage throwing a runtime error

I'm trying to pass text to a 3rd party program but running into a snag.
I have isolated the Class Handler ID inside my program,validated with the messagebox. However, when I try sending it text, I get a run time error.
Public Declare Function FindWindow Lib "user32.dll" Alias "FindWindowA" (ByVal lpClassName As String, ByVal lpWindowName As String) As Int32
Public Declare Function SendMessage Lib "user32.dll" Alias "SendMessageA" (ByVal hwnd As Int32, ByVal wMsg As Int32, ByVal wParam As Int32, ByVal lParam As Int32) As Int32
Public Declare Function FindWindowEx Lib "user32.dll" Alias "FindWindowExA" (ByVal hWnd1 As Int32, ByVal hWnd2 As Int32, ByVal lpsz1 As String, ByVal lpsz2 As String) As Int32
Dim hwnd As Integer
Dim hwindow2 As Integer
Dim main_view As Integer
Dim sub_window As Integer
Public Const WM_SETTEXT = &H0
And
Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click
hwindow2 = FindWindow(vbNullString, "Trace")
main_view = FindWindowEx(hwindow2, 0&, "#32770", vbNullString)
System.Threading.Thread.Sleep(10)
sub_window = FindWindowEx(main_view, 0&, "Edit", vbNullString)
MessageBox.Show(main_view)
MessageBox.Show(sub_window)
Call SendMessage(sub_window, WM_SETTEXT, 0, "test")
End Sub
Any help would be appreciated.
Thanks
you might consider using PostMessage(), it is an asynchronous method and it won't wait for the response from the receiving end. while SendMessage method is synchronous, it 'does not return until the window procedure has processed the message'.
see suggestions from post here
it is also good to indicate the error message to better understand the problem.

How to change combo box selected value of another application? Visual Basic

I know how to click a button of another application using the codes below. But now I need to know how to change the selected value of a combo box.
'Declaration
Private Declare Auto Function FindWindow Lib "user32.dll" (ByVal lpClassName As String, ByVal lpWindowName As String) As IntPtr
Private Declare Auto Function FindWindowEx Lib "user32.dll" (ByVal hWndParent As IntPtr, ByVal hWndChildAfter As IntPtr, ByVal lpszClass As String, ByVal lpszWindow As String) As IntPtr
Declare Auto Function PostMessage Lib "user32.dll" (ByVal hWnd As IntPtr, ByVal Msg As Integer, ByVal wParam As IntPtr, ByRef lParam As IntPtr) As IntPtr
Private Const BM_CLICK = &HF5
'Usage
Dim ButtonHandle As IntPtr
Dim MainWindowHandle As IntPtr
MainWindowHandle = FindWindow(FormClass, FormCaption)
ButtonHandle = FindWindowEx(MainWindowHandle, IntPtr.Zero, TargetClass, TargetCaption)
If ButtonHandle <> 0 Then
PostMessage(ButtonHandle, BM_CLICK, 0, 0)
End If
All I need to do is to change the combobox selected value of a different application from its default value of Off to a value of On. Any help is very much appreciated. Thank You.
Finally I now know how to do this. The code that I used is shown below.
'Declaration
Private Declare Auto Function FindWindow Lib "user32.dll" (ByVal lpClassName As String, ByVal lpWindowName As String) As IntPtr
Private Declare Auto Function FindWindowEx Lib "user32.dll" (ByVal hWndParent As IntPtr, ByVal hWndChildAfter As IntPtr, ByVal lpszClass As String, ByVal lpszWindow As String) As IntPtr
Declare Auto Function PostMessage Lib "user32.dll" (ByVal hWnd As IntPtr, ByVal Msg As Integer, ByVal wParam As IntPtr, ByRef lParam As IntPtr) As IntPtr
Private Const BM_CLICK = &HF5
Private Const CB_SETCURSEL = &H14E
'Usage
Dim MainWindowHandle As IntPtr
Dim ChildAfter As IntPtr
Dim ComboBoxHandle As IntPtr
'Get the Handle
MainWindowHandle = FindWindow(FormClass, FormCaption)
'Get the ChildAfter of the Combo Box
ChildAfter = FindWindowEx(MainWindowHandle, IntPtr.Zero, ChildClass, ChildCaption)
'Get the handle of the combobox dropdown
ComboBoxHandle = FindWindowEx(MainWindowHandle, ChildAfter, "ComboBox", vbNullString)
'Select combo box index(1)
PostMessage(ComboBoxHandle, CB_SETCURSEL, 1, 0)
From the MSDN documentation of FindWindowEx:
hwndChildAfter [in, optional]
Type: HWND
A handle to a child window. The search begins with the next child window in the Z order. The child window must be a direct child window of hwndParent, not just a descendant window.
If hwndChildAfter is NULL, the search begins with the first child window of hwndParent.
#RemyLebeau Thank you so much for helping me do this.

Updating VBA API to 64-bit Excel 2013

this is a shortcut API that allows you to access directly to the name box in Excel. Since I've changed to a 64-bit version I cannot make it to work. The error displayed is Type mismatch.
Private Declare PtrSafe Function FindWindow Lib "USER32" Alias "FindWindowA" (ByVal lpClassName As String, ByVal lpWindowName As String) As LongPtr
Private Declare PtrSafe Function FindWindowEx Lib "USER32" Alias "FindWindowExA" (ByVal hWnd1 As LongPtr, ByVal hWnd2 As LongPtr, ByVal lpsz1 As String, ByVal lpsz2 As String) As LongPtr
Public Declare PtrSafe Function SendMessageA Lib "USER32" (ByVal hwnd As LongPtr, ByVal wMsg As Long, ByVal wParam As LongPtr, lParam As Any) As LongPtr
Private Sub NameBox_Shortcut()
Dim hWnd As LongLong
Const NUL = vbNullString
Const EXCEL_WINDOW = "XLMAIN"
Const FORMULABAR_LEFT_HALF = "EXCEL;"
Const NAMEBOX = "COMBOBOX"
Const WM_LBUTTONDOWN = &H201
Const WM_LBUTTONUP = &H202
hWnd = FindWindowEx(FindWindowEx(FindWindow(EXCEL_WINDOW, NUL), 0, FORMULABAR_LEFT_HALF, NUL), 0, NAMEBOX, NUL)
SendMessageA hwnd, WM_LBUTTONDOWN, 0&, 0&
SendMessageA hwnd, WM_LBUTTONUP, 0&, 0&
End Sub
Edit: Updated the code.
declare your variable as longptr will solve your problem :
Dim hWnd As LongPtr

Trouble with button pushes outside of app

Using Spy++ I've been trying to control form buttons on an external program with my own program..
The picture shows what control I am attempting to mimic and here's my following code below...
Dim hWnd As IntPtr = FindWindow(vbNullString, ListView4.SelectedItems(0).SubItems(3).Text)
If hWnd.Equals(IntPtr.Zero) Then
Return
End If
Dim hWndButton As IntPtr = _
FindWindowEx(hWnd, IntPtr.Zero, "Button", "Load Settings")
If hWndButton.Equals(IntPtr.Zero) Then
Return
End If
However nothing happens when I run the code.. one possibility is the window name I'm grabbing is wrong, but if that's not the case is my code correct?
Well, as Alex pointed out, I wasn't actually initiating the button press.. now that he pointed that out I was able to fix my code.. Here's what I now use:
Private Declare Auto Function FindWindow Lib "user32.dll" ( _
ByVal lpClassName As String, _
ByVal lpWindowName As String _
) As IntPtr
Private Declare Auto Function FindWindowEx Lib "user32.dll" ( _
ByVal hwndParent As IntPtr, _
ByVal hwndChildAfter As IntPtr, _
ByVal lpszClass As String, _
ByVal lpszWindow As String _
) As IntPtr
Declare Auto Function SendMessage Lib "user32" (ByVal hwnd As IntPtr, ByVal Msg As Integer, ByVal wParam As IntPtr, ByVal lParam As IntPtr) As IntPtr
Private Const BM_CLICK = &HF5
Dim hwndParent As Long = FindWindow(vbNullString, ListView4.SelectedItems(0).SubItems(3).Text)
Debug.Print("findwindow: " & hwndParent)
Dim hwndButton As Long = FindWindowEx(hwndParent, IntPtr.Zero, "Button", "Save as")
Debug.Print("OK: " & hwndButton)
hwndButton = SendMessage(hwndButton, BM_CLICK, 0, 0)
Debug.Print("Clicked: " & hwndButton)

how to send mouse click to minimized window?

Heres my code that does not work:
Private Const MOUSEEVENTF_LEFTDOWN = &H2
Private Const MOUSEEVENTF_LEFTUP = &H4
Private Declare Function FindWindow Lib "user32.dll" Alias "FindWindowA" (ByVal lpClassName As String, ByVal lpWindowName As String) As Integer
Private Declare Function PostMessage Lib "user32" Alias "PostMessageA" (ByVal hwnd As Long, ByVal wMsg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
Dim wHandle As Long = FindWindow(vbNullString, "Ultima Online")
PostMessage(wHandle, MOUSEEVENTF_LEFTDOWN, 0, 0)
PostMessage(wHandle, MOUSEEVENTF_LEFTUP, 0, 0)
I'm not sure why this code should work - it seems you're just clicking on the window, not on a specific button.
To minimize windows you could use another api function: SetWindowPlacement,
see: http://www.codeproject.com/KB/dialog/Minimizewindow.aspx
Another idea: If you want a hacky solution you can send the keys Alt+Space n to minimize a window, but this is very hacky, and works only for English machines:
SendKeys ("% n") ''//in vb6
SendKeys.Send("% n") ''//in vb.net