简体   繁体   English

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

[英]Drag&drop event (WM_DROPFILES) in C++ GUI

I am trying to create a simple application where the user can drag and drop files from outside of the window (usually Explorer) into an area inside of the window.我正在尝试创建一个简单的应用程序,用户可以在其中将文件从窗口(通常是资源管理器)外部拖放到窗口内部的区域中。 My ultimate purpose is to get the file path to later on process it.我的最终目的是获取文件路径以供以后处理。

Currently I can drag and drop files into the area but I never receive the WM_DROPFILES event.目前我可以将文件拖放到该区域,但我从未收到 WM_DROPFILES 事件。 I have tried with some related functions (DoDragDrop, RegisterDragDrop, CDropSource), but they all have been either impossible to compile or unsuccessful.我尝试过一些相关的函数(DoDragDrop、RegisterDragDrop、CDropSource),但它们要么无法编译,要么编译不成功。

Could anyone tell me if I am missing setting any property?谁能告诉我我是否缺少设置任何属性?

Many thanks in advance提前谢谢了

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;
}

You are not receiving the WM_DROPFILES message because you are not subclassing the STATIC control you create to receive messages that are sent to it.您没有收到WM_DROPFILES消息,因为您没有继承您创建的 STATIC 控件来接收发送给它的消息。 You are assuming you can catch the message in the control's parent window, but that is not where the message goes.您假设您可以在控件的窗口中捕获消息,但这不是消息所在的位置。 It is sent to the window that you actually drop onto - the STATIC control.它被发送到您实际放置的窗口 - STATIC 控件。

Try this instead:试试这个:

LRESULT CALLBACK StaticWndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam, UINT_PTR uIdSubclass, DWORD_PTR dwRefData)
{
    switch (uMsg) {
        case WM_NCDESTROY: {
            RemoveWindowSubclass(hwnd, &StaticWndProc, uIdSubclass);
            break;
        }
        case WM_DROPFILES: {
            MessageBox(hwnd, "Dragged!", "Title", MB_OK | MB_ICONINFORMATION);
            break;
        }
    }
        
    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() and RegisterDragDrop() (which you should be using instead of WM_DROPFILES ) have nothing to do with receiving WM_DROPFILES . DoDragDrop()RegisterDragDrop() (您应该使用它而不是WM_DROPFILES )与接收WM_DROPFILES

You are missing你不见了

DragAcceptFiles( hwnd, TRUE );

Put it just before message loop.把它放在消息循环之前。

WM_DROPFILES fails to correctly transfer data from 32-bit application to 64-bit one. WM_DROPFILES无法正确地将数据从 32 位应用程序传输到 64 位应用程序。 Could be remedied by implementing IDropTarget and removing WM_DROPFILES handling.可以通过实现IDropTarget和删除WM_DROPFILES处理来补救。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM