2014-02-25, 11:09 #1
- Join Date
- Dec 2009
- Thanked 0 Times in 0 Posts
Filling in text-boxes in another app
While my "programming environment" is Excel/VBA, I don't think it really matters.
I'm using Excel to create a data file for use by a 3rd party standalone Windows app. Upon starting this app, a form is presented that contains 2 text-boxes - one for an input file; the other for an output file. Both have a "Browse..." button for selecting the location/file. There are some other "input" controls (check box, etc) but I'm not concerned with those.
The app does NOT accept command-line parameters and does NOT utilize the registry.
What I would like to do is start the app and then fill in a location/filename into each of the 2 text-boxes. The "input" location/filename is currently available via the Excel macro (because I'm creating it there) while the "output" file would just have a different extension.
While it has been a while since I used it, I think I could have used something like "QuickKeys" (on the Mac) to accomplish this.
Is there another way? PowerShell, perhaps?
Any help would be greatly appreciated.
Subscribe to our Windows Secrets Newsletter - It's Free!
Get our unique weekly Newsletter with tips and techniques, how to's and critical updates on Windows 7, Windows 8, Windows XP, Firefox, Internet Explorer, Google, etc. Join our 480,000 subscribers!
+ Get this BONUS — free!
Get the most of Excel! Learn about new features, basics of creating a new spreadsheet and using the infamous Ribbon in the first chapter of Excel 2013: The Missing Manual - Subscribe and download Chapter 1 for free!
2014-05-16, 13:00 #2
- Join Date
- Mar 2010
- Tampa, FL, USA
- Thanked 6 Times in 6 Posts
This isn't simple, and I've begun researching this myself to fill in a Save As dialog of another program that my Excel VBA initiates. I've found it requires the use of Windows API function calls, such as FindWindowEx and SendMessage.
Essentially the process goes like:
- Find the caption of the window and the specific control(s) on that window you will want to manipulate using a tool like Microsoft's Spy++ or Au3Info.exe from AutoIt3.
- Add declarations in your module for the Windows API functions FindWindowEx, SendMessage and any other function you'll need.
- Use FindWindowEx to return the current handle of the window found through the caption you obtained.
- Use the caption of the control you want to fill in to locate it's handle.
- Use SendMessage to send data to the control.
I've purposely left this generic as most solutions are too specific to benefit from a generic answer, and you'll benefit from googling for specific functions you need.
To leave you with some starting point, here's the code to click the "YES" button on the dialog box I've identified using the developer tool Au3Info.exe. Windows API's are not for the faint of heart, but open up a whole new world of possibilities for your code ...
Option Explicit Private Declare Function SendMessage _ Lib "user32" Alias "SendMessageA" _ ( _ ByVal hWnd As Long, _ ByVal wMsg As Long, _ ByVal wParam As Long, _ lParam As Any _ ) As Long Private Declare Function FindWindow _ Lib "user32" Alias "FindWindowA" _ ( _ ByVal lpClassName As String, _ ByVal lpWindowName As String _ ) As Long Private Declare Function FindWindowEx _ Lib "user32" Alias "FindWindowExA" _ ( _ ByVal hWnd1 As Long, _ ByVal hWnd2 As Long, _ ByVal lpsz1 As String, _ ByVal lpsz2 As String _ ) As Long Private Declare Function SetForegroundWindow _ Lib "user32" Alias "" _ ( _ ByVal hWnd As Long _ ) As Long Private Declare Function GetWindowText _ Lib "user32" Alias "GetWindowTextA" _ ( _ ByVal hWnd As Long, _ ByVal lpString As String, _ ByVal cch As Long _ ) As Long Private Declare Function GetWindowTextLength _ Lib "user32" Alias "GetWindowTextLengthA" _ ( _ ByVal hWnd As Long _ ) As Long Private Const BM_CLICK = &HF5 Private Const BM_SETSTATE = &HF3 Private Const WM_LBUTTONDOWN = &H201 Private Const WM_LBUTTONUP = &H202 Private Const MK_LBUTTON = &H1 Sub ExampleUsage() CloseDialog "Yes" End Sub Function CloseDialog(ButtonText As String) As Boolean Dim DialogHwnd As Long Dim ButtonHwnd As Long Dim ControlText As String DialogHwnd = FindWindow("#32770", vbNullString) 'get the handle of the first button ButtonHwnd = FindWindowEx(DialogHwnd, 0, "Button", vbNullString) ControlText = String(GetWindowTextLength(ButtonHwnd) + 1, Chr$(0)) GetWindowText ButtonHwnd, ControlText, Len(ControlText) 'loop in zorder Do Until InStr(ControlText, ButtonText) <> 0 ButtonHwnd = FindWindowEx(DialogHwnd, ButtonHwnd, "Button", vbNullString) ControlText = String(GetWindowTextLength(ButtonHwnd) + 1, Chr$(0)) GetWindowText ButtonHwnd, ControlText, Len(ControlText) If ButtonHwnd = 0 Then Exit Function Loop 'special considerations when clicking "Yes" or "Ok" 'a BM_CLICK alone may not close the dialog when clicking on "Yes" or "Ok" 'also, the dialog window may need to have focus in order for this to work 'this is built in security to prevent code from automatically closing 'dialogs. Because of this behavior, you will not be able to step through 'your code to test this. If the VBA IDE has focus, the dialog may not 'close. The behavior will depend on your version of Windows and IE SetForegroundWindow DialogHwnd SendMessage ButtonHwnd, BM_CLICK, 0, 0 SendMessage ButtonHwnd, BM_SETSTATE, 1, 0 SendMessage ButtonHwnd, WM_LBUTTONDOWN, MK_LBUTTON, 0 SendMessage ButtonHwnd, WM_LBUTTONUP, MK_LBUTTON, 0 End FunctionPJ in FL