为什么我找不到 window use parent specified in Spy++?
Why did I fail to find window use parent specified in Spy++?
假设有一个带有 <input type="file" />
的网页。我在 Firefox 中打开此页面,然后单击文件按钮。然后会弹出一个对话框。
我想在 C++ 中以编程方式设置弹出对话框的文件名编辑:
首先我使用 Spy++ 检查 window class,Spy++ 中的 Firefox window 和弹出对话框属性如下所示:
Firefox window:
Handle: 001E013E
Caption: Table with objects - Mozilla Firefox
Class: MozillaWindowClass
Popup dialog:
Handle: 004508BE
Caption: File Upload
Class: #32770 (Dialog)
Spy++ 还显示浏览器 window 是弹出对话框的父级。
我的代码如下所示:
#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 window,只有一个选项卡。
然后我尝试将我的代码更改为:
// 0x001E013E is the handle in Spy++
HWND hDialog = FindWindowEx((HWND)0x001E013E, NULL, L"#32770 (Dialog)", NULL);
hDialog
仍然输出为 NULL
.
问题:
- 为什么Spy++中的句柄和我在程序中得到的句柄不一样?
- Spy++中的"parent window"和
FindWindowEx
中的parent参数是同一个意思吗?
Note: I can't use window title to do the find, due to localization issue (Firefox may be installed in languages other than English).
MozillaWindowClass 是打开对话框的所有者,它不是可以与 FindWindowEx
一起使用的父级。也可以有多个 MozillaWindowClass window 所以最好先查找对话框:
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] = '[=10=]'; // 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;
}
此代码依赖于未记录的内部名称和 window 关系,它可能随时中断。
请记住,"MozillaWindowClass" 是 Mozilla 的内部名称,随时可能更改。 documented cmb13 id of the filename control is only documented for GetOpenFileName
and GetSaveFileName
but not for IFileDialog
based dialogs. You really should use UI Automation 当您与另一个应用程序中打开的对话框交互时!
假设有一个带有 <input type="file" />
的网页。我在 Firefox 中打开此页面,然后单击文件按钮。然后会弹出一个对话框。
我想在 C++ 中以编程方式设置弹出对话框的文件名编辑:
首先我使用 Spy++ 检查 window class,Spy++ 中的 Firefox window 和弹出对话框属性如下所示:
Firefox window:
Handle: 001E013E
Caption: Table with objects - Mozilla Firefox
Class: MozillaWindowClass
Popup dialog:
Handle: 004508BE
Caption: File Upload
Class: #32770 (Dialog)
Spy++ 还显示浏览器 window 是弹出对话框的父级。
我的代码如下所示:
#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 window,只有一个选项卡。
然后我尝试将我的代码更改为:
// 0x001E013E is the handle in Spy++
HWND hDialog = FindWindowEx((HWND)0x001E013E, NULL, L"#32770 (Dialog)", NULL);
hDialog
仍然输出为 NULL
.
问题:
- 为什么Spy++中的句柄和我在程序中得到的句柄不一样?
- Spy++中的"parent window"和
FindWindowEx
中的parent参数是同一个意思吗?
Note: I can't use window title to do the find, due to localization issue (Firefox may be installed in languages other than English).
MozillaWindowClass 是打开对话框的所有者,它不是可以与 FindWindowEx
一起使用的父级。也可以有多个 MozillaWindowClass window 所以最好先查找对话框:
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] = '[=10=]'; // 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;
}
此代码依赖于未记录的内部名称和 window 关系,它可能随时中断。
请记住,"MozillaWindowClass" 是 Mozilla 的内部名称,随时可能更改。 documented cmb13 id of the filename control is only documented for GetOpenFileName
and GetSaveFileName
but not for IFileDialog
based dialogs. You really should use UI Automation 当您与另一个应用程序中打开的对话框交互时!