Wednesday, June 24, 2009

Dragging Deferred

Sometimes it's desireable to start a dragging operation in code, for a specific control. One such case is the dragging of forms from a menu or button, when dragging forms is not supported by the widgedset, or for dragging a docked control from a dockzone header.

Now it looks to me as if the widgetsets behave differently, when Control.BeginDrag is invoked. With gtk2, which does not (yet) allow to drag forms, dragging a control from the zone header starts and completes as expected - the docked control can be undocked and docked again somewhere else. With the win32 widgetset the GUI hangs, and when it becomes responsive again, after some clicking, the wrong control may have become floating. How that?

This behaviour may result from the capture and handling of mouse events, where the LButtonDown on the zone header will set csLButtonDown in the ControlState of the dock site (container TWinControl), in TControl.WndProc. This flag should be cleared during the start of dragging, but there exists no information about *which* control has this flag set. When the DragManager assumes that the flag was set for the control to be dragged, this assumption is not always correct. In Delphi the this flag is not set when the DragManager is invoked by BeginAutoDrag (see the lengthy comment in TControl.WndProc, case LM_LBUTTONDOWN, in control.inc).

Now I need some more detailed information about the handling of mouse button events: what will happen when a button is pressed over one control, and is released over a different control?

At least the mouse buttons and states would be much easier to handle, when the target and mouse position of a button press would be stored globally, so that the button-down flag can be cleared in any case, in the control with this flag set. Then it also were possible to delay the start of a dragging operaion in the TControl.WndProc, when the dragging threshold is exceeded by a mouse move, relative to the (globally) stored mouse-down position. The mouse button flag(s) IMO should be removed from the controls' state, and should be moved into the Mouse object instead. Then all clicks and moves could be handled inside the mouse object, and only the resulting Click events etc. should be sent to the affected control.

No comments:

Post a Comment