chintogtokh
chintogtokh

Reputation: 803

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). I've tried iterating using GetParent, but it doesn't seem to work.

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).

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

}

Upvotes: 2

Views: 897

Answers (1)

IInspectable
IInspectable

Reputation: 51506

A convenience function (C++) to determine whether two windows identified by their HWND belong to the same process would look like this:

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. The return values are IDs and do not need to be cleaned up.

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

Upvotes: 4

Related Questions