0

So I want to use

pid = Shell(MyApp, 1)

with VBA to automate the use of a crappy external program. This program unfortunately has all sorts of annoying dialog boxes and popups that must be clicked. Is there any way to directly control each dialog box to ensure that the "OK" button is pressed rather than "Cancel"?

Currently I am using

AppActivate pid
Application.SendKeys ("%R")

But this command can only guarantee the "OK" of the initial pop-up dialog. Subsequent pop-ups may not be clicked, especially because I'm not sure how to guarantee focus on the new popup. Is there a way to find the child process ID's of any new popups? Is there any way to directly "click" a particularly labeled control button?

4
  • 1
    @findwindow might be helpful here lol, look into the windows api msdn.microsoft.com/en-us/library/windows/desktop/… Commented Dec 23, 2015 at 22:13
  • 1
    If a process (for example a messagebox) is hosted in an external application, your process (VBA) can access its object only through an API (Application Programming Interface). If the developers of this application have developed a VBA api, look for it on the web (or tell us the name of the application and we can try to help you finding it). Otherwise, your best chance is to "hack" the application (like sending a key, or finding the window etc.). But it will always be a "hack": as soon as something doesn't go as you expect, your code will likely fail. Commented Dec 23, 2015 at 22:24
  • P.s. "as soon as something doesn't go as you expect" means: the window is not on the right place, the focus is somewhere else, the process doesn't start etc. You can try to handle many possibilities but not all. Cause Shell, SendKeys, FindWindow etc. are Windows API (i.e. a way of VBA to access the methods of the Windows operating framework). Commented Dec 23, 2015 at 22:26
  • I'm currently writing and testing the code to answer your question Commented Dec 23, 2015 at 22:55

1 Answer 1

1

How to Interact with a Button on a Dialog

Well, there is a way of sending a WM_COMMAND message to common buttons on a dialog box effectively closing it:

Declare Function SendMessageA Lib "user32" (ByVal hWnd As Long, ByVal Msg As Integer, ByVal wParam As Long, ByVal lParam As Long) As Long
Declare Function FindWindowA Lib "user32" (ByVal lpClassName As String, ByVal lpWindowName As String) As Long

Const WM_COMMAND As Integer = 273
Const WM_CLOSE As Integer = 16
Const IDOK As Integer = 1
Const IDCANCEL As Integer = 2

Sub ShowDialogs()
    If Shell("C:\Users\myself\dialogs.exe") <> 0 Then
        Dim hWnd As Long
        hWnd = FindWindowA("#32770", "Info")
        Debug.Print hWnd
        SendMessageA hWnd, WM_COMMAND, IDOK, 0
    End If
End Sub

Important Notes:

  • I had to use Spy++ to find out what class name Windows gives to message box dialogs.

  • The Windows SDK headers contained useful constants, especially the value for WM_COMMAND which was obtained from WinUser.h.

  • Each time a dialog is a created, you will need to obtain the handle for the window again using FindWindowA, as shown in the preceding code.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.