为什么我找不到在Spy ++中指定的窗口使用父级?

时间:2017-03-15 08:02:30

标签: c++ windows winapi findwindow spy++

想象一下,有一个<input type="file" />的网页。我在Firefox中打开此页面,然后单击文件按钮。然后会弹出一个对话框。

我想在C ++中以编程方式设置弹出对话框的文件名编辑:

enter image description here

首先我使用Spy ++检查窗口类,Spy ++中的Firefox窗口和弹出对话框属性如下:

Firefox window:
Handle:     001E013E
Caption:    Table with objects - Mozilla Firefox
Class:      MozillaWindowClass

Popup dialog:
Handle:     004508BE
Caption:    File Upload
Class:      #32770 (Dialog)

Spy ++还显示浏览器窗口是弹出对话框的父级。

我的代码如下:

#include <Windows.h>
#include <stdio.h>

int main()
{
    HWND hBrowser = FindWindow(L"MozillaWindowClass", NULL);
    printf("Browser hwnd=%X\n", hBrowser);

    HWND hDialog = FindWindowEx(hBrowser, NULL, L"#32770 (Dialog)", NULL);
    printf("Dialog hwnd=%X\n", hDialog);

    system("pause");
}

hBrowser的值与Spy ++对话框中的值不相等,hDialog的值为NULL。我只打开了一个Firefox窗口,只有一个选项卡。

然后我尝试将我的代码更改为:

// 0x001E013E is the handle in Spy++
HWND hDialog = FindWindowEx((HWND)0x001E013E, NULL, L"#32770 (Dialog)", NULL);

hDialog仍然以NULL输出。

问题:

  1. 为什么Spy ++中的句柄和程序中的句柄不一样?
  2. Spy ++中的“父窗口”与FindWindowEx中的父参数具有相同的含义吗?
  3.   

    注意:由于本地化问题,我无法使用窗口标题进行查找(Firefox可能以非英语语言安装)。

1 个答案:

答案 0 :(得分:3)

MozillaWindowClass是打开对话框的所有者,它不是您可以与FindWindowEx一起使用的父级。也可以有多个MozillaWindowClass窗口,因此最好首先查找对话框:

BOOL CALLBACK FindMozillaOpenFilenameDialogEnumProc(HWND hWnd, LPARAM param)
{
    HWND*pData = (HWND*) param;
    if (GetClassLongPtr(hWnd, GCW_ATOM) == 32770) // Found a dialog?
    {
        HWND hOwner = GetWindow(hWnd, GW_OWNER);
        if (hOwner)
        {
            WCHAR buf[100];
            GetClassName(hOwner, buf, 100);
            if (0 == lstrcmp(buf, TEXT("MozillaWindowClass"))) // The dialog is owned by a Mozilla window?
            {
                HWND hCombo = GetDlgItem(hWnd, 0x047c); // cmb13
                GetClassName(hCombo, buf, 100);
                buf[8] = '\0'; // Some Windows versions use ComboBox and some use ComboBoxEx32, we only care if it is some type of combobox
                if (0 == lstrcmp(buf, TEXT("ComboBox"))) // The dialog contains a ComboBox with the expected ID?
                {
                    *pData = hWnd;
                    return false;
                }
            }
        }
    }
    return true;
}


int main()
{

    HWND hDialog = NULL;
    EnumWindows(FindMozillaOpenFilenameDialogEnumProc, (LPARAM) &hDialog);
    printf("Dialog hwnd=%X\n", hDialog);
    if (hDialog)
    {
        HWND hCombo = GetDlgItem(hDialog, 0x047c);
        SendMessage(hCombo, WM_SETTEXT, 0, (LPARAM) TEXT("c:\\foo\\bar.exe")); // Could also use CDM_SETCONTROLTEXT?
    }
    return 0;
}

此代码依赖于未记录的内部名称和窗口关系,它可能随时中断。

请记住&#34; MozillaWindowClass&#34;是一个内部Mozilla名称,可以随时更改。文件名控件的documented cmb13 id仅记录GetOpenFileNameGetSaveFileName,但不记录基于IFileDialog的对话框。当您与另一个应用程序中的打开对话框进行交互时,您真的应该使用UI Automation