4 * Copyright 1998 Eric Kohl
5 * Copyright 1999 Luc Tourangeau
8 * Listview control implementation.
12 * 1. Multiple selections in icon or small icon display modes DO NOT
13 * behave like the Microsoft control.
14 * 2. No horizontal scrolling when header is larger than the client area.
15 * 3. Implement LVM_FINDITEM for key selections.
16 * 4. Drawing optimizations.
19 * LISTVIEW_Notify : most notifications from children (editbox and header)
22 * LISTVIEW_SortItems : empty stub
23 * LISTVIEW_SetItemCount : empty stub
26 * LISTVIEW_SetItem32W : no unicode support
27 * LISTVIEW_InsertItem32W : no unicode support
28 * LISTVIEW_InsertColumn32W : no unicode support
29 * LISTVIEW_GetColumnW : no unicode support
31 * Advanced functionality:
32 * LISTVIEW_GetNumberOfWorkAreas : not implemented
33 * LISTVIEW_GetNextItem : empty stub
34 * LISTVIEW_GetHotCursor : not implemented
35 * LISTVIEW_GetHotItem : not implemented
36 * LISTVIEW_GetHoverTime : not implemented
37 * LISTVIEW_GetISearchString : not implemented
38 * LISTVIEW_GetBkImage : not implemented
39 * LISTVIEW_EditLabel : REPORT (need to implement a timer)
40 * LISTVIEW_GetColumnOrderArray : not implemented
41 * LISTVIEW_Arrange : empty stub
42 * LISTVIEW_FindItem : empty stub
43 * LISTVIEW_ApproximateViewRect : incomplete
44 * LISTVIEW_Scroll : not implemented
45 * LISTVIEW_KeyDown : page up and page down + redo small icon and icon
46 * LISTVIEW_RedrawItems : empty stub
47 * LISTVIEW_Update : not completed
56 DEFAULT_DEBUG_CHANNEL(listview
)
62 /* maximum size of a label */
63 #define DISP_TEXT_SIZE 128
65 /* padding for items in list and small icon display modes */
66 #define WIDTH_PADDING 12
68 /* padding for items in list, report and small icon display modes */
69 #define HEIGHT_PADDING 1
71 /* offset of items in report display mode */
72 #define REPORT_MARGINX 2
74 /* padding for icon in large icon display mode */
75 #define ICON_TOP_PADDING 2
76 #define ICON_BOTTOM_PADDING 2
78 /* padding for label in large icon display mode */
79 #define LABEL_VERT_OFFSET 2
81 /* default label width for items in list and small icon display modes */
82 #define DEFAULT_LABEL_WIDTH 40
84 /* default column width for items in list display mode */
85 #define DEFAULT_COLUMN_WIDTH 96
91 /* retrieve the number of items in the listview */
92 #define GETITEMCOUNT(infoPtr) ((infoPtr)->hdpaItems->nItemCount)
93 #define ListView_LVNotify(hwnd,lCtrlId,plvnm) \
94 (BOOL)SendMessageA((hwnd),WM_NOTIFY,(WPARAM)(INT)lCtrlId,(LPARAM)(LPNMLISTVIEW)(plvnm))
95 #define ListView_Notify(hwnd,lCtrlId,pnmh) \
96 (BOOL)SendMessageA((hwnd),WM_NOTIFY,(WPARAM)(INT)lCtrlId,(LPARAM)(LPNMHDR)(pnmh))
99 * forward declarations
102 static VOID
LISTVIEW_AlignLeft(HWND
);
103 static VOID
LISTVIEW_AlignTop(HWND
);
104 static VOID
LISTVIEW_AddGroupSelection(HWND
, INT
);
105 static VOID
LISTVIEW_AddSelection(HWND
, INT
);
106 static BOOL
LISTVIEW_AddSubItem(HWND
, LPLVITEMA
);
107 static INT
LISTVIEW_FindInsertPosition(HDPA
, INT
);
108 static VOID
LISTVIEW_GetItemDispInfo(HWND
, INT
, LISTVIEW_ITEM
*lpItem
, INT
*,
109 UINT
*, CHAR
**, INT
);
110 static INT
LISTVIEW_GetItemHeight(HWND
, LONG
);
111 static BOOL
LISTVIEW_GetItemPosition(HWND
, INT
, LPPOINT
);
112 static LRESULT
LISTVIEW_GetItemRect(HWND
, INT
, LPRECT
);
113 static INT
LISTVIEW_GetItemWidth(HWND
, LONG
);
114 static INT
LISTVIEW_GetLabelWidth(HWND
, INT
);
115 static LRESULT
LISTVIEW_GetOrigin(HWND
, LPPOINT
);
116 static LISTVIEW_SUBITEM
* LISTVIEW_GetSubItem(HDPA
, INT
);
117 static VOID
LISTVIEW_GetSubItemDispInfo(HWND hwnd
, INT
, LPARAM
,
118 LISTVIEW_SUBITEM
*, INT
, INT
*,
120 static LRESULT
LISTVIEW_GetViewRect(HWND
, LPRECT
);
121 static BOOL
LISTVIEW_InitItem(HWND
, LISTVIEW_ITEM
*, LPLVITEMA
);
122 static BOOL
LISTVIEW_InitSubItem(HWND
, LISTVIEW_SUBITEM
*, LPLVITEMA
);
123 static LRESULT
LISTVIEW_MouseSelection(HWND
, INT
, INT
);
124 static BOOL
LISTVIEW_RemoveColumn(HDPA
, INT
);
125 static VOID
LISTVIEW_RemoveSelections(HWND
, INT
, INT
);
126 static BOOL
LISTVIEW_RemoveSubItem(HDPA
, INT
);
127 static BOOL
LISTVIEW_ScrollView(HWND
, INT
, INT
);
128 static VOID
LISTVIEW_SetGroupSelection(HWND
, INT
);
129 static BOOL
LISTVIEW_SetItem(HWND
, LPLVITEMA
);
130 static VOID
LISTVIEW_SetItemFocus(HWND
, INT
);
131 static BOOL
LISTVIEW_SetItemPosition(HWND
, INT
, INT
, INT
);
132 static VOID
LISTVIEW_SetScroll(HWND
, LONG
);
133 static VOID
LISTVIEW_SetSelection(HWND
, INT
);
134 static VOID
LISTVIEW_SetSize(HWND
, LONG
, LONG
, LONG
);
135 static BOOL
LISTVIEW_SetSubItem(HWND
, LPLVITEMA
);
136 static VOID
LISTVIEW_SetViewInfo(HWND
, LONG
);
137 static LRESULT
LISTVIEW_SetViewRect(HWND
, LPRECT
);
138 static BOOL
LISTVIEW_ToggleSelection(HWND
, INT
);
139 static VOID
LISTVIEW_UnsupportedStyles(LONG lStyle
);
143 * Scrolls the content of the listview.
146 * [I] HWND : window handle
147 * [I] INT : number of horizontal scroll positions
148 * (relative to the current scroll postioon)
149 * [I] INT : number of vertical scroll positions
150 * (relative to the current scroll postioon)
156 static BOOL
LISTVIEW_ScrollView(HWND hwnd
, INT nHScroll
, INT nVScroll
)
158 LISTVIEW_INFO
*infoPtr
= (LISTVIEW_INFO
*)GetWindowLongA(hwnd
, 0);
159 LONG lStyle
= GetWindowLongA(hwnd
, GWL_STYLE
);
160 INT nListWidth
= infoPtr
->rcList
.right
- infoPtr
->rcList
.left
;
161 INT nListHeight
= infoPtr
->rcList
.bottom
- infoPtr
->rcList
.top
;
166 BOOL bResult
= FALSE
;
168 if (((lStyle
& WS_HSCROLL
) != 0) && (nHScroll
!= 0))
170 switch (LVS_TYPEMASK
& lStyle
)
173 nHScrollInc
= nHScroll
* infoPtr
->nItemWidth
;
177 /* TO DO : not implemented at this point. I experiences some
178 problems when performing child window scrolling. */
183 nHScrollInc
= nHScroll
* max(nListWidth
, nListWidth
/ 10);
187 nHScrollPos
= GetScrollPos(hwnd
, SB_HORZ
) + nHScroll
;
190 if (((lStyle
& WS_VSCROLL
) != 0) & (nVScroll
!= 0))
192 switch (LVS_TYPEMASK
& lStyle
)
195 nVScrollInc
= nVScroll
* infoPtr
->nItemHeight
;
196 nVScrollPos
= GetScrollPos(hwnd
, SB_VERT
) + nVScroll
;
201 nVScrollInc
= nVScroll
* max(nListHeight
, nListHeight
/ 10);
202 nVScrollPos
= GetScrollPos(hwnd
, SB_VERT
) + nVScroll
;
207 /* perform scroll operation & set new scroll position */
208 if ((nHScrollInc
!= 0) || (nVScrollInc
!= 0))
211 HDC hdc
= GetDC(hwnd
);
212 ScrollDC(hdc
, -nHScrollInc
, -nVScrollInc
, &infoPtr
->rcList
, NULL
,
214 InvalidateRect(hwnd
, &rc
, TRUE
);
215 SetScrollPos(hwnd
, SB_HORZ
, nHScrollPos
, TRUE
);
216 SetScrollPos(hwnd
, SB_VERT
, nVScrollPos
, TRUE
);
217 ReleaseDC(hwnd
, hdc
);
226 * Prints a message for unsupported window styles.
227 * A kind of TODO list for window styles.
230 * [I] LONG : window style
235 static VOID
LISTVIEW_UnsupportedStyles(LONG lStyle
)
237 if ((LVS_TYPEMASK
& lStyle
) == LVS_EDITLABELS
)
239 FIXME( listview
, " LVS_EDITLABELS\n");
242 if ((LVS_TYPEMASK
& lStyle
) == LVS_NOCOLUMNHEADER
)
244 FIXME( listview
, " LVS_SORTDESCENDING\n");
247 if ((LVS_TYPEMASK
& lStyle
) == LVS_NOLABELWRAP
)
249 FIXME( listview
, " LVS_NOLABELWRAP\n");
252 if ((LVS_TYPEMASK
& lStyle
) == LVS_NOSCROLL
)
254 FIXME( listview
, " LVS_NOSCROLL\n");
257 if ((LVS_TYPEMASK
& lStyle
) == LVS_NOSORTHEADER
)
259 FIXME( listview
, " LVS_NOSORTHEADER\n");
262 if ((LVS_TYPEMASK
& lStyle
) == LVS_OWNERDRAWFIXED
)
264 FIXME( listview
, " LVS_OWNERDRAWFIXED\n");
267 if ((LVS_TYPEMASK
& lStyle
) == LVS_SHAREIMAGELISTS
)
269 FIXME( listview
, " LVS_SHAREIMAGELISTS\n");
272 if ((LVS_TYPEMASK
& lStyle
) == LVS_SHOWSELALWAYS
)
274 FIXME( listview
, " LVS_SHOWSELALWAYS\n");
277 if ((LVS_TYPEMASK
& lStyle
) == LVS_SINGLESEL
)
279 FIXME( listview
, " LVS_SINGLESEL\n");
282 if ((LVS_TYPEMASK
& lStyle
) == LVS_SORTASCENDING
)
284 FIXME( listview
, " LVS_SORTASCENDING\n");
287 if ((LVS_TYPEMASK
& lStyle
) == LVS_SORTDESCENDING
)
289 FIXME( listview
, " LVS_SORTDESCENDING\n");
295 * Aligns the items with the top edge of the window.
298 * [I] HWND : window handle
303 static VOID
LISTVIEW_AlignTop(HWND hwnd
)
305 LISTVIEW_INFO
*infoPtr
= (LISTVIEW_INFO
*)GetWindowLongA(hwnd
, 0);
306 LONG lStyle
= GetWindowLongA(hwnd
, GWL_STYLE
);
307 INT nListWidth
= infoPtr
->rcList
.right
- infoPtr
->rcList
.left
;
312 switch (LVS_TYPEMASK
& lStyle
)
316 ZeroMemory(&ptItem
, sizeof(POINT
));
317 ZeroMemory(&rcView
, sizeof(RECT
));
318 if (nListWidth
> infoPtr
->nItemWidth
)
320 for (i
= 0; i
< GETITEMCOUNT(infoPtr
); i
++)
322 if (ptItem
.x
+ infoPtr
->nItemWidth
> nListWidth
)
325 ptItem
.y
+= infoPtr
->nItemHeight
;
328 LISTVIEW_SetItemPosition(hwnd
, i
, ptItem
.x
, ptItem
.y
);
329 ptItem
.x
+= infoPtr
->nItemWidth
;
330 rcView
.right
= max(rcView
.right
, ptItem
.x
);
335 for (i
= 0; i
< GETITEMCOUNT(infoPtr
); i
++)
337 LISTVIEW_SetItemPosition(hwnd
, i
, ptItem
.x
, ptItem
.y
);
338 ptItem
.x
+= infoPtr
->nItemWidth
;
340 rcView
.right
= ptItem
.x
;
341 rcView
.bottom
= infoPtr
->nItemHeight
;
344 rcView
.bottom
= ptItem
.y
+ infoPtr
->nItemHeight
;
345 LISTVIEW_SetViewRect(hwnd
, &rcView
);
351 * Aligns the items with the left edge of the window.
354 * [I] HWND : window handle
359 static VOID
LISTVIEW_AlignLeft(HWND hwnd
)
361 LISTVIEW_INFO
*infoPtr
= (LISTVIEW_INFO
*)GetWindowLongA(hwnd
, 0);
362 LONG lStyle
= GetWindowLongA(hwnd
, GWL_STYLE
);
363 INT nListHeight
= infoPtr
->rcList
.bottom
- infoPtr
->rcList
.top
;
368 switch (LVS_TYPEMASK
& lStyle
)
372 ZeroMemory(&ptItem
, sizeof(POINT
));
373 ZeroMemory(&rcView
, sizeof(RECT
));
374 if (nListHeight
> infoPtr
->nItemHeight
)
376 for (i
= 0; i
< GETITEMCOUNT(infoPtr
); i
++)
378 if (ptItem
.y
+ infoPtr
->nItemHeight
> nListHeight
)
381 ptItem
.x
+= infoPtr
->nItemWidth
;
384 LISTVIEW_SetItemPosition(hwnd
, i
, ptItem
.x
, ptItem
.y
);
385 ptItem
.y
+= infoPtr
->nItemHeight
;
386 rcView
.bottom
= max(rcView
.bottom
, ptItem
.y
);
391 for (i
= 0; i
< GETITEMCOUNT(infoPtr
); i
++)
393 LISTVIEW_SetItemPosition(hwnd
, i
, ptItem
.x
, ptItem
.y
);
394 ptItem
.y
+= infoPtr
->nItemHeight
;
396 rcView
.bottom
= ptItem
.y
;
397 rcView
.right
= infoPtr
->nItemWidth
;
400 rcView
.right
= ptItem
.x
+ infoPtr
->nItemWidth
;
401 LISTVIEW_SetViewRect(hwnd
, &rcView
);
408 * Retrieves display information.
411 * [I] HWND : window handle
412 * [I] INT : item index
413 * [I] LISTVIEW_ITEM* : listview control item
414 * [O] INT : image index
415 * [O] UINT : state value
416 * [O] CHAR** : string
417 * [I] INT : size of string
422 static VOID
LISTVIEW_GetItemDispInfo(HWND hwnd
, INT nItem
,
423 LISTVIEW_ITEM
*lpItem
, INT
*pnDispImage
,
424 UINT
*puState
, CHAR
**ppszDispText
,
427 LISTVIEW_INFO
*infoPtr
= (LISTVIEW_INFO
*)GetWindowLongA(hwnd
, 0);
428 LONG lCtrlId
= GetWindowLongA(hwnd
, GWL_ID
);
429 NMLVDISPINFOA dispInfo
;
430 ZeroMemory(&dispInfo
, sizeof(NMLVDISPINFOA
));
432 if ((pnDispImage
!= NULL
) && (lpItem
->iImage
== I_IMAGECALLBACK
))
434 dispInfo
.item
.mask
|= LVIF_IMAGE
;
437 if ((ppszDispText
!= NULL
) && (lpItem
->pszText
== LPSTR_TEXTCALLBACKA
))
439 ZeroMemory(*ppszDispText
, sizeof(CHAR
)*nDispTextSize
);
440 dispInfo
.item
.mask
|= LVIF_TEXT
;
441 dispInfo
.item
.pszText
= *ppszDispText
;
442 dispInfo
.item
.cchTextMax
= nDispTextSize
;
445 if ((puState
!= NULL
) && (infoPtr
->uCallbackMask
!= 0))
447 dispInfo
.item
.mask
|= LVIF_STATE
;
448 dispInfo
.item
.stateMask
= infoPtr
->uCallbackMask
;
451 if (dispInfo
.item
.mask
!= 0)
453 dispInfo
.hdr
.hwndFrom
= hwnd
;
454 dispInfo
.hdr
.idFrom
= lCtrlId
;
455 dispInfo
.hdr
.code
= LVN_GETDISPINFOA
;
456 dispInfo
.item
.iItem
= nItem
;
457 dispInfo
.item
.iSubItem
= 0;
458 dispInfo
.item
.lParam
= lpItem
->lParam
;
459 ListView_Notify(GetParent(hwnd
), lCtrlId
, &dispInfo
);
462 if (pnDispImage
!= NULL
)
464 if (dispInfo
.item
.mask
& LVIF_IMAGE
)
466 *pnDispImage
= dispInfo
.item
.iImage
;
470 *pnDispImage
= lpItem
->iImage
;
474 if (ppszDispText
!= NULL
)
476 if (dispInfo
.item
.mask
& LVIF_TEXT
)
478 if (dispInfo
.item
.mask
& LVIF_DI_SETITEM
)
480 Str_SetPtrA(&lpItem
->pszText
, dispInfo
.item
.pszText
);
482 *ppszDispText
= dispInfo
.item
.pszText
;
486 *ppszDispText
= lpItem
->pszText
;
492 if (dispInfo
.item
.mask
& LVIF_STATE
)
494 *puState
= lpItem
->state
;
495 *puState
&= ~dispInfo
.item
.stateMask
;
496 *puState
|= (dispInfo
.item
.state
& dispInfo
.item
.stateMask
);
500 *puState
= lpItem
->state
;
507 * Retrieves subitem display information.
510 * [I] HWND : window handle
511 * [I] INT : item index
512 * [I] LONG : LPARAM of item
513 * [I] LISTVIEW_SUBITEM* : listview control subitem
514 * [I] INT : subitem position/order
515 * [O] INT : image index
516 * [O] UINT : state value
517 * [O] CHAR** : display string
518 * [I] INT : size of string
523 static VOID
LISTVIEW_GetSubItemDispInfo(HWND hwnd
, INT nItem
, LPARAM lParam
,
524 LISTVIEW_SUBITEM
*lpSubItem
,
525 INT nSubItemPos
, INT
*pnDispImage
,
526 CHAR
**ppszDispText
, INT nDispTextSize
)
528 LONG lCtrlId
= GetWindowLongA(hwnd
, GWL_ID
);
529 NMLVDISPINFOA dispInfo
;
530 ZeroMemory(&dispInfo
, sizeof(NMLVDISPINFOA
));
532 if (lpSubItem
== NULL
)
534 ZeroMemory(*ppszDispText
, sizeof(CHAR
)*nDispTextSize
);
535 dispInfo
.item
.mask
|= LVIF_TEXT
;
536 dispInfo
.item
.pszText
= *ppszDispText
;
537 dispInfo
.item
.cchTextMax
= nDispTextSize
;
538 dispInfo
.hdr
.hwndFrom
= hwnd
;
539 dispInfo
.hdr
.idFrom
= lCtrlId
;
540 dispInfo
.hdr
.code
= LVN_GETDISPINFOA
;
541 dispInfo
.item
.iItem
= nItem
;
542 dispInfo
.item
.iSubItem
= nSubItemPos
;
543 dispInfo
.item
.lParam
= lParam
;
544 ListView_Notify(GetParent(hwnd
), lCtrlId
, &dispInfo
);
545 if (dispInfo
.item
.mask
& LVIF_DI_SETITEM
)
547 Str_SetPtrA(&lpSubItem
->pszText
, dispInfo
.item
.pszText
);
549 *ppszDispText
= dispInfo
.item
.pszText
;
553 if ((pnDispImage
!= NULL
) && (lpSubItem
->iImage
== I_IMAGECALLBACK
))
555 dispInfo
.item
.mask
|= LVIF_IMAGE
;
558 if ((ppszDispText
!= NULL
) && (lpSubItem
->pszText
== LPSTR_TEXTCALLBACKA
))
560 ZeroMemory(*ppszDispText
, sizeof(CHAR
)*nDispTextSize
);
561 dispInfo
.item
.mask
|= LVIF_TEXT
;
562 dispInfo
.item
.pszText
= *ppszDispText
;
563 dispInfo
.item
.cchTextMax
= nDispTextSize
;
566 if (dispInfo
.item
.mask
!= 0)
568 dispInfo
.hdr
.hwndFrom
= hwnd
;
569 dispInfo
.hdr
.idFrom
= lCtrlId
;
570 dispInfo
.hdr
.code
= LVN_GETDISPINFOA
;
571 dispInfo
.item
.iItem
= nItem
;
572 dispInfo
.item
.iSubItem
= lpSubItem
->iSubItem
;
573 dispInfo
.item
.lParam
= lParam
;
574 ListView_Notify(GetParent(hwnd
), lCtrlId
, &dispInfo
);
577 if (pnDispImage
!= NULL
)
579 if (dispInfo
.item
.mask
& LVIF_IMAGE
)
581 *pnDispImage
= dispInfo
.item
.iImage
;
585 *pnDispImage
= lpSubItem
->iImage
;
589 if (ppszDispText
!= NULL
)
591 if (dispInfo
.item
.mask
& LVIF_TEXT
)
593 if (dispInfo
.item
.mask
& LVIF_DI_SETITEM
)
595 Str_SetPtrA(&lpSubItem
->pszText
, dispInfo
.item
.pszText
);
597 *ppszDispText
= dispInfo
.item
.pszText
;
601 *ppszDispText
= lpSubItem
->pszText
;
609 * Calculates the width of an item.
612 * [I] HWND : window handle
613 * [I] LONG : window style
616 * Returns item width.
618 static INT
LISTVIEW_GetItemWidth(HWND hwnd
, LONG lStyle
)
620 LISTVIEW_INFO
*infoPtr
= (LISTVIEW_INFO
*)GetWindowLongA(hwnd
, 0);
621 INT nHeaderItemCount
;
627 TRACE(listview
, "(hwnd=%x,lStyle=%lx)\n", hwnd
, lStyle
);
629 switch (LVS_TYPEMASK
& lStyle
)
632 nItemWidth
= infoPtr
->iconSpacing
.cx
;
636 /* calculate width of header */
637 nHeaderItemCount
= Header_GetItemCount(infoPtr
->hwndHeader
);
638 for (i
= 0; i
< nHeaderItemCount
; i
++)
640 if (Header_GetItemRect(infoPtr
->hwndHeader
, i
, &rcHeaderItem
) != 0)
642 nItemWidth
+= (rcHeaderItem
.right
- rcHeaderItem
.left
);
649 for (i
= 0; i
< GETITEMCOUNT(infoPtr
); i
++)
651 nLabelWidth
= LISTVIEW_GetLabelWidth(hwnd
, i
);
652 nItemWidth
= max(nItemWidth
, nLabelWidth
);
655 /* default label size */
656 if (GETITEMCOUNT(infoPtr
) == 0)
658 nItemWidth
= DEFAULT_COLUMN_WIDTH
;
664 nItemWidth
= DEFAULT_LABEL_WIDTH
;
669 nItemWidth
+= WIDTH_PADDING
;
671 if (infoPtr
->himlSmall
!= NULL
)
673 nItemWidth
+= infoPtr
->iconSize
.cx
;
676 if (infoPtr
->himlState
!= NULL
)
678 nItemWidth
+= infoPtr
->iconSize
.cx
;
691 * Calculates the height of an item.
694 * [I] HWND : window handle
695 * [I] LONG : window style
698 * Returns item width.
700 static INT
LISTVIEW_GetItemHeight(HWND hwnd
, LONG lStyle
)
702 LISTVIEW_INFO
*infoPtr
= (LISTVIEW_INFO
*)GetWindowLongA(hwnd
, 0);
708 switch (LVS_TYPEMASK
& lStyle
)
711 nItemHeight
= infoPtr
->iconSpacing
.cy
;
718 hOldFont
= SelectObject(hdc
, infoPtr
->hFont
);
719 GetTextMetricsA(hdc
, &tm
);
720 nItemHeight
= max(tm
.tmHeight
, infoPtr
->iconSize
.cy
) + HEIGHT_PADDING
;
721 SelectObject(hdc
, hOldFont
);
722 ReleaseDC(hwnd
, hdc
);
731 * Sets diplay information (needed for drawing operations).
734 * [I] HWND : window handle
739 static VOID
LISTVIEW_SetViewInfo(HWND hwnd
, LONG lStyle
)
741 LISTVIEW_INFO
*infoPtr
= (LISTVIEW_INFO
*)GetWindowLongA(hwnd
, 0);
742 INT nListHeight
= infoPtr
->rcList
.bottom
- infoPtr
->rcList
.top
;
743 INT nListWidth
= infoPtr
->rcList
.right
- infoPtr
->rcList
.left
;
745 switch (LVS_TYPEMASK
& lStyle
)
748 /* get number of fully visible items per column */
749 infoPtr
->nCountPerColumn
= max(1, nListHeight
/ infoPtr
->nItemHeight
);
753 /* get number of fully visible items per column */
754 infoPtr
->nCountPerColumn
= max(1, nListHeight
/ infoPtr
->nItemHeight
);
756 /* get number of fully visible items per row */
757 infoPtr
->nCountPerRow
= max(1, nListWidth
/ infoPtr
->nItemWidth
);
764 * Adds a block of selections.
767 * [I] HWND : window handle
768 * [I] INT : item index
773 static VOID
LISTVIEW_AddGroupSelection(HWND hwnd
, INT nItem
)
775 LISTVIEW_INFO
*infoPtr
= (LISTVIEW_INFO
*)GetWindowLongA(hwnd
, 0);
776 INT nFirst
= min(infoPtr
->nSelectionMark
, nItem
);
777 INT nLast
= max(infoPtr
->nSelectionMark
, nItem
);
781 lvItem
.state
= LVIS_SELECTED
;
782 lvItem
.stateMask
= LVIS_SELECTED
;
784 for (i
= nFirst
; i
<= nLast
; i
++)
786 ListView_SetItemState(hwnd
, i
, &lvItem
);
789 LISTVIEW_SetItemFocus(hwnd
, nItem
);
790 infoPtr
->nSelectionMark
= nItem
;
795 * Adds a single selection.
798 * [I] HWND : window handle
799 * [I] INT : item index
804 static VOID
LISTVIEW_AddSelection(HWND hwnd
, INT nItem
)
806 LISTVIEW_INFO
*infoPtr
= (LISTVIEW_INFO
*)GetWindowLongA(hwnd
, 0);
809 lvItem
.state
= LVIS_SELECTED
;
810 lvItem
.stateMask
= LVIS_SELECTED
;
812 ListView_SetItemState(hwnd
, nItem
, &lvItem
);
814 LISTVIEW_SetItemFocus(hwnd
, nItem
);
815 infoPtr
->nSelectionMark
= nItem
;
820 * Selects or unselects an item.
823 * [I] HWND : window handle
824 * [I] INT : item index
830 static BOOL
LISTVIEW_ToggleSelection(HWND hwnd
, INT nItem
)
832 LISTVIEW_INFO
*infoPtr
= (LISTVIEW_INFO
*)GetWindowLongA(hwnd
, 0);
836 lvItem
.stateMask
= LVIS_SELECTED
;
838 if (ListView_GetItemState(hwnd
, nItem
, LVIS_SELECTED
) & LVIS_SELECTED
)
841 ListView_SetItemState(hwnd
, nItem
, &lvItem
);
846 lvItem
.state
= LVIS_SELECTED
;
847 ListView_SetItemState(hwnd
, nItem
, &lvItem
);
851 LISTVIEW_SetItemFocus(hwnd
, nItem
);
852 infoPtr
->nSelectionMark
= nItem
;
859 * Sets a single group selection.
862 * [I] HWND : window handle
863 * [I] INT : item index
868 static VOID
LISTVIEW_SetGroupSelection(HWND hwnd
, INT nItem
)
870 LISTVIEW_INFO
*infoPtr
= (LISTVIEW_INFO
*)GetWindowLongA(hwnd
, 0);
871 INT nFirst
= min(infoPtr
->nSelectionMark
, nItem
);
872 INT nLast
= max(infoPtr
->nSelectionMark
, nItem
);
878 LISTVIEW_RemoveSelections(hwnd
, 0, nFirst
- 1);
881 if (nLast
< GETITEMCOUNT(infoPtr
))
883 LISTVIEW_RemoveSelections(hwnd
, nLast
+ 1, GETITEMCOUNT(infoPtr
));
886 lvItem
.state
= LVIS_SELECTED
;
887 lvItem
.stateMask
= LVIS_SELECTED
;
889 for (i
= nFirst
; i
<= nLast
; i
++)
891 ListView_SetItemState(hwnd
, i
, &lvItem
);
894 LISTVIEW_SetItemFocus(hwnd
, nItem
);
899 * Manages the item focus.
902 * [I] HWND : window handle
903 * [I] INT : item index
908 static VOID
LISTVIEW_SetItemFocus(HWND hwnd
, INT nItem
)
910 LISTVIEW_INFO
*infoPtr
= (LISTVIEW_INFO
*)GetWindowLongA(hwnd
, 0);
914 lvItem
.stateMask
= LVIS_FOCUSED
;
915 ListView_SetItemState(hwnd
, infoPtr
->nFocusedItem
, &lvItem
);
917 lvItem
.state
= LVIS_FOCUSED
;
918 lvItem
.stateMask
= LVIS_FOCUSED
;
919 ListView_SetItemState(hwnd
, nItem
, &lvItem
);
921 infoPtr
->nFocusedItem
= nItem
;
923 /* if multiple selection is allowed */
924 ListView_EnsureVisible(hwnd
, nItem
, FALSE
);
929 * Sets a single selection.
932 * [I] HWND : window handle
933 * [I] INT : item index
938 static VOID
LISTVIEW_SetSelection(HWND hwnd
, INT nItem
)
940 LISTVIEW_INFO
*infoPtr
= (LISTVIEW_INFO
*)GetWindowLongA(hwnd
, 0);
945 LISTVIEW_RemoveSelections(hwnd
, 0, nItem
- 1);
948 if (nItem
< GETITEMCOUNT(infoPtr
))
950 LISTVIEW_RemoveSelections(hwnd
, nItem
+ 1, GETITEMCOUNT(infoPtr
));
954 lvItem
.stateMask
= LVIS_FOCUSED
;
955 ListView_SetItemState(hwnd
, infoPtr
->nFocusedItem
, &lvItem
);
957 lvItem
.state
= LVIS_SELECTED
| LVIS_FOCUSED
;
958 lvItem
.stateMask
= LVIS_SELECTED
| LVIS_FOCUSED
;
959 ListView_SetItemState(hwnd
, nItem
, &lvItem
);
961 infoPtr
->nFocusedItem
= nItem
;
962 infoPtr
->nSelectionMark
= nItem
;
967 * Set selection(s) with keyboard.
970 * [I] HWND : window handle
971 * [I] INT : item index
976 static VOID
LISTVIEW_KeySelection(HWND hwnd
, INT nItem
)
978 WORD wShift
= HIWORD(GetKeyState(VK_SHIFT
));
979 WORD wCtrl
= HIWORD(GetKeyState(VK_CONTROL
));
983 LISTVIEW_SetGroupSelection(hwnd
, nItem
);
987 LISTVIEW_SetItemFocus(hwnd
, nItem
);
991 LISTVIEW_SetSelection(hwnd
, nItem
);
993 /* if multiple selection is allowed */
994 ListView_EnsureVisible(hwnd
, nItem
, FALSE
);
1000 * Determines the selected item.
1003 * [I] HWND : window handle
1004 * [I] INT : x ccordinate
1005 * [I] INT : y coordinate
1008 * SUCCESS : item index
1011 static LRESULT
LISTVIEW_MouseSelection(HWND hwnd
, INT nPosX
, INT nPosY
)
1013 LISTVIEW_INFO
*infoPtr
= (LISTVIEW_INFO
*)GetWindowLongA(hwnd
, 0);
1017 for (i
= 0; i
< GETITEMCOUNT(infoPtr
); i
++)
1019 rcItem
.left
= LVIR_SELECTBOUNDS
;
1020 if (LISTVIEW_GetItemRect(hwnd
, i
, &rcItem
) == TRUE
)
1022 if ((rcItem
.left
<= nPosX
) && (nPosX
<= rcItem
.right
) &&
1023 (rcItem
.top
<= nPosY
) && (nPosY
<= rcItem
.bottom
))
1035 * Removes all selection states.
1038 * [I] HWND : window handle
1039 * [I] INT : item index
1045 static VOID
LISTVIEW_RemoveSelections(HWND hwnd
, INT nFirst
, INT nLast
)
1051 lvItem
.stateMask
= LVIS_SELECTED
;
1053 for (i
= nFirst
; i
<= nLast
; i
++)
1055 ListView_SetItemState(hwnd
, i
, &lvItem
);
1064 * [IO] HDPA : dynamic pointer array handle
1065 * [I] INT : column index (subitem index)
1071 static BOOL
LISTVIEW_RemoveColumn(HDPA hdpaItems
, INT nSubItem
)
1073 BOOL bResult
= TRUE
;
1077 for (i
= 0; i
< hdpaItems
->nItemCount
; i
++)
1079 hdpaSubItems
= (HDPA
)DPA_GetPtr(hdpaItems
, i
);
1080 if (hdpaSubItems
!= NULL
)
1082 if (LISTVIEW_RemoveSubItem(hdpaSubItems
, nSubItem
) == FALSE
)
1094 * Removes a subitem at a given position.
1097 * [IO] HDPA : dynamic pointer array handle
1098 * [I] INT : subitem index
1104 static BOOL
LISTVIEW_RemoveSubItem(HDPA hdpaSubItems
, INT nSubItem
)
1106 LISTVIEW_SUBITEM
*lpSubItem
;
1109 for (i
= 1; i
< hdpaSubItems
->nItemCount
; i
++)
1111 lpSubItem
= (LISTVIEW_SUBITEM
*)DPA_GetPtr(hdpaSubItems
, i
);
1112 if (lpSubItem
!= NULL
)
1114 if (lpSubItem
->iSubItem
== nSubItem
)
1117 if ((lpSubItem
->pszText
!= NULL
) &&
1118 (lpSubItem
->pszText
!= LPSTR_TEXTCALLBACKA
))
1120 COMCTL32_Free(lpSubItem
->pszText
);
1124 COMCTL32_Free(lpSubItem
);
1126 /* free dpa memory */
1127 if (DPA_DeletePtr(hdpaSubItems
, i
) == NULL
)
1132 else if (lpSubItem
->iSubItem
> nSubItem
)
1144 * Compares the item information.
1147 * [I] LISTVIEW_ITEM *: destination item
1148 * [I] LPLVITEM : source item
1151 * SUCCCESS : TRUE (EQUAL)
1152 * FAILURE : FALSE (NOT EQUAL)
1154 static UINT
LISTVIEW_GetItemChanges(LISTVIEW_ITEM
*lpItem
, LPLVITEMA lpLVItem
)
1158 if ((lpItem
!= NULL
) && (lpLVItem
!= NULL
))
1160 if (lpLVItem
->mask
& LVIF_STATE
)
1162 if ((lpItem
->state
& lpLVItem
->stateMask
) !=
1163 (lpLVItem
->state
& lpLVItem
->stateMask
))
1165 uChanged
|= LVIF_STATE
;
1169 if (lpLVItem
->mask
& LVIF_IMAGE
)
1171 if (lpItem
->iImage
!= lpLVItem
->iImage
)
1173 uChanged
|= LVIF_IMAGE
;
1177 if (lpLVItem
->mask
& LVIF_PARAM
)
1179 if (lpItem
->lParam
!= lpLVItem
->lParam
)
1181 uChanged
|= LVIF_PARAM
;
1185 if (lpLVItem
->mask
& LVIF_INDENT
)
1187 if (lpItem
->iIndent
!= lpLVItem
->iIndent
)
1189 uChanged
|= LVIF_INDENT
;
1193 if (lpLVItem
->mask
& LVIF_TEXT
)
1195 if (lpLVItem
->pszText
== LPSTR_TEXTCALLBACKA
)
1197 if (lpItem
->pszText
!= LPSTR_TEXTCALLBACKA
)
1199 uChanged
|= LVIF_TEXT
;
1204 if (lpItem
->pszText
== LPSTR_TEXTCALLBACKA
)
1206 uChanged
|= LVIF_TEXT
;
1217 * Initializes item attributes.
1220 * [I] HWND : window handle
1221 * [O] LISTVIEW_ITEM *: destination item
1222 * [I] LPLVITEM : source item
1228 static BOOL
LISTVIEW_InitItem(HWND hwnd
, LISTVIEW_ITEM
*lpItem
,
1231 LONG lStyle
= GetWindowLongA(hwnd
, GWL_STYLE
);
1232 BOOL bResult
= FALSE
;
1234 if ((lpItem
!= NULL
) && (lpLVItem
!= NULL
))
1238 if (lpLVItem
->mask
& LVIF_STATE
)
1240 lpItem
->state
&= ~lpLVItem
->stateMask
;
1241 lpItem
->state
|= (lpLVItem
->state
& lpLVItem
->stateMask
);
1244 if (lpLVItem
->mask
& LVIF_IMAGE
)
1246 lpItem
->iImage
= lpLVItem
->iImage
;
1249 if (lpLVItem
->mask
& LVIF_PARAM
)
1251 lpItem
->lParam
= lpLVItem
->lParam
;
1254 if (lpLVItem
->mask
& LVIF_INDENT
)
1256 lpItem
->iIndent
= lpLVItem
->iIndent
;
1259 if (lpLVItem
->mask
& LVIF_TEXT
)
1261 if (lpLVItem
->pszText
== LPSTR_TEXTCALLBACKA
)
1263 if ((lStyle
& LVS_SORTASCENDING
) || (lStyle
& LVS_SORTDESCENDING
))
1268 if ((lpItem
->pszText
!= NULL
) &&
1269 (lpItem
->pszText
!= LPSTR_TEXTCALLBACKA
))
1271 COMCTL32_Free(lpItem
->pszText
);
1274 lpItem
->pszText
= LPSTR_TEXTCALLBACKA
;
1278 if (lpItem
->pszText
== LPSTR_TEXTCALLBACKA
)
1280 lpItem
->pszText
= NULL
;
1283 bResult
= Str_SetPtrA(&lpItem
->pszText
, lpLVItem
->pszText
);
1293 * Initializes subitem attributes.
1295 * NOTE: the documentation specifies that the operation fails if the user
1296 * tries to set the indent of a subitem.
1299 * [I] HWND : window handle
1300 * [O] LISTVIEW_SUBITEM *: destination subitem
1301 * [I] LPLVITEM : source subitem
1307 static BOOL
LISTVIEW_InitSubItem(HWND hwnd
, LISTVIEW_SUBITEM
*lpSubItem
,
1310 LONG lStyle
= GetWindowLongA(hwnd
, GWL_STYLE
);
1311 BOOL bResult
= FALSE
;
1313 if ((lpSubItem
!= NULL
) && (lpLVItem
!= NULL
))
1315 if (!(lpLVItem
->mask
& LVIF_INDENT
))
1318 ZeroMemory(lpSubItem
, sizeof(LISTVIEW_SUBITEM
));
1320 lpSubItem
->iSubItem
= lpLVItem
->iSubItem
;
1322 if (lpLVItem
->mask
& LVIF_IMAGE
)
1324 lpSubItem
->iImage
= lpLVItem
->iImage
;
1327 if (lpLVItem
->mask
& LVIF_TEXT
)
1329 if (lpLVItem
->pszText
== LPSTR_TEXTCALLBACKA
)
1331 if ((lStyle
& LVS_SORTASCENDING
) || (lStyle
& LVS_SORTDESCENDING
))
1336 if ((lpSubItem
->pszText
!= NULL
) &&
1337 (lpSubItem
->pszText
!= LPSTR_TEXTCALLBACKA
))
1339 COMCTL32_Free(lpSubItem
->pszText
);
1342 lpSubItem
->pszText
= LPSTR_TEXTCALLBACKA
;
1346 if (lpSubItem
->pszText
== LPSTR_TEXTCALLBACKA
)
1348 lpSubItem
->pszText
= NULL
;
1351 bResult
= Str_SetPtrA(&lpSubItem
->pszText
, lpLVItem
->pszText
);
1362 * Adds a subitem at a given position (column index).
1365 * [I] HWND : window handle
1366 * [I] LPLVITEM : new subitem atttributes
1372 static BOOL
LISTVIEW_AddSubItem(HWND hwnd
, LPLVITEMA lpLVItem
)
1374 LISTVIEW_INFO
*infoPtr
= (LISTVIEW_INFO
*)GetWindowLongA(hwnd
, 0);
1375 LISTVIEW_SUBITEM
*lpSubItem
= NULL
;
1376 BOOL bResult
= FALSE
;
1378 INT nPosition
, nItem
;
1380 if (lpLVItem
!= NULL
)
1382 hdpaSubItems
= (HDPA
)DPA_GetPtr(infoPtr
->hdpaItems
, lpLVItem
->iItem
);
1383 if (hdpaSubItems
!= NULL
)
1385 lpSubItem
= (LISTVIEW_SUBITEM
*)COMCTL32_Alloc(sizeof(LISTVIEW_SUBITEM
));
1386 if (lpSubItem
!= NULL
)
1388 if (LISTVIEW_InitSubItem(hwnd
, lpSubItem
, lpLVItem
) != FALSE
)
1390 nPosition
= LISTVIEW_FindInsertPosition(hdpaSubItems
,
1391 lpSubItem
->iSubItem
);
1392 nItem
= DPA_InsertPtr(hdpaSubItems
, nPosition
, lpSubItem
);
1402 /* cleanup if unsuccessful */
1403 if ((bResult
== FALSE
) && (lpSubItem
!= NULL
))
1405 COMCTL32_Free(lpSubItem
);
1413 * Finds the dpa insert position (array index).
1416 * [I] HWND : window handle
1417 * [I] INT : subitem index
1423 static INT
LISTVIEW_FindInsertPosition(HDPA hdpaSubItems
, INT nSubItem
)
1425 LISTVIEW_SUBITEM
*lpSubItem
;
1428 for (i
= 1; i
< hdpaSubItems
->nItemCount
; i
++)
1430 lpSubItem
= (LISTVIEW_SUBITEM
*)DPA_GetPtr(hdpaSubItems
, i
);
1431 if (lpSubItem
!= NULL
)
1433 if (lpSubItem
->iSubItem
> nSubItem
)
1440 return hdpaSubItems
->nItemCount
;
1445 * Retrieves a listview subitem at a given position (column index).
1448 * [I] HWND : window handle
1449 * [I] INT : subitem index
1455 static LISTVIEW_SUBITEM
* LISTVIEW_GetSubItem(HDPA hdpaSubItems
, INT nSubItem
)
1457 LISTVIEW_SUBITEM
*lpSubItem
;
1460 for (i
= 1; i
< hdpaSubItems
->nItemCount
; i
++)
1462 lpSubItem
= (LISTVIEW_SUBITEM
*)DPA_GetPtr(hdpaSubItems
, i
);
1463 if (lpSubItem
!= NULL
)
1465 if (lpSubItem
->iSubItem
== nSubItem
)
1469 else if (lpSubItem
->iSubItem
> nSubItem
)
1481 * Sets item attributes.
1484 * [I] HWND : window handle
1485 * [I] LPLVITEM : new item atttributes
1491 static BOOL
LISTVIEW_SetItem(HWND hwnd
, LPLVITEMA lpLVItem
)
1493 LISTVIEW_INFO
*infoPtr
= (LISTVIEW_INFO
*)GetWindowLongA(hwnd
, 0);
1494 BOOL bResult
= FALSE
;
1496 LISTVIEW_ITEM
*lpItem
;
1499 LONG lCtrlId
= GetWindowLongA(hwnd
, GWL_ID
);
1501 if (lpLVItem
!= NULL
)
1503 if (lpLVItem
->iSubItem
== 0)
1505 hdpaSubItems
= (HDPA
)DPA_GetPtr(infoPtr
->hdpaItems
, lpLVItem
->iItem
);
1506 if (hdpaSubItems
!= NULL
)
1508 lpItem
= (LISTVIEW_ITEM
*)DPA_GetPtr(hdpaSubItems
, lpLVItem
->iSubItem
);
1511 ZeroMemory(&nmlv
, sizeof(NMLISTVIEW
));
1512 nmlv
.hdr
.hwndFrom
= hwnd
;
1513 nmlv
.hdr
.idFrom
= lCtrlId
;
1514 nmlv
.hdr
.code
= LVN_ITEMCHANGING
;
1515 nmlv
.lParam
= lpItem
->lParam
;
1516 uChanged
= LISTVIEW_GetItemChanges(lpItem
, lpLVItem
);
1519 if (uChanged
& LVIF_STATE
)
1521 nmlv
.uNewState
= lpLVItem
->state
& lpLVItem
->stateMask
;
1522 nmlv
.uOldState
= lpItem
->state
& lpLVItem
->stateMask
;
1525 nmlv
.uChanged
= uChanged
;
1526 nmlv
.iItem
= lpLVItem
->iItem
;
1527 nmlv
.lParam
= lpItem
->lParam
;
1528 /* send LVN_ITEMCHANGING notification */
1529 ListView_LVNotify(GetParent(hwnd
), lCtrlId
, &nmlv
);
1531 /* copy information */
1532 bResult
= LISTVIEW_InitItem(hwnd
, lpItem
, lpLVItem
);
1534 /* send LVN_ITEMCHANGED notification */
1535 nmlv
.hdr
.code
= LVN_ITEMCHANGED
;
1536 ListView_LVNotify(GetParent(hwnd
), lCtrlId
, &nmlv
);
1543 InvalidateRect(hwnd
, NULL
, FALSE
);
1554 * Sets subitem attributes.
1557 * [I] HWND : window handle
1558 * [I] LPLVITEM : new subitem atttributes
1564 static BOOL
LISTVIEW_SetSubItem(HWND hwnd
, LPLVITEMA lpLVItem
)
1566 LISTVIEW_INFO
*infoPtr
= (LISTVIEW_INFO
*)GetWindowLongA(hwnd
, 0);
1567 BOOL bResult
= FALSE
;
1569 LISTVIEW_SUBITEM
*lpSubItem
;
1571 if (lpLVItem
!= NULL
)
1573 if (lpLVItem
->iSubItem
> 0)
1575 hdpaSubItems
= (HDPA
)DPA_GetPtr(infoPtr
->hdpaItems
, lpLVItem
->iItem
);
1576 if (hdpaSubItems
!= NULL
)
1578 /* set subitem only if column is present */
1579 if (Header_GetItemCount(infoPtr
->hwndHeader
) > lpLVItem
->iSubItem
)
1581 lpSubItem
= LISTVIEW_GetSubItem(hdpaSubItems
, lpLVItem
->iSubItem
);
1582 if (lpSubItem
!= NULL
)
1584 bResult
= LISTVIEW_InitSubItem(hwnd
, lpSubItem
, lpLVItem
);
1588 bResult
= LISTVIEW_AddSubItem(hwnd
, lpLVItem
);
1591 InvalidateRect(hwnd
, NULL
, FALSE
);
1602 * Retrieves the index of the item at coordinate (0, 0) of the client area.
1605 * [I] HWND : window handle
1610 static INT
LISTVIEW_GetTopIndex(HWND hwnd
)
1612 LISTVIEW_INFO
*infoPtr
= (LISTVIEW_INFO
*) GetWindowLongA(hwnd
, 0);
1613 LONG lStyle
= GetWindowLongA(hwnd
, GWL_STYLE
);
1616 switch (LVS_TYPEMASK
& lStyle
)
1619 if (lStyle
& WS_HSCROLL
)
1621 nItem
= GetScrollPos(hwnd
, SB_HORZ
) * infoPtr
->nCountPerColumn
;
1626 if (lStyle
& WS_VSCROLL
)
1628 nItem
= GetScrollPos(hwnd
, SB_VERT
);
1638 * Evaluates if scrollbars are needed & sets the scroll range/position.
1641 * [I] HWND : window handle
1642 * [I] LONG : window style
1647 static VOID
LISTVIEW_SetScroll(HWND hwnd
, LONG lStyle
)
1649 LISTVIEW_INFO
*infoPtr
= (LISTVIEW_INFO
*)GetWindowLongA(hwnd
, 0);
1650 INT nListWidth
= infoPtr
->rcList
.right
- infoPtr
->rcList
.left
;
1651 INT nListHeight
= infoPtr
->rcList
.bottom
- infoPtr
->rcList
.top
;
1652 INT nHScrollHeight
= GetSystemMetrics(SM_CYHSCROLL
);
1653 INT nVScrollWidth
= GetSystemMetrics(SM_CXVSCROLL
);
1656 INT nHiddenItemCount
;
1660 INT nPixPerScrollPos
;
1663 TRACE(listview
, "(hwnd=%x,lStyle=%lx)\n", hwnd
, lStyle
);
1665 switch (LVS_TYPEMASK
& lStyle
)
1668 nCountPerPage
= infoPtr
->nCountPerRow
* infoPtr
->nCountPerColumn
;
1669 if (nCountPerPage
< GETITEMCOUNT(infoPtr
))
1671 /* display horizontal scrollbar */
1672 if ((lStyle
& WS_HSCROLL
) == 0)
1674 ShowScrollBar(hwnd
, SB_HORZ
, TRUE
);
1677 /* calculate new scrollbar range */
1678 nHiddenItemCount
= GETITEMCOUNT(infoPtr
) - nCountPerPage
;
1679 if ((nHiddenItemCount
% infoPtr
->nCountPerColumn
) == 0)
1681 nMaxRange
= nHiddenItemCount
/ infoPtr
->nCountPerColumn
;
1685 nMaxRange
= nHiddenItemCount
/ infoPtr
->nCountPerColumn
+ 1;
1688 SetScrollRange(hwnd
, SB_HORZ
, 0, nMaxRange
, FALSE
);
1689 nScrollPos
= ListView_GetTopIndex(hwnd
) / infoPtr
->nCountPerColumn
;
1690 SetScrollPos(hwnd
, SB_HORZ
, nScrollPos
, TRUE
);
1694 /* hide scrollbar */
1695 if ((lStyle
& WS_HSCROLL
) != 0)
1697 ShowScrollBar(hwnd
, SB_HORZ
, FALSE
);
1704 * This section was commented out because I experienced some problems
1705 * with the scrolling of the header control. The idea was to add a
1706 * horizontal scrollbar when the width of the client area was smaller
1707 * than the width of the header control.
1710 /* if (infoPtr->nItemWidth > nListWidth) */
1712 /* if ((lStyle & WS_HSCROLL) == 0) */
1714 /* ShowScrollBar(hwnd, SB_HORZ, TRUE); */
1715 /* LISTVIEW_SetSize(hwnd, lStyle, -1, -1); */
1716 /* LISTVIEW_SetViewInfo(hwnd, lStyle); */
1719 /* nListWidth = infoPtr->rcList.right - infoPtr->rcList.left; */
1720 /* nHiddenWidth = infoPtr->nItemWidth - nListWidth; */
1721 /* nPixPerScrollPos = max(1, nListWidth / 10); */
1723 /* if ((nHiddenWidth % nPixPerScrollPos) == 0) */
1725 /* nMaxRange = nHiddenWidth / nPixPerScrollPos; */
1729 /* nMaxRange = nHiddenWidth / nPixPerScrollPos + 1; */
1732 /* SetScrollRange(hwnd, SB_HORZ, 0, nMaxRange, FALSE); */
1733 /* SetScrollPos(hwnd, SB_HORZ, 0, TRUE); */
1737 /* if ((lStyle & WS_HSCROLL) != 0) */
1739 /* ShowScrollBar(hwnd, SB_HORZ, FASLE); */
1740 /* LISTVIEW_SetSize(hwnd, lStyle, -1, -1); */
1741 /* LISTVIEW_SetViewInfo(hwnd, lStyle); */
1745 if (infoPtr
->nCountPerColumn
< GETITEMCOUNT(infoPtr
))
1747 if ((lStyle
& WS_VSCROLL
) == 0)
1749 if (nListWidth
> nVScrollWidth
)
1751 ShowScrollBar(hwnd
, SB_VERT
, TRUE
);
1752 nListWidth
-= nVScrollWidth
;
1756 /* vertical range & position */
1757 nMaxRange
= GETITEMCOUNT(infoPtr
) - infoPtr
->nCountPerColumn
;
1758 SetScrollRange(hwnd
, SB_VERT
, 0, nMaxRange
, FALSE
);
1759 SetScrollPos(hwnd
, SB_VERT
, ListView_GetTopIndex(hwnd
), TRUE
);
1763 if ((lStyle
& WS_VSCROLL
) != 0)
1765 ShowScrollBar(hwnd
, SB_VERT
, FALSE
);
1766 nListWidth
+= nVScrollWidth
;
1773 if (LISTVIEW_GetViewRect(hwnd
, &rcView
) != FALSE
)
1775 if (rcView
.right
- rcView
.left
> nListWidth
)
1777 if ((lStyle
& WS_HSCROLL
) == 0)
1779 if (nListHeight
> nHScrollHeight
)
1781 ShowScrollBar(hwnd
, SB_HORZ
, TRUE
);
1782 nListHeight
-= nHScrollHeight
;
1786 /* calculate size of hidden items */
1787 nHiddenWidth
= rcView
.right
- rcView
.left
- nListWidth
;
1788 nPixPerScrollPos
= max(1, nListWidth
/ 10);
1790 /* vertical range & position */
1791 if ((nHiddenWidth
% nPixPerScrollPos
) == 0)
1793 nMaxRange
= nHiddenWidth
/ nPixPerScrollPos
;
1797 nMaxRange
= nHiddenWidth
/ nPixPerScrollPos
+ 1;
1800 /* set range and position */
1801 SetScrollRange(hwnd
, SB_HORZ
, 0, nMaxRange
, FALSE
);
1802 SetScrollPos(hwnd
, SB_HORZ
, 0, TRUE
);
1806 if ((lStyle
& WS_HSCROLL
) != 0)
1808 ShowScrollBar(hwnd
, SB_HORZ
, FALSE
);
1809 nListHeight
+= nHScrollHeight
;
1813 if (rcView
.bottom
- rcView
.top
> nListHeight
)
1815 if ((lStyle
& WS_VSCROLL
) == 0)
1817 if (nListWidth
> nVScrollWidth
)
1819 ShowScrollBar(hwnd
, SB_VERT
, TRUE
);
1820 nListWidth
-= nVScrollWidth
;
1824 /* calculate size of hidden items */
1825 nHiddenHeight
= rcView
.bottom
- rcView
.top
- nListHeight
;
1826 nPixPerScrollPos
= max(1, nListHeight
/ 10);
1828 /* set vertical range & position */
1829 if ((nHiddenHeight
% nPixPerScrollPos
) == 0)
1831 nMaxRange
= nHiddenHeight
/ nPixPerScrollPos
;
1835 nMaxRange
= nHiddenHeight
/ nPixPerScrollPos
+ 1;
1838 /* set range and position */
1839 SetScrollRange(hwnd
, SB_VERT
, 0, nMaxRange
, FALSE
);
1840 SetScrollPos(hwnd
, SB_VERT
, 0, TRUE
);
1844 if ((lStyle
& WS_VSCROLL
) != 0)
1846 ShowScrollBar(hwnd
, SB_VERT
, FALSE
);
1847 nListWidth
+= nVScrollWidth
;
1860 * [I] HWND : window handle
1861 * [I] HDC : device context handle
1862 * [I] INT : item index
1863 * [I] LPARAM : item lparam
1864 * [I] LISTVIEW_SUBITEM * : item
1865 * [I] INT : column index (header index)
1866 * [I] RECT * : clipping rectangle
1871 static VOID
LISTVIEW_DrawSubItem(HWND hwnd
, HDC hdc
, INT nItem
, LPARAM lParam
,
1872 LISTVIEW_SUBITEM
*lpSubItem
, INT nColumn
,
1875 LISTVIEW_INFO
*infoPtr
= (LISTVIEW_INFO
*)GetWindowLongA(hwnd
, 0);
1876 CHAR szDispText
[DISP_TEXT_SIZE
];
1877 LPSTR pszDispText
= NULL
;
1879 /* set item colors */
1880 SetBkColor(hdc
, infoPtr
->clrTextBk
);
1881 SetTextColor(hdc
, infoPtr
->clrText
);
1883 pszDispText
= szDispText
;
1884 LISTVIEW_GetSubItemDispInfo(hwnd
, nItem
, lParam
, lpSubItem
, nColumn
, NULL
,
1885 &pszDispText
, DISP_TEXT_SIZE
);
1887 /* draw text : using arbitrary offset of 10 pixels */
1889 ExtTextOutA(hdc
, lprc
->left
, lprc
->top
, ETO_OPAQUE
|ETO_CLIPPED
,
1890 lprc
, pszDispText
, lstrlenA(pszDispText
), NULL
);
1898 * [I] HWND : window handle
1899 * [I] HDC : device context handle
1900 * [I] LISTVIEW_ITEM * : item
1901 * [I] INT : item index
1902 * [I] RECT * : clipping rectangle
1907 static VOID
LISTVIEW_DrawItem(HWND hwnd
, HDC hdc
, LISTVIEW_ITEM
*lpItem
,
1910 LISTVIEW_INFO
*infoPtr
= (LISTVIEW_INFO
*)GetWindowLongA(hwnd
, 0);
1911 CHAR szDispText
[DISP_TEXT_SIZE
];
1912 LPSTR pszDispText
= NULL
;
1918 TRACE(listview
, "(hwnd=%x,hdc=%x,lpItem=%p,nItem=%d,rc.left=%d,rctop=%d,rc.right=%d,rc.bottom=%d)\n", hwnd
, hdc
, lpItem
, nItem
, rc
.left
, rc
.top
, rc
.right
, rc
.bottom
);
1920 pszDispText
= szDispText
;
1921 LISTVIEW_GetItemDispInfo(hwnd
, nItem
, lpItem
, &nImage
, &uState
, &pszDispText
,
1924 if (uState
& LVIS_SELECTED
)
1928 /* set item colors */
1929 SetBkColor(hdc
, GetSysColor(COLOR_HIGHLIGHT
));
1930 SetTextColor(hdc
, GetSysColor(COLOR_HIGHLIGHTTEXT
));
1932 /* set raster mode */
1933 SetROP2(hdc
, R2_XORPEN
);
1939 /* set item colors */
1940 SetBkColor(hdc
, infoPtr
->clrTextBk
);
1941 SetTextColor(hdc
, infoPtr
->clrText
);
1943 /* set raster mode */
1944 SetROP2(hdc
, R2_COPYPEN
);
1948 if (infoPtr
->himlState
!= NULL
)
1950 /* right shift 12 bits to obtain index in image list */
1951 if (bSelected
!= FALSE
)
1953 ImageList_Draw(infoPtr
->himlState
, uState
>> 12, hdc
, rc
.left
,
1954 rc
.top
, ILD_SELECTED
);
1958 ImageList_Draw(infoPtr
->himlState
, uState
>> 12, hdc
, rc
.left
,
1959 rc
.top
, ILD_NORMAL
);
1962 rc
.left
+= infoPtr
->iconSize
.cx
;
1966 if (infoPtr
->himlSmall
!= NULL
)
1968 if (bSelected
!= FALSE
)
1970 ImageList_Draw(infoPtr
->himlSmall
, nImage
, hdc
, rc
.left
,
1971 rc
.top
, ILD_SELECTED
);
1975 ImageList_Draw(infoPtr
->himlSmall
, nImage
, hdc
, rc
.left
,
1976 rc
.top
, ILD_NORMAL
);
1979 rc
.left
+= infoPtr
->iconSize
.cx
;
1982 nLabelWidth
= ListView_GetStringWidthA(hwnd
, pszDispText
);
1983 if (rc
.left
+ nLabelWidth
< rc
.right
)
1985 rc
.right
= rc
.left
+ nLabelWidth
;
1989 ExtTextOutA(hdc
, rc
.left
, rc
.top
, ETO_OPAQUE
|ETO_CLIPPED
,
1990 &rc
, pszDispText
, lstrlenA(pszDispText
), NULL
);
1992 if (lpItem
->state
& LVIS_FOCUSED
)
1994 Rectangle(hdc
, rc
.left
, rc
.top
, rc
.right
, rc
.bottom
);
2000 * Draws an item when in large icon display mode.
2003 * [I] HWND : window handle
2004 * [I] HDC : device context handle
2005 * [I] LISTVIEW_ITEM * : item
2006 * [I] INT : item index
2007 * [I] RECT * : clipping rectangle
2012 static VOID
LISTVIEW_DrawLargeItem(HWND hwnd
, HDC hdc
, LISTVIEW_ITEM
*lpItem
,
2015 LISTVIEW_INFO
*infoPtr
= (LISTVIEW_INFO
*)GetWindowLongA(hwnd
, 0);
2016 CHAR szDispText
[DISP_TEXT_SIZE
];
2017 LPSTR pszDispText
= NULL
;
2025 TRACE(listview
, "(hwnd=%x,hdc=%x,lpItem=%p,nItem=%d,rc.left=%d,rctop=%d,rc.right=%d,rc.bottom=%d)\n", hwnd
, hdc
, lpItem
, nItem
, rc
.left
, rc
.top
, rc
.right
, rc
.bottom
);
2027 pszDispText
= szDispText
;
2028 LISTVIEW_GetItemDispInfo(hwnd
, nItem
, lpItem
, &nImage
, &uState
, &pszDispText
,
2030 if (uState
& LVIS_SELECTED
)
2034 /* set item colors */
2035 SetBkColor(hdc
, GetSysColor(COLOR_HIGHLIGHT
));
2036 SetTextColor(hdc
, GetSysColor(COLOR_HIGHLIGHTTEXT
));
2038 /* set raster mode */
2039 SetROP2(hdc
, R2_XORPEN
);
2045 /* set item colors */
2046 SetBkColor(hdc
, infoPtr
->clrTextBk
);
2047 SetTextColor(hdc
, infoPtr
->clrText
);
2049 /* set raster mode */
2050 SetROP2(hdc
, R2_COPYPEN
);
2053 if (infoPtr
->himlNormal
!= NULL
)
2055 rc
.top
+= ICON_TOP_PADDING
;
2056 nDrawPosX
= rc
.left
+ (infoPtr
->iconSpacing
.cx
- infoPtr
->iconSize
.cx
) / 2;
2057 if (bSelected
!= FALSE
)
2059 ImageList_Draw(infoPtr
->himlNormal
, nImage
, hdc
, nDrawPosX
, rc
.top
,
2064 ImageList_Draw(infoPtr
->himlNormal
, nImage
, hdc
, nDrawPosX
, rc
.top
,
2069 rc
.top
+= infoPtr
->iconSize
.cy
+ ICON_BOTTOM_PADDING
;
2070 nLabelWidth
= ListView_GetStringWidthA(hwnd
, pszDispText
);
2071 nDrawPosX
= infoPtr
->iconSpacing
.cx
- nLabelWidth
;
2074 rc
.left
+= nDrawPosX
/ 2;
2075 rc
.right
= rc
.left
+ nLabelWidth
;
2080 rc
.right
= rc
.left
+ infoPtr
->iconSpacing
.cx
- 1;
2084 GetTextMetricsA(hdc
, &tm
);
2085 rc
.bottom
= rc
.top
+ tm
.tmHeight
+ HEIGHT_PADDING
;
2086 ExtTextOutA(hdc
, rc
.left
, rc
.top
, ETO_OPAQUE
|ETO_CLIPPED
,
2087 &rc
, pszDispText
, lstrlenA(pszDispText
), NULL
);
2089 if (lpItem
->state
& LVIS_FOCUSED
)
2091 Rectangle(hdc
, rc
.left
, rc
.top
, rc
.right
, rc
.bottom
);
2097 * Draws listview items when in report display mode.
2100 * [I] HWND : window handle
2101 * [I] HDC : device context handle
2106 static VOID
LISTVIEW_RefreshReport(HWND hwnd
, HDC hdc
)
2108 LISTVIEW_INFO
*infoPtr
= (LISTVIEW_INFO
*)GetWindowLongA(hwnd
,0);
2109 INT nDrawPosY
= infoPtr
->rcList
.top
;
2110 LISTVIEW_ITEM
*lpItem
;
2111 LISTVIEW_SUBITEM
*lpSubItem
= NULL
;
2112 BOOL bNeedSubItem
= TRUE
;
2120 nItem
= ListView_GetTopIndex(hwnd
);
2121 nLast
= nItem
+ infoPtr
->nCountPerColumn
;
2122 while (nItem
<= nLast
)
2124 hdpaSubItems
= (HDPA
)DPA_GetPtr(infoPtr
->hdpaItems
, nItem
);
2125 if (hdpaSubItems
!= NULL
)
2127 lpItem
= (LISTVIEW_ITEM
*)DPA_GetPtr(hdpaSubItems
, 0);
2130 /* the width of the header items will determine the size of the
2132 Header_GetItemRect(infoPtr
->hwndHeader
, 0, &rcItem
);
2133 rcItem
.left
+= REPORT_MARGINX
;
2134 rcItem
.right
= max(rcItem
.left
, rcItem
.right
- REPORT_MARGINX
);
2135 rcItem
.top
= nDrawPosY
;
2136 rcItem
.bottom
= rcItem
.top
+ infoPtr
->nItemHeight
;
2137 LISTVIEW_DrawItem(hwnd
, hdc
, lpItem
, nItem
, rcItem
);
2140 nColumnCount
= Header_GetItemCount(infoPtr
->hwndHeader
);
2141 for (k
= 1, j
= 1; j
< nColumnCount
; j
++)
2143 Header_GetItemRect(infoPtr
->hwndHeader
, j
, &rcItem
);
2144 rcItem
.left
+= REPORT_MARGINX
;
2145 rcItem
.right
= max(rcItem
.left
, rcItem
.right
- REPORT_MARGINX
);
2146 rcItem
.top
= nDrawPosY
;
2147 rcItem
.bottom
= rcItem
.top
+ infoPtr
->nItemHeight
;
2149 if (k
< hdpaSubItems
->nItemCount
)
2151 if (bNeedSubItem
!= FALSE
)
2153 lpSubItem
= (LISTVIEW_SUBITEM
*)DPA_GetPtr(hdpaSubItems
, k
);
2157 if (lpSubItem
!= NULL
)
2159 if (lpSubItem
->iSubItem
== j
)
2161 LISTVIEW_DrawSubItem(hwnd
, hdc
, nItem
, lpItem
->lParam
, lpSubItem
,
2163 bNeedSubItem
= TRUE
;
2167 LISTVIEW_DrawSubItem(hwnd
, hdc
, nItem
, lpItem
->lParam
, NULL
, j
,
2169 bNeedSubItem
= FALSE
;
2174 LISTVIEW_DrawSubItem(hwnd
, hdc
, nItem
, lpItem
->lParam
, NULL
, j
,
2176 bNeedSubItem
= TRUE
;
2181 LISTVIEW_DrawSubItem(hwnd
, hdc
, nItem
, lpItem
->lParam
, NULL
, j
,
2187 nDrawPosY
+= infoPtr
->nItemHeight
;
2194 * Draws listview items when in list display mode.
2197 * [I] HWND : window handle
2198 * [I] HDC : device context handle
2203 static VOID
LISTVIEW_RefreshList(HWND hwnd
, HDC hdc
)
2205 LISTVIEW_INFO
*infoPtr
= (LISTVIEW_INFO
*)GetWindowLongA(hwnd
, 0);
2206 LISTVIEW_ITEM
*lpItem
;
2211 INT nItem
= ListView_GetTopIndex(hwnd
);
2213 if (infoPtr
->rcList
.right
> 0)
2215 /* get number of display columns */
2216 if (infoPtr
->rcList
.right
% infoPtr
->nItemWidth
== 0)
2218 nColumnCount
= infoPtr
->rcList
.right
/ infoPtr
->nItemWidth
;
2222 nColumnCount
= infoPtr
->rcList
.right
/ infoPtr
->nItemWidth
+ 1;
2225 for (i
= 0; i
< nColumnCount
; i
++)
2228 while ((nItem
< GETITEMCOUNT(infoPtr
)) &&
2229 (j
<infoPtr
->nCountPerColumn
))
2231 hdpaSubItems
= (HDPA
)DPA_GetPtr(infoPtr
->hdpaItems
, nItem
);
2232 if (hdpaSubItems
!= NULL
)
2234 lpItem
= (LISTVIEW_ITEM
*)DPA_GetPtr(hdpaSubItems
, 0);
2237 rc
.top
= j
* infoPtr
->nItemHeight
;
2238 rc
.left
= i
* infoPtr
->nItemWidth
;
2239 rc
.bottom
= rc
.top
+ infoPtr
->nItemHeight
;
2240 rc
.right
= rc
.left
+ infoPtr
->nItemWidth
;
2241 LISTVIEW_DrawItem(hwnd
, hdc
, lpItem
, nItem
, rc
);
2254 * Draws listview items when in icon or small icon display mode.
2257 * [I] HWND : window handle
2258 * [I] HDC : device context handle
2263 static VOID
LISTVIEW_RefreshIcon(HWND hwnd
, HDC hdc
, BOOL bSmall
)
2265 LISTVIEW_INFO
*infoPtr
= (LISTVIEW_INFO
*)GetWindowLongA(hwnd
, 0);
2266 LISTVIEW_ITEM
*lpItem
;
2273 LISTVIEW_GetOrigin(hwnd
, &ptOrigin
);
2275 for (i
= 0; i
< GETITEMCOUNT(infoPtr
); i
++)
2277 LISTVIEW_GetItemPosition(hwnd
, i
, &ptPosition
);
2278 ptPosition
.x
+= ptOrigin
.x
;
2279 ptPosition
.y
+= ptOrigin
.y
;
2281 if (ptPosition
.y
+ infoPtr
->nItemHeight
> infoPtr
->rcList
.top
)
2283 if (ptPosition
.x
+ infoPtr
->nItemWidth
> infoPtr
->rcList
.left
)
2285 if (ptPosition
.y
< infoPtr
->rcList
.bottom
)
2287 if (ptPosition
.x
< infoPtr
->rcList
.right
)
2289 hdpaSubItems
= (HDPA
)DPA_GetPtr(infoPtr
->hdpaItems
, i
);
2290 if (hdpaSubItems
!= NULL
)
2292 lpItem
= (LISTVIEW_ITEM
*)DPA_GetPtr(hdpaSubItems
, 0);
2295 rc
.top
= ptPosition
.y
;
2296 rc
.left
= ptPosition
.x
;
2297 rc
.bottom
= rc
.top
+ infoPtr
->nItemHeight
;
2298 rc
.right
= rc
.left
+ infoPtr
->nItemWidth
;
2299 if (bSmall
== FALSE
)
2301 LISTVIEW_DrawLargeItem(hwnd
, hdc
, lpItem
, i
, rc
);
2305 LISTVIEW_DrawItem(hwnd
, hdc
, lpItem
, i
, rc
);
2318 * Draws listview items.
2321 * [I] HWND : window handle
2322 * [I] HDC : device context handle
2327 static VOID
LISTVIEW_Refresh(HWND hwnd
, HDC hdc
)
2329 LISTVIEW_INFO
*infoPtr
= (LISTVIEW_INFO
*)GetWindowLongA(hwnd
, 0);
2330 LONG lStyle
= GetWindowLongA(hwnd
, GWL_STYLE
);
2335 hOldFont
= SelectObject(hdc
, infoPtr
->hFont
);
2337 /* select the doted pen (for drawing the focus box) */
2338 hPen
= CreatePen(PS_DOT
, 1, 0);
2339 hOldPen
= SelectObject(hdc
, hPen
);
2341 /* select transparent brush (for drawing the focus box) */
2342 SelectObject(hdc
, GetStockObject(NULL_BRUSH
));
2344 switch (LVS_TYPEMASK
& lStyle
)
2347 LISTVIEW_RefreshList(hwnd
, hdc
);
2350 LISTVIEW_RefreshReport(hwnd
, hdc
);
2353 LISTVIEW_RefreshIcon(hwnd
, hdc
, TRUE
);
2356 LISTVIEW_RefreshIcon(hwnd
, hdc
, FALSE
);
2359 /* unselect objects */
2360 SelectObject(hdc
, hOldFont
);
2361 SelectObject(hdc
, hOldPen
);
2370 * Calculates the approximate width and height of a given number of items.
2373 * [I] HWND : window handle
2374 * [I] INT : number of items
2379 * Returns a DWORD. The width in the low word and the height in high word.
2381 static LRESULT
LISTVIEW_ApproximateViewRect(HWND hwnd
, INT nItemCount
,
2382 WORD wWidth
, WORD wHeight
)
2384 LISTVIEW_INFO
*infoPtr
= (LISTVIEW_INFO
*)GetWindowLongA(hwnd
, 0);
2385 LONG lStyle
= GetWindowLongA(hwnd
, GWL_STYLE
);
2386 INT nItemCountPerColumn
= 1;
2387 INT nColumnCount
= 0;
2388 DWORD dwViewRect
= 0;
2390 if (nItemCount
== -1)
2391 nItemCount
= GETITEMCOUNT(infoPtr
);
2393 if (lStyle
& LVS_LIST
)
2395 if (wHeight
== 0xFFFF)
2397 /* use current height */
2398 wHeight
= infoPtr
->rcList
.bottom
;
2401 if (wHeight
< infoPtr
->nItemHeight
)
2403 wHeight
= infoPtr
->nItemHeight
;
2408 if (infoPtr
->nItemHeight
> 0)
2410 nItemCountPerColumn
= wHeight
/ infoPtr
->nItemHeight
;
2411 if (nItemCountPerColumn
== 0)
2412 nItemCountPerColumn
= 1;
2414 if (nItemCount
% nItemCountPerColumn
!= 0)
2415 nColumnCount
= nItemCount
/ nItemCountPerColumn
;
2417 nColumnCount
= nItemCount
/ nItemCountPerColumn
+ 1;
2421 /* Microsoft padding magic */
2422 wHeight
= nItemCountPerColumn
* infoPtr
->nItemHeight
+ 2;
2423 wWidth
= nColumnCount
* infoPtr
->nItemWidth
+ 2;
2425 dwViewRect
= MAKELONG(wWidth
, wHeight
);
2427 else if (lStyle
& LVS_REPORT
)
2431 else if (lStyle
& LVS_SMALLICON
)
2435 else if (lStyle
& LVS_ICON
)
2445 * Arranges listview items in icon display mode.
2448 * [I] HWND : window handle
2449 * [I] INT : alignment code
2455 static LRESULT
LISTVIEW_Arrange(HWND hwnd
, INT nAlignCode
)
2457 LONG lStyle
= GetWindowLongA(hwnd
, GWL_STYLE
);
2458 BOOL bResult
= FALSE
;
2460 if (((LVS_TYPEMASK
& lStyle
) == LVS_ICON
) ||
2461 ((LVS_TYPEMASK
& lStyle
) == LVS_SMALLICON
))
2474 case LVA_SNAPTOGRID
:
2483 /* << LISTVIEW_CreateDragImage >> */
2487 * Removes all listview items and subitems.
2490 * [I] HWND : window handle
2496 static LRESULT
LISTVIEW_DeleteAllItems(HWND hwnd
)
2498 LISTVIEW_INFO
*infoPtr
= (LISTVIEW_INFO
*)GetWindowLongA(hwnd
, 0);
2499 LONG lCtrlId
= GetWindowLongA(hwnd
, GWL_ID
);
2500 LONG lStyle
= GetWindowLongA(hwnd
, GWL_STYLE
);
2501 LISTVIEW_ITEM
*lpItem
;
2502 LISTVIEW_SUBITEM
*lpSubItem
;
2505 BOOL bResult
= FALSE
;
2510 TRACE(listview
, "(hwnd=%x,)\n", hwnd
);
2512 if (GETITEMCOUNT(infoPtr
) > 0)
2514 /* initialize memory */
2515 ZeroMemory(&nmlv
, sizeof(NMLISTVIEW
));
2517 /* send LVN_DELETEALLITEMS notification */
2518 nmlv
.hdr
.hwndFrom
= hwnd
;
2519 nmlv
.hdr
.idFrom
= lCtrlId
;
2520 nmlv
.hdr
.code
= LVN_DELETEALLITEMS
;
2523 /* verify if subsequent LVN_DELETEITEM notifications should be
2525 bSuppress
= ListView_LVNotify(GetParent(hwnd
), lCtrlId
, &nmlv
);
2527 for (i
= 0; i
< GETITEMCOUNT(infoPtr
); i
++)
2529 hdpaSubItems
= (HDPA
)DPA_GetPtr(infoPtr
->hdpaItems
, i
);
2530 if (hdpaSubItems
!= NULL
)
2532 for (j
= 1; j
< hdpaSubItems
->nItemCount
; j
++)
2534 lpSubItem
= (LISTVIEW_SUBITEM
*)DPA_GetPtr(hdpaSubItems
, j
);
2535 if (lpSubItem
!= NULL
)
2537 /* free subitem string */
2538 if ((lpSubItem
->pszText
!= NULL
) &&
2539 (lpSubItem
->pszText
!= LPSTR_TEXTCALLBACKA
))
2541 COMCTL32_Free(lpSubItem
->pszText
);
2545 COMCTL32_Free(lpSubItem
);
2549 lpItem
= (LISTVIEW_ITEM
*)DPA_GetPtr(hdpaSubItems
, 0);
2552 if (bSuppress
== FALSE
)
2554 /* send LVN_DELETEITEM notification */
2555 nmlv
.hdr
.code
= LVN_DELETEITEM
;
2557 nmlv
.lParam
= lpItem
->lParam
;
2558 ListView_LVNotify(GetParent(hwnd
), lCtrlId
, &nmlv
);
2561 /* free item string */
2562 if ((lpItem
->pszText
!= NULL
) &&
2563 (lpItem
->pszText
!= LPSTR_TEXTCALLBACKA
))
2565 COMCTL32_Free(lpItem
->pszText
);
2569 COMCTL32_Free(lpItem
);
2572 DPA_Destroy(hdpaSubItems
);
2576 /* reinitialize listview memory */
2577 bResult
= DPA_DeleteAllPtrs(infoPtr
->hdpaItems
);
2579 /* align items (set position of each item) */
2580 switch (lStyle
& LVS_TYPEMASK
)
2584 if (lStyle
& LVS_ALIGNLEFT
)
2586 LISTVIEW_AlignLeft(hwnd
);
2590 LISTVIEW_AlignTop(hwnd
);
2595 LISTVIEW_SetScroll(hwnd
, lStyle
);
2597 /* invalidate client area (optimization needed) */
2598 InvalidateRect(hwnd
, NULL
, TRUE
);
2606 * Removes a column from the listview control.
2609 * [I] HWND : window handle
2610 * [I] INT : column index
2616 static LRESULT
LISTVIEW_DeleteColumn(HWND hwnd
, INT nColumn
)
2618 LISTVIEW_INFO
*infoPtr
= (LISTVIEW_INFO
*)GetWindowLongA(hwnd
, 0);
2619 LONG lStyle
= GetWindowLongA(hwnd
, GWL_STYLE
);
2620 BOOL bResult
= FALSE
;
2622 if (Header_DeleteItem(infoPtr
->hwndHeader
, nColumn
) != FALSE
)
2624 bResult
= LISTVIEW_RemoveColumn(infoPtr
->hdpaItems
, nColumn
);
2626 /* reset scroll parameters */
2627 if ((lStyle
& LVS_TYPEMASK
) == LVS_REPORT
)
2629 LISTVIEW_SetViewInfo(hwnd
, lStyle
);
2630 LISTVIEW_SetScroll(hwnd
, lStyle
);
2633 /* refresh client area */
2634 InvalidateRect(hwnd
, NULL
, FALSE
);
2642 * Removes an item from the listview control.
2645 * [I] HWND : window handle
2646 * [I] INT : item index
2652 static LRESULT
LISTVIEW_DeleteItem(HWND hwnd
, INT nItem
)
2654 LISTVIEW_INFO
*infoPtr
= (LISTVIEW_INFO
*)GetWindowLongA(hwnd
, 0);
2655 LONG lStyle
= GetWindowLongA(hwnd
, GWL_STYLE
);
2656 LONG lCtrlId
= GetWindowLongA(hwnd
, GWL_ID
);
2658 BOOL bResult
= FALSE
;
2660 LISTVIEW_ITEM
*lpItem
;
2661 LISTVIEW_SUBITEM
*lpSubItem
;
2664 TRACE(listview
, "(hwnd=%x,nItem=%d)\n", hwnd
, nItem
);
2666 if ((nItem
>= 0) && (nItem
< GETITEMCOUNT(infoPtr
)))
2668 /* initialize memory */
2669 ZeroMemory(&nmlv
, sizeof(NMLISTVIEW
));
2671 hdpaSubItems
= (HDPA
)DPA_DeletePtr(infoPtr
->hdpaItems
, nItem
);
2672 if (hdpaSubItems
!= NULL
)
2674 for (i
= 1; i
< hdpaSubItems
->nItemCount
; i
++)
2676 lpSubItem
= (LISTVIEW_SUBITEM
*)DPA_GetPtr(hdpaSubItems
, i
);
2677 if (lpSubItem
!= NULL
)
2679 /* free item string */
2680 if ((lpSubItem
->pszText
!= NULL
) &&
2681 (lpSubItem
->pszText
!= LPSTR_TEXTCALLBACKA
))
2683 COMCTL32_Free(lpSubItem
->pszText
);
2687 COMCTL32_Free(lpSubItem
);
2691 lpItem
= (LISTVIEW_ITEM
*)DPA_GetPtr(hdpaSubItems
, 0);
2694 /* send LVN_DELETEITEM notification */
2695 nmlv
.hdr
.hwndFrom
= hwnd
;
2696 nmlv
.hdr
.idFrom
= lCtrlId
;
2697 nmlv
.hdr
.code
= LVN_DELETEITEM
;
2699 nmlv
.lParam
= lpItem
->lParam
;
2700 SendMessageA(GetParent(hwnd
), WM_NOTIFY
, (WPARAM
)lCtrlId
,
2703 /* free item string */
2704 if ((lpItem
->pszText
!= NULL
) &&
2705 (lpItem
->pszText
!= LPSTR_TEXTCALLBACKA
))
2707 COMCTL32_Free(lpItem
->pszText
);
2711 COMCTL32_Free(lpItem
);
2714 bResult
= DPA_Destroy(hdpaSubItems
);
2717 /* align items (set position of each item) */
2718 switch(lStyle
& LVS_TYPEMASK
)
2722 if (lStyle
& LVS_ALIGNLEFT
)
2724 LISTVIEW_AlignLeft(hwnd
);
2728 LISTVIEW_AlignTop(hwnd
);
2733 LISTVIEW_SetScroll(hwnd
, lStyle
);
2735 /* refresh client area */
2736 InvalidateRect(hwnd
, NULL
, TRUE
);
2742 /* LISTVIEW_EditLabel */
2746 * Ensures the specified item is visible, scrolling into view if necessary.
2749 * [I] HWND : window handle
2750 * [I] INT : item index
2751 * [I] BOOL : partially or entirely visible
2757 static BOOL
LISTVIEW_EnsureVisible(HWND hwnd
, INT nItem
, BOOL bPartial
)
2759 LISTVIEW_INFO
*infoPtr
= (LISTVIEW_INFO
*)GetWindowLongA(hwnd
, 0);
2760 LONG lStyle
= GetWindowLongA(hwnd
, GWL_STYLE
);
2761 INT nListHeight
= infoPtr
->rcList
.bottom
- infoPtr
->rcList
.top
;
2762 INT nListWidth
= infoPtr
->rcList
.right
- infoPtr
->rcList
.left
;
2763 INT nHScrollPos
= 0;
2764 INT nVScrollPos
= 0;
2765 INT nScrollPosHeight
= 0;
2766 INT nScrollPosWidth
= 0;
2768 BOOL bResult
= FALSE
;
2770 /* ALWAYS bPartial == FALSE, FOR NOW! */
2772 rcItem
.left
= LVIR_BOUNDS
;
2773 if (LISTVIEW_GetItemRect(hwnd
, nItem
, &rcItem
) != FALSE
)
2775 if (rcItem
.left
< infoPtr
->rcList
.left
)
2778 switch (LVS_TYPEMASK
& lStyle
)
2781 rcItem
.left
+= infoPtr
->rcList
.left
;
2782 nScrollPosWidth
= infoPtr
->nItemWidth
;
2787 nScrollPosWidth
= max(1, nListWidth
/ 10);
2788 rcItem
.left
+= infoPtr
->rcList
.left
;
2792 if (rcItem
.left
% nScrollPosWidth
== 0)
2794 nHScrollPos
= rcItem
.left
/ nScrollPosWidth
;
2798 nHScrollPos
= rcItem
.left
/ nScrollPosWidth
- 1;
2801 else if (rcItem
.right
> infoPtr
->rcList
.right
)
2804 switch (LVS_TYPEMASK
& lStyle
)
2807 rcItem
.right
-= infoPtr
->rcList
.right
;
2808 nScrollPosWidth
= infoPtr
->nItemWidth
;
2813 nScrollPosWidth
= max(1, nListWidth
/ 10);
2814 rcItem
.right
-= infoPtr
->rcList
.right
;
2818 if (rcItem
.right
% nScrollPosWidth
== 0)
2820 nHScrollPos
= rcItem
.right
/ nScrollPosWidth
;
2824 nHScrollPos
= rcItem
.right
/ nScrollPosWidth
+ 1;
2828 if (rcItem
.top
< infoPtr
->rcList
.top
)
2831 switch (LVS_TYPEMASK
& lStyle
)
2834 rcItem
.top
-= infoPtr
->rcList
.top
;
2835 nScrollPosHeight
= infoPtr
->nItemHeight
;
2840 nScrollPosHeight
= max(1, nListHeight
/ 10);
2841 rcItem
.top
+= infoPtr
->rcList
.top
;
2845 if (rcItem
.top
% nScrollPosHeight
== 0)
2847 nVScrollPos
= rcItem
.top
/ nScrollPosHeight
;
2851 nVScrollPos
= rcItem
.top
/ nScrollPosHeight
- 1;
2854 else if (rcItem
.bottom
> infoPtr
->rcList
.bottom
)
2856 switch (LVS_TYPEMASK
& lStyle
)
2859 rcItem
.bottom
-= infoPtr
->rcList
.bottom
;
2860 nScrollPosHeight
= infoPtr
->nItemHeight
;
2865 nScrollPosHeight
= max(1, nListHeight
/ 10);
2866 rcItem
.bottom
-= infoPtr
->rcList
.bottom
;
2870 if (rcItem
.bottom
% nScrollPosHeight
== 0)
2872 nVScrollPos
= rcItem
.bottom
/ nScrollPosHeight
;
2876 nVScrollPos
= rcItem
.bottom
/ nScrollPosHeight
+ 1;
2880 bResult
= LISTVIEW_ScrollView(hwnd
, nHScrollPos
, nVScrollPos
);
2888 * Searches for an item with specific characteristics.
2891 * [I] HWND : window handle
2892 * [I] INT : base item index
2893 * [I] LPLVFINDINFO : item information to look for
2896 * SUCCESS : index of item
2899 static LRESULT
LISTVIEW_FindItem(HWND hwnd
, INT nStart
,
2900 LPLVFINDINFO lpFindInfo
)
2902 FIXME (listview
, "empty stub!\n");
2909 * Retrieves the background color of the listview control.
2912 * [I] HWND : window handle
2915 * COLORREF associated with the background.
2917 static LRESULT
LISTVIEW_GetBkColor(HWND hwnd
)
2919 LISTVIEW_INFO
*infoPtr
= (LISTVIEW_INFO
*)GetWindowLongA(hwnd
, 0);
2921 return infoPtr
->clrBk
;
2926 * Retrieves the background image of the listview control.
2929 * [I] HWND : window handle
2930 * [O] LPLVMKBIMAGE : background image attributes
2936 /* static LRESULT LISTVIEW_GetBkImage(HWND hwnd, LPLVBKIMAGE lpBkImage) */
2938 /* FIXME (listview, "empty stub!\n"); */
2944 * Retrieves the callback mask.
2947 * [I] HWND : window handle
2952 static UINT
LISTVIEW_GetCallbackMask(HWND hwnd
)
2954 LISTVIEW_INFO
*infoPtr
= (LISTVIEW_INFO
*)GetWindowLongA(hwnd
, 0);
2956 return infoPtr
->uCallbackMask
;
2961 * Retrieves column attributes.
2964 * [I] HWND : window handle
2965 * [I] INT : column index
2966 * [IO] LPLVCOLUMNA : column information
2972 static LRESULT
LISTVIEW_GetColumnA(HWND hwnd
, INT nItem
,
2973 LPLVCOLUMNA lpColumn
)
2975 LISTVIEW_INFO
*infoPtr
= (LISTVIEW_INFO
*)GetWindowLongA(hwnd
, 0);
2977 BOOL bResult
= FALSE
;
2979 if (lpColumn
!= NULL
)
2981 /* initialize memory */
2982 ZeroMemory(&hdi
, sizeof(HDITEMA
));
2984 if (lpColumn
->mask
& LVCF_FMT
)
2986 hdi
.mask
|= HDI_FORMAT
;
2989 if (lpColumn
->mask
& LVCF_WIDTH
)
2991 hdi
.mask
|= HDI_WIDTH
;
2994 if (lpColumn
->mask
& LVCF_TEXT
)
2996 hdi
.mask
|= (HDI_TEXT
| HDI_FORMAT
);
2999 if (lpColumn
->mask
& LVCF_IMAGE
)
3001 hdi
.mask
|= HDI_IMAGE
;
3004 if (lpColumn
->mask
& LVCF_ORDER
)
3006 hdi
.mask
|= HDI_ORDER
;
3009 bResult
= Header_GetItemA(infoPtr
->hwndHeader
, nItem
, &hdi
);
3010 if (bResult
!= FALSE
)
3012 if (lpColumn
->mask
& LVCF_FMT
)
3016 if (hdi
.fmt
& HDF_LEFT
)
3018 lpColumn
->fmt
|= LVCFMT_LEFT
;
3020 else if (hdi
.fmt
& HDF_RIGHT
)
3022 lpColumn
->fmt
|= LVCFMT_RIGHT
;
3024 else if (hdi
.fmt
& HDF_CENTER
)
3026 lpColumn
->fmt
|= LVCFMT_CENTER
;
3029 if (hdi
.fmt
& HDF_IMAGE
)
3031 lpColumn
->fmt
|= LVCFMT_COL_HAS_IMAGES
;
3035 if (lpColumn
->mask
& LVCF_WIDTH
)
3037 lpColumn
->cx
= hdi
.cxy
;
3040 if ((lpColumn
->mask
& LVCF_TEXT
) && (lpColumn
->pszText
) && (hdi
.pszText
))
3042 lstrcpynA (lpColumn
->pszText
, hdi
.pszText
, lpColumn
->cchTextMax
);
3045 if (lpColumn
->mask
& LVCF_IMAGE
)
3047 lpColumn
->iImage
= hdi
.iImage
;
3050 if (lpColumn
->mask
& LVCF_ORDER
)
3052 lpColumn
->iOrder
= hdi
.iOrder
;
3060 /* LISTVIEW_GetColumnW */
3061 /* LISTVIEW_GetColumnOrderArray */
3065 * Retrieves the column width.
3068 * [I] HWND : window handle
3069 * [I] int : column index
3072 * SUCCESS : column width
3075 static LRESULT
LISTVIEW_GetColumnWidth(HWND hwnd
, INT nColumn
)
3077 LISTVIEW_INFO
*infoPtr
= (LISTVIEW_INFO
*)GetWindowLongA(hwnd
, 0);
3078 LONG lStyle
= GetWindowLongA(hwnd
, GWL_STYLE
);
3080 INT nColumnWidth
= 0;
3082 switch (LVS_TYPEMASK
& lStyle
)
3085 nColumnWidth
= infoPtr
->nItemWidth
;
3089 /* get column width from header */
3090 ZeroMemory(&hdi
, sizeof(HDITEMA
));
3091 hdi
.mask
= HDI_WIDTH
;
3092 if (Header_GetItemA(infoPtr
->hwndHeader
, nColumn
, &hdi
) != FALSE
)
3094 nColumnWidth
= hdi
.cxy
;
3099 return nColumnWidth
;
3104 * In list or report display mode, retrieves the number of items that can fit
3105 * vertically in the visible area. In icon or small icon display mode,
3106 * retrieves the total number of visible items.
3109 * [I] HWND : window handle
3112 * Number of fully visible items.
3114 static LRESULT
LISTVIEW_GetCountPerPage(HWND hwnd
)
3116 LISTVIEW_INFO
*infoPtr
= (LISTVIEW_INFO
*)GetWindowLongA(hwnd
, 0);
3117 LONG lStyle
= GetWindowLongA(hwnd
, GWL_STYLE
);
3120 switch (LVS_TYPEMASK
& lStyle
)
3123 if (infoPtr
->rcList
.right
/ infoPtr
->nItemWidth
)
3125 nItemCount
= infoPtr
->nCountPerRow
* infoPtr
->nCountPerColumn
;
3130 nItemCount
= infoPtr
->nCountPerColumn
;
3135 nItemCount
= GETITEMCOUNT(infoPtr
);
3142 /* LISTVIEW_GetEditControl */
3143 /* LISTVIEW_GetExtendedListViewStyle */
3147 * Retrieves the handle to the header control.
3150 * [I] HWND : window handle
3155 static LRESULT
LISTVIEW_GetHeader(HWND hwnd
)
3157 LISTVIEW_INFO
*infoPtr
= (LISTVIEW_INFO
*)GetWindowLongA(hwnd
, 0);
3159 return infoPtr
->hwndHeader
;
3162 /* LISTVIEW_GetHotCursor */
3163 /* LISTVIEW_GetHotItem */
3164 /* LISTVIEW_GetHoverTime */
3168 * Retrieves an image list handle.
3171 * [I] HWND : window handle
3172 * [I] INT : image list identifier
3175 * SUCCESS : image list handle
3178 static LRESULT
LISTVIEW_GetImageList(HWND hwnd
, INT nImageList
)
3180 LISTVIEW_INFO
*infoPtr
= (LISTVIEW_INFO
*)GetWindowLongA(hwnd
, 0);
3181 HIMAGELIST himl
= NULL
;
3186 himl
= infoPtr
->himlNormal
;
3189 himl
= infoPtr
->himlSmall
;
3192 himl
= infoPtr
->himlState
;
3196 return (LRESULT
)himl
;
3199 /* LISTVIEW_GetISearchString */
3203 * Retrieves item attributes.
3206 * [I] HWND : window handle
3207 * [IO] LPLVITEMA : item info
3213 static LRESULT
LISTVIEW_GetItemA(HWND hwnd
, LPLVITEMA lpLVItem
)
3215 LISTVIEW_INFO
*infoPtr
= (LISTVIEW_INFO
*)GetWindowLongA(hwnd
, 0);
3216 LISTVIEW_ITEM
*lpItem
;
3217 LISTVIEW_SUBITEM
*lpSubItem
;
3219 BOOL bResult
= FALSE
;
3221 TRACE(listview
, "(hwnd=%x,lpLVItem=%p)\n", hwnd
, lpLVItem
);
3223 if (lpLVItem
!= NULL
)
3225 if ((lpLVItem
->iItem
>= 0) && (lpLVItem
->iItem
< GETITEMCOUNT(infoPtr
)))
3227 hdpaSubItems
= (HDPA
)DPA_GetPtr(infoPtr
->hdpaItems
, lpLVItem
->iItem
);
3228 if (hdpaSubItems
!= NULL
)
3230 if (lpLVItem
->iSubItem
== 0)
3232 lpItem
= (LISTVIEW_ITEM
*)DPA_GetPtr(hdpaSubItems
, 0);
3237 /* retrieve valid data */
3238 if (lpLVItem
->mask
& LVIF_STATE
)
3240 lpLVItem
->state
= lpItem
->state
& lpLVItem
->stateMask
;
3243 if (lpLVItem
->mask
& LVIF_TEXT
)
3245 if (lpItem
->pszText
== LPSTR_TEXTCALLBACKA
)
3247 lpLVItem
->pszText
= LPSTR_TEXTCALLBACKA
;
3251 bResult
= Str_GetPtrA(lpItem
->pszText
, lpLVItem
->pszText
,
3252 lpLVItem
->cchTextMax
);
3256 if (lpLVItem
->mask
& LVIF_IMAGE
)
3258 lpLVItem
->iImage
= lpItem
->iImage
;
3261 if (lpLVItem
->mask
& LVIF_PARAM
)
3263 lpLVItem
->lParam
= lpItem
->lParam
;
3266 if (lpLVItem
->mask
& LVIF_INDENT
)
3268 lpLVItem
->iIndent
= lpItem
->iIndent
;
3274 lpSubItem
= (LISTVIEW_SUBITEM
*)DPA_GetPtr(hdpaSubItems
,
3275 lpLVItem
->iSubItem
);
3276 if (lpSubItem
!= NULL
)
3280 if (lpLVItem
->mask
& LVIF_TEXT
)
3282 if (lpSubItem
->pszText
== LPSTR_TEXTCALLBACKA
)
3284 lpLVItem
->pszText
= LPSTR_TEXTCALLBACKA
;
3288 bResult
= Str_GetPtrA(lpSubItem
->pszText
, lpLVItem
->pszText
,
3289 lpLVItem
->cchTextMax
);
3293 if (lpLVItem
->mask
& LVIF_IMAGE
)
3295 lpLVItem
->iImage
= lpSubItem
->iImage
;
3306 /* LISTVIEW_GetItemW */
3307 /* LISTVIEW_GetHotCursor */
3308 /* LISTVIEW_GetHotItem */
3309 /* LISTVIEW_GetHoverTime> */
3313 * Retrieves the number of items in the listview control.
3316 * [I] HWND : window handle
3321 static LRESULT
LISTVIEW_GetItemCount(HWND hwnd
)
3323 LISTVIEW_INFO
*infoPtr
= (LISTVIEW_INFO
*)GetWindowLongA(hwnd
, 0);
3325 return GETITEMCOUNT(infoPtr
);
3330 * Retrieves the position (upper-left) of the listview control item.
3333 * [I] HWND : window handle
3334 * [I] INT : item index
3335 * [O] LPPOINT : coordinate information
3341 static BOOL
LISTVIEW_GetItemPosition(HWND hwnd
, INT nItem
,
3342 LPPOINT lpptPosition
)
3344 LISTVIEW_INFO
*infoPtr
= (LISTVIEW_INFO
*)GetWindowLongA(hwnd
, 0);
3345 LONG lStyle
= GetWindowLongA(hwnd
, GWL_STYLE
);
3346 BOOL bResult
= FALSE
;
3348 LISTVIEW_ITEM
*lpItem
;
3351 TRACE(listview
, "(hwnd=%x,nItem=%d,lpptPosition=%p)\n", hwnd
, nItem
,
3354 if ((nItem
>= 0) && (nItem
< GETITEMCOUNT(infoPtr
)) &&
3355 (lpptPosition
!= NULL
))
3357 switch (LVS_TYPEMASK
& lStyle
)
3361 nItem
= nItem
- ListView_GetTopIndex(hwnd
);
3364 nRow
= nItem
% infoPtr
->nCountPerColumn
;
3367 lpptPosition
->x
= (nItem
/ infoPtr
->nCountPerColumn
*
3368 infoPtr
->nItemWidth
);
3369 lpptPosition
->y
= 0;
3373 lpptPosition
->x
= ((nItem
/ infoPtr
->nCountPerColumn
- 1) *
3374 infoPtr
->nItemWidth
);
3375 lpptPosition
->y
= ((nRow
+ infoPtr
->nCountPerColumn
) *
3376 infoPtr
->nItemHeight
);
3381 lpptPosition
->x
= (nItem
/ infoPtr
->nCountPerColumn
*
3382 infoPtr
->nItemWidth
);
3383 lpptPosition
->y
= (nItem
% infoPtr
->nCountPerColumn
*
3384 infoPtr
->nItemHeight
);
3390 lpptPosition
->x
= REPORT_MARGINX
;
3391 lpptPosition
->y
= ((nItem
- ListView_GetTopIndex(hwnd
)) *
3392 infoPtr
->nItemHeight
) + infoPtr
->rcList
.top
;
3397 hdpaSubItems
= (HDPA
)DPA_GetPtr(infoPtr
->hdpaItems
, nItem
);
3398 if (hdpaSubItems
!= NULL
)
3400 lpItem
= (LISTVIEW_ITEM
*)DPA_GetPtr(hdpaSubItems
, 0);
3404 lpptPosition
->x
= lpItem
->ptPosition
.x
;
3405 lpptPosition
->y
= lpItem
->ptPosition
.y
;
3417 * Retrieves the bounding rectangle for a listview control item.
3420 * [I] HWND : window handle
3421 * [I] INT : item index
3422 * [IO] LPRECT : bounding rectangle coordinates
3428 static LRESULT
LISTVIEW_GetItemRect(HWND hwnd
, INT nItem
, LPRECT lprc
)
3430 LISTVIEW_INFO
*infoPtr
= (LISTVIEW_INFO
*)GetWindowLongA(hwnd
, 0);
3431 LONG lStyle
= GetWindowLongA(hwnd
, GWL_STYLE
);
3432 BOOL bResult
= FALSE
;
3441 TRACE(listview
, "(hwnd=%x,nItem=%d,lprc=%p)\n", hwnd
, nItem
, lprc
);
3443 if ((nItem
>= 0) && (nItem
< GETITEMCOUNT(infoPtr
)) && (lprc
!= NULL
))
3445 if (ListView_GetItemPosition(hwnd
, nItem
, &ptItem
) != FALSE
)
3450 switch (LVS_TYPEMASK
& lStyle
)
3453 if (infoPtr
->himlNormal
!= NULL
)
3455 if (LISTVIEW_GetOrigin(hwnd
, &ptOrigin
) != FALSE
)
3458 lprc
->left
= ptItem
.x
+ ptOrigin
.x
;
3459 lprc
->top
= ptItem
.y
+ ptOrigin
.y
;
3460 lprc
->right
= lprc
->left
+ infoPtr
->iconSize
.cx
;
3461 lprc
->bottom
= (lprc
->top
+ infoPtr
->iconSize
.cy
+
3462 ICON_BOTTOM_PADDING
+ ICON_TOP_PADDING
);
3468 if (LISTVIEW_GetOrigin(hwnd
, &ptOrigin
) != FALSE
)
3471 lprc
->left
= ptItem
.x
+ ptOrigin
.x
;
3472 lprc
->top
= ptItem
.y
+ ptOrigin
.y
;
3473 lprc
->bottom
= lprc
->top
+ infoPtr
->nItemHeight
;
3475 if (infoPtr
->himlState
!= NULL
)
3477 lprc
->left
+= infoPtr
->iconSize
.cx
;
3480 if (infoPtr
->himlSmall
!= NULL
)
3482 lprc
->right
= lprc
->left
+ infoPtr
->iconSize
.cx
;
3486 lprc
->right
= lprc
->left
;
3494 lprc
->left
= ptItem
.x
;
3495 lprc
->top
= ptItem
.y
;
3496 lprc
->bottom
= lprc
->top
+ infoPtr
->nItemHeight
;
3498 if (infoPtr
->himlState
!= NULL
)
3500 lprc
->left
+= infoPtr
->iconSize
.cx
;
3503 if (infoPtr
->himlSmall
!= NULL
)
3505 lprc
->right
= lprc
->left
+ infoPtr
->iconSize
.cx
;
3509 lprc
->right
= lprc
->left
;
3516 switch (LVS_TYPEMASK
& lStyle
)
3519 if (infoPtr
->himlNormal
!= NULL
)
3521 if (LISTVIEW_GetOrigin(hwnd
, &ptOrigin
) != FALSE
)
3524 lprc
->left
= ptItem
.x
+ ptOrigin
.x
;
3525 lprc
->top
= (ptItem
.y
+ ptOrigin
.y
+ infoPtr
->iconSize
.cy
+
3526 ICON_BOTTOM_PADDING
+ ICON_TOP_PADDING
);
3527 nLabelWidth
= LISTVIEW_GetLabelWidth(hwnd
, nItem
);
3528 if (infoPtr
->iconSpacing
.cx
- nLabelWidth
> 1)
3530 lprc
->left
+= (infoPtr
->iconSpacing
.cx
- nLabelWidth
) / 2;
3531 lprc
->right
= lprc
->left
+ nLabelWidth
;
3536 lprc
->right
= lprc
->left
+ infoPtr
->iconSpacing
.cx
- 1;
3540 hOldFont
= SelectObject(hdc
, infoPtr
->hFont
);
3541 GetTextMetricsA(hdc
, &tm
);
3542 lprc
->bottom
= lprc
->top
+ tm
.tmHeight
+ HEIGHT_PADDING
;
3543 SelectObject(hdc
, hOldFont
);
3544 ReleaseDC(hwnd
, hdc
);
3550 if (LISTVIEW_GetOrigin(hwnd
, &ptOrigin
) != FALSE
)
3553 nMaxWidth
= lprc
->left
= ptItem
.x
+ ptOrigin
.x
;
3554 lprc
->top
= ptItem
.y
+ ptOrigin
.y
;
3555 lprc
->bottom
= lprc
->top
+ infoPtr
->nItemHeight
;
3557 if (infoPtr
->himlState
!= NULL
)
3559 lprc
->left
+= infoPtr
->iconSize
.cx
;
3562 if (infoPtr
->himlSmall
!= NULL
)
3564 lprc
->left
+= infoPtr
->iconSize
.cx
;
3567 nLabelWidth
= LISTVIEW_GetLabelWidth(hwnd
, nItem
);
3568 if (lprc
->left
+ nLabelWidth
< nMaxWidth
+ infoPtr
->nItemWidth
)
3570 lprc
->right
= lprc
->left
+ nLabelWidth
;
3574 lprc
->right
= nMaxWidth
+ infoPtr
->nItemWidth
;
3582 lprc
->left
= ptItem
.x
;
3583 lprc
->top
= ptItem
.y
;
3584 lprc
->bottom
= lprc
->top
+ infoPtr
->nItemHeight
;
3586 if (infoPtr
->himlState
!= NULL
)
3588 lprc
->left
+= infoPtr
->iconSize
.cx
;
3591 if (infoPtr
->himlSmall
!= NULL
)
3593 lprc
->left
+= infoPtr
->iconSize
.cx
;
3596 lprc
->right
= lprc
->left
+ LISTVIEW_GetLabelWidth(hwnd
, nItem
);
3602 switch (LVS_TYPEMASK
& lStyle
)
3605 if (infoPtr
->himlNormal
!= NULL
)
3607 if (LISTVIEW_GetOrigin(hwnd
, &ptOrigin
) != FALSE
)
3610 lprc
->left
= ptItem
.x
+ ptOrigin
.x
;
3611 lprc
->top
= ptItem
.y
+ ptOrigin
.y
;
3612 lprc
->right
= lprc
->left
+ infoPtr
->iconSpacing
.cx
;
3613 lprc
->bottom
= lprc
->top
+ infoPtr
->iconSpacing
.cy
;
3619 if (LISTVIEW_GetOrigin(hwnd
, &ptOrigin
) != FALSE
)
3622 lprc
->left
= ptItem
.x
+ptOrigin
.x
;
3623 lprc
->right
= lprc
->left
;
3624 lprc
->top
= ptItem
.y
+ ptOrigin
.y
;
3625 lprc
->bottom
= lprc
->top
+ infoPtr
->nItemHeight
;
3627 if (infoPtr
->himlState
!= NULL
)
3629 lprc
->right
+= infoPtr
->iconSize
.cx
;
3632 if (infoPtr
->himlSmall
!= NULL
)
3634 lprc
->right
+= infoPtr
->iconSize
.cx
;
3637 lprc
->right
+= LISTVIEW_GetLabelWidth(hwnd
, nItem
);
3644 lprc
->left
= ptItem
.x
;
3645 lprc
->right
= lprc
->left
;
3646 lprc
->top
= ptItem
.y
;
3647 lprc
->bottom
= lprc
->top
+ infoPtr
->nItemHeight
;
3649 if (infoPtr
->himlState
!= NULL
)
3651 lprc
->right
+= infoPtr
->iconSize
.cx
;
3654 if (infoPtr
->himlSmall
!= NULL
)
3656 lprc
->right
+= infoPtr
->iconSize
.cx
;
3659 lprc
->right
+= LISTVIEW_GetLabelWidth(hwnd
, nItem
);
3664 case LVIR_SELECTBOUNDS
:
3665 switch (LVS_TYPEMASK
& lStyle
)
3668 if (infoPtr
->himlNormal
!= NULL
)
3670 if (LISTVIEW_GetOrigin(hwnd
, &ptOrigin
) != FALSE
)
3673 lprc
->left
= ptItem
.x
+ ptOrigin
.x
;
3674 lprc
->top
= ptItem
.y
+ ptOrigin
.y
;
3675 lprc
->right
= lprc
->left
+ infoPtr
->iconSpacing
.cx
;
3676 lprc
->bottom
= lprc
->top
+ infoPtr
->iconSpacing
.cy
;
3682 if (LISTVIEW_GetOrigin(hwnd
, &ptOrigin
) != FALSE
)
3685 lprc
->left
= ptItem
.x
+ ptOrigin
.x
;
3686 lprc
->top
= ptItem
.y
+ ptOrigin
.y
;
3687 lprc
->bottom
= lprc
->top
+ infoPtr
->nItemHeight
;
3689 if (infoPtr
->himlState
!= NULL
)
3691 lprc
->left
+= infoPtr
->iconSize
.cx
;
3694 lprc
->right
= lprc
->left
;
3696 if (infoPtr
->himlSmall
!= NULL
)
3698 lprc
->right
+= infoPtr
->iconSize
.cx
;
3701 lprc
->right
+= LISTVIEW_GetLabelWidth(hwnd
, nItem
);
3708 lprc
->left
= ptItem
.x
;
3709 lprc
->top
= ptItem
.y
;
3710 lprc
->bottom
= lprc
->top
+ infoPtr
->nItemHeight
;
3712 if (infoPtr
->himlState
!= NULL
)
3714 lprc
->left
+= infoPtr
->iconSize
.cx
;
3717 lprc
->right
= lprc
->left
;
3719 if (infoPtr
->himlSmall
!= NULL
)
3721 lprc
->right
+= infoPtr
->iconSize
.cx
;
3724 lprc
->right
+= LISTVIEW_GetLabelWidth(hwnd
, nItem
);
3737 * Retrieves the width of a label.
3740 * [I] HWND : window handle
3743 * SUCCESS : string width (in pixels)
3747 static INT
LISTVIEW_GetLabelWidth(HWND hwnd
, INT nItem
)
3749 LISTVIEW_INFO
*infoPtr
= (LISTVIEW_INFO
*)GetWindowLongA(hwnd
, 0);
3750 LISTVIEW_ITEM
*lpItem
;
3752 INT nLabelWidth
= 0;
3754 TRACE(listview
, "(hwnd=%x,nItem=%d)\n", hwnd
, nItem
);
3756 hdpaSubItems
= (HDPA
)DPA_GetPtr(infoPtr
->hdpaItems
, nItem
);
3757 if (hdpaSubItems
!= NULL
)
3759 lpItem
= (LISTVIEW_ITEM
*)DPA_GetPtr(hdpaSubItems
, 0);
3762 CHAR szDispText
[DISP_TEXT_SIZE
];
3763 LPSTR pszDispText
= NULL
;
3764 pszDispText
= szDispText
;
3765 LISTVIEW_GetItemDispInfo(hwnd
, nItem
, lpItem
, NULL
, NULL
, &pszDispText
,
3767 nLabelWidth
= ListView_GetStringWidthA(hwnd
, pszDispText
);
3776 * Retrieves the spacing between listview control items.
3779 * [I] HWND : window handle
3780 * [I] BOOL : flag for small or large icon
3783 * Horizontal + vertical spacing
3785 static LRESULT
LISTVIEW_GetItemSpacing(HWND hwnd
, BOOL bSmall
)
3787 LISTVIEW_INFO
*infoPtr
= (LISTVIEW_INFO
*)GetWindowLongA(hwnd
, 0);
3790 if (bSmall
== FALSE
)
3792 lResult
= MAKELONG(infoPtr
->iconSpacing
.cx
, infoPtr
->iconSpacing
.cy
);
3796 /* TODO: need to store width of smallicon item */
3797 lResult
= MAKELONG(0, infoPtr
->nItemHeight
);
3805 * Retrieves the state of a listview control item.
3808 * [I] HWND : window handle
3809 * [I] INT : item index
3810 * [I] UINT : state mask
3813 * State specified by the mask.
3815 static LRESULT
LISTVIEW_GetItemState(HWND hwnd
, INT nItem
, UINT uMask
)
3817 LISTVIEW_INFO
*infoPtr
= (LISTVIEW_INFO
*)GetWindowLongA(hwnd
, 0);
3821 if ((nItem
>= 0) && (nItem
< GETITEMCOUNT(infoPtr
)))
3823 ZeroMemory(&lvItem
, sizeof(LVITEMA
));
3824 lvItem
.iItem
= nItem
;
3825 lvItem
.stateMask
= uMask
;
3826 lvItem
.mask
= LVIF_STATE
;
3827 if (ListView_GetItemA(hwnd
, &lvItem
) != FALSE
)
3829 uState
= lvItem
.state
;
3838 * Retrieves the text of a listview control item or subitem.
3841 * [I] HWND : window handle
3842 * [I] INT : item index
3843 * [IO] LPLVITEMA : item information
3848 static LRESULT
LISTVIEW_GetItemTextA(HWND hwnd
, INT nItem
, LPLVITEMA lpLVItem
)
3850 LISTVIEW_INFO
*infoPtr
= (LISTVIEW_INFO
*)GetWindowLongA(hwnd
, 0);
3851 LISTVIEW_ITEM
*lpItem
;
3852 LISTVIEW_SUBITEM
*lpSubItem
;
3856 if (lpLVItem
!= NULL
)
3858 if ((nItem
>= 0) && (nItem
< GETITEMCOUNT(infoPtr
)))
3860 hdpaSubItems
= (HDPA
)DPA_GetPtr(infoPtr
->hdpaItems
, lpLVItem
->iItem
);
3861 if (hdpaSubItems
!= NULL
)
3863 if (lpLVItem
->iSubItem
== 0)
3865 lpItem
= (LISTVIEW_ITEM
*)DPA_GetPtr(hdpaSubItems
, 0);
3868 if (lpLVItem
->mask
& LVIF_TEXT
)
3870 if (lpItem
->pszText
== LPSTR_TEXTCALLBACKA
)
3872 lpLVItem
->pszText
= LPSTR_TEXTCALLBACKA
;
3876 nLength
= Str_GetPtrA(lpItem
->pszText
, lpLVItem
->pszText
,
3877 lpLVItem
->cchTextMax
);
3884 lpSubItem
= (LISTVIEW_SUBITEM
*)DPA_GetPtr(hdpaSubItems
,
3885 lpLVItem
->iSubItem
);
3886 if (lpSubItem
!= NULL
)
3888 if (lpLVItem
->mask
& LVIF_TEXT
)
3890 if (lpSubItem
->pszText
== LPSTR_TEXTCALLBACKA
)
3892 lpLVItem
->pszText
= LPSTR_TEXTCALLBACKA
;
3896 nLength
= Str_GetPtrA(lpSubItem
->pszText
, lpLVItem
->pszText
,
3897 lpLVItem
->cchTextMax
);
3911 * Searches for an item based on properties + relationships.
3914 * [I] HWND : window handle
3915 * [I] INT : item index
3916 * [I] UINT : relationship flag
3919 * SUCCESS : item index
3922 static LRESULT
LISTVIEW_GetNextItem(HWND hwnd
, INT nItem
, UINT uFlags
)
3924 FIXME (listview
, "empty stub!\n");
3929 /* LISTVIEW_GetNumberOfWorkAreas */
3933 * Retrieves the origin coordinates when in icon or small icon display mode.
3936 * [I] HWND : window handle
3937 * [O] LPPOINT : coordinate information
3943 static LRESULT
LISTVIEW_GetOrigin(HWND hwnd
, LPPOINT lpptOrigin
)
3945 LISTVIEW_INFO
*infoPtr
= (LISTVIEW_INFO
*)GetWindowLongA(hwnd
, 0);
3946 LONG lStyle
= GetWindowLongA(hwnd
, GWL_STYLE
);
3947 INT nListWidth
= infoPtr
->rcList
.right
- infoPtr
->rcList
.left
;
3948 INT nListHeight
= infoPtr
->rcList
.bottom
- infoPtr
->rcList
.top
;
3949 BOOL bResult
= FALSE
;
3951 TRACE(listview
, "(hwnd=%x,lpptOrigin=%p)\n", hwnd
, lpptOrigin
);
3953 switch (LVS_TYPEMASK
& lStyle
)
3957 if ((lStyle
& WS_HSCROLL
) != 0)
3959 lpptOrigin
->x
= -GetScrollPos(hwnd
, SB_HORZ
) * nListWidth
/ 10;
3966 if ((lStyle
& WS_VSCROLL
) != 0)
3968 lpptOrigin
->y
= -GetScrollPos(hwnd
, SB_VERT
) * nListHeight
/ 10;
3984 * Retrieves the number of items that are marked as selected.
3987 * [I] HWND : window handle
3990 * Number of items selected.
3992 static LRESULT
LISTVIEW_GetSelectedCount(HWND hwnd
)
3994 LISTVIEW_INFO
*infoPtr
= (LISTVIEW_INFO
*)GetWindowLongA(hwnd
, 0);
3995 INT nSelectedCount
= 0;
3998 for (i
= 0; i
< GETITEMCOUNT(infoPtr
); i
++)
4000 if (ListView_GetItemState(hwnd
, i
, LVIS_SELECTED
) & LVIS_SELECTED
)
4006 return nSelectedCount
;
4011 * Retrieves item index that marks the start of a multiple selection.
4014 * [I] HWND : window handle
4017 * Index number or -1 if there is no selection mark.
4019 static LRESULT
LISTVIEW_GetSelectionMark(HWND hwnd
)
4021 LISTVIEW_INFO
*infoPtr
= (LISTVIEW_INFO
*)GetWindowLongA(hwnd
, 0);
4023 return infoPtr
->nSelectionMark
;
4028 * Retrieves the width of a string.
4031 * [I] HWND : window handle
4034 * SUCCESS : string width (in pixels)
4037 static LRESULT
LISTVIEW_GetStringWidthA(HWND hwnd
, LPCSTR lpszText
)
4039 LISTVIEW_INFO
*infoPtr
= (LISTVIEW_INFO
*)GetWindowLongA(hwnd
, 0);
4040 HFONT hFont
, hOldFont
;
4044 ZeroMemory(&stringSize
, sizeof(SIZE
));
4045 if (lpszText
!= NULL
)
4047 hFont
= infoPtr
->hFont
? infoPtr
->hFont
: infoPtr
->hDefaultFont
;
4049 hOldFont
= SelectObject(hdc
, hFont
);
4050 GetTextExtentPointA(hdc
, lpszText
, lstrlenA(lpszText
), &stringSize
);
4051 SelectObject(hdc
, hOldFont
);
4052 ReleaseDC(hwnd
, hdc
);
4055 return stringSize
.cx
;
4060 * Retrieves the text backgound color.
4063 * [I] HWND : window handle
4066 * COLORREF associated with the the background.
4068 static LRESULT
LISTVIEW_GetTextBkColor(HWND hwnd
)
4070 LISTVIEW_INFO
*infoPtr
= (LISTVIEW_INFO
*)GetWindowLongA(hwnd
, 0);
4072 return infoPtr
->clrTextBk
;
4077 * Retrieves the text color.
4080 * [I] HWND : window handle
4083 * COLORREF associated with the text.
4085 static LRESULT
LISTVIEW_GetTextColor(HWND hwnd
)
4087 LISTVIEW_INFO
*infoPtr
= (LISTVIEW_INFO
*)GetWindowLongA(hwnd
, 0);
4089 return infoPtr
->clrText
;
4094 * Set the bounding rectangle of all the items.
4097 * [I] HWND : window handle
4098 * [I] LPRECT : bounding rectangle
4104 static LRESULT
LISTVIEW_SetViewRect(HWND hwnd
, LPRECT lprcView
)
4106 LISTVIEW_INFO
*infoPtr
= (LISTVIEW_INFO
*)GetWindowLongA(hwnd
, 0);
4107 LONG lStyle
= GetWindowLongA(hwnd
, GWL_STYLE
);
4108 BOOL bResult
= FALSE
;
4110 TRACE(listview
, "(hwnd=%x,lprcView->left=%d,lprcView->top=%d,lprcView->right=%d,lprcView->bottom=%d)\n", hwnd
, lprcView
->left
, lprcView
->top
, lprcView
->right
, lprcView
->bottom
);
4112 if (lprcView
!= NULL
)
4114 switch (lStyle
& LVS_TYPEMASK
)
4119 infoPtr
->rcView
.left
= lprcView
->left
;
4120 infoPtr
->rcView
.top
= lprcView
->top
;
4121 infoPtr
->rcView
.right
= lprcView
->right
;
4122 infoPtr
->rcView
.bottom
= lprcView
->bottom
;
4132 * Retrieves the bounding rectangle of all the items.
4135 * [I] HWND : window handle
4136 * [O] LPRECT : bounding rectangle
4142 static LRESULT
LISTVIEW_GetViewRect(HWND hwnd
, LPRECT lprcView
)
4144 LISTVIEW_INFO
*infoPtr
= (LISTVIEW_INFO
*)GetWindowLongA(hwnd
, 0);
4145 BOOL bResult
= FALSE
;
4148 TRACE(listview
, "(hwnd=%x,lprcView=%p)\n", hwnd
, lprcView
);
4150 if (lprcView
!= NULL
)
4152 bResult
= LISTVIEW_GetOrigin(hwnd
, &ptOrigin
);
4153 if (bResult
!= FALSE
)
4155 lprcView
->left
= infoPtr
->rcView
.left
+ ptOrigin
.x
;
4156 lprcView
->top
= infoPtr
->rcView
.top
+ ptOrigin
.y
;
4157 lprcView
->right
= infoPtr
->rcView
.right
+ ptOrigin
.x
;
4158 lprcView
->bottom
= infoPtr
->rcView
.bottom
+ ptOrigin
.y
;
4161 TRACE(listview
, "(lprcView->left=%d,lprcView->top=%d,lprcView->right=%d,lprcView->bottom=%d)\n", lprcView
->left
, lprcView
->top
, lprcView
->right
, lprcView
->bottom
);
4170 * Determines which section of the item was selected (if any).
4173 * [I] HWND : window handle
4174 * [IO] LPLVHITTESTINFO : hit test information
4177 * SUCCESS : item index
4180 static INT
LISTVIEW_HitTestItem(HWND hwnd
, LPLVHITTESTINFO lpHitTestInfo
)
4182 LISTVIEW_INFO
*infoPtr
= (LISTVIEW_INFO
*)GetWindowLongA(hwnd
, 0);
4186 for (i
= 0; i
< GETITEMCOUNT(infoPtr
); i
++)
4188 rcItem
.left
= LVIR_BOUNDS
;
4189 if (LISTVIEW_GetItemRect(hwnd
, i
, &rcItem
) != FALSE
)
4191 rcItem
.left
= LVIR_ICON
;
4192 if (LISTVIEW_GetItemRect(hwnd
, i
, &rcItem
) != FALSE
)
4194 if ((lpHitTestInfo
->pt
.x
>= rcItem
.left
) &&
4195 (lpHitTestInfo
->pt
.x
<= rcItem
.right
) &&
4196 (lpHitTestInfo
->pt
.y
>= rcItem
.top
) &&
4197 (lpHitTestInfo
->pt
.y
<= rcItem
.bottom
))
4199 lpHitTestInfo
->flags
= LVHT_ONITEMICON
| LVHT_ONITEM
;
4200 lpHitTestInfo
->iItem
= i
;
4201 lpHitTestInfo
->iSubItem
= 0;
4206 rcItem
.left
= LVIR_LABEL
;
4207 if (LISTVIEW_GetItemRect(hwnd
, i
, &rcItem
) != FALSE
)
4209 if ((lpHitTestInfo
->pt
.x
>= rcItem
.left
) &&
4210 (lpHitTestInfo
->pt
.x
<= rcItem
.right
) &&
4211 (lpHitTestInfo
->pt
.y
>= rcItem
.top
) &&
4212 (lpHitTestInfo
->pt
.y
<= rcItem
.bottom
))
4214 lpHitTestInfo
->flags
= LVHT_ONITEMLABEL
| LVHT_ONITEM
;
4215 lpHitTestInfo
->iItem
= i
;
4216 lpHitTestInfo
->iSubItem
= 0;
4221 lpHitTestInfo
->flags
= LVHT_ONITEMSTATEICON
| LVHT_ONITEM
;
4222 lpHitTestInfo
->iItem
= i
;
4223 lpHitTestInfo
->iSubItem
= 0;
4228 lpHitTestInfo
->flags
= LVHT_NOWHERE
;
4235 * Determines wich listview item is located at the specified position.
4238 * [I] HWND : window handle
4239 * [IO} LPLVHITTESTINFO : hit test information
4242 * SUCCESS : item index
4245 static LRESULT
LISTVIEW_HitTest(HWND hwnd
, LPLVHITTESTINFO lpHitTestInfo
)
4247 LISTVIEW_INFO
*infoPtr
= (LISTVIEW_INFO
*)GetWindowLongA(hwnd
, 0);
4250 lpHitTestInfo
->flags
= 0;
4251 if (infoPtr
->rcList
.left
> lpHitTestInfo
->pt
.x
)
4253 lpHitTestInfo
->flags
= LVHT_TOLEFT
;
4255 else if (infoPtr
->rcList
.right
< lpHitTestInfo
->pt
.x
)
4257 lpHitTestInfo
->flags
= LVHT_TORIGHT
;
4260 if (infoPtr
->rcList
.top
> lpHitTestInfo
->pt
.y
)
4262 lpHitTestInfo
->flags
|= LVHT_ABOVE
;
4264 else if (infoPtr
->rcList
.bottom
< lpHitTestInfo
->pt
.y
)
4266 lpHitTestInfo
->flags
|= LVHT_BELOW
;
4269 if (lpHitTestInfo
->flags
== 0)
4271 nItem
= LISTVIEW_HitTestItem(hwnd
, lpHitTestInfo
);
4279 * Inserts a new column.
4282 * [I] HWND : window handle
4283 * [I] INT : column index
4284 * [I] LPLVCOLUMNA : column information
4287 * SUCCESS : new column index
4290 static LRESULT
LISTVIEW_InsertColumnA(HWND hwnd
, INT nColumn
,
4291 LPLVCOLUMNA lpColumn
)
4293 LISTVIEW_INFO
*infoPtr
= (LISTVIEW_INFO
*)GetWindowLongA(hwnd
, 0);
4294 LONG lStyle
= GetWindowLongA(hwnd
, GWL_STYLE
);
4296 INT nNewColumn
= -1;
4298 TRACE(listview
,"(hwnd=%x,nColumn=%d,lpColumn=%p)\n",hwnd
, nColumn
, lpColumn
);
4300 if (lpColumn
!= NULL
)
4302 /* initialize memory */
4303 ZeroMemory(&hdi
, sizeof(HDITEMA
));
4305 if (lpColumn
->mask
& LVCF_FMT
)
4307 /* format member is valid */
4308 hdi
.mask
|= HDI_FORMAT
;
4310 /* set text alignment (leftmost column must be left-aligned) */
4313 hdi
.fmt
|= HDF_LEFT
;
4317 if (lpColumn
->fmt
& LVCFMT_LEFT
)
4319 hdi
.fmt
|= HDF_LEFT
;
4321 else if (lpColumn
->fmt
& LVCFMT_RIGHT
)
4323 hdi
.fmt
|= HDF_RIGHT
;
4325 else if (lpColumn
->fmt
& LVCFMT_CENTER
)
4327 hdi
.fmt
|= HDF_CENTER
;
4331 if (lpColumn
->fmt
& LVCFMT_BITMAP_ON_RIGHT
)
4333 hdi
.fmt
|= HDF_BITMAP_ON_RIGHT
;
4337 if (lpColumn
->fmt
& LVCFMT_COL_HAS_IMAGES
)
4342 if (lpColumn
->fmt
& LVCFMT_IMAGE
)
4344 hdi
.fmt
|= HDF_IMAGE
;
4345 hdi
.iImage
= I_IMAGECALLBACK
;
4349 if (lpColumn
->mask
& LVCF_WIDTH
)
4351 hdi
.mask
|= HDI_WIDTH
;
4352 hdi
.cxy
= lpColumn
->cx
;
4355 if (lpColumn
->mask
& LVCF_TEXT
)
4357 hdi
.mask
|= HDI_TEXT
| HDI_FORMAT
;
4358 hdi
.pszText
= lpColumn
->pszText
;
4359 hdi
.cchTextMax
= lstrlenA(lpColumn
->pszText
);
4360 hdi
.fmt
|= HDF_STRING
;
4363 if (lpColumn
->mask
& LVCF_IMAGE
)
4365 hdi
.mask
|= HDI_IMAGE
;
4366 hdi
.iImage
= lpColumn
->iImage
;
4369 if (lpColumn
->mask
& LVCF_ORDER
)
4371 hdi
.mask
|= HDI_ORDER
;
4372 hdi
.iOrder
= lpColumn
->iOrder
;
4375 /* insert item in header control */
4376 nNewColumn
= SendMessageA(infoPtr
->hwndHeader
, HDM_INSERTITEMA
,
4377 (WPARAM
)nColumn
, (LPARAM
)&hdi
);
4379 LISTVIEW_SetScroll(hwnd
, lStyle
);
4380 InvalidateRect(hwnd
, NULL
, FALSE
);
4386 /* LISTVIEW_InsertColumnW */
4390 * Inserts a new item in the listview control.
4393 * [I] HWND : window handle
4394 * [I] LPLVITEMA : item information
4397 * SUCCESS : new item index
4400 static LRESULT
LISTVIEW_InsertItemA(HWND hwnd
, LPLVITEMA lpLVItem
)
4402 LISTVIEW_INFO
*infoPtr
= (LISTVIEW_INFO
*)GetWindowLongA(hwnd
, 0);
4403 LONG lStyle
= GetWindowLongA(hwnd
, GWL_STYLE
);
4404 LONG lCtrlId
= GetWindowLongA(hwnd
, GWL_ID
);
4408 LISTVIEW_ITEM
*lpItem
= NULL
;
4410 TRACE(listview
, "(hwnd=%x,lpLVItem=%p)\n", hwnd
, lpLVItem
);
4412 if (lpLVItem
!= NULL
)
4414 /* make sure it's not a subitem; cannot insert a subitem */
4415 if (lpLVItem
->iSubItem
== 0)
4417 lpItem
= (LISTVIEW_ITEM
*)COMCTL32_Alloc(sizeof(LISTVIEW_ITEM
));
4420 ZeroMemory(lpItem
, sizeof(LISTVIEW_ITEM
));
4421 if (LISTVIEW_InitItem(hwnd
, lpItem
, lpLVItem
) != FALSE
)
4423 /* insert item in listview control data structure */
4424 hdpaSubItems
= DPA_Create(8);
4425 if (hdpaSubItems
!= NULL
)
4427 nItem
= DPA_InsertPtr(hdpaSubItems
, 0, lpItem
);
4430 nItem
= DPA_InsertPtr(infoPtr
->hdpaItems
, lpLVItem
->iItem
,
4434 /* manage item focus */
4435 if (lpLVItem
->mask
& LVIF_STATE
)
4437 if (lpLVItem
->stateMask
& LVIS_FOCUSED
)
4439 LISTVIEW_SetItemFocus(hwnd
, nItem
);
4443 /* send LVN_INSERTITEM notification */
4444 ZeroMemory(&nmlv
, sizeof(NMLISTVIEW
));
4445 nmlv
.hdr
.hwndFrom
= hwnd
;
4446 nmlv
.hdr
.idFrom
= lCtrlId
;
4447 nmlv
.hdr
.code
= LVN_INSERTITEM
;
4449 nmlv
.lParam
= lpItem
->lParam
;;
4450 ListView_LVNotify(GetParent(hwnd
), lCtrlId
, &nmlv
);
4452 /* align items (set position of each item) */
4453 switch (lStyle
& LVS_TYPEMASK
)
4457 if (lStyle
& LVS_ALIGNLEFT
)
4459 LISTVIEW_AlignLeft(hwnd
);
4463 LISTVIEW_AlignTop(hwnd
);
4468 LISTVIEW_SetScroll(hwnd
, lStyle
);
4469 /* refresh client area */
4470 InvalidateRect(hwnd
, NULL
, FALSE
);
4479 /* free memory if unsuccessful */
4480 if ((nItem
== -1) && (lpItem
!= NULL
))
4482 COMCTL32_Free(lpItem
);
4488 /* LISTVIEW_InsertItemW */
4492 * Redraws a range of items.
4495 * [I] HWND : window handle
4496 * [I] INT : first item
4497 * [I] INT : last item
4503 static LRESULT
LISTVIEW_RedrawItems(HWND hwnd
, INT nFirst
, INT nLast
)
4505 LISTVIEW_INFO
*infoPtr
= (LISTVIEW_INFO
*)GetWindowLongA(hwnd
, 0);
4506 BOOL bResult
= FALSE
;
4509 if (nFirst
<= nLast
)
4511 if ((nFirst
>= 0) && (nFirst
< GETITEMCOUNT(infoPtr
)))
4513 if ((nLast
>= 0) && (nLast
< GETITEMCOUNT(infoPtr
)))
4516 InvalidateRect(hwnd
, &rc
, FALSE
);
4524 /* LISTVIEW_Scroll */
4528 * Sets the background color.
4531 * [I] HWND : window handle
4532 * [I] COLORREF : background color
4538 static LRESULT
LISTVIEW_SetBkColor(HWND hwnd
, COLORREF clrBk
)
4540 LISTVIEW_INFO
*infoPtr
= (LISTVIEW_INFO
*)GetWindowLongA(hwnd
, 0);
4542 infoPtr
->clrBk
= clrBk
;
4543 InvalidateRect(hwnd
, NULL
, TRUE
);
4550 * Sets the callback mask. This mask will be used when the parent
4551 * window stores state information (some or all).
4554 * [I] HWND : window handle
4555 * [I] UINT : state mask
4561 static BOOL
LISTVIEW_SetCallbackMask(HWND hwnd
, UINT uMask
)
4563 LISTVIEW_INFO
*infoPtr
= (LISTVIEW_INFO
*)GetWindowLongA(hwnd
, 0);
4565 infoPtr
->uCallbackMask
= uMask
;
4572 * Sets the attributes of a header item.
4575 * [I] HWND : window handle
4576 * [I] INT : column index
4577 * [I] LPLVCOLUMNA : column attributes
4583 static LRESULT
LISTVIEW_SetColumnA(HWND hwnd
, INT nColumn
,
4584 LPLVCOLUMNA lpColumn
)
4586 LISTVIEW_INFO
*infoPtr
= (LISTVIEW_INFO
*)GetWindowLongA(hwnd
, 0);
4587 BOOL bResult
= FALSE
;
4590 if ((lpColumn
!= NULL
) && (nColumn
>= 0) &&
4591 (nColumn
< Header_GetItemCount(infoPtr
->hwndHeader
)))
4593 /* initialize memory */
4594 ZeroMemory(&hdi
, sizeof(HDITEMA
));
4596 if (lpColumn
->mask
& LVCF_FMT
)
4598 /* format member is valid */
4599 hdi
.mask
|= HDI_FORMAT
;
4601 /* set text alignment (leftmost column must be left-aligned) */
4604 hdi
.fmt
|= HDF_LEFT
;
4608 if (lpColumn
->fmt
& LVCFMT_LEFT
)
4610 hdi
.fmt
|= HDF_LEFT
;
4612 else if (lpColumn
->fmt
& LVCFMT_RIGHT
)
4614 hdi
.fmt
|= HDF_RIGHT
;
4616 else if (lpColumn
->fmt
& LVCFMT_CENTER
)
4618 hdi
.fmt
|= HDF_CENTER
;
4622 if (lpColumn
->fmt
& LVCFMT_BITMAP_ON_RIGHT
)
4624 hdi
.fmt
|= HDF_BITMAP_ON_RIGHT
;
4627 if (lpColumn
->fmt
& LVCFMT_COL_HAS_IMAGES
)
4629 hdi
.fmt
|= HDF_IMAGE
;
4632 if (lpColumn
->fmt
& LVCFMT_IMAGE
)
4634 hdi
.fmt
|= HDF_IMAGE
;
4635 hdi
.iImage
= I_IMAGECALLBACK
;
4639 if (lpColumn
->mask
& LVCF_WIDTH
)
4641 hdi
.mask
|= HDI_WIDTH
;
4642 hdi
.cxy
= lpColumn
->cx
;
4645 if (lpColumn
->mask
& LVCF_TEXT
)
4647 hdi
.mask
|= HDI_TEXT
| HDI_FORMAT
;
4648 hdi
.pszText
= lpColumn
->pszText
;
4649 hdi
.cchTextMax
= lstrlenA(lpColumn
->pszText
);
4650 hdi
.fmt
|= HDF_STRING
;
4653 if (lpColumn
->mask
& LVCF_IMAGE
)
4655 hdi
.mask
|= HDI_IMAGE
;
4656 hdi
.iImage
= lpColumn
->iImage
;
4659 if (lpColumn
->mask
& LVCF_ORDER
)
4661 hdi
.mask
|= HDI_ORDER
;
4662 hdi
.iOrder
= lpColumn
->iOrder
;
4665 /* set header item attributes */
4666 bResult
= Header_SetItemA(infoPtr
->hwndHeader
, nColumn
, &hdi
);
4674 * Sets the width of a column
4677 * [I] HWND : window handle
4678 * [I] INT : column index
4679 * [I] INT : column width
4685 static LRESULT
LISTVIEW_SetColumnWidth(HWND hwnd
, INT iCol
, INT cx
)
4687 LISTVIEW_INFO
*infoPtr
;
4692 // set column width only if in report mode
4693 lStyle
= GetWindowLongA(hwnd
, GWL_STYLE
);
4694 if ((lStyle
& LVS_TYPEMASK
) != LVS_REPORT
)
4697 // make sure we can get the listview info
4698 if (!(infoPtr
= (LISTVIEW_INFO
*)GetWindowLongA(hwnd
, 0)))
4700 if (!infoPtr
->hwndHeader
) // make sure we have a header
4703 // FIXME: currently ignoring LVSCW_AUTOSIZE (-1) and
4704 // LVSCV_AUTOSIZE_USEHEADER (-2)
4708 hdi
.mask
= HDI_WIDTH
;
4711 // call header to update the column change
4712 lret
= Header_SetItemA(infoPtr
->hwndHeader
, (WPARAM
)iCol
, (LPARAM
)&hdi
);
4714 infoPtr
->nItemWidth
= LISTVIEW_GetItemWidth(hwnd
, LVS_REPORT
);
4716 InvalidateRect(hwnd
, NULL
, TRUE
); // force redraw of the listview
4726 * [I] HWND : window handle
4727 * [I] INT : image list type
4728 * [I] HIMAGELIST : image list handle
4731 * SUCCESS : old image list
4734 static LRESULT
LISTVIEW_SetImageList(HWND hwnd
, INT nType
, HIMAGELIST himl
)
4736 LISTVIEW_INFO
*infoPtr
= (LISTVIEW_INFO
*)GetWindowLongA(hwnd
, 0);
4737 HIMAGELIST himlTemp
= 0;
4742 himlTemp
= infoPtr
->himlNormal
;
4743 infoPtr
->himlNormal
= himl
;
4744 return (LRESULT
)himlTemp
;
4747 himlTemp
= infoPtr
->himlSmall
;
4748 infoPtr
->himlSmall
= himl
;
4749 return (LRESULT
)himlTemp
;
4752 himlTemp
= infoPtr
->himlState
;
4753 infoPtr
->himlState
= himl
;
4754 return (LRESULT
)himlTemp
;
4757 return (LRESULT
)NULL
;
4763 * Sets the attributes of an item.
4766 * [I] HWND : window handle
4767 * [I] LPLVITEM : item information
4773 static LRESULT
LISTVIEW_SetItemA(HWND hwnd
, LPLVITEMA lpLVItem
)
4775 LISTVIEW_INFO
*infoPtr
= (LISTVIEW_INFO
*)GetWindowLongA(hwnd
, 0);
4776 BOOL bResult
= FALSE
;
4778 if (lpLVItem
!= NULL
)
4780 if ((lpLVItem
->iItem
>= 0) && (lpLVItem
->iItem
< GETITEMCOUNT(infoPtr
)))
4782 if (lpLVItem
->iSubItem
== 0)
4784 bResult
= LISTVIEW_SetItem(hwnd
, lpLVItem
);
4788 bResult
= LISTVIEW_SetSubItem(hwnd
, lpLVItem
);
4797 /* LISTVIEW_SetItemW */
4801 * Preallocates memory.
4804 * [I] HWND : window handle
4805 * [I] INT : item count (prjected number of items)
4810 static VOID
LISTVIEW_SetItemCount(HWND hwnd
, INT nItemCount
)
4812 FIXME (listview
, "empty stub!\n");
4817 * Sets the position of an item.
4820 * [I] HWND : window handle
4821 * [I] INT : item index
4822 * [I] INT : x coordinate
4823 * [I] INT : y coordinate
4829 static BOOL
LISTVIEW_SetItemPosition(HWND hwnd
, INT nItem
,
4830 INT nPosX
, INT nPosY
)
4832 LISTVIEW_INFO
*infoPtr
= (LISTVIEW_INFO
*)GetWindowLongA(hwnd
, 0);
4833 LONG lStyle
= GetWindowLongA(hwnd
, GWL_STYLE
);
4834 LISTVIEW_ITEM
*lpItem
;
4836 BOOL bResult
= FALSE
;
4838 TRACE(listview
, "(hwnd=%x,nItem=%d,X=%d,Y=%d)\n", hwnd
, nItem
, nPosX
, nPosY
);
4840 if ((nItem
>= 0) || (nItem
< GETITEMCOUNT(infoPtr
)))
4842 switch (lStyle
& LVS_TYPEMASK
)
4846 hdpaSubItems
= (HDPA
)DPA_GetPtr(infoPtr
->hdpaItems
, nItem
);
4847 if (hdpaSubItems
!= NULL
)
4849 lpItem
= (LISTVIEW_ITEM
*)DPA_GetPtr(hdpaSubItems
, 0);
4853 lpItem
->ptPosition
.x
= nPosX
;
4854 lpItem
->ptPosition
.y
= nPosY
;
4866 * Sets the state of one or many items.
4869 * [I] HWND : window handle
4870 * [I]INT : item index
4871 * [I] LPLVITEM : item or subitem info
4877 static LRESULT
LISTVIEW_SetItemState(HWND hwnd
, INT nItem
, LPLVITEMA lpLVItem
)
4879 LISTVIEW_INFO
*infoPtr
= (LISTVIEW_INFO
*)GetWindowLongA(hwnd
, 0);
4880 BOOL bResult
= FALSE
;
4887 ZeroMemory(&lvItem
, sizeof(LVITEMA
));
4888 lvItem
.mask
= LVIF_STATE
;
4889 lvItem
.state
= lpLVItem
->state
;
4890 lvItem
.stateMask
= lpLVItem
->stateMask
;
4892 /* apply to all items */
4893 for (i
= 0; i
< GETITEMCOUNT(infoPtr
); i
++)
4896 if (ListView_SetItemA(hwnd
, &lvItem
) == FALSE
)
4904 ZeroMemory(&lvItem
, sizeof(LVITEMA
));
4905 lvItem
.mask
= LVIF_STATE
;
4906 lvItem
.state
= lpLVItem
->state
;
4907 lvItem
.stateMask
= lpLVItem
->stateMask
;
4908 lvItem
.iItem
= nItem
;
4909 bResult
= ListView_SetItemA(hwnd
, &lvItem
);
4917 * Sets the text of an item or subitem.
4920 * [I] HWND : window handle
4921 * [I] INT : item index
4922 * [I] LPLVITEMA : item or subitem info
4928 static BOOL
LISTVIEW_SetItemTextA(HWND hwnd
, INT nItem
, LPLVITEMA lpLVItem
)
4930 LISTVIEW_INFO
*infoPtr
= (LISTVIEW_INFO
*)GetWindowLongA(hwnd
, 0);
4931 BOOL bResult
= FALSE
;
4934 if ((nItem
>= 0) && (nItem
< GETITEMCOUNT(infoPtr
)))
4936 ZeroMemory(&lvItem
, sizeof(LVITEMA
));
4937 lvItem
.mask
= LVIF_TEXT
;
4938 lvItem
.pszText
= lpLVItem
->pszText
;
4939 lvItem
.iItem
= nItem
;
4940 lvItem
.iSubItem
= lpLVItem
->iSubItem
;
4941 bResult
= ListView_SetItemA(hwnd
, &lvItem
);
4949 * Sets the text background color.
4952 * [I] HWND : window handle
4953 * [I] COLORREF : text background color
4959 static LRESULT
LISTVIEW_SetTextBkColor(HWND hwnd
, COLORREF clrTextBk
)
4961 LISTVIEW_INFO
*infoPtr
= (LISTVIEW_INFO
*)GetWindowLongA(hwnd
, 0);
4963 infoPtr
->clrTextBk
= clrTextBk
;
4964 InvalidateRect(hwnd
, NULL
, TRUE
);
4971 * Sets the text foreground color.
4974 * [I] HWND : window handle
4975 * [I] COLORREF : text color
4981 static LRESULT
LISTVIEW_SetTextColor (HWND hwnd
, COLORREF clrText
)
4983 LISTVIEW_INFO
*infoPtr
= (LISTVIEW_INFO
*)GetWindowLongA(hwnd
, 0);
4985 infoPtr
->clrText
= clrText
;
4986 InvalidateRect(hwnd
, NULL
, TRUE
);
4993 * Sorts the listview items.
4996 * [I] HWND : window handle
5002 static LRESULT
LISTVIEW_SortItems(HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
5004 FIXME (listview
, "empty stub!\n");
5011 * Updates an items or rearranges the listview control.
5014 * [I] HWND : window handle
5015 * [I] INT : item index
5021 static LRESULT
LISTVIEW_Update(HWND hwnd
, INT nItem
)
5023 LISTVIEW_INFO
*infoPtr
= (LISTVIEW_INFO
*)GetWindowLongA(hwnd
, 0);
5024 LONG lStyle
= GetWindowLongA(hwnd
, GWL_STYLE
);
5025 BOOL bResult
= FALSE
;
5028 if ((nItem
>= 0) && (nItem
< GETITEMCOUNT(infoPtr
)))
5032 /* rearrange with default alignment style */
5033 if ((lStyle
& LVS_AUTOARRANGE
) && (((lStyle
& LVS_TYPEMASK
) == LVS_ICON
) ||
5034 ((lStyle
& LVS_TYPEMASK
) == LVS_SMALLICON
)))
5036 ListView_Arrange(hwnd
, 0);
5040 /* get item bounding rectangle */
5041 rc
.left
= LVIR_BOUNDS
;
5042 ListView_GetItemRect(hwnd
, nItem
, &rc
);
5043 InvalidateRect(hwnd
, &rc
, FALSE
);
5052 * Creates the listview control.
5055 * [I] HWND : window handle
5060 static LRESULT
LISTVIEW_Create(HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
5062 LISTVIEW_INFO
*infoPtr
= (LISTVIEW_INFO
*)GetWindowLongA(hwnd
, 0);
5063 LPCREATESTRUCTA lpcs
= (LPCREATESTRUCTA
)lParam
;
5066 /* initialize info pointer */
5067 ZeroMemory(infoPtr
, sizeof(LISTVIEW_INFO
));
5069 /* determine the type of structures to use */
5070 infoPtr
->notifyFormat
= SendMessageA(GetParent(hwnd
), WM_NOTIFYFORMAT
,
5071 (WPARAM
)hwnd
, (LPARAM
)NF_QUERY
);
5072 if (infoPtr
->notifyFormat
!= NFR_ANSI
)
5074 FIXME (listview
, "ANSI notify format is NOT used\n");
5077 /* initialize color information */
5078 infoPtr
->clrBk
= GetSysColor(COLOR_WINDOW
);
5079 infoPtr
->clrText
= GetSysColor(COLOR_WINDOWTEXT
);
5080 infoPtr
->clrTextBk
= GetSysColor(COLOR_WINDOW
);
5082 /* set default values */
5083 infoPtr
->uCallbackMask
= 0;
5084 infoPtr
->nFocusedItem
= -1;
5085 infoPtr
->nSelectionMark
= -1;
5086 infoPtr
->iconSpacing
.cx
= GetSystemMetrics(SM_CXICONSPACING
);
5087 infoPtr
->iconSpacing
.cy
= GetSystemMetrics(SM_CYICONSPACING
);
5088 ZeroMemory(&infoPtr
->rcList
, sizeof(RECT
));
5090 /* get default font (icon title) */
5091 SystemParametersInfoA(SPI_GETICONTITLELOGFONT
, 0, &logFont
, 0);
5092 infoPtr
->hDefaultFont
= CreateFontIndirectA(&logFont
);
5093 infoPtr
->hFont
= infoPtr
->hDefaultFont
;
5096 infoPtr
->hwndHeader
= CreateWindowA(WC_HEADERA
, (LPCSTR
)NULL
,
5097 WS_CHILD
| HDS_HORZ
| HDS_BUTTONS
,
5098 0, 0, 0, 0, hwnd
, (HMENU
)0,
5099 lpcs
->hInstance
, NULL
);
5101 /* set header font */
5102 SendMessageA(infoPtr
->hwndHeader
, WM_SETFONT
, (WPARAM
)infoPtr
->hFont
,
5106 switch (lpcs
->style
& LVS_TYPEMASK
)
5109 infoPtr
->iconSize
.cx
= GetSystemMetrics(SM_CXICON
);
5110 infoPtr
->iconSize
.cy
= GetSystemMetrics(SM_CYICON
);
5114 ShowWindow(infoPtr
->hwndHeader
, SW_SHOWNORMAL
);
5117 infoPtr
->iconSize
.cx
= GetSystemMetrics(SM_CXSMICON
);
5118 infoPtr
->iconSize
.cy
= GetSystemMetrics(SM_CYSMICON
);
5122 /* display unsupported listview window styles */
5123 LISTVIEW_UnsupportedStyles(lpcs
->style
);
5125 /* allocate memory for the data structure */
5126 infoPtr
->hdpaItems
= DPA_Create(10);
5128 /* initialize size of items */
5129 infoPtr
->nItemWidth
= LISTVIEW_GetItemWidth(hwnd
, lpcs
->style
);
5130 infoPtr
->nItemHeight
= LISTVIEW_GetItemHeight(hwnd
, lpcs
->style
);
5137 * Erases the background of the listview control.
5140 * [I] HWND : window handle
5141 * [I] WPARAM : device context handle
5142 * [I] LPARAM : not used
5148 static LRESULT
LISTVIEW_EraseBackground(HWND hwnd
, WPARAM wParam
,
5151 LISTVIEW_INFO
*infoPtr
= (LISTVIEW_INFO
*)GetWindowLongA(hwnd
, 0);
5154 if (infoPtr
->clrBk
== CLR_NONE
)
5156 bResult
= SendMessageA(GetParent(hwnd
), WM_ERASEBKGND
, wParam
, lParam
);
5161 HBRUSH hBrush
= CreateSolidBrush(infoPtr
->clrBk
);
5162 GetClientRect(hwnd
, &rc
);
5163 FillRect((HDC
)wParam
, &rc
, hBrush
);
5164 DeleteObject(hBrush
);
5173 * Retrieves the listview control font.
5176 * [I] HWND : window handle
5181 static LRESULT
LISTVIEW_GetFont(HWND hwnd
)
5183 LISTVIEW_INFO
*infoPtr
= (LISTVIEW_INFO
*)GetWindowLongA(hwnd
, 0);
5185 return infoPtr
->hFont
;
5190 * Performs vertical scrolling.
5193 * [I] HWND : window handle
5194 * [I] INT : scroll code
5195 * [I] INT : scroll position
5196 * [I] HWND : scrollbar control window handle
5201 static LRESULT
LISTVIEW_VScroll(HWND hwnd
, INT nScrollCode
, INT nScroll
,
5204 LISTVIEW_INFO
*infoPtr
= (LISTVIEW_INFO
*)GetWindowLongA(hwnd
, 0);
5205 LONG lStyle
= GetWindowLongA(hwnd
, GWL_STYLE
);
5206 INT nScrollPosInc
= 0;
5211 GetScrollRange(hwnd
, SB_VERT
, &nMinRange
, &nMaxRange
);
5212 nScrollPos
= GetScrollPos(hwnd
, SB_VERT
);
5214 switch (nScrollCode
)
5217 if (nScrollPos
> nMinRange
)
5224 if (nScrollPos
< nMaxRange
)
5231 switch (LVS_TYPEMASK
& lStyle
)
5234 if (nScrollPos
> nMinRange
+ infoPtr
->nCountPerColumn
)
5236 nScrollPosInc
= -infoPtr
->nCountPerColumn
;
5240 nScrollPosInc
= nMinRange
- nScrollPos
;
5246 if (nScrollPos
> nMinRange
+ 10)
5248 nScrollPosInc
= -10;
5252 nScrollPosInc
= nMinRange
- nScrollPos
;
5259 switch (LVS_TYPEMASK
& lStyle
)
5262 if (nScrollPos
< nMaxRange
- infoPtr
->nCountPerColumn
)
5264 nScrollPosInc
= infoPtr
->nCountPerColumn
;
5268 nScrollPosInc
= nMaxRange
- nScrollPos
;
5274 if (nScrollPos
< nMaxRange
- 10)
5280 nScrollPosInc
= nMaxRange
- nScrollPos
;
5286 case SB_THUMBPOSITION
:
5287 nScrollPosInc
= nScroll
- nScrollPos
;
5291 if (nScrollPosInc
!= 0)
5293 LISTVIEW_ScrollView(hwnd
, 0, nScrollPosInc
);
5302 * Performs horizontal scrolling.
5305 * [I] HWND : window handle
5306 * [I] INT : scroll code
5307 * [I] INT : scroll position
5308 * [I] HWND : scrollbar control window handle
5313 static LRESULT
LISTVIEW_HScroll(HWND hwnd
, INT nScrollCode
,
5314 INT nScroll
, HWND hScrollWnd
)
5316 LISTVIEW_INFO
*infoPtr
= (LISTVIEW_INFO
*)GetWindowLongA(hwnd
, 0);
5317 LONG lStyle
= GetWindowLongA(hwnd
, GWL_STYLE
);
5318 INT nScrollPosInc
= 0;
5323 GetScrollRange(hwnd
, SB_HORZ
, &nMinRange
, &nMaxRange
);
5324 nScrollPos
= GetScrollPos(hwnd
, SB_HORZ
);
5326 switch (nScrollCode
)
5329 if (nScrollPos
> nMinRange
)
5336 if (nScrollPos
< nMaxRange
)
5343 switch (LVS_TYPEMASK
& lStyle
)
5346 if (nScrollPos
> nMinRange
+ infoPtr
->nCountPerRow
)
5348 nScrollPosInc
= -infoPtr
->nCountPerRow
;
5352 nScrollPosInc
= nMinRange
- nScrollPos
;
5359 if (nScrollPos
> nMinRange
+ 10)
5361 nScrollPosInc
= -10;
5365 nScrollPosInc
= nMinRange
- nScrollPos
;
5372 switch (LVS_TYPEMASK
& lStyle
)
5375 if (nScrollPos
< nMaxRange
- infoPtr
->nCountPerRow
)
5377 nScrollPosInc
= infoPtr
->nCountPerRow
;
5381 nScrollPosInc
= nMaxRange
- nScrollPos
;
5388 if (nScrollPos
< nMaxRange
- 10)
5394 nScrollPosInc
= nMaxRange
- nScrollPos
;
5400 case SB_THUMBPOSITION
:
5401 nScrollPosInc
= nScroll
- nScrollPos
;
5405 if (nScrollPosInc
!= 0)
5407 LISTVIEW_ScrollView(hwnd
, nScrollPosInc
, 0);
5418 * [I] HWND : window handle
5419 * [I] INT : virtual key
5420 * [I] LONG : key data
5425 static LRESULT
LISTVIEW_KeyDown(HWND hwnd
, INT nVirtualKey
, LONG lKeyData
)
5427 LISTVIEW_INFO
*infoPtr
= (LISTVIEW_INFO
*)GetWindowLongA(hwnd
, 0);
5428 LONG lStyle
= GetWindowLongA(hwnd
, GWL_STYLE
);
5429 INT nCtrlId
= GetWindowLongA(hwnd
, GWL_ID
);
5430 INT nCountPerColumn
;
5432 HWND hwndParent
= GetParent(hwnd
);
5433 NMLVKEYDOWN nmKeyDown
;
5436 /* send LVN_KEYDOWN notification */
5437 ZeroMemory(&nmKeyDown
, sizeof(NMLVKEYDOWN
));
5438 nmKeyDown
.hdr
.hwndFrom
= hwnd
;
5439 nmKeyDown
.hdr
.idFrom
= nCtrlId
;
5440 nmKeyDown
.hdr
.code
= LVN_KEYDOWN
;
5441 nmKeyDown
.wVKey
= nVirtualKey
;
5442 nmKeyDown
.flags
= 0;
5443 SendMessageA(hwndParent
, WM_NOTIFY
, (WPARAM
)nCtrlId
, (LPARAM
)&nmKeyDown
);
5446 nmh
.hwndFrom
= hwnd
;
5447 nmh
.idFrom
= nCtrlId
;
5449 switch (nVirtualKey
)
5452 if ((GETITEMCOUNT(infoPtr
) > 0) && (infoPtr
->nFocusedItem
!= -1))
5454 /* send NM_RETURN notification */
5455 nmh
.code
= NM_RETURN
;
5456 ListView_Notify(hwndParent
, nCtrlId
, &nmh
);
5458 /* send LVN_ITEMACTIVATE notification */
5459 nmh
.code
= LVN_ITEMACTIVATE
;
5460 ListView_Notify(hwndParent
, nCtrlId
, &nmh
);
5465 if (GETITEMCOUNT(infoPtr
) > 0)
5467 LISTVIEW_KeySelection(hwnd
, 0);
5472 if (GETITEMCOUNT(infoPtr
) > 0)
5474 LISTVIEW_KeySelection(hwnd
, GETITEMCOUNT(infoPtr
) - 1);
5479 switch (LVS_TYPEMASK
& lStyle
)
5482 if (infoPtr
->nFocusedItem
>= infoPtr
->nCountPerColumn
)
5484 LISTVIEW_KeySelection(hwnd
, infoPtr
->nFocusedItem
-
5485 infoPtr
->nCountPerColumn
);
5491 if (lStyle
& LVS_ALIGNLEFT
)
5493 nCountPerColumn
= max((infoPtr
->rcList
.bottom
- infoPtr
->rcList
.top
) /
5494 infoPtr
->nItemHeight
, 1);
5495 if (infoPtr
->nFocusedItem
>= nCountPerColumn
)
5497 LISTVIEW_KeySelection(hwnd
, infoPtr
->nFocusedItem
- nCountPerColumn
);
5502 nCountPerRow
= max((infoPtr
->rcList
.right
- infoPtr
->rcList
.left
) /
5503 infoPtr
->nItemWidth
, 1);
5504 if (infoPtr
->nFocusedItem
% nCountPerRow
!= 0)
5506 LISTVIEW_SetSelection(hwnd
, infoPtr
->nFocusedItem
- 1);
5514 switch (LVS_TYPEMASK
& lStyle
)
5518 if (infoPtr
->nFocusedItem
> 0)
5520 LISTVIEW_KeySelection(hwnd
, infoPtr
->nFocusedItem
- 1);
5525 if (lStyle
& LVS_ALIGNLEFT
)
5527 nCountPerColumn
= max((infoPtr
->rcList
.bottom
- infoPtr
->rcList
.top
) /
5528 infoPtr
->nItemHeight
, 1);
5529 if (infoPtr
->nFocusedItem
% nCountPerColumn
!= 0)
5531 LISTVIEW_KeySelection(hwnd
, infoPtr
->nFocusedItem
- 1);
5536 nCountPerRow
= max((infoPtr
->rcList
.right
- infoPtr
->rcList
.left
) /
5537 infoPtr
->nItemWidth
, 1);
5538 if (infoPtr
->nFocusedItem
>= nCountPerRow
)
5540 LISTVIEW_KeySelection(hwnd
, infoPtr
->nFocusedItem
- nCountPerRow
);
5547 switch (LVS_TYPEMASK
& lStyle
)
5550 if (infoPtr
->nFocusedItem
< GETITEMCOUNT(infoPtr
) -
5551 infoPtr
->nCountPerColumn
)
5553 LISTVIEW_KeySelection(hwnd
, infoPtr
->nFocusedItem
+
5554 infoPtr
->nCountPerColumn
);
5560 if (lStyle
& LVS_ALIGNLEFT
)
5562 nCountPerColumn
= max((infoPtr
->rcList
.bottom
- infoPtr
->rcList
.top
) /
5563 infoPtr
->nItemHeight
, 1);
5564 if (infoPtr
->nFocusedItem
< GETITEMCOUNT(infoPtr
) - nCountPerColumn
)
5566 LISTVIEW_KeySelection(hwnd
, infoPtr
->nFocusedItem
+ nCountPerColumn
);
5571 nCountPerRow
= max((infoPtr
->rcList
.right
- infoPtr
->rcList
.left
) /
5572 infoPtr
->nItemWidth
, 1);
5573 if ((infoPtr
->nFocusedItem
% nCountPerRow
!= nCountPerRow
- 1) &&
5574 (infoPtr
->nFocusedItem
< GETITEMCOUNT(infoPtr
) - 1))
5576 LISTVIEW_KeySelection(hwnd
, infoPtr
->nFocusedItem
+ 1);
5583 switch (LVS_TYPEMASK
& lStyle
)
5587 if (infoPtr
->nFocusedItem
< GETITEMCOUNT(infoPtr
) - 1)
5589 LISTVIEW_KeySelection(hwnd
, infoPtr
->nFocusedItem
+ 1);
5595 if (lStyle
& LVS_ALIGNLEFT
)
5597 nCountPerColumn
= max((infoPtr
->rcList
.bottom
- infoPtr
->rcList
.top
) /
5598 infoPtr
->nItemHeight
, 1);
5599 if (infoPtr
->nFocusedItem
% nCountPerColumn
!= nCountPerColumn
- 1)
5601 LISTVIEW_KeySelection(hwnd
, infoPtr
->nFocusedItem
+ 1);
5606 nCountPerRow
= max((infoPtr
->rcList
.right
- infoPtr
->rcList
.left
) /
5607 infoPtr
->nItemWidth
, 1);
5608 if (infoPtr
->nFocusedItem
< GETITEMCOUNT(infoPtr
) - nCountPerRow
)
5610 LISTVIEW_KeySelection(hwnd
, infoPtr
->nFocusedItem
+ nCountPerRow
);
5623 /* refresh client area */
5624 InvalidateRect(hwnd
, NULL
, TRUE
);
5634 * [I] HWND : window handle
5639 static LRESULT
LISTVIEW_KillFocus(HWND hwnd
)
5641 LISTVIEW_INFO
*infoPtr
= (LISTVIEW_INFO
*)GetWindowLongA(hwnd
, 0);
5642 INT nCtrlId
= GetWindowLongA(hwnd
, GWL_ID
);
5645 /* send NM_KILLFOCUS notification */
5646 nmh
.hwndFrom
= hwnd
;
5647 nmh
.idFrom
= nCtrlId
;
5648 nmh
.code
= NM_KILLFOCUS
;
5649 ListView_Notify(GetParent(hwnd
), nCtrlId
, &nmh
);
5651 /* set window focus flag */
5652 infoPtr
->bFocus
= FALSE
;
5659 * Processes double click messages (left mouse button).
5662 * [I] HWND : window handle
5663 * [I] WORD : key flag
5664 * [I] WORD : x coordinate
5665 * [I] WORD : y coordinate
5670 static LRESULT
LISTVIEW_LButtonDblClk(HWND hwnd
, WORD wKey
, WORD wPosX
,
5673 LONG nCtrlId
= GetWindowLongA(hwnd
, GWL_ID
);
5676 TRACE(listview
, "(hwnd=%x,key=%hu,X=%hu,Y=%hu)\n", hwnd
, wKey
, wPosX
, wPosY
);
5678 /* send NM_DBLCLK notification */
5679 nmh
.hwndFrom
= hwnd
;
5680 nmh
.idFrom
= nCtrlId
;
5681 nmh
.code
= NM_DBLCLK
;
5682 ListView_Notify(GetParent(hwnd
), nCtrlId
, &nmh
);
5684 /* send LVN_ITEMACTIVATE notification */
5685 nmh
.code
= LVN_ITEMACTIVATE
;
5686 ListView_Notify(GetParent(hwnd
), nCtrlId
, &nmh
);
5693 * Processes mouse down messages (left mouse button).
5696 * [I] HWND : window handle
5697 * [I] WORD : key flag
5698 * [I] WORD : x coordinate
5699 * [I] WORD : y coordinate
5704 static LRESULT
LISTVIEW_LButtonDown(HWND hwnd
, WORD wKey
, WORD wPosX
,
5707 LISTVIEW_INFO
*infoPtr
= (LISTVIEW_INFO
*)GetWindowLongA(hwnd
, 0);
5708 INT nCtrlId
= GetWindowLongA(hwnd
, GWL_ID
);
5709 static BOOL bGroupSelect
= TRUE
;
5713 TRACE(listview
, "(hwnd=%x,key=%hu,X=%hu,Y=%hu)\n", hwnd
, wKey
, wPosX
, wPosY
);
5715 /* send NM_RELEASEDCAPTURE notification */
5716 nmh
.hwndFrom
= hwnd
;
5717 nmh
.idFrom
= nCtrlId
;
5718 nmh
.code
= NM_RELEASEDCAPTURE
;
5719 ListView_Notify(GetParent(hwnd
), nCtrlId
, &nmh
);
5721 if (infoPtr
->bFocus
== FALSE
)
5726 /* set left button down flag */
5727 infoPtr
->bLButtonDown
= TRUE
;
5729 nItem
= LISTVIEW_MouseSelection(hwnd
, wPosX
, wPosY
);
5730 if ((nItem
>= 0) && (nItem
< GETITEMCOUNT(infoPtr
)))
5732 if ((wKey
& MK_CONTROL
) && (wKey
& MK_SHIFT
))
5734 if (bGroupSelect
!= FALSE
)
5736 LISTVIEW_AddGroupSelection(hwnd
, nItem
);
5740 LISTVIEW_AddSelection(hwnd
, nItem
);
5743 else if (wKey
& MK_CONTROL
)
5745 bGroupSelect
= LISTVIEW_ToggleSelection(hwnd
, nItem
);
5747 else if (wKey
& MK_SHIFT
)
5749 LISTVIEW_SetGroupSelection(hwnd
, nItem
);
5753 LISTVIEW_SetSelection(hwnd
, nItem
);
5758 /* remove all selections */
5759 LISTVIEW_RemoveSelections(hwnd
, 0, GETITEMCOUNT(infoPtr
));
5762 InvalidateRect(hwnd
, NULL
, TRUE
);
5769 * Processes mouse up messages (left mouse button).
5772 * [I] HWND : window handle
5773 * [I] WORD : key flag
5774 * [I] WORD : x coordinate
5775 * [I] WORD : y coordinate
5780 static LRESULT
LISTVIEW_LButtonUp(HWND hwnd
, WORD wKey
, WORD wPosX
,
5783 LISTVIEW_INFO
*infoPtr
= (LISTVIEW_INFO
*)GetWindowLongA(hwnd
, 0);
5785 TRACE(listview
, "(hwnd=%x,key=%hu,X=%hu,Y=%hu)\n", hwnd
, wKey
, wPosX
, wPosY
);
5787 if (infoPtr
->bLButtonDown
!= FALSE
)
5789 INT nCtrlId
= GetWindowLongA(hwnd
, GWL_ID
);
5792 /* send NM_CLICK notification */
5793 nmh
.hwndFrom
= hwnd
;
5794 nmh
.idFrom
= nCtrlId
;
5795 nmh
.code
= NM_CLICK
;
5796 ListView_Notify(GetParent(hwnd
), nCtrlId
, &nmh
);
5798 /* set left button flag */
5799 infoPtr
->bLButtonDown
= FALSE
;
5807 * Creates the listview control (called before WM_CREATE).
5810 * [I] HWND : window handle
5811 * [I] WPARAM : unhandled
5812 * [I] LPARAM : widow creation info
5817 static LRESULT
LISTVIEW_NCCreate(HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
5819 LISTVIEW_INFO
*infoPtr
;
5821 TRACE(listview
, "(hwnd=%x,wParam=%x,lParam=%lx)\n", hwnd
, wParam
, lParam
);
5823 /* allocate memory for info structure */
5824 infoPtr
= (LISTVIEW_INFO
*)COMCTL32_Alloc(sizeof(LISTVIEW_INFO
));
5825 SetWindowLongA(hwnd
, 0, (LONG
)infoPtr
);
5826 if (infoPtr
== NULL
)
5828 ERR(listview
, "could not allocate info memory!\n");
5832 if ((LISTVIEW_INFO
*)GetWindowLongA(hwnd
, 0) != infoPtr
)
5834 ERR(listview
, "pointer assignment error!\n");
5838 return DefWindowProcA(hwnd
, WM_NCCREATE
, wParam
, lParam
);
5843 * Destroys the listview control (called after WM_DESTROY).
5846 * [I] HWND : window handle
5851 static LRESULT
LISTVIEW_NCDestroy(HWND hwnd
)
5853 LISTVIEW_INFO
*infoPtr
= (LISTVIEW_INFO
*)GetWindowLongA(hwnd
, 0);
5855 TRACE(listview
, "(hwnd=%x)\n", hwnd
);
5857 /* delete all items */
5858 LISTVIEW_DeleteAllItems(hwnd
);
5860 /* destroy data structure */
5861 DPA_Destroy(infoPtr
->hdpaItems
);
5864 infoPtr
->hFont
= (HFONT
)0;
5865 if (infoPtr
->hDefaultFont
)
5867 DeleteObject(infoPtr
->hDefaultFont
);
5870 /* free listview info pointer*/
5871 COMCTL32_Free(infoPtr
);
5878 * Handles notifications from children.
5881 * [I] HWND : window handle
5882 * [I] INT : control identifier
5883 * [I] LPNMHDR : notification information
5888 static LRESULT
LISTVIEW_Notify(HWND hwnd
, INT nCtrlId
, LPNMHDR lpnmh
)
5890 LISTVIEW_INFO
*infoPtr
= (LISTVIEW_INFO
*)GetWindowLongA(hwnd
, 0);
5892 if (lpnmh
->hwndFrom
== infoPtr
->hwndHeader
)
5894 /* handle notification from header control */
5895 if (lpnmh
->code
== HDN_ENDTRACKA
)
5897 infoPtr
->nItemWidth
= LISTVIEW_GetItemWidth(hwnd
, LVS_REPORT
);
5898 InvalidateRect(hwnd
, NULL
, TRUE
);
5907 * Determines the type of structure to use.
5910 * [I] HWND : window handle of the sender
5911 * [I] HWND : listview window handle
5912 * [I] INT : command specifying the nature of the WM_NOTIFYFORMAT
5917 static LRESULT
LISTVIEW_NotifyFormat(HWND hwndFrom
, HWND hwnd
, INT nCommand
)
5919 LISTVIEW_INFO
*infoPtr
= (LISTVIEW_INFO
*)GetWindowLongA(hwnd
, 0);
5921 if (nCommand
== NF_REQUERY
)
5923 /* determine the type of structure to use */
5924 infoPtr
->notifyFormat
= SendMessageA(hwndFrom
, WM_NOTIFYFORMAT
,
5925 (WPARAM
)hwnd
, (LPARAM
)NF_QUERY
);
5926 if (infoPtr
->notifyFormat
== NFR_UNICODE
)
5928 FIXME (listview
, "NO support for unicode structures");
5937 * Paints/Repaints the listview control.
5940 * [I] HWND : window handle
5941 * [I] HDC : device context handle
5946 static LRESULT
LISTVIEW_Paint(HWND hwnd
, HDC hdc
)
5950 TRACE(listview
, "(hwnd=%x,hdc=%x)\n", hwnd
, hdc
);
5954 hdc
= BeginPaint(hwnd
, &ps
);
5955 LISTVIEW_Refresh(hwnd
, hdc
);
5956 EndPaint(hwnd
, &ps
);
5960 LISTVIEW_Refresh(hwnd
, hdc
);
5968 * Processes double click messages (right mouse button).
5971 * [I] HWND : window handle
5972 * [I] WORD : key flag
5973 * [I] WORD : x coordinate
5974 * [I] WORD : y coordinate
5979 static LRESULT
LISTVIEW_RButtonDblClk(HWND hwnd
, WORD wKey
, WORD wPosX
,
5982 INT nCtrlId
= GetWindowLongA(hwnd
, GWL_ID
);
5985 TRACE(listview
, "(hwnd=%x,key=%hu,X=%hu,Y=%hu)\n", hwnd
, wKey
, wPosX
, wPosY
);
5987 /* send NM_RELEASEDCAPTURE notification */
5988 nmh
.hwndFrom
= hwnd
;
5989 nmh
.idFrom
= nCtrlId
;
5990 nmh
.code
= NM_RELEASEDCAPTURE
;
5991 ListView_Notify(GetParent(hwnd
), nCtrlId
, &nmh
);
5993 /* send NM_RDBLCLK notification */
5994 nmh
.code
= NM_RDBLCLK
;
5995 ListView_Notify(GetParent(hwnd
), nCtrlId
, &nmh
);
6002 * Processes mouse down messages (right mouse button).
6005 * [I] HWND : window handle
6006 * [I] WORD : key flag
6007 * [I] WORD : x coordinate
6008 * [I] WORD : y coordinate
6013 static LRESULT
LISTVIEW_RButtonDown(HWND hwnd
, WORD wKey
, WORD wPosX
,
6016 LISTVIEW_INFO
*infoPtr
= (LISTVIEW_INFO
*)GetWindowLongA(hwnd
, 0);
6017 INT nCtrlId
= GetWindowLongA(hwnd
, GWL_ID
);
6021 TRACE(listview
, "(hwnd=%x,key=%hu,X=%hu,Y=%hu)\n", hwnd
, wKey
, wPosX
, wPosY
);
6023 /* send NM_RELEASEDCAPTURE notification */
6024 nmh
.hwndFrom
= hwnd
;
6025 nmh
.idFrom
= nCtrlId
;
6026 nmh
.code
= NM_RELEASEDCAPTURE
;
6027 ListView_Notify(GetParent(hwnd
), nCtrlId
, &nmh
);
6029 /* make sure the listview control window has the focus */
6030 if (infoPtr
->bFocus
== FALSE
)
6035 /* set right button down flag */
6036 infoPtr
->bRButtonDown
= TRUE
;
6038 /* determine the index of the selected item */
6039 nItem
= LISTVIEW_MouseSelection(hwnd
, wPosX
, wPosY
);
6040 if ((nItem
>= 0) && (nItem
< GETITEMCOUNT(infoPtr
)))
6042 if (!((wKey
& MK_SHIFT
) || (wKey
& MK_CONTROL
)))
6044 LISTVIEW_SetSelection(hwnd
, nItem
);
6049 LISTVIEW_RemoveSelections(hwnd
, 0, GETITEMCOUNT(infoPtr
));
6057 * Processes mouse up messages (right mouse button).
6060 * [I] HWND : window handle
6061 * [I] WORD : key flag
6062 * [I] WORD : x coordinate
6063 * [I] WORD : y coordinate
6068 static LRESULT
LISTVIEW_RButtonUp(HWND hwnd
, WORD wKey
, WORD wPosX
,
6071 LISTVIEW_INFO
*infoPtr
= (LISTVIEW_INFO
*)GetWindowLongA(hwnd
, 0);
6072 INT nCtrlId
= GetWindowLongA(hwnd
, GWL_ID
);
6075 TRACE(listview
, "(hwnd=%x,key=%hu,X=%hu,Y=%hu)\n", hwnd
, wKey
, wPosX
, wPosY
);
6077 if (infoPtr
->bRButtonDown
!= FALSE
)
6079 /* send NM_RClICK notification */
6080 ZeroMemory(&nmh
, sizeof(NMHDR
));
6081 nmh
.hwndFrom
= hwnd
;
6082 nmh
.idFrom
= nCtrlId
;
6083 nmh
.code
= NM_RCLICK
;
6084 ListView_Notify(GetParent(hwnd
), nCtrlId
, &nmh
);
6086 /* set button flag */
6087 infoPtr
->bRButtonDown
= FALSE
;
6098 * [I] HWND : window handle
6099 * [I] HWND : window handle of previously focused window
6104 static LRESULT
LISTVIEW_SetFocus(HWND hwnd
, HWND hwndLoseFocus
)
6106 LISTVIEW_INFO
*infoPtr
= (LISTVIEW_INFO
*)GetWindowLongA(hwnd
, 0);
6107 INT nCtrlId
= GetWindowLongA(hwnd
, GWL_ID
);
6110 /* send NM_SETFOCUS notification */
6111 nmh
.hwndFrom
= hwnd
;
6112 nmh
.idFrom
= nCtrlId
;
6113 nmh
.code
= NM_SETFOCUS
;
6114 ListView_Notify(GetParent(hwnd
), nCtrlId
, &nmh
);
6116 /* set window focus flag */
6117 infoPtr
->bFocus
= TRUE
;
6127 * [I] HWND : window handle
6128 * [I] HFONT : font handle
6129 * [I] WORD : redraw flag
6134 static LRESULT
LISTVIEW_SetFont(HWND hwnd
, HFONT hFont
, WORD fRedraw
)
6136 LISTVIEW_INFO
*infoPtr
= (LISTVIEW_INFO
*)GetWindowLongA(hwnd
, 0);
6137 LONG lStyle
= GetWindowLongA(hwnd
, GWL_STYLE
);
6139 TRACE(listview
, "(hwnd=%x,hfont=%x,redraw=%hu)\n", hwnd
, hFont
, fRedraw
);
6143 infoPtr
->hFont
= infoPtr
->hDefaultFont
;
6147 infoPtr
->hFont
= hFont
;
6150 if ((LVS_TYPEMASK
& lStyle
) == LVS_REPORT
)
6152 /* set header font */
6153 SendMessageA(infoPtr
->hwndHeader
, WM_SETFONT
, (WPARAM
)hFont
,
6154 MAKELPARAM(fRedraw
, 0));
6157 /* invalidate listview control client area */
6158 InvalidateRect(hwnd
, NULL
, TRUE
);
6160 if (fRedraw
!= FALSE
)
6170 * Resizes the listview control. This function processes WM_SIZE
6171 * messages. At this time, the width and height are not used.
6174 * [I] HWND : window handle
6175 * [I] WORD : new width
6176 * [I] WORD : new height
6181 static LRESULT
LISTVIEW_Size(HWND hwnd
, int Width
, int Height
)
6183 LONG lStyle
= GetWindowLongA(hwnd
, GWL_STYLE
);
6185 TRACE(listview
, "(hwnd=%x,width=%d,height=%d)\n",hwnd
, Width
, Height
);
6187 LISTVIEW_SetSize(hwnd
, lStyle
, -1, -1);
6188 switch (lStyle
& LVS_TYPEMASK
)
6192 LISTVIEW_SetViewInfo(hwnd
, lStyle
);
6197 if (lStyle
& LVS_ALIGNLEFT
)
6199 LISTVIEW_AlignLeft(hwnd
);
6203 LISTVIEW_AlignTop(hwnd
);
6208 LISTVIEW_SetScroll(hwnd
, lStyle
);
6210 /* invalidate + erase background */
6211 InvalidateRect(hwnd
, NULL
, TRUE
);
6218 * Sets the size information for a given style.
6221 * [I] HWND : window handle
6222 * [I] LONG : window style
6223 * [I] WORD : new width
6224 * [I] WORD : new height
6229 static VOID
LISTVIEW_SetSize(HWND hwnd
, LONG lStyle
, LONG lWidth
, LONG lHeight
)
6231 LISTVIEW_INFO
*infoPtr
= (LISTVIEW_INFO
*)GetWindowLongA(hwnd
, 0);
6236 GetClientRect(hwnd
, &rcList
);
6239 infoPtr
->rcList
.left
= max(rcList
.left
, 0);
6240 infoPtr
->rcList
.right
= max(rcList
.right
, 0);
6244 infoPtr
->rcList
.left
= max(rcList
.left
, 0);
6245 infoPtr
->rcList
.right
= infoPtr
->rcList
.left
+ max(lWidth
, 0);
6250 infoPtr
->rcList
.top
= max(rcList
.top
, 0);
6251 infoPtr
->rcList
.bottom
= max(rcList
.bottom
, 0);
6255 infoPtr
->rcList
.top
= max(rcList
.top
, 0);
6256 infoPtr
->rcList
.bottom
= infoPtr
->rcList
.top
+ max(lHeight
, 0);
6259 switch (lStyle
& LVS_TYPEMASK
)
6262 if ((lStyle
& WS_HSCROLL
) == 0)
6265 nHScrollHeight
= GetSystemMetrics(SM_CYHSCROLL
);
6266 if (infoPtr
->rcList
.bottom
> nHScrollHeight
)
6268 infoPtr
->rcList
.bottom
-= nHScrollHeight
;
6276 Header_Layout(infoPtr
->hwndHeader
, &hl
);
6277 infoPtr
->rcList
.top
= max(wp
.cy
, 0);
6284 * Processes WM_STYLECHANGED messages.
6287 * [I] HWND : window handle
6288 * [I] WPARAM : window style type (normal or extended)
6289 * [I] LPSTYLESTRUCT : window style information
6294 static INT
LISTVIEW_StyleChanged(HWND hwnd
, WPARAM wStyleType
,
6297 LISTVIEW_INFO
*infoPtr
= (LISTVIEW_INFO
*)GetWindowLongA(hwnd
, 0);
6298 RECT rcList
= infoPtr
->rcList
;
6302 TRACE(listview
, "(hwnd=%x,styletype=%x,stylestruct=%p)\n",
6303 hwnd
, wStyleType
, lpss
);
6305 if (wStyleType
== GWL_STYLE
)
6307 if ((lpss
->styleOld
& WS_HSCROLL
) != 0)
6309 ShowScrollBar(hwnd
, SB_HORZ
, FALSE
);
6312 if ((lpss
->styleOld
& WS_VSCROLL
) != 0)
6314 ShowScrollBar(hwnd
, SB_VERT
, FALSE
);
6317 if ((LVS_TYPEMASK
& lpss
->styleOld
) == LVS_REPORT
)
6320 ShowWindow(infoPtr
->hwndHeader
, SW_HIDE
);
6323 switch (lpss
->styleNew
& LVS_TYPEMASK
)
6326 infoPtr
->iconSize
.cx
= GetSystemMetrics(SM_CXICON
);
6327 infoPtr
->iconSize
.cy
= GetSystemMetrics(SM_CYICON
);
6328 LISTVIEW_SetSize(hwnd
, lpss
->styleNew
, -1, -1);
6329 infoPtr
->nItemWidth
= LISTVIEW_GetItemWidth(hwnd
, lpss
->styleNew
);
6330 infoPtr
->nItemHeight
= LISTVIEW_GetItemHeight(hwnd
, lpss
->styleNew
);
6331 if (lpss
->styleNew
& LVS_ALIGNLEFT
)
6333 LISTVIEW_AlignLeft(hwnd
);
6337 LISTVIEW_AlignTop(hwnd
);
6344 Header_Layout(infoPtr
->hwndHeader
, &hl
);
6345 SetWindowPos(infoPtr
->hwndHeader
, hwnd
, wp
.x
, wp
.y
, wp
.cx
,
6347 ShowWindow(infoPtr
->hwndHeader
, SW_SHOWNORMAL
);
6348 infoPtr
->iconSize
.cx
= GetSystemMetrics(SM_CXSMICON
);
6349 infoPtr
->iconSize
.cy
= GetSystemMetrics(SM_CYSMICON
);
6350 infoPtr
->nItemWidth
= LISTVIEW_GetItemWidth(hwnd
, lpss
->styleNew
);
6351 infoPtr
->nItemHeight
= LISTVIEW_GetItemHeight(hwnd
, lpss
->styleNew
);
6352 LISTVIEW_SetSize(hwnd
, lpss
->styleNew
, -1, -1);
6353 LISTVIEW_SetViewInfo(hwnd
, lpss
->styleNew
);
6357 infoPtr
->iconSize
.cx
= GetSystemMetrics(SM_CXSMICON
);
6358 infoPtr
->iconSize
.cy
= GetSystemMetrics(SM_CYSMICON
);
6359 infoPtr
->nItemWidth
= LISTVIEW_GetItemWidth(hwnd
, lpss
->styleNew
);
6360 infoPtr
->nItemHeight
= LISTVIEW_GetItemHeight(hwnd
, lpss
->styleNew
);
6361 LISTVIEW_SetSize(hwnd
, lpss
->styleNew
, -1, -1);
6362 LISTVIEW_SetViewInfo(hwnd
, lpss
->styleNew
);
6366 infoPtr
->iconSize
.cx
= GetSystemMetrics(SM_CXSMICON
);
6367 infoPtr
->iconSize
.cy
= GetSystemMetrics(SM_CYSMICON
);
6368 LISTVIEW_SetSize(hwnd
, lpss
->styleNew
, -1, -1);
6369 infoPtr
->nItemWidth
= LISTVIEW_GetItemWidth(hwnd
, lpss
->styleNew
);
6370 infoPtr
->nItemHeight
= LISTVIEW_GetItemHeight(hwnd
, lpss
->styleNew
);
6371 if (lpss
->styleNew
& LVS_ALIGNLEFT
)
6373 LISTVIEW_AlignLeft(hwnd
);
6377 LISTVIEW_AlignTop(hwnd
);
6382 LISTVIEW_SetScroll(hwnd
, lpss
->styleNew
);
6384 /* print unsupported styles */
6385 LISTVIEW_UnsupportedStyles(lpss
->styleNew
);
6387 /* invalidate client area */
6388 InvalidateRect(hwnd
, NULL
, TRUE
);
6396 * Window procedure of the listview control.
6407 LRESULT WINAPI
LISTVIEW_WindowProc(HWND hwnd
, UINT uMsg
, WPARAM wParam
,
6412 case LVM_APPROXIMATEVIEWRECT
:
6413 return LISTVIEW_ApproximateViewRect(hwnd
, (INT
)wParam
,
6414 LOWORD(lParam
), HIWORD(lParam
));
6416 return LISTVIEW_Arrange(hwnd
, (INT
)wParam
);
6418 /* case LVM_CREATEDRAGIMAGE: */
6420 case LVM_DELETEALLITEMS
:
6421 return LISTVIEW_DeleteAllItems(hwnd
);
6423 case LVM_DELETECOLUMN
:
6424 return LISTVIEW_DeleteColumn(hwnd
, (INT
)wParam
);
6426 case LVM_DELETEITEM
:
6427 return LISTVIEW_DeleteItem(hwnd
, (INT
)wParam
);
6429 /* case LVM_EDITLABEL: */
6431 case LVM_ENSUREVISIBLE
:
6432 return LISTVIEW_EnsureVisible(hwnd
, (INT
)wParam
, (BOOL
)lParam
);
6435 return LISTVIEW_FindItem(hwnd
, (INT
)wParam
, (LPLVFINDINFO
)lParam
);
6437 case LVM_GETBKCOLOR
:
6438 return LISTVIEW_GetBkColor(hwnd
);
6440 /* case LVM_GETBKIMAGE: */
6442 case LVM_GETCALLBACKMASK
:
6443 return LISTVIEW_GetCallbackMask(hwnd
);
6445 case LVM_GETCOLUMNA
:
6446 return LISTVIEW_GetColumnA(hwnd
, (INT
)wParam
, (LPLVCOLUMNA
)lParam
);
6448 /* case LVM_GETCOLUMNW: */
6449 /* case LVM_GETCOLUMNORDERARRAY: */
6451 case LVM_GETCOLUMNWIDTH
:
6452 return LISTVIEW_GetColumnWidth(hwnd
, (INT
)wParam
);
6454 case LVM_GETCOUNTPERPAGE
:
6455 return LISTVIEW_GetCountPerPage(hwnd
);
6457 /* case LVM_GETEDITCONTROL: */
6458 /* case LVM_GETEXTENDEDLISTVIEWSTYLE: */
6461 return LISTVIEW_GetHeader(hwnd
);
6463 /* case LVM_GETHOTCURSOR: */
6464 /* case LVM_GETHOTITEM: */
6465 /* case LVM_GETHOVERTIME: */
6467 case LVM_GETIMAGELIST
:
6468 return LISTVIEW_GetImageList(hwnd
, (INT
)wParam
);
6470 /* case LVM_GETISEARCHSTRING: */
6473 return LISTVIEW_GetItemA(hwnd
, (LPLVITEMA
)lParam
);
6475 /* case LVM_GETITEMW: */
6477 case LVM_GETITEMCOUNT
:
6478 return LISTVIEW_GetItemCount(hwnd
);
6480 case LVM_GETITEMPOSITION
:
6481 return LISTVIEW_GetItemPosition(hwnd
, (INT
)wParam
, (LPPOINT
)lParam
);
6483 case LVM_GETITEMRECT
:
6484 return LISTVIEW_GetItemRect(hwnd
, (INT
)wParam
, (LPRECT
)lParam
);
6486 case LVM_GETITEMSPACING
:
6487 return LISTVIEW_GetItemSpacing(hwnd
, (BOOL
)wParam
);
6489 case LVM_GETITEMSTATE
:
6490 return LISTVIEW_GetItemState(hwnd
, (INT
)wParam
, (UINT
)lParam
);
6492 case LVM_GETITEMTEXTA
:
6493 LISTVIEW_GetItemTextA(hwnd
, (INT
)wParam
, (LPLVITEMA
)lParam
);
6496 /* case LVM_GETITEMTEXTW: */
6498 case LVM_GETNEXTITEM
:
6499 return LISTVIEW_GetNextItem(hwnd
, (INT
)wParam
, LOWORD(lParam
));
6501 /* case LVM_GETNUMBEROFWORKAREAS: */
6504 return LISTVIEW_GetOrigin(hwnd
, (LPPOINT
)lParam
);
6506 case LVM_GETSELECTEDCOUNT
:
6507 return LISTVIEW_GetSelectedCount(hwnd
);
6509 case LVM_GETSELECTIONMARK
:
6510 return LISTVIEW_GetSelectionMark(hwnd
);
6512 case LVM_GETSTRINGWIDTHA
:
6513 return LISTVIEW_GetStringWidthA (hwnd
, (LPCSTR
)lParam
);
6515 /* case LVM_GETSTRINGWIDTHW: */
6516 /* case LVM_GETSUBITEMRECT: */
6518 case LVM_GETTEXTBKCOLOR
:
6519 return LISTVIEW_GetTextBkColor(hwnd
);
6521 case LVM_GETTEXTCOLOR
:
6522 return LISTVIEW_GetTextColor(hwnd
);
6524 /* case LVM_GETTOOLTIPS: */
6526 case LVM_GETTOPINDEX
:
6527 return LISTVIEW_GetTopIndex(hwnd
);
6529 /* case LVM_GETUNICODEFORMAT: */
6531 case LVM_GETVIEWRECT
:
6532 return LISTVIEW_GetViewRect(hwnd
, (LPRECT
)lParam
);
6534 /* case LVM_GETWORKAREAS: */
6537 return LISTVIEW_HitTest(hwnd
, (LPLVHITTESTINFO
)lParam
);
6539 case LVM_INSERTCOLUMNA
:
6540 return LISTVIEW_InsertColumnA(hwnd
, (INT
)wParam
,
6541 (LPLVCOLUMNA
)lParam
);
6543 /* case LVM_INSERTCOLUMNW: */
6545 case LVM_INSERTITEMA
:
6546 return LISTVIEW_InsertItemA(hwnd
, (LPLVITEMA
)lParam
);
6548 /* case LVM_INSERTITEMW: */
6550 case LVM_REDRAWITEMS
:
6551 return LISTVIEW_RedrawItems(hwnd
, (INT
)wParam
, (INT
)lParam
);
6553 /* case LVM_SCROLL: */
6554 /* return LISTVIEW_Scroll(hwnd, (INT)wParam, (INT)lParam); */
6556 case LVM_SETBKCOLOR
:
6557 return LISTVIEW_SetBkColor(hwnd
, (COLORREF
)lParam
);
6559 /* case LVM_SETBKIMAGE: */
6561 case LVM_SETCALLBACKMASK
:
6562 return LISTVIEW_SetCallbackMask(hwnd
, (UINT
)wParam
);
6564 case LVM_SETCOLUMNA
:
6565 return LISTVIEW_SetColumnA(hwnd
, (INT
)wParam
, (LPLVCOLUMNA
)lParam
);
6567 /* case LVM_SETCOLUMNW: */
6568 /* case LVM_SETCOLUMNORDERARRAY: */
6570 case LVM_SETCOLUMNWIDTH
:
6571 return LISTVIEW_SetColumnWidth(hwnd
, (INT
)wParam
, (INT
)lParam
);
6573 /* case LVM_SETEXTENDEDLISTVIEWSTYLE: */
6574 /* case LVM_SETHOTCURSOR: */
6575 /* case LVM_SETHOTITEM: */
6576 /* case LVM_SETHOVERTIME: */
6577 /* case LVM_SETICONSPACING: */
6579 case LVM_SETIMAGELIST
:
6580 return LISTVIEW_SetImageList(hwnd
, (INT
)wParam
, (HIMAGELIST
)lParam
);
6583 return LISTVIEW_SetItemA(hwnd
, (LPLVITEMA
)lParam
);
6585 /* case LVM_SETITEMW: */
6587 case LVM_SETITEMCOUNT
:
6588 LISTVIEW_SetItemCount(hwnd
, (INT
)wParam
);
6591 case LVM_SETITEMPOSITION
:
6592 return LISTVIEW_SetItemPosition(hwnd
, (INT
)wParam
, (INT
)LOWORD(lParam
),
6593 (INT
)HIWORD(lParam
));
6595 /* case LVM_SETITEMPOSITION: */
6597 case LVM_SETITEMSTATE
:
6598 return LISTVIEW_SetItemState(hwnd
, (INT
)wParam
, (LPLVITEMA
)lParam
);
6600 case LVM_SETITEMTEXTA
:
6601 return LISTVIEW_SetItemTextA(hwnd
, (INT
)wParam
, (LPLVITEMA
)lParam
);
6603 /* case LVM_SETSELECTIONMARK: */
6605 case LVM_SETTEXTBKCOLOR
:
6606 return LISTVIEW_SetTextBkColor(hwnd
, (COLORREF
)lParam
);
6608 case LVM_SETTEXTCOLOR
:
6609 return LISTVIEW_SetTextColor(hwnd
, (COLORREF
)lParam
);
6611 /* case LVM_SETTOOLTIPS: */
6612 /* case LVM_SETUNICODEFORMAT: */
6613 /* case LVM_SETWORKAREAS: */
6616 return LISTVIEW_SortItems(hwnd
, wParam
, lParam
);
6618 /* case LVM_SUBITEMHITTEST: */
6621 return LISTVIEW_Update(hwnd
, (INT
)wParam
);
6624 /* case WM_COMMAND: */
6627 return LISTVIEW_Create(hwnd
, wParam
, lParam
);
6630 return LISTVIEW_EraseBackground(hwnd
, wParam
, lParam
);
6633 return DLGC_WANTTAB
| DLGC_WANTARROWS
;
6636 return LISTVIEW_GetFont(hwnd
);
6639 return LISTVIEW_HScroll(hwnd
, (INT
)LOWORD(wParam
),
6640 (INT
)HIWORD(wParam
), (HWND
)lParam
);
6643 return LISTVIEW_KeyDown(hwnd
, (INT
)wParam
, (LONG
)lParam
);
6646 return LISTVIEW_KillFocus(hwnd
);
6648 case WM_LBUTTONDBLCLK
:
6649 return LISTVIEW_LButtonDblClk(hwnd
, (WORD
)wParam
, LOWORD(lParam
),
6652 case WM_LBUTTONDOWN
:
6653 return LISTVIEW_LButtonDown(hwnd
, (WORD
)wParam
, LOWORD(lParam
),
6656 return LISTVIEW_LButtonUp(hwnd
, (WORD
)wParam
, LOWORD(lParam
),
6659 /* case WM_MOUSEMOVE: */
6660 /* return LISTVIEW_MouseMove (hwnd, wParam, lParam); */
6663 return LISTVIEW_NCCreate(hwnd
, wParam
, lParam
);
6666 return LISTVIEW_NCDestroy(hwnd
);
6669 return LISTVIEW_Notify(hwnd
, (INT
)wParam
, (LPNMHDR
)lParam
);
6671 case WM_NOTIFYFORMAT
:
6672 return LISTVIEW_NotifyFormat(hwnd
, (HWND
)wParam
, (INT
)lParam
);
6675 return LISTVIEW_Paint(hwnd
, (HDC
)wParam
);
6677 case WM_RBUTTONDBLCLK
:
6678 return LISTVIEW_RButtonDblClk(hwnd
, (WORD
)wParam
, LOWORD(lParam
),
6681 case WM_RBUTTONDOWN
:
6682 return LISTVIEW_RButtonDown(hwnd
, (WORD
)wParam
, LOWORD(lParam
),
6686 return LISTVIEW_RButtonUp(hwnd
, (WORD
)wParam
, LOWORD(lParam
),
6690 return LISTVIEW_SetFocus(hwnd
, (HWND
)wParam
);
6693 return LISTVIEW_SetFont(hwnd
, (HFONT
)wParam
, (WORD
)lParam
);
6695 /* case WM_SETREDRAW: */
6698 return LISTVIEW_Size(hwnd
, (int)SLOWORD(lParam
), (int)SHIWORD(lParam
));
6700 case WM_STYLECHANGED
:
6701 return LISTVIEW_StyleChanged(hwnd
, wParam
, (LPSTYLESTRUCT
)lParam
);
6703 /* case WM_TIMER: */
6706 return LISTVIEW_VScroll(hwnd
, (INT
)LOWORD(wParam
),
6707 (INT
)HIWORD(wParam
), (HWND
)lParam
);
6709 /* case WM_WINDOWPOSCHANGED: */
6710 /* case WM_WININICHANGE: */
6713 if (uMsg
>= WM_USER
)
6715 ERR(listview
, "unknown msg %04x wp=%08x lp=%08lx\n", uMsg
, wParam
,
6719 /* call default window procedure */
6720 return DefWindowProcA(hwnd
, uMsg
, wParam
, lParam
);
6728 * Registers the window class.
6736 VOID
LISTVIEW_Register(VOID
)
6740 if (!GlobalFindAtomA(WC_LISTVIEWA
))
6742 ZeroMemory(&wndClass
, sizeof(WNDCLASSA
));
6743 wndClass
.style
= CS_GLOBALCLASS
| CS_DBLCLKS
;
6744 wndClass
.lpfnWndProc
= (WNDPROC
)LISTVIEW_WindowProc
;
6745 wndClass
.cbClsExtra
= 0;
6746 wndClass
.cbWndExtra
= sizeof(LISTVIEW_INFO
*);
6747 wndClass
.hCursor
= LoadCursorA(0, IDC_ARROWA
);
6748 wndClass
.hbrBackground
= (HBRUSH
)(COLOR_WINDOW
+ 1);
6749 wndClass
.lpszClassName
= WC_LISTVIEWA
;
6750 RegisterClassA(&wndClass
);
6756 * Unregisters the window class.
6764 VOID
LISTVIEW_Unregister(VOID
)
6766 if (GlobalFindAtomA(WC_LISTVIEWA
))
6768 UnregisterClassA(WC_LISTVIEWA
, (HINSTANCE
)NULL
);