listview: dnd support

Huw D M Davies h.davies1 at physics.ox.ac.uk
Mon Nov 3 16:54:35 CST 2003


	Ulrich Czekalla <ulrich at codeweavers.com>
	Huw Davies <huw at codeweavers.com>
	
	Add drag and drop support to listview
	
Index: dlls/comctl32/listview.c
===================================================================
RCS file: /home/wine/wine/dlls/comctl32/listview.c,v
retrieving revision 1.369
diff -u -r1.369 listview.c
--- dlls/comctl32/listview.c	7 Oct 2003 03:30:47 -0000	1.369
+++ dlls/comctl32/listview.c	3 Nov 2003 22:52:55 -0000
@@ -95,7 +95,7 @@
  *   -- LVS_EX_UNDERLINEHOT
  *   
  * Notifications:
- *   -- LVN_BEGINDRAG, LVN_BEGINRDRAG
+ *   -- LVN_BEGINRDRAG
  *   -- LVN_BEGINSCROLL, LVN_ENDSCROLL
  *   -- LVN_GETINFOTIP
  *   -- LVN_HOTTRACK
@@ -107,7 +107,6 @@
  *
  * Messages:
  *   -- LVM_CANCELEDITLABEL
- *   -- LVM_CREATEDRAGIMAGE
  *   -- LVM_ENABLEGROUPVIEW
  *   -- LVM_GETBKIMAGE, LVM_SETBKIMAGE
  *   -- LVM_GETGROUPINFO, LVM_SETGROUPINFO
@@ -4000,7 +3999,70 @@
   return dwViewRect;
 }
 
-/* << LISTVIEW_CreateDragImage >> */
+
+/***
+ * DESCRIPTION:
+ * Create a drag image list for the specified item.
+ *
+ * PARAMETER(S):
+ * [I] infoPtr : valid pointer to the listview structure
+ * [I] iItem   : index of item
+ * [O] lppt    : Upperr-left corner of the image
+ *
+ * RETURN:
+ * Returns a handle to the image list if successful, NULL otherwise.
+ */
+static HIMAGELIST LISTVIEW_CreateDragImage(LISTVIEW_INFO *infoPtr, INT iItem, LPPOINT lppt)
+{
+    RECT rcItem;
+    SIZE size;
+    POINT pos;
+    HDC hdc, hdcOrig;
+    HBITMAP hbmp, hOldbmp;
+    HIMAGELIST dragList = 0;
+    TRACE("iItem=%d Count=%d \n", iItem, infoPtr->nItemCount);
+
+    if (iItem < 0 || iItem >= infoPtr->nItemCount)
+        return 0;
+
+    rcItem.left = LVIR_BOUNDS;
+    if (!LISTVIEW_GetItemRect(infoPtr, iItem, &rcItem))
+        return 0;
+
+    lppt->x = rcItem.left;
+    lppt->y = rcItem.top;
+
+    size.cx = rcItem.right - rcItem.left;
+    size.cy = rcItem.bottom - rcItem.top;
+
+    hdcOrig = GetDC(infoPtr->hwndSelf);
+    hdc = CreateCompatibleDC(hdcOrig);
+    hbmp = CreateCompatibleBitmap(hdcOrig, size.cx, size.cy);
+    hOldbmp = SelectObject(hdc, hbmp);
+
+    rcItem.left = rcItem.top = 0;
+    rcItem.right = size.cx;
+    rcItem.bottom = size.cy;
+    FillRect(hdc, &rcItem, infoPtr->hBkBrush);
+    
+    pos.x = pos.y = 0;
+    if (LISTVIEW_DrawItem(infoPtr, hdc, iItem, 0, pos, infoPtr->cditemmode))
+    {
+        dragList = ImageList_Create(size.cx, size.cy, ILC_COLOR, 10, 10);
+        SelectObject(hdc, hOldbmp);
+        ImageList_Add(dragList, hbmp, 0);
+    }
+    else
+        SelectObject(hdc, hOldbmp);
+
+    DeleteObject(hbmp);
+    DeleteDC(hdc);
+    ReleaseDC(infoPtr->hwndSelf, hdcOrig);
+
+    TRACE("ret=%p\n", dragList);
+
+    return dragList;
+}
 
 
 /***
@@ -7675,6 +7737,68 @@
     return 0;
 }
 
+
+/***
+ * DESCRIPTION:
+ * Track mouse/dragging
+ *
+ * PARAMETER(S):
+ * [I] infoPtr : valid pointer to the listview structure
+ * [I] pt : mouse coordinate
+ *
+ * RETURN:
+ * Zero
+ */
+static LRESULT LISTVIEW_TrackMouse(LISTVIEW_INFO *infoPtr, POINT pt)
+{
+    INT cxDrag = GetSystemMetrics(SM_CXDRAG);
+    INT cyDrag = GetSystemMetrics(SM_CYDRAG);
+    RECT r;
+    MSG msg;
+
+    TRACE("\n");
+
+    r.top = pt.y - cyDrag;
+    r.left = pt.x - cxDrag;
+    r.bottom = pt.y + cyDrag;
+    r.right = pt.x + cxDrag;
+
+    SetCapture(infoPtr->hwndSelf);
+
+    while (1)
+    {
+	if (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE | PM_NOYIELD))
+	{
+	    if (msg.message == WM_MOUSEMOVE)
+	    {
+		pt.x = (short)LOWORD(msg.lParam);
+		pt.y = (short)HIWORD(msg.lParam);
+		if (PtInRect(&r, pt))
+		    continue;
+		else
+		{
+		    ReleaseCapture();
+		    return 1;
+		}
+	    }
+	    else if (msg.message >= WM_LBUTTONDOWN &&
+		     msg.message <= WM_RBUTTONDBLCLK)
+	    {
+		break;
+	    }
+
+	    DispatchMessageA(&msg);
+	}
+
+	if (GetCapture() != infoPtr->hwndSelf)
+	    return 0;
+    }
+
+    ReleaseCapture();
+    return 0;
+}
+
+
 /***
  * DESCRIPTION:
  * Processes double click messages (left mouse button).
@@ -7746,6 +7870,20 @@
   infoPtr->nEditLabelItem = -1;
   if ((nItem >= 0) && (nItem < infoPtr->nItemCount))
   {
+    if (LISTVIEW_TrackMouse(infoPtr, lvHitTestInfo.pt))
+    {
+        NMLISTVIEW nmlv;
+
+	ZeroMemory(&nmlv, sizeof(nmlv));
+        nmlv.iItem = nItem;
+        nmlv.ptAction.x = lvHitTestInfo.pt.x;
+        nmlv.ptAction.y = lvHitTestInfo.pt.y;
+
+        notify_listview(infoPtr, LVN_BEGINDRAG, &nmlv);
+
+        return 0;
+    }
+
     if (infoPtr->dwStyle & LVS_SINGLESEL)
     {
       if (LISTVIEW_GetItemState(infoPtr, nItem, LVIS_SELECTED))
@@ -8499,7 +8637,8 @@
 
 /* case LVM_CANCELEDITLABEL: */
 
-/* case LVM_CREATEDRAGIMAGE: */
+  case LVM_CREATEDRAGIMAGE:
+    return (LRESULT)LISTVIEW_CreateDragImage(infoPtr, (INT)wParam, (LPPOINT)lParam);
 
   case LVM_DELETEALLITEMS:
     return LISTVIEW_DeleteAllItems(infoPtr);



More information about the wine-patches mailing list