ocornut / imgui

Dear ImGui: Bloat-free Graphical User interface for C++ with minimal dependencies
MIT License
61.15k stars 10.3k forks source link

ImGui window accepting dropped file from external source #7848

Open lyd405121 opened 3 months ago

lyd405121 commented 3 months ago

Version/Branch of Dear ImGui:

Version 1.91

Back-ends:

imgui_impl_iWin32.cpp

Compiler, OS:

Window10

Full config/build information:

No response

Details:

Background

https://github.com/user-attachments/assets/e99f6c75-f23f-4a0e-b865-9c021b140d97

How to do this

WINDOW-PROPERTY

    case WM_DROPFILES:
    {
        HDROP hDrop = reinterpret_cast<HDROP>(wParam);
        char filename[MAX_PATH];
        UINT count = DragQueryFileA(hDrop, -1, NULL, 0);
        for (UINT i = 0; i < count; ++i)
        {
            if (DragQueryFileA(hDrop, i, filename, MAX_PATH))
            {
                printf("%s\n", filename);
            }

        }
        DragFinish(hDrop);
        return 0;
    }

wm

https://github.com/user-attachments/assets/2be1d57c-cbf0-4ed8-8059-f4f89cddb9b0

Can it be a feature

// code generate by coploit
#include <GLFW/glfw3.h>
#include <iostream>

// File drop callback function
void drop_callback(GLFWwindow* window, int count, const char** paths) {
    for (int i = 0; i < count; i++) {
        std::cout << "Dropped file: " << paths[i] << std::endl;
    }
}

int main() {
    // Initialize GLFW
    if (!glfwInit()) {
        std::cerr << "Failed to initialize GLFW" << std::endl;
        return -1;
    }

    // Create a windowed mode window and its OpenGL context
    GLFWwindow* window = glfwCreateWindow(800, 600, "GLFW Drag and Drop Example", NULL, NULL);
    if (!window) {
        std::cerr << "Failed to create GLFW window" << std::endl;
        glfwTerminate();
        return -1;
    }

    // Set the file drop callback
    glfwSetDropCallback(window, drop_callback);

    // Main loop
    while (!glfwWindowShouldClose(window)) {
        // Poll for and process events
        glfwPollEvents();

        // Rendering code (if any)
        // ...

        // Swap front and back buffers
        glfwSwapBuffers(window);
    }

    // Clean up and exit
    glfwDestroyWindow(window);
    glfwTerminate();
    return 0;
}
  // Callback and functions types
typedef int     (*ImGuiInputTextCallback)(ImGuiInputTextCallbackData* data);    // Callback function for ImGui::InputText()
typedef void    (*ImGuiSizeCallback)(ImGuiSizeCallbackData* data);              // Callback function for ImGui::SetNextWindowSizeConstraints()
typedef void*   (*ImGuiMemAllocFunc)(size_t sz, void* user_data);               // Function signature for ImGui::SetAllocatorFunctions()
typedef void    (*ImGuiMemFreeFunc)(void* ptr, void* user_data);                // Function signature for ImGui::SetAllocatorFunctions()

typedef int    (*ImGuiDropFile)(char* file_path);  

Screenshots/Video:

No response

Minimal, Complete and Verifiable Example code:

No response

learn-more commented 3 months ago
    case WM_DROPFILES:
    {
        HDROP hDrop = reinterpret_cast<HDROP>(wParam);
        char filename[MAX_PATH];
        UINT count = DragQueryFileA(hDrop, -1, NULL, 0);
        for (UINT i = 0; i < count; ++i)
        {
            if (DragQueryFileA(hDrop, i, filename, MAX_PATH))
            {
                printf("%s\n", filename);
            }

        }
        DragFinish(hDrop);
        return 0;
    }

Please note that there are a few things that could be improved here:

ocornut commented 3 months ago

I am not 100% sure there is value is handling this on our side. It may be done on user/app side just as well: your WM_DROPFILES event handler can be in app code without modifying the backend.

If we add some support then we need to do it and maintain it for all backends. I suppose it would be good to add it as a helper, but it doesn't seem like a very important thing, and I worry it could grow into a more complex thing if we try to design a generic version of it: It's quite unusual API design for us to use a callback for this, ideally we would expose it as a sort of getter then user is free to handle the event when they like in the frame. Also some people would like to connect this to BeginDragDropSource() with ImGuiDragDropFlags_SourceExtern, some people may want to query it differently. It's not something we can do without careful design.

ocornut commented 3 months ago

Also see #2602

lyd405121 commented 3 months ago