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

Posted

技术标签:

【中文标题】C++ GUI 中的拖放事件 (WM_DROPFILES)【英文标题】:Drag&drop event (WM_DROPFILES) in C++ GUI 【发布时间】:2018-07-06 07:10:05 【问题描述】:

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

目前我可以将文件拖放到该区域,但我从未收到 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;

【问题讨论】:

【参考方案1】:

您没有收到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 无关。

【讨论】:

【参考方案2】:

你不见了

DragAcceptFiles( hwnd, TRUE );

把它放在消息循环之前。

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

【讨论】:

以上是关于C++ GUI 中的拖放事件 (WM_DROPFILES)的主要内容,如果未能解决你的问题,请参考以下文章

fullCalendar 中的拖放事件不起作用

HTML5 拖放 getData() 仅适用于 Chrome 中的拖放事件?

HTML5 拖放 getData() 仅适用于 Chrome 中的拖放事件?

如何在 mousedown 元素之外捕获 mouseup 事件? (即正确的拖放?)

H5的拖放事件(拖拽删除)

表单中的拖放功能仍处于禁用状态