【问题标题】:Click A MessageBox button programmatically以编程方式单击 MessageBox 按钮
【发布时间】:2013-05-23 17:43:15
【问题描述】:

正如标题所示,我正在尝试以编程方式模拟 MessageBox 中的按钮单击。我之前尝试通过标题找到它的句柄来关闭消息框,然后在SendMessage() 中应用WM_CLOSESC_CLOSE。但是,由于存在是/否按钮,这不起作用(X 按钮变灰)。

现在我正在尝试单击“否”按钮,如下所示-:

List<IntPtr> result = new List<IntPtr>();
GCHandle listHandle = GCHandle.Alloc(result);
try
{
     IntPtr Window_hWnd = CloseMessageBox.FindWindowByCaption("#32770", "LastQuestion"); //Could use null as the first argument too. "#32770" represents classname Dialog.
     CloseMessageBox.EnumChildWindows(Window_hWnd, (hWnd, lParam) =>
     {
          StringBuilder sb = new StringBuilder();
          foreach (var control in GCHandle.FromIntPtr(lParam).Target as List<IntPtr>)
          {
                CloseMessageBox.GetWindowText(control, sb, 250);
                if (sb.Equals("&No"))
                {
                    CloseMessageBox.PostMessage(hWnd, CloseMessageBox.MouseDown, 0, 0);
                    CloseMessageBox.PostMessage(hWnd, CloseMessageBox.MouseUp, 0, 0);
                }
          }
          return false;
     }, GCHandle.ToIntPtr(listHandle));

 }
 catch (Exception e)
 {
     MessageBox.Show(e.ToString());
 }
 finally
 {
     if (listHandle.IsAllocated)
        listHandle.Free();
 }

在 IRC 某人的建议下走了这么远,我发现之前进行了一些编辑,我得到了按钮句柄(只有“&Yes”按钮),但不是全部。然后他提出了这种方法,但control 列表没有填充,因此它永远不会进入foreach。我该怎么做才能解决这个问题?

【问题讨论】:

标签: c# pinvoke findwindow


【解决方案1】:

给你。

// A delegate which is used by EnumChildWindows to execute a callback method.
public delegate bool EnumWindowProc(IntPtr hWnd, IntPtr parameter);

// This method accepts a string which represents the title name of the window you're looking for the controls on.
public static void ClickButtonLabeledNo(string windowTitle)
{
    try
    {
        // Find the main window's handle by the title.
        var windowHWnd = FindWindowByCaption(IntPtr.Zero, windowTitle);

        // Loop though the child windows, and execute the EnumChildWindowsCallback method
        EnumChildWindows(windowHWnd, EnumChildWindowsCallback, IntPtr.Zero);
    }
    catch (Exception e)
    {
        MessageBox.Show(e.ToString());
    }
}

private static bool EnumChildWindowsCallback(IntPtr handle, IntPtr pointer)
{
    const uint WM_LBUTTONDOWN = 0x0201;
    const uint WM_LBUTTONUP = 0x0202;

    var sb = new StringBuilder(256);
    // Get the control's text.
    GetWindowCaption(handle, sb, 256);
    var text = sb.ToString();

    // If the text on the control == &No send a left mouse click to the handle.
    if (text == @"&No")
    {
        PostMessage(handle, WM_LBUTTONDOWN, IntPtr.Zero, IntPtr.Zero);
        PostMessage(handle, WM_LBUTTONUP, IntPtr.Zero, IntPtr.Zero);
    }

    return true;
}

[DllImport("user32")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool EnumChildWindows(IntPtr window, EnumWindowProc callback, IntPtr i);

[DllImport("user32.dll", EntryPoint = "FindWindow", SetLastError = true)]
private static extern IntPtr FindWindowByCaption(IntPtr ZeroOnly, string lpWindowName);

[DllImport("user32.dll", EntryPoint = "GetWindowText", CharSet = CharSet.Auto)]
private static extern IntPtr GetWindowCaption(IntPtr hwnd, StringBuilder lpString, int maxCount);

[return: MarshalAs(UnmanagedType.Bool)]
[DllImport("user32.dll", SetLastError = true)]
private static extern bool PostMessage(IntPtr hWnd, uint Msg, IntPtr wParam, IntPtr lParam);

【讨论】:

  • 最后,一个简单的无按钮点击模拟就完成了!在 IRC 上花了我 7 个小时,最后是这样。非常感谢!
  • 我刚试了一下,它可以工作,除了 WM_LBUTTONUP 应该是 0x0202 根据msdn.microsoft.com/en-us/library/windows/desktop/… 之外,这工作得很好!
  • 糟糕!感谢您发现这一点!
  • 请注意,这仅适用于英语版本的 Windows。对于所有其他语言,Yes/No 将被翻译成当地语言,这种方法将被打破。
  • 它不适用于“是”按钮,你能建议我错过了什么吗?
猜你喜欢
  • 2013-10-09
  • 2017-06-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-08-08
  • 2017-06-03
  • 1970-01-01
相关资源
最近更新 更多