Mikołaj Zalewski : comctl32: header: Draw the drag image and hot dividers while dragging an item.

Alexandre Julliard julliard at wine.codeweavers.com
Fri May 26 05:42:15 CDT 2006


Module: wine
Branch: master
Commit: 7ab41112ae49ba10a4f9f07fe5e4b4c0521f713c
URL:    http://source.winehq.org/git/?p=wine.git;a=commit;h=7ab41112ae49ba10a4f9f07fe5e4b4c0521f713c

Author: Mikołaj Zalewski <mikolaj at zalewski.pl>
Date:   Thu May 25 23:53:24 2006 +0200

comctl32: header: Draw the drag image and hot dividers while dragging an item.

---

 dlls/comctl32/header.c |  108 +++++++++++++++++++++++++++++++++++++-----------
 1 files changed, 83 insertions(+), 25 deletions(-)

diff --git a/dlls/comctl32/header.c b/dlls/comctl32/header.c
index 3242bbd..dccc6a2 100644
--- a/dlls/comctl32/header.c
+++ b/dlls/comctl32/header.c
@@ -32,6 +32,7 @@
  */
 
 #include <stdarg.h>
+#include <stdlib.h>
 #include <string.h>
 
 #include "windef.h"
@@ -77,7 +78,9 @@ typedef struct
     HCURSOR   hcurDivopen;	/* handle to a cursor (used over dividers) <-||-> */
     BOOL      bCaptured;	/* Is the mouse captured? */
     BOOL      bPressed;		/* Is a header item pressed (down)? */
+    BOOL      bDragging;        /* Are we dragging an item? */
     BOOL      bTracking;	/* Is in tracking mode? */
+    POINT     ptLButtonDown;    /* The point where the left button was pressed */
     INT       iMoveItem;	/* index of tracked item. (Tracking mode) */
     INT       xTrackOffset;	/* distance between the right side of the tracked item and the cursor */
     INT       xOldTrack;	/* track offset (see above) after the last WM_MOUSEMOVE */
@@ -512,6 +515,9 @@ HEADER_Refresh (HWND hwnd, HDC hdc)
 
     /* get rect for the bar, adjusted for the border */
     GetClientRect (hwnd, &rect);
+    
+    if (infoPtr->bDragging)
+	ImageList_DragShowNolock(FALSE);
 
     hFont = infoPtr->hFont ? infoPtr->hFont : GetStockObject (SYSTEM_FONT);
     hOldFont = SelectObject (hdc, hFont);
@@ -546,6 +552,9 @@ HEADER_Refresh (HWND hwnd, HDC hdc)
     
     if (infoPtr->iHotDivider != -1)
         HEADER_DrawHotDivider(hwnd, hdc);
+
+    if (infoPtr->bDragging)
+	ImageList_DragShowNolock(TRUE);
     SelectObject (hdc, hOldFont);
 }
 
@@ -1556,6 +1565,16 @@ HEADER_GetFont (HWND hwnd)
 }
 
 
+static BOOL
+HEADER_IsDragDistance(HEADER_INFO *infoPtr, POINT *pt)
+{
+    /* Windows allows for a mouse movement before starting the drag. We use the
+     * SM_CXDOUBLECLICK/SM_CYDOUBLECLICK as that distance.
+     */
+    return (abs(infoPtr->ptLButtonDown.x - pt->x)>GetSystemMetrics(SM_CXDOUBLECLK) ||
+            abs(infoPtr->ptLButtonDown.y - pt->y)>GetSystemMetrics(SM_CYDOUBLECLK));
+}
+
 static LRESULT
 HEADER_LButtonDblClk (HWND hwnd, WPARAM wParam, LPARAM lParam)
 {
@@ -1594,7 +1613,9 @@ HEADER_LButtonDown (HWND hwnd, WPARAM wP
 	SetCapture (hwnd);
 	infoPtr->bCaptured = TRUE;
 	infoPtr->bPressed  = TRUE;
+	infoPtr->bDragging = FALSE;
 	infoPtr->iMoveItem = nItem;
+	infoPtr->ptLButtonDown = pt;
 
 	infoPtr->items[nItem].bDown = TRUE;
 
@@ -1644,7 +1665,37 @@ HEADER_LButtonUp (HWND hwnd, WPARAM wPar
     HEADER_InternalHitTest (hwnd, &pt, &flags, &nItem);
 
     if (infoPtr->bPressed) {
-	if ((nItem == infoPtr->iMoveItem) && (flags == HHT_ONHEADER)) {
+	if (infoPtr->bDragging)
+	{
+	    ImageList_DragShowNolock(FALSE);
+	    ImageList_EndDrag();
+	    infoPtr->items[infoPtr->iMoveItem].bDown=FALSE;
+	    /* FIXME: the new order field should be sent, not the old one */
+	    if (!HEADER_SendHeaderNotifyT(hwnd, HDN_ENDDRAG, infoPtr->iMoveItem, HDI_ORDER, NULL))
+	    {
+		HEADER_ITEM *lpItem;
+		INT newindex = HEADER_IndexToOrder(hwnd,nItem);
+		INT oldindex = HEADER_IndexToOrder(hwnd,infoPtr->iMoveItem);
+
+		TRACE("Exchanging [index:order] [%d:%d] [%d:%d]\n",
+		    infoPtr->iMoveItem,oldindex,nItem,newindex);
+        	lpItem= &infoPtr->items[nItem];
+		lpItem->iOrder=oldindex;
+
+        	lpItem= &infoPtr->items[infoPtr->iMoveItem];
+		lpItem->iOrder = newindex;
+
+        	infoPtr->order[oldindex] = nItem;
+        	infoPtr->order[newindex] = infoPtr->iMoveItem;
+
+		infoPtr->bRectsValid = FALSE;
+		InvalidateRect(hwnd, NULL, FALSE);
+	    }
+	    else
+		InvalidateRect(hwnd, &infoPtr->items[infoPtr->iMoveItem].rect, FALSE);
+	}
+	else if (!(dwStyle&HDS_DRAGDROP) || !HEADER_IsDragDistance(infoPtr, &pt))
+	{
 	    infoPtr->items[infoPtr->iMoveItem].bDown = FALSE;
 	    hdc = GetDC (hwnd);
 	    HEADER_RefreshItem (hwnd, hdc, infoPtr->iMoveItem);
@@ -1652,27 +1703,6 @@ HEADER_LButtonUp (HWND hwnd, WPARAM wPar
 
 	    HEADER_SendClickNotify (hwnd, HDN_ITEMCLICKA, infoPtr->iMoveItem);
 	}
-	else if (flags == HHT_ONHEADER)
-	  {
-	    HEADER_ITEM *lpItem;
-	    INT newindex = HEADER_IndexToOrder(hwnd,nItem);
-	    INT oldindex = HEADER_IndexToOrder(hwnd,infoPtr->iMoveItem);
-
-	    TRACE("Exchanging [index:order] [%d:%d] [%d:%d]\n",
-		  infoPtr->iMoveItem,oldindex,nItem,newindex);
-            lpItem= &infoPtr->items[nItem];
-	    lpItem->iOrder=oldindex;
-
-            lpItem= &infoPtr->items[infoPtr->iMoveItem];
-	    lpItem->iOrder = newindex;
-
-            infoPtr->order[oldindex] = nItem;
-            infoPtr->order[newindex] = infoPtr->iMoveItem;
-
-	    infoPtr->bRectsValid = FALSE;
-	    InvalidateRect(hwnd, NULL, FALSE);
-	    /* FIXME: Should some WM_NOTIFY be sent */
-	  }
 
 	TRACE("Released item %d!\n", infoPtr->iMoveItem);
 	infoPtr->bPressed = FALSE;
@@ -1735,7 +1765,6 @@ HEADER_NotifyFormat (HWND hwnd, WPARAM w
     return 0;
 }
 
-
 static LRESULT
 HEADER_MouseLeave (HWND hwnd, WPARAM wParam, LPARAM lParam)
 {
@@ -1779,7 +1808,36 @@ HEADER_MouseMove (HWND hwnd, WPARAM wPar
     }
 
     if (infoPtr->bCaptured) {
-	if (infoPtr->bPressed) {
+        /* check if we should drag the header */
+	if (infoPtr->bPressed && !infoPtr->bDragging && dwStyle&HDS_DRAGDROP
+	    && HEADER_IsDragDistance(infoPtr, &pt))
+	{
+	    if (!HEADER_SendHeaderNotifyT(hwnd, HDN_BEGINDRAG, infoPtr->iMoveItem, 0, NULL))
+	    {
+		HIMAGELIST hDragItem = (HIMAGELIST)HEADER_CreateDragImage(hwnd, infoPtr->iMoveItem);
+		if (hDragItem != NULL)
+		{
+		    HEADER_ITEM *lpItem = &infoPtr->items[infoPtr->iMoveItem];
+		    TRACE("Starting item drag\n");
+		    ImageList_BeginDrag(hDragItem, 0, pt.x - lpItem->rect.left, 0);
+		    ImageList_DragShowNolock(TRUE);
+		    ImageList_Destroy(hDragItem);
+		    infoPtr->bDragging = TRUE;
+		}
+	    }
+	}
+	
+	if (infoPtr->bDragging)
+	{
+	    POINT drag;
+	    drag.x = pt.x;
+	    drag.y = 0;
+	    ClientToScreen(hwnd, &drag);
+	    ImageList_DragMove(drag.x, drag.y);
+	    HEADER_SetHotDivider(hwnd, TRUE, lParam);
+	}
+	
+	if (infoPtr->bPressed && !infoPtr->bDragging) {
             BOOL oldState = infoPtr->items[infoPtr->iMoveItem].bDown;
 	    if ((nItem == infoPtr->iMoveItem) && (flags == HHT_ONHEADER))
 		infoPtr->items[infoPtr->iMoveItem].bDown = TRUE;
@@ -1836,7 +1894,7 @@ HEADER_MouseMove (HWND hwnd, WPARAM wPar
 
     if (hotTrackEnabled) {
         TRACKMOUSEEVENT tme;
-        if (oldHotItem != infoPtr->iHotItem) {
+        if (oldHotItem != infoPtr->iHotItem && !infoPtr->bDragging) {
 	    hdc = GetDC (hwnd);
 	    if (oldHotItem != -1) HEADER_RefreshItem (hwnd, hdc, oldHotItem);
 	    if (infoPtr->iHotItem != -1) HEADER_RefreshItem (hwnd, hdc, infoPtr->iHotItem);




More information about the wine-cvs mailing list