C++ 为什么我找不到Spy++;?

C++ 为什么我找不到Spy++;?,c++,windows,winapi,findwindow,spy++,C++,Windows,Winapi,Findwindow,Spy++,假设有一个网页上有一个。我在Firefox中打开此页面,然后单击文件按钮。然后会弹出一个对话框 我想用C++编程设置弹出对话框的文件名编辑: 首先,我使用Spy++检查窗口类,Spy++中的Firefox窗口和弹出对话框属性如下所示: Firefox window: Handle: 001E013E Caption: Table with objects - Mozilla Firefox Class: MozillaWindowClass Popup dialog:

假设有一个网页上有一个
。我在Firefox中打开此页面,然后单击文件按钮。然后会弹出一个对话框

我想用C++编程设置弹出对话框的文件名编辑:

首先,我使用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");
}
hDialog
仍输出为
NULL

问题:

  • 为什么Spy++中的句柄和我在程序中得到的句柄不一样
  • Spy++中的“父窗口”与
    FindWindowEx
    中的父参数的含义是否相同
  • 注意:由于本地化问题,我无法使用窗口标题进行查找(Firefox可能以英语以外的语言安装)


    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;
    }
    
    此代码依赖于未记录的内部名称和窗口关系,它可能随时中断


    请记住,“MozillaWindowClass”是一个内部Mozilla名称,可以随时更改。文件名控件的cmb13 id仅为
    GetOpenFileName
    GetSaveFileName
    记录,但不用于基于文件名的对话框。在与另一个应用程序中的“打开”对话框交互时,确实应该使用

    据猜测,有不止一个MozillaWindowClass窗口,而你从FindWindow获得的窗口不是你用Spy++指向的窗口。@BobMoore我只打开了一个Firefox窗口,只有一个选项卡。Firefox中的编辑字段不是win32控件,你不能用win32 api更改它们的内容。class L“#32770(Dialog)”不存在。需要在
    FindWindowEx
    FindWindowEx子窗口中使用L“#32770”。对话框是弹出窗口,而不是子窗口。API和MSDN文档的某些部分将父子关系与所有者拥有的父子关系混为一谈,但在某些情况下,区别很重要。
    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;
    }