Window - click ok button by code - vb.net

I'm adding a SDE feature class into ArcMap and before it adds in I have to click the ok button on the "Connection Details" Window. Is there a way to click the ok button by code? I was thinking maybe it could be done by using Window notification code (e.g. code below), however I'm not seeing any option for button click Ok or Cancel. Maybe it could be done by "Windows.Forms.DialogResult.Ok" somehow or by getting the focus of the ok button?
Thanks
Private Declare Function FindWindow Lib "user32" Alias "FindWindowA" (ByVal lpClassName As String, ByVal lpWindowName As String) As Long
Private Declare Function PostMessage Lib "user32" Alias "PostMessageA" (ByVal hwnd As Long, ByVal wMsg As Long, ByVal wParam As Long, lParam As Any) As Long
Const WM_CLOSE = &H10
'Close SDE connection details dialog
Dim WinWnd As Long, Ret As String
'Ask for a Window title
Ret = "Connection Details"
If Ret = "" Then Exit Sub
'Search the window
WinWnd = FindWindow(vbNullString, Ret)
'If WinWnd = 0 Then Messagebox.show "Couldn't find the window ...": Exit Sub
'Post a message to the window to close itself
PostMessage WinWnd, WM_CLOSE, 0&, 0&

I can think of two ways to do so:
You can find the OK button position (using FindWindowEx and GetWindowRect), place the cursor on the button (SetCursorPosition) and simulate a mouse click (mouse_event.) Or you can set focus on the button and simulate pressing Enter key (with keyb_event).
Send BM_CLICK message to OK button's handle.
I personally like the second approach better:
<Runtime.InteropServices.DllImport("user32.dll", SetLastError:=True, CharSet:=Runtime.InteropServices.CharSet.Auto)> _
Public Shared Function SendMessage(ByVal hWnd As IntPtr, ByVal Msg As UInteger, ByVal wParam As IntPtr, ByVal lParam As IntPtr) As IntPtr
End Function
Public BM_CLICK As Integer = &HF5
SendMessage(`OK BUTTON HANDLE`, BM_CLICK, 0, 0); // The button handle can be found with FindWindowEx

Related

Close any open .PDF-file using VBA

I use 'Close_by_Caption' to close open .PDFs before they are regenerated. Previously this was easy because I could assume that always 'Foxit Reader' opened the file and that each file was opened in a separate instance of Foxit.
Newly, 'PDF-XChange Editor' should also be used to open .PDF. Now I don't know if I have to close the file with 'Close_By_Caption 'Demo - PDF-XChange Editor' or 'Demo.pdf - Foxit Reader'.
Of course I can run both commands one after the other - but surely someone will come soon who wants to use another viewer....
Is there a way to find all programs that have the word 'Demo' in 'AppCaption'? Of course, it would be even better if I would knew that either the program is a .PDF-viewer or the opened file is a .PDF...
'API Find application by full caption
Private Declare Function FindWindow _
Lib "user32" _
Alias "FindWindowA" _
( _
ByVal lpClassName As String, _
ByVal lpWindowName As String _
) _
As Long
'*****************************************
'API Bring Window to foreground
Private Declare Function SetForegroundWindow Lib "user32" (ByVal hWnd As Long) As Long
'*****************************************
'API Send message to application
Private Declare Function PostMessage _
Lib "user32" _
Alias "PostMessageA" _
( _
ByVal hWnd As Long, _
ByVal wMsg As Long, _
ByVal wParam As Long, _
lParam As Any _
) _
As Long
'*****************************************
Const WM_CLOSE = &H10
'*****************************************
Function Close_By_Caption(AppCaption As String)
Dim hWnd As Long
hWnd = FindWindow(vbNullString, AppCaption)
If hWnd Then
'Bring to Front
SetForegroundWindow hWnd
'Close the app nicely
PostMessage hWnd, WM_CLOSE, 0&, 0&
End If
End Function
'*****************************************
Sub Test_Close()
Close_By_Caption "demo.pdf - Foxit Reader"
End Sub
'*****************************************```

Accessing buttons on the Internet Explorer 11 View downloads form

I have a piece of code in vb.net to open a web link for an application and to download a file from the page. The web browser loads the page and the program auto clicks the link on the page to download the file which then makes the "View Downloads - Internet Explorer" window in IE 11 to pop up as shown below:
Internet Explorer 11- VIew Downloads window
I managed to activate the window but not able to click the Save button to automatically download the file without user intervention. The code that I tried to activate and click the button is as below
Private Declare Auto Function FindWindow Lib "user32" (ByVal ClassName As String, ByVal WindowTitle As String) As IntPtr
Private Declare Auto Function FindWindowEx Lib "user32" (ByVal parentHandle As IntPtr, ByVal childAfter As IntPtr, ByVal ClassName As String, ByVal WindowTitle As String) As IntPtr
Private Declare Auto Function SendMessage Lib "user32.dll" (ByVal hWnd As IntPtr, ByVal msg As Integer, ByVal wParam As Integer, ByVal lParam As IntPtr) As IntPtr
Private Sub Button5_Click(sender As Object, e As EventArgs) Handles Button5.Click
Dim ParentWndHandle As IntPtr
ParentWndHandle = FindWindow("#32770", "View Downloads - Internet Explorer")
If ParentWndHandle <> IntPtr.Zero Then
Dim ChildWndHandle As IntPtr
ChildWndHandle = FindWindowEx(ParentWndHandle, vbNullString, "DirectUIHWND", vbNullString)
Dim btn1 As IntPtr = FindWindowEx(ChildWndHandle, IntPtr.Zero, "Button", "&Save")
SendMessage(ChildWndHandle, WM_ACTIVATE, WA_ACTIVE, 0)
SendMessage(ChildWndHandle, WM_COMMAND, VK_RETURN, IntPtr.Zero)
End If
End Sub
I think your issue might be the same as this thread: You need to use SetActiveWindow before SendMessage.
Or can you extract the file url? If so, you can refer to this doc to use the simple DownloadFile method to download files:
My.Computer.Network.DownloadFile(
"http://www.example.com/downloads/abc.txt",
"C:\Documents and Settings\All Users\Documents\abc.txt")

WM_SETTEXT & WM_GETTEXT delay/lag issue

I have tried automating a few external window's Combo box controls using the API functions, SendMessage and PostMessage and using the Window Messages WM_SETTEXT WM_GETTEXTLENGTH and WM_GETTEXT.
I can get this to work when I run through the code for example pressing F11 through each line or putting a breakpoint in and running it at a certain point, but when I run it as normal, the WM_SETTEXT message doesn't update the Combo box.
It seems to be an issue with the speed that the code is running so my first solution was to put a piece of validation that ensures the text is in the combo box, but for some reason the WM_GETTEXT retrieves the text that should be in the text box even though its not visible.
The code below is a snippet of the kind of validation I've tried, my question here would be is there any sort of wait until method I could use to ensure that the text actually gets entered, I know about the Sleep API but I would ideally like something that actually makes sure that text is there and doesn't load f x seconds and hopes that the text is there.
Any ideas are appriciated.
Many Thanks
VB.net Code Example:
Private Enum WindowMessages
WM_SETTEXT = &HC
WM_GETTEXT = &HD
WM_GETTEXTLENGTH = &HE
End Enum
Private Declare Function SendMessage Lib "user32" Alias _
"SendMessageA" (ByVal hWnd As Int32, ByVal wMsg As Int32, ByVal _
wParam As Int32, lParam As String) As Int32
Public Declare Function PostMessage Lib "user32.dll" Alias "PostMessageA" (ByVal hWnd
As Int32, _
ByVal wMsg As Int32, ByVal wParam As Int32, ByVal lParam As String) As Int32
Private Sub TestExample(ByVal hWndTextBox as Int32, ByVal TextString as String)
'####Using the hWnd of a Combo box control and a string to enter in the combo box.####
Dim TextLength as Int32
Dim ItemText as string
Do until ItemText = TextString
SendMessage(hWndTextBox, WM_SETTEXT, 0, TextString) > 0
TextLength = SendMessage(hWndTextBox, WM_GETTEXTLENGTH, 0, 0)
ItemText = Space(TextLength)
SendMessage(hWndTextBox, WM_GETTEXT, TextLen + 1, ItemText)
Loop
End Sub

VB.NET Send Tab key to another application window

I want to send "{TAB}" Key to another application window(send the key to the window not to textbox).
I tried:
SendMessage(hWnd, WM_SETHOTKEY, VK_TAB, 0)
Nothing happened.
my goal is:
send tab key to my application Or other application when the application window is not in focus.
(i know that sendkey is not professional in this case there is no choice(This is the first time that I'm using it).)
I made many attempts and I always returned to the same result:
Nothing happened.
Does anyone know the answer?
SendKeys requires the application that you are sending the Keys to, to be active.
From above Link:
Use SendKeys to send keystrokes and keystroke combinations to the active application.
I order to get around this limitation you will have to resort to using the WinApi Functions.
FindWindow pInvoke.net
FindWindowEx pInvoke.net
sendMessage pInvoke.net
See this MSDN Forum Post for an example
Here is a modified example from that Posting:
Public Class Form1
Declare Function FindWindow Lib "user32" Alias "FindWindowA" _
(ByVal lpClassName As String, ByVal lpWindowName As String) As IntPtr
Declare Function FindWindowEx Lib "user32" Alias "FindWindowExA" _
(ByVal hWnd As IntPtr, ByVal hWndChildAfterA As IntPtr, ByVal lpszClass As String, ByVal lpszWindow As String) As IntPtr
Declare Function SendMessage Lib "user32" Alias "SendMessageA" _
(ByVal hWnd As IntPtr, ByVal wMsg As Integer, ByVal wParam As IntPtr, ByVal lParam As String) As IntPtr
Const WM_SETTEXT As Integer = &HC
Private Sub Button1_Click(sender As System.Object, e As System.EventArgs) Handles Button1.Click
Dim destination As IntPtr = FindWindow(Nothing, "Untitled - Notepad")
Dim destControl As IntPtr = FindWindowEx(destination, IntPtr.Zero, "Edit", Nothing)
SendMessage(destControl, WM_SETTEXT, IntPtr.Zero, "Hello" & vbTab & "GoodBye" & vbCrLf)
End Sub
End Class
Added an Additional Example using WM_KEYDOWN I created another small application with the Window Title set to TestForm and overrode the WndProc Method to determine if the application got the TabKey.
Sending Form
Public Class Form1
Declare Function FindWindow Lib "user32" Alias "FindWindowA" _
(ByVal lpClassName As String, ByVal lpWindowName As String) As IntPtr
Declare Function SendMessage Lib "user32" Alias "SendMessageA" _
(ByVal hWnd As IntPtr, ByVal wMsg As Integer, ByVal wParam As Integer, ByVal lParam As Integer) As IntPtr
Const WM_KEYDOWN As Integer = &H100
Const VK_TAB As Integer = &H9
Private Sub Button1_Click(sender As System.Object, e As System.EventArgs) Handles Button1.Click
Dim destination As IntPtr = FindWindow(Nothing, "TestForm")
SendMessage(destination, WM_KEYDOWN, VK_TAB, 0)
End Sub
End Class
Test Form
Put a breakpoint on MyBase.WndProc(m) and look at m to see what has been sent.
Public Class Form1
Protected Overrides Sub WndProc(ByRef m As System.Windows.Forms.Message)
MyBase.WndProc(m)
End Sub
End Class
Having struggled with this type of this a few times before, i would suggest a couple of things to look at.
The 1st is autoit which includes a dll you can reference from vb.net, and is very simple you use, and well documented. I tend to use that whenever i need to control a 3rd party program.
The other is the ui automation classes
See this for an example:
http://blog.functionalfun.net/2009/06/introduction-to-ui-automation-with.html
you need make the other window active first. check Change focus to another window in VB.NET . then use send key.

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