简体   繁体   English

给定一个窗口,如何确定它是否属于winforms应用程序?

[英]Given a window, how can I determine if it is part of a winforms application?

I have handles to the main form of the Winforms application, and the window that I'm trying to check (which may or may not be part of the application). 我有Winforms应用程序的主要形式的句柄,还有我要检查的窗口(它可能是应用程序的一部分,也可能不是该应用程序的一部分)。 I've tried iterating using GetParent, but it doesn't seem to work. 我已经尝试过使用GetParent进行迭代,但是它似乎不起作用。

What I'm essentially trying to do is detect a modal window (such as a MsgBox), get it's controls, and send a button click message if the controls fulfill some requirements (like be a Button ). 我实质上想做的是检测一个模式窗口(例如MsgBox),获取它的控件,并在控件满足某些要求(例如Button )时发送按钮单击消息。

Now, while I can detect if a modal window is open, and can find the currently focused window, I have no idea if the currently focused window is the modal window that was detected. 现在,虽然我可以检测是否打开了模态窗口并可以找到当前聚焦的窗口,但是我不知道当前聚焦的窗口是否是检测到的模态窗口。 Essentially, if I open a model window and then open up a completely different program, it tries to find the controls of that external program. 本质上,如果我打开一个模型窗口,然后打开一个完全不同的程序,它将尝试查找该外部程序的控件。

The code is below: 代码如下:

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);
        }
    }
}

}

A convenience function (C++) to determine whether two windows identified by their HWND belong to the same process would look like this: 一个便捷函数(C ++),用于确定由其HWND标识的两个窗口是否属于同一进程,如下所示:

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;
}

The GetWindowThreadProcessId is not subject to UIPI (User Interface Privilege Isolation) and will always succeed given valid input. GetWindowThreadProcessId不受UIPI(用户界面特权隔离)的约束,并且在有效输入的情况下将始终成功。 The return values are IDs and do not need to be cleaned up. 返回值是ID,不需要清理。

Translated to C#: 转换为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 );
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM