如何获取 VBA 消息框的窗口句柄

本文关键字:消息 窗口句柄 VBA 何获取 获取 | 更新日期: 2023-09-27 18:36:36

我在大量 Excel 工作簿上运行 C# 脚本,该脚本涉及在每个工作簿中调用一个宏;由于错误处理程序,宏有时会生成 MsgBox,这会暂停脚本的执行,直到我在 MsgBox 中单击"确定"。

MsgBox 的标题文本是"进程子中的错误",正文是"错误(类型不匹配)"。

我想也许我可以有一个并发线程来查找所有当前打开的窗口,如果它找到 MsgBox,请单击"确定"。 我正在尝试使用类似的东西找到窗口:

using System.Diagnostics;
public Process getErrorWindow()
    {
        Process[] processList = Process.GetProcesses();
        foreach (Process process in processList)
        {
            if (process.MainWindowTitle=="Error in processSub")
            {
                return process;
            }
        }
    }

但这什么也找不到。 当我浏览processList[]时,它似乎只找到主Excel窗口,而不是其VBA代码生成的任何子窗口。 有没有办法找到消息框并单击其"确定"按钮?

如何获取 VBA 消息框的窗口句柄

您可以使用 winapi 函数 FindWindow 按标题和类检索窗口的句柄。 将以下代码添加到程序中:

[DllImport("user32.dll", SetLastError = true)]
private static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool SetForegroundWindow(IntPtr hWnd);
public static IntPtr FindExcelErrorPopup()
{
    return FindWindow(null, "Error in processSub");
}

要单击该按钮:

IntPtr hwnd = FindExcelErrorPopup();
if (hwnd != IntPtr.Zero)
{
    SetForegroundWindow(hwnd); // activates the window
    SendKeys.SendWait("{ENTER}"); // send ENTER key
}

如果默认按钮不是"确定",请在 ENTER 之前发送一些 TAB 键笔划以选择它。不要忘记为DllImportusing System.Runtime.InteropServices;.

编辑:对于远程桌面,请尝试以下本机方法:

[DllImport("user32.dll")]
private static extern void keybd_event(Keys bVk, byte bScan, uint dwFlags, UIntPtr dwExtraInfo);
private const uint KEYEVENTF_EXTENDEDKEY = 0x0001;
private const uint KEYEVENTF_KEYUP = 0x0002;
const uint KEYEVENTF_EXTENDEDKEY = 0x0001;
const uint KEYEVENTF_KEYUP = 0x0002;

并像这样举起密钥:

keybd_event(Keys.Enter, 0x45, KEYEVENTF_EXTENDEDKEY, UIntPtr.Zero); // key down
keybd_event(Keys.Enter, 0x45, KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP, UIntPtr.Zero); // key up