SFML community forums

Help => Window => Topic started by: Me-Myself-And-I on September 09, 2024, 05:06:35 pm

Title: (SOLVED)My implementation of dragndrop files for window is not working at all.
Post by: Me-Myself-And-I on September 09, 2024, 05:06:35 pm
Hello. I'm trying to implement dragndrop files functionality into my sf::window for windows 11 using the window handle and WINAPI. So far I have this but it doesn't do anything. The window shows it allows dragndrop but it doesn't receive any path to the dropped files.

int main(int argc,char* argv[])
{
       
               
       
       
        IntRect workarea;
        workarea=getWorkArea();
        RenderWindow window(VideoMode(workarea.width,workarea.height),"Desk Engine",Style::None);
        window.setPosition(Vector2i(0,0));     
       
        //Set SFML to allow dragNdrop and hide from taskbar.
        WindowHandle handle = window.getSystemHandle();
        SetWindowLongPtrA(handle,GWL_EXSTYLE,WS_EX_ACCEPTFILES|WS_EX_TOOLWINDOW);

        DragAcceptFiles(handle, TRUE);
       
        while(window.isOpen())
        {
               
                Event e;
                while(window.pollEvent(e))
                {
                        if(e.type==Event::Closed)
                                window.close();
                }
               
                //Handle DRAG and DROP
                MSG msg;
        while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
        {
            if (msg.message == WM_DROPFILES)
            {
                HDROP hDrop = (HDROP)msg.wParam;
                char filePath[MAX_PATH];
                DragQueryFileA(hDrop, 0, filePath, MAX_PATH);
                DragFinish(hDrop);
                cout << filePath << endl;
            }
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }
       
        //render stuff
}
 
Thanks in advance!
Title: Re: My implementation of dragndrop files for window is not working at all.
Post by: eXpl0it3r on September 10, 2024, 07:55:13 am
You're passing NULL has the window handle, so there's no connection between the window an the inserted event pump.
SFML already implements an event pump, so you can't just write another one next to it, but you'll have to insert your own callback for event processing like this:

#include <SFML/Graphics.hpp>
#include <Windows.h>

LONG_PTR SfmlEventCallback = 0x0;

LRESULT CALLBACK CustomEventCallback(HWND handle, UINT message, WPARAM wParam, LPARAM lParam)
{
    if (message == WM_MENU...)
    {
        // Your event handling
    }

    return CallWindowProcW(reinterpret_cast<WNDPROC>(SfmlEventCallback), handle, message, wParam, lParam);
}

int main()
{
    auto app = sf::RenderWindow{ { 640u, 480u }, "Custom Event Handling" };
    HWND handle = app.getSystemHandle();

    SfmlEventCallback = SetWindowLongPtrW(handle, GWLP_WNDPROC, reinterpret_cast<LONG_PTR>(CustomEventCallback));

    while (app.isOpen())
    {
        for (auto event = sf::Event{}; app.pollEvent(event);)
        {
            if (event.type == sf::Event::Closed)
            {
                app.close();
            }
        }

        app.clear();
        app.display();
    }
}
 

And here's some code from FRex for a custom file drop handling:

#include <SFML/Window.hpp>
#include <iostream>
#include <Windows.h>

LONG_PTR originalsfmlcallback = 0x0;

LRESULT CALLBACK mycallback(HWND handle, UINT message, WPARAM wParam, LPARAM lParam)
{
    if(message == WM_DROPFILES)
    {
        HDROP hdrop = reinterpret_cast<HDROP>(wParam);
        POINT p;
        p.x = 0;
        p.y = 0;
        if(DragQueryPoint(hdrop, &p))
            std::printf("Point is %d, %d\n", p.x, p.y);
        else
            std::cout << "Failed to get point" << std::endl;

        const UINT filescount = DragQueryFile(hdrop, 0xFFFFFFFF, NULL, 0);
        for(UINT i = 0; i < filescount; ++i)
        {
            const UINT bufsize = DragQueryFile(hdrop, i, NULL, 0);
            std::wstring str;
            str.resize(bufsize + 1);
            if(DragQueryFile(hdrop, i, &str[0], bufsize + 1))
            {
                std::string stdstr;
                sf::Utf8::fromWide(str.begin(), str.end(), std::back_inserter(stdstr));
                std::cout << stdstr << std::endl;
            }
        }
        DragFinish(hdrop);
        std::cout << "-------------" << std::endl;
    }//if WM_DROPFILES
    return CallWindowProcW(reinterpret_cast<WNDPROC>(originalsfmlcallback), handle, message, wParam, lParam);
}

int main(int argc, char ** argv)
{
    sf::Window app(sf::VideoMode(640u, 480u), "Drag and Drop from USERLAND");
    HWND handle = app.getSystemHandle();

    DragAcceptFiles(handle, TRUE);
    originalsfmlcallback = SetWindowLongPtrW(handle, GWLP_WNDPROC, reinterpret_cast<LONG_PTR>(mycallback));

    while(app.isOpen())
    {
        sf::Event eve;
        while(app.pollEvent(eve))
        {
            if(eve.type == sf::Event::Closed)
                app.close();

        }//while app poll event eve
        app.display();
    }//while app is open
}
 
Title: Re: My implementation of dragndrop files for window is not working at all.
Post by: Me-Myself-And-I on September 10, 2024, 11:28:37 pm
Thankyou so much! :D This is just what i've been looking for.
btw the function DragQueryFile didn't work for me with the third parameter being wstring. I changed it to char fPath(MAX_PATH); and that worked. I don't know if thats better or worse but I just thought i'd mention the aforementioned wstring didn't work for me. Thanks again for your help. ;D