I tried using a timer to solve this problem, but I still want to know if there is a more direct way
import c4d
import threading
from c4d.gui import GeUserArea, GeDialog
GADGET_ID_GEUSERAREA = 10000
class DropArea(GeUserArea):
def __init__(self):
# Used to store all objects involved in the drag-and-drop operation
self.currentDragObjects = []
# Flag to indicate whether a drag operation is in progress
self.isDragging = False
# Define a timer to delay the handling of the drag completion
self.dragTimer = None
def Message(self, msg, result):
# Handle drag-and-drop messages
if msg.GetId() == c4d.BFM_DRAGRECEIVE:
# Check if the drag was lost or canceled
if msg.GetInt32(c4d.BFM_DRAG_LOST) or msg.GetInt32(c4d.BFM_DRAG_ESC):
self.isDragging = False
return self.SetDragDestination(c4d.MOUSE_FORBIDDEN)
# If the drag just started, clear the previous object list
if not self.isDragging:
self.currentDragObjects = [] # Initialize the storage list
self.isDragging = True # Mark the beginning of the drag
# Verify if it is a valid drop area
if not self.CheckDropArea(msg, True, True):
return self.SetDragDestination(c4d.MOUSE_FORBIDDEN)
# Get the dragged file object
dragInfo = self.GetDragObject(msg)
if dragInfo is not None:
dragObject = dragInfo['object']
# Check if the object already exists in the list to avoid duplicates
if dragObject not in self.currentDragObjects:
self.currentDragObjects.append(dragObject)
# Reset the timer to delay the handling of drag completion
if self.dragTimer is not None:
self.dragTimer.cancel()
# Set a short timer (e.g., 0.2 seconds) to determine if the drag operation is complete
self.dragTimer = threading.Timer(0.2, self._finalize_drag)
self.dragTimer.start()
# Set the mouse cursor to a valid state
return self.SetDragDestination(c4d.MOUSE_MOVE)
# Call the base class Message() method to handle other messages
return c4d.gui.GeUserArea.Message(self, msg, result)
def _finalize_drag(self):
# Delayed execution to ensure all dragged objects have been received
self.isDragging = False
if self.currentDragObjects:
# Print all dropped files
print(f"Dropped files: {self.currentDragObjects}")
# Additional logic can be executed here, e.g., handling file paths or other content
# Clear the object list for the next drag-and-drop operation
self.currentDragObjects = []
# Redraw the user area (if UI update is needed)
self.Redraw()
class ExampleDialog(GeDialog):
geUserArea = DropArea()
def CreateLayout(self):
self.SetTitle("Drag Area")
if self.GroupBegin(0, c4d.BFH_SCALEFIT | c4d.BFV_SCALEFIT, cols=1, rows=0, title="", groupflags=0, initw=100, inith=100):
self.GroupBorderSpace(8, 8, 8, 8)
self.GroupSpace(2, 2)
# Add the user area gadget
self.AddUserArea(GADGET_ID_GEUSERAREA, c4d.BFH_SCALEFIT | c4d.BFV_SCALEFIT, 200, 200)
# Attach the user area to the gadget
self.AttachUserArea(self.geUserArea, GADGET_ID_GEUSERAREA)
self.GroupEnd()
return True
if __name__ == "__main__":
global dlg
dlg = ExampleDialog()
dlg.Open(dlgtype=c4d.DLG_TYPE_ASYNC, defaultw=200, defaulth=200)