我正在编写一个接受文件拖放的 C 程序。
当它以 32 位编译时,它在任何情况下都可以工作。但当它以 64 位编译时,它仅适用于从 64 位应用程序拖动的文件:
- 32 位 -> 32 位:成功
- 64 位 -> 64 位:成功
- 64 位 -> 32 位:成功
- 32 位 -> 64 位:失败
我仍然收到 WM_DROPFILES 消息,但 DragQueryFile 没有返回任何内容(文件数为 0)。
这对于很多应用程序来说似乎都是一个问题,但我想知道是否有解决方法。
Edit:
- 如果我将文件从 64 位可执行文件拖放到我的 64 位应用程序中,wParam 的值将为 0x000000F211C000B8(这表明不存在转换问题)。
- 接下来,在不关闭我的应用程序的情况下,如果我从 32 位可执行文件中拖动文件,wParam 将具有类似 0x0000000011C000B8 或 0xFFFFFFFF11C000B8 的内容,这意味着高位 32 位无效。
- 如果我将无效的高位替换为上一条消息中的有效高位(在本例中,这将是 0x000000F2),则 DragQueryFile 可以工作!
所以数据在这里,在某个地方,我只是不知道如何检索它们(至少没有丑陋的黑客)。
Edit 2:
我不会提供任何代码,因为我假设回答者了解这个影响大量软件的问题。
- - - 编辑 - - - - -
重现它的最少代码
LRESULT WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
WCHAR sz[32];
switch (uMsg)
{
case WM_DROPFILES:
swprintf(sz, L"%p", wParam);// look for wParam
MessageBox(0,0,sz,0);
break;
case WM_NCCREATE:
DragAcceptFiles(hwnd, TRUE);
break;
case WM_NCDESTROY:
PostQuitMessage(0);
break;
}
return DefWindowProc(hwnd, uMsg, wParam, lParam);
}
void minimal()
{
static WNDCLASS wndcls = { 0, WindowProc, 0, 0, 0, 0, 0, 0, 0, L"testwnd" };
if (RegisterClass(&wndcls))
{
if (HWND hwnd = CreateWindowEx(WS_EX_ACCEPTFILES, wndcls.lpszClassName, 0,
WS_OVERLAPPEDWINDOW|WS_VISIBLE, CW_USEDEFAULT, CW_USEDEFAULT,
CW_USEDEFAULT, CW_USEDEFAULT, HWND_DESKTOP, 0, 0, 0))
{
MSG msg;
while (0 < GetMessage(&msg, 0, 0, 0))
{
if (msg.message == WM_DROPFILES)
{
// look for msg.wParam returned by GetMessage
WCHAR name[256];
DragQueryFile((HDROP)msg.wParam, 0, name, RTL_NUMBER_OF(name));
}
DispatchMessage(&msg);
}
}
UnregisterClass(wndcls.lpszClassName, 0);
}
}
有趣的是,如果调用 DragAcceptFiles(即使只跳转到第一个 it 指令),wParam 的高 32 位将全部为 1。如果不调用它,则通过自行设置 WS_EX_ACCEPTFILES exstyle - wParam 的所有高位将为 0
为了测试可以执行 32 位记事本,打开“打开文件”对话框并将任何文件拖放到我们的窗口中