【问题标题】:vba How to control message boxes from another program?vba 如何控制来自另一个程序的消息框?
【发布时间】:2015-12-23 21:24:38
【问题描述】:

所以我想用

pid = Shell(MyApp, 1)

使用 VBA 自动使用蹩脚的外部程序。不幸的是,这个程序有各种烦人的对话框和必须点击的弹出窗口。有什么办法可以直接控制每个对话框,确保按下的是“确定”按钮而不是“取消”?

目前我正在使用

AppActivate pid
Application.SendKeys ("%R")

但是这个命令只能保证初始弹出对话框的“OK”。后续的弹窗可能不会被点击,尤其是因为我不确定如何保证关注新的弹窗。有没有办法找到任何新弹出窗口的子进程 ID?有没有办法直接“点击”一个特别标注的控制按钮?

【问题讨论】:

  • @findwindow 在这里可能会有所帮助,哈哈,看看 windows api msdn.microsoft.com/en-us/library/windows/desktop/…
  • 如果进程(例如消息框)托管在外部应用程序中,您的进程 (VBA) 只能通过 API(应用程序编程接口)访问其对象。如果此应用程序的开发人员已经开发了 VBA api,请在网络上查找它(或告诉我们应用程序的名称,我们可以尝试帮助您找到它)。否则,您最好的机会是“破解”应用程序(例如发送密钥或查找窗口等)。但它永远是一个“黑客”:一旦事情没有按照你的预期进行,你的代码很可能会失败。
  • 附言。 “一旦事情没有按您的预期进行”意味着:窗口不在正确的位置,焦点在其他地方,过程没有开始等。您可以尝试处理许多可能性,但不是全部。因为 Shell、SendKeys、FindWindow 等是 Windows API(即 VBA 访问 Windows 操作系统方法的一种方式)。
  • 我目前正在编写和测试代码以回答您的问题

标签: windows vba shell


【解决方案1】:

如何与对话框上的按钮交互

嗯,有一种方法可以将WM_COMMAND 消息发送到对话框上的常用按钮,从而有效地关闭它:

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

重要提示:

  • 我不得不使用 Spy++ 来找出 Windows 为消息框对话框赋予的类名。

  • Windows SDK 标头包含有用的常量,尤其是从 WinUser.h 获得的 WM_COMMAND 的值。

  • 每次创建对话框时,都需要再次使用FindWindowA获取窗口句柄,如上述代码所示。

【讨论】:

    猜你喜欢
    • 2014-09-20
    • 2010-11-05
    • 1970-01-01
    • 2013-11-30
    • 1970-01-01
    • 2013-07-20
    • 1970-01-01
    • 2013-09-15
    • 2014-10-13
    相关资源
    最近更新 更多