Results 1 to 2 of 2
  1. #1
    New Lounger
    Join Date
    Dec 2009
    Location
    US
    Posts
    3
    Thanks
    0
    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.

    Thanks.

  2. #2
    2 Star Lounger
    Join Date
    Mar 2010
    Location
    Tampa, FL, USA
    Posts
    114
    Thanks
    11
    Thanked 9 Times in 8 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:
    1. 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.
    2. Add declarations in your module for the Windows API functions FindWindowEx, SendMessage and any other function you'll need.
    3. Use FindWindowEx to return the current handle of the window found through the caption you obtained.
    4. Use the caption of the control you want to fill in to locate it's handle.
    5. 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 ...

    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 Function
    PJ in FL

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •