Owen Rudge : comctl32: Implement highlighting (marquee) selection support in listview.
Alexandre Julliard
julliard at winehq.org
Thu Oct 1 09:48:19 CDT 2009
Module: wine
Branch: master
Commit: 69b76a18fb19bd4a6c83f4f05eb942513af970fd
URL: http://source.winehq.org/git/wine.git/?a=commit;h=69b76a18fb19bd4a6c83f4f05eb942513af970fd
Author: Owen Rudge <orudge at codeweavers.com>
Date: Wed Sep 30 16:41:23 2009 +0100
comctl32: Implement highlighting (marquee) selection support in listview.
---
dlls/comctl32/listview.c | 135 ++++++++++++++++++++++++++++++++++++++++-----
1 files changed, 120 insertions(+), 15 deletions(-)
diff --git a/dlls/comctl32/listview.c b/dlls/comctl32/listview.c
index 1c0f58b..eb2dbfb 100644
--- a/dlls/comctl32/listview.c
+++ b/dlls/comctl32/listview.c
@@ -7,6 +7,7 @@
* Copyright 2001 CodeWeavers Inc.
* Copyright 2002 Dimitrie O. Paun
* Copyright 2009 Nikolay Sivov
+ * Copyright 2009 Owen Rudge for CodeWeavers
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -98,7 +99,6 @@
* -- LVN_BEGINSCROLL, LVN_ENDSCROLL
* -- LVN_GETINFOTIP
* -- LVN_HOTTRACK
- * -- LVN_MARQUEEBEGIN
* -- LVN_SETDISPINFO
* -- NM_HOVER
* -- LVN_BEGINRDRAG
@@ -248,6 +248,8 @@ typedef struct tagLISTVIEW_INFO
BOOL bLButtonDown;
BOOL bRButtonDown;
BOOL bDragging;
+ BOOL bMarqueeSelect; /* marquee selection/highlight underway */
+ RECT marqueeRect;
POINT ptClickPos; /* point where the user clicked */
BOOL bNoItemMetrics; /* flags if item metrics are not yet computed */
INT nItemHeight;
@@ -3605,17 +3607,94 @@ static LRESULT LISTVIEW_MouseMove(LISTVIEW_INFO *infoPtr, WORD fwKeys, INT x, IN
WORD wDragWidth = GetSystemMetrics(SM_CXDRAG);
WORD wDragHeight= GetSystemMetrics(SM_CYDRAG);
- rect.left = infoPtr->ptClickPos.x - wDragWidth;
- rect.right = infoPtr->ptClickPos.x + wDragWidth;
- rect.top = infoPtr->ptClickPos.y - wDragHeight;
- rect.bottom = infoPtr->ptClickPos.y + wDragHeight;
-
tmp.x = x;
tmp.y = y;
lvHitTestInfo.pt = tmp;
LISTVIEW_HitTest(infoPtr, &lvHitTestInfo, TRUE, TRUE);
+ if (infoPtr->bMarqueeSelect)
+ {
+ LVITEMW item;
+ ITERATOR i;
+
+ if (x > infoPtr->ptClickPos.x)
+ {
+ rect.left = infoPtr->ptClickPos.x;
+ rect.right = x;
+ }
+ else
+ {
+ rect.left = x;
+ rect.right = infoPtr->ptClickPos.x;
+ }
+
+ if (y > infoPtr->ptClickPos.y)
+ {
+ rect.top = infoPtr->ptClickPos.y;
+ rect.bottom = y;
+ }
+ else
+ {
+ rect.top = y;
+ rect.bottom = infoPtr->ptClickPos.y;
+ }
+
+ /* Cancel out the old marquee rectangle and draw the new one */
+ LISTVIEW_InvalidateRect(infoPtr, &infoPtr->marqueeRect);
+
+ /* Invert the items in the old marquee rectangle */
+ iterator_frameditems(&i, infoPtr, &infoPtr->marqueeRect);
+
+ while (iterator_next(&i))
+ {
+ if (i.nItem > -1)
+ {
+ if (LISTVIEW_GetItemState(infoPtr, i.nItem, LVIS_SELECTED) == LVIS_SELECTED)
+ item.state = 0;
+ else
+ item.state = LVIS_SELECTED;
+
+ item.stateMask = LVIS_SELECTED;
+
+ LISTVIEW_SetItemState(infoPtr, i.nItem, &item);
+ }
+ }
+
+ iterator_destroy(&i);
+
+ CopyRect(&infoPtr->marqueeRect, &rect);
+
+ /* Iterate over the items within our marquee rectangle */
+ iterator_frameditems(&i, infoPtr, &rect);
+
+ while (iterator_next(&i))
+ {
+ if (i.nItem > -1)
+ {
+ /* If CTRL is pressed, invert. If not, always select the item. */
+ if ((fwKeys & MK_CONTROL) && (LISTVIEW_GetItemState(infoPtr, i.nItem, LVIS_SELECTED)))
+ item.state = 0;
+ else
+ item.state = LVIS_SELECTED;
+
+ item.stateMask = LVIS_SELECTED;
+
+ LISTVIEW_SetItemState(infoPtr, i.nItem, &item);
+ }
+ }
+
+ iterator_destroy(&i);
+
+ LISTVIEW_InvalidateRect(infoPtr, &rect);
+ return 0;
+ }
+
+ rect.left = infoPtr->ptClickPos.x - wDragWidth;
+ rect.right = infoPtr->ptClickPos.x + wDragWidth;
+ rect.top = infoPtr->ptClickPos.y - wDragHeight;
+ rect.bottom = infoPtr->ptClickPos.y + wDragHeight;
+
/* reset item marker */
if (infoPtr->nLButtonDownItem != lvHitTestInfo.iItem)
infoPtr->nLButtonDownItem = -1;
@@ -3640,17 +3719,31 @@ static LRESULT LISTVIEW_MouseMove(LISTVIEW_INFO *infoPtr, WORD fwKeys, INT x, IN
if (!infoPtr->bDragging)
{
- NMLISTVIEW nmlv;
-
lvHitTestInfo.pt = infoPtr->ptClickPos;
LISTVIEW_HitTest(infoPtr, &lvHitTestInfo, TRUE, TRUE);
- ZeroMemory(&nmlv, sizeof(nmlv));
- nmlv.iItem = lvHitTestInfo.iItem;
- nmlv.ptAction = infoPtr->ptClickPos;
+ /* If the click is outside the range of an item, begin a
+ highlight. If not, begin an item drag. */
+ if (lvHitTestInfo.iItem == -1)
+ {
+ NMHDR hdr;
+
+ /* If we're allowing multiple selections, send notification.
+ If return value is non-zero, cancel. */
+ if (!(infoPtr->dwStyle & LVS_SINGLESEL) && (notify_hdr(infoPtr, LVN_MARQUEEBEGIN, &hdr) == 0))
+ infoPtr->bMarqueeSelect = TRUE;
+ }
+ else
+ {
+ NMLISTVIEW nmlv;
- notify_listview(infoPtr, LVN_BEGINDRAG, &nmlv);
- infoPtr->bDragging = TRUE;
+ ZeroMemory(&nmlv, sizeof(nmlv));
+ nmlv.iItem = lvHitTestInfo.iItem;
+ nmlv.ptAction = infoPtr->ptClickPos;
+
+ notify_listview(infoPtr, LVN_BEGINDRAG, &nmlv);
+ infoPtr->bDragging = TRUE;
+ }
}
return 0;
@@ -4643,6 +4736,10 @@ enddraw:
if ((infoPtr->uView == LV_VIEW_DETAILS) && infoPtr->dwLvExStyle & LVS_EX_GRIDLINES)
LISTVIEW_RefreshReportGrid(infoPtr, hdc);
+ /* Draw marquee rectangle if appropriate */
+ if (infoPtr->bMarqueeSelect)
+ DrawFocusRect(hdc, &infoPtr->marqueeRect);
+
if (cdmode & CDRF_NOTIFYPOSTPAINT)
notify_postpaint(infoPtr, &nmlvcd);
@@ -9312,6 +9409,7 @@ static LRESULT LISTVIEW_LButtonDown(LISTVIEW_INFO *infoPtr, WORD wKey, INT x, IN
infoPtr->bLButtonDown = TRUE;
infoPtr->ptClickPos = pt;
infoPtr->bDragging = FALSE;
+ infoPtr->bMarqueeSelect = FALSE;
lvHitTestInfo.pt.x = x;
lvHitTestInfo.pt.y = y;
@@ -9433,9 +9531,16 @@ static LRESULT LISTVIEW_LButtonUp(LISTVIEW_INFO *infoPtr, WORD wKey, INT x, INT
LISTVIEW_SetSelection(infoPtr, infoPtr->nLButtonDownItem);
infoPtr->nLButtonDownItem = -1;
- if (infoPtr->bDragging)
+ if (infoPtr->bDragging || infoPtr->bMarqueeSelect)
{
+ /* Remove the marquee rectangle */
+ if (infoPtr->bMarqueeSelect)
+ LISTVIEW_InvalidateRect(infoPtr, &infoPtr->marqueeRect);
+
+ SetRect(&infoPtr->marqueeRect, 0, 0, 0, 0);
+
infoPtr->bDragging = FALSE;
+ infoPtr->bMarqueeSelect = FALSE;
return 0;
}
More information about the wine-cvs
mailing list