【问题标题】:Given a window, how can I determine if it is part of a winforms application?给定一个窗口,我如何确定它是否是 winforms 应用程序的一部分?
【发布时间】:2014-06-20 05:52:42
【问题描述】:

我有 Winforms 应用程序主窗体的句柄,以及我要检查的窗口(可能是也可能不是应用程序的一部分)。我尝试过使用 GetParent 进行迭代,但它似乎不起作用。

我实际上要做的是检测模式窗口(例如 MsgBox),获取它的控件,并在控件满足某些要求时发送按钮单击消息(例如 Button)。

现在,虽然我可以检测模态窗口是否打开,并且可以找到当前聚焦的窗口,但我不知道当前聚焦的窗口是否是检测到的模态窗口。本质上,如果我打开一个模型窗口,然后打开一个完全不同的程序,它会尝试查找该外部程序的控件。

代码如下:

if (pF.Visible && !pF.CanFocus) //Is a Modal Window
{

///TODO: Check if currently active window is a child of the main window


///Gets information of currently active window
string currentActiveWindow = GetActiveWindowTitle();
IntPtr currentActiveHandle = GetActiveWindowHandle();

///Gets 'children' or controls of currently active window
var hwndChild = EnumAllWindows(currentActiveHandle);

///Iterate over all child windows
foreach (IntPtr element in hwndChild) {
    const int nChars = 256;
    StringBuilder Buff = new StringBuilder(nChars);
    IntPtr handle = GetForegroundWindow();
    string windowElementType = GetWindowClassName(element);

    ///Check if the "windows" are buttons
    if (GetWindowText(element, Buff, nChars) > 0 && windowElementType=="Button")
    {
        string windowElement = Buff.ToString();
        if (windowElement.ToLower()=="ok")
        {
            ///Send Button click message
            const int BM_CLICK = 0x00F5;
            SendMessage(element, BM_CLICK, IntPtr.Zero, IntPtr.Zero);
        }
    }
}

}

【问题讨论】:

  • 如何检索“外部”窗口?
  • 我认为Process.GetCurrentProcess().Handlethis.Handle 可能会起作用。
  • 向我们展示您的尝试...您是否积极地确定您得到了您的需求窗口?因为那是第一步。第二步是确定它的来源。
  • 与其纠结于窗口句柄和发送窗口消息,不如使用为例如设计的UI Automation 框架。连接到其他应用程序并公开语义信息的辅助技术?
  • UI 自动化是执行此操作的方法。也就是说,我什至无法理解您的问题或问题。你到底想做什么?您在寻找哪个窗口?

标签: c# .net winforms winapi


【解决方案1】:

判断由HWND 标识的两个窗口是否属于同一进程的便捷函数 (C++) 如下所示:

bool OwnedBySameProcess(HWND hWnd1, HWND hWnd2) {
    if ( ::IsWindow(hWnd1) && ::IsWindow(hWnd2) ) {
        DWORD procId1 = 0x0;
        DWORD procId2 = 0x0;
        ::GetWindowThreadProcessId(hWnd1, &procId1);
        ::GetWindowThreadProcessId(hWnd2, &procId2);
        return ( procId1 == procId2 );
    }
    return false;
}

GetWindowThreadProcessId 不受UIPI (User Interface Privilege Isolation) 的约束,并且在有效输入的情况下始终会成功。返回值是 ID,不需要清理。

翻译成C#:

public class Helper
{
    [DllImport("user32.dll")]
    [return: MarshalAs(UnmanagedType.Bool)]
    static extern bool IsWindow(IntPtr hWnd);

    [DllImport("user32.dll")]
    static extern uint GetWindowThreadProcessId(IntPtr hWnd,
                                                out uint lpdwProcessId);

    public static bool OwnedBySameProcess(IntPtr hWnd1, IntPtr hWnd2)
    {
        if ( !IsWindow(hWnd1) )
            throw new ArgumentException("hWnd1");
        if ( !IsWindow(hWnd2) )
            throw new ArgumentException("hWnd2");
        uint procId1 = 0;
        GetWindowThreadProcessId(hWnd1, out procId1);
        uint procId2 = 0;
        GetWindowThreadProcessId(hWnd2, out procId2);
        return ( procId1 == procId2 );
    }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-03-30
    • 1970-01-01
    • 2017-12-16
    • 1970-01-01
    • 2016-03-05
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多