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_GetHotCursor : not implemented
34 * LISTVIEW_GetHotItem : not implemented
35 * LISTVIEW_GetHoverTime : not implemented
36 * LISTVIEW_GetISearchString : not implemented
37 * LISTVIEW_GetBkImage : not implemented
38 * LISTVIEW_EditLabel : REPORT (need to implement a timer)
39 * LISTVIEW_GetColumnOrderArray : not implemented
40 * LISTVIEW_Arrange : empty stub
41 * LISTVIEW_FindItem : empty stub
42 * LISTVIEW_ApproximateViewRect : incomplete
43 * LISTVIEW_Scroll : not implemented
44 * LISTVIEW_KeyDown : page up and page down + redo small icon and icon
45 * LISTVIEW_RedrawItems : empty stub
46 * LISTVIEW_Update : not completed
55 DEFAULT_DEBUG_CHANNEL(listview
)
61 /* maximum size of a label */
62 #define DISP_TEXT_SIZE 128
64 /* padding for items in list and small icon display modes */
65 #define WIDTH_PADDING 12
67 /* padding for items in list, report and small icon display modes */
68 #define HEIGHT_PADDING 1
70 /* offset of items in report display mode */
71 #define REPORT_MARGINX 2
73 /* padding for icon in large icon display mode */
74 #define ICON_TOP_PADDING 2
75 #define ICON_BOTTOM_PADDING 2
77 /* padding for label in large icon display mode */
78 #define LABEL_VERT_OFFSET 2
80 /* default label width for items in list and small icon display modes */
81 #define DEFAULT_LABEL_WIDTH 40
83 /* default column width for items in list display mode */
84 #define DEFAULT_COLUMN_WIDTH 96
90 /* retrieve the number of items in the listview */
91 #define GETITEMCOUNT(infoPtr) ((infoPtr)->hdpaItems->nItemCount)
92 #define ListView_LVNotify(hwnd,lCtrlId,plvnm) \
93 (BOOL)SendMessageA((hwnd),WM_NOTIFY,(WPARAM)(INT)lCtrlId,(LPARAM)(LPNMLISTVIEW)(plvnm))
94 #define ListView_Notify(hwnd,lCtrlId,pnmh) \
95 (BOOL)SendMessageA((hwnd),WM_NOTIFY,(WPARAM)(INT)lCtrlId,(LPARAM)(LPNMHDR)(pnmh))
98 * forward declarations
101 static VOID
LISTVIEW_AlignLeft(HWND
);
102 static VOID
LISTVIEW_AlignTop(HWND
);
103 static VOID
LISTVIEW_AddGroupSelection(HWND
, INT
);
104 static VOID
LISTVIEW_AddSelection(HWND
, INT
);
105 static BOOL
LISTVIEW_AddSubItem(HWND
, LPLVITEMA
);
106 static INT
LISTVIEW_FindInsertPosition(HDPA
, INT
);
107 static VOID
LISTVIEW_GetItemDispInfo(HWND
, INT
, LISTVIEW_ITEM
*lpItem
, INT
*,
108 UINT
*, CHAR
**, INT
);
109 static INT
LISTVIEW_GetItemHeight(HWND
, LONG
);
110 static BOOL
LISTVIEW_GetItemPosition(HWND
, INT
, LPPOINT
);
111 static LRESULT
LISTVIEW_GetItemRect(HWND
, INT
, LPRECT
);
112 static INT
LISTVIEW_GetItemWidth(HWND
, LONG
);
113 static INT
LISTVIEW_GetLabelWidth(HWND
, INT
);
114 static LRESULT
LISTVIEW_GetOrigin(HWND
, LPPOINT
);
115 static LISTVIEW_SUBITEM
* LISTVIEW_GetSubItem(HDPA
, INT
);
116 static VOID
LISTVIEW_GetSubItemDispInfo(HWND hwnd
, INT
, LPARAM
,
117 LISTVIEW_SUBITEM
*, INT
, INT
*,
119 static LRESULT
LISTVIEW_GetViewRect(HWND
, LPRECT
);
120 static BOOL
LISTVIEW_InitItem(HWND
, LISTVIEW_ITEM
*, LPLVITEMA
);
121 static BOOL
LISTVIEW_InitSubItem(HWND
, LISTVIEW_SUBITEM
*, LPLVITEMA
);
122 static LRESULT
LISTVIEW_MouseSelection(HWND
, INT
, INT
);
123 static BOOL
LISTVIEW_RemoveColumn(HDPA
, INT
);
124 static VOID
LISTVIEW_RemoveSelections(HWND
, INT
, INT
);
125 static BOOL
LISTVIEW_RemoveSubItem(HDPA
, INT
);
126 static BOOL
LISTVIEW_ScrollView(HWND
, INT
, INT
);
127 static VOID
LISTVIEW_SetGroupSelection(HWND
, INT
);
128 static BOOL
LISTVIEW_SetItem(HWND
, LPLVITEMA
);
129 static VOID
LISTVIEW_SetItemFocus(HWND
, INT
);
130 static BOOL
LISTVIEW_SetItemPosition(HWND
, INT
, INT
, INT
);
131 static VOID
LISTVIEW_SetScroll(HWND
, LONG
);
132 static VOID
LISTVIEW_SetSelection(HWND
, INT
);
133 static VOID
LISTVIEW_SetSize(HWND
, LONG
, LONG
, LONG
);
134 static BOOL
LISTVIEW_SetSubItem(HWND
, LPLVITEMA
);
135 static VOID
LISTVIEW_SetViewInfo(HWND
, LONG
);
136 static LRESULT
LISTVIEW_SetViewRect(HWND
, LPRECT
);
137 static BOOL
LISTVIEW_ToggleSelection(HWND
, INT
);
138 static VOID
LISTVIEW_UnsupportedStyles(LONG lStyle
);
142 * Scrolls the content of the listview.
145 * [I] HWND : window handle
146 * [I] INT : number of horizontal scroll positions
147 * (relative to the current scroll postioon)
148 * [I] INT : number of vertical scroll positions
149 * (relative to the current scroll postioon)
155 static BOOL
LISTVIEW_ScrollView(HWND hwnd
, INT nHScroll
, INT nVScroll
)
157 LISTVIEW_INFO
*infoPtr
= (LISTVIEW_INFO
*)GetWindowLongA(hwnd
, 0);
158 LONG lStyle
= GetWindowLongA(hwnd
, GWL_STYLE
);
159 INT nListWidth
= infoPtr
->rcList
.right
- infoPtr
->rcList
.left
;
160 INT nListHeight
= infoPtr
->rcList
.bottom
- infoPtr
->rcList
.top
;
165 BOOL bResult
= FALSE
;
167 if (((lStyle
& WS_HSCROLL
) != 0) && (nHScroll
!= 0))
169 switch (LVS_TYPEMASK
& lStyle
)
172 nHScrollInc
= nHScroll
* infoPtr
->nItemWidth
;
176 /* TO DO : not implemented at this point. I experiences some
177 problems when performing child window scrolling. */
182 nHScrollInc
= nHScroll
* max(nListWidth
, nListWidth
/ 10);
186 nHScrollPos
= GetScrollPos(hwnd
, SB_HORZ
) + nHScroll
;
189 if (((lStyle
& WS_VSCROLL
) != 0) & (nVScroll
!= 0))
191 switch (LVS_TYPEMASK
& lStyle
)
194 nVScrollInc
= nVScroll
* infoPtr
->nItemHeight
;
195 nVScrollPos
= GetScrollPos(hwnd
, SB_VERT
) + nVScroll
;
200 nVScrollInc
= nVScroll
* max(nListHeight
, nListHeight
/ 10);
201 nVScrollPos
= GetScrollPos(hwnd
, SB_VERT
) + nVScroll
;
206 /* perform scroll operation & set new scroll position */
207 if ((nHScrollInc
!= 0) || (nVScrollInc
!= 0))
210 HDC hdc
= GetDC(hwnd
);
211 ScrollDC(hdc
, -nHScrollInc
, -nVScrollInc
, &infoPtr
->rcList
, NULL
,
213 InvalidateRect(hwnd
, &rc
, TRUE
);
214 SetScrollPos(hwnd
, SB_HORZ
, nHScrollPos
, TRUE
);
215 SetScrollPos(hwnd
, SB_VERT
, nVScrollPos
, TRUE
);
216 ReleaseDC(hwnd
, hdc
);
225 * Prints a message for unsupported window styles.
226 * A kind of TODO list for window styles.
229 * [I] LONG : window style
234 static VOID
LISTVIEW_UnsupportedStyles(LONG lStyle
)
236 if ((LVS_TYPEMASK
& lStyle
) == LVS_EDITLABELS
)
238 FIXME( listview
, " LVS_EDITLABELS\n");
241 if ((LVS_TYPEMASK
& lStyle
) == LVS_NOCOLUMNHEADER
)
243 FIXME( listview
, " LVS_SORTDESCENDING\n");
246 if ((LVS_TYPEMASK
& lStyle
) == LVS_NOLABELWRAP
)
248 FIXME( listview
, " LVS_NOLABELWRAP\n");
251 if ((LVS_TYPEMASK
& lStyle
) == LVS_NOSCROLL
)
253 FIXME( listview
, " LVS_NOSCROLL\n");
256 if ((LVS_TYPEMASK
& lStyle
) == LVS_NOSORTHEADER
)
258 FIXME( listview
, " LVS_NOSORTHEADER\n");
261 if ((LVS_TYPEMASK
& lStyle
) == LVS_OWNERDRAWFIXED
)
263 FIXME( listview
, " LVS_OWNERDRAWFIXED\n");
266 if ((LVS_TYPEMASK
& lStyle
) == LVS_SHAREIMAGELISTS
)
268 FIXME( listview
, " LVS_SHAREIMAGELISTS\n");
271 if ((LVS_TYPEMASK
& lStyle
) == LVS_SHOWSELALWAYS
)
273 FIXME( listview
, " LVS_SHOWSELALWAYS\n");
276 if ((LVS_TYPEMASK
& lStyle
) == LVS_SINGLESEL
)
278 FIXME( listview
, " LVS_SINGLESEL\n");
281 if ((LVS_TYPEMASK
& lStyle
) == LVS_SORTASCENDING
)
283 FIXME( listview
, " LVS_SORTASCENDING\n");
286 if ((LVS_TYPEMASK
& lStyle
) == LVS_SORTDESCENDING
)
288 FIXME( listview
, " LVS_SORTDESCENDING\n");
294 * Aligns the items with the top edge of the window.
297 * [I] HWND : window handle
302 static VOID
LISTVIEW_AlignTop(HWND hwnd
)
304 LISTVIEW_INFO
*infoPtr
= (LISTVIEW_INFO
*)GetWindowLongA(hwnd
, 0);
305 LONG lStyle
= GetWindowLongA(hwnd
, GWL_STYLE
);
306 INT nListWidth
= infoPtr
->rcList
.right
- infoPtr
->rcList
.left
;
311 switch (LVS_TYPEMASK
& lStyle
)
315 ZeroMemory(&ptItem
, sizeof(POINT
));
316 ZeroMemory(&rcView
, sizeof(RECT
));
317 if (nListWidth
> infoPtr
->nItemWidth
)
319 for (i
= 0; i
< GETITEMCOUNT(infoPtr
); i
++)
321 if (ptItem
.x
+ infoPtr
->nItemWidth
> nListWidth
)
324 ptItem
.y
+= infoPtr
->nItemHeight
;
327 LISTVIEW_SetItemPosition(hwnd
, i
, ptItem
.x
, ptItem
.y
);
328 ptItem
.x
+= infoPtr
->nItemWidth
;
329 rcView
.right
= max(rcView
.right
, ptItem
.x
);
334 for (i
= 0; i
< GETITEMCOUNT(infoPtr
); i
++)
336 LISTVIEW_SetItemPosition(hwnd
, i
, ptItem
.x
, ptItem
.y
);
337 ptItem
.x
+= infoPtr
->nItemWidth
;
339 rcView
.right
= ptItem
.x
;
340 rcView
.bottom
= infoPtr
->nItemHeight
;
343 rcView
.bottom
= ptItem
.y
+ infoPtr
->nItemHeight
;
344 LISTVIEW_SetViewRect(hwnd
, &rcView
);
350 * Aligns the items with the left edge of the window.
353 * [I] HWND : window handle
358 static VOID
LISTVIEW_AlignLeft(HWND hwnd
)
360 LISTVIEW_INFO
*infoPtr
= (LISTVIEW_INFO
*)GetWindowLongA(hwnd
, 0);
361 LONG lStyle
= GetWindowLongA(hwnd
, GWL_STYLE
);
362 INT nListHeight
= infoPtr
->rcList
.bottom
- infoPtr
->rcList
.top
;
367 switch (LVS_TYPEMASK
& lStyle
)
371 ZeroMemory(&ptItem
, sizeof(POINT
));
372 ZeroMemory(&rcView
, sizeof(RECT
));
373 if (nListHeight
> infoPtr
->nItemHeight
)
375 for (i
= 0; i
< GETITEMCOUNT(infoPtr
); i
++)
377 if (ptItem
.y
+ infoPtr
->nItemHeight
> nListHeight
)
380 ptItem
.x
+= infoPtr
->nItemWidth
;
383 LISTVIEW_SetItemPosition(hwnd
, i
, ptItem
.x
, ptItem
.y
);
384 ptItem
.y
+= infoPtr
->nItemHeight
;
385 rcView
.bottom
= max(rcView
.bottom
, ptItem
.y
);
390 for (i
= 0; i
< GETITEMCOUNT(infoPtr
); i
++)
392 LISTVIEW_SetItemPosition(hwnd
, i
, ptItem
.x
, ptItem
.y
);
393 ptItem
.y
+= infoPtr
->nItemHeight
;
395 rcView
.bottom
= ptItem
.y
;
396 rcView
.right
= infoPtr
->nItemWidth
;
399 rcView
.right
= ptItem
.x
+ infoPtr
->nItemWidth
;
400 LISTVIEW_SetViewRect(hwnd
, &rcView
);
407 * Retrieves display information.
410 * [I] HWND : window handle
411 * [I] INT : item index
412 * [I] LISTVIEW_ITEM* : listview control item
413 * [O] INT : image index
414 * [O] UINT : state value
415 * [O] CHAR** : string
416 * [I] INT : size of string
421 static VOID
LISTVIEW_GetItemDispInfo(HWND hwnd
, INT nItem
,
422 LISTVIEW_ITEM
*lpItem
, INT
*pnDispImage
,
423 UINT
*puState
, CHAR
**ppszDispText
,
426 LISTVIEW_INFO
*infoPtr
= (LISTVIEW_INFO
*)GetWindowLongA(hwnd
, 0);
427 LONG lCtrlId
= GetWindowLongA(hwnd
, GWL_ID
);
428 NMLVDISPINFOA dispInfo
;
429 ZeroMemory(&dispInfo
, sizeof(NMLVDISPINFOA
));
431 if ((pnDispImage
!= NULL
) && (lpItem
->iImage
== I_IMAGECALLBACK
))
433 dispInfo
.item
.mask
|= LVIF_IMAGE
;
436 if ((ppszDispText
!= NULL
) && (lpItem
->pszText
== LPSTR_TEXTCALLBACKA
))
438 ZeroMemory(*ppszDispText
, sizeof(CHAR
)*nDispTextSize
);
439 dispInfo
.item
.mask
|= LVIF_TEXT
;
440 dispInfo
.item
.pszText
= *ppszDispText
;
441 dispInfo
.item
.cchTextMax
= nDispTextSize
;
444 if ((puState
!= NULL
) && (infoPtr
->uCallbackMask
!= 0))
446 dispInfo
.item
.mask
|= LVIF_STATE
;
447 dispInfo
.item
.stateMask
= infoPtr
->uCallbackMask
;
450 if (dispInfo
.item
.mask
!= 0)
452 dispInfo
.hdr
.hwndFrom
= hwnd
;
453 dispInfo
.hdr
.idFrom
= lCtrlId
;
454 dispInfo
.hdr
.code
= LVN_GETDISPINFOA
;
455 dispInfo
.item
.iItem
= nItem
;
456 dispInfo
.item
.iSubItem
= 0;
457 dispInfo
.item
.lParam
= lpItem
->lParam
;
458 ListView_Notify(GetParent(hwnd
), lCtrlId
, &dispInfo
);
461 if (pnDispImage
!= NULL
)
463 if (dispInfo
.item
.mask
& LVIF_IMAGE
)
465 *pnDispImage
= dispInfo
.item
.iImage
;
469 *pnDispImage
= lpItem
->iImage
;
473 if (ppszDispText
!= NULL
)
475 if (dispInfo
.item
.mask
& LVIF_TEXT
)
477 if (dispInfo
.item
.mask
& LVIF_DI_SETITEM
)
479 Str_SetPtrA(&lpItem
->pszText
, dispInfo
.item
.pszText
);
481 *ppszDispText
= dispInfo
.item
.pszText
;
485 *ppszDispText
= lpItem
->pszText
;
491 if (dispInfo
.item
.mask
& LVIF_STATE
)
493 *puState
= lpItem
->state
;
494 *puState
&= ~dispInfo
.item
.stateMask
;
495 *puState
|= (dispInfo
.item
.state
& dispInfo
.item
.stateMask
);
499 *puState
= lpItem
->state
;
506 * Retrieves subitem display information.
509 * [I] HWND : window handle
510 * [I] INT : item index
511 * [I] LONG : LPARAM of item
512 * [I] LISTVIEW_SUBITEM* : listview control subitem
513 * [I] INT : subitem position/order
514 * [O] INT : image index
515 * [O] UINT : state value
516 * [O] CHAR** : display string
517 * [I] INT : size of string
522 static VOID
LISTVIEW_GetSubItemDispInfo(HWND hwnd
, INT nItem
, LPARAM lParam
,
523 LISTVIEW_SUBITEM
*lpSubItem
,
524 INT nSubItemPos
, INT
*pnDispImage
,
525 CHAR
**ppszDispText
, INT nDispTextSize
)
527 LONG lCtrlId
= GetWindowLongA(hwnd
, GWL_ID
);
528 NMLVDISPINFOA dispInfo
;
529 ZeroMemory(&dispInfo
, sizeof(NMLVDISPINFOA
));
531 if (lpSubItem
== NULL
)
533 ZeroMemory(*ppszDispText
, sizeof(CHAR
)*nDispTextSize
);
534 dispInfo
.item
.mask
|= LVIF_TEXT
;
535 dispInfo
.item
.pszText
= *ppszDispText
;
536 dispInfo
.item
.cchTextMax
= nDispTextSize
;
537 dispInfo
.hdr
.hwndFrom
= hwnd
;
538 dispInfo
.hdr
.idFrom
= lCtrlId
;
539 dispInfo
.hdr
.code
= LVN_GETDISPINFOA
;
540 dispInfo
.item
.iItem
= nItem
;
541 dispInfo
.item
.iSubItem
= nSubItemPos
;
542 dispInfo
.item
.lParam
= lParam
;
543 ListView_Notify(GetParent(hwnd
), lCtrlId
, &dispInfo
);
544 if (dispInfo
.item
.mask
& LVIF_DI_SETITEM
)
546 Str_SetPtrA(&lpSubItem
->pszText
, dispInfo
.item
.pszText
);
548 *ppszDispText
= dispInfo
.item
.pszText
;
552 if ((pnDispImage
!= NULL
) && (lpSubItem
->iImage
== I_IMAGECALLBACK
))
554 dispInfo
.item
.mask
|= LVIF_IMAGE
;
557 if ((ppszDispText
!= NULL
) && (lpSubItem
->pszText
== LPSTR_TEXTCALLBACKA
))
559 ZeroMemory(*ppszDispText
, sizeof(CHAR
)*nDispTextSize
);
560 dispInfo
.item
.mask
|= LVIF_TEXT
;
561 dispInfo
.item
.pszText
= *ppszDispText
;
562 dispInfo
.item
.cchTextMax
= nDispTextSize
;
565 if (dispInfo
.item
.mask
!= 0)
567 dispInfo
.hdr
.hwndFrom
= hwnd
;
568 dispInfo
.hdr
.idFrom
= lCtrlId
;
569 dispInfo
.hdr
.code
= LVN_GETDISPINFOA
;
570 dispInfo
.item
.iItem
= nItem
;
571 dispInfo
.item
.iSubItem
= lpSubItem
->iSubItem
;
572 dispInfo
.item
.lParam
= lParam
;
573 ListView_Notify(GetParent(hwnd
), lCtrlId
, &dispInfo
);
576 if (pnDispImage
!= NULL
)
578 if (dispInfo
.item
.mask
& LVIF_IMAGE
)
580 *pnDispImage
= dispInfo
.item
.iImage
;
584 *pnDispImage
= lpSubItem
->iImage
;
588 if (ppszDispText
!= NULL
)
590 if (dispInfo
.item
.mask
& LVIF_TEXT
)
592 if (dispInfo
.item
.mask
& LVIF_DI_SETITEM
)
594 Str_SetPtrA(&lpSubItem
->pszText
, dispInfo
.item
.pszText
);
596 *ppszDispText
= dispInfo
.item
.pszText
;
600 *ppszDispText
= lpSubItem
->pszText
;
608 * Calculates the width of an item.
611 * [I] HWND : window handle
612 * [I] LONG : window style
615 * Returns item width.
617 static INT
LISTVIEW_GetItemWidth(HWND hwnd
, LONG lStyle
)
619 LISTVIEW_INFO
*infoPtr
= (LISTVIEW_INFO
*)GetWindowLongA(hwnd
, 0);
620 INT nHeaderItemCount
;
626 TRACE(listview
, "(hwnd=%x,lStyle=%lx)\n", hwnd
, lStyle
);
628 switch (LVS_TYPEMASK
& lStyle
)
631 nItemWidth
= infoPtr
->iconSpacing
.cx
;
635 /* calculate width of header */
636 nHeaderItemCount
= Header_GetItemCount(infoPtr
->hwndHeader
);
637 for (i
= 0; i
< nHeaderItemCount
; i
++)
639 if (Header_GetItemRect(infoPtr
->hwndHeader
, i
, &rcHeaderItem
) != 0)
641 nItemWidth
+= (rcHeaderItem
.right
- rcHeaderItem
.left
);
648 for (i
= 0; i
< GETITEMCOUNT(infoPtr
); i
++)
650 nLabelWidth
= LISTVIEW_GetLabelWidth(hwnd
, i
);
651 nItemWidth
= max(nItemWidth
, nLabelWidth
);
654 /* default label size */
655 if (GETITEMCOUNT(infoPtr
) == 0)
657 nItemWidth
= DEFAULT_COLUMN_WIDTH
;
663 nItemWidth
= DEFAULT_LABEL_WIDTH
;
668 nItemWidth
+= WIDTH_PADDING
;
670 if (infoPtr
->himlSmall
!= NULL
)
672 nItemWidth
+= infoPtr
->iconSize
.cx
;
675 if (infoPtr
->himlState
!= NULL
)
677 nItemWidth
+= infoPtr
->iconSize
.cx
;
690 * Calculates the height of an item.
693 * [I] HWND : window handle
694 * [I] LONG : window style
697 * Returns item width.
699 static INT
LISTVIEW_GetItemHeight(HWND hwnd
, LONG lStyle
)
701 LISTVIEW_INFO
*infoPtr
= (LISTVIEW_INFO
*)GetWindowLongA(hwnd
, 0);
707 switch (LVS_TYPEMASK
& lStyle
)
710 nItemHeight
= infoPtr
->iconSpacing
.cy
;
717 hOldFont
= SelectObject(hdc
, infoPtr
->hFont
);
718 GetTextMetricsA(hdc
, &tm
);
719 nItemHeight
= max(tm
.tmHeight
, infoPtr
->iconSize
.cy
) + HEIGHT_PADDING
;
720 SelectObject(hdc
, hOldFont
);
721 ReleaseDC(hwnd
, hdc
);
730 * Sets diplay information (needed for drawing operations).
733 * [I] HWND : window handle
738 static VOID
LISTVIEW_SetViewInfo(HWND hwnd
, LONG lStyle
)
740 LISTVIEW_INFO
*infoPtr
= (LISTVIEW_INFO
*)GetWindowLongA(hwnd
, 0);
741 INT nListHeight
= infoPtr
->rcList
.bottom
- infoPtr
->rcList
.top
;
742 INT nListWidth
= infoPtr
->rcList
.right
- infoPtr
->rcList
.left
;
744 switch (LVS_TYPEMASK
& lStyle
)
747 /* get number of fully visible items per column */
748 infoPtr
->nCountPerColumn
= max(1, nListHeight
/ infoPtr
->nItemHeight
);
752 /* get number of fully visible items per column */
753 infoPtr
->nCountPerColumn
= max(1, nListHeight
/ infoPtr
->nItemHeight
);
755 /* get number of fully visible items per row */
756 infoPtr
->nCountPerRow
= max(1, nListWidth
/ infoPtr
->nItemWidth
);
763 * Adds a block of selections.
766 * [I] HWND : window handle
767 * [I] INT : item index
772 static VOID
LISTVIEW_AddGroupSelection(HWND hwnd
, INT nItem
)
774 LISTVIEW_INFO
*infoPtr
= (LISTVIEW_INFO
*)GetWindowLongA(hwnd
, 0);
775 INT nFirst
= min(infoPtr
->nSelectionMark
, nItem
);
776 INT nLast
= max(infoPtr
->nSelectionMark
, nItem
);
780 lvItem
.state
= LVIS_SELECTED
;
781 lvItem
.stateMask
= LVIS_SELECTED
;
783 for (i
= nFirst
; i
<= nLast
; i
++)
785 ListView_SetItemState(hwnd
, i
, &lvItem
);
788 LISTVIEW_SetItemFocus(hwnd
, nItem
);
789 infoPtr
->nSelectionMark
= nItem
;
794 * Adds a single selection.
797 * [I] HWND : window handle
798 * [I] INT : item index
803 static VOID
LISTVIEW_AddSelection(HWND hwnd
, INT nItem
)
805 LISTVIEW_INFO
*infoPtr
= (LISTVIEW_INFO
*)GetWindowLongA(hwnd
, 0);
808 lvItem
.state
= LVIS_SELECTED
;
809 lvItem
.stateMask
= LVIS_SELECTED
;
811 ListView_SetItemState(hwnd
, nItem
, &lvItem
);
813 LISTVIEW_SetItemFocus(hwnd
, nItem
);
814 infoPtr
->nSelectionMark
= nItem
;
819 * Selects or unselects an item.
822 * [I] HWND : window handle
823 * [I] INT : item index
829 static BOOL
LISTVIEW_ToggleSelection(HWND hwnd
, INT nItem
)
831 LISTVIEW_INFO
*infoPtr
= (LISTVIEW_INFO
*)GetWindowLongA(hwnd
, 0);
835 lvItem
.stateMask
= LVIS_SELECTED
;
837 if (ListView_GetItemState(hwnd
, nItem
, LVIS_SELECTED
) & LVIS_SELECTED
)
840 ListView_SetItemState(hwnd
, nItem
, &lvItem
);
845 lvItem
.state
= LVIS_SELECTED
;
846 ListView_SetItemState(hwnd
, nItem
, &lvItem
);
850 LISTVIEW_SetItemFocus(hwnd
, nItem
);
851 infoPtr
->nSelectionMark
= nItem
;
858 * Sets a single group selection.
861 * [I] HWND : window handle
862 * [I] INT : item index
867 static VOID
LISTVIEW_SetGroupSelection(HWND hwnd
, INT nItem
)
869 LISTVIEW_INFO
*infoPtr
= (LISTVIEW_INFO
*)GetWindowLongA(hwnd
, 0);
870 INT nFirst
= min(infoPtr
->nSelectionMark
, nItem
);
871 INT nLast
= max(infoPtr
->nSelectionMark
, nItem
);
877 LISTVIEW_RemoveSelections(hwnd
, 0, nFirst
- 1);
880 if (nLast
< GETITEMCOUNT(infoPtr
))
882 LISTVIEW_RemoveSelections(hwnd
, nLast
+ 1, GETITEMCOUNT(infoPtr
));
885 lvItem
.state
= LVIS_SELECTED
;
886 lvItem
.stateMask
= LVIS_SELECTED
;
888 for (i
= nFirst
; i
<= nLast
; i
++)
890 ListView_SetItemState(hwnd
, i
, &lvItem
);
893 LISTVIEW_SetItemFocus(hwnd
, nItem
);
898 * Manages the item focus.
901 * [I] HWND : window handle
902 * [I] INT : item index
907 static VOID
LISTVIEW_SetItemFocus(HWND hwnd
, INT nItem
)
909 LISTVIEW_INFO
*infoPtr
= (LISTVIEW_INFO
*)GetWindowLongA(hwnd
, 0);
913 lvItem
.stateMask
= LVIS_FOCUSED
;
914 ListView_SetItemState(hwnd
, infoPtr
->nFocusedItem
, &lvItem
);
916 lvItem
.state
= LVIS_FOCUSED
;
917 lvItem
.stateMask
= LVIS_FOCUSED
;
918 ListView_SetItemState(hwnd
, nItem
, &lvItem
);
920 infoPtr
->nFocusedItem
= nItem
;
922 /* if multiple selection is allowed */
923 ListView_EnsureVisible(hwnd
, nItem
, FALSE
);
928 * Sets a single selection.
931 * [I] HWND : window handle
932 * [I] INT : item index
937 static VOID
LISTVIEW_SetSelection(HWND hwnd
, INT nItem
)
939 LISTVIEW_INFO
*infoPtr
= (LISTVIEW_INFO
*)GetWindowLongA(hwnd
, 0);
944 LISTVIEW_RemoveSelections(hwnd
, 0, nItem
- 1);
947 if (nItem
< GETITEMCOUNT(infoPtr
))
949 LISTVIEW_RemoveSelections(hwnd
, nItem
+ 1, GETITEMCOUNT(infoPtr
));
953 lvItem
.stateMask
= LVIS_FOCUSED
;
954 ListView_SetItemState(hwnd
, infoPtr
->nFocusedItem
, &lvItem
);
956 lvItem
.state
= LVIS_SELECTED
| LVIS_FOCUSED
;
957 lvItem
.stateMask
= LVIS_SELECTED
| LVIS_FOCUSED
;
958 ListView_SetItemState(hwnd
, nItem
, &lvItem
);
960 infoPtr
->nFocusedItem
= nItem
;
961 infoPtr
->nSelectionMark
= nItem
;
966 * Set selection(s) with keyboard.
969 * [I] HWND : window handle
970 * [I] INT : item index
975 static VOID
LISTVIEW_KeySelection(HWND hwnd
, INT nItem
)
977 WORD wShift
= HIWORD(GetKeyState(VK_SHIFT
));
978 WORD wCtrl
= HIWORD(GetKeyState(VK_CONTROL
));
982 LISTVIEW_SetGroupSelection(hwnd
, nItem
);
986 LISTVIEW_SetItemFocus(hwnd
, nItem
);
990 LISTVIEW_SetSelection(hwnd
, nItem
);
992 /* if multiple selection is allowed */
993 ListView_EnsureVisible(hwnd
, nItem
, FALSE
);
999 * Determines the selected item.
1002 * [I] HWND : window handle
1003 * [I] INT : x ccordinate
1004 * [I] INT : y coordinate
1007 * SUCCESS : item index
1010 static LRESULT
LISTVIEW_MouseSelection(HWND hwnd
, INT nPosX
, INT nPosY
)
1012 LISTVIEW_INFO
*infoPtr
= (LISTVIEW_INFO
*)GetWindowLongA(hwnd
, 0);
1016 for (i
= 0; i
< GETITEMCOUNT(infoPtr
); i
++)
1018 rcItem
.left
= LVIR_SELECTBOUNDS
;
1019 if (LISTVIEW_GetItemRect(hwnd
, i
, &rcItem
) == TRUE
)
1021 if ((rcItem
.left
<= nPosX
) && (nPosX
<= rcItem
.right
) &&
1022 (rcItem
.top
<= nPosY
) && (nPosY
<= rcItem
.bottom
))
1034 * Removes all selection states.
1037 * [I] HWND : window handle
1038 * [I] INT : item index
1044 static VOID
LISTVIEW_RemoveSelections(HWND hwnd
, INT nFirst
, INT nLast
)
1050 lvItem
.stateMask
= LVIS_SELECTED
;
1052 for (i
= nFirst
; i
<= nLast
; i
++)
1054 ListView_SetItemState(hwnd
, i
, &lvItem
);
1063 * [IO] HDPA : dynamic pointer array handle
1064 * [I] INT : column index (subitem index)
1070 static BOOL
LISTVIEW_RemoveColumn(HDPA hdpaItems
, INT nSubItem
)
1072 BOOL bResult
= TRUE
;
1076 for (i
= 0; i
< hdpaItems
->nItemCount
; i
++)
1078 hdpaSubItems
= (HDPA
)DPA_GetPtr(hdpaItems
, i
);
1079 if (hdpaSubItems
!= NULL
)
1081 if (LISTVIEW_RemoveSubItem(hdpaSubItems
, nSubItem
) == FALSE
)
1093 * Removes a subitem at a given position.
1096 * [IO] HDPA : dynamic pointer array handle
1097 * [I] INT : subitem index
1103 static BOOL
LISTVIEW_RemoveSubItem(HDPA hdpaSubItems
, INT nSubItem
)
1105 LISTVIEW_SUBITEM
*lpSubItem
;
1108 for (i
= 1; i
< hdpaSubItems
->nItemCount
; i
++)
1110 lpSubItem
= (LISTVIEW_SUBITEM
*)DPA_GetPtr(hdpaSubItems
, i
);
1111 if (lpSubItem
!= NULL
)
1113 if (lpSubItem
->iSubItem
== nSubItem
)
1116 if ((lpSubItem
->pszText
!= NULL
) &&
1117 (lpSubItem
->pszText
!= LPSTR_TEXTCALLBACKA
))
1119 COMCTL32_Free(lpSubItem
->pszText
);
1123 COMCTL32_Free(lpSubItem
);
1125 /* free dpa memory */
1126 if (DPA_DeletePtr(hdpaSubItems
, i
) == NULL
)
1131 else if (lpSubItem
->iSubItem
> nSubItem
)
1143 * Compares the item information.
1146 * [I] LISTVIEW_ITEM *: destination item
1147 * [I] LPLVITEM : source item
1150 * SUCCCESS : TRUE (EQUAL)
1151 * FAILURE : FALSE (NOT EQUAL)
1153 static UINT
LISTVIEW_GetItemChanges(LISTVIEW_ITEM
*lpItem
, LPLVITEMA lpLVItem
)
1157 if ((lpItem
!= NULL
) && (lpLVItem
!= NULL
))
1159 if (lpLVItem
->mask
& LVIF_STATE
)
1161 if ((lpItem
->state
& lpLVItem
->stateMask
) !=
1162 (lpLVItem
->state
& lpLVItem
->stateMask
))
1164 uChanged
|= LVIF_STATE
;
1168 if (lpLVItem
->mask
& LVIF_IMAGE
)
1170 if (lpItem
->iImage
!= lpLVItem
->iImage
)
1172 uChanged
|= LVIF_IMAGE
;
1176 if (lpLVItem
->mask
& LVIF_PARAM
)
1178 if (lpItem
->lParam
!= lpLVItem
->lParam
)
1180 uChanged
|= LVIF_PARAM
;
1184 if (lpLVItem
->mask
& LVIF_INDENT
)
1186 if (lpItem
->iIndent
!= lpLVItem
->iIndent
)
1188 uChanged
|= LVIF_INDENT
;
1192 if (lpLVItem
->mask
& LVIF_TEXT
)
1194 if (lpLVItem
->pszText
== LPSTR_TEXTCALLBACKA
)
1196 if (lpItem
->pszText
!= LPSTR_TEXTCALLBACKA
)
1198 uChanged
|= LVIF_TEXT
;
1203 if (lpItem
->pszText
== LPSTR_TEXTCALLBACKA
)
1205 uChanged
|= LVIF_TEXT
;
1209 if (lpLVItem
->pszText
)
1211 if (lpItem
->pszText
)
1213 if (strcmp(lpLVItem
->pszText
, lpItem
->pszText
) != 0)
1215 uChanged
|= LVIF_TEXT
;
1220 uChanged
|= LVIF_TEXT
;
1225 if (lpItem
->pszText
)
1227 uChanged
|= LVIF_TEXT
;
1239 * Initializes item attributes.
1242 * [I] HWND : window handle
1243 * [O] LISTVIEW_ITEM *: destination item
1244 * [I] LPLVITEM : source item
1250 static BOOL
LISTVIEW_InitItem(HWND hwnd
, LISTVIEW_ITEM
*lpItem
,
1253 LONG lStyle
= GetWindowLongA(hwnd
, GWL_STYLE
);
1254 BOOL bResult
= FALSE
;
1256 if ((lpItem
!= NULL
) && (lpLVItem
!= NULL
))
1260 if (lpLVItem
->mask
& LVIF_STATE
)
1262 lpItem
->state
&= ~lpLVItem
->stateMask
;
1263 lpItem
->state
|= (lpLVItem
->state
& lpLVItem
->stateMask
);
1266 if (lpLVItem
->mask
& LVIF_IMAGE
)
1268 lpItem
->iImage
= lpLVItem
->iImage
;
1271 if (lpLVItem
->mask
& LVIF_PARAM
)
1273 lpItem
->lParam
= lpLVItem
->lParam
;
1276 if (lpLVItem
->mask
& LVIF_INDENT
)
1278 lpItem
->iIndent
= lpLVItem
->iIndent
;
1281 if (lpLVItem
->mask
& LVIF_TEXT
)
1283 if (lpLVItem
->pszText
== LPSTR_TEXTCALLBACKA
)
1285 if ((lStyle
& LVS_SORTASCENDING
) || (lStyle
& LVS_SORTDESCENDING
))
1290 if ((lpItem
->pszText
!= NULL
) &&
1291 (lpItem
->pszText
!= LPSTR_TEXTCALLBACKA
))
1293 COMCTL32_Free(lpItem
->pszText
);
1296 lpItem
->pszText
= LPSTR_TEXTCALLBACKA
;
1300 if (lpItem
->pszText
== LPSTR_TEXTCALLBACKA
)
1302 lpItem
->pszText
= NULL
;
1305 bResult
= Str_SetPtrA(&lpItem
->pszText
, lpLVItem
->pszText
);
1315 * Initializes subitem attributes.
1317 * NOTE: the documentation specifies that the operation fails if the user
1318 * tries to set the indent of a subitem.
1321 * [I] HWND : window handle
1322 * [O] LISTVIEW_SUBITEM *: destination subitem
1323 * [I] LPLVITEM : source subitem
1329 static BOOL
LISTVIEW_InitSubItem(HWND hwnd
, LISTVIEW_SUBITEM
*lpSubItem
,
1332 LONG lStyle
= GetWindowLongA(hwnd
, GWL_STYLE
);
1333 BOOL bResult
= FALSE
;
1335 if ((lpSubItem
!= NULL
) && (lpLVItem
!= NULL
))
1337 if (!(lpLVItem
->mask
& LVIF_INDENT
))
1340 ZeroMemory(lpSubItem
, sizeof(LISTVIEW_SUBITEM
));
1342 lpSubItem
->iSubItem
= lpLVItem
->iSubItem
;
1344 if (lpLVItem
->mask
& LVIF_IMAGE
)
1346 lpSubItem
->iImage
= lpLVItem
->iImage
;
1349 if (lpLVItem
->mask
& LVIF_TEXT
)
1351 if (lpLVItem
->pszText
== LPSTR_TEXTCALLBACKA
)
1353 if ((lStyle
& LVS_SORTASCENDING
) || (lStyle
& LVS_SORTDESCENDING
))
1358 if ((lpSubItem
->pszText
!= NULL
) &&
1359 (lpSubItem
->pszText
!= LPSTR_TEXTCALLBACKA
))
1361 COMCTL32_Free(lpSubItem
->pszText
);
1364 lpSubItem
->pszText
= LPSTR_TEXTCALLBACKA
;
1368 if (lpSubItem
->pszText
== LPSTR_TEXTCALLBACKA
)
1370 lpSubItem
->pszText
= NULL
;
1373 bResult
= Str_SetPtrA(&lpSubItem
->pszText
, lpLVItem
->pszText
);
1384 * Adds a subitem at a given position (column index).
1387 * [I] HWND : window handle
1388 * [I] LPLVITEM : new subitem atttributes
1394 static BOOL
LISTVIEW_AddSubItem(HWND hwnd
, LPLVITEMA lpLVItem
)
1396 LISTVIEW_INFO
*infoPtr
= (LISTVIEW_INFO
*)GetWindowLongA(hwnd
, 0);
1397 LISTVIEW_SUBITEM
*lpSubItem
= NULL
;
1398 BOOL bResult
= FALSE
;
1400 INT nPosition
, nItem
;
1402 if (lpLVItem
!= NULL
)
1404 hdpaSubItems
= (HDPA
)DPA_GetPtr(infoPtr
->hdpaItems
, lpLVItem
->iItem
);
1405 if (hdpaSubItems
!= NULL
)
1407 lpSubItem
= (LISTVIEW_SUBITEM
*)COMCTL32_Alloc(sizeof(LISTVIEW_SUBITEM
));
1408 if (lpSubItem
!= NULL
)
1410 if (LISTVIEW_InitSubItem(hwnd
, lpSubItem
, lpLVItem
) != FALSE
)
1412 nPosition
= LISTVIEW_FindInsertPosition(hdpaSubItems
,
1413 lpSubItem
->iSubItem
);
1414 nItem
= DPA_InsertPtr(hdpaSubItems
, nPosition
, lpSubItem
);
1424 /* cleanup if unsuccessful */
1425 if ((bResult
== FALSE
) && (lpSubItem
!= NULL
))
1427 COMCTL32_Free(lpSubItem
);
1435 * Finds the dpa insert position (array index).
1438 * [I] HWND : window handle
1439 * [I] INT : subitem index
1445 static INT
LISTVIEW_FindInsertPosition(HDPA hdpaSubItems
, INT nSubItem
)
1447 LISTVIEW_SUBITEM
*lpSubItem
;
1450 for (i
= 1; i
< hdpaSubItems
->nItemCount
; i
++)
1452 lpSubItem
= (LISTVIEW_SUBITEM
*)DPA_GetPtr(hdpaSubItems
, i
);
1453 if (lpSubItem
!= NULL
)
1455 if (lpSubItem
->iSubItem
> nSubItem
)
1462 return hdpaSubItems
->nItemCount
;
1467 * Retrieves a listview subitem at a given position (column index).
1470 * [I] HWND : window handle
1471 * [I] INT : subitem index
1477 static LISTVIEW_SUBITEM
* LISTVIEW_GetSubItem(HDPA hdpaSubItems
, INT nSubItem
)
1479 LISTVIEW_SUBITEM
*lpSubItem
;
1482 for (i
= 1; i
< hdpaSubItems
->nItemCount
; i
++)
1484 lpSubItem
= (LISTVIEW_SUBITEM
*)DPA_GetPtr(hdpaSubItems
, i
);
1485 if (lpSubItem
!= NULL
)
1487 if (lpSubItem
->iSubItem
== nSubItem
)
1491 else if (lpSubItem
->iSubItem
> nSubItem
)
1503 * Sets item attributes.
1506 * [I] HWND : window handle
1507 * [I] LPLVITEM : new item atttributes
1513 static BOOL
LISTVIEW_SetItem(HWND hwnd
, LPLVITEMA lpLVItem
)
1515 LISTVIEW_INFO
*infoPtr
= (LISTVIEW_INFO
*)GetWindowLongA(hwnd
, 0);
1516 BOOL bResult
= FALSE
;
1518 LISTVIEW_ITEM
*lpItem
;
1521 LONG lCtrlId
= GetWindowLongA(hwnd
, GWL_ID
);
1523 if (lpLVItem
!= NULL
)
1525 if (lpLVItem
->iSubItem
== 0)
1527 hdpaSubItems
= (HDPA
)DPA_GetPtr(infoPtr
->hdpaItems
, lpLVItem
->iItem
);
1528 if (hdpaSubItems
!= NULL
)
1530 lpItem
= (LISTVIEW_ITEM
*)DPA_GetPtr(hdpaSubItems
, lpLVItem
->iSubItem
);
1533 ZeroMemory(&nmlv
, sizeof(NMLISTVIEW
));
1534 nmlv
.hdr
.hwndFrom
= hwnd
;
1535 nmlv
.hdr
.idFrom
= lCtrlId
;
1536 nmlv
.hdr
.code
= LVN_ITEMCHANGING
;
1537 nmlv
.lParam
= lpItem
->lParam
;
1538 uChanged
= LISTVIEW_GetItemChanges(lpItem
, lpLVItem
);
1541 if (uChanged
& LVIF_STATE
)
1543 nmlv
.uNewState
= lpLVItem
->state
& lpLVItem
->stateMask
;
1544 nmlv
.uOldState
= lpItem
->state
& lpLVItem
->stateMask
;
1547 nmlv
.uChanged
= uChanged
;
1548 nmlv
.iItem
= lpLVItem
->iItem
;
1549 nmlv
.lParam
= lpItem
->lParam
;
1550 /* send LVN_ITEMCHANGING notification */
1551 ListView_LVNotify(GetParent(hwnd
), lCtrlId
, &nmlv
);
1553 /* copy information */
1554 bResult
= LISTVIEW_InitItem(hwnd
, lpItem
, lpLVItem
);
1556 /* send LVN_ITEMCHANGED notification */
1557 nmlv
.hdr
.code
= LVN_ITEMCHANGED
;
1558 ListView_LVNotify(GetParent(hwnd
), lCtrlId
, &nmlv
);
1565 InvalidateRect(hwnd
, NULL
, FALSE
);
1576 * Sets subitem attributes.
1579 * [I] HWND : window handle
1580 * [I] LPLVITEM : new subitem atttributes
1586 static BOOL
LISTVIEW_SetSubItem(HWND hwnd
, LPLVITEMA lpLVItem
)
1588 LISTVIEW_INFO
*infoPtr
= (LISTVIEW_INFO
*)GetWindowLongA(hwnd
, 0);
1589 BOOL bResult
= FALSE
;
1591 LISTVIEW_SUBITEM
*lpSubItem
;
1593 if (lpLVItem
!= NULL
)
1595 if (lpLVItem
->iSubItem
> 0)
1597 hdpaSubItems
= (HDPA
)DPA_GetPtr(infoPtr
->hdpaItems
, lpLVItem
->iItem
);
1598 if (hdpaSubItems
!= NULL
)
1600 /* set subitem only if column is present */
1601 if (Header_GetItemCount(infoPtr
->hwndHeader
) > lpLVItem
->iSubItem
)
1603 lpSubItem
= LISTVIEW_GetSubItem(hdpaSubItems
, lpLVItem
->iSubItem
);
1604 if (lpSubItem
!= NULL
)
1606 bResult
= LISTVIEW_InitSubItem(hwnd
, lpSubItem
, lpLVItem
);
1610 bResult
= LISTVIEW_AddSubItem(hwnd
, lpLVItem
);
1613 InvalidateRect(hwnd
, NULL
, FALSE
);
1624 * Retrieves the index of the item at coordinate (0, 0) of the client area.
1627 * [I] HWND : window handle
1632 static INT
LISTVIEW_GetTopIndex(HWND hwnd
)
1634 LISTVIEW_INFO
*infoPtr
= (LISTVIEW_INFO
*) GetWindowLongA(hwnd
, 0);
1635 LONG lStyle
= GetWindowLongA(hwnd
, GWL_STYLE
);
1638 switch (LVS_TYPEMASK
& lStyle
)
1641 if (lStyle
& WS_HSCROLL
)
1643 nItem
= GetScrollPos(hwnd
, SB_HORZ
) * infoPtr
->nCountPerColumn
;
1648 if (lStyle
& WS_VSCROLL
)
1650 nItem
= GetScrollPos(hwnd
, SB_VERT
);
1660 * Evaluates if scrollbars are needed & sets the scroll range/position.
1663 * [I] HWND : window handle
1664 * [I] LONG : window style
1669 static VOID
LISTVIEW_SetScroll(HWND hwnd
, LONG lStyle
)
1671 LISTVIEW_INFO
*infoPtr
= (LISTVIEW_INFO
*)GetWindowLongA(hwnd
, 0);
1672 INT nListWidth
= infoPtr
->rcList
.right
- infoPtr
->rcList
.left
;
1673 INT nListHeight
= infoPtr
->rcList
.bottom
- infoPtr
->rcList
.top
;
1674 INT nHScrollHeight
= GetSystemMetrics(SM_CYHSCROLL
);
1675 INT nVScrollWidth
= GetSystemMetrics(SM_CXVSCROLL
);
1678 INT nHiddenItemCount
;
1682 INT nPixPerScrollPos
;
1685 TRACE(listview
, "(hwnd=%x,lStyle=%lx)\n", hwnd
, lStyle
);
1687 switch (LVS_TYPEMASK
& lStyle
)
1690 nCountPerPage
= infoPtr
->nCountPerRow
* infoPtr
->nCountPerColumn
;
1691 if (nCountPerPage
< GETITEMCOUNT(infoPtr
))
1693 /* display horizontal scrollbar */
1694 if ((lStyle
& WS_HSCROLL
) == 0)
1696 ShowScrollBar(hwnd
, SB_HORZ
, TRUE
);
1699 /* calculate new scrollbar range */
1700 nHiddenItemCount
= GETITEMCOUNT(infoPtr
) - nCountPerPage
;
1701 if ((nHiddenItemCount
% infoPtr
->nCountPerColumn
) == 0)
1703 nMaxRange
= nHiddenItemCount
/ infoPtr
->nCountPerColumn
;
1707 nMaxRange
= nHiddenItemCount
/ infoPtr
->nCountPerColumn
+ 1;
1710 SetScrollRange(hwnd
, SB_HORZ
, 0, nMaxRange
, FALSE
);
1711 nScrollPos
= ListView_GetTopIndex(hwnd
) / infoPtr
->nCountPerColumn
;
1712 SetScrollPos(hwnd
, SB_HORZ
, nScrollPos
, TRUE
);
1716 /* hide scrollbar */
1717 if ((lStyle
& WS_HSCROLL
) != 0)
1719 ShowScrollBar(hwnd
, SB_HORZ
, FALSE
);
1726 * This section was commented out because I experienced some problems
1727 * with the scrolling of the header control. The idea was to add a
1728 * horizontal scrollbar when the width of the client area was smaller
1729 * than the width of the header control.
1732 /* if (infoPtr->nItemWidth > nListWidth) */
1734 /* if ((lStyle & WS_HSCROLL) == 0) */
1736 /* ShowScrollBar(hwnd, SB_HORZ, TRUE); */
1737 /* LISTVIEW_SetSize(hwnd, lStyle, -1, -1); */
1738 /* LISTVIEW_SetViewInfo(hwnd, lStyle); */
1741 /* nListWidth = infoPtr->rcList.right - infoPtr->rcList.left; */
1742 /* nHiddenWidth = infoPtr->nItemWidth - nListWidth; */
1743 /* nPixPerScrollPos = max(1, nListWidth / 10); */
1745 /* if ((nHiddenWidth % nPixPerScrollPos) == 0) */
1747 /* nMaxRange = nHiddenWidth / nPixPerScrollPos; */
1751 /* nMaxRange = nHiddenWidth / nPixPerScrollPos + 1; */
1754 /* SetScrollRange(hwnd, SB_HORZ, 0, nMaxRange, FALSE); */
1755 /* SetScrollPos(hwnd, SB_HORZ, 0, TRUE); */
1759 /* if ((lStyle & WS_HSCROLL) != 0) */
1761 /* ShowScrollBar(hwnd, SB_HORZ, FASLE); */
1762 /* LISTVIEW_SetSize(hwnd, lStyle, -1, -1); */
1763 /* LISTVIEW_SetViewInfo(hwnd, lStyle); */
1767 if (infoPtr
->nCountPerColumn
< GETITEMCOUNT(infoPtr
))
1769 if ((lStyle
& WS_VSCROLL
) == 0)
1771 if (nListWidth
> nVScrollWidth
)
1773 ShowScrollBar(hwnd
, SB_VERT
, TRUE
);
1774 nListWidth
-= nVScrollWidth
;
1778 /* vertical range & position */
1779 nMaxRange
= GETITEMCOUNT(infoPtr
) - infoPtr
->nCountPerColumn
;
1780 SetScrollRange(hwnd
, SB_VERT
, 0, nMaxRange
, FALSE
);
1781 SetScrollPos(hwnd
, SB_VERT
, ListView_GetTopIndex(hwnd
), TRUE
);
1785 if ((lStyle
& WS_VSCROLL
) != 0)
1787 ShowScrollBar(hwnd
, SB_VERT
, FALSE
);
1788 nListWidth
+= nVScrollWidth
;
1795 if (LISTVIEW_GetViewRect(hwnd
, &rcView
) != FALSE
)
1797 if (rcView
.right
- rcView
.left
> nListWidth
)
1799 if ((lStyle
& WS_HSCROLL
) == 0)
1801 if (nListHeight
> nHScrollHeight
)
1803 ShowScrollBar(hwnd
, SB_HORZ
, TRUE
);
1804 nListHeight
-= nHScrollHeight
;
1808 /* calculate size of hidden items */
1809 nHiddenWidth
= rcView
.right
- rcView
.left
- nListWidth
;
1810 nPixPerScrollPos
= max(1, nListWidth
/ 10);
1812 /* vertical range & position */
1813 if ((nHiddenWidth
% nPixPerScrollPos
) == 0)
1815 nMaxRange
= nHiddenWidth
/ nPixPerScrollPos
;
1819 nMaxRange
= nHiddenWidth
/ nPixPerScrollPos
+ 1;
1822 /* set range and position */
1823 SetScrollRange(hwnd
, SB_HORZ
, 0, nMaxRange
, FALSE
);
1824 SetScrollPos(hwnd
, SB_HORZ
, 0, TRUE
);
1828 if ((lStyle
& WS_HSCROLL
) != 0)
1830 ShowScrollBar(hwnd
, SB_HORZ
, FALSE
);
1831 nListHeight
+= nHScrollHeight
;
1835 if (rcView
.bottom
- rcView
.top
> nListHeight
)
1837 if ((lStyle
& WS_VSCROLL
) == 0)
1839 if (nListWidth
> nVScrollWidth
)
1841 ShowScrollBar(hwnd
, SB_VERT
, TRUE
);
1842 nListWidth
-= nVScrollWidth
;
1846 /* calculate size of hidden items */
1847 nHiddenHeight
= rcView
.bottom
- rcView
.top
- nListHeight
;
1848 nPixPerScrollPos
= max(1, nListHeight
/ 10);
1850 /* set vertical range & position */
1851 if ((nHiddenHeight
% nPixPerScrollPos
) == 0)
1853 nMaxRange
= nHiddenHeight
/ nPixPerScrollPos
;
1857 nMaxRange
= nHiddenHeight
/ nPixPerScrollPos
+ 1;
1860 /* set range and position */
1861 SetScrollRange(hwnd
, SB_VERT
, 0, nMaxRange
, FALSE
);
1862 SetScrollPos(hwnd
, SB_VERT
, 0, TRUE
);
1866 if ((lStyle
& WS_VSCROLL
) != 0)
1868 ShowScrollBar(hwnd
, SB_VERT
, FALSE
);
1869 nListWidth
+= nVScrollWidth
;
1882 * [I] HWND : window handle
1883 * [I] HDC : device context handle
1884 * [I] INT : item index
1885 * [I] LPARAM : item lparam
1886 * [I] LISTVIEW_SUBITEM * : item
1887 * [I] INT : column index (header index)
1888 * [I] RECT * : clipping rectangle
1893 static VOID
LISTVIEW_DrawSubItem(HWND hwnd
, HDC hdc
, INT nItem
, LPARAM lParam
,
1894 LISTVIEW_SUBITEM
*lpSubItem
, INT nColumn
,
1897 LISTVIEW_INFO
*infoPtr
= (LISTVIEW_INFO
*)GetWindowLongA(hwnd
, 0);
1898 CHAR szDispText
[DISP_TEXT_SIZE
];
1899 LPSTR pszDispText
= NULL
;
1901 /* set item colors */
1902 SetBkColor(hdc
, infoPtr
->clrTextBk
);
1903 SetTextColor(hdc
, infoPtr
->clrText
);
1905 pszDispText
= szDispText
;
1906 LISTVIEW_GetSubItemDispInfo(hwnd
, nItem
, lParam
, lpSubItem
, nColumn
, NULL
,
1907 &pszDispText
, DISP_TEXT_SIZE
);
1909 /* draw text : using arbitrary offset of 10 pixels */
1911 ExtTextOutA(hdc
, lprc
->left
, lprc
->top
, ETO_OPAQUE
|ETO_CLIPPED
,
1912 lprc
, pszDispText
, lstrlenA(pszDispText
), NULL
);
1920 * [I] HWND : window handle
1921 * [I] HDC : device context handle
1922 * [I] LISTVIEW_ITEM * : item
1923 * [I] INT : item index
1924 * [I] RECT * : clipping rectangle
1929 static VOID
LISTVIEW_DrawItem(HWND hwnd
, HDC hdc
, LISTVIEW_ITEM
*lpItem
,
1932 LISTVIEW_INFO
*infoPtr
= (LISTVIEW_INFO
*)GetWindowLongA(hwnd
, 0);
1933 CHAR szDispText
[DISP_TEXT_SIZE
];
1934 LPSTR pszDispText
= NULL
;
1940 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
);
1942 pszDispText
= szDispText
;
1943 LISTVIEW_GetItemDispInfo(hwnd
, nItem
, lpItem
, &nImage
, &uState
, &pszDispText
,
1946 if (uState
& LVIS_SELECTED
)
1950 /* set item colors */
1951 SetBkColor(hdc
, GetSysColor(COLOR_HIGHLIGHT
));
1952 SetTextColor(hdc
, GetSysColor(COLOR_HIGHLIGHTTEXT
));
1954 /* set raster mode */
1955 SetROP2(hdc
, R2_XORPEN
);
1961 /* set item colors */
1962 SetBkColor(hdc
, infoPtr
->clrTextBk
);
1963 SetTextColor(hdc
, infoPtr
->clrText
);
1965 /* set raster mode */
1966 SetROP2(hdc
, R2_COPYPEN
);
1970 if (infoPtr
->himlState
!= NULL
)
1972 /* right shift 12 bits to obtain index in image list */
1973 if (bSelected
!= FALSE
)
1975 ImageList_Draw(infoPtr
->himlState
, uState
>> 12, hdc
, rc
.left
,
1976 rc
.top
, ILD_SELECTED
);
1980 ImageList_Draw(infoPtr
->himlState
, uState
>> 12, hdc
, rc
.left
,
1981 rc
.top
, ILD_NORMAL
);
1984 rc
.left
+= infoPtr
->iconSize
.cx
;
1988 if (infoPtr
->himlSmall
!= NULL
)
1990 if (bSelected
!= FALSE
)
1992 ImageList_Draw(infoPtr
->himlSmall
, nImage
, hdc
, rc
.left
,
1993 rc
.top
, ILD_SELECTED
);
1997 ImageList_Draw(infoPtr
->himlSmall
, nImage
, hdc
, rc
.left
,
1998 rc
.top
, ILD_NORMAL
);
2001 rc
.left
+= infoPtr
->iconSize
.cx
;
2004 nLabelWidth
= ListView_GetStringWidthA(hwnd
, pszDispText
);
2005 if (rc
.left
+ nLabelWidth
< rc
.right
)
2007 rc
.right
= rc
.left
+ nLabelWidth
;
2011 ExtTextOutA(hdc
, rc
.left
, rc
.top
, ETO_OPAQUE
|ETO_CLIPPED
,
2012 &rc
, pszDispText
, lstrlenA(pszDispText
), NULL
);
2014 if (lpItem
->state
& LVIS_FOCUSED
)
2016 Rectangle(hdc
, rc
.left
, rc
.top
, rc
.right
, rc
.bottom
);
2022 * Draws an item when in large icon display mode.
2025 * [I] HWND : window handle
2026 * [I] HDC : device context handle
2027 * [I] LISTVIEW_ITEM * : item
2028 * [I] INT : item index
2029 * [I] RECT * : clipping rectangle
2034 static VOID
LISTVIEW_DrawLargeItem(HWND hwnd
, HDC hdc
, LISTVIEW_ITEM
*lpItem
,
2037 LISTVIEW_INFO
*infoPtr
= (LISTVIEW_INFO
*)GetWindowLongA(hwnd
, 0);
2038 CHAR szDispText
[DISP_TEXT_SIZE
];
2039 LPSTR pszDispText
= NULL
;
2047 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
);
2049 pszDispText
= szDispText
;
2050 LISTVIEW_GetItemDispInfo(hwnd
, nItem
, lpItem
, &nImage
, &uState
, &pszDispText
,
2052 if (uState
& LVIS_SELECTED
)
2056 /* set item colors */
2057 SetBkColor(hdc
, GetSysColor(COLOR_HIGHLIGHT
));
2058 SetTextColor(hdc
, GetSysColor(COLOR_HIGHLIGHTTEXT
));
2060 /* set raster mode */
2061 SetROP2(hdc
, R2_XORPEN
);
2067 /* set item colors */
2068 SetBkColor(hdc
, infoPtr
->clrTextBk
);
2069 SetTextColor(hdc
, infoPtr
->clrText
);
2071 /* set raster mode */
2072 SetROP2(hdc
, R2_COPYPEN
);
2075 if (infoPtr
->himlNormal
!= NULL
)
2077 rc
.top
+= ICON_TOP_PADDING
;
2078 nDrawPosX
= rc
.left
+ (infoPtr
->iconSpacing
.cx
- infoPtr
->iconSize
.cx
) / 2;
2079 if (bSelected
!= FALSE
)
2081 ImageList_Draw(infoPtr
->himlNormal
, nImage
, hdc
, nDrawPosX
, rc
.top
,
2086 ImageList_Draw(infoPtr
->himlNormal
, nImage
, hdc
, nDrawPosX
, rc
.top
,
2091 rc
.top
+= infoPtr
->iconSize
.cy
+ ICON_BOTTOM_PADDING
;
2092 nLabelWidth
= ListView_GetStringWidthA(hwnd
, pszDispText
);
2093 nDrawPosX
= infoPtr
->iconSpacing
.cx
- nLabelWidth
;
2096 rc
.left
+= nDrawPosX
/ 2;
2097 rc
.right
= rc
.left
+ nLabelWidth
;
2102 rc
.right
= rc
.left
+ infoPtr
->iconSpacing
.cx
- 1;
2106 GetTextMetricsA(hdc
, &tm
);
2107 rc
.bottom
= rc
.top
+ tm
.tmHeight
+ HEIGHT_PADDING
;
2108 ExtTextOutA(hdc
, rc
.left
, rc
.top
, ETO_OPAQUE
|ETO_CLIPPED
,
2109 &rc
, pszDispText
, lstrlenA(pszDispText
), NULL
);
2111 if (lpItem
->state
& LVIS_FOCUSED
)
2113 Rectangle(hdc
, rc
.left
, rc
.top
, rc
.right
, rc
.bottom
);
2119 * Draws listview items when in report display mode.
2122 * [I] HWND : window handle
2123 * [I] HDC : device context handle
2128 static VOID
LISTVIEW_RefreshReport(HWND hwnd
, HDC hdc
)
2130 LISTVIEW_INFO
*infoPtr
= (LISTVIEW_INFO
*)GetWindowLongA(hwnd
,0);
2131 INT nDrawPosY
= infoPtr
->rcList
.top
;
2132 LISTVIEW_ITEM
*lpItem
;
2133 LISTVIEW_SUBITEM
*lpSubItem
= NULL
;
2134 BOOL bNeedSubItem
= TRUE
;
2142 nItem
= ListView_GetTopIndex(hwnd
);
2143 nLast
= nItem
+ infoPtr
->nCountPerColumn
;
2144 while (nItem
<= nLast
)
2146 hdpaSubItems
= (HDPA
)DPA_GetPtr(infoPtr
->hdpaItems
, nItem
);
2147 if (hdpaSubItems
!= NULL
)
2149 lpItem
= (LISTVIEW_ITEM
*)DPA_GetPtr(hdpaSubItems
, 0);
2152 /* the width of the header items will determine the size of the
2154 Header_GetItemRect(infoPtr
->hwndHeader
, 0, &rcItem
);
2155 rcItem
.left
+= REPORT_MARGINX
;
2156 rcItem
.right
= max(rcItem
.left
, rcItem
.right
- REPORT_MARGINX
);
2157 rcItem
.top
= nDrawPosY
;
2158 rcItem
.bottom
= rcItem
.top
+ infoPtr
->nItemHeight
;
2159 LISTVIEW_DrawItem(hwnd
, hdc
, lpItem
, nItem
, rcItem
);
2162 nColumnCount
= Header_GetItemCount(infoPtr
->hwndHeader
);
2163 for (k
= 1, j
= 1; j
< nColumnCount
; j
++)
2165 Header_GetItemRect(infoPtr
->hwndHeader
, j
, &rcItem
);
2166 rcItem
.left
+= REPORT_MARGINX
;
2167 rcItem
.right
= max(rcItem
.left
, rcItem
.right
- REPORT_MARGINX
);
2168 rcItem
.top
= nDrawPosY
;
2169 rcItem
.bottom
= rcItem
.top
+ infoPtr
->nItemHeight
;
2171 if (k
< hdpaSubItems
->nItemCount
)
2173 if (bNeedSubItem
!= FALSE
)
2175 lpSubItem
= (LISTVIEW_SUBITEM
*)DPA_GetPtr(hdpaSubItems
, k
);
2179 if (lpSubItem
!= NULL
)
2181 if (lpSubItem
->iSubItem
== j
)
2183 LISTVIEW_DrawSubItem(hwnd
, hdc
, nItem
, lpItem
->lParam
, lpSubItem
,
2185 bNeedSubItem
= TRUE
;
2189 LISTVIEW_DrawSubItem(hwnd
, hdc
, nItem
, lpItem
->lParam
, NULL
, j
,
2191 bNeedSubItem
= FALSE
;
2196 LISTVIEW_DrawSubItem(hwnd
, hdc
, nItem
, lpItem
->lParam
, NULL
, j
,
2198 bNeedSubItem
= TRUE
;
2203 LISTVIEW_DrawSubItem(hwnd
, hdc
, nItem
, lpItem
->lParam
, NULL
, j
,
2209 nDrawPosY
+= infoPtr
->nItemHeight
;
2216 * Draws listview items when in list display mode.
2219 * [I] HWND : window handle
2220 * [I] HDC : device context handle
2225 static VOID
LISTVIEW_RefreshList(HWND hwnd
, HDC hdc
)
2227 LISTVIEW_INFO
*infoPtr
= (LISTVIEW_INFO
*)GetWindowLongA(hwnd
, 0);
2228 LISTVIEW_ITEM
*lpItem
;
2233 INT nItem
= ListView_GetTopIndex(hwnd
);
2235 if (infoPtr
->rcList
.right
> 0)
2237 /* get number of display columns */
2238 if (infoPtr
->rcList
.right
% infoPtr
->nItemWidth
== 0)
2240 nColumnCount
= infoPtr
->rcList
.right
/ infoPtr
->nItemWidth
;
2244 nColumnCount
= infoPtr
->rcList
.right
/ infoPtr
->nItemWidth
+ 1;
2247 for (i
= 0; i
< nColumnCount
; i
++)
2250 while ((nItem
< GETITEMCOUNT(infoPtr
)) &&
2251 (j
<infoPtr
->nCountPerColumn
))
2253 hdpaSubItems
= (HDPA
)DPA_GetPtr(infoPtr
->hdpaItems
, nItem
);
2254 if (hdpaSubItems
!= NULL
)
2256 lpItem
= (LISTVIEW_ITEM
*)DPA_GetPtr(hdpaSubItems
, 0);
2259 rc
.top
= j
* infoPtr
->nItemHeight
;
2260 rc
.left
= i
* infoPtr
->nItemWidth
;
2261 rc
.bottom
= rc
.top
+ infoPtr
->nItemHeight
;
2262 rc
.right
= rc
.left
+ infoPtr
->nItemWidth
;
2263 LISTVIEW_DrawItem(hwnd
, hdc
, lpItem
, nItem
, rc
);
2276 * Draws listview items when in icon or small icon display mode.
2279 * [I] HWND : window handle
2280 * [I] HDC : device context handle
2285 static VOID
LISTVIEW_RefreshIcon(HWND hwnd
, HDC hdc
, BOOL bSmall
)
2287 LISTVIEW_INFO
*infoPtr
= (LISTVIEW_INFO
*)GetWindowLongA(hwnd
, 0);
2288 LISTVIEW_ITEM
*lpItem
;
2295 LISTVIEW_GetOrigin(hwnd
, &ptOrigin
);
2297 for (i
= 0; i
< GETITEMCOUNT(infoPtr
); i
++)
2299 LISTVIEW_GetItemPosition(hwnd
, i
, &ptPosition
);
2300 ptPosition
.x
+= ptOrigin
.x
;
2301 ptPosition
.y
+= ptOrigin
.y
;
2303 if (ptPosition
.y
+ infoPtr
->nItemHeight
> infoPtr
->rcList
.top
)
2305 if (ptPosition
.x
+ infoPtr
->nItemWidth
> infoPtr
->rcList
.left
)
2307 if (ptPosition
.y
< infoPtr
->rcList
.bottom
)
2309 if (ptPosition
.x
< infoPtr
->rcList
.right
)
2311 hdpaSubItems
= (HDPA
)DPA_GetPtr(infoPtr
->hdpaItems
, i
);
2312 if (hdpaSubItems
!= NULL
)
2314 lpItem
= (LISTVIEW_ITEM
*)DPA_GetPtr(hdpaSubItems
, 0);
2317 rc
.top
= ptPosition
.y
;
2318 rc
.left
= ptPosition
.x
;
2319 rc
.bottom
= rc
.top
+ infoPtr
->nItemHeight
;
2320 rc
.right
= rc
.left
+ infoPtr
->nItemWidth
;
2321 if (bSmall
== FALSE
)
2323 LISTVIEW_DrawLargeItem(hwnd
, hdc
, lpItem
, i
, rc
);
2327 LISTVIEW_DrawItem(hwnd
, hdc
, lpItem
, i
, rc
);
2340 * Draws listview items.
2343 * [I] HWND : window handle
2344 * [I] HDC : device context handle
2349 static VOID
LISTVIEW_Refresh(HWND hwnd
, HDC hdc
)
2351 LISTVIEW_INFO
*infoPtr
= (LISTVIEW_INFO
*)GetWindowLongA(hwnd
, 0);
2352 LONG lStyle
= GetWindowLongA(hwnd
, GWL_STYLE
);
2357 hOldFont
= SelectObject(hdc
, infoPtr
->hFont
);
2359 /* select the doted pen (for drawing the focus box) */
2360 hPen
= CreatePen(PS_DOT
, 1, 0);
2361 hOldPen
= SelectObject(hdc
, hPen
);
2363 /* select transparent brush (for drawing the focus box) */
2364 SelectObject(hdc
, GetStockObject(NULL_BRUSH
));
2366 switch (LVS_TYPEMASK
& lStyle
)
2369 LISTVIEW_RefreshList(hwnd
, hdc
);
2372 LISTVIEW_RefreshReport(hwnd
, hdc
);
2375 LISTVIEW_RefreshIcon(hwnd
, hdc
, TRUE
);
2378 LISTVIEW_RefreshIcon(hwnd
, hdc
, FALSE
);
2381 /* unselect objects */
2382 SelectObject(hdc
, hOldFont
);
2383 SelectObject(hdc
, hOldPen
);
2392 * Calculates the approximate width and height of a given number of items.
2395 * [I] HWND : window handle
2396 * [I] INT : number of items
2401 * Returns a DWORD. The width in the low word and the height in high word.
2403 static LRESULT
LISTVIEW_ApproximateViewRect(HWND hwnd
, INT nItemCount
,
2404 WORD wWidth
, WORD wHeight
)
2406 LISTVIEW_INFO
*infoPtr
= (LISTVIEW_INFO
*)GetWindowLongA(hwnd
, 0);
2407 LONG lStyle
= GetWindowLongA(hwnd
, GWL_STYLE
);
2408 INT nItemCountPerColumn
= 1;
2409 INT nColumnCount
= 0;
2410 DWORD dwViewRect
= 0;
2412 if (nItemCount
== -1)
2413 nItemCount
= GETITEMCOUNT(infoPtr
);
2415 if (lStyle
& LVS_LIST
)
2417 if (wHeight
== 0xFFFF)
2419 /* use current height */
2420 wHeight
= infoPtr
->rcList
.bottom
;
2423 if (wHeight
< infoPtr
->nItemHeight
)
2425 wHeight
= infoPtr
->nItemHeight
;
2430 if (infoPtr
->nItemHeight
> 0)
2432 nItemCountPerColumn
= wHeight
/ infoPtr
->nItemHeight
;
2433 if (nItemCountPerColumn
== 0)
2434 nItemCountPerColumn
= 1;
2436 if (nItemCount
% nItemCountPerColumn
!= 0)
2437 nColumnCount
= nItemCount
/ nItemCountPerColumn
;
2439 nColumnCount
= nItemCount
/ nItemCountPerColumn
+ 1;
2443 /* Microsoft padding magic */
2444 wHeight
= nItemCountPerColumn
* infoPtr
->nItemHeight
+ 2;
2445 wWidth
= nColumnCount
* infoPtr
->nItemWidth
+ 2;
2447 dwViewRect
= MAKELONG(wWidth
, wHeight
);
2449 else if (lStyle
& LVS_REPORT
)
2453 else if (lStyle
& LVS_SMALLICON
)
2457 else if (lStyle
& LVS_ICON
)
2467 * Arranges listview items in icon display mode.
2470 * [I] HWND : window handle
2471 * [I] INT : alignment code
2477 static LRESULT
LISTVIEW_Arrange(HWND hwnd
, INT nAlignCode
)
2479 LONG lStyle
= GetWindowLongA(hwnd
, GWL_STYLE
);
2480 BOOL bResult
= FALSE
;
2482 if (((LVS_TYPEMASK
& lStyle
) == LVS_ICON
) ||
2483 ((LVS_TYPEMASK
& lStyle
) == LVS_SMALLICON
))
2496 case LVA_SNAPTOGRID
:
2505 /* << LISTVIEW_CreateDragImage >> */
2509 * Removes all listview items and subitems.
2512 * [I] HWND : window handle
2518 static LRESULT
LISTVIEW_DeleteAllItems(HWND hwnd
)
2520 LISTVIEW_INFO
*infoPtr
= (LISTVIEW_INFO
*)GetWindowLongA(hwnd
, 0);
2521 LONG lCtrlId
= GetWindowLongA(hwnd
, GWL_ID
);
2522 LONG lStyle
= GetWindowLongA(hwnd
, GWL_STYLE
);
2523 LISTVIEW_ITEM
*lpItem
;
2524 LISTVIEW_SUBITEM
*lpSubItem
;
2527 BOOL bResult
= FALSE
;
2532 TRACE(listview
, "(hwnd=%x,)\n", hwnd
);
2534 if (GETITEMCOUNT(infoPtr
) > 0)
2536 /* initialize memory */
2537 ZeroMemory(&nmlv
, sizeof(NMLISTVIEW
));
2539 /* send LVN_DELETEALLITEMS notification */
2540 nmlv
.hdr
.hwndFrom
= hwnd
;
2541 nmlv
.hdr
.idFrom
= lCtrlId
;
2542 nmlv
.hdr
.code
= LVN_DELETEALLITEMS
;
2545 /* verify if subsequent LVN_DELETEITEM notifications should be
2547 bSuppress
= ListView_LVNotify(GetParent(hwnd
), lCtrlId
, &nmlv
);
2549 for (i
= 0; i
< GETITEMCOUNT(infoPtr
); i
++)
2551 hdpaSubItems
= (HDPA
)DPA_GetPtr(infoPtr
->hdpaItems
, i
);
2552 if (hdpaSubItems
!= NULL
)
2554 for (j
= 1; j
< hdpaSubItems
->nItemCount
; j
++)
2556 lpSubItem
= (LISTVIEW_SUBITEM
*)DPA_GetPtr(hdpaSubItems
, j
);
2557 if (lpSubItem
!= NULL
)
2559 /* free subitem string */
2560 if ((lpSubItem
->pszText
!= NULL
) &&
2561 (lpSubItem
->pszText
!= LPSTR_TEXTCALLBACKA
))
2563 COMCTL32_Free(lpSubItem
->pszText
);
2567 COMCTL32_Free(lpSubItem
);
2571 lpItem
= (LISTVIEW_ITEM
*)DPA_GetPtr(hdpaSubItems
, 0);
2574 if (bSuppress
== FALSE
)
2576 /* send LVN_DELETEITEM notification */
2577 nmlv
.hdr
.code
= LVN_DELETEITEM
;
2579 nmlv
.lParam
= lpItem
->lParam
;
2580 ListView_LVNotify(GetParent(hwnd
), lCtrlId
, &nmlv
);
2583 /* free item string */
2584 if ((lpItem
->pszText
!= NULL
) &&
2585 (lpItem
->pszText
!= LPSTR_TEXTCALLBACKA
))
2587 COMCTL32_Free(lpItem
->pszText
);
2591 COMCTL32_Free(lpItem
);
2594 DPA_Destroy(hdpaSubItems
);
2598 /* reinitialize listview memory */
2599 bResult
= DPA_DeleteAllPtrs(infoPtr
->hdpaItems
);
2601 /* align items (set position of each item) */
2602 switch (lStyle
& LVS_TYPEMASK
)
2606 if (lStyle
& LVS_ALIGNLEFT
)
2608 LISTVIEW_AlignLeft(hwnd
);
2612 LISTVIEW_AlignTop(hwnd
);
2617 LISTVIEW_SetScroll(hwnd
, lStyle
);
2619 /* invalidate client area (optimization needed) */
2620 InvalidateRect(hwnd
, NULL
, TRUE
);
2628 * Removes a column from the listview control.
2631 * [I] HWND : window handle
2632 * [I] INT : column index
2638 static LRESULT
LISTVIEW_DeleteColumn(HWND hwnd
, INT nColumn
)
2640 LISTVIEW_INFO
*infoPtr
= (LISTVIEW_INFO
*)GetWindowLongA(hwnd
, 0);
2641 LONG lStyle
= GetWindowLongA(hwnd
, GWL_STYLE
);
2642 BOOL bResult
= FALSE
;
2644 if (Header_DeleteItem(infoPtr
->hwndHeader
, nColumn
) != FALSE
)
2646 bResult
= LISTVIEW_RemoveColumn(infoPtr
->hdpaItems
, nColumn
);
2648 /* reset scroll parameters */
2649 if ((lStyle
& LVS_TYPEMASK
) == LVS_REPORT
)
2651 LISTVIEW_SetViewInfo(hwnd
, lStyle
);
2652 LISTVIEW_SetScroll(hwnd
, lStyle
);
2655 /* refresh client area */
2656 InvalidateRect(hwnd
, NULL
, FALSE
);
2664 * Removes an item from the listview control.
2667 * [I] HWND : window handle
2668 * [I] INT : item index
2674 static LRESULT
LISTVIEW_DeleteItem(HWND hwnd
, INT nItem
)
2676 LISTVIEW_INFO
*infoPtr
= (LISTVIEW_INFO
*)GetWindowLongA(hwnd
, 0);
2677 LONG lStyle
= GetWindowLongA(hwnd
, GWL_STYLE
);
2678 LONG lCtrlId
= GetWindowLongA(hwnd
, GWL_ID
);
2680 BOOL bResult
= FALSE
;
2682 LISTVIEW_ITEM
*lpItem
;
2683 LISTVIEW_SUBITEM
*lpSubItem
;
2686 TRACE(listview
, "(hwnd=%x,nItem=%d)\n", hwnd
, nItem
);
2688 if ((nItem
>= 0) && (nItem
< GETITEMCOUNT(infoPtr
)))
2690 /* initialize memory */
2691 ZeroMemory(&nmlv
, sizeof(NMLISTVIEW
));
2693 hdpaSubItems
= (HDPA
)DPA_DeletePtr(infoPtr
->hdpaItems
, nItem
);
2694 if (hdpaSubItems
!= NULL
)
2696 for (i
= 1; i
< hdpaSubItems
->nItemCount
; i
++)
2698 lpSubItem
= (LISTVIEW_SUBITEM
*)DPA_GetPtr(hdpaSubItems
, i
);
2699 if (lpSubItem
!= NULL
)
2701 /* free item string */
2702 if ((lpSubItem
->pszText
!= NULL
) &&
2703 (lpSubItem
->pszText
!= LPSTR_TEXTCALLBACKA
))
2705 COMCTL32_Free(lpSubItem
->pszText
);
2709 COMCTL32_Free(lpSubItem
);
2713 lpItem
= (LISTVIEW_ITEM
*)DPA_GetPtr(hdpaSubItems
, 0);
2716 /* send LVN_DELETEITEM notification */
2717 nmlv
.hdr
.hwndFrom
= hwnd
;
2718 nmlv
.hdr
.idFrom
= lCtrlId
;
2719 nmlv
.hdr
.code
= LVN_DELETEITEM
;
2721 nmlv
.lParam
= lpItem
->lParam
;
2722 SendMessageA(GetParent(hwnd
), WM_NOTIFY
, (WPARAM
)lCtrlId
,
2725 /* free item string */
2726 if ((lpItem
->pszText
!= NULL
) &&
2727 (lpItem
->pszText
!= LPSTR_TEXTCALLBACKA
))
2729 COMCTL32_Free(lpItem
->pszText
);
2733 COMCTL32_Free(lpItem
);
2736 bResult
= DPA_Destroy(hdpaSubItems
);
2739 /* align items (set position of each item) */
2740 switch(lStyle
& LVS_TYPEMASK
)
2744 if (lStyle
& LVS_ALIGNLEFT
)
2746 LISTVIEW_AlignLeft(hwnd
);
2750 LISTVIEW_AlignTop(hwnd
);
2755 LISTVIEW_SetScroll(hwnd
, lStyle
);
2757 /* refresh client area */
2758 InvalidateRect(hwnd
, NULL
, TRUE
);
2764 /* LISTVIEW_EditLabel */
2768 * Ensures the specified item is visible, scrolling into view if necessary.
2771 * [I] HWND : window handle
2772 * [I] INT : item index
2773 * [I] BOOL : partially or entirely visible
2779 static BOOL
LISTVIEW_EnsureVisible(HWND hwnd
, INT nItem
, BOOL bPartial
)
2781 LISTVIEW_INFO
*infoPtr
= (LISTVIEW_INFO
*)GetWindowLongA(hwnd
, 0);
2782 LONG lStyle
= GetWindowLongA(hwnd
, GWL_STYLE
);
2783 INT nListHeight
= infoPtr
->rcList
.bottom
- infoPtr
->rcList
.top
;
2784 INT nListWidth
= infoPtr
->rcList
.right
- infoPtr
->rcList
.left
;
2785 INT nHScrollPos
= 0;
2786 INT nVScrollPos
= 0;
2787 INT nScrollPosHeight
= 0;
2788 INT nScrollPosWidth
= 0;
2790 BOOL bResult
= FALSE
;
2792 /* ALWAYS bPartial == FALSE, FOR NOW! */
2794 rcItem
.left
= LVIR_BOUNDS
;
2795 if (LISTVIEW_GetItemRect(hwnd
, nItem
, &rcItem
) != FALSE
)
2797 if (rcItem
.left
< infoPtr
->rcList
.left
)
2800 switch (LVS_TYPEMASK
& lStyle
)
2803 rcItem
.left
+= infoPtr
->rcList
.left
;
2804 nScrollPosWidth
= infoPtr
->nItemWidth
;
2809 nScrollPosWidth
= max(1, nListWidth
/ 10);
2810 rcItem
.left
+= infoPtr
->rcList
.left
;
2814 if (rcItem
.left
% nScrollPosWidth
== 0)
2816 nHScrollPos
= rcItem
.left
/ nScrollPosWidth
;
2820 nHScrollPos
= rcItem
.left
/ nScrollPosWidth
- 1;
2823 else if (rcItem
.right
> infoPtr
->rcList
.right
)
2826 switch (LVS_TYPEMASK
& lStyle
)
2829 rcItem
.right
-= infoPtr
->rcList
.right
;
2830 nScrollPosWidth
= infoPtr
->nItemWidth
;
2835 nScrollPosWidth
= max(1, nListWidth
/ 10);
2836 rcItem
.right
-= infoPtr
->rcList
.right
;
2840 if (rcItem
.right
% nScrollPosWidth
== 0)
2842 nHScrollPos
= rcItem
.right
/ nScrollPosWidth
;
2846 nHScrollPos
= rcItem
.right
/ nScrollPosWidth
+ 1;
2850 if (rcItem
.top
< infoPtr
->rcList
.top
)
2853 switch (LVS_TYPEMASK
& lStyle
)
2856 rcItem
.top
-= infoPtr
->rcList
.top
;
2857 nScrollPosHeight
= infoPtr
->nItemHeight
;
2862 nScrollPosHeight
= max(1, nListHeight
/ 10);
2863 rcItem
.top
+= infoPtr
->rcList
.top
;
2867 if (rcItem
.top
% nScrollPosHeight
== 0)
2869 nVScrollPos
= rcItem
.top
/ nScrollPosHeight
;
2873 nVScrollPos
= rcItem
.top
/ nScrollPosHeight
- 1;
2876 else if (rcItem
.bottom
> infoPtr
->rcList
.bottom
)
2878 switch (LVS_TYPEMASK
& lStyle
)
2881 rcItem
.bottom
-= infoPtr
->rcList
.bottom
;
2882 nScrollPosHeight
= infoPtr
->nItemHeight
;
2887 nScrollPosHeight
= max(1, nListHeight
/ 10);
2888 rcItem
.bottom
-= infoPtr
->rcList
.bottom
;
2892 if (rcItem
.bottom
% nScrollPosHeight
== 0)
2894 nVScrollPos
= rcItem
.bottom
/ nScrollPosHeight
;
2898 nVScrollPos
= rcItem
.bottom
/ nScrollPosHeight
+ 1;
2902 bResult
= LISTVIEW_ScrollView(hwnd
, nHScrollPos
, nVScrollPos
);
2910 * Searches for an item with specific characteristics.
2913 * [I] HWND : window handle
2914 * [I] INT : base item index
2915 * [I] LPLVFINDINFO : item information to look for
2918 * SUCCESS : index of item
2921 static LRESULT
LISTVIEW_FindItem(HWND hwnd
, INT nStart
,
2922 LPLVFINDINFO lpFindInfo
)
2924 FIXME (listview
, "empty stub!\n");
2931 * Retrieves the background color of the listview control.
2934 * [I] HWND : window handle
2937 * COLORREF associated with the background.
2939 static LRESULT
LISTVIEW_GetBkColor(HWND hwnd
)
2941 LISTVIEW_INFO
*infoPtr
= (LISTVIEW_INFO
*)GetWindowLongA(hwnd
, 0);
2943 return infoPtr
->clrBk
;
2948 * Retrieves the background image of the listview control.
2951 * [I] HWND : window handle
2952 * [O] LPLVMKBIMAGE : background image attributes
2958 /* static LRESULT LISTVIEW_GetBkImage(HWND hwnd, LPLVBKIMAGE lpBkImage) */
2960 /* FIXME (listview, "empty stub!\n"); */
2966 * Retrieves the callback mask.
2969 * [I] HWND : window handle
2974 static UINT
LISTVIEW_GetCallbackMask(HWND hwnd
)
2976 LISTVIEW_INFO
*infoPtr
= (LISTVIEW_INFO
*)GetWindowLongA(hwnd
, 0);
2978 return infoPtr
->uCallbackMask
;
2983 * Retrieves column attributes.
2986 * [I] HWND : window handle
2987 * [I] INT : column index
2988 * [IO] LPLVCOLUMNA : column information
2994 static LRESULT
LISTVIEW_GetColumnA(HWND hwnd
, INT nItem
,
2995 LPLVCOLUMNA lpColumn
)
2997 LISTVIEW_INFO
*infoPtr
= (LISTVIEW_INFO
*)GetWindowLongA(hwnd
, 0);
2999 BOOL bResult
= FALSE
;
3001 if (lpColumn
!= NULL
)
3003 /* initialize memory */
3004 ZeroMemory(&hdi
, sizeof(HDITEMA
));
3006 if (lpColumn
->mask
& LVCF_FMT
)
3008 hdi
.mask
|= HDI_FORMAT
;
3011 if (lpColumn
->mask
& LVCF_WIDTH
)
3013 hdi
.mask
|= HDI_WIDTH
;
3016 if (lpColumn
->mask
& LVCF_TEXT
)
3018 hdi
.mask
|= (HDI_TEXT
| HDI_FORMAT
);
3021 if (lpColumn
->mask
& LVCF_IMAGE
)
3023 hdi
.mask
|= HDI_IMAGE
;
3026 if (lpColumn
->mask
& LVCF_ORDER
)
3028 hdi
.mask
|= HDI_ORDER
;
3031 bResult
= Header_GetItemA(infoPtr
->hwndHeader
, nItem
, &hdi
);
3032 if (bResult
!= FALSE
)
3034 if (lpColumn
->mask
& LVCF_FMT
)
3038 if (hdi
.fmt
& HDF_LEFT
)
3040 lpColumn
->fmt
|= LVCFMT_LEFT
;
3042 else if (hdi
.fmt
& HDF_RIGHT
)
3044 lpColumn
->fmt
|= LVCFMT_RIGHT
;
3046 else if (hdi
.fmt
& HDF_CENTER
)
3048 lpColumn
->fmt
|= LVCFMT_CENTER
;
3051 if (hdi
.fmt
& HDF_IMAGE
)
3053 lpColumn
->fmt
|= LVCFMT_COL_HAS_IMAGES
;
3057 if (lpColumn
->mask
& LVCF_WIDTH
)
3059 lpColumn
->cx
= hdi
.cxy
;
3062 if ((lpColumn
->mask
& LVCF_TEXT
) && (lpColumn
->pszText
) && (hdi
.pszText
))
3064 lstrcpynA (lpColumn
->pszText
, hdi
.pszText
, lpColumn
->cchTextMax
);
3067 if (lpColumn
->mask
& LVCF_IMAGE
)
3069 lpColumn
->iImage
= hdi
.iImage
;
3072 if (lpColumn
->mask
& LVCF_ORDER
)
3074 lpColumn
->iOrder
= hdi
.iOrder
;
3082 /* LISTVIEW_GetColumnW */
3083 /* LISTVIEW_GetColumnOrderArray */
3087 * Retrieves the column width.
3090 * [I] HWND : window handle
3091 * [I] int : column index
3094 * SUCCESS : column width
3097 static LRESULT
LISTVIEW_GetColumnWidth(HWND hwnd
, INT nColumn
)
3099 LISTVIEW_INFO
*infoPtr
= (LISTVIEW_INFO
*)GetWindowLongA(hwnd
, 0);
3100 LONG lStyle
= GetWindowLongA(hwnd
, GWL_STYLE
);
3102 INT nColumnWidth
= 0;
3104 switch (LVS_TYPEMASK
& lStyle
)
3107 nColumnWidth
= infoPtr
->nItemWidth
;
3111 /* get column width from header */
3112 ZeroMemory(&hdi
, sizeof(HDITEMA
));
3113 hdi
.mask
= HDI_WIDTH
;
3114 if (Header_GetItemA(infoPtr
->hwndHeader
, nColumn
, &hdi
) != FALSE
)
3116 nColumnWidth
= hdi
.cxy
;
3121 return nColumnWidth
;
3126 * In list or report display mode, retrieves the number of items that can fit
3127 * vertically in the visible area. In icon or small icon display mode,
3128 * retrieves the total number of visible items.
3131 * [I] HWND : window handle
3134 * Number of fully visible items.
3136 static LRESULT
LISTVIEW_GetCountPerPage(HWND hwnd
)
3138 LISTVIEW_INFO
*infoPtr
= (LISTVIEW_INFO
*)GetWindowLongA(hwnd
, 0);
3139 LONG lStyle
= GetWindowLongA(hwnd
, GWL_STYLE
);
3142 switch (LVS_TYPEMASK
& lStyle
)
3145 if (infoPtr
->rcList
.right
/ infoPtr
->nItemWidth
)
3147 nItemCount
= infoPtr
->nCountPerRow
* infoPtr
->nCountPerColumn
;
3152 nItemCount
= infoPtr
->nCountPerColumn
;
3157 nItemCount
= GETITEMCOUNT(infoPtr
);
3164 /* LISTVIEW_GetEditControl */
3165 /* LISTVIEW_GetExtendedListViewStyle */
3169 * Retrieves the handle to the header control.
3172 * [I] HWND : window handle
3177 static LRESULT
LISTVIEW_GetHeader(HWND hwnd
)
3179 LISTVIEW_INFO
*infoPtr
= (LISTVIEW_INFO
*)GetWindowLongA(hwnd
, 0);
3181 return infoPtr
->hwndHeader
;
3184 /* LISTVIEW_GetHotCursor */
3185 /* LISTVIEW_GetHotItem */
3186 /* LISTVIEW_GetHoverTime */
3190 * Retrieves an image list handle.
3193 * [I] HWND : window handle
3194 * [I] INT : image list identifier
3197 * SUCCESS : image list handle
3200 static LRESULT
LISTVIEW_GetImageList(HWND hwnd
, INT nImageList
)
3202 LISTVIEW_INFO
*infoPtr
= (LISTVIEW_INFO
*)GetWindowLongA(hwnd
, 0);
3203 HIMAGELIST himl
= NULL
;
3208 himl
= infoPtr
->himlNormal
;
3211 himl
= infoPtr
->himlSmall
;
3214 himl
= infoPtr
->himlState
;
3218 return (LRESULT
)himl
;
3221 /* LISTVIEW_GetISearchString */
3225 * Retrieves item attributes.
3228 * [I] HWND : window handle
3229 * [IO] LPLVITEMA : item info
3235 static LRESULT
LISTVIEW_GetItemA(HWND hwnd
, LPLVITEMA lpLVItem
)
3237 LISTVIEW_INFO
*infoPtr
= (LISTVIEW_INFO
*)GetWindowLongA(hwnd
, 0);
3238 LISTVIEW_ITEM
*lpItem
;
3239 LISTVIEW_SUBITEM
*lpSubItem
;
3241 BOOL bResult
= FALSE
;
3243 TRACE(listview
, "(hwnd=%x,lpLVItem=%p)\n", hwnd
, lpLVItem
);
3245 if (lpLVItem
!= NULL
)
3247 if ((lpLVItem
->iItem
>= 0) && (lpLVItem
->iItem
< GETITEMCOUNT(infoPtr
)))
3249 hdpaSubItems
= (HDPA
)DPA_GetPtr(infoPtr
->hdpaItems
, lpLVItem
->iItem
);
3250 if (hdpaSubItems
!= NULL
)
3252 if (lpLVItem
->iSubItem
== 0)
3254 lpItem
= (LISTVIEW_ITEM
*)DPA_GetPtr(hdpaSubItems
, 0);
3259 /* retrieve valid data */
3260 if (lpLVItem
->mask
& LVIF_STATE
)
3262 lpLVItem
->state
= lpItem
->state
& lpLVItem
->stateMask
;
3265 if (lpLVItem
->mask
& LVIF_TEXT
)
3267 if (lpItem
->pszText
== LPSTR_TEXTCALLBACKA
)
3269 lpLVItem
->pszText
= LPSTR_TEXTCALLBACKA
;
3273 bResult
= Str_GetPtrA(lpItem
->pszText
, lpLVItem
->pszText
,
3274 lpLVItem
->cchTextMax
);
3278 if (lpLVItem
->mask
& LVIF_IMAGE
)
3280 lpLVItem
->iImage
= lpItem
->iImage
;
3283 if (lpLVItem
->mask
& LVIF_PARAM
)
3285 lpLVItem
->lParam
= lpItem
->lParam
;
3288 if (lpLVItem
->mask
& LVIF_INDENT
)
3290 lpLVItem
->iIndent
= lpItem
->iIndent
;
3296 lpSubItem
= (LISTVIEW_SUBITEM
*)DPA_GetPtr(hdpaSubItems
,
3297 lpLVItem
->iSubItem
);
3298 if (lpSubItem
!= NULL
)
3302 if (lpLVItem
->mask
& LVIF_TEXT
)
3304 if (lpSubItem
->pszText
== LPSTR_TEXTCALLBACKA
)
3306 lpLVItem
->pszText
= LPSTR_TEXTCALLBACKA
;
3310 bResult
= Str_GetPtrA(lpSubItem
->pszText
, lpLVItem
->pszText
,
3311 lpLVItem
->cchTextMax
);
3315 if (lpLVItem
->mask
& LVIF_IMAGE
)
3317 lpLVItem
->iImage
= lpSubItem
->iImage
;
3328 /* LISTVIEW_GetItemW */
3329 /* LISTVIEW_GetHotCursor */
3330 /* LISTVIEW_GetHotItem */
3331 /* LISTVIEW_GetHoverTime> */
3335 * Retrieves the number of items in the listview control.
3338 * [I] HWND : window handle
3343 static LRESULT
LISTVIEW_GetItemCount(HWND hwnd
)
3345 LISTVIEW_INFO
*infoPtr
= (LISTVIEW_INFO
*)GetWindowLongA(hwnd
, 0);
3347 return GETITEMCOUNT(infoPtr
);
3352 * Retrieves the position (upper-left) of the listview control item.
3355 * [I] HWND : window handle
3356 * [I] INT : item index
3357 * [O] LPPOINT : coordinate information
3363 static BOOL
LISTVIEW_GetItemPosition(HWND hwnd
, INT nItem
,
3364 LPPOINT lpptPosition
)
3366 LISTVIEW_INFO
*infoPtr
= (LISTVIEW_INFO
*)GetWindowLongA(hwnd
, 0);
3367 LONG lStyle
= GetWindowLongA(hwnd
, GWL_STYLE
);
3368 BOOL bResult
= FALSE
;
3370 LISTVIEW_ITEM
*lpItem
;
3373 TRACE(listview
, "(hwnd=%x,nItem=%d,lpptPosition=%p)\n", hwnd
, nItem
,
3376 if ((nItem
>= 0) && (nItem
< GETITEMCOUNT(infoPtr
)) &&
3377 (lpptPosition
!= NULL
))
3379 switch (LVS_TYPEMASK
& lStyle
)
3383 nItem
= nItem
- ListView_GetTopIndex(hwnd
);
3386 nRow
= nItem
% infoPtr
->nCountPerColumn
;
3389 lpptPosition
->x
= (nItem
/ infoPtr
->nCountPerColumn
*
3390 infoPtr
->nItemWidth
);
3391 lpptPosition
->y
= 0;
3395 lpptPosition
->x
= ((nItem
/ infoPtr
->nCountPerColumn
- 1) *
3396 infoPtr
->nItemWidth
);
3397 lpptPosition
->y
= ((nRow
+ infoPtr
->nCountPerColumn
) *
3398 infoPtr
->nItemHeight
);
3403 lpptPosition
->x
= (nItem
/ infoPtr
->nCountPerColumn
*
3404 infoPtr
->nItemWidth
);
3405 lpptPosition
->y
= (nItem
% infoPtr
->nCountPerColumn
*
3406 infoPtr
->nItemHeight
);
3412 lpptPosition
->x
= REPORT_MARGINX
;
3413 lpptPosition
->y
= ((nItem
- ListView_GetTopIndex(hwnd
)) *
3414 infoPtr
->nItemHeight
) + infoPtr
->rcList
.top
;
3419 hdpaSubItems
= (HDPA
)DPA_GetPtr(infoPtr
->hdpaItems
, nItem
);
3420 if (hdpaSubItems
!= NULL
)
3422 lpItem
= (LISTVIEW_ITEM
*)DPA_GetPtr(hdpaSubItems
, 0);
3426 lpptPosition
->x
= lpItem
->ptPosition
.x
;
3427 lpptPosition
->y
= lpItem
->ptPosition
.y
;
3439 * Retrieves the bounding rectangle for a listview control item.
3442 * [I] HWND : window handle
3443 * [I] INT : item index
3444 * [IO] LPRECT : bounding rectangle coordinates
3450 static LRESULT
LISTVIEW_GetItemRect(HWND hwnd
, INT nItem
, LPRECT lprc
)
3452 LISTVIEW_INFO
*infoPtr
= (LISTVIEW_INFO
*)GetWindowLongA(hwnd
, 0);
3453 LONG lStyle
= GetWindowLongA(hwnd
, GWL_STYLE
);
3454 BOOL bResult
= FALSE
;
3463 TRACE(listview
, "(hwnd=%x,nItem=%d,lprc=%p)\n", hwnd
, nItem
, lprc
);
3465 if ((nItem
>= 0) && (nItem
< GETITEMCOUNT(infoPtr
)) && (lprc
!= NULL
))
3467 if (ListView_GetItemPosition(hwnd
, nItem
, &ptItem
) != FALSE
)
3472 switch (LVS_TYPEMASK
& lStyle
)
3475 if (infoPtr
->himlNormal
!= NULL
)
3477 if (LISTVIEW_GetOrigin(hwnd
, &ptOrigin
) != FALSE
)
3480 lprc
->left
= ptItem
.x
+ ptOrigin
.x
;
3481 lprc
->top
= ptItem
.y
+ ptOrigin
.y
;
3482 lprc
->right
= lprc
->left
+ infoPtr
->iconSize
.cx
;
3483 lprc
->bottom
= (lprc
->top
+ infoPtr
->iconSize
.cy
+
3484 ICON_BOTTOM_PADDING
+ ICON_TOP_PADDING
);
3490 if (LISTVIEW_GetOrigin(hwnd
, &ptOrigin
) != FALSE
)
3493 lprc
->left
= ptItem
.x
+ ptOrigin
.x
;
3494 lprc
->top
= ptItem
.y
+ ptOrigin
.y
;
3495 lprc
->bottom
= lprc
->top
+ infoPtr
->nItemHeight
;
3497 if (infoPtr
->himlState
!= NULL
)
3499 lprc
->left
+= infoPtr
->iconSize
.cx
;
3502 if (infoPtr
->himlSmall
!= NULL
)
3504 lprc
->right
= lprc
->left
+ infoPtr
->iconSize
.cx
;
3508 lprc
->right
= lprc
->left
;
3516 lprc
->left
= ptItem
.x
;
3517 lprc
->top
= ptItem
.y
;
3518 lprc
->bottom
= lprc
->top
+ infoPtr
->nItemHeight
;
3520 if (infoPtr
->himlState
!= NULL
)
3522 lprc
->left
+= infoPtr
->iconSize
.cx
;
3525 if (infoPtr
->himlSmall
!= NULL
)
3527 lprc
->right
= lprc
->left
+ infoPtr
->iconSize
.cx
;
3531 lprc
->right
= lprc
->left
;
3538 switch (LVS_TYPEMASK
& lStyle
)
3541 if (infoPtr
->himlNormal
!= NULL
)
3543 if (LISTVIEW_GetOrigin(hwnd
, &ptOrigin
) != FALSE
)
3546 lprc
->left
= ptItem
.x
+ ptOrigin
.x
;
3547 lprc
->top
= (ptItem
.y
+ ptOrigin
.y
+ infoPtr
->iconSize
.cy
+
3548 ICON_BOTTOM_PADDING
+ ICON_TOP_PADDING
);
3549 nLabelWidth
= LISTVIEW_GetLabelWidth(hwnd
, nItem
);
3550 if (infoPtr
->iconSpacing
.cx
- nLabelWidth
> 1)
3552 lprc
->left
+= (infoPtr
->iconSpacing
.cx
- nLabelWidth
) / 2;
3553 lprc
->right
= lprc
->left
+ nLabelWidth
;
3558 lprc
->right
= lprc
->left
+ infoPtr
->iconSpacing
.cx
- 1;
3562 hOldFont
= SelectObject(hdc
, infoPtr
->hFont
);
3563 GetTextMetricsA(hdc
, &tm
);
3564 lprc
->bottom
= lprc
->top
+ tm
.tmHeight
+ HEIGHT_PADDING
;
3565 SelectObject(hdc
, hOldFont
);
3566 ReleaseDC(hwnd
, hdc
);
3572 if (LISTVIEW_GetOrigin(hwnd
, &ptOrigin
) != FALSE
)
3575 nMaxWidth
= lprc
->left
= ptItem
.x
+ ptOrigin
.x
;
3576 lprc
->top
= ptItem
.y
+ ptOrigin
.y
;
3577 lprc
->bottom
= lprc
->top
+ infoPtr
->nItemHeight
;
3579 if (infoPtr
->himlState
!= NULL
)
3581 lprc
->left
+= infoPtr
->iconSize
.cx
;
3584 if (infoPtr
->himlSmall
!= NULL
)
3586 lprc
->left
+= infoPtr
->iconSize
.cx
;
3589 nLabelWidth
= LISTVIEW_GetLabelWidth(hwnd
, nItem
);
3590 if (lprc
->left
+ nLabelWidth
< nMaxWidth
+ infoPtr
->nItemWidth
)
3592 lprc
->right
= lprc
->left
+ nLabelWidth
;
3596 lprc
->right
= nMaxWidth
+ infoPtr
->nItemWidth
;
3604 lprc
->left
= ptItem
.x
;
3605 lprc
->top
= ptItem
.y
;
3606 lprc
->bottom
= lprc
->top
+ infoPtr
->nItemHeight
;
3608 if (infoPtr
->himlState
!= NULL
)
3610 lprc
->left
+= infoPtr
->iconSize
.cx
;
3613 if (infoPtr
->himlSmall
!= NULL
)
3615 lprc
->left
+= infoPtr
->iconSize
.cx
;
3618 lprc
->right
= lprc
->left
+ LISTVIEW_GetLabelWidth(hwnd
, nItem
);
3624 switch (LVS_TYPEMASK
& lStyle
)
3627 if (infoPtr
->himlNormal
!= NULL
)
3629 if (LISTVIEW_GetOrigin(hwnd
, &ptOrigin
) != FALSE
)
3632 lprc
->left
= ptItem
.x
+ ptOrigin
.x
;
3633 lprc
->top
= ptItem
.y
+ ptOrigin
.y
;
3634 lprc
->right
= lprc
->left
+ infoPtr
->iconSpacing
.cx
;
3635 lprc
->bottom
= lprc
->top
+ infoPtr
->iconSpacing
.cy
;
3641 if (LISTVIEW_GetOrigin(hwnd
, &ptOrigin
) != FALSE
)
3644 lprc
->left
= ptItem
.x
+ptOrigin
.x
;
3645 lprc
->right
= lprc
->left
;
3646 lprc
->top
= ptItem
.y
+ ptOrigin
.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
);
3666 lprc
->left
= ptItem
.x
;
3667 lprc
->right
= lprc
->left
;
3668 lprc
->top
= ptItem
.y
;
3669 lprc
->bottom
= lprc
->top
+ infoPtr
->nItemHeight
;
3671 if (infoPtr
->himlState
!= NULL
)
3673 lprc
->right
+= infoPtr
->iconSize
.cx
;
3676 if (infoPtr
->himlSmall
!= NULL
)
3678 lprc
->right
+= infoPtr
->iconSize
.cx
;
3681 lprc
->right
+= LISTVIEW_GetLabelWidth(hwnd
, nItem
);
3686 case LVIR_SELECTBOUNDS
:
3687 switch (LVS_TYPEMASK
& lStyle
)
3690 if (infoPtr
->himlNormal
!= NULL
)
3692 if (LISTVIEW_GetOrigin(hwnd
, &ptOrigin
) != FALSE
)
3695 lprc
->left
= ptItem
.x
+ ptOrigin
.x
;
3696 lprc
->top
= ptItem
.y
+ ptOrigin
.y
;
3697 lprc
->right
= lprc
->left
+ infoPtr
->iconSpacing
.cx
;
3698 lprc
->bottom
= lprc
->top
+ infoPtr
->iconSpacing
.cy
;
3704 if (LISTVIEW_GetOrigin(hwnd
, &ptOrigin
) != FALSE
)
3707 lprc
->left
= ptItem
.x
+ ptOrigin
.x
;
3708 lprc
->top
= ptItem
.y
+ ptOrigin
.y
;
3709 lprc
->bottom
= lprc
->top
+ infoPtr
->nItemHeight
;
3711 if (infoPtr
->himlState
!= NULL
)
3713 lprc
->left
+= infoPtr
->iconSize
.cx
;
3716 lprc
->right
= lprc
->left
;
3718 if (infoPtr
->himlSmall
!= NULL
)
3720 lprc
->right
+= infoPtr
->iconSize
.cx
;
3723 lprc
->right
+= LISTVIEW_GetLabelWidth(hwnd
, nItem
);
3730 lprc
->left
= ptItem
.x
;
3731 lprc
->top
= ptItem
.y
;
3732 lprc
->bottom
= lprc
->top
+ infoPtr
->nItemHeight
;
3734 if (infoPtr
->himlState
!= NULL
)
3736 lprc
->left
+= infoPtr
->iconSize
.cx
;
3739 lprc
->right
= lprc
->left
;
3741 if (infoPtr
->himlSmall
!= NULL
)
3743 lprc
->right
+= infoPtr
->iconSize
.cx
;
3746 lprc
->right
+= LISTVIEW_GetLabelWidth(hwnd
, nItem
);
3759 * Retrieves the width of a label.
3762 * [I] HWND : window handle
3765 * SUCCESS : string width (in pixels)
3769 static INT
LISTVIEW_GetLabelWidth(HWND hwnd
, INT nItem
)
3771 LISTVIEW_INFO
*infoPtr
= (LISTVIEW_INFO
*)GetWindowLongA(hwnd
, 0);
3772 LISTVIEW_ITEM
*lpItem
;
3774 INT nLabelWidth
= 0;
3776 TRACE(listview
, "(hwnd=%x,nItem=%d)\n", hwnd
, nItem
);
3778 hdpaSubItems
= (HDPA
)DPA_GetPtr(infoPtr
->hdpaItems
, nItem
);
3779 if (hdpaSubItems
!= NULL
)
3781 lpItem
= (LISTVIEW_ITEM
*)DPA_GetPtr(hdpaSubItems
, 0);
3784 CHAR szDispText
[DISP_TEXT_SIZE
];
3785 LPSTR pszDispText
= NULL
;
3786 pszDispText
= szDispText
;
3787 LISTVIEW_GetItemDispInfo(hwnd
, nItem
, lpItem
, NULL
, NULL
, &pszDispText
,
3789 nLabelWidth
= ListView_GetStringWidthA(hwnd
, pszDispText
);
3798 * Retrieves the spacing between listview control items.
3801 * [I] HWND : window handle
3802 * [I] BOOL : flag for small or large icon
3805 * Horizontal + vertical spacing
3807 static LRESULT
LISTVIEW_GetItemSpacing(HWND hwnd
, BOOL bSmall
)
3809 LISTVIEW_INFO
*infoPtr
= (LISTVIEW_INFO
*)GetWindowLongA(hwnd
, 0);
3812 if (bSmall
== FALSE
)
3814 lResult
= MAKELONG(infoPtr
->iconSpacing
.cx
, infoPtr
->iconSpacing
.cy
);
3818 /* TODO: need to store width of smallicon item */
3819 lResult
= MAKELONG(0, infoPtr
->nItemHeight
);
3827 * Retrieves the state of a listview control item.
3830 * [I] HWND : window handle
3831 * [I] INT : item index
3832 * [I] UINT : state mask
3835 * State specified by the mask.
3837 static LRESULT
LISTVIEW_GetItemState(HWND hwnd
, INT nItem
, UINT uMask
)
3839 LISTVIEW_INFO
*infoPtr
= (LISTVIEW_INFO
*)GetWindowLongA(hwnd
, 0);
3843 if ((nItem
>= 0) && (nItem
< GETITEMCOUNT(infoPtr
)))
3845 ZeroMemory(&lvItem
, sizeof(LVITEMA
));
3846 lvItem
.iItem
= nItem
;
3847 lvItem
.stateMask
= uMask
;
3848 lvItem
.mask
= LVIF_STATE
;
3849 if (ListView_GetItemA(hwnd
, &lvItem
) != FALSE
)
3851 uState
= lvItem
.state
;
3860 * Retrieves the text of a listview control item or subitem.
3863 * [I] HWND : window handle
3864 * [I] INT : item index
3865 * [IO] LPLVITEMA : item information
3870 static LRESULT
LISTVIEW_GetItemTextA(HWND hwnd
, INT nItem
, LPLVITEMA lpLVItem
)
3872 LISTVIEW_INFO
*infoPtr
= (LISTVIEW_INFO
*)GetWindowLongA(hwnd
, 0);
3873 LISTVIEW_ITEM
*lpItem
;
3874 LISTVIEW_SUBITEM
*lpSubItem
;
3878 if (lpLVItem
!= NULL
)
3880 if ((nItem
>= 0) && (nItem
< GETITEMCOUNT(infoPtr
)))
3882 hdpaSubItems
= (HDPA
)DPA_GetPtr(infoPtr
->hdpaItems
, lpLVItem
->iItem
);
3883 if (hdpaSubItems
!= NULL
)
3885 if (lpLVItem
->iSubItem
== 0)
3887 lpItem
= (LISTVIEW_ITEM
*)DPA_GetPtr(hdpaSubItems
, 0);
3890 if (lpLVItem
->mask
& LVIF_TEXT
)
3892 if (lpItem
->pszText
== LPSTR_TEXTCALLBACKA
)
3894 lpLVItem
->pszText
= LPSTR_TEXTCALLBACKA
;
3898 nLength
= Str_GetPtrA(lpItem
->pszText
, lpLVItem
->pszText
,
3899 lpLVItem
->cchTextMax
);
3906 lpSubItem
= (LISTVIEW_SUBITEM
*)DPA_GetPtr(hdpaSubItems
,
3907 lpLVItem
->iSubItem
);
3908 if (lpSubItem
!= NULL
)
3910 if (lpLVItem
->mask
& LVIF_TEXT
)
3912 if (lpSubItem
->pszText
== LPSTR_TEXTCALLBACKA
)
3914 lpLVItem
->pszText
= LPSTR_TEXTCALLBACKA
;
3918 nLength
= Str_GetPtrA(lpSubItem
->pszText
, lpLVItem
->pszText
,
3919 lpLVItem
->cchTextMax
);
3933 * Searches for an item based on properties + relationships.
3936 * [I] HWND : window handle
3937 * [I] INT : starting search item index
3938 * [I] UINT : relationship flag
3941 * SUCCESS : item index
3944 static LRESULT
LISTVIEW_GetNextItem(HWND hwnd
, INT iStart
, UINT uFlags
)
3946 LISTVIEW_INFO
*infoPtr
= (LISTVIEW_INFO
*)GetWindowLongA(hwnd
, 0);
3947 LONG lStyle
= GetWindowLongA(hwnd
, GWL_STYLE
);
3948 LISTVIEW_ITEM
*lpItem
;
3949 UINT style_mask
= LVS_TYPEMASK
& lStyle
;
3951 INT nItems
= GETITEMCOUNT(infoPtr
);
3952 INT iIndex
= iStart
;
3953 INT eIndex
= nItems
- 1;
3957 INT nCountPerColumn
= max((infoPtr
->rcList
.bottom
- infoPtr
->rcList
.top
) /
3958 infoPtr
->nItemHeight
, 1);
3959 INT nCountPerRow
= max((infoPtr
->rcList
.right
- infoPtr
->rcList
.left
) /
3960 infoPtr
->nItemWidth
, 1);
3962 if(uFlags
& LVNI_ABOVE
) /* moving upwards from iStart */
3964 if(style_mask
== LVS_LIST
|| style_mask
== LVS_REPORT
)
3968 if(lStyle
& LVS_ALIGNLEFT
)
3970 sIndex
= iStart
- (iStart
% nCountPerColumn
);
3974 delta
= -nCountPerRow
;
3977 else if(uFlags
& LVNI_BELOW
) /* moving downwards from iStart */
3979 if(style_mask
== LVS_SMALLICON
|| style_mask
== LVS_ICON
)
3981 if (lStyle
& LVS_ALIGNLEFT
)
3982 eIndex
= iStart
+ (nCountPerColumn
- (iStart
% nCountPerColumn
) - 1);
3984 delta
= nCountPerRow
;
3987 else if(uFlags
& LVNI_TOLEFT
) /* moving to the left of iStart */
3989 if(style_mask
== LVS_LIST
)
3990 delta
= -infoPtr
->nCountPerColumn
;
3991 else if(style_mask
== LVS_SMALLICON
|| style_mask
== LVS_ICON
)
3993 if(style_mask
& LVS_ALIGNLEFT
)
3994 delta
= -nCountPerColumn
;
3997 sIndex
= iStart
- (iStart
% nCountPerRow
);
4001 else if(style_mask
== LVS_REPORT
)
4004 else if(uFlags
& LVNI_TORIGHT
) /* moving to the right of iStart */
4006 if(style_mask
== LVS_LIST
)
4007 delta
= infoPtr
->nCountPerColumn
;
4008 else if(style_mask
== LVS_ICON
|| style_mask
== LVS_SMALLICON
)
4010 if(lStyle
& LVS_ALIGNLEFT
)
4011 delta
= nCountPerColumn
;
4013 eIndex
= iStart
+ (nCountPerRow
- (iStart
% nCountPerRow
) - 1);
4015 else if(style_mask
== LVS_REPORT
)
4019 /* perform come bounds checking before entering the main loop */
4020 if(sIndex
< 0) sIndex
= 0;
4021 if(eIndex
> (nItems
- 1)) eIndex
= (nItems
- 1);
4023 /* build uMask, the mask we are searching for */
4024 if(uFlags
& LVNI_CUT
) uMask
|=LVIS_CUT
;
4025 if(uFlags
& LVNI_DROPHILITED
) uMask
|=LVIS_DROPHILITED
;
4026 if(uFlags
& LVNI_FOCUSED
) uMask
|=LVIS_FOCUSED
;
4027 if(uFlags
& LVNI_SELECTED
) uMask
|=LVIS_SELECTED
;
4029 while(TRUE
) /* searching loop */
4033 if((iIndex
< sIndex
) || (iIndex
> eIndex
))
4036 /* see if flags match */
4037 if(!uMask
|| (LISTVIEW_GetItemState(hwnd
, iIndex
, uMask
) == uMask
))
4043 /* LISTVIEW_GetNumberOfWorkAreas */
4047 * Retrieves the origin coordinates when in icon or small icon display mode.
4050 * [I] HWND : window handle
4051 * [O] LPPOINT : coordinate information
4057 static LRESULT
LISTVIEW_GetOrigin(HWND hwnd
, LPPOINT lpptOrigin
)
4059 LISTVIEW_INFO
*infoPtr
= (LISTVIEW_INFO
*)GetWindowLongA(hwnd
, 0);
4060 LONG lStyle
= GetWindowLongA(hwnd
, GWL_STYLE
);
4061 INT nListWidth
= infoPtr
->rcList
.right
- infoPtr
->rcList
.left
;
4062 INT nListHeight
= infoPtr
->rcList
.bottom
- infoPtr
->rcList
.top
;
4063 BOOL bResult
= FALSE
;
4065 TRACE(listview
, "(hwnd=%x,lpptOrigin=%p)\n", hwnd
, lpptOrigin
);
4067 switch (LVS_TYPEMASK
& lStyle
)
4071 if ((lStyle
& WS_HSCROLL
) != 0)
4073 lpptOrigin
->x
= -GetScrollPos(hwnd
, SB_HORZ
) * nListWidth
/ 10;
4080 if ((lStyle
& WS_VSCROLL
) != 0)
4082 lpptOrigin
->y
= -GetScrollPos(hwnd
, SB_VERT
) * nListHeight
/ 10;
4098 * Retrieves the number of items that are marked as selected.
4101 * [I] HWND : window handle
4104 * Number of items selected.
4106 static LRESULT
LISTVIEW_GetSelectedCount(HWND hwnd
)
4108 LISTVIEW_INFO
*infoPtr
= (LISTVIEW_INFO
*)GetWindowLongA(hwnd
, 0);
4109 INT nSelectedCount
= 0;
4112 for (i
= 0; i
< GETITEMCOUNT(infoPtr
); i
++)
4114 if (ListView_GetItemState(hwnd
, i
, LVIS_SELECTED
) & LVIS_SELECTED
)
4120 return nSelectedCount
;
4125 * Retrieves item index that marks the start of a multiple selection.
4128 * [I] HWND : window handle
4131 * Index number or -1 if there is no selection mark.
4133 static LRESULT
LISTVIEW_GetSelectionMark(HWND hwnd
)
4135 LISTVIEW_INFO
*infoPtr
= (LISTVIEW_INFO
*)GetWindowLongA(hwnd
, 0);
4137 return infoPtr
->nSelectionMark
;
4142 * Retrieves the width of a string.
4145 * [I] HWND : window handle
4148 * SUCCESS : string width (in pixels)
4151 static LRESULT
LISTVIEW_GetStringWidthA(HWND hwnd
, LPCSTR lpszText
)
4153 LISTVIEW_INFO
*infoPtr
= (LISTVIEW_INFO
*)GetWindowLongA(hwnd
, 0);
4154 HFONT hFont
, hOldFont
;
4158 ZeroMemory(&stringSize
, sizeof(SIZE
));
4159 if (lpszText
!= NULL
)
4161 hFont
= infoPtr
->hFont
? infoPtr
->hFont
: infoPtr
->hDefaultFont
;
4163 hOldFont
= SelectObject(hdc
, hFont
);
4164 GetTextExtentPointA(hdc
, lpszText
, lstrlenA(lpszText
), &stringSize
);
4165 SelectObject(hdc
, hOldFont
);
4166 ReleaseDC(hwnd
, hdc
);
4169 return stringSize
.cx
;
4174 * Retrieves the text backgound color.
4177 * [I] HWND : window handle
4180 * COLORREF associated with the the background.
4182 static LRESULT
LISTVIEW_GetTextBkColor(HWND hwnd
)
4184 LISTVIEW_INFO
*infoPtr
= (LISTVIEW_INFO
*)GetWindowLongA(hwnd
, 0);
4186 return infoPtr
->clrTextBk
;
4191 * Retrieves the text color.
4194 * [I] HWND : window handle
4197 * COLORREF associated with the text.
4199 static LRESULT
LISTVIEW_GetTextColor(HWND hwnd
)
4201 LISTVIEW_INFO
*infoPtr
= (LISTVIEW_INFO
*)GetWindowLongA(hwnd
, 0);
4203 return infoPtr
->clrText
;
4208 * Set the bounding rectangle of all the items.
4211 * [I] HWND : window handle
4212 * [I] LPRECT : bounding rectangle
4218 static LRESULT
LISTVIEW_SetViewRect(HWND hwnd
, LPRECT lprcView
)
4220 LISTVIEW_INFO
*infoPtr
= (LISTVIEW_INFO
*)GetWindowLongA(hwnd
, 0);
4221 LONG lStyle
= GetWindowLongA(hwnd
, GWL_STYLE
);
4222 BOOL bResult
= FALSE
;
4224 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
);
4226 if (lprcView
!= NULL
)
4228 switch (lStyle
& LVS_TYPEMASK
)
4233 infoPtr
->rcView
.left
= lprcView
->left
;
4234 infoPtr
->rcView
.top
= lprcView
->top
;
4235 infoPtr
->rcView
.right
= lprcView
->right
;
4236 infoPtr
->rcView
.bottom
= lprcView
->bottom
;
4246 * Retrieves the bounding rectangle of all the items.
4249 * [I] HWND : window handle
4250 * [O] LPRECT : bounding rectangle
4256 static LRESULT
LISTVIEW_GetViewRect(HWND hwnd
, LPRECT lprcView
)
4258 LISTVIEW_INFO
*infoPtr
= (LISTVIEW_INFO
*)GetWindowLongA(hwnd
, 0);
4259 BOOL bResult
= FALSE
;
4262 TRACE(listview
, "(hwnd=%x,lprcView=%p)\n", hwnd
, lprcView
);
4264 if (lprcView
!= NULL
)
4266 bResult
= LISTVIEW_GetOrigin(hwnd
, &ptOrigin
);
4267 if (bResult
!= FALSE
)
4269 lprcView
->left
= infoPtr
->rcView
.left
+ ptOrigin
.x
;
4270 lprcView
->top
= infoPtr
->rcView
.top
+ ptOrigin
.y
;
4271 lprcView
->right
= infoPtr
->rcView
.right
+ ptOrigin
.x
;
4272 lprcView
->bottom
= infoPtr
->rcView
.bottom
+ ptOrigin
.y
;
4275 TRACE(listview
, "(lprcView->left=%d,lprcView->top=%d,lprcView->right=%d,lprcView->bottom=%d)\n", lprcView
->left
, lprcView
->top
, lprcView
->right
, lprcView
->bottom
);
4284 * Determines which section of the item was selected (if any).
4287 * [I] HWND : window handle
4288 * [IO] LPLVHITTESTINFO : hit test information
4291 * SUCCESS : item index
4294 static INT
LISTVIEW_HitTestItem(HWND hwnd
, LPLVHITTESTINFO lpHitTestInfo
)
4296 LISTVIEW_INFO
*infoPtr
= (LISTVIEW_INFO
*)GetWindowLongA(hwnd
, 0);
4300 for (i
= 0; i
< GETITEMCOUNT(infoPtr
); i
++)
4302 rcItem
.left
= LVIR_BOUNDS
;
4303 if (LISTVIEW_GetItemRect(hwnd
, i
, &rcItem
) != FALSE
)
4305 rcItem
.left
= LVIR_ICON
;
4306 if (LISTVIEW_GetItemRect(hwnd
, i
, &rcItem
) != FALSE
)
4308 if ((lpHitTestInfo
->pt
.x
>= rcItem
.left
) &&
4309 (lpHitTestInfo
->pt
.x
<= rcItem
.right
) &&
4310 (lpHitTestInfo
->pt
.y
>= rcItem
.top
) &&
4311 (lpHitTestInfo
->pt
.y
<= rcItem
.bottom
))
4313 lpHitTestInfo
->flags
= LVHT_ONITEMICON
| LVHT_ONITEM
;
4314 lpHitTestInfo
->iItem
= i
;
4315 lpHitTestInfo
->iSubItem
= 0;
4320 rcItem
.left
= LVIR_LABEL
;
4321 if (LISTVIEW_GetItemRect(hwnd
, i
, &rcItem
) != FALSE
)
4323 if ((lpHitTestInfo
->pt
.x
>= rcItem
.left
) &&
4324 (lpHitTestInfo
->pt
.x
<= rcItem
.right
) &&
4325 (lpHitTestInfo
->pt
.y
>= rcItem
.top
) &&
4326 (lpHitTestInfo
->pt
.y
<= rcItem
.bottom
))
4328 lpHitTestInfo
->flags
= LVHT_ONITEMLABEL
| LVHT_ONITEM
;
4329 lpHitTestInfo
->iItem
= i
;
4330 lpHitTestInfo
->iSubItem
= 0;
4335 lpHitTestInfo
->flags
= LVHT_ONITEMSTATEICON
| LVHT_ONITEM
;
4336 lpHitTestInfo
->iItem
= i
;
4337 lpHitTestInfo
->iSubItem
= 0;
4342 lpHitTestInfo
->flags
= LVHT_NOWHERE
;
4349 * Determines wich listview item is located at the specified position.
4352 * [I] HWND : window handle
4353 * [IO} LPLVHITTESTINFO : hit test information
4356 * SUCCESS : item index
4359 static LRESULT
LISTVIEW_HitTest(HWND hwnd
, LPLVHITTESTINFO lpHitTestInfo
)
4361 LISTVIEW_INFO
*infoPtr
= (LISTVIEW_INFO
*)GetWindowLongA(hwnd
, 0);
4364 lpHitTestInfo
->flags
= 0;
4365 if (infoPtr
->rcList
.left
> lpHitTestInfo
->pt
.x
)
4367 lpHitTestInfo
->flags
= LVHT_TOLEFT
;
4369 else if (infoPtr
->rcList
.right
< lpHitTestInfo
->pt
.x
)
4371 lpHitTestInfo
->flags
= LVHT_TORIGHT
;
4374 if (infoPtr
->rcList
.top
> lpHitTestInfo
->pt
.y
)
4376 lpHitTestInfo
->flags
|= LVHT_ABOVE
;
4378 else if (infoPtr
->rcList
.bottom
< lpHitTestInfo
->pt
.y
)
4380 lpHitTestInfo
->flags
|= LVHT_BELOW
;
4383 if (lpHitTestInfo
->flags
== 0)
4385 nItem
= LISTVIEW_HitTestItem(hwnd
, lpHitTestInfo
);
4393 * Inserts a new column.
4396 * [I] HWND : window handle
4397 * [I] INT : column index
4398 * [I] LPLVCOLUMNA : column information
4401 * SUCCESS : new column index
4404 static LRESULT
LISTVIEW_InsertColumnA(HWND hwnd
, INT nColumn
,
4405 LPLVCOLUMNA lpColumn
)
4407 LISTVIEW_INFO
*infoPtr
= (LISTVIEW_INFO
*)GetWindowLongA(hwnd
, 0);
4408 LONG lStyle
= GetWindowLongA(hwnd
, GWL_STYLE
);
4410 INT nNewColumn
= -1;
4412 TRACE(listview
,"(hwnd=%x,nColumn=%d,lpColumn=%p)\n",hwnd
, nColumn
, lpColumn
);
4414 if (lpColumn
!= NULL
)
4416 /* initialize memory */
4417 ZeroMemory(&hdi
, sizeof(HDITEMA
));
4419 if (lpColumn
->mask
& LVCF_FMT
)
4421 /* format member is valid */
4422 hdi
.mask
|= HDI_FORMAT
;
4424 /* set text alignment (leftmost column must be left-aligned) */
4427 hdi
.fmt
|= HDF_LEFT
;
4431 if (lpColumn
->fmt
& LVCFMT_LEFT
)
4433 hdi
.fmt
|= HDF_LEFT
;
4435 else if (lpColumn
->fmt
& LVCFMT_RIGHT
)
4437 hdi
.fmt
|= HDF_RIGHT
;
4439 else if (lpColumn
->fmt
& LVCFMT_CENTER
)
4441 hdi
.fmt
|= HDF_CENTER
;
4445 if (lpColumn
->fmt
& LVCFMT_BITMAP_ON_RIGHT
)
4447 hdi
.fmt
|= HDF_BITMAP_ON_RIGHT
;
4451 if (lpColumn
->fmt
& LVCFMT_COL_HAS_IMAGES
)
4456 if (lpColumn
->fmt
& LVCFMT_IMAGE
)
4458 hdi
.fmt
|= HDF_IMAGE
;
4459 hdi
.iImage
= I_IMAGECALLBACK
;
4463 if (lpColumn
->mask
& LVCF_WIDTH
)
4465 hdi
.mask
|= HDI_WIDTH
;
4466 hdi
.cxy
= lpColumn
->cx
;
4469 if (lpColumn
->mask
& LVCF_TEXT
)
4471 hdi
.mask
|= HDI_TEXT
| HDI_FORMAT
;
4472 hdi
.pszText
= lpColumn
->pszText
;
4473 hdi
.cchTextMax
= lstrlenA(lpColumn
->pszText
);
4474 hdi
.fmt
|= HDF_STRING
;
4477 if (lpColumn
->mask
& LVCF_IMAGE
)
4479 hdi
.mask
|= HDI_IMAGE
;
4480 hdi
.iImage
= lpColumn
->iImage
;
4483 if (lpColumn
->mask
& LVCF_ORDER
)
4485 hdi
.mask
|= HDI_ORDER
;
4486 hdi
.iOrder
= lpColumn
->iOrder
;
4489 /* insert item in header control */
4490 nNewColumn
= SendMessageA(infoPtr
->hwndHeader
, HDM_INSERTITEMA
,
4491 (WPARAM
)nColumn
, (LPARAM
)&hdi
);
4493 LISTVIEW_SetScroll(hwnd
, lStyle
);
4494 InvalidateRect(hwnd
, NULL
, FALSE
);
4500 /* LISTVIEW_InsertColumnW */
4504 * Inserts a new item in the listview control.
4507 * [I] HWND : window handle
4508 * [I] LPLVITEMA : item information
4511 * SUCCESS : new item index
4514 static LRESULT
LISTVIEW_InsertItemA(HWND hwnd
, LPLVITEMA lpLVItem
)
4516 LISTVIEW_INFO
*infoPtr
= (LISTVIEW_INFO
*)GetWindowLongA(hwnd
, 0);
4517 LONG lStyle
= GetWindowLongA(hwnd
, GWL_STYLE
);
4518 LONG lCtrlId
= GetWindowLongA(hwnd
, GWL_ID
);
4522 LISTVIEW_ITEM
*lpItem
= NULL
;
4524 TRACE(listview
, "(hwnd=%x,lpLVItem=%p)\n", hwnd
, lpLVItem
);
4526 if (lpLVItem
!= NULL
)
4528 /* make sure it's not a subitem; cannot insert a subitem */
4529 if (lpLVItem
->iSubItem
== 0)
4531 lpItem
= (LISTVIEW_ITEM
*)COMCTL32_Alloc(sizeof(LISTVIEW_ITEM
));
4534 ZeroMemory(lpItem
, sizeof(LISTVIEW_ITEM
));
4535 if (LISTVIEW_InitItem(hwnd
, lpItem
, lpLVItem
) != FALSE
)
4537 /* insert item in listview control data structure */
4538 hdpaSubItems
= DPA_Create(8);
4539 if (hdpaSubItems
!= NULL
)
4541 nItem
= DPA_InsertPtr(hdpaSubItems
, 0, lpItem
);
4544 nItem
= DPA_InsertPtr(infoPtr
->hdpaItems
, lpLVItem
->iItem
,
4548 /* manage item focus */
4549 if (lpLVItem
->mask
& LVIF_STATE
)
4551 if (lpLVItem
->stateMask
& LVIS_FOCUSED
)
4553 LISTVIEW_SetItemFocus(hwnd
, nItem
);
4557 /* send LVN_INSERTITEM notification */
4558 ZeroMemory(&nmlv
, sizeof(NMLISTVIEW
));
4559 nmlv
.hdr
.hwndFrom
= hwnd
;
4560 nmlv
.hdr
.idFrom
= lCtrlId
;
4561 nmlv
.hdr
.code
= LVN_INSERTITEM
;
4563 nmlv
.lParam
= lpItem
->lParam
;;
4564 ListView_LVNotify(GetParent(hwnd
), lCtrlId
, &nmlv
);
4566 /* align items (set position of each item) */
4567 switch (lStyle
& LVS_TYPEMASK
)
4571 if (lStyle
& LVS_ALIGNLEFT
)
4573 LISTVIEW_AlignLeft(hwnd
);
4577 LISTVIEW_AlignTop(hwnd
);
4582 LISTVIEW_SetScroll(hwnd
, lStyle
);
4583 /* refresh client area */
4584 InvalidateRect(hwnd
, NULL
, FALSE
);
4593 /* free memory if unsuccessful */
4594 if ((nItem
== -1) && (lpItem
!= NULL
))
4596 COMCTL32_Free(lpItem
);
4602 /* LISTVIEW_InsertItemW */
4606 * Redraws a range of items.
4609 * [I] HWND : window handle
4610 * [I] INT : first item
4611 * [I] INT : last item
4617 static LRESULT
LISTVIEW_RedrawItems(HWND hwnd
, INT nFirst
, INT nLast
)
4619 LISTVIEW_INFO
*infoPtr
= (LISTVIEW_INFO
*)GetWindowLongA(hwnd
, 0);
4620 BOOL bResult
= FALSE
;
4623 if (nFirst
<= nLast
)
4625 if ((nFirst
>= 0) && (nFirst
< GETITEMCOUNT(infoPtr
)))
4627 if ((nLast
>= 0) && (nLast
< GETITEMCOUNT(infoPtr
)))
4630 InvalidateRect(hwnd
, &rc
, FALSE
);
4638 /* LISTVIEW_Scroll */
4642 * Sets the background color.
4645 * [I] HWND : window handle
4646 * [I] COLORREF : background color
4652 static LRESULT
LISTVIEW_SetBkColor(HWND hwnd
, COLORREF clrBk
)
4654 LISTVIEW_INFO
*infoPtr
= (LISTVIEW_INFO
*)GetWindowLongA(hwnd
, 0);
4656 infoPtr
->clrBk
= clrBk
;
4657 InvalidateRect(hwnd
, NULL
, TRUE
);
4664 * Sets the callback mask. This mask will be used when the parent
4665 * window stores state information (some or all).
4668 * [I] HWND : window handle
4669 * [I] UINT : state mask
4675 static BOOL
LISTVIEW_SetCallbackMask(HWND hwnd
, UINT uMask
)
4677 LISTVIEW_INFO
*infoPtr
= (LISTVIEW_INFO
*)GetWindowLongA(hwnd
, 0);
4679 infoPtr
->uCallbackMask
= uMask
;
4686 * Sets the attributes of a header item.
4689 * [I] HWND : window handle
4690 * [I] INT : column index
4691 * [I] LPLVCOLUMNA : column attributes
4697 static LRESULT
LISTVIEW_SetColumnA(HWND hwnd
, INT nColumn
,
4698 LPLVCOLUMNA lpColumn
)
4700 LISTVIEW_INFO
*infoPtr
= (LISTVIEW_INFO
*)GetWindowLongA(hwnd
, 0);
4701 BOOL bResult
= FALSE
;
4704 if ((lpColumn
!= NULL
) && (nColumn
>= 0) &&
4705 (nColumn
< Header_GetItemCount(infoPtr
->hwndHeader
)))
4707 /* initialize memory */
4708 ZeroMemory(&hdi
, sizeof(HDITEMA
));
4710 if (lpColumn
->mask
& LVCF_FMT
)
4712 /* format member is valid */
4713 hdi
.mask
|= HDI_FORMAT
;
4715 /* set text alignment (leftmost column must be left-aligned) */
4718 hdi
.fmt
|= HDF_LEFT
;
4722 if (lpColumn
->fmt
& LVCFMT_LEFT
)
4724 hdi
.fmt
|= HDF_LEFT
;
4726 else if (lpColumn
->fmt
& LVCFMT_RIGHT
)
4728 hdi
.fmt
|= HDF_RIGHT
;
4730 else if (lpColumn
->fmt
& LVCFMT_CENTER
)
4732 hdi
.fmt
|= HDF_CENTER
;
4736 if (lpColumn
->fmt
& LVCFMT_BITMAP_ON_RIGHT
)
4738 hdi
.fmt
|= HDF_BITMAP_ON_RIGHT
;
4741 if (lpColumn
->fmt
& LVCFMT_COL_HAS_IMAGES
)
4743 hdi
.fmt
|= HDF_IMAGE
;
4746 if (lpColumn
->fmt
& LVCFMT_IMAGE
)
4748 hdi
.fmt
|= HDF_IMAGE
;
4749 hdi
.iImage
= I_IMAGECALLBACK
;
4753 if (lpColumn
->mask
& LVCF_WIDTH
)
4755 hdi
.mask
|= HDI_WIDTH
;
4756 hdi
.cxy
= lpColumn
->cx
;
4759 if (lpColumn
->mask
& LVCF_TEXT
)
4761 hdi
.mask
|= HDI_TEXT
| HDI_FORMAT
;
4762 hdi
.pszText
= lpColumn
->pszText
;
4763 hdi
.cchTextMax
= lstrlenA(lpColumn
->pszText
);
4764 hdi
.fmt
|= HDF_STRING
;
4767 if (lpColumn
->mask
& LVCF_IMAGE
)
4769 hdi
.mask
|= HDI_IMAGE
;
4770 hdi
.iImage
= lpColumn
->iImage
;
4773 if (lpColumn
->mask
& LVCF_ORDER
)
4775 hdi
.mask
|= HDI_ORDER
;
4776 hdi
.iOrder
= lpColumn
->iOrder
;
4779 /* set header item attributes */
4780 bResult
= Header_SetItemA(infoPtr
->hwndHeader
, nColumn
, &hdi
);
4788 * Sets the width of a column
4791 * [I] HWND : window handle
4792 * [I] INT : column index
4793 * [I] INT : column width
4799 static LRESULT
LISTVIEW_SetColumnWidth(HWND hwnd
, INT iCol
, INT cx
)
4801 LISTVIEW_INFO
*infoPtr
;
4806 /* set column width only if in report mode */
4807 lStyle
= GetWindowLongA(hwnd
, GWL_STYLE
);
4808 if ((lStyle
& LVS_TYPEMASK
) != LVS_REPORT
)
4811 /* make sure we can get the listview info */
4812 if (!(infoPtr
= (LISTVIEW_INFO
*)GetWindowLongA(hwnd
, 0)))
4814 if (!infoPtr
->hwndHeader
) /* make sure we have a header */
4818 * FIXME: currently ignoring LVSCW_AUTOSIZE (-1) and
4819 * LVSCV_AUTOSIZE_USEHEADER (-2)
4824 hdi
.mask
= HDI_WIDTH
;
4827 /* call header to update the column change */
4828 lret
= Header_SetItemA(infoPtr
->hwndHeader
, (WPARAM
)iCol
, (LPARAM
)&hdi
);
4830 infoPtr
->nItemWidth
= LISTVIEW_GetItemWidth(hwnd
, LVS_REPORT
);
4832 InvalidateRect(hwnd
, NULL
, TRUE
); /* force redraw of the listview */
4842 * [I] HWND : window handle
4843 * [I] INT : image list type
4844 * [I] HIMAGELIST : image list handle
4847 * SUCCESS : old image list
4850 static LRESULT
LISTVIEW_SetImageList(HWND hwnd
, INT nType
, HIMAGELIST himl
)
4852 LISTVIEW_INFO
*infoPtr
= (LISTVIEW_INFO
*)GetWindowLongA(hwnd
, 0);
4853 HIMAGELIST himlTemp
= 0;
4858 himlTemp
= infoPtr
->himlNormal
;
4859 infoPtr
->himlNormal
= himl
;
4860 return (LRESULT
)himlTemp
;
4863 himlTemp
= infoPtr
->himlSmall
;
4864 infoPtr
->himlSmall
= himl
;
4865 return (LRESULT
)himlTemp
;
4868 himlTemp
= infoPtr
->himlState
;
4869 infoPtr
->himlState
= himl
;
4870 return (LRESULT
)himlTemp
;
4873 return (LRESULT
)NULL
;
4879 * Sets the attributes of an item.
4882 * [I] HWND : window handle
4883 * [I] LPLVITEM : item information
4889 static LRESULT
LISTVIEW_SetItemA(HWND hwnd
, LPLVITEMA lpLVItem
)
4891 LISTVIEW_INFO
*infoPtr
= (LISTVIEW_INFO
*)GetWindowLongA(hwnd
, 0);
4892 BOOL bResult
= FALSE
;
4894 if (lpLVItem
!= NULL
)
4896 if ((lpLVItem
->iItem
>= 0) && (lpLVItem
->iItem
< GETITEMCOUNT(infoPtr
)))
4898 if (lpLVItem
->iSubItem
== 0)
4900 bResult
= LISTVIEW_SetItem(hwnd
, lpLVItem
);
4904 bResult
= LISTVIEW_SetSubItem(hwnd
, lpLVItem
);
4913 /* LISTVIEW_SetItemW */
4917 * Preallocates memory.
4920 * [I] HWND : window handle
4921 * [I] INT : item count (prjected number of items)
4926 static VOID
LISTVIEW_SetItemCount(HWND hwnd
, INT nItemCount
)
4928 FIXME (listview
, "empty stub!\n");
4933 * Sets the position of an item.
4936 * [I] HWND : window handle
4937 * [I] INT : item index
4938 * [I] INT : x coordinate
4939 * [I] INT : y coordinate
4945 static BOOL
LISTVIEW_SetItemPosition(HWND hwnd
, INT nItem
,
4946 INT nPosX
, INT nPosY
)
4948 LISTVIEW_INFO
*infoPtr
= (LISTVIEW_INFO
*)GetWindowLongA(hwnd
, 0);
4949 LONG lStyle
= GetWindowLongA(hwnd
, GWL_STYLE
);
4950 LISTVIEW_ITEM
*lpItem
;
4952 BOOL bResult
= FALSE
;
4954 TRACE(listview
, "(hwnd=%x,nItem=%d,X=%d,Y=%d)\n", hwnd
, nItem
, nPosX
, nPosY
);
4956 if ((nItem
>= 0) || (nItem
< GETITEMCOUNT(infoPtr
)))
4958 switch (lStyle
& LVS_TYPEMASK
)
4962 hdpaSubItems
= (HDPA
)DPA_GetPtr(infoPtr
->hdpaItems
, nItem
);
4963 if (hdpaSubItems
!= NULL
)
4965 lpItem
= (LISTVIEW_ITEM
*)DPA_GetPtr(hdpaSubItems
, 0);
4969 lpItem
->ptPosition
.x
= nPosX
;
4970 lpItem
->ptPosition
.y
= nPosY
;
4982 * Sets the state of one or many items.
4985 * [I] HWND : window handle
4986 * [I]INT : item index
4987 * [I] LPLVITEM : item or subitem info
4993 static LRESULT
LISTVIEW_SetItemState(HWND hwnd
, INT nItem
, LPLVITEMA lpLVItem
)
4995 LISTVIEW_INFO
*infoPtr
= (LISTVIEW_INFO
*)GetWindowLongA(hwnd
, 0);
4996 BOOL bResult
= FALSE
;
5003 ZeroMemory(&lvItem
, sizeof(LVITEMA
));
5004 lvItem
.mask
= LVIF_STATE
;
5005 lvItem
.state
= lpLVItem
->state
;
5006 lvItem
.stateMask
= lpLVItem
->stateMask
;
5008 /* apply to all items */
5009 for (i
= 0; i
< GETITEMCOUNT(infoPtr
); i
++)
5012 if (ListView_SetItemA(hwnd
, &lvItem
) == FALSE
)
5020 ZeroMemory(&lvItem
, sizeof(LVITEMA
));
5021 lvItem
.mask
= LVIF_STATE
;
5022 lvItem
.state
= lpLVItem
->state
;
5023 lvItem
.stateMask
= lpLVItem
->stateMask
;
5024 lvItem
.iItem
= nItem
;
5025 bResult
= ListView_SetItemA(hwnd
, &lvItem
);
5033 * Sets the text of an item or subitem.
5036 * [I] HWND : window handle
5037 * [I] INT : item index
5038 * [I] LPLVITEMA : item or subitem info
5044 static BOOL
LISTVIEW_SetItemTextA(HWND hwnd
, INT nItem
, LPLVITEMA lpLVItem
)
5046 LISTVIEW_INFO
*infoPtr
= (LISTVIEW_INFO
*)GetWindowLongA(hwnd
, 0);
5047 BOOL bResult
= FALSE
;
5050 if ((nItem
>= 0) && (nItem
< GETITEMCOUNT(infoPtr
)))
5052 ZeroMemory(&lvItem
, sizeof(LVITEMA
));
5053 lvItem
.mask
= LVIF_TEXT
;
5054 lvItem
.pszText
= lpLVItem
->pszText
;
5055 lvItem
.iItem
= nItem
;
5056 lvItem
.iSubItem
= lpLVItem
->iSubItem
;
5057 bResult
= ListView_SetItemA(hwnd
, &lvItem
);
5065 * Sets the text background color.
5068 * [I] HWND : window handle
5069 * [I] COLORREF : text background color
5075 static LRESULT
LISTVIEW_SetTextBkColor(HWND hwnd
, COLORREF clrTextBk
)
5077 LISTVIEW_INFO
*infoPtr
= (LISTVIEW_INFO
*)GetWindowLongA(hwnd
, 0);
5079 infoPtr
->clrTextBk
= clrTextBk
;
5080 InvalidateRect(hwnd
, NULL
, TRUE
);
5087 * Sets the text foreground color.
5090 * [I] HWND : window handle
5091 * [I] COLORREF : text color
5097 static LRESULT
LISTVIEW_SetTextColor (HWND hwnd
, COLORREF clrText
)
5099 LISTVIEW_INFO
*infoPtr
= (LISTVIEW_INFO
*)GetWindowLongA(hwnd
, 0);
5101 infoPtr
->clrText
= clrText
;
5102 InvalidateRect(hwnd
, NULL
, TRUE
);
5109 * Sorts the listview items.
5112 * [I] HWND : window handle
5118 static LRESULT
LISTVIEW_SortItems(HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
5120 FIXME (listview
, "empty stub!\n");
5127 * Updates an items or rearranges the listview control.
5130 * [I] HWND : window handle
5131 * [I] INT : item index
5137 static LRESULT
LISTVIEW_Update(HWND hwnd
, INT nItem
)
5139 LISTVIEW_INFO
*infoPtr
= (LISTVIEW_INFO
*)GetWindowLongA(hwnd
, 0);
5140 LONG lStyle
= GetWindowLongA(hwnd
, GWL_STYLE
);
5141 BOOL bResult
= FALSE
;
5144 if ((nItem
>= 0) && (nItem
< GETITEMCOUNT(infoPtr
)))
5148 /* rearrange with default alignment style */
5149 if ((lStyle
& LVS_AUTOARRANGE
) && (((lStyle
& LVS_TYPEMASK
) == LVS_ICON
) ||
5150 ((lStyle
& LVS_TYPEMASK
) == LVS_SMALLICON
)))
5152 ListView_Arrange(hwnd
, 0);
5156 /* get item bounding rectangle */
5157 rc
.left
= LVIR_BOUNDS
;
5158 ListView_GetItemRect(hwnd
, nItem
, &rc
);
5159 InvalidateRect(hwnd
, &rc
, FALSE
);
5168 * Creates the listview control.
5171 * [I] HWND : window handle
5176 static LRESULT
LISTVIEW_Create(HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
5178 LISTVIEW_INFO
*infoPtr
= (LISTVIEW_INFO
*)GetWindowLongA(hwnd
, 0);
5179 LPCREATESTRUCTA lpcs
= (LPCREATESTRUCTA
)lParam
;
5182 /* initialize info pointer */
5183 ZeroMemory(infoPtr
, sizeof(LISTVIEW_INFO
));
5185 /* determine the type of structures to use */
5186 infoPtr
->notifyFormat
= SendMessageA(GetParent(hwnd
), WM_NOTIFYFORMAT
,
5187 (WPARAM
)hwnd
, (LPARAM
)NF_QUERY
);
5188 if (infoPtr
->notifyFormat
!= NFR_ANSI
)
5190 FIXME (listview
, "ANSI notify format is NOT used\n");
5193 /* initialize color information */
5194 infoPtr
->clrBk
= GetSysColor(COLOR_WINDOW
);
5195 infoPtr
->clrText
= GetSysColor(COLOR_WINDOWTEXT
);
5196 infoPtr
->clrTextBk
= GetSysColor(COLOR_WINDOW
);
5198 /* set default values */
5199 infoPtr
->uCallbackMask
= 0;
5200 infoPtr
->nFocusedItem
= -1;
5201 infoPtr
->nSelectionMark
= -1;
5202 infoPtr
->iconSpacing
.cx
= GetSystemMetrics(SM_CXICONSPACING
);
5203 infoPtr
->iconSpacing
.cy
= GetSystemMetrics(SM_CYICONSPACING
);
5204 ZeroMemory(&infoPtr
->rcList
, sizeof(RECT
));
5206 /* get default font (icon title) */
5207 SystemParametersInfoA(SPI_GETICONTITLELOGFONT
, 0, &logFont
, 0);
5208 infoPtr
->hDefaultFont
= CreateFontIndirectA(&logFont
);
5209 infoPtr
->hFont
= infoPtr
->hDefaultFont
;
5212 infoPtr
->hwndHeader
= CreateWindowA(WC_HEADERA
, (LPCSTR
)NULL
,
5213 WS_CHILD
| HDS_HORZ
| HDS_BUTTONS
,
5214 0, 0, 0, 0, hwnd
, (HMENU
)0,
5215 lpcs
->hInstance
, NULL
);
5217 /* set header font */
5218 SendMessageA(infoPtr
->hwndHeader
, WM_SETFONT
, (WPARAM
)infoPtr
->hFont
,
5222 switch (lpcs
->style
& LVS_TYPEMASK
)
5225 infoPtr
->iconSize
.cx
= GetSystemMetrics(SM_CXICON
);
5226 infoPtr
->iconSize
.cy
= GetSystemMetrics(SM_CYICON
);
5230 ShowWindow(infoPtr
->hwndHeader
, SW_SHOWNORMAL
);
5233 infoPtr
->iconSize
.cx
= GetSystemMetrics(SM_CXSMICON
);
5234 infoPtr
->iconSize
.cy
= GetSystemMetrics(SM_CYSMICON
);
5238 /* display unsupported listview window styles */
5239 LISTVIEW_UnsupportedStyles(lpcs
->style
);
5241 /* allocate memory for the data structure */
5242 infoPtr
->hdpaItems
= DPA_Create(10);
5244 /* initialize size of items */
5245 infoPtr
->nItemWidth
= LISTVIEW_GetItemWidth(hwnd
, lpcs
->style
);
5246 infoPtr
->nItemHeight
= LISTVIEW_GetItemHeight(hwnd
, lpcs
->style
);
5253 * Erases the background of the listview control.
5256 * [I] HWND : window handle
5257 * [I] WPARAM : device context handle
5258 * [I] LPARAM : not used
5264 static LRESULT
LISTVIEW_EraseBackground(HWND hwnd
, WPARAM wParam
,
5267 LISTVIEW_INFO
*infoPtr
= (LISTVIEW_INFO
*)GetWindowLongA(hwnd
, 0);
5270 if (infoPtr
->clrBk
== CLR_NONE
)
5272 bResult
= SendMessageA(GetParent(hwnd
), WM_ERASEBKGND
, wParam
, lParam
);
5277 HBRUSH hBrush
= CreateSolidBrush(infoPtr
->clrBk
);
5278 GetClientRect(hwnd
, &rc
);
5279 FillRect((HDC
)wParam
, &rc
, hBrush
);
5280 DeleteObject(hBrush
);
5289 * Retrieves the listview control font.
5292 * [I] HWND : window handle
5297 static LRESULT
LISTVIEW_GetFont(HWND hwnd
)
5299 LISTVIEW_INFO
*infoPtr
= (LISTVIEW_INFO
*)GetWindowLongA(hwnd
, 0);
5301 return infoPtr
->hFont
;
5306 * Performs vertical scrolling.
5309 * [I] HWND : window handle
5310 * [I] INT : scroll code
5311 * [I] INT : scroll position
5312 * [I] HWND : scrollbar control window handle
5317 static LRESULT
LISTVIEW_VScroll(HWND hwnd
, INT nScrollCode
, INT nScroll
,
5320 LISTVIEW_INFO
*infoPtr
= (LISTVIEW_INFO
*)GetWindowLongA(hwnd
, 0);
5321 LONG lStyle
= GetWindowLongA(hwnd
, GWL_STYLE
);
5322 INT nScrollPosInc
= 0;
5327 GetScrollRange(hwnd
, SB_VERT
, &nMinRange
, &nMaxRange
);
5328 nScrollPos
= GetScrollPos(hwnd
, SB_VERT
);
5330 switch (nScrollCode
)
5333 if (nScrollPos
> nMinRange
)
5340 if (nScrollPos
< nMaxRange
)
5347 switch (LVS_TYPEMASK
& lStyle
)
5350 if (nScrollPos
> nMinRange
+ infoPtr
->nCountPerColumn
)
5352 nScrollPosInc
= -infoPtr
->nCountPerColumn
;
5356 nScrollPosInc
= nMinRange
- nScrollPos
;
5362 if (nScrollPos
> nMinRange
+ 10)
5364 nScrollPosInc
= -10;
5368 nScrollPosInc
= nMinRange
- nScrollPos
;
5375 switch (LVS_TYPEMASK
& lStyle
)
5378 if (nScrollPos
< nMaxRange
- infoPtr
->nCountPerColumn
)
5380 nScrollPosInc
= infoPtr
->nCountPerColumn
;
5384 nScrollPosInc
= nMaxRange
- nScrollPos
;
5390 if (nScrollPos
< nMaxRange
- 10)
5396 nScrollPosInc
= nMaxRange
- nScrollPos
;
5402 case SB_THUMBPOSITION
:
5403 nScrollPosInc
= nScroll
- nScrollPos
;
5407 if (nScrollPosInc
!= 0)
5409 LISTVIEW_ScrollView(hwnd
, 0, nScrollPosInc
);
5418 * Performs horizontal scrolling.
5421 * [I] HWND : window handle
5422 * [I] INT : scroll code
5423 * [I] INT : scroll position
5424 * [I] HWND : scrollbar control window handle
5429 static LRESULT
LISTVIEW_HScroll(HWND hwnd
, INT nScrollCode
,
5430 INT nScroll
, HWND hScrollWnd
)
5432 LISTVIEW_INFO
*infoPtr
= (LISTVIEW_INFO
*)GetWindowLongA(hwnd
, 0);
5433 LONG lStyle
= GetWindowLongA(hwnd
, GWL_STYLE
);
5434 INT nScrollPosInc
= 0;
5439 GetScrollRange(hwnd
, SB_HORZ
, &nMinRange
, &nMaxRange
);
5440 nScrollPos
= GetScrollPos(hwnd
, SB_HORZ
);
5442 switch (nScrollCode
)
5445 if (nScrollPos
> nMinRange
)
5452 if (nScrollPos
< nMaxRange
)
5459 switch (LVS_TYPEMASK
& lStyle
)
5462 if (nScrollPos
> nMinRange
+ infoPtr
->nCountPerRow
)
5464 nScrollPosInc
= -infoPtr
->nCountPerRow
;
5468 nScrollPosInc
= nMinRange
- nScrollPos
;
5475 if (nScrollPos
> nMinRange
+ 10)
5477 nScrollPosInc
= -10;
5481 nScrollPosInc
= nMinRange
- nScrollPos
;
5488 switch (LVS_TYPEMASK
& lStyle
)
5491 if (nScrollPos
< nMaxRange
- infoPtr
->nCountPerRow
)
5493 nScrollPosInc
= infoPtr
->nCountPerRow
;
5497 nScrollPosInc
= nMaxRange
- nScrollPos
;
5504 if (nScrollPos
< nMaxRange
- 10)
5510 nScrollPosInc
= nMaxRange
- nScrollPos
;
5516 case SB_THUMBPOSITION
:
5517 nScrollPosInc
= nScroll
- nScrollPos
;
5521 if (nScrollPosInc
!= 0)
5523 LISTVIEW_ScrollView(hwnd
, nScrollPosInc
, 0);
5534 * [I] HWND : window handle
5535 * [I] INT : virtual key
5536 * [I] LONG : key data
5541 static LRESULT
LISTVIEW_KeyDown(HWND hwnd
, INT nVirtualKey
, LONG lKeyData
)
5543 LISTVIEW_INFO
*infoPtr
= (LISTVIEW_INFO
*)GetWindowLongA(hwnd
, 0);
5544 LONG lStyle
= GetWindowLongA(hwnd
, GWL_STYLE
);
5545 INT nCtrlId
= GetWindowLongA(hwnd
, GWL_ID
);
5546 INT nCountPerColumn
;
5548 HWND hwndParent
= GetParent(hwnd
);
5549 NMLVKEYDOWN nmKeyDown
;
5552 /* send LVN_KEYDOWN notification */
5553 ZeroMemory(&nmKeyDown
, sizeof(NMLVKEYDOWN
));
5554 nmKeyDown
.hdr
.hwndFrom
= hwnd
;
5555 nmKeyDown
.hdr
.idFrom
= nCtrlId
;
5556 nmKeyDown
.hdr
.code
= LVN_KEYDOWN
;
5557 nmKeyDown
.wVKey
= nVirtualKey
;
5558 nmKeyDown
.flags
= 0;
5559 SendMessageA(hwndParent
, WM_NOTIFY
, (WPARAM
)nCtrlId
, (LPARAM
)&nmKeyDown
);
5562 nmh
.hwndFrom
= hwnd
;
5563 nmh
.idFrom
= nCtrlId
;
5565 switch (nVirtualKey
)
5568 if ((GETITEMCOUNT(infoPtr
) > 0) && (infoPtr
->nFocusedItem
!= -1))
5570 /* send NM_RETURN notification */
5571 nmh
.code
= NM_RETURN
;
5572 ListView_Notify(hwndParent
, nCtrlId
, &nmh
);
5574 /* send LVN_ITEMACTIVATE notification */
5575 nmh
.code
= LVN_ITEMACTIVATE
;
5576 ListView_Notify(hwndParent
, nCtrlId
, &nmh
);
5581 if (GETITEMCOUNT(infoPtr
) > 0)
5583 LISTVIEW_KeySelection(hwnd
, 0);
5588 if (GETITEMCOUNT(infoPtr
) > 0)
5590 LISTVIEW_KeySelection(hwnd
, GETITEMCOUNT(infoPtr
) - 1);
5595 switch (LVS_TYPEMASK
& lStyle
)
5598 if (infoPtr
->nFocusedItem
>= infoPtr
->nCountPerColumn
)
5600 LISTVIEW_KeySelection(hwnd
, infoPtr
->nFocusedItem
-
5601 infoPtr
->nCountPerColumn
);
5607 if (lStyle
& LVS_ALIGNLEFT
)
5609 nCountPerColumn
= max((infoPtr
->rcList
.bottom
- infoPtr
->rcList
.top
) /
5610 infoPtr
->nItemHeight
, 1);
5611 if (infoPtr
->nFocusedItem
>= nCountPerColumn
)
5613 LISTVIEW_KeySelection(hwnd
, infoPtr
->nFocusedItem
- nCountPerColumn
);
5618 nCountPerRow
= max((infoPtr
->rcList
.right
- infoPtr
->rcList
.left
) /
5619 infoPtr
->nItemWidth
, 1);
5620 if (infoPtr
->nFocusedItem
% nCountPerRow
!= 0)
5622 LISTVIEW_SetSelection(hwnd
, infoPtr
->nFocusedItem
- 1);
5630 switch (LVS_TYPEMASK
& lStyle
)
5634 if (infoPtr
->nFocusedItem
> 0)
5636 LISTVIEW_KeySelection(hwnd
, infoPtr
->nFocusedItem
- 1);
5641 if (lStyle
& LVS_ALIGNLEFT
)
5643 nCountPerColumn
= max((infoPtr
->rcList
.bottom
- infoPtr
->rcList
.top
) /
5644 infoPtr
->nItemHeight
, 1);
5645 if (infoPtr
->nFocusedItem
% nCountPerColumn
!= 0)
5647 LISTVIEW_KeySelection(hwnd
, infoPtr
->nFocusedItem
- 1);
5652 nCountPerRow
= max((infoPtr
->rcList
.right
- infoPtr
->rcList
.left
) /
5653 infoPtr
->nItemWidth
, 1);
5654 if (infoPtr
->nFocusedItem
>= nCountPerRow
)
5656 LISTVIEW_KeySelection(hwnd
, infoPtr
->nFocusedItem
- nCountPerRow
);
5663 switch (LVS_TYPEMASK
& lStyle
)
5666 if (infoPtr
->nFocusedItem
< GETITEMCOUNT(infoPtr
) -
5667 infoPtr
->nCountPerColumn
)
5669 LISTVIEW_KeySelection(hwnd
, infoPtr
->nFocusedItem
+
5670 infoPtr
->nCountPerColumn
);
5676 if (lStyle
& LVS_ALIGNLEFT
)
5678 nCountPerColumn
= max((infoPtr
->rcList
.bottom
- infoPtr
->rcList
.top
) /
5679 infoPtr
->nItemHeight
, 1);
5680 if (infoPtr
->nFocusedItem
< GETITEMCOUNT(infoPtr
) - nCountPerColumn
)
5682 LISTVIEW_KeySelection(hwnd
, infoPtr
->nFocusedItem
+ nCountPerColumn
);
5687 nCountPerRow
= max((infoPtr
->rcList
.right
- infoPtr
->rcList
.left
) /
5688 infoPtr
->nItemWidth
, 1);
5689 if ((infoPtr
->nFocusedItem
% nCountPerRow
!= nCountPerRow
- 1) &&
5690 (infoPtr
->nFocusedItem
< GETITEMCOUNT(infoPtr
) - 1))
5692 LISTVIEW_KeySelection(hwnd
, infoPtr
->nFocusedItem
+ 1);
5699 switch (LVS_TYPEMASK
& lStyle
)
5703 if (infoPtr
->nFocusedItem
< GETITEMCOUNT(infoPtr
) - 1)
5705 LISTVIEW_KeySelection(hwnd
, infoPtr
->nFocusedItem
+ 1);
5711 if (lStyle
& LVS_ALIGNLEFT
)
5713 nCountPerColumn
= max((infoPtr
->rcList
.bottom
- infoPtr
->rcList
.top
) /
5714 infoPtr
->nItemHeight
, 1);
5715 if (infoPtr
->nFocusedItem
% nCountPerColumn
!= nCountPerColumn
- 1)
5717 LISTVIEW_KeySelection(hwnd
, infoPtr
->nFocusedItem
+ 1);
5722 nCountPerRow
= max((infoPtr
->rcList
.right
- infoPtr
->rcList
.left
) /
5723 infoPtr
->nItemWidth
, 1);
5724 if (infoPtr
->nFocusedItem
< GETITEMCOUNT(infoPtr
) - nCountPerRow
)
5726 LISTVIEW_KeySelection(hwnd
, infoPtr
->nFocusedItem
+ nCountPerRow
);
5739 /* refresh client area */
5740 InvalidateRect(hwnd
, NULL
, TRUE
);
5750 * [I] HWND : window handle
5755 static LRESULT
LISTVIEW_KillFocus(HWND hwnd
)
5757 LISTVIEW_INFO
*infoPtr
= (LISTVIEW_INFO
*)GetWindowLongA(hwnd
, 0);
5758 INT nCtrlId
= GetWindowLongA(hwnd
, GWL_ID
);
5761 /* send NM_KILLFOCUS notification */
5762 nmh
.hwndFrom
= hwnd
;
5763 nmh
.idFrom
= nCtrlId
;
5764 nmh
.code
= NM_KILLFOCUS
;
5765 ListView_Notify(GetParent(hwnd
), nCtrlId
, &nmh
);
5767 /* set window focus flag */
5768 infoPtr
->bFocus
= FALSE
;
5775 * Processes double click messages (left mouse button).
5778 * [I] HWND : window handle
5779 * [I] WORD : key flag
5780 * [I] WORD : x coordinate
5781 * [I] WORD : y coordinate
5786 static LRESULT
LISTVIEW_LButtonDblClk(HWND hwnd
, WORD wKey
, WORD wPosX
,
5789 LONG nCtrlId
= GetWindowLongA(hwnd
, GWL_ID
);
5792 TRACE(listview
, "(hwnd=%x,key=%hu,X=%hu,Y=%hu)\n", hwnd
, wKey
, wPosX
, wPosY
);
5794 /* send NM_DBLCLK notification */
5795 nmh
.hwndFrom
= hwnd
;
5796 nmh
.idFrom
= nCtrlId
;
5797 nmh
.code
= NM_DBLCLK
;
5798 ListView_Notify(GetParent(hwnd
), nCtrlId
, &nmh
);
5800 /* send LVN_ITEMACTIVATE notification */
5801 nmh
.code
= LVN_ITEMACTIVATE
;
5802 ListView_Notify(GetParent(hwnd
), nCtrlId
, &nmh
);
5809 * Processes mouse down messages (left mouse button).
5812 * [I] HWND : window handle
5813 * [I] WORD : key flag
5814 * [I] WORD : x coordinate
5815 * [I] WORD : y coordinate
5820 static LRESULT
LISTVIEW_LButtonDown(HWND hwnd
, WORD wKey
, WORD wPosX
,
5823 LISTVIEW_INFO
*infoPtr
= (LISTVIEW_INFO
*)GetWindowLongA(hwnd
, 0);
5824 INT nCtrlId
= GetWindowLongA(hwnd
, GWL_ID
);
5825 static BOOL bGroupSelect
= TRUE
;
5829 TRACE(listview
, "(hwnd=%x,key=%hu,X=%hu,Y=%hu)\n", hwnd
, wKey
, wPosX
, wPosY
);
5831 /* send NM_RELEASEDCAPTURE notification */
5832 nmh
.hwndFrom
= hwnd
;
5833 nmh
.idFrom
= nCtrlId
;
5834 nmh
.code
= NM_RELEASEDCAPTURE
;
5835 ListView_Notify(GetParent(hwnd
), nCtrlId
, &nmh
);
5837 if (infoPtr
->bFocus
== FALSE
)
5842 /* set left button down flag */
5843 infoPtr
->bLButtonDown
= TRUE
;
5845 nItem
= LISTVIEW_MouseSelection(hwnd
, wPosX
, wPosY
);
5846 if ((nItem
>= 0) && (nItem
< GETITEMCOUNT(infoPtr
)))
5848 if ((wKey
& MK_CONTROL
) && (wKey
& MK_SHIFT
))
5850 if (bGroupSelect
!= FALSE
)
5852 LISTVIEW_AddGroupSelection(hwnd
, nItem
);
5856 LISTVIEW_AddSelection(hwnd
, nItem
);
5859 else if (wKey
& MK_CONTROL
)
5861 bGroupSelect
= LISTVIEW_ToggleSelection(hwnd
, nItem
);
5863 else if (wKey
& MK_SHIFT
)
5865 LISTVIEW_SetGroupSelection(hwnd
, nItem
);
5869 LISTVIEW_SetSelection(hwnd
, nItem
);
5874 /* remove all selections */
5875 LISTVIEW_RemoveSelections(hwnd
, 0, GETITEMCOUNT(infoPtr
));
5878 InvalidateRect(hwnd
, NULL
, TRUE
);
5885 * Processes mouse up messages (left mouse button).
5888 * [I] HWND : window handle
5889 * [I] WORD : key flag
5890 * [I] WORD : x coordinate
5891 * [I] WORD : y coordinate
5896 static LRESULT
LISTVIEW_LButtonUp(HWND hwnd
, WORD wKey
, WORD wPosX
,
5899 LISTVIEW_INFO
*infoPtr
= (LISTVIEW_INFO
*)GetWindowLongA(hwnd
, 0);
5901 TRACE(listview
, "(hwnd=%x,key=%hu,X=%hu,Y=%hu)\n", hwnd
, wKey
, wPosX
, wPosY
);
5903 if (infoPtr
->bLButtonDown
!= FALSE
)
5905 INT nCtrlId
= GetWindowLongA(hwnd
, GWL_ID
);
5908 /* send NM_CLICK notification */
5909 nmh
.hwndFrom
= hwnd
;
5910 nmh
.idFrom
= nCtrlId
;
5911 nmh
.code
= NM_CLICK
;
5912 ListView_Notify(GetParent(hwnd
), nCtrlId
, &nmh
);
5914 /* set left button flag */
5915 infoPtr
->bLButtonDown
= FALSE
;
5923 * Creates the listview control (called before WM_CREATE).
5926 * [I] HWND : window handle
5927 * [I] WPARAM : unhandled
5928 * [I] LPARAM : widow creation info
5933 static LRESULT
LISTVIEW_NCCreate(HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
5935 LISTVIEW_INFO
*infoPtr
;
5937 TRACE(listview
, "(hwnd=%x,wParam=%x,lParam=%lx)\n", hwnd
, wParam
, lParam
);
5939 /* allocate memory for info structure */
5940 infoPtr
= (LISTVIEW_INFO
*)COMCTL32_Alloc(sizeof(LISTVIEW_INFO
));
5941 SetWindowLongA(hwnd
, 0, (LONG
)infoPtr
);
5942 if (infoPtr
== NULL
)
5944 ERR(listview
, "could not allocate info memory!\n");
5948 if ((LISTVIEW_INFO
*)GetWindowLongA(hwnd
, 0) != infoPtr
)
5950 ERR(listview
, "pointer assignment error!\n");
5954 return DefWindowProcA(hwnd
, WM_NCCREATE
, wParam
, lParam
);
5959 * Destroys the listview control (called after WM_DESTROY).
5962 * [I] HWND : window handle
5967 static LRESULT
LISTVIEW_NCDestroy(HWND hwnd
)
5969 LISTVIEW_INFO
*infoPtr
= (LISTVIEW_INFO
*)GetWindowLongA(hwnd
, 0);
5971 TRACE(listview
, "(hwnd=%x)\n", hwnd
);
5973 /* delete all items */
5974 LISTVIEW_DeleteAllItems(hwnd
);
5976 /* destroy data structure */
5977 DPA_Destroy(infoPtr
->hdpaItems
);
5980 infoPtr
->hFont
= (HFONT
)0;
5981 if (infoPtr
->hDefaultFont
)
5983 DeleteObject(infoPtr
->hDefaultFont
);
5986 /* free listview info pointer*/
5987 COMCTL32_Free(infoPtr
);
5994 * Handles notifications from children.
5997 * [I] HWND : window handle
5998 * [I] INT : control identifier
5999 * [I] LPNMHDR : notification information
6004 static LRESULT
LISTVIEW_Notify(HWND hwnd
, INT nCtrlId
, LPNMHDR lpnmh
)
6006 LISTVIEW_INFO
*infoPtr
= (LISTVIEW_INFO
*)GetWindowLongA(hwnd
, 0);
6008 if (lpnmh
->hwndFrom
== infoPtr
->hwndHeader
)
6010 /* handle notification from header control */
6011 if (lpnmh
->code
== HDN_ENDTRACKA
)
6013 infoPtr
->nItemWidth
= LISTVIEW_GetItemWidth(hwnd
, LVS_REPORT
);
6014 InvalidateRect(hwnd
, NULL
, TRUE
);
6023 * Determines the type of structure to use.
6026 * [I] HWND : window handle of the sender
6027 * [I] HWND : listview window handle
6028 * [I] INT : command specifying the nature of the WM_NOTIFYFORMAT
6033 static LRESULT
LISTVIEW_NotifyFormat(HWND hwndFrom
, HWND hwnd
, INT nCommand
)
6035 LISTVIEW_INFO
*infoPtr
= (LISTVIEW_INFO
*)GetWindowLongA(hwnd
, 0);
6037 if (nCommand
== NF_REQUERY
)
6039 /* determine the type of structure to use */
6040 infoPtr
->notifyFormat
= SendMessageA(hwndFrom
, WM_NOTIFYFORMAT
,
6041 (WPARAM
)hwnd
, (LPARAM
)NF_QUERY
);
6042 if (infoPtr
->notifyFormat
== NFR_UNICODE
)
6044 FIXME (listview
, "NO support for unicode structures");
6053 * Paints/Repaints the listview control.
6056 * [I] HWND : window handle
6057 * [I] HDC : device context handle
6062 static LRESULT
LISTVIEW_Paint(HWND hwnd
, HDC hdc
)
6066 TRACE(listview
, "(hwnd=%x,hdc=%x)\n", hwnd
, hdc
);
6070 hdc
= BeginPaint(hwnd
, &ps
);
6071 LISTVIEW_Refresh(hwnd
, hdc
);
6072 EndPaint(hwnd
, &ps
);
6076 LISTVIEW_Refresh(hwnd
, hdc
);
6084 * Processes double click messages (right mouse button).
6087 * [I] HWND : window handle
6088 * [I] WORD : key flag
6089 * [I] WORD : x coordinate
6090 * [I] WORD : y coordinate
6095 static LRESULT
LISTVIEW_RButtonDblClk(HWND hwnd
, WORD wKey
, WORD wPosX
,
6098 INT nCtrlId
= GetWindowLongA(hwnd
, GWL_ID
);
6101 TRACE(listview
, "(hwnd=%x,key=%hu,X=%hu,Y=%hu)\n", hwnd
, wKey
, wPosX
, wPosY
);
6103 /* send NM_RELEASEDCAPTURE notification */
6104 nmh
.hwndFrom
= hwnd
;
6105 nmh
.idFrom
= nCtrlId
;
6106 nmh
.code
= NM_RELEASEDCAPTURE
;
6107 ListView_Notify(GetParent(hwnd
), nCtrlId
, &nmh
);
6109 /* send NM_RDBLCLK notification */
6110 nmh
.code
= NM_RDBLCLK
;
6111 ListView_Notify(GetParent(hwnd
), nCtrlId
, &nmh
);
6118 * Processes mouse down messages (right mouse button).
6121 * [I] HWND : window handle
6122 * [I] WORD : key flag
6123 * [I] WORD : x coordinate
6124 * [I] WORD : y coordinate
6129 static LRESULT
LISTVIEW_RButtonDown(HWND hwnd
, WORD wKey
, WORD wPosX
,
6132 LISTVIEW_INFO
*infoPtr
= (LISTVIEW_INFO
*)GetWindowLongA(hwnd
, 0);
6133 INT nCtrlId
= GetWindowLongA(hwnd
, GWL_ID
);
6137 TRACE(listview
, "(hwnd=%x,key=%hu,X=%hu,Y=%hu)\n", hwnd
, wKey
, wPosX
, wPosY
);
6139 /* send NM_RELEASEDCAPTURE notification */
6140 nmh
.hwndFrom
= hwnd
;
6141 nmh
.idFrom
= nCtrlId
;
6142 nmh
.code
= NM_RELEASEDCAPTURE
;
6143 ListView_Notify(GetParent(hwnd
), nCtrlId
, &nmh
);
6145 /* make sure the listview control window has the focus */
6146 if (infoPtr
->bFocus
== FALSE
)
6151 /* set right button down flag */
6152 infoPtr
->bRButtonDown
= TRUE
;
6154 /* determine the index of the selected item */
6155 nItem
= LISTVIEW_MouseSelection(hwnd
, wPosX
, wPosY
);
6156 if ((nItem
>= 0) && (nItem
< GETITEMCOUNT(infoPtr
)))
6158 if (!((wKey
& MK_SHIFT
) || (wKey
& MK_CONTROL
)))
6160 LISTVIEW_SetSelection(hwnd
, nItem
);
6165 LISTVIEW_RemoveSelections(hwnd
, 0, GETITEMCOUNT(infoPtr
));
6173 * Processes mouse up messages (right mouse button).
6176 * [I] HWND : window handle
6177 * [I] WORD : key flag
6178 * [I] WORD : x coordinate
6179 * [I] WORD : y coordinate
6184 static LRESULT
LISTVIEW_RButtonUp(HWND hwnd
, WORD wKey
, WORD wPosX
,
6187 LISTVIEW_INFO
*infoPtr
= (LISTVIEW_INFO
*)GetWindowLongA(hwnd
, 0);
6188 INT nCtrlId
= GetWindowLongA(hwnd
, GWL_ID
);
6191 TRACE(listview
, "(hwnd=%x,key=%hu,X=%hu,Y=%hu)\n", hwnd
, wKey
, wPosX
, wPosY
);
6193 if (infoPtr
->bRButtonDown
!= FALSE
)
6195 /* send NM_RClICK notification */
6196 ZeroMemory(&nmh
, sizeof(NMHDR
));
6197 nmh
.hwndFrom
= hwnd
;
6198 nmh
.idFrom
= nCtrlId
;
6199 nmh
.code
= NM_RCLICK
;
6200 ListView_Notify(GetParent(hwnd
), nCtrlId
, &nmh
);
6202 /* set button flag */
6203 infoPtr
->bRButtonDown
= FALSE
;
6214 * [I] HWND : window handle
6215 * [I] HWND : window handle of previously focused window
6220 static LRESULT
LISTVIEW_SetFocus(HWND hwnd
, HWND hwndLoseFocus
)
6222 LISTVIEW_INFO
*infoPtr
= (LISTVIEW_INFO
*)GetWindowLongA(hwnd
, 0);
6223 INT nCtrlId
= GetWindowLongA(hwnd
, GWL_ID
);
6226 /* send NM_SETFOCUS notification */
6227 nmh
.hwndFrom
= hwnd
;
6228 nmh
.idFrom
= nCtrlId
;
6229 nmh
.code
= NM_SETFOCUS
;
6230 ListView_Notify(GetParent(hwnd
), nCtrlId
, &nmh
);
6232 /* set window focus flag */
6233 infoPtr
->bFocus
= TRUE
;
6243 * [I] HWND : window handle
6244 * [I] HFONT : font handle
6245 * [I] WORD : redraw flag
6250 static LRESULT
LISTVIEW_SetFont(HWND hwnd
, HFONT hFont
, WORD fRedraw
)
6252 LISTVIEW_INFO
*infoPtr
= (LISTVIEW_INFO
*)GetWindowLongA(hwnd
, 0);
6253 LONG lStyle
= GetWindowLongA(hwnd
, GWL_STYLE
);
6255 TRACE(listview
, "(hwnd=%x,hfont=%x,redraw=%hu)\n", hwnd
, hFont
, fRedraw
);
6259 infoPtr
->hFont
= infoPtr
->hDefaultFont
;
6263 infoPtr
->hFont
= hFont
;
6266 if ((LVS_TYPEMASK
& lStyle
) == LVS_REPORT
)
6268 /* set header font */
6269 SendMessageA(infoPtr
->hwndHeader
, WM_SETFONT
, (WPARAM
)hFont
,
6270 MAKELPARAM(fRedraw
, 0));
6273 /* invalidate listview control client area */
6274 InvalidateRect(hwnd
, NULL
, TRUE
);
6276 if (fRedraw
!= FALSE
)
6286 * Resizes the listview control. This function processes WM_SIZE
6287 * messages. At this time, the width and height are not used.
6290 * [I] HWND : window handle
6291 * [I] WORD : new width
6292 * [I] WORD : new height
6297 static LRESULT
LISTVIEW_Size(HWND hwnd
, int Width
, int Height
)
6299 LONG lStyle
= GetWindowLongA(hwnd
, GWL_STYLE
);
6301 TRACE(listview
, "(hwnd=%x,width=%d,height=%d)\n",hwnd
, Width
, Height
);
6303 LISTVIEW_SetSize(hwnd
, lStyle
, -1, -1);
6304 switch (lStyle
& LVS_TYPEMASK
)
6308 LISTVIEW_SetViewInfo(hwnd
, lStyle
);
6313 if (lStyle
& LVS_ALIGNLEFT
)
6315 LISTVIEW_AlignLeft(hwnd
);
6319 LISTVIEW_AlignTop(hwnd
);
6324 LISTVIEW_SetScroll(hwnd
, lStyle
);
6326 /* invalidate + erase background */
6327 InvalidateRect(hwnd
, NULL
, TRUE
);
6334 * Sets the size information for a given style.
6337 * [I] HWND : window handle
6338 * [I] LONG : window style
6339 * [I] WORD : new width
6340 * [I] WORD : new height
6345 static VOID
LISTVIEW_SetSize(HWND hwnd
, LONG lStyle
, LONG lWidth
, LONG lHeight
)
6347 LISTVIEW_INFO
*infoPtr
= (LISTVIEW_INFO
*)GetWindowLongA(hwnd
, 0);
6352 GetClientRect(hwnd
, &rcList
);
6355 infoPtr
->rcList
.left
= max(rcList
.left
, 0);
6356 infoPtr
->rcList
.right
= max(rcList
.right
, 0);
6360 infoPtr
->rcList
.left
= max(rcList
.left
, 0);
6361 infoPtr
->rcList
.right
= infoPtr
->rcList
.left
+ max(lWidth
, 0);
6366 infoPtr
->rcList
.top
= max(rcList
.top
, 0);
6367 infoPtr
->rcList
.bottom
= max(rcList
.bottom
, 0);
6371 infoPtr
->rcList
.top
= max(rcList
.top
, 0);
6372 infoPtr
->rcList
.bottom
= infoPtr
->rcList
.top
+ max(lHeight
, 0);
6375 switch (lStyle
& LVS_TYPEMASK
)
6378 if ((lStyle
& WS_HSCROLL
) == 0)
6381 nHScrollHeight
= GetSystemMetrics(SM_CYHSCROLL
);
6382 if (infoPtr
->rcList
.bottom
> nHScrollHeight
)
6384 infoPtr
->rcList
.bottom
-= nHScrollHeight
;
6392 Header_Layout(infoPtr
->hwndHeader
, &hl
);
6393 infoPtr
->rcList
.top
= max(wp
.cy
, 0);
6400 * Processes WM_STYLECHANGED messages.
6403 * [I] HWND : window handle
6404 * [I] WPARAM : window style type (normal or extended)
6405 * [I] LPSTYLESTRUCT : window style information
6410 static INT
LISTVIEW_StyleChanged(HWND hwnd
, WPARAM wStyleType
,
6413 LISTVIEW_INFO
*infoPtr
= (LISTVIEW_INFO
*)GetWindowLongA(hwnd
, 0);
6414 RECT rcList
= infoPtr
->rcList
;
6418 TRACE(listview
, "(hwnd=%x,styletype=%x,stylestruct=%p)\n",
6419 hwnd
, wStyleType
, lpss
);
6421 if (wStyleType
== GWL_STYLE
)
6423 if ((lpss
->styleOld
& WS_HSCROLL
) != 0)
6425 ShowScrollBar(hwnd
, SB_HORZ
, FALSE
);
6428 if ((lpss
->styleOld
& WS_VSCROLL
) != 0)
6430 ShowScrollBar(hwnd
, SB_VERT
, FALSE
);
6433 if ((LVS_TYPEMASK
& lpss
->styleOld
) == LVS_REPORT
)
6436 ShowWindow(infoPtr
->hwndHeader
, SW_HIDE
);
6439 switch (lpss
->styleNew
& LVS_TYPEMASK
)
6442 infoPtr
->iconSize
.cx
= GetSystemMetrics(SM_CXICON
);
6443 infoPtr
->iconSize
.cy
= GetSystemMetrics(SM_CYICON
);
6444 LISTVIEW_SetSize(hwnd
, lpss
->styleNew
, -1, -1);
6445 infoPtr
->nItemWidth
= LISTVIEW_GetItemWidth(hwnd
, lpss
->styleNew
);
6446 infoPtr
->nItemHeight
= LISTVIEW_GetItemHeight(hwnd
, lpss
->styleNew
);
6447 if (lpss
->styleNew
& LVS_ALIGNLEFT
)
6449 LISTVIEW_AlignLeft(hwnd
);
6453 LISTVIEW_AlignTop(hwnd
);
6460 Header_Layout(infoPtr
->hwndHeader
, &hl
);
6461 SetWindowPos(infoPtr
->hwndHeader
, hwnd
, wp
.x
, wp
.y
, wp
.cx
,
6463 ShowWindow(infoPtr
->hwndHeader
, SW_SHOWNORMAL
);
6464 infoPtr
->iconSize
.cx
= GetSystemMetrics(SM_CXSMICON
);
6465 infoPtr
->iconSize
.cy
= GetSystemMetrics(SM_CYSMICON
);
6466 infoPtr
->nItemWidth
= LISTVIEW_GetItemWidth(hwnd
, lpss
->styleNew
);
6467 infoPtr
->nItemHeight
= LISTVIEW_GetItemHeight(hwnd
, lpss
->styleNew
);
6468 LISTVIEW_SetSize(hwnd
, lpss
->styleNew
, -1, -1);
6469 LISTVIEW_SetViewInfo(hwnd
, lpss
->styleNew
);
6473 infoPtr
->iconSize
.cx
= GetSystemMetrics(SM_CXSMICON
);
6474 infoPtr
->iconSize
.cy
= GetSystemMetrics(SM_CYSMICON
);
6475 infoPtr
->nItemWidth
= LISTVIEW_GetItemWidth(hwnd
, lpss
->styleNew
);
6476 infoPtr
->nItemHeight
= LISTVIEW_GetItemHeight(hwnd
, lpss
->styleNew
);
6477 LISTVIEW_SetSize(hwnd
, lpss
->styleNew
, -1, -1);
6478 LISTVIEW_SetViewInfo(hwnd
, lpss
->styleNew
);
6482 infoPtr
->iconSize
.cx
= GetSystemMetrics(SM_CXSMICON
);
6483 infoPtr
->iconSize
.cy
= GetSystemMetrics(SM_CYSMICON
);
6484 LISTVIEW_SetSize(hwnd
, lpss
->styleNew
, -1, -1);
6485 infoPtr
->nItemWidth
= LISTVIEW_GetItemWidth(hwnd
, lpss
->styleNew
);
6486 infoPtr
->nItemHeight
= LISTVIEW_GetItemHeight(hwnd
, lpss
->styleNew
);
6487 if (lpss
->styleNew
& LVS_ALIGNLEFT
)
6489 LISTVIEW_AlignLeft(hwnd
);
6493 LISTVIEW_AlignTop(hwnd
);
6498 LISTVIEW_SetScroll(hwnd
, lpss
->styleNew
);
6500 /* print unsupported styles */
6501 LISTVIEW_UnsupportedStyles(lpss
->styleNew
);
6503 /* invalidate client area */
6504 InvalidateRect(hwnd
, NULL
, TRUE
);
6512 * Window procedure of the listview control.
6523 LRESULT WINAPI
LISTVIEW_WindowProc(HWND hwnd
, UINT uMsg
, WPARAM wParam
,
6528 case LVM_APPROXIMATEVIEWRECT
:
6529 return LISTVIEW_ApproximateViewRect(hwnd
, (INT
)wParam
,
6530 LOWORD(lParam
), HIWORD(lParam
));
6532 return LISTVIEW_Arrange(hwnd
, (INT
)wParam
);
6534 /* case LVM_CREATEDRAGIMAGE: */
6536 case LVM_DELETEALLITEMS
:
6537 return LISTVIEW_DeleteAllItems(hwnd
);
6539 case LVM_DELETECOLUMN
:
6540 return LISTVIEW_DeleteColumn(hwnd
, (INT
)wParam
);
6542 case LVM_DELETEITEM
:
6543 return LISTVIEW_DeleteItem(hwnd
, (INT
)wParam
);
6545 /* case LVM_EDITLABEL: */
6547 case LVM_ENSUREVISIBLE
:
6548 return LISTVIEW_EnsureVisible(hwnd
, (INT
)wParam
, (BOOL
)lParam
);
6551 return LISTVIEW_FindItem(hwnd
, (INT
)wParam
, (LPLVFINDINFO
)lParam
);
6553 case LVM_GETBKCOLOR
:
6554 return LISTVIEW_GetBkColor(hwnd
);
6556 /* case LVM_GETBKIMAGE: */
6558 case LVM_GETCALLBACKMASK
:
6559 return LISTVIEW_GetCallbackMask(hwnd
);
6561 case LVM_GETCOLUMNA
:
6562 return LISTVIEW_GetColumnA(hwnd
, (INT
)wParam
, (LPLVCOLUMNA
)lParam
);
6564 /* case LVM_GETCOLUMNW: */
6565 /* case LVM_GETCOLUMNORDERARRAY: */
6567 case LVM_GETCOLUMNWIDTH
:
6568 return LISTVIEW_GetColumnWidth(hwnd
, (INT
)wParam
);
6570 case LVM_GETCOUNTPERPAGE
:
6571 return LISTVIEW_GetCountPerPage(hwnd
);
6573 /* case LVM_GETEDITCONTROL: */
6574 /* case LVM_GETEXTENDEDLISTVIEWSTYLE: */
6577 return LISTVIEW_GetHeader(hwnd
);
6579 /* case LVM_GETHOTCURSOR: */
6580 /* case LVM_GETHOTITEM: */
6581 /* case LVM_GETHOVERTIME: */
6583 case LVM_GETIMAGELIST
:
6584 return LISTVIEW_GetImageList(hwnd
, (INT
)wParam
);
6586 /* case LVM_GETISEARCHSTRING: */
6589 return LISTVIEW_GetItemA(hwnd
, (LPLVITEMA
)lParam
);
6591 /* case LVM_GETITEMW: */
6593 case LVM_GETITEMCOUNT
:
6594 return LISTVIEW_GetItemCount(hwnd
);
6596 case LVM_GETITEMPOSITION
:
6597 return LISTVIEW_GetItemPosition(hwnd
, (INT
)wParam
, (LPPOINT
)lParam
);
6599 case LVM_GETITEMRECT
:
6600 return LISTVIEW_GetItemRect(hwnd
, (INT
)wParam
, (LPRECT
)lParam
);
6602 case LVM_GETITEMSPACING
:
6603 return LISTVIEW_GetItemSpacing(hwnd
, (BOOL
)wParam
);
6605 case LVM_GETITEMSTATE
:
6606 return LISTVIEW_GetItemState(hwnd
, (INT
)wParam
, (UINT
)lParam
);
6608 case LVM_GETITEMTEXTA
:
6609 LISTVIEW_GetItemTextA(hwnd
, (INT
)wParam
, (LPLVITEMA
)lParam
);
6612 /* case LVM_GETITEMTEXTW: */
6614 case LVM_GETNEXTITEM
:
6615 return LISTVIEW_GetNextItem(hwnd
, (INT
)wParam
, LOWORD(lParam
));
6617 /* case LVM_GETNUMBEROFWORKAREAS: */
6620 return LISTVIEW_GetOrigin(hwnd
, (LPPOINT
)lParam
);
6622 case LVM_GETSELECTEDCOUNT
:
6623 return LISTVIEW_GetSelectedCount(hwnd
);
6625 case LVM_GETSELECTIONMARK
:
6626 return LISTVIEW_GetSelectionMark(hwnd
);
6628 case LVM_GETSTRINGWIDTHA
:
6629 return LISTVIEW_GetStringWidthA (hwnd
, (LPCSTR
)lParam
);
6631 /* case LVM_GETSTRINGWIDTHW: */
6632 /* case LVM_GETSUBITEMRECT: */
6634 case LVM_GETTEXTBKCOLOR
:
6635 return LISTVIEW_GetTextBkColor(hwnd
);
6637 case LVM_GETTEXTCOLOR
:
6638 return LISTVIEW_GetTextColor(hwnd
);
6640 /* case LVM_GETTOOLTIPS: */
6642 case LVM_GETTOPINDEX
:
6643 return LISTVIEW_GetTopIndex(hwnd
);
6645 /* case LVM_GETUNICODEFORMAT: */
6647 case LVM_GETVIEWRECT
:
6648 return LISTVIEW_GetViewRect(hwnd
, (LPRECT
)lParam
);
6650 /* case LVM_GETWORKAREAS: */
6653 return LISTVIEW_HitTest(hwnd
, (LPLVHITTESTINFO
)lParam
);
6655 case LVM_INSERTCOLUMNA
:
6656 return LISTVIEW_InsertColumnA(hwnd
, (INT
)wParam
,
6657 (LPLVCOLUMNA
)lParam
);
6659 /* case LVM_INSERTCOLUMNW: */
6661 case LVM_INSERTITEMA
:
6662 return LISTVIEW_InsertItemA(hwnd
, (LPLVITEMA
)lParam
);
6664 /* case LVM_INSERTITEMW: */
6666 case LVM_REDRAWITEMS
:
6667 return LISTVIEW_RedrawItems(hwnd
, (INT
)wParam
, (INT
)lParam
);
6669 /* case LVM_SCROLL: */
6670 /* return LISTVIEW_Scroll(hwnd, (INT)wParam, (INT)lParam); */
6672 case LVM_SETBKCOLOR
:
6673 return LISTVIEW_SetBkColor(hwnd
, (COLORREF
)lParam
);
6675 /* case LVM_SETBKIMAGE: */
6677 case LVM_SETCALLBACKMASK
:
6678 return LISTVIEW_SetCallbackMask(hwnd
, (UINT
)wParam
);
6680 case LVM_SETCOLUMNA
:
6681 return LISTVIEW_SetColumnA(hwnd
, (INT
)wParam
, (LPLVCOLUMNA
)lParam
);
6683 /* case LVM_SETCOLUMNW: */
6684 /* case LVM_SETCOLUMNORDERARRAY: */
6686 case LVM_SETCOLUMNWIDTH
:
6687 return LISTVIEW_SetColumnWidth(hwnd
, (INT
)wParam
, (INT
)lParam
);
6689 /* case LVM_SETEXTENDEDLISTVIEWSTYLE: */
6690 /* case LVM_SETHOTCURSOR: */
6691 /* case LVM_SETHOTITEM: */
6692 /* case LVM_SETHOVERTIME: */
6693 /* case LVM_SETICONSPACING: */
6695 case LVM_SETIMAGELIST
:
6696 return LISTVIEW_SetImageList(hwnd
, (INT
)wParam
, (HIMAGELIST
)lParam
);
6699 return LISTVIEW_SetItemA(hwnd
, (LPLVITEMA
)lParam
);
6701 /* case LVM_SETITEMW: */
6703 case LVM_SETITEMCOUNT
:
6704 LISTVIEW_SetItemCount(hwnd
, (INT
)wParam
);
6707 case LVM_SETITEMPOSITION
:
6708 return LISTVIEW_SetItemPosition(hwnd
, (INT
)wParam
, (INT
)LOWORD(lParam
),
6709 (INT
)HIWORD(lParam
));
6711 /* case LVM_SETITEMPOSITION: */
6713 case LVM_SETITEMSTATE
:
6714 return LISTVIEW_SetItemState(hwnd
, (INT
)wParam
, (LPLVITEMA
)lParam
);
6716 case LVM_SETITEMTEXTA
:
6717 return LISTVIEW_SetItemTextA(hwnd
, (INT
)wParam
, (LPLVITEMA
)lParam
);
6719 /* case LVM_SETSELECTIONMARK: */
6721 case LVM_SETTEXTBKCOLOR
:
6722 return LISTVIEW_SetTextBkColor(hwnd
, (COLORREF
)lParam
);
6724 case LVM_SETTEXTCOLOR
:
6725 return LISTVIEW_SetTextColor(hwnd
, (COLORREF
)lParam
);
6727 /* case LVM_SETTOOLTIPS: */
6728 /* case LVM_SETUNICODEFORMAT: */
6729 /* case LVM_SETWORKAREAS: */
6732 return LISTVIEW_SortItems(hwnd
, wParam
, lParam
);
6734 /* case LVM_SUBITEMHITTEST: */
6737 return LISTVIEW_Update(hwnd
, (INT
)wParam
);
6740 /* case WM_COMMAND: */
6743 return LISTVIEW_Create(hwnd
, wParam
, lParam
);
6746 return LISTVIEW_EraseBackground(hwnd
, wParam
, lParam
);
6749 return DLGC_WANTTAB
| DLGC_WANTARROWS
;
6752 return LISTVIEW_GetFont(hwnd
);
6755 return LISTVIEW_HScroll(hwnd
, (INT
)LOWORD(wParam
),
6756 (INT
)HIWORD(wParam
), (HWND
)lParam
);
6759 return LISTVIEW_KeyDown(hwnd
, (INT
)wParam
, (LONG
)lParam
);
6762 return LISTVIEW_KillFocus(hwnd
);
6764 case WM_LBUTTONDBLCLK
:
6765 return LISTVIEW_LButtonDblClk(hwnd
, (WORD
)wParam
, LOWORD(lParam
),
6768 case WM_LBUTTONDOWN
:
6769 return LISTVIEW_LButtonDown(hwnd
, (WORD
)wParam
, LOWORD(lParam
),
6772 return LISTVIEW_LButtonUp(hwnd
, (WORD
)wParam
, LOWORD(lParam
),
6775 /* case WM_MOUSEMOVE: */
6776 /* return LISTVIEW_MouseMove (hwnd, wParam, lParam); */
6779 return LISTVIEW_NCCreate(hwnd
, wParam
, lParam
);
6782 return LISTVIEW_NCDestroy(hwnd
);
6785 return LISTVIEW_Notify(hwnd
, (INT
)wParam
, (LPNMHDR
)lParam
);
6787 case WM_NOTIFYFORMAT
:
6788 return LISTVIEW_NotifyFormat(hwnd
, (HWND
)wParam
, (INT
)lParam
);
6791 return LISTVIEW_Paint(hwnd
, (HDC
)wParam
);
6793 case WM_RBUTTONDBLCLK
:
6794 return LISTVIEW_RButtonDblClk(hwnd
, (WORD
)wParam
, LOWORD(lParam
),
6797 case WM_RBUTTONDOWN
:
6798 return LISTVIEW_RButtonDown(hwnd
, (WORD
)wParam
, LOWORD(lParam
),
6802 return LISTVIEW_RButtonUp(hwnd
, (WORD
)wParam
, LOWORD(lParam
),
6806 return LISTVIEW_SetFocus(hwnd
, (HWND
)wParam
);
6809 return LISTVIEW_SetFont(hwnd
, (HFONT
)wParam
, (WORD
)lParam
);
6811 /* case WM_SETREDRAW: */
6814 return LISTVIEW_Size(hwnd
, (int)SLOWORD(lParam
), (int)SHIWORD(lParam
));
6816 case WM_STYLECHANGED
:
6817 return LISTVIEW_StyleChanged(hwnd
, wParam
, (LPSTYLESTRUCT
)lParam
);
6819 /* case WM_TIMER: */
6822 return LISTVIEW_VScroll(hwnd
, (INT
)LOWORD(wParam
),
6823 (INT
)HIWORD(wParam
), (HWND
)lParam
);
6825 /* case WM_WINDOWPOSCHANGED: */
6826 /* case WM_WININICHANGE: */
6829 if (uMsg
>= WM_USER
)
6831 ERR(listview
, "unknown msg %04x wp=%08x lp=%08lx\n", uMsg
, wParam
,
6835 /* call default window procedure */
6836 return DefWindowProcA(hwnd
, uMsg
, wParam
, lParam
);
6844 * Registers the window class.
6852 VOID
LISTVIEW_Register(VOID
)
6856 if (!GlobalFindAtomA(WC_LISTVIEWA
))
6858 ZeroMemory(&wndClass
, sizeof(WNDCLASSA
));
6859 wndClass
.style
= CS_GLOBALCLASS
| CS_DBLCLKS
;
6860 wndClass
.lpfnWndProc
= (WNDPROC
)LISTVIEW_WindowProc
;
6861 wndClass
.cbClsExtra
= 0;
6862 wndClass
.cbWndExtra
= sizeof(LISTVIEW_INFO
*);
6863 wndClass
.hCursor
= LoadCursorA(0, IDC_ARROWA
);
6864 wndClass
.hbrBackground
= (HBRUSH
)(COLOR_WINDOW
+ 1);
6865 wndClass
.lpszClassName
= WC_LISTVIEWA
;
6866 RegisterClassA(&wndClass
);
6872 * Unregisters the window class.
6880 VOID
LISTVIEW_Unregister(VOID
)
6882 if (GlobalFindAtomA(WC_LISTVIEWA
))
6884 UnregisterClassA(WC_LISTVIEWA
, (HINSTANCE
)NULL
);