C ++ GUI中的拖放事件(WM_DROPFILES)

时间:2018-07-06 07:10:05

标签: c++ windows user-interface winapi drag-and-drop

我正在尝试创建一个简单的应用程序,用户可以在其中将文件从窗口外部(通常是资源管理器)拖放到窗口内部的区域中。我的最终目的是获取文件路径以供以后处理。

当前,我可以将文件拖放到该区域中,但是我从未收到WM_DROPFILES事件。我已经尝试了一些相关功能(DoDragDrop,RegisterDragDrop,CDropSource),但是它们要么都无法编译,要么都失败了。

有人可以告诉我是否缺少设置任何属性吗?

非常感谢

LRESULT CALLBACK WndProc(HWND hwnd, UINT Message, WPARAM wParam, LPARAM lParam)
{
    switch (Message)
    {
        case WM_CREATE:
        {
            CreateWindowEx(
                WS_EX_ACCEPTFILES,
                TEXT("static"),
                TEXT("Drag and drop your file to this area"),
                WS_VISIBLE | WS_CHILD,
                20, // x
                20, // y
                120, // w
                60, // h
                hwnd, // parent window
                (HMENU) 1, // unique label
                NULL, NULL);
        }
        case WM_DROPFILES:
        {
            MessageBox(hwnd, "Dragged!", "Title", MB_OK | MB_ICONINFORMATION);
        }

        case WM_DESTROY:
        {
            PostQuitMessage(0);
            break;
        }

        default:
        {
            return DefWindowProc(hwnd, Message, wParam, lParam);
        }
    }
    return 0;
}

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
    WNDCLASSEX wc;
    HWND hwnd;
    MSG msg;

    memset(&wc,0,sizeof(wc));
    wc.cbSize        = sizeof(WNDCLASSEX);
    wc.lpfnWndProc   = WndProc;
    wc.hInstance     = hInstance;
    wc.hCursor       = LoadCursor(NULL, IDC_ARROW); 
    wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
    wc.lpszClassName = "WindowClass";
    wc.hIcon         = LoadIcon(NULL, IDI_APPLICATION);
    wc.hIconSm       = LoadIcon(NULL, IDI_APPLICATION);

    if (!RegisterClassEx(&wc))
    {
        MessageBox(NULL, "Window Registration Failed!","Error!",MB_ICONEXCLAMATION|MB_OK);
        return 0;
    }

    hwnd = CreateWindowEx(
        WS_EX_CLIENTEDGE,
        "WindowClass",
        "MySimpleApp",
        WS_VISIBLE | WS_OVERLAPPEDWINDOW,
        CW_USEDEFAULT,
        CW_USEDEFAULT,
        WINDOW_W,
        WINDOW_H,
        NULL,NULL,hInstance,NULL);

    if (hwnd == NULL)
    {
        MessageBox(NULL, "Window Creation Failed!","Error!",MB_ICONEXCLAMATION|MB_OK);
        return 0;
    }

    while (GetMessage(&msg, NULL, 0, 0) > 0)
    {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }
    return msg.wParam;
}

2 个答案:

答案 0 :(得分:2)

您没有收到WM_DROPFILES消息,因为您没有将创建的STATIC控件子类化以接收发送给它的消息。您假设可以在控件的 parent 窗口中捕获消息,但这不是消息所在的地方。它被发送到您实际放置的窗口-STATIC控件。

尝试以下方法:

LRESULT CALLBACK StaticWndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam, UINT_PTR uIdSubclass, DWORD_PTR dwRefData)
{
    if (uMsg == WM_DROPFILES) {
        MessageBox(hwnd, "Dragged!", "Title", MB_OK | MB_ICONINFORMATION);
    }
    return DefSubclassProc(hwnd, uMsg, wParam, lParam);
}

LRESULT CALLBACK WndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
    switch (uMsg)
    {
        case WM_CREATE: {
            HWND hStatic = CreateWindowEx(
                WS_EX_ACCEPTFILES,
                TEXT("static"),
                TEXT("Drag and drop your file to this area"),
                WS_VISIBLE | WS_CHILD,
                20, // x
                20, // y
                120, // w
                60, // h
                hwnd, // parent window
                (HMENU) 1, // unique label
                NULL, NULL);
            SetWindowSubclass(hStatic, &StaticWndProc, 0, 0);
            break;
        }

        case WM_DESTROY: {
            PostQuitMessage(0);
            break;
        }

        default: {
            return DefWindowProc(hwnd, Message, wParam, lParam);
        }
    }

    return 0;
}

DoDragDrop()RegisterDragDrop()(您应该使用它们而不是WM_DROPFILES来使用)与接收WM_DROPFILES无关。

答案 1 :(得分:1)

你失踪了

DragAcceptFiles( hwnd, TRUE );

将其放在消息循环之前。

WM_DROPFILES无法将数据从64位应用程序正确传输到32位应用程序。可以通过实施IDropTarget并删除WM_DROPFILES处理来补救。