Skip to content

Commit 9fb950e

Browse files
committed
test
1 parent 823ccc2 commit 9fb950e

File tree

4 files changed

+139
-20
lines changed

4 files changed

+139
-20
lines changed

backends/imgui_impl_win32.cpp

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -799,6 +799,51 @@ IMGUI_IMPL_API LRESULT ImGui_ImplWin32_WndProcHandlerEx(HWND hwnd, UINT msg, WPA
799799
bd->WantUpdateHasGamepad = true;
800800
#endif
801801
return 0;
802+
803+
case WM_DROPFILES:
804+
{
805+
// Process dropped files
806+
HDROP hDrop = (HDROP)wParam;
807+
UINT fileCount = ::DragQueryFile(hDrop, 0xFFFFFFFF, nullptr, 0);
808+
809+
// Start drag and drop operation with external source flag
810+
ImGuiContext* ctx = ImGui::GetCurrentContext();
811+
if (ctx != nullptr)
812+
{
813+
ImGuiPayload& payload = ctx->DragDropPayload;
814+
if (!payload.SourceId)
815+
{
816+
// Begin drag drop source with external flag
817+
ImGui::BeginDragDropSource(ImGuiDragDropFlags_SourceExtern);
818+
819+
// Add payload for each dropped file
820+
for (UINT i = 0; i < fileCount; i++)
821+
{
822+
// Get file path
823+
wchar_t filePath[MAX_PATH];
824+
::DragQueryFile(hDrop, i, filePath, MAX_PATH);
825+
826+
// Convert to UTF-8
827+
int utf8Length = ::WideCharToMultiByte(CP_UTF8, 0, filePath, -1, nullptr, 0, nullptr, nullptr);
828+
if (utf8Length > 0)
829+
{
830+
std::vector<char> utf8FilePath(utf8Length);
831+
::WideCharToMultiByte(CP_UTF8, 0, filePath, -1, utf8FilePath.data(), utf8Length, nullptr, nullptr);
832+
833+
// Add payload item with file path
834+
ImGui::AddDragDropPayload("DND_FILE_PATH", utf8FilePath.data(), utf8FilePath.size() - 1);
835+
}
836+
}
837+
838+
// End drag drop source
839+
ImGui::EndDragDropSource();
840+
}
841+
}
842+
843+
// Release drop handle
844+
::DragFinish(hDrop);
845+
return 0;
846+
}
802847
}
803848
return 0;
804849
}
@@ -962,6 +1007,12 @@ void ImGui_ImplWin32_EnableAlphaCompositing(void* hwnd)
9621007
}
9631008
}
9641009

1010+
void ImGui_ImplWin32_EnableDragDropAcceptFiles(void* hwnd, bool enabled)
1011+
{
1012+
IM_ASSERT(hwnd != NULL);
1013+
::DragAcceptFiles((HWND)hwnd, enabled ? TRUE : FALSE);
1014+
}
1015+
9651016
//---------------------------------------------------------------------------------------------------------
9661017

9671018
#if defined(__GNUC__)

backends/imgui_impl_win32.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,5 +49,6 @@ IMGUI_IMPL_API float ImGui_ImplWin32_GetDpiScaleForMonitor(void* monitor); //
4949
// - Use to enable alpha compositing transparency with the desktop.
5050
// - Use together with e.g. clearing your framebuffer with zero-alpha.
5151
IMGUI_IMPL_API void ImGui_ImplWin32_EnableAlphaCompositing(void* hwnd); // HWND hwnd
52+
IMGUI_IMPL_API void ImGui_ImplWin32_EnableDragDropAcceptFiles(void* hwnd, bool enabled); // HWND hwnd
5253

5354
#endif // #ifndef IMGUI_DISABLE

imgui.cpp

Lines changed: 64 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -14697,6 +14697,44 @@ void ImGui::EndDragDropSource()
1469714697
}
1469814698

1469914699
// Use 'cond' to choose to submit payload on drag start or every frame
14700+
bool ImGui::AddDragDropPayload(const char* type, const void* data, size_t data_size)
14701+
{
14702+
ImGuiContext& g = *GImGui;
14703+
ImGuiPayload& payload = g.DragDropPayload;
14704+
14705+
IM_ASSERT(type != NULL);
14706+
IM_ASSERT(ImStrlen(type) < IM_ARRAYSIZE(ImGuiPayloadItem::DataType) && "Payload type can be at most 32 characters long");
14707+
IM_ASSERT((data != NULL && data_size > 0) || (data == NULL && data_size == 0));
14708+
IM_ASSERT(payload.SourceId != 0); // Not called between BeginDragDropSource() and EndDragDropSource()
14709+
IM_ASSERT(payload.DataFrameCount != -1); // SetDragDropPayload() must be called first
14710+
14711+
// Create new payload item
14712+
ImGuiPayloadItem item;
14713+
ImStrncpy(item.DataType, type, IM_ARRAYSIZE(item.DataType));
14714+
14715+
// Copy data
14716+
if (data_size > 0)
14717+
{
14718+
// Store in heap
14719+
void* item_data = g.DragDropPayloadBufHeap.Data + g.DragDropPayloadBufHeap.Size;
14720+
g.DragDropPayloadBufHeap.resize(g.DragDropPayloadBufHeap.Size + (int)data_size);
14721+
memcpy(item_data, data, data_size);
14722+
item.Data = item_data;
14723+
item.DataSize = (int)data_size;
14724+
}
14725+
else
14726+
{
14727+
item.Data = NULL;
14728+
item.DataSize = 0;
14729+
}
14730+
14731+
// Add item to payload
14732+
payload.Items.push_back(item);
14733+
14734+
// Return whether the payload has been accepted
14735+
return (g.DragDropAcceptFrameCount == g.FrameCount) || (g.DragDropAcceptFrameCount == g.FrameCount - 1);
14736+
}
14737+
1470014738
bool ImGui::SetDragDropPayload(const char* type, const void* data, size_t data_size, ImGuiCond cond)
1470114739
{
1470214740
ImGuiContext& g = *GImGui;
@@ -14705,35 +14743,39 @@ bool ImGui::SetDragDropPayload(const char* type, const void* data, size_t data_s
1470514743
cond = ImGuiCond_Always;
1470614744

1470714745
IM_ASSERT(type != NULL);
14708-
IM_ASSERT(ImStrlen(type) < IM_ARRAYSIZE(payload.DataType) && "Payload type can be at most 32 characters long");
14746+
IM_ASSERT(ImStrlen(type) < IM_ARRAYSIZE(ImGuiPayloadItem::DataType) && "Payload type can be at most 32 characters long");
1470914747
IM_ASSERT((data != NULL && data_size > 0) || (data == NULL && data_size == 0));
1471014748
IM_ASSERT(cond == ImGuiCond_Always || cond == ImGuiCond_Once);
1471114749
IM_ASSERT(payload.SourceId != 0); // Not called between BeginDragDropSource() and EndDragDropSource()
1471214750

1471314751
if (cond == ImGuiCond_Always || payload.DataFrameCount == -1)
1471414752
{
14715-
// Copy payload
14716-
ImStrncpy(payload.DataType, type, IM_ARRAYSIZE(payload.DataType));
14753+
// Clear existing payload items
14754+
payload.Items.clear();
1471714755
g.DragDropPayloadBufHeap.resize(0);
14718-
if (data_size > sizeof(g.DragDropPayloadBufLocal))
14756+
14757+
// Create first payload item
14758+
ImGuiPayloadItem item;
14759+
ImStrncpy(item.DataType, type, IM_ARRAYSIZE(item.DataType));
14760+
14761+
// Copy data
14762+
if (data_size > 0)
1471914763
{
1472014764
// Store in heap
1472114765
g.DragDropPayloadBufHeap.resize((int)data_size);
14722-
payload.Data = g.DragDropPayloadBufHeap.Data;
14723-
memcpy(payload.Data, data, data_size);
14724-
}
14725-
else if (data_size > 0)
14726-
{
14727-
// Store locally
14728-
memset(&g.DragDropPayloadBufLocal, 0, sizeof(g.DragDropPayloadBufLocal));
14729-
payload.Data = g.DragDropPayloadBufLocal;
14730-
memcpy(payload.Data, data, data_size);
14766+
item.Data = g.DragDropPayloadBufHeap.Data;
14767+
memcpy(item.Data, data, data_size);
14768+
item.DataSize = (int)data_size;
1473114769
}
1473214770
else
1473314771
{
14734-
payload.Data = NULL;
14772+
item.Data = NULL;
14773+
item.DataSize = 0;
1473514774
}
14736-
payload.DataSize = (int)data_size;
14775+
14776+
// Add item to payload and set as current for backward compatibility
14777+
payload.Items.push_back(item);
14778+
payload.CurrentItem = &payload.Items[0];
1473714779
}
1473814780
payload.DataFrameCount = g.FrameCount;
1473914781

@@ -14868,6 +14910,13 @@ const ImGuiPayload* ImGui::AcceptDragDropPayload(const char* type, ImGuiDragDrop
1486814910
RenderDragDropTargetRectForItem(r);
1486914911
}
1487014912

14913+
// Set current item for backward compatibility
14914+
payload.CurrentItem = NULL;
14915+
if (type != NULL)
14916+
payload.CurrentItem = payload.GetItemByType(type);
14917+
else if (!payload.Items.empty())
14918+
payload.CurrentItem = &payload.Items[0];
14919+
1487114920
g.DragDropAcceptFrameCount = g.FrameCount;
1487214921
if ((g.DragDropSourceFlags & ImGuiDragDropFlags_SourceExtern) && g.DragDropMouseButton == -1)
1487314922
payload.Delivery = was_accepted_previously && (g.DragDropSourceFrameCount < g.FrameCount);

imgui.h

Lines changed: 23 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -967,11 +967,13 @@ namespace ImGui
967967
// - An item can be both drag source and drop target.
968968
IMGUI_API bool BeginDragDropSource(ImGuiDragDropFlags flags = 0); // call after submitting an item which may be dragged. when this return true, you can call SetDragDropPayload() + EndDragDropSource()
969969
IMGUI_API bool SetDragDropPayload(const char* type, const void* data, size_t sz, ImGuiCond cond = 0); // type is a user defined string of maximum 32 characters. Strings starting with '_' are reserved for dear imgui internal types. Data is copied and held by imgui. Return true when payload has been accepted.
970+
IMGUI_API bool AddDragDropPayload(const char* type, const void* data, size_t sz); // Add another payload item to the current drag and drop operation. Return true when payload has been accepted.
970971
IMGUI_API void EndDragDropSource(); // only call EndDragDropSource() if BeginDragDropSource() returns true!
971972
IMGUI_API bool BeginDragDropTarget(); // call after submitting an item that may receive a payload. If this returns true, you can call AcceptDragDropPayload() + EndDragDropTarget()
972973
IMGUI_API const ImGuiPayload* AcceptDragDropPayload(const char* type, ImGuiDragDropFlags flags = 0); // accept contents of a given type. If ImGuiDragDropFlags_AcceptBeforeDelivery is set you can peek into the payload before the mouse button is released.
973974
IMGUI_API void EndDragDropTarget(); // only call EndDragDropTarget() if BeginDragDropTarget() returns true!
974975
IMGUI_API const ImGuiPayload* GetDragDropPayload(); // peek directly into the current payload from anywhere. returns NULL when drag and drop is finished or inactive. use ImGuiPayload::IsDataType() to test for the payload type.
976+
IMGUI_API bool AddDragDropPayload(const char* type, const void* data, size_t sz); // Add another payload item to the current drag and drop operation. Return true when payload has been accepted.
975977

976978
// Disabling [BETA API]
977979
// - Disable all user interactions and dim items visuals (applying style.DisabledAlpha over current colors)
@@ -2654,26 +2656,42 @@ struct ImGuiSizeCallbackData
26542656
ImVec2 DesiredSize; // Read-write. Desired size, based on user's mouse position. Write to this field to restrain resizing.
26552657
};
26562658

2659+
// Data payload item for Drag and Drop operations
2660+
struct ImGuiPayloadItem
2661+
{
2662+
void* Data; // Data (copied and owned by dear imgui)
2663+
int DataSize; // Data size
2664+
char DataType[32 + 1]; // Data type tag (short user-supplied string, 32 characters max)
2665+
2666+
ImGuiPayloadItem() { Clear(); }
2667+
void Clear() { Data = NULL; DataSize = 0; memset(DataType, 0, sizeof(DataType)); }
2668+
bool IsDataType(const char* type) const { return strcmp(type, DataType) == 0; }
2669+
};
2670+
26572671
// Data payload for Drag and Drop operations: AcceptDragDropPayload(), GetDragDropPayload()
26582672
struct ImGuiPayload
26592673
{
26602674
// Members
2661-
void* Data; // Data (copied and owned by dear imgui)
2662-
int DataSize; // Data size
2675+
ImVector<ImGuiPayloadItem> Items; // Multiple payload items
2676+
const ImGuiPayloadItem* CurrentItem; // Current item for backward compatibility
26632677

26642678
// [Internal]
26652679
ImGuiID SourceId; // Source item id
26662680
ImGuiID SourceParentId; // Source parent id (if available)
26672681
int DataFrameCount; // Data timestamp
2668-
char DataType[32 + 1]; // Data type tag (short user-supplied string, 32 characters max)
26692682
bool Preview; // Set when AcceptDragDropPayload() was called and mouse has been hovering the target item (nb: handle overlapping drag targets)
26702683
bool Delivery; // Set when AcceptDragDropPayload() was called and mouse button is released over the target item.
26712684

26722685
ImGuiPayload() { Clear(); }
2673-
void Clear() { SourceId = SourceParentId = 0; Data = NULL; DataSize = 0; memset(DataType, 0, sizeof(DataType)); DataFrameCount = -1; Preview = Delivery = false; }
2674-
bool IsDataType(const char* type) const { return DataFrameCount != -1 && strcmp(type, DataType) == 0; }
2686+
void Clear() { SourceId = SourceParentId = 0; Items.clear(); CurrentItem = NULL; DataFrameCount = -1; Preview = Delivery = false; }
2687+
bool IsDataType(const char* type) const { for (int i = 0; i < Items.Size; i++) if (Items[i].IsDataType(type)) return true; return false; }
2688+
const ImGuiPayloadItem* GetItemByType(const char* type) const { for (int i = 0; i < Items.Size; i++) if (Items[i].IsDataType(type)) return &Items[i]; return NULL; }
26752689
bool IsPreview() const { return Preview; }
26762690
bool IsDelivery() const { return Delivery; }
2691+
// Backward compatibility
2692+
const void* GetData() const { return CurrentItem ? CurrentItem->Data : NULL; }
2693+
int GetDataSize() const { return CurrentItem ? CurrentItem->DataSize : 0; }
2694+
const char* GetDataType() const { return CurrentItem ? CurrentItem->DataType : NULL; }
26772695
};
26782696

26792697
//-----------------------------------------------------------------------------

0 commit comments

Comments
 (0)