4 * Copyright 1998 Eric Kohl
5 * Copyright 1999 Luc Tourangeau
8 * Listview control implementation.
11 * LISTVIEW_GetMaxItemWidth : large icon view
12 * LISTVIEW_Notify : notification from children
13 * LISTVIEW_KeyDown : key press messages
14 * LISTVIEW_HScroll : small icon and icon
15 * LISTVIEW_VScroll : small icon and icon
16 * LISTVIEW_SortItems : empty stub
17 * LISTVIEW_SetItemPosition : small icon and icon
18 * LISTVIEW_SetItemCount : empty stub
19 * LISTVIEW_SetItem32W : no unicode yet!
20 * LISTVIEW_SetColumn32A : DOUBLE CHECK
21 * LISTVIEW_Scroll : scrolling in pixels
22 * LISTVIEW_RedrawItems : define bounding rect
23 * LISTVIEW_InsertItem32W : no unicode yet!
24 * LISTVIEW_InsertColumn32W : no unicode yet!
25 * LISTVIEW_GetViewRect : small icon and icon
26 * LISTVIEW_GetOrigin : small icon and icon
27 * LISTVIEW_GetNumberOfWorkAreas : small icon and icon
28 * LISTVIEW_GetNextItem : all
29 * LISTVIEW_SetScroll : scrolling in pixels
30 * LISTVIEW_GetItemRect : all
31 * LISTVIEW_GetHotCursor : all
32 * LISTVIEW_GetHotItem : all
33 * LISTVIEW_GetHoverTime : all
34 * LISTVIEW_GetISearchString : all
35 * LISTVIEW_GetBkImage : all
36 * LISTVIEW_FindItem : all
37 * LISTVIEW_EnsureVisible : some
38 * LISTVIEW_EditLabel : REPORT (need to implement a timer)
39 * LISTVIEW_GetItemPosition : small icon and icon
40 * LISTVIEW_GetItemRect : some
41 * LISTVIEW_Arrange : small icon and icon
42 * LISTVIEW_ApproximateViewRect : report, small icon and icon
43 * LISTVIEW_RefreshIcon : large icon draw function
53 #define DISP_TEXT_SIZE 128
54 #define WIDTH_PADDING 12
55 #define HEIGHT_PADDING 2
56 #define MIN_COLUMN_WIDTH 96
59 #define GETITEMCOUNT(infoPtr) ((infoPtr)->hdpaItems->nItemCount)
60 #define ListView_LVNotify(hwnd,lCtrlId,plvnm) \
61 (BOOL)SendMessageA((hwnd),WM_NOTIFY,(WPARAM)(INT)lCtrlId,(LPARAM)(LPNMLISTVIEW)(plvnm))
62 #define ListView_Notify(hwnd,lCtrlId,pnmh) \
63 (BOOL)SendMessageA((hwnd),WM_NOTIFY,(WPARAM)(INT)lCtrlId,(LPARAM)(LPNMHDR)(pnmh))
65 /* forward declarations */
66 static VOID LISTVIEW_SetSize(HWND hwnd, LONG lStyle, LONG lWidth,
68 static VOID LISTVIEW_SetViewInfo(HWND hwnd);
69 static VOID LISTVIEW_SetScroll(HWND hwnd);
70 static VOID LISTVIEW_AddGroupSelection(HWND hwnd, INT nItem);
71 static VOID LISTVIEW_AddSelection(HWND hwnd, INT nItem);
72 static BOOL LISTVIEW_ToggleSelection(HWND hwnd, INT nItem);
73 static VOID LISTVIEW_SetGroupSelection(HWND hwnd, INT nItem);
74 static VOID LISTVIEW_SetSelection(HWND hwnd, INT nItem);
75 static VOID LISTVIEW_RemoveSelections(HWND hwnd, INT nFirst, INT nLast);
76 static VOID LISTVIEW_SetItemFocus(HWND hwnd, INT nItem);
77 static BOOL LISTVIEW_RemoveSubItem(HDPA hdpaSubItems, INT nSubItem);
78 static BOOL LISTVIEW_RemoveColumn(HDPA hdpaItems, INT nColumn);
79 static BOOL LISTVIEW_InitItem(HWND hwnd, LISTVIEW_ITEM *lpItem,
81 static BOOL LISTVIEW_InitSubItem(HWND hwnd, LISTVIEW_SUBITEM *lpSubItem,
83 static BOOL LISTVIEW_AddSubItem(HWND hwnd, LPLVITEMA lpLVItem);
84 static BOOL LISTVIEW_SetItem(HWND hwnd, LPLVITEMA lpLVItem);
85 static BOOL LISTVIEW_SetSubItem(HWND hwnd, LPLVITEMA lpLVItem);
86 static INT LISTVIEW_FindInsertPosition(HDPA hdpaSubItems, INT nSubItem);
87 static LISTVIEW_SUBITEM* LISTVIEW_GetSubItem(HDPA hdpaSubItems, INT nSubItem);
92 * Prints a message for unsupported window styles.
95 * [I] LONG : window style
100 static VOID LISTVIEW_UnsupportedStyles(LONG lStyle)
102 if ((LVS_TYPEMASK & lStyle) == LVS_ALIGNLEFT)
104 FIXME(listview, " LVS_ALIGNLEFT\n");
107 if ((LVS_TYPEMASK & lStyle) == LVS_ALIGNTOP)
109 FIXME(listview, " LVS_ALIGNTOP\n");
112 if ((LVS_TYPEMASK & lStyle) == LVS_AUTOARRANGE)
114 FIXME(listview, " LVS_AUTOARRANGE\n");
117 if ((LVS_TYPEMASK & lStyle) == LVS_EDITLABELS)
119 FIXME(listview, " LVS_EDITLABELS\n");
122 if ((LVS_TYPEMASK & lStyle) == LVS_ICON)
124 FIXME(listview, " LVS_ICON\n");
127 if ((LVS_TYPEMASK & lStyle) == LVS_NOCOLUMNHEADER)
129 FIXME(listview, " LVS_SORTDESCENDING\n");
132 if ((LVS_TYPEMASK & lStyle) == LVS_NOLABELWRAP)
134 FIXME(listview, " LVS_NOLABELWRAP\n");
137 if ((LVS_TYPEMASK & lStyle) == LVS_NOSCROLL)
139 FIXME(listview, " LVS_NOSCROLL\n");
142 if ((LVS_TYPEMASK & lStyle) == LVS_NOSORTHEADER)
144 FIXME(listview, " LVS_NOSORTHEADER\n");
147 if ((LVS_TYPEMASK & lStyle) == LVS_OWNERDRAWFIXED)
149 FIXME(listview, " LVS_OWNERDRAWFIXED\n");
152 if ((LVS_TYPEMASK & lStyle) == LVS_SHAREIMAGELISTS)
154 FIXME(listview, " LVS_SHAREIMAGELISTS\n");
157 if ((LVS_TYPEMASK & lStyle) == LVS_SHOWSELALWAYS)
159 FIXME(listview, " LVS_SHOWSELALWAYS\n");
162 if ((LVS_TYPEMASK & lStyle) == LVS_SINGLESEL)
164 FIXME(listview, " LVS_SINGLESEL\n");
167 if ((LVS_TYPEMASK & lStyle) == LVS_SMALLICON)
169 FIXME(listview, " LVS_SMALLICON\n");
172 if ((LVS_TYPEMASK & lStyle) == LVS_SORTDESCENDING)
174 FIXME(listview, " LVS_SORTDESCENDING\n");
177 if ((LVS_TYPEMASK & lStyle) == LVS_SORTDESCENDING)
179 FIXME(listview, " LVS_SORTDESCENDING\n");
185 * Retrieves display information.
188 * [I] HWND : window handle
189 * [I] LISTVIEW_ITEM* : listview control item
190 * [O] INT : image index
191 * [O] UINT : state value
192 * [O] CHAR** : string
193 * [I] INT : size of string
198 static VOID LISTVIEW_GetItemDispInfo(HWND hwnd, INT nItem,
199 LISTVIEW_ITEM *lpItem, INT *pnDispImage,
200 UINT *puState, CHAR **ppszDispText,
203 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
204 LONG lCtrlId = GetWindowLongA(hwnd, GWL_ID);
205 NMLVDISPINFOA dispInfo;
206 ZeroMemory(&dispInfo, sizeof(NMLVDISPINFOA));
208 if ((pnDispImage != NULL) && (lpItem->iImage == I_IMAGECALLBACK))
210 dispInfo.item.mask |= LVIF_IMAGE;
213 if ((ppszDispText != NULL) && (lpItem->pszText == LPSTR_TEXTCALLBACKA))
215 ZeroMemory(*ppszDispText, sizeof(CHAR)*nDispTextSize);
216 dispInfo.item.mask |= LVIF_TEXT;
217 dispInfo.item.pszText = *ppszDispText;
218 dispInfo.item.cchTextMax = nDispTextSize;
221 if ((puState != NULL) && (infoPtr->uCallbackMask != 0))
223 dispInfo.item.mask |= LVIF_STATE;
224 dispInfo.item.stateMask = infoPtr->uCallbackMask;
227 if (dispInfo.item.mask != 0)
229 dispInfo.hdr.hwndFrom = hwnd;
230 dispInfo.hdr.idFrom = lCtrlId;
231 dispInfo.hdr.code = LVN_GETDISPINFOA;
232 dispInfo.item.iItem = nItem;
233 dispInfo.item.iSubItem = 0;
234 dispInfo.item.lParam = lpItem->lParam;
235 ListView_Notify(GetParent(hwnd), lCtrlId, &dispInfo);
238 if (pnDispImage != NULL)
240 if (dispInfo.item.mask & LVIF_IMAGE)
242 *pnDispImage = dispInfo.item.iImage;
246 *pnDispImage = lpItem->iImage;
250 if (ppszDispText != NULL)
252 if (dispInfo.item.mask & LVIF_TEXT)
254 if (dispInfo.item.mask & LVIF_DI_SETITEM)
256 Str_SetPtrA(&lpItem->pszText, dispInfo.item.pszText);
258 *ppszDispText = dispInfo.item.pszText;
262 *ppszDispText = lpItem->pszText;
268 if (dispInfo.item.mask & LVIF_STATE)
270 *puState = lpItem->state;
271 *puState &= ~dispInfo.item.stateMask;
272 *puState |= (dispInfo.item.state & dispInfo.item.stateMask);
276 *puState = lpItem->state;
283 * Retrieves display information.
286 * [I] HWND : window handle
287 * [I] LISTVIEW_SUBITEM* : listview control subitem
288 * [O] INT : image index
289 * [O] UINT : state value
290 * [O] CHAR** : string
291 * [I] INT : size of string
296 static VOID LISTVIEW_GetSubItemDispInfo(HWND hwnd, INT nItem, LPARAM lParam,
297 LISTVIEW_SUBITEM *lpSubItem,
298 INT nColumn, INT *pnDispImage,
299 CHAR **ppszDispText, INT nDispTextSize)
301 LONG lCtrlId = GetWindowLongA(hwnd, GWL_ID);
302 NMLVDISPINFOA dispInfo;
303 ZeroMemory(&dispInfo, sizeof(NMLVDISPINFOA));
305 if (lpSubItem == NULL)
307 ZeroMemory(*ppszDispText, sizeof(CHAR)*nDispTextSize);
308 dispInfo.item.mask |= LVIF_TEXT;
309 dispInfo.item.pszText = *ppszDispText;
310 dispInfo.item.cchTextMax = nDispTextSize;
311 dispInfo.hdr.hwndFrom = hwnd;
312 dispInfo.hdr.idFrom = lCtrlId;
313 dispInfo.hdr.code = LVN_GETDISPINFOA;
314 dispInfo.item.iItem = nItem;
315 dispInfo.item.iSubItem = nColumn;
316 dispInfo.item.lParam = lParam;
317 ListView_Notify(GetParent(hwnd), lCtrlId, &dispInfo);
318 if (dispInfo.item.mask & LVIF_DI_SETITEM)
320 Str_SetPtrA(&lpSubItem->pszText, dispInfo.item.pszText);
322 *ppszDispText = dispInfo.item.pszText;
326 if ((pnDispImage != NULL) && (lpSubItem->iImage == I_IMAGECALLBACK))
328 dispInfo.item.mask |= LVIF_IMAGE;
331 if ((ppszDispText != NULL) && (lpSubItem->pszText == LPSTR_TEXTCALLBACKA))
333 ZeroMemory(*ppszDispText, sizeof(CHAR)*nDispTextSize);
334 dispInfo.item.mask |= LVIF_TEXT;
335 dispInfo.item.pszText = *ppszDispText;
336 dispInfo.item.cchTextMax = nDispTextSize;
339 if (dispInfo.item.mask != 0)
341 dispInfo.hdr.hwndFrom = hwnd;
342 dispInfo.hdr.idFrom = lCtrlId;
343 dispInfo.hdr.code = LVN_GETDISPINFOA;
344 dispInfo.item.iItem = nItem;
345 dispInfo.item.iSubItem = lpSubItem->iSubItem;
346 dispInfo.item.lParam = lParam;
347 ListView_Notify(GetParent(hwnd), lCtrlId, &dispInfo);
350 if (pnDispImage != NULL)
352 if (dispInfo.item.mask & LVIF_IMAGE)
354 *pnDispImage = dispInfo.item.iImage;
358 *pnDispImage = lpSubItem->iImage;
362 if (ppszDispText != NULL)
364 if (dispInfo.item.mask & LVIF_TEXT)
366 if (dispInfo.item.mask & LVIF_DI_SETITEM)
368 Str_SetPtrA(&lpSubItem->pszText, dispInfo.item.pszText);
370 *ppszDispText = dispInfo.item.pszText;
374 *ppszDispText = lpSubItem->pszText;
382 * Calculates a new column width.
385 * [I] HWND : window handle
388 * Returns item width.
390 static INT LISTVIEW_GetMaxItemWidth(HWND hwnd)
392 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
393 LONG lStyle = GetWindowLongA(hwnd, GWL_STYLE);
394 LISTVIEW_ITEM *lpItem;
397 INT nMaxItemWidth = 0;
400 if ((LVS_TYPEMASK & lStyle) == LVS_ICON)
406 for (i = 0; i < GETITEMCOUNT(infoPtr); i++)
408 hdpaSubItems = (HDPA)DPA_GetPtr(infoPtr->hdpaItems, i);
409 if (hdpaSubItems != NULL)
411 lpItem = (LISTVIEW_ITEM *)DPA_GetPtr(hdpaSubItems, 0);
414 CHAR szDispText[DISP_TEXT_SIZE];
416 pszDispText = szDispText;
417 LISTVIEW_GetItemDispInfo(hwnd, i, lpItem, NULL, NULL, &pszDispText,
419 nStringWidth = ListView_GetStringWidthA(hwnd, pszDispText);
420 nMaxItemWidth = max(nMaxItemWidth, nStringWidth);
425 /* add arbitrary padding for separating columns */
426 nMaxItemWidth += WIDTH_PADDING;
428 if (infoPtr->himlSmall != NULL)
430 nMaxItemWidth += infoPtr->iconSize.cx;
433 if (infoPtr->himlState != NULL)
435 nMaxItemWidth += infoPtr->iconSize.cx;
439 nMaxItemWidth = max(MIN_COLUMN_WIDTH, nMaxItemWidth);
441 return nMaxItemWidth;
446 * Sets diplay information (needed for drawing and calculations).
449 * [I] HWND : window handle
454 static VOID LISTVIEW_SetViewInfo(HWND hwnd)
456 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
457 LONG lStyle = GetWindowLongA(hwnd, GWL_STYLE);
464 /* get text height */
466 hOldFont = SelectObject(hdc, infoPtr->hFont);
467 GetTextMetricsA(hdc, &tm);
469 nHeight = infoPtr->rcList.bottom - infoPtr->rcList.top;
470 nWidth = infoPtr->rcList.right - infoPtr->rcList.left;
472 switch (LVS_TYPEMASK & lStyle)
475 infoPtr->nColumnWidth = LISTVIEW_GetMaxItemWidth(hwnd);
476 infoPtr->nItemHeight = (max(tm.tmHeight, infoPtr->iconSize.cy) +
479 infoPtr->nCountPerColumn = nHeight / infoPtr->nItemHeight;
480 if (infoPtr->nCountPerColumn == 0)
482 infoPtr->nCountPerColumn = 1;
485 infoPtr->nCountPerRow = nWidth / infoPtr->nColumnWidth;
486 if (infoPtr->nCountPerRow == 0)
488 infoPtr->nCountPerRow = 1;
493 infoPtr->nItemHeight = (max(tm.tmHeight, infoPtr->iconSize.cy) +
495 infoPtr->nCountPerRow = 1;
496 infoPtr->nCountPerColumn = nHeight / infoPtr->nItemHeight;
497 if (infoPtr->nCountPerColumn == 0)
499 infoPtr->nCountPerColumn = 1;
505 SelectObject(hdc, hOldFont);
506 ReleaseDC(hwnd, hdc);
511 * Adds a block of selections.
514 * [I] HWND : window handle
515 * [I] INT : item index
520 static VOID LISTVIEW_AddGroupSelection(HWND hwnd, INT nItem)
522 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
523 INT nFirst = min(infoPtr->nSelectionMark, nItem);
524 INT nLast = max(infoPtr->nSelectionMark, nItem);
528 lvItem.state = LVIS_SELECTED;
529 lvItem.stateMask= LVIS_SELECTED;
531 for (i = nFirst; i <= nLast; i++)
533 ListView_SetItemState(hwnd, i, &lvItem);
536 LISTVIEW_SetItemFocus(hwnd, nItem);
537 infoPtr->nSelectionMark = nItem;
542 * Adds a single selection.
545 * [I] HWND : window handle
546 * [I] INT : item index
551 static VOID LISTVIEW_AddSelection(HWND hwnd, INT nItem)
553 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
556 lvItem.state = LVIS_SELECTED;
557 lvItem.stateMask= LVIS_SELECTED;
559 ListView_SetItemState(hwnd, nItem, &lvItem);
561 LISTVIEW_SetItemFocus(hwnd, nItem);
562 infoPtr->nSelectionMark = nItem;
567 * Selects or unselects an item.
570 * [I] HWND : window handle
571 * [I] INT : item index
577 static BOOL LISTVIEW_ToggleSelection(HWND hwnd, INT nItem)
579 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
583 lvItem.stateMask= LVIS_SELECTED;
585 if (ListView_GetItemState(hwnd, nItem, LVIS_SELECTED) & LVIS_SELECTED)
588 ListView_SetItemState(hwnd, nItem, &lvItem);
593 lvItem.state = LVIS_SELECTED;
594 ListView_SetItemState(hwnd, nItem, &lvItem);
598 LISTVIEW_SetItemFocus(hwnd, nItem);
599 infoPtr->nSelectionMark = nItem;
606 * Reinitilizes the listview items.
609 * [I] HWND : window handle
610 * [I] INT : item index
615 static VOID LISTVIEW_SetGroupSelection(HWND hwnd, INT nItem)
617 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
618 INT nFirst = min(infoPtr->nSelectionMark, nItem);
619 INT nLast = max(infoPtr->nSelectionMark, nItem);
625 LISTVIEW_RemoveSelections(hwnd, 0, nFirst - 1);
628 if (nLast < GETITEMCOUNT(infoPtr))
630 LISTVIEW_RemoveSelections(hwnd, nLast + 1, GETITEMCOUNT(infoPtr));
633 lvItem.state = LVIS_SELECTED;
634 lvItem.stateMask = LVIS_SELECTED;
636 for (i = nFirst; i <= nLast; i++)
638 ListView_SetItemState(hwnd, i, &lvItem);
641 LISTVIEW_SetItemFocus(hwnd, nItem);
646 * Manages the item focus.
649 * [I] HWND : window handle
650 * [I] INT : item index
655 static VOID LISTVIEW_SetItemFocus(HWND hwnd, INT nItem)
657 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
661 lvItem.stateMask = LVIS_FOCUSED;
662 ListView_SetItemState(hwnd, infoPtr->nFocusedItem, &lvItem);
664 lvItem.state = LVIS_FOCUSED;
665 lvItem.stateMask = LVIS_FOCUSED;
666 ListView_SetItemState(hwnd, nItem, &lvItem);
668 infoPtr->nFocusedItem = nItem;
670 /* if multiple selection is allowed */
671 ListView_EnsureVisible(hwnd, nItem, FALSE);
676 * Reinitilizes the listview items.
679 * [I] HWND : window handle
680 * [I] INT : item index
685 static VOID LISTVIEW_SetSelection(HWND hwnd, INT nItem)
687 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
692 LISTVIEW_RemoveSelections(hwnd, 0, nItem - 1);
695 if (nItem < GETITEMCOUNT(infoPtr))
697 LISTVIEW_RemoveSelections(hwnd, nItem + 1, GETITEMCOUNT(infoPtr));
701 lvItem.stateMask = LVIS_FOCUSED;
702 ListView_SetItemState(hwnd, infoPtr->nFocusedItem, &lvItem);
704 lvItem.state = LVIS_SELECTED | LVIS_FOCUSED;
705 lvItem.stateMask = LVIS_SELECTED | LVIS_FOCUSED;
706 ListView_SetItemState(hwnd, nItem, &lvItem);
708 infoPtr->nFocusedItem = nItem;
709 infoPtr->nSelectionMark = nItem;
714 * Reinitilizes the listview items.
717 * [I] HWND : window handle
718 * [I] INT : item index
723 static VOID LISTVIEW_KeySelection(HWND hwnd, INT nItem)
725 WORD wShift = HIWORD(GetKeyState(VK_SHIFT));
726 WORD wCtrl = HIWORD(GetKeyState(VK_CONTROL));
730 LISTVIEW_SetGroupSelection(hwnd, nItem);
734 LISTVIEW_SetItemFocus(hwnd, nItem);
738 LISTVIEW_SetSelection(hwnd, nItem);
740 /* if multiple selection is allowed */
741 ListView_EnsureVisible(hwnd, nItem, FALSE);
747 * Removes all selection states.
750 * [I] HWND : window handle
751 * [I] INT : item index
757 static VOID LISTVIEW_RemoveSelections(HWND hwnd, INT nFirst, INT nLast)
763 lvItem.stateMask = LVIS_SELECTED;
765 for (i = nFirst; i <= nLast; i++)
767 ListView_SetItemState(hwnd, i, &lvItem);
776 * [IO] HDPA : dynamic pointer array handle
777 * [I] INT : column index (subitem index)
783 static BOOL LISTVIEW_RemoveColumn(HDPA hdpaItems, INT nSubItem)
789 for (i = 0; i < hdpaItems->nItemCount; i++)
791 hdpaSubItems = (HDPA)DPA_GetPtr(hdpaItems, i);
792 if (hdpaSubItems != NULL)
794 if (LISTVIEW_RemoveSubItem(hdpaSubItems, nSubItem) == FALSE)
806 * Removes a subitem at a given position.
809 * [IO] HDPA : dynamic pointer array handle
810 * [I] INT : subitem index
816 static BOOL LISTVIEW_RemoveSubItem(HDPA hdpaSubItems, INT nSubItem)
818 LISTVIEW_SUBITEM *lpSubItem;
821 for (i = 1; i < hdpaSubItems->nItemCount; i++)
823 lpSubItem = (LISTVIEW_SUBITEM *)DPA_GetPtr(hdpaSubItems, i);
824 if (lpSubItem != NULL)
826 if (lpSubItem->iSubItem == nSubItem)
829 if ((lpSubItem->pszText != NULL) &&
830 (lpSubItem->pszText != LPSTR_TEXTCALLBACKA))
832 COMCTL32_Free(lpSubItem->pszText);
836 COMCTL32_Free(lpSubItem);
838 /* free dpa memory */
839 if (DPA_DeletePtr(hdpaSubItems, i) == NULL)
844 else if (lpSubItem->iSubItem > nSubItem)
856 * Compares the item information.
859 * [I] LISTVIEW_ITEM *: destination item
860 * [I] LPLVITEM : source item
863 * SUCCCESS : TRUE (EQUAL)
864 * FAILURE : FALSE (NOT EQUAL)
866 static UINT LISTVIEW_GetItemChanges(LISTVIEW_ITEM *lpItem, LPLVITEMA lpLVItem)
870 if ((lpItem != NULL) && (lpLVItem != NULL))
872 if (lpLVItem->mask & LVIF_STATE)
874 if ((lpItem->state & lpLVItem->stateMask) !=
875 (lpLVItem->state & lpLVItem->stateMask))
877 uChanged |= LVIF_STATE;
881 if (lpLVItem->mask & LVIF_IMAGE)
883 if (lpItem->iImage != lpLVItem->iImage)
885 uChanged |= LVIF_IMAGE;
889 if (lpLVItem->mask & LVIF_PARAM)
891 if (lpItem->lParam != lpLVItem->lParam)
893 uChanged |= LVIF_PARAM;
897 if (lpLVItem->mask & LVIF_INDENT)
899 if (lpItem->iIndent != lpLVItem->iIndent)
901 uChanged |= LVIF_INDENT;
905 if (lpLVItem->mask & LVIF_TEXT)
907 if (lpLVItem->pszText == LPSTR_TEXTCALLBACKA)
909 if (lpItem->pszText != LPSTR_TEXTCALLBACKA)
911 uChanged |= LVIF_TEXT;
916 if (lpItem->pszText == LPSTR_TEXTCALLBACKA)
918 uChanged |= LVIF_TEXT;
929 * Initializes item attributes.
932 * [I] HWND : window handle
933 * [O] LISTVIEW_ITEM *: destination item
934 * [I] LPLVITEM : source item
940 static BOOL LISTVIEW_InitItem(HWND hwnd, LISTVIEW_ITEM *lpItem,
943 LONG lStyle = GetWindowLongA(hwnd, GWL_STYLE);
944 BOOL bResult = FALSE;
946 if ((lpItem != NULL) && (lpLVItem != NULL))
950 if (lpLVItem->mask & LVIF_STATE)
952 lpItem->state &= ~lpLVItem->stateMask;
953 lpItem->state |= (lpLVItem->state & lpLVItem->stateMask);
956 if (lpLVItem->mask & LVIF_IMAGE)
958 lpItem->iImage = lpLVItem->iImage;
961 if (lpLVItem->mask & LVIF_PARAM)
963 lpItem->lParam = lpLVItem->lParam;
966 if (lpLVItem->mask & LVIF_INDENT)
968 lpItem->iIndent = lpLVItem->iIndent;
971 if (lpLVItem->mask & LVIF_TEXT)
973 if (lpLVItem->pszText == LPSTR_TEXTCALLBACKA)
975 if ((lStyle & LVS_SORTASCENDING) || (lStyle & LVS_SORTDESCENDING))
980 if ((lpItem->pszText != NULL) &&
981 (lpItem->pszText != LPSTR_TEXTCALLBACKA))
983 COMCTL32_Free(lpItem->pszText);
986 lpItem->pszText = LPSTR_TEXTCALLBACKA;
990 if (lpItem->pszText == LPSTR_TEXTCALLBACKA)
992 lpItem->pszText = NULL;
995 bResult = Str_SetPtrA(&lpItem->pszText, lpLVItem->pszText);
1005 * Initializes subitem attributes.
1007 * NOTE: the documentation specifies that the operation fails if the user
1008 * tries to set the indent of a subitem.
1011 * [I] HWND : window handle
1012 * [O] LISTVIEW_SUBITEM *: destination subitem
1013 * [I] LPLVITEM : source subitem
1019 static BOOL LISTVIEW_InitSubItem(HWND hwnd, LISTVIEW_SUBITEM *lpSubItem,
1022 LONG lStyle = GetWindowLongA(hwnd, GWL_STYLE);
1023 BOOL bResult = FALSE;
1025 if ((lpSubItem != NULL) && (lpLVItem != NULL))
1027 if (!(lpLVItem->mask & LVIF_INDENT))
1030 ZeroMemory(lpSubItem, sizeof(LISTVIEW_SUBITEM));
1032 lpSubItem->iSubItem = lpLVItem->iSubItem;
1034 if (lpLVItem->mask & LVIF_IMAGE)
1036 lpSubItem->iImage = lpLVItem->iImage;
1039 if (lpLVItem->mask & LVIF_TEXT)
1041 if (lpLVItem->pszText == LPSTR_TEXTCALLBACKA)
1043 if ((lStyle & LVS_SORTASCENDING) || (lStyle & LVS_SORTDESCENDING))
1048 if ((lpSubItem->pszText != NULL) &&
1049 (lpSubItem->pszText != LPSTR_TEXTCALLBACKA))
1051 COMCTL32_Free(lpSubItem->pszText);
1054 lpSubItem->pszText = LPSTR_TEXTCALLBACKA;
1058 if (lpSubItem->pszText == LPSTR_TEXTCALLBACKA)
1060 lpSubItem->pszText = NULL;
1063 bResult = Str_SetPtrA(&lpSubItem->pszText, lpLVItem->pszText);
1074 * Adds a subitem at a given position (column index).
1077 * [I] HWND : window handle
1078 * [I] LPLVITEM : new subitem atttributes
1084 static BOOL LISTVIEW_AddSubItem(HWND hwnd, LPLVITEMA lpLVItem)
1086 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
1087 BOOL bResult = FALSE;
1089 LISTVIEW_SUBITEM *lpSubItem = NULL;
1090 INT nPosition, nItem;
1092 if (lpLVItem != NULL)
1094 hdpaSubItems = (HDPA)DPA_GetPtr(infoPtr->hdpaItems, lpLVItem->iItem);
1095 if (hdpaSubItems != NULL)
1097 lpSubItem = (LISTVIEW_SUBITEM *)COMCTL32_Alloc(sizeof(LISTVIEW_SUBITEM));
1098 if (lpSubItem != NULL)
1100 if (LISTVIEW_InitSubItem(hwnd, lpSubItem, lpLVItem) == TRUE)
1102 nPosition = LISTVIEW_FindInsertPosition(hdpaSubItems,
1103 lpSubItem->iSubItem);
1104 nItem = DPA_InsertPtr(hdpaSubItems, nPosition, lpSubItem);
1114 /* cleanup if unsuccessful */
1115 if ((bResult == FALSE) && (lpSubItem != NULL))
1117 COMCTL32_Free(lpSubItem);
1125 * Finds the dpa insert position (array index).
1128 * [I] HWND : window handle
1129 * [I] INT : subitem index
1135 static INT LISTVIEW_FindInsertPosition(HDPA hdpaSubItems, INT nSubItem)
1137 LISTVIEW_SUBITEM *lpSubItem;
1140 for (i = 1; i < hdpaSubItems->nItemCount; i++)
1142 lpSubItem = (LISTVIEW_SUBITEM *)DPA_GetPtr(hdpaSubItems, i);
1143 if (lpSubItem != NULL)
1145 if (lpSubItem->iSubItem > nSubItem)
1152 return hdpaSubItems->nItemCount;
1157 * Retrieves a listview subitem at a given position (column index).
1160 * [I] HWND : window handle
1161 * [I] INT : subitem index
1167 static LISTVIEW_SUBITEM* LISTVIEW_GetSubItem(HDPA hdpaSubItems, INT nSubItem)
1169 LISTVIEW_SUBITEM *lpSubItem;
1172 for (i = 1; i < hdpaSubItems->nItemCount; i++)
1174 lpSubItem = (LISTVIEW_SUBITEM *)DPA_GetPtr(hdpaSubItems, i);
1175 if (lpSubItem != NULL)
1177 if (lpSubItem->iSubItem == nSubItem)
1181 else if (lpSubItem->iSubItem > nSubItem)
1193 * Sets item attributes.
1196 * [I] HWND : window handle
1197 * [I] LPLVITEM : new item atttributes
1203 static BOOL LISTVIEW_SetItem(HWND hwnd, LPLVITEMA lpLVItem)
1205 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
1206 BOOL bResult = FALSE;
1208 LISTVIEW_ITEM *lpItem;
1211 LONG lCtrlId = GetWindowLongA(hwnd, GWL_ID);
1213 if (lpLVItem != NULL)
1215 if (lpLVItem->iSubItem == 0)
1217 hdpaSubItems = (HDPA)DPA_GetPtr(infoPtr->hdpaItems, lpLVItem->iItem);
1218 if (hdpaSubItems != NULL)
1220 lpItem = (LISTVIEW_ITEM *)DPA_GetPtr(hdpaSubItems, lpLVItem->iSubItem);
1223 ZeroMemory(&nmlv, sizeof(NMLISTVIEW));
1224 nmlv.hdr.hwndFrom = hwnd;
1225 nmlv.hdr.idFrom = lCtrlId;
1226 nmlv.hdr.code = LVN_ITEMCHANGING;
1227 nmlv.lParam = lpItem->lParam;
1228 uChanged = LISTVIEW_GetItemChanges(lpItem, lpLVItem);
1231 if (uChanged & LVIF_STATE)
1233 nmlv.uNewState = lpLVItem->state & lpLVItem->stateMask;
1234 nmlv.uOldState = lpItem->state & lpLVItem->stateMask;
1237 nmlv.uChanged = uChanged;
1238 nmlv.iItem = lpLVItem->iItem;
1239 nmlv.lParam = lpItem->lParam;
1240 /* send LVN_ITEMCHANGING notification */
1241 ListView_LVNotify(GetParent(hwnd), lCtrlId, &nmlv);
1243 /* copy information */
1244 bResult = LISTVIEW_InitItem(hwnd, lpItem, lpLVItem);
1246 /* send LVN_ITEMCHANGED notification */
1247 nmlv.hdr.code = LVN_ITEMCHANGED;
1248 ListView_LVNotify(GetParent(hwnd), lCtrlId, &nmlv);
1255 InvalidateRect(hwnd, NULL, FALSE);
1266 * Sets subitem attributes.
1269 * [I] HWND : window handle
1270 * [I] LPLVITEM : new subitem atttributes
1276 static BOOL LISTVIEW_SetSubItem(HWND hwnd, LPLVITEMA lpLVItem)
1278 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
1279 BOOL bResult = FALSE;
1281 LISTVIEW_SUBITEM *lpSubItem;
1283 if (lpLVItem != NULL)
1285 if (lpLVItem->iSubItem > 0)
1287 hdpaSubItems = (HDPA)DPA_GetPtr(infoPtr->hdpaItems, lpLVItem->iItem);
1288 if (hdpaSubItems != NULL)
1290 /* set subitem only if column is present */
1291 if (Header_GetItemCount(infoPtr->hwndHeader) > lpLVItem->iSubItem)
1293 lpSubItem = LISTVIEW_GetSubItem(hdpaSubItems, lpLVItem->iSubItem);
1294 if (lpSubItem != NULL)
1296 bResult = LISTVIEW_InitSubItem(hwnd, lpSubItem, lpLVItem);
1300 bResult = LISTVIEW_AddSubItem(hwnd, lpLVItem);
1303 InvalidateRect(hwnd, NULL, FALSE);
1314 * Retrieves the index of the item at coordinate (0, 0) of the client area.
1317 * [I] HWND : window handle
1322 static INT LISTVIEW_GetTopIndex(HWND hwnd)
1324 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *) GetWindowLongA(hwnd, 0);
1325 LONG lStyle = GetWindowLongA(hwnd, GWL_STYLE);
1328 switch (LVS_TYPEMASK & lStyle)
1331 if (lStyle & WS_HSCROLL)
1333 nItem = GetScrollPos(hwnd, SB_HORZ) * infoPtr->nCountPerColumn;
1338 if (lStyle & WS_VSCROLL)
1340 nItem = GetScrollPos(hwnd, SB_VERT);
1350 * Sets scrollbar(s).
1353 * [I] HWND : window handle
1356 * TRUE if scrollbars were added, modified or removed.
1358 static VOID LISTVIEW_SetVScroll(HWND hwnd)
1360 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
1361 LONG lStyle = GetWindowLongA(hwnd, GWL_STYLE);
1365 switch (LVS_TYPEMASK & lStyle)
1368 nMaxRange = GETITEMCOUNT(infoPtr) - infoPtr->nCountPerColumn;
1369 SetScrollRange(hwnd, SB_VERT, 0, nMaxRange, FALSE);
1370 nScrollPos = ListView_GetTopIndex(hwnd);
1371 SetScrollPos(hwnd, SB_VERT, nScrollPos, TRUE);
1379 static VOID LISTVIEW_SetHScroll(HWND hwnd)
1381 /* LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0); */
1382 LONG lStyle = GetWindowLongA(hwnd, GWL_STYLE);
1383 /* INT nScrollPos; */
1384 /* INT nMaxRange; */
1386 switch (LVS_TYPEMASK & lStyle)
1397 static VOID LISTVIEW_SetScroll(HWND hwnd)
1399 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
1400 LONG lStyle = GetWindowLongA(hwnd, GWL_STYLE);
1401 INT nHiddenItemCount;
1406 BOOL bHScroll = FALSE;
1407 BOOL bVScroll = FALSE;
1408 INT nHeaderWidth = 0;
1412 switch (LVS_TYPEMASK & lStyle)
1415 nCountPerPage = infoPtr->nCountPerRow * infoPtr->nCountPerColumn;
1416 if (nCountPerPage < GETITEMCOUNT(infoPtr))
1418 /* add scrollbar if not already present */
1419 if (!(lStyle & WS_HSCROLL))
1421 ShowScrollBar(hwnd, SB_HORZ, TRUE);
1424 /* calculate new scrollbar range */
1425 nHiddenItemCount = GETITEMCOUNT(infoPtr) - nCountPerPage;
1426 if ((nHiddenItemCount % infoPtr->nCountPerColumn) == 0)
1428 nMaxRange = nHiddenItemCount / infoPtr->nCountPerColumn;
1432 nMaxRange = nHiddenItemCount / infoPtr->nCountPerColumn + 1;
1435 SetScrollRange(hwnd, SB_HORZ, 0, nMaxRange, FALSE);
1436 nScrollPos = ListView_GetTopIndex(hwnd) / infoPtr->nCountPerColumn;
1437 SetScrollPos(hwnd, SB_HORZ, nScrollPos, TRUE);
1441 /* remove scrollbar if present */
1442 if (lStyle & WS_HSCROLL)
1444 /* hide scrollbar */
1445 ShowScrollBar(hwnd, SB_HORZ, FALSE);
1451 nItemCount = Header_GetItemCount(infoPtr->hwndHeader);
1452 for (i = 0; i < nItemCount; i++)
1454 if (Header_GetItemRect(infoPtr->hwndHeader, i, &rc) != 0)
1456 nHeaderWidth += (rc.right - rc.left);
1460 if (nHeaderWidth > (infoPtr->rcList.right - infoPtr->rcList.left))
1464 /* add horizontal scrollbar if not present */
1465 if (!(lStyle & WS_HSCROLL))
1467 /* display scrollbar */
1468 ShowScrollBar(hwnd, SB_HORZ, TRUE);
1473 /* remove scrollbar if present */
1474 if (lStyle & WS_HSCROLL)
1476 /* hide scrollbar */
1477 ShowScrollBar(hwnd, SB_HORZ, FALSE);
1481 if (infoPtr->nCountPerColumn < GETITEMCOUNT(infoPtr))
1485 /* add scrollbar if not already present */
1486 if (!(lStyle & WS_VSCROLL))
1488 /* display scrollbar */
1489 ShowScrollBar(hwnd, SB_VERT, TRUE);
1494 /* remove scrollbar if present */
1495 if (lStyle & WS_VSCROLL)
1497 /* hide scrollbar */
1498 ShowScrollBar(hwnd, SB_VERT, FALSE);
1507 /* set range and position */
1508 GetClientRect(hwnd, &rc);
1509 if ((bHScroll == TRUE) || (bVScroll == TRUE))
1511 LISTVIEW_SetSize(hwnd, lStyle, rc.right, rc.bottom);
1512 LISTVIEW_SetViewInfo(hwnd);
1513 if (bHScroll == TRUE)
1515 LISTVIEW_SetHScroll(hwnd);
1518 if (bVScroll == TRUE)
1520 LISTVIEW_SetVScroll(hwnd);
1530 * [I] HDC : device context handle
1531 * [I] LISTVIEW_INFO * : listview information
1532 * [I] LISTVIEW_SUBITEM * : subitem
1533 * [I] RECT * : clipping rectangle
1538 static VOID LISTVIEW_DrawSubItem(HWND hwnd, HDC hdc, INT nItem, LPARAM lParam,
1539 LISTVIEW_SUBITEM *lpSubItem, INT nColumn,
1542 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
1543 CHAR szDispText[DISP_TEXT_SIZE];
1544 LPSTR pszDispText = NULL;
1546 /* set item colors */
1547 SetBkColor(hdc, infoPtr->clrTextBk);
1548 SetTextColor(hdc, infoPtr->clrText);
1550 pszDispText = szDispText;
1551 LISTVIEW_GetSubItemDispInfo(hwnd, nItem, lParam, lpSubItem, nColumn, NULL,
1552 &pszDispText, DISP_TEXT_SIZE);
1554 /* draw text : using arbitrary offset of 10 pixels */
1555 ExtTextOutA(hdc, lprc->left + 10, lprc->top, ETO_OPAQUE|ETO_CLIPPED,
1556 lprc, pszDispText, lstrlenA(pszDispText), NULL);
1564 * [I] HDC : device context handle
1565 * [I] LISTVIEW_INFO * : listview information
1566 * [I] LISTVIEW_ITEM * : item
1567 * [I] RECT * : clipping rectangle
1572 static VOID LISTVIEW_DrawItem(HWND hwnd, HDC hdc, LISTVIEW_ITEM *lpItem,
1573 INT nItem, RECT *lprc)
1575 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
1579 CHAR szDispText[DISP_TEXT_SIZE];
1580 LPSTR pszDispText = NULL;
1583 pszDispText = szDispText;
1584 LISTVIEW_GetItemDispInfo(hwnd, nItem, lpItem, &nImage, &uState, &pszDispText,
1586 if (uState & LVIS_SELECTED)
1590 /* set item colors */
1591 SetBkColor(hdc, GetSysColor(COLOR_HIGHLIGHT));
1592 SetTextColor(hdc, GetSysColor(COLOR_HIGHLIGHTTEXT));
1594 /* set raster mode */
1595 SetROP2(hdc, R2_XORPEN);
1601 /* set item colors */
1602 SetBkColor(hdc, infoPtr->clrTextBk);
1603 SetTextColor(hdc, infoPtr->clrText);
1605 /* set raster mode */
1606 SetROP2(hdc, R2_COPYPEN);
1610 if (infoPtr->himlState != NULL)
1612 /* right shift 12 bits to obtain index in image list */
1613 if (bSelected == TRUE)
1615 ImageList_Draw(infoPtr->himlState, uState >> 12, hdc, lprc->left,
1616 lprc->top, ILD_SELECTED);
1620 ImageList_Draw(infoPtr->himlState, uState >> 12, hdc, lprc->left,
1621 lprc->top, ILD_NORMAL);
1624 lprc->left += infoPtr->iconSize.cx;
1628 if (infoPtr->himlSmall != NULL)
1630 if (bSelected == TRUE)
1632 ImageList_Draw(infoPtr->himlSmall, nImage, hdc, lprc->left,
1633 lprc->top, ILD_SELECTED);
1637 ImageList_Draw(infoPtr->himlSmall, nImage, hdc, lprc->left,
1638 lprc->top, ILD_NORMAL);
1641 lprc->left += infoPtr->iconSize.cx;
1644 nLabelWidth = ListView_GetStringWidthA(hwnd, pszDispText);
1645 if (lprc->left + nLabelWidth < lprc->right)
1647 lprc->right = lprc->left + nLabelWidth;
1651 ExtTextOutA(hdc, lprc->left + 1, lprc->top + 1, ETO_OPAQUE|ETO_CLIPPED,
1652 lprc, pszDispText, lstrlenA(pszDispText), NULL);
1654 if (lpItem->state & LVIS_FOCUSED)
1656 Rectangle(hdc, lprc->left, lprc->top, lprc->right, lprc->bottom);
1662 * Draws listview items when in report display mode.
1665 * [I] HWND : window handle
1666 * [I] HDC : device context handle
1671 static VOID LISTVIEW_RefreshReport(HWND hwnd, HDC hdc)
1673 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd,0);
1674 INT nDrawPosY = infoPtr->rcList.top;
1675 LISTVIEW_ITEM *lpItem;
1676 LISTVIEW_SUBITEM *lpSubItem = NULL;
1683 BOOL bNeedSubItem = TRUE;
1685 nItem = ListView_GetTopIndex(hwnd);
1686 nLast = nItem + infoPtr->nCountPerColumn;
1687 while (nItem <= nLast)
1689 hdpaSubItems = (HDPA)DPA_GetPtr(infoPtr->hdpaItems, nItem);
1690 if (hdpaSubItems != NULL)
1692 lpItem = (LISTVIEW_ITEM *)DPA_GetPtr(hdpaSubItems, 0);
1695 Header_GetItemRect(infoPtr->hwndHeader, 0, &rc);
1697 rc.bottom = rc.top + infoPtr->nItemHeight;
1699 /* draw state icon + icon + text */
1700 LISTVIEW_DrawItem(hwnd, hdc, lpItem, nItem, &rc);
1703 nColumnCount = Header_GetItemCount(infoPtr->hwndHeader);
1704 for (k = 1, j = 1; j < nColumnCount; j++)
1706 Header_GetItemRect(infoPtr->hwndHeader, j, &rc);
1708 rc.bottom = rc.top + infoPtr->nItemHeight;
1710 if (k < hdpaSubItems->nItemCount)
1712 if (bNeedSubItem == TRUE)
1714 lpSubItem = (LISTVIEW_SUBITEM *)DPA_GetPtr(hdpaSubItems, k);
1718 if (lpSubItem != NULL)
1720 if (lpSubItem->iSubItem == j)
1722 LISTVIEW_DrawSubItem(hwnd, hdc, nItem, lpItem->lParam, lpSubItem,
1724 bNeedSubItem = TRUE;
1728 LISTVIEW_DrawSubItem(hwnd, hdc, nItem, lpItem->lParam, NULL, j,
1730 bNeedSubItem = FALSE;
1735 LISTVIEW_DrawSubItem(hwnd, hdc, nItem, lpItem->lParam, NULL, j,
1737 bNeedSubItem = TRUE;
1742 LISTVIEW_DrawSubItem(hwnd, hdc, nItem, lpItem->lParam, NULL, j, &rc);
1747 nDrawPosY += infoPtr->nItemHeight;
1754 * Draws listview items when in list display mode.
1757 * [I] HWND : window handle
1758 * [I] HDC : device context handle
1763 static VOID LISTVIEW_RefreshList(HWND hwnd, HDC hdc)
1765 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
1766 LISTVIEW_ITEM *lpItem;
1771 INT nItem = ListView_GetTopIndex(hwnd);
1773 if (infoPtr->rcList.right > 0)
1775 /* get number of display columns */
1776 if (infoPtr->rcList.right % infoPtr->nColumnWidth == 0)
1778 nColumnCount = infoPtr->rcList.right / infoPtr->nColumnWidth;
1782 nColumnCount = infoPtr->rcList.right / infoPtr->nColumnWidth + 1;
1785 for (i = 0; i < nColumnCount; i++)
1788 while ((nItem < GETITEMCOUNT(infoPtr)) && (j < infoPtr->nCountPerColumn))
1790 hdpaSubItems = (HDPA)DPA_GetPtr(infoPtr->hdpaItems, nItem);
1791 if (hdpaSubItems != NULL)
1793 lpItem = (LISTVIEW_ITEM *)DPA_GetPtr(hdpaSubItems, 0);
1796 rc.top = j * infoPtr->nItemHeight;
1797 rc.left = i * infoPtr->nColumnWidth;
1798 rc.bottom = rc.top + infoPtr->nItemHeight;
1799 rc.right = rc.left + infoPtr->nColumnWidth;
1801 /* draw state icon + icon + text */
1802 LISTVIEW_DrawItem(hwnd, hdc, lpItem, nItem, &rc);
1815 * Draws listview items when in small icon display mode.
1818 * [I] HWND : window handle
1819 * [I] HDC : device context handle
1824 static VOID LISTVIEW_RefreshSmallIcon(HWND hwnd, HDC hdc)
1826 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
1827 LISTVIEW_ITEM *lpItem;
1831 INT nItem = ListView_GetTopIndex(hwnd);
1833 for (i = 0; i < infoPtr->nCountPerColumn; i++)
1836 while ((nItem < GETITEMCOUNT(infoPtr)) && (j < infoPtr->nCountPerRow))
1838 hdpaSubItems = (HDPA)DPA_GetPtr(infoPtr->hdpaItems, nItem);
1839 if (hdpaSubItems != NULL)
1841 lpItem = (LISTVIEW_ITEM *)DPA_GetPtr(hdpaSubItems, 0);
1844 rc.top = i * infoPtr->nItemHeight;
1845 rc.left = j * infoPtr->nColumnWidth;
1846 rc.bottom = rc.top + infoPtr->nItemHeight;
1847 rc.right = rc.left + infoPtr->nColumnWidth;
1849 /* draw state icon + icon + text */
1850 LISTVIEW_DrawItem(hwnd, hdc, lpItem, nItem, &rc);
1862 * Draws listview items when in icon display mode.
1865 * [I] HWND : window handle
1866 * [I] HDC : device context handle
1871 static VOID LISTVIEW_RefreshIcon(HWND hwnd, HDC hdc)
1878 * Draws listview items.
1881 * [I] HWND : window handle
1882 * [I] HDC : device context handle
1887 static VOID LISTVIEW_Refresh(HWND hwnd, HDC hdc)
1889 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
1890 LONG lStyle = GetWindowLongA(hwnd, GWL_STYLE);
1895 hOldFont = SelectObject(hdc, infoPtr->hFont);
1897 /* select the doted pen (for drawing the focus box) */
1898 hPen = CreatePen(PS_DOT, 1, 0);
1899 hOldPen = SelectObject(hdc, hPen);
1901 /* select transparent brush (for drawing the focus box) */
1902 SelectObject(hdc, GetStockObject(NULL_BRUSH));
1904 switch (LVS_TYPEMASK & lStyle)
1907 LISTVIEW_RefreshList(hwnd, hdc);
1910 LISTVIEW_RefreshReport(hwnd, hdc);
1913 LISTVIEW_RefreshSmallIcon(hwnd, hdc);
1916 LISTVIEW_RefreshIcon(hwnd, hdc);
1919 /* unselect objects */
1920 SelectObject(hdc, hOldFont);
1921 SelectObject(hdc, hOldPen);
1930 * Calculates the approximate width and height of a given number of items.
1933 * [I] HWND : window handle
1934 * [I] INT : number of items
1939 * Returns a DWORD. The width in the low word and the height in high word.
1941 static LRESULT LISTVIEW_ApproximateViewRect(HWND hwnd, INT nItemCount,
1942 WORD wWidth, WORD wHeight)
1944 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
1945 LONG lStyle = GetWindowLongA(hwnd, GWL_STYLE);
1946 INT nItemCountPerColumn = 1;
1947 INT nColumnCount = 0;
1948 DWORD dwViewRect = 0;
1950 if (nItemCount == -1)
1951 nItemCount = GETITEMCOUNT(infoPtr);
1953 if (lStyle & LVS_LIST)
1955 if (wHeight == 0xFFFF)
1957 /* use current height */
1958 wHeight = infoPtr->rcList.bottom;
1961 if (wHeight < infoPtr->nItemHeight)
1963 wHeight = infoPtr->nItemHeight;
1968 if (infoPtr->nItemHeight > 0)
1970 nItemCountPerColumn = wHeight / infoPtr->nItemHeight;
1971 if (nItemCountPerColumn == 0)
1972 nItemCountPerColumn = 1;
1974 if (nItemCount % nItemCountPerColumn != 0)
1975 nColumnCount = nItemCount / nItemCountPerColumn;
1977 nColumnCount = nItemCount / nItemCountPerColumn + 1;
1981 /* Microsoft padding magic */
1982 wHeight = nItemCountPerColumn * infoPtr->nItemHeight + 2;
1983 wWidth = nColumnCount * infoPtr->nColumnWidth + 2;
1985 dwViewRect = MAKELONG(wWidth, wHeight);
1987 else if (lStyle & LVS_REPORT)
1991 else if (lStyle & LVS_SMALLICON)
1995 else if (lStyle & LVS_ICON)
2005 * Arranges listview items in icon display mode.
2008 * [I] HWND : window handle
2009 * [I] INT : alignment code
2015 static LRESULT LISTVIEW_Arrange(HWND hwnd, INT nAlignCode)
2017 LONG lStyle = GetWindowLongA(hwnd, GWL_STYLE);
2018 BOOL bResult = FALSE;
2020 if (((LVS_TYPEMASK & lStyle) == LVS_ICON) ||
2021 ((LVS_TYPEMASK & lStyle) == LVS_SMALLICON))
2034 case LVA_SNAPTOGRID:
2042 /* << LISTVIEW_CreateDragImage >> */
2046 * Removes all listview items and subitems.
2049 * [I] HWND : window handle
2055 static LRESULT LISTVIEW_DeleteAllItems(HWND hwnd)
2057 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
2058 LONG lCtrlId = GetWindowLongA(hwnd, GWL_ID);
2059 LISTVIEW_ITEM *lpItem;
2060 LISTVIEW_SUBITEM *lpSubItem;
2063 BOOL bResult = FALSE;
2068 if (GETITEMCOUNT(infoPtr) > 0)
2070 /* initialize memory */
2071 ZeroMemory(&nmlv, sizeof(NMLISTVIEW));
2073 /* send LVN_DELETEALLITEMS notification */
2074 nmlv.hdr.hwndFrom = hwnd;
2075 nmlv.hdr.idFrom = lCtrlId;
2076 nmlv.hdr.code = LVN_DELETEALLITEMS;
2079 /* verify if subsequent LVN_DELETEITEM notifications should be
2081 bSuppress = ListView_LVNotify(GetParent(hwnd), lCtrlId, &nmlv);
2083 for (i = 0; i < GETITEMCOUNT(infoPtr); i++)
2085 hdpaSubItems = (HDPA)DPA_GetPtr(infoPtr->hdpaItems, i);
2086 if (hdpaSubItems != NULL)
2088 for (j = 1; j < hdpaSubItems->nItemCount; j++)
2090 lpSubItem = (LISTVIEW_SUBITEM *)DPA_GetPtr(hdpaSubItems, j);
2091 if (lpSubItem != NULL)
2093 /* free subitem string */
2094 if ((lpSubItem->pszText != NULL) &&
2095 (lpSubItem->pszText != LPSTR_TEXTCALLBACKA))
2097 COMCTL32_Free(lpSubItem->pszText);
2101 COMCTL32_Free(lpSubItem);
2105 lpItem = (LISTVIEW_ITEM *)DPA_GetPtr(hdpaSubItems, 0);
2108 if (bSuppress == FALSE)
2110 /* send LVN_DELETEITEM notification */
2111 nmlv.hdr.code = LVN_DELETEITEM;
2113 nmlv.lParam = lpItem->lParam;
2114 ListView_LVNotify(GetParent(hwnd), lCtrlId, &nmlv);
2117 /* free item string */
2118 if ((lpItem->pszText != NULL) &&
2119 (lpItem->pszText != LPSTR_TEXTCALLBACKA))
2121 COMCTL32_Free(lpItem->pszText);
2125 COMCTL32_Free(lpItem);
2128 DPA_Destroy(hdpaSubItems);
2132 /* reinitialize listview memory */
2133 bResult = DPA_DeleteAllPtrs(infoPtr->hdpaItems);
2135 /* reset scroll parameters */
2136 LISTVIEW_SetScroll(hwnd);
2138 /* invalidate client area (optimization needed) */
2139 InvalidateRect(hwnd, NULL, FALSE);
2147 * Removes a column from the listview control.
2150 * [I] HWND : window handle
2151 * [I] INT : column index
2157 static LRESULT LISTVIEW_DeleteColumn(HWND hwnd, INT nColumn)
2159 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
2160 BOOL bResult = FALSE;
2162 if (Header_DeleteItem(infoPtr->hwndHeader, nColumn) == TRUE)
2164 bResult = LISTVIEW_RemoveColumn(infoPtr->hdpaItems, nColumn);
2167 /* reset scroll parameters */
2168 LISTVIEW_SetScroll(hwnd);
2170 /* refresh client area */
2171 InvalidateRect(hwnd, NULL, FALSE);
2178 * Removes an item from the listview control.
2181 * [I] HWND : window handle
2182 * [I] INT : item index
2188 static LRESULT LISTVIEW_DeleteItem(HWND hwnd, INT nItem)
2190 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
2191 LONG lCtrlId = GetWindowLongA(hwnd, GWL_ID);
2193 BOOL bResult = FALSE;
2195 LISTVIEW_ITEM *lpItem;
2196 LISTVIEW_SUBITEM *lpSubItem;
2199 if ((nItem >= 0) && (nItem < GETITEMCOUNT(infoPtr)))
2201 /* initialize memory */
2202 ZeroMemory(&nmlv, sizeof(NMLISTVIEW));
2204 hdpaSubItems = (HDPA)DPA_DeletePtr(infoPtr->hdpaItems, nItem);
2205 if (hdpaSubItems != NULL)
2207 for (i = 1; i < hdpaSubItems->nItemCount; i++)
2209 lpSubItem = (LISTVIEW_SUBITEM *)DPA_GetPtr(hdpaSubItems, i);
2210 if (lpSubItem != NULL)
2212 /* free item string */
2213 if ((lpSubItem->pszText != NULL) &&
2214 (lpSubItem->pszText != LPSTR_TEXTCALLBACKA))
2216 COMCTL32_Free(lpSubItem->pszText);
2220 COMCTL32_Free(lpSubItem);
2224 lpItem = (LISTVIEW_ITEM *)DPA_GetPtr(hdpaSubItems, 0);
2227 /* send LVN_DELETEITEM notification */
2228 nmlv.hdr.hwndFrom = hwnd;
2229 nmlv.hdr.idFrom = lCtrlId;
2230 nmlv.hdr.code = LVN_DELETEITEM;
2232 nmlv.lParam = lpItem->lParam;
2233 SendMessageA(GetParent(hwnd), WM_NOTIFY, (WPARAM)lCtrlId,
2236 /* free item string */
2237 if ((lpItem->pszText != NULL) &&
2238 (lpItem->pszText != LPSTR_TEXTCALLBACKA))
2240 COMCTL32_Free(lpItem->pszText);
2244 COMCTL32_Free(lpItem);
2247 bResult = DPA_Destroy(hdpaSubItems);
2250 /* refresh client area */
2251 InvalidateRect(hwnd, NULL, FALSE);
2257 /* << LISTVIEW_EditLabel >> */
2261 * Ensures the specified item is visible, scrolling into view if necessary.
2264 * [I] HWND : window handle
2265 * [I] INT : item index
2266 * [I] BOOL : partially or entirely visible
2272 static BOOL LISTVIEW_EnsureVisible(HWND hwnd, INT nItem, BOOL bPartial)
2274 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
2275 LONG lStyle = GetWindowLongA(hwnd, GWL_STYLE);
2279 BOOL bResult = TRUE;
2281 switch (LVS_TYPEMASK & lStyle)
2284 if (lStyle & WS_HSCROLL)
2286 nFirst = ListView_GetTopIndex(hwnd);
2288 /* calculate last fully visible item index */
2289 nLast = infoPtr->nCountPerColumn * infoPtr->nCountPerRow + nFirst - 1;
2293 /* calculate new scroll position based on item index */
2294 if (((nItem - nLast) % infoPtr->nCountPerColumn) == 0)
2296 nScrollPos = (nItem - nLast) / infoPtr->nCountPerColumn;
2300 nScrollPos = (nItem - nLast) / infoPtr->nCountPerColumn + 1;
2303 bResult = ListView_Scroll(hwnd, nScrollPos, 0);
2305 else if (nItem < nFirst)
2307 /* calculate new scroll position based on item index */
2308 if (((nItem - nFirst) % infoPtr->nCountPerColumn) == 0)
2310 nScrollPos = (nItem - nFirst) / infoPtr->nCountPerColumn;
2314 nScrollPos = (nItem - nFirst) / infoPtr->nCountPerColumn -1;
2317 bResult = ListView_Scroll(hwnd, nScrollPos, 0);
2323 if (lStyle & WS_VSCROLL)
2325 nFirst = ListView_GetTopIndex(hwnd);
2327 /* calculate last fully visible item index */
2328 nLast = infoPtr->nCountPerColumn + nFirst - 1;
2331 nScrollPos = nItem - nLast;
2332 bResult = ListView_Scroll(hwnd, 0, nScrollPos);
2334 else if (nItem < nFirst)
2336 nScrollPos = nItem - nFirst;
2337 bResult = ListView_Scroll(hwnd, 0, nScrollPos);
2355 * Searches for an item with specific characteristics.
2358 * [I] HWND : window handle
2359 * [I] INT : base item index
2360 * [I] LPLVFINDINFO : item information to look for
2363 * SUCCESS : index of item
2366 static LRESULT LISTVIEW_FindItem(HWND hwnd, INT nStart,
2367 LPLVFINDINFO lpFindInfo)
2369 /* LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0); */
2370 /* LISTVIEW_ITEM *lpItem; */
2372 /* INT nEnd = GETITEMCOUNT(infoPtr); */
2373 /* BOOL bWrap = FALSE; */
2374 /* if (nStart == -1) */
2378 /* if (lpFindInfo->flags & LVFI_PARAM) */
2380 /* for (nItem = nStart; nItem < nEnd; nItem++) */
2382 /* get item pointer */
2383 /* lpItem = (LISTVIEW_ITEM *)DPA_GetPtr(infoPtr->hdpaItems, nItem); */
2384 /* if (lpItem != NULL) */
2386 /* if (lpFindInfo->lParam == lpItem->lParam) */
2393 /* if (lpFindInfo->flags & LVFI_PARTIAL) */
2395 /* for (nItem = nStart; nItem < nEnd; nItem++) */
2397 /* get item pointer */
2398 /* lpItem = (LISTVIEW_ITEM *)DPA_GetPtr(infoPtr->hdpaItems, nItem); */
2401 /* if (strncmp(lpItem->pszText, lpFindInfo->psz, strlen(lpFindInfo->psz)) */
2408 /* if (lpFindInfo->flags & LVFI_STRING) */
2410 /* for (nItem = nStart; nItem < nEnd; nItem++) */
2412 /* get item pointer */
2413 /* lpItem = (LISTVIEW_ITEM *)DPA_GetPtr(infoPtr->hdpaItems, nItem); */
2414 /* if (lpItem != NULL) */
2416 /* if (strcmp(lpItem->pszText, lpFindInfo->psz) == 0) */
2422 /* if ((lpFindInfo->flags & LVFI_WRAP) && nStart) */
2424 /* nEnd = nStart; */
2429 /* bWrap = FALSE; */
2436 * Retrieves the background color of the listview control.
2439 * [I] HWND : window handle
2442 * COLORREF associated with the background.
2444 static LRESULT LISTVIEW_GetBkColor(HWND hwnd)
2446 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
2448 return infoPtr->clrBk;
2453 * Retrieves the background image of the listview control.
2456 * [I] HWND : window handle
2457 * [O] LPLVMKBIMAGE : background image attributes
2463 /* static LRESULT LISTVIEW_GetBkImage(HWND hwnd, LPLVBKIMAGE lpBkImage) */
2470 * Retrieves the callback mask.
2473 * [I] HWND : window handle
2478 static UINT LISTVIEW_GetCallbackMask(HWND hwnd)
2480 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
2482 return infoPtr->uCallbackMask;
2487 * Retrieves column attributes.
2490 * [I] HWND : window handle
2491 * [I] INT : column index
2492 * [IO] LPLVCOLUMNA : column information
2498 static LRESULT LISTVIEW_GetColumnA(HWND hwnd, INT nItem,
2499 LPLVCOLUMNA lpColumn)
2501 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
2503 BOOL bResult = FALSE;
2505 if (lpColumn != NULL)
2507 /* initialize memory */
2508 ZeroMemory(&hdi, sizeof(HDITEMA));
2510 if (lpColumn->mask & LVCF_FMT)
2512 hdi.mask |= HDI_FORMAT;
2515 if (lpColumn->mask & LVCF_WIDTH)
2517 hdi.mask |= HDI_WIDTH;
2520 if (lpColumn->mask & LVCF_TEXT)
2522 hdi.mask |= (HDI_TEXT | HDI_FORMAT);
2525 if (lpColumn->mask & LVCF_IMAGE)
2527 hdi.mask |= HDI_IMAGE;
2530 if (lpColumn->mask & LVCF_ORDER)
2532 hdi.mask |= HDI_ORDER;
2535 bResult = Header_GetItemA(infoPtr->hwndHeader, nItem, &hdi);
2536 if (bResult == TRUE)
2538 if (lpColumn->mask & LVCF_FMT)
2542 if (hdi.fmt & HDF_LEFT)
2544 lpColumn->fmt |= LVCFMT_LEFT;
2546 else if (hdi.fmt & HDF_RIGHT)
2548 lpColumn->fmt |= LVCFMT_RIGHT;
2550 else if (hdi.fmt & HDF_CENTER)
2552 lpColumn->fmt |= LVCFMT_CENTER;
2555 if (hdi.fmt & HDF_IMAGE)
2557 lpColumn->fmt |= LVCFMT_COL_HAS_IMAGES;
2561 if (lpColumn->mask & LVCF_WIDTH)
2563 lpColumn->cx = hdi.cxy;
2566 if ((lpColumn->mask & LVCF_TEXT) && (lpColumn->pszText) && (hdi.pszText))
2568 lstrcpynA (lpColumn->pszText, hdi.pszText, lpColumn->cchTextMax);
2571 if (lpColumn->mask & LVCF_IMAGE)
2573 lpColumn->iImage = hdi.iImage;
2576 if (lpColumn->mask & LVCF_ORDER)
2578 lpColumn->iOrder = hdi.iOrder;
2586 /* << LISTVIEW_GetColumnW >> */
2587 /* << LISTVIEW_GetColumnOrderArray >> */
2591 * Retrieves the column width.
2594 * [I] HWND : window handle
2595 * [I] int : column index
2598 * SUCCESS : column width
2601 static LRESULT LISTVIEW_GetColumnWidth(HWND hwnd, INT nColumn)
2603 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
2604 LONG lStyle = GetWindowLongA(hwnd, GWL_STYLE);
2606 INT nColumnWidth = 0;
2608 if ((LVS_TYPEMASK & lStyle) == LVS_LIST)
2610 nColumnWidth = infoPtr->nColumnWidth;
2612 else if ((LVS_TYPEMASK & lStyle) == LVS_REPORT)
2614 /* get column width from header */
2615 ZeroMemory(&hdi, sizeof(HDITEMA));
2616 hdi.mask = HDI_WIDTH;
2617 if (Header_GetItemA(infoPtr->hwndHeader, nColumn, &hdi) == TRUE)
2619 nColumnWidth = hdi.cxy;
2623 return nColumnWidth;
2628 * In list or report display mode, retrieves the number of items that can fit
2629 * vertically in the visible area. In icon or small icon display mode,
2630 * retrieves the total number of visible items.
2633 * [I] HWND : window handle
2636 * Number of fully visible items.
2638 static LRESULT LISTVIEW_GetCountPerPage(HWND hwnd)
2640 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
2641 LONG lStyle = GetWindowLongA(hwnd, GWL_STYLE);
2644 switch (LVS_TYPEMASK & lStyle)
2647 if (infoPtr->rcList.right / infoPtr->nColumnWidth)
2649 nItemCount = infoPtr->nCountPerRow * infoPtr->nCountPerColumn;
2654 nItemCount = infoPtr->nCountPerColumn;
2658 nItemCount = GETITEMCOUNT(infoPtr);
2664 /* << LISTVIEW_GetEditControl >> */
2665 /* << LISTVIEW_GetExtendedListViewStyle >> */
2669 * Retrieves a header handle.
2672 * [I] HWND : window handle
2677 static LRESULT LISTVIEW_GetHeader(HWND hwnd)
2679 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
2681 return infoPtr->hwndHeader;
2684 /* << LISTVIEW_GetHotCursor >> */
2685 /* << LISTVIEW_GetHotItem >> */
2686 /* << LISTVIEW_GetHoverTime >> */
2690 * Retrieves an image list handle.
2693 * [I] HWND : window handle
2694 * [I] INT : image list identifier
2697 * SUCCESS : image list handle
2700 static LRESULT LISTVIEW_GetImageList(HWND hwnd, INT nImageList)
2702 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
2703 HIMAGELIST himl = NULL;
2708 himl = infoPtr->himlNormal;
2711 himl = infoPtr->himlSmall;
2714 himl = infoPtr->himlState;
2718 return (LRESULT)himl;
2721 /* << LISTVIEW_GetISearchString >> */
2725 * Retrieves item attributes.
2728 * [I] HWND : window handle
2729 * [IO] LPLVITEMA : item info
2735 static LRESULT LISTVIEW_GetItemA(HWND hwnd, LPLVITEMA lpLVItem)
2737 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
2738 LISTVIEW_ITEM *lpItem;
2739 LISTVIEW_SUBITEM *lpSubItem;
2741 BOOL bResult = FALSE;
2743 if (lpLVItem != NULL)
2745 if ((lpLVItem->iItem >= 0) && (lpLVItem->iItem < GETITEMCOUNT(infoPtr)))
2747 hdpaSubItems = (HDPA)DPA_GetPtr(infoPtr->hdpaItems, lpLVItem->iItem);
2748 if (hdpaSubItems != NULL)
2750 if (lpLVItem->iSubItem == 0)
2752 lpItem = (LISTVIEW_ITEM *)DPA_GetPtr(hdpaSubItems, 0);
2757 /* retrieve valid data */
2758 if (lpLVItem->mask & LVIF_STATE)
2760 lpLVItem->state = lpItem->state & lpLVItem->stateMask;
2763 if (lpLVItem->mask & LVIF_TEXT)
2765 if (lpItem->pszText == LPSTR_TEXTCALLBACKA)
2767 lpLVItem->pszText = LPSTR_TEXTCALLBACKA;
2771 bResult = Str_GetPtrA(lpItem->pszText, lpLVItem->pszText,
2772 lpLVItem->cchTextMax);
2776 if (lpLVItem->mask & LVIF_IMAGE)
2778 lpLVItem->iImage = lpItem->iImage;
2781 if (lpLVItem->mask & LVIF_PARAM)
2783 lpLVItem->lParam = lpItem->lParam;
2786 if (lpLVItem->mask & LVIF_INDENT)
2788 lpLVItem->iIndent = lpItem->iIndent;
2794 lpSubItem = (LISTVIEW_SUBITEM *)DPA_GetPtr(hdpaSubItems,
2795 lpLVItem->iSubItem);
2796 if (lpSubItem != NULL)
2800 if (lpLVItem->mask & LVIF_TEXT)
2802 if (lpSubItem->pszText == LPSTR_TEXTCALLBACKA)
2804 lpLVItem->pszText = LPSTR_TEXTCALLBACKA;
2808 bResult = Str_GetPtrA(lpSubItem->pszText, lpLVItem->pszText,
2809 lpLVItem->cchTextMax);
2813 if (lpLVItem->mask & LVIF_IMAGE)
2815 lpLVItem->iImage = lpSubItem->iImage;
2826 /* << LISTVIEW_GetItemW >> */
2827 /* << LISTVIEW_GetHotCursor >> */
2828 /* << LISTVIEW_GetHotItem >> */
2829 /* << LISTVIEW_GetHoverTime >> */
2833 * Retrieves the number of items in the listview control.
2836 * [I] HWND : window handle
2841 static LRESULT LISTVIEW_GetItemCount(HWND hwnd)
2843 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
2845 return GETITEMCOUNT(infoPtr);
2850 * Retrieves the position (upper-left) of the listview control item.
2853 * [I] HWND : window handle
2854 * [I] INT : item index
2855 * [O] LPPOINT : coordinate information
2861 static LRESULT LISTVIEW_GetItemPosition(HWND hwnd, INT nItem,
2864 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
2865 LONG lStyle = GetWindowLongA(hwnd, GWL_STYLE);
2868 BOOL bResult = FALSE;
2872 if ((nItem >= 0) && (nItem < GETITEMCOUNT(infoPtr)) && (lppt != NULL))
2874 switch (LVS_TYPEMASK & lStyle)
2877 nFirst = ListView_GetTopIndex(hwnd);
2878 nLast = infoPtr->nCountPerColumn * infoPtr->nCountPerRow + nFirst - 1;
2880 if ((nItem >= nFirst) || (nItem <= nLast))
2885 nColumn = nItem / infoPtr->nCountPerColumn;
2888 nRow = nItem % infoPtr->nCountPerColumn;
2890 /* X coordinate of the column */
2891 lppt->x = nColumn * infoPtr->nColumnWidth + infoPtr->rcList.left;
2893 /* Y coordinate of the item */
2894 lppt->y = nRow * infoPtr->nItemHeight + infoPtr->rcList.top;
2901 nFirst = ListView_GetTopIndex(hwnd);
2902 nLast = infoPtr->nCountPerColumn * infoPtr->nCountPerRow + nFirst - 1;
2905 nColumn = nItem / infoPtr->nCountPerColumn;
2908 nRow = nItem % infoPtr->nCountPerColumn;
2910 if ((nItem >= nFirst) || (nItem <= nLast))
2915 nColumn = nItem / infoPtr->nCountPerColumn;
2918 nRow = nItem % infoPtr->nCountPerColumn;
2920 /* X coordinate of the column */
2921 lppt->x = infoPtr->rcList.left;
2923 /* Y coordinate of the item */
2924 lppt->y = nRow * infoPtr->nItemHeight + infoPtr->rcList.top;
2939 * Retrieves the bounding rectangle for a listview control item.
2942 * [I] HWND : window handle
2943 * [I] INT : item index
2944 * [IO] LPRECT : bounding rectangle coordinates
2950 static LRESULT LISTVIEW_GetItemRect(HWND hwnd, INT nItem, LPRECT lprc)
2952 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
2953 LONG lStyle = GetWindowLongA(hwnd, GWL_STYLE);
2954 LISTVIEW_ITEM *lpItem;
2956 INT nLabelWidth = 0;
2957 INT nStateWidth = 0;
2959 BOOL bResult = FALSE;
2960 CHAR szDispText[DISP_TEXT_SIZE];
2965 pszDispText = szDispText;
2967 if ((nItem >= 0) && (nItem < GETITEMCOUNT(infoPtr)) && (lprc != NULL))
2969 hdpaSubItems = (HDPA)DPA_GetPtr(infoPtr->hdpaItems, nItem);
2970 if (hdpaSubItems != NULL)
2972 lpItem = (LISTVIEW_ITEM *)DPA_GetPtr(hdpaSubItems, 0);
2975 if ((LVS_TYPEMASK & lStyle) == LVS_ICON)
2981 if (ListView_GetItemPosition(hwnd, nItem, &pt) == TRUE)
2983 /* get width of label in pixels */
2984 LISTVIEW_GetItemDispInfo(hwnd, nItem, lpItem, NULL, NULL,
2985 &pszDispText, DISP_TEXT_SIZE);
2986 nLabelWidth = ListView_GetStringWidthA(hwnd, pszDispText);
2989 if (infoPtr->himlState != NULL)
2991 nStateWidth = infoPtr->iconSize.cx;
2994 if (infoPtr->himlSmall == NULL)
2996 nIconWidth = infoPtr->iconSize.cx;
3004 lprc->right = lprc->left + nStateWidth + nIconWidth + nLabelWidth;
3005 lprc->bottom = lprc->top + infoPtr->nItemHeight;
3009 lprc->left = pt.x + nStateWidth;
3011 lprc->right = lprc->left + nIconWidth;
3012 lprc->bottom = lprc->top + infoPtr->nItemHeight;
3016 lprc->left = pt.x + nIconWidth + nStateWidth;
3018 lprc->right = lprc->left + nLabelWidth;
3019 lprc->bottom = infoPtr->nItemHeight;
3022 case LVIR_SELECTBOUNDS:
3023 lprc->left = pt.x + nStateWidth;
3025 lprc->right = lprc->left + nIconWidth + nLabelWidth;
3026 lprc->bottom = lprc->top + infoPtr->nItemHeight;
3039 * Retrieves the spacing between listview control items.
3042 * [I] HWND : window handle
3043 * [I] BOOL : flag for small or large icon
3046 * Horizontal + vertical spacing
3048 static LRESULT LISTVIEW_GetItemSpacing(HWND hwnd, BOOL bSmall)
3050 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
3055 lResult = MAKELONG(infoPtr->largeIconSpacing.cx,
3056 infoPtr->largeIconSpacing.cy);
3060 lResult = MAKELONG(infoPtr->smallIconSpacing.cx,
3061 infoPtr->smallIconSpacing.cy);
3069 * Retrieves the state of a listview control item.
3072 * [I] HWND : window handle
3073 * [I] INT : item index
3074 * [I] UINT : state mask
3077 * State specified by the mask.
3079 static LRESULT LISTVIEW_GetItemState(HWND hwnd, INT nItem, UINT uMask)
3081 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
3085 if ((nItem >= 0) && (nItem < GETITEMCOUNT(infoPtr)))
3087 ZeroMemory(&lvItem, sizeof(LVITEMA));
3088 lvItem.iItem = nItem;
3089 lvItem.stateMask = uMask;
3090 lvItem.mask = LVIF_STATE;
3091 if (ListView_GetItemA(hwnd, &lvItem) == TRUE)
3093 uState = lvItem.state;
3102 * Retrieves the text of a listview control item or subitem.
3105 * [I] HWND : window handle
3106 * [I] INT : item index
3107 * [IO] LPLVITEMA : item information
3112 static LRESULT LISTVIEW_GetItemTextA(HWND hwnd, INT nItem,
3115 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
3116 LISTVIEW_ITEM *lpItem;
3117 LISTVIEW_SUBITEM *lpSubItem;
3121 if (lpLVItem != NULL)
3123 if ((nItem >= 0) && (nItem < GETITEMCOUNT(infoPtr)))
3125 hdpaSubItems = (HDPA)DPA_GetPtr(infoPtr->hdpaItems, lpLVItem->iItem);
3126 if (hdpaSubItems != NULL)
3128 if (lpLVItem->iSubItem == 0)
3130 lpItem = (LISTVIEW_ITEM *)DPA_GetPtr(hdpaSubItems, 0);
3133 if (lpLVItem->mask & LVIF_TEXT)
3135 if (lpItem->pszText == LPSTR_TEXTCALLBACKA)
3137 lpLVItem->pszText = LPSTR_TEXTCALLBACKA;
3141 nLength = Str_GetPtrA(lpItem->pszText, lpLVItem->pszText,
3142 lpLVItem->cchTextMax);
3149 lpSubItem = (LISTVIEW_SUBITEM *)DPA_GetPtr(hdpaSubItems,
3150 lpLVItem->iSubItem);
3151 if (lpSubItem != NULL)
3153 if (lpLVItem->mask & LVIF_TEXT)
3155 if (lpSubItem->pszText == LPSTR_TEXTCALLBACKA)
3157 lpLVItem->pszText = LPSTR_TEXTCALLBACKA;
3161 nLength = Str_GetPtrA(lpSubItem->pszText, lpLVItem->pszText,
3162 lpLVItem->cchTextMax);
3176 * Searches for an item based on properties + relationships.
3179 * [I] HWND : window handle
3180 * [I] INT : item index
3181 * [I] UINT : relationship flag
3184 * SUCCESS : item index
3187 static LRESULT LISTVIEW_GetNextItem(HWND hwnd, INT nItem, UINT uFlags)
3189 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
3194 /* start at begin */
3199 /* exclude specified item */
3203 if ((nItem >= 0) && (nItem < GETITEMCOUNT(infoPtr)))
3211 /* << LISTVIEW_GetNumberOfWorkAreas >> */
3215 * Retrieves the current origin when in icon or small icon display mode.
3218 * [I] HWND : window handle
3219 * [O] LPPOINT : coordinate information
3225 static LRESULT LISTVIEW_GetOrigin(HWND hwnd, LPPOINT lpOrigin)
3227 LONG lStyle = GetWindowLongA(hwnd, GWL_ID);
3228 BOOL bResult = FALSE;
3230 if ((lStyle & LVS_TYPEMASK) == LVS_SMALLICON)
3236 else if ((lStyle & LVS_TYPEMASK) == LVS_ICON)
3248 * Retrieves the number of items that are marked as selected.
3251 * [I] HWND : window handle
3254 * Number of items selected.
3256 static LRESULT LISTVIEW_GetSelectedCount(HWND hwnd)
3258 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
3259 INT nSelectedCount = 0;
3262 for (i = 0; i < GETITEMCOUNT(infoPtr); i++)
3264 if (ListView_GetItemState(hwnd, i, LVIS_SELECTED) & LVIS_SELECTED)
3270 return nSelectedCount;
3275 * Retrieves item index that marks the start of a multiple selection.
3278 * [I] HWND : window handle
3281 * Index number or -1 if there is no selection mark.
3283 static LRESULT LISTVIEW_GetSelectionMark(HWND hwnd)
3285 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
3287 return infoPtr->nSelectionMark;
3292 * Retrieves the width of a string.
3295 * [I] HWND : window handle
3298 * SUCCESS : string width (in pixels)
3301 static LRESULT LISTVIEW_GetStringWidthA(HWND hwnd, LPCSTR lpsz)
3303 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
3304 HFONT hFont, hOldFont;
3309 ZeroMemory(&textSize, sizeof(SIZE));
3312 hFont = infoPtr->hFont ? infoPtr->hFont : infoPtr->hDefaultFont;
3314 hOldFont = SelectObject(hdc, hFont);
3315 GetTextExtentPointA(hdc, lpsz, lstrlenA(lpsz), &textSize);
3316 SelectObject(hdc, hOldFont);
3317 ReleaseDC(hwnd, hdc);
3325 * Retrieves the text backgound color.
3328 * [I] HWND : window handle
3331 * COLORREF associated with the the background.
3333 static LRESULT LISTVIEW_GetTextBkColor(HWND hwnd)
3335 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO*)GetWindowLongA(hwnd, 0);
3337 return infoPtr->clrTextBk;
3342 * Retrieves the text color.
3345 * [I] HWND : window handle
3348 * COLORREF associated with the text.
3350 static LRESULT LISTVIEW_GetTextColor(HWND hwnd)
3352 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO*)GetWindowLongA(hwnd, 0);
3354 return infoPtr->clrText;
3359 * Retrieves the bounding rectangle of all the items.
3362 * [I] HWND : window handle
3363 * [O] LPRECT : bounding rectangle
3369 static LRESULT LISTVIEW_GetViewRect(HWND hwnd, LPRECT lprc)
3371 /* LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0); */
3372 LONG lStyle = GetWindowLongA(hwnd, GWL_STYLE);
3373 BOOL bResult = FALSE;
3377 if (((lStyle & LVS_TYPEMASK) == LVS_ICON) ||
3378 ((lStyle & LVS_TYPEMASK) == LVS_SMALLICON))
3389 * Determines which section of the item was selected (if any).
3392 * [I] HWND : window handle
3393 * [I] INT : item index
3394 * [IO] LPLVHITTESTINFO : hit test information
3397 * SUCCESS : item index
3400 static INT LISTVIEW_HitTestItem(HWND hwnd, INT nItem,
3401 LPLVHITTESTINFO lpHitTestInfo)
3403 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
3404 LONG lStyle = GetWindowLongA(hwnd, GWL_STYLE);
3406 LISTVIEW_ITEM *lpItem;
3410 CHAR szDispText[DISP_TEXT_SIZE];
3414 pszDispText = szDispText;
3416 if ((LVS_TYPEMASK & lStyle) == LVS_LIST)
3418 /* calculate offset from start of item (in pixels) */
3419 nOffset = lpHitTestInfo->pt.x % infoPtr->nColumnWidth;
3423 nOffset = lpHitTestInfo->pt.x;
3426 /* verify existance of item */
3427 if (nItem < GETITEMCOUNT(infoPtr))
3430 hdpaSubItems = (HDPA)DPA_GetPtr(infoPtr->hdpaItems, nItem);
3431 if (hdpaSubItems != NULL)
3433 lpItem = (LISTVIEW_ITEM *)DPA_GetPtr(hdpaSubItems, 0);
3436 if (infoPtr->himlState != NULL)
3438 nPosX += infoPtr->iconSize.cx;
3439 if (nOffset <= nPosX)
3441 lpHitTestInfo->flags = LVHT_ONITEMSTATEICON | LVHT_ONITEM;
3442 lpHitTestInfo->iItem = nItem;
3443 lpHitTestInfo->iSubItem = 0;
3448 if (infoPtr->himlSmall != NULL)
3450 nPosX += infoPtr->iconSize.cx;
3451 if (nOffset <= nPosX)
3453 lpHitTestInfo->flags = LVHT_ONITEMICON | LVHT_ONITEM;
3454 lpHitTestInfo->iItem = nItem;
3455 lpHitTestInfo->iSubItem = 0;
3460 /* get width of label in pixels */
3461 LISTVIEW_GetItemDispInfo(hwnd, nItem, lpItem, NULL, NULL,
3462 &pszDispText, DISP_TEXT_SIZE);
3463 nLabelWidth = ListView_GetStringWidthA(hwnd, pszDispText);
3464 nLabelWidth += nPosX;
3466 if (nOffset <= nLabelWidth)
3468 lpHitTestInfo->flags = LVHT_ONITEMLABEL | LVHT_ONITEM;
3469 lpHitTestInfo->iItem = nItem;
3470 lpHitTestInfo->iSubItem = 0;
3477 /* hit is not on item */
3478 lpHitTestInfo->flags = LVHT_NOWHERE;
3485 * Determines wich listview item is located at the specified position.
3488 * [I] HWND : window handle
3489 * [IO} LPLVHITTESTINFO : hit test information
3492 * SUCCESS : item index
3495 static LRESULT LISTVIEW_HitTest(HWND hwnd, LPLVHITTESTINFO lpHitTestInfo)
3497 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
3498 LONG lStyle = GetWindowLongA(hwnd, GWL_STYLE);
3504 lpHitTestInfo->flags = 0;
3505 if (infoPtr->rcList.left > lpHitTestInfo->pt.x)
3507 lpHitTestInfo->flags = LVHT_TOLEFT;
3509 else if (infoPtr->rcList.right < lpHitTestInfo->pt.x)
3511 lpHitTestInfo->flags = LVHT_TORIGHT;
3514 if (infoPtr->rcList.top > lpHitTestInfo->pt.y)
3516 lpHitTestInfo->flags |= LVHT_ABOVE;
3518 else if (infoPtr->rcList.bottom < lpHitTestInfo->pt.y)
3520 lpHitTestInfo->flags |= LVHT_BELOW;
3523 if (lpHitTestInfo->flags == 0)
3525 switch (LVS_TYPEMASK & lStyle)
3528 /* get current column */
3529 nColumn = lpHitTestInfo->pt.x / infoPtr->nColumnWidth;
3531 /* get current row */
3532 nRow = lpHitTestInfo->pt.y / infoPtr->nItemHeight;
3534 /* get the index of the first visible item */
3535 nTopIndex = ListView_GetTopIndex(hwnd);
3537 nItem = nColumn * infoPtr->nCountPerColumn + nTopIndex + nRow;
3538 nItem = LISTVIEW_HitTestItem(hwnd, nItem, lpHitTestInfo);
3542 /* get current row */
3543 nRow = ((lpHitTestInfo->pt.y - infoPtr->rcList.top) /
3544 infoPtr->nItemHeight);
3546 /* get the index of the first visible item */
3547 nTopIndex = ListView_GetTopIndex(hwnd);
3549 nItem = nTopIndex + nRow;
3550 nItem = LISTVIEW_HitTestItem(hwnd, nItem, lpHitTestInfo);
3554 /* nItem = LISTVIEW_HitTestItem(hwnd, nItem, lpHitTestInfo); */
3563 * Inserts a new column.
3566 * [I] HWND : window handle
3567 * [I] INT : column index
3568 * [I] LPLVCOLUMNA : column information
3571 * SUCCESS : new column index
3574 static LRESULT LISTVIEW_InsertColumnA(HWND hwnd, INT nColumn,
3575 LPLVCOLUMNA lpColumn)
3577 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
3579 INT nNewColumn = -1;
3581 if (lpColumn != NULL)
3583 /* initialize memory */
3584 ZeroMemory(&hdi, sizeof(HDITEMA));
3586 if (lpColumn->mask & LVCF_FMT)
3588 /* format member is valid */
3589 hdi.mask |= HDI_FORMAT;
3591 /* set text alignment (leftmost column must be left-aligned) */
3594 hdi.fmt |= HDF_LEFT;
3598 if (lpColumn->fmt & LVCFMT_LEFT)
3600 hdi.fmt |= HDF_LEFT;
3602 else if (lpColumn->fmt & LVCFMT_RIGHT)
3604 hdi.fmt |= HDF_RIGHT;
3606 else if (lpColumn->fmt & LVCFMT_CENTER)
3608 hdi.fmt |= HDF_CENTER;
3612 if (lpColumn->fmt & LVCFMT_BITMAP_ON_RIGHT)
3614 hdi.fmt |= HDF_BITMAP_ON_RIGHT;
3618 if (lpColumn->fmt & LVCFMT_COL_HAS_IMAGES)
3623 if (lpColumn->fmt & LVCFMT_IMAGE)
3625 hdi.fmt |= HDF_IMAGE;
3626 hdi.iImage = I_IMAGECALLBACK;
3630 if (lpColumn->mask & LVCF_WIDTH)
3632 hdi.mask |= HDI_WIDTH;
3633 hdi.cxy = lpColumn->cx;
3636 if (lpColumn->mask & LVCF_TEXT)
3638 hdi.mask |= HDI_TEXT | HDI_FORMAT;
3639 hdi.pszText = lpColumn->pszText;
3640 hdi.cchTextMax = lstrlenA(lpColumn->pszText);
3641 hdi.fmt |= HDF_STRING;
3644 if (lpColumn->mask & LVCF_IMAGE)
3646 hdi.mask |= HDI_IMAGE;
3647 hdi.iImage = lpColumn->iImage;
3650 if (lpColumn->mask & LVCF_ORDER)
3652 hdi.mask |= HDI_ORDER;
3653 hdi.iOrder = lpColumn->iOrder;
3656 /* insert item in header control */
3657 nNewColumn = SendMessageA(infoPtr->hwndHeader, HDM_INSERTITEMA,
3658 (WPARAM)nColumn, (LPARAM)&hdi);
3660 LISTVIEW_SetScroll(hwnd);
3661 InvalidateRect(hwnd, NULL, FALSE);
3667 /* << LISTVIEW_InsertColumnW >> */
3671 * Inserts a new item in the listview control.
3674 * [I] HWND : window handle
3675 * [I] LPLVITEMA : item information
3678 * SUCCESS : new item index
3681 static LRESULT LISTVIEW_InsertItemA(HWND hwnd, LPLVITEMA lpLVItem)
3683 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
3684 LONG lCtrlId = GetWindowLongA(hwnd, GWL_ID);
3688 LISTVIEW_ITEM *lpItem = NULL;
3690 if (lpLVItem != NULL)
3692 /* make sure it's not a subitem; cannot insert a subitem */
3693 if (lpLVItem->iSubItem == 0)
3695 lpItem = (LISTVIEW_ITEM *)COMCTL32_Alloc(sizeof(LISTVIEW_ITEM));
3698 ZeroMemory(lpItem, sizeof(LISTVIEW_ITEM));
3699 if (LISTVIEW_InitItem(hwnd, lpItem, lpLVItem) == TRUE)
3701 /* insert item in listview control data structure */
3702 hdpaSubItems = DPA_Create(8);
3703 if (hdpaSubItems != NULL)
3705 nItem = DPA_InsertPtr(hdpaSubItems, 0, lpItem);
3708 nItem = DPA_InsertPtr(infoPtr->hdpaItems, lpLVItem->iItem,
3712 /* manage item focus */
3713 if (lpLVItem->mask & LVIF_STATE)
3715 if (lpLVItem->stateMask & LVIS_FOCUSED)
3717 LISTVIEW_SetItemFocus(hwnd, nItem);
3721 /* send LVN_INSERTITEM notification */
3722 ZeroMemory(&nmlv, sizeof(NMLISTVIEW));
3723 nmlv.hdr.hwndFrom = hwnd;
3724 nmlv.hdr.idFrom = lCtrlId;
3725 nmlv.hdr.code = LVN_INSERTITEM;
3727 nmlv.lParam = lpItem->lParam;;
3728 ListView_LVNotify(GetParent(hwnd), lCtrlId, &nmlv);
3730 /* set scrolling parameters */
3731 LISTVIEW_SetScroll(hwnd);
3733 /* refresh client area */
3734 InvalidateRect(hwnd, NULL, FALSE);
3743 /* free memory if unsuccessful */
3744 if ((nItem == -1) && (lpItem != NULL))
3746 COMCTL32_Free(lpItem);
3752 /* << LISTVIEW_InsertItemW >> */
3756 * Redraws a range of items.
3759 * [I] HWND : window handle
3760 * [I] INT : first item
3761 * [I] INT : last item
3767 static LRESULT LISTVIEW_RedrawItems(HWND hwnd, INT nFirst, INT nLast)
3769 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
3770 BOOL bResult = FALSE;
3773 if (nFirst <= nLast)
3775 if ((nFirst >= 0) && (nFirst < GETITEMCOUNT(infoPtr)))
3777 if ((nLast >= 0) && (nLast < GETITEMCOUNT(infoPtr)))
3780 InvalidateRect(hwnd, &rc, FALSE);
3790 * Scrolls the content of a listview.
3793 * [I] HWND : window handle
3794 * [I] INT : amount of horizontal scrolling
3795 * [I] INT : amount of vertical scrolling
3801 static LRESULT LISTVIEW_Scroll(HWND hwnd, INT nHScroll, INT nVScroll)
3803 LONG lStyle = GetWindowLongA(hwnd, GWL_STYLE);
3805 BOOL bResult = FALSE;
3809 if (lStyle & WS_HSCROLL)
3811 nScrollPos = GetScrollPos(hwnd, SB_HORZ);
3812 GetScrollRange(hwnd, SB_HORZ, &nMinRange, &nMaxRange);
3813 nScrollPos += nHScroll;
3815 if ((LVS_TYPEMASK & lStyle) == LVS_LIST)
3817 nScrollPos = GetScrollPos(hwnd, SB_HORZ);
3818 GetScrollRange(hwnd, SB_HORZ, &nMinRange, &nMaxRange);
3819 nScrollPos += nHScroll;
3820 if ((nMinRange <= nScrollPos) && (nScrollPos <= nMaxRange))
3823 SetScrollPos(hwnd, SB_HORZ, nScrollPos, TRUE);
3832 if (lStyle & WS_VSCROLL)
3834 if ((LVS_TYPEMASK & lStyle) == LVS_REPORT)
3836 nScrollPos = GetScrollPos(hwnd, SB_VERT);
3837 GetScrollRange(hwnd, SB_VERT, &nMinRange, &nMaxRange);
3838 nScrollPos += nVScroll;
3839 if ((nMinRange <= nScrollPos) && (nScrollPos <= nMaxRange))
3842 SetScrollPos(hwnd, SB_VERT, nScrollPos, TRUE);
3851 if (bResult == TRUE)
3853 /* refresh client area */
3854 InvalidateRect(hwnd, NULL, TRUE);
3862 * Sets the background color.
3865 * [I] HWND : window handle
3866 * [I] COLORREF : background color
3872 static LRESULT LISTVIEW_SetBkColor(HWND hwnd, COLORREF clrBk)
3874 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
3876 infoPtr->clrBk = clrBk;
3877 InvalidateRect(hwnd, NULL, TRUE);
3884 * Sets the callback mask. This mask will be used when the parent
3885 * window stores the state information (some or all).
3888 * [I] HWND : window handle
3889 * [I] UINT : state mask
3895 static BOOL LISTVIEW_SetCallbackMask(HWND hwnd, UINT uMask)
3897 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
3899 infoPtr->uCallbackMask = uMask;
3906 * Sets column attributes.
3909 * [I] HWND : window handle
3910 * [I] INT : column index
3911 * [I] LPLVCOLUMNA : column attributes
3917 static LRESULT LISTVIEW_SetColumnA(HWND hwnd, INT nColumn,
3918 LPLVCOLUMNA lpColumn)
3920 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
3922 BOOL bResult = FALSE;
3924 if ((lpColumn != NULL) && (nColumn >= 0) &&
3925 (nColumn < Header_GetItemCount(infoPtr->hwndHeader)))
3927 /* initialize memory */
3928 ZeroMemory(&hdi, sizeof(HDITEMA));
3930 if (lpColumn->mask & LVCF_FMT)
3932 /* format member is valid */
3933 hdi.mask |= HDI_FORMAT;
3935 /* set text alignment (leftmost column must be left-aligned) */
3938 hdi.fmt |= HDF_LEFT;
3942 if (lpColumn->fmt & LVCFMT_LEFT)
3944 hdi.fmt |= HDF_LEFT;
3946 else if (lpColumn->fmt & LVCFMT_RIGHT)
3948 hdi.fmt |= HDF_RIGHT;
3950 else if (lpColumn->fmt & LVCFMT_CENTER)
3952 hdi.fmt |= HDF_CENTER;
3956 if (lpColumn->fmt & LVCFMT_BITMAP_ON_RIGHT)
3958 hdi.fmt |= HDF_BITMAP_ON_RIGHT;
3961 if (lpColumn->fmt & LVCFMT_COL_HAS_IMAGES)
3963 hdi.fmt |= HDF_IMAGE;
3966 if (lpColumn->fmt & LVCFMT_IMAGE)
3968 hdi.fmt |= HDF_IMAGE;
3969 hdi.iImage = I_IMAGECALLBACK;
3973 if (lpColumn->mask & LVCF_WIDTH)
3975 hdi.mask |= HDI_WIDTH;
3976 hdi.cxy = lpColumn->cx;
3979 if (lpColumn->mask & LVCF_TEXT)
3981 hdi.mask |= HDI_TEXT | HDI_FORMAT;
3982 hdi.pszText = lpColumn->pszText;
3983 hdi.cchTextMax = lstrlenA(lpColumn->pszText);
3984 hdi.fmt |= HDF_STRING;
3987 if (lpColumn->mask & LVCF_IMAGE)
3989 hdi.mask |= HDI_IMAGE;
3990 hdi.iImage = lpColumn->iImage;
3993 if (lpColumn->mask & LVCF_ORDER)
3995 hdi.mask |= HDI_ORDER;
3996 hdi.iOrder = lpColumn->iOrder;
3999 /* set header item attributes */
4000 bResult = Header_SetItemA(infoPtr->hwndHeader, nColumn, &hdi);
4011 * [I] HWND : window handle
4012 * [I] INT : image list type
4013 * [I] HIMAGELIST : image list handle
4016 * SUCCESS : old image list
4019 static LRESULT LISTVIEW_SetImageList(HWND hwnd, INT nType, HIMAGELIST himl)
4021 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
4022 HIMAGELIST himlTemp = 0;
4027 himlTemp = infoPtr->himlNormal;
4028 infoPtr->himlNormal = himl;
4029 return (LRESULT)himlTemp;
4032 himlTemp = infoPtr->himlSmall;
4033 infoPtr->himlSmall = himl;
4034 return (LRESULT)himlTemp;
4037 himlTemp = infoPtr->himlState;
4038 infoPtr->himlState = himl;
4039 return (LRESULT)himlTemp;
4042 return (LRESULT)NULL;
4048 * Sets item attributes.
4051 * [I] HWND : window handle
4052 * [I] LPLVITEM : item information
4058 static LRESULT LISTVIEW_SetItemA(HWND hwnd, LPLVITEMA lpLVItem)
4060 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
4061 BOOL bResult = FALSE;
4063 if (lpLVItem != NULL)
4065 if ((lpLVItem->iItem >= 0) && (lpLVItem->iItem < GETITEMCOUNT(infoPtr)))
4067 if (lpLVItem->iSubItem == 0)
4069 bResult = LISTVIEW_SetItem(hwnd, lpLVItem);
4073 bResult = LISTVIEW_SetSubItem(hwnd, lpLVItem);
4082 /* << LISTVIEW_SetItemW >> */
4086 * Preallocates memory.
4089 * [I] HWND : window handle
4090 * [I] INT : item count (prjected number of items)
4095 static VOID LISTVIEW_SetItemCount(HWND hwnd, INT nItemCount)
4102 * Sets item position.
4105 * [I] HWND : window handle
4106 * [I] INT : item index
4107 * [I] INT : x coordinate
4108 * [I] INT : y coordinate
4114 static LRESULT LISTVIEW_SetItemPosition(HWND hwnd, INT nItem,
4115 INT nPosX, INT nPosY)
4117 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO*)GetWindowLongA(hwnd, 0);
4118 LONG lStyle = GetWindowLongA(hwnd, GWL_STYLE);
4119 BOOL bResult = FALSE;
4121 if ((nItem >= 0) || (nItem < GETITEMCOUNT(infoPtr)))
4123 if (((lStyle & LVS_TYPEMASK) == LVS_ICON) ||
4124 ((lStyle & LVS_TYPEMASK) == LVS_SMALLICON))
4135 * Sets the state of one or many items.
4138 * [I] HWND : window handle
4139 * [I]INT : item index
4140 * [I] LPLVITEM : item or subitem info
4146 static LRESULT LISTVIEW_SetItemState(HWND hwnd, INT nItem,
4149 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
4150 BOOL bResult = FALSE;
4157 ZeroMemory(&lvItem, sizeof(LVITEMA));
4158 lvItem.mask = LVIF_STATE;
4159 lvItem.state = lpLVItem->state;
4160 lvItem.stateMask = lpLVItem->stateMask;
4162 /* apply to all items */
4163 for (i = 0; i< GETITEMCOUNT(infoPtr); i++)
4166 if (ListView_SetItemA(hwnd, &lvItem) == FALSE)
4174 ZeroMemory(&lvItem, sizeof(LVITEMA));
4175 lvItem.mask = LVIF_STATE;
4176 lvItem.state = lpLVItem->state;
4177 lvItem.stateMask = lpLVItem->stateMask;
4178 lvItem.iItem = nItem;
4179 bResult = ListView_SetItemA(hwnd, &lvItem);
4187 * Sets the text of an item or subitem.
4190 * [I] HWND : window handle
4191 * [I] INT : item index
4192 * [I] LPLVITEMA : item or subitem info
4198 static BOOL LISTVIEW_SetItemTextA(HWND hwnd, INT nItem,
4201 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
4202 BOOL bResult = FALSE;
4205 if ((nItem >= 0) && (nItem < GETITEMCOUNT(infoPtr)))
4207 ZeroMemory(&lvItem, sizeof(LVITEMA));
4208 lvItem.mask = LVIF_TEXT;
4209 lvItem.pszText = lpLVItem->pszText;
4210 lvItem.iItem = nItem;
4211 lvItem.iSubItem = lpLVItem->iSubItem;
4212 bResult = ListView_SetItemA(hwnd, &lvItem);
4220 * Sets the text background color.
4223 * [I] HWND : window handle
4224 * [I] COLORREF : text background color
4230 static LRESULT LISTVIEW_SetTextBkColor(HWND hwnd, COLORREF clrTextBk)
4232 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
4234 infoPtr->clrTextBk = clrTextBk;
4241 * Sets the text background color.
4244 * [I] HWND : window handle
4245 * [I] COLORREF : text color
4251 static LRESULT LISTVIEW_SetTextColor (HWND hwnd, COLORREF clrText)
4253 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
4255 infoPtr->clrText = clrText;
4265 * [I] HWND : window handle
4271 static LRESULT LISTVIEW_SortItems(HWND hwnd, WPARAM wParam, LPARAM lParam)
4273 FIXME (listview, "empty stub!\n");
4280 * Updates an items or rearranges the listview control.
4283 * [I] HWND : window handle
4284 * [I] INT : item index
4290 static LRESULT LISTVIEW_Update(HWND hwnd, INT nItem)
4292 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
4293 LONG lStyle = GetWindowLongA(hwnd, GWL_STYLE);
4294 BOOL bResult = FALSE;
4297 if ((nItem >= 0) && (nItem < GETITEMCOUNT(infoPtr)))
4301 /* rearrange with default alignment style */
4302 if ((lStyle & LVS_AUTOARRANGE) && (((lStyle & LVS_TYPEMASK) == LVS_ICON) ||
4303 ((lStyle & LVS_TYPEMASK) == LVS_SMALLICON)))
4305 ListView_Arrange(hwnd, 0);
4309 /* get item bounding rectangle */
4310 rc.left = LVIR_BOUNDS;
4311 ListView_GetItemRect(hwnd, nItem, &rc);
4312 InvalidateRect(hwnd, &rc, FALSE);
4321 * Creates a listview control.
4324 * [I] HWND : window handle
4329 static LRESULT LISTVIEW_Create(HWND hwnd, WPARAM wParam, LPARAM lParam)
4331 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
4332 LPCREATESTRUCTA lpcs = (LPCREATESTRUCTA)lParam;
4337 /* determine the type of structures to use */
4338 infoPtr->notifyFormat = SendMessageA(GetParent(hwnd), WM_NOTIFYFORMAT,
4339 (WPARAM)hwnd, (LPARAM)NF_QUERY);
4340 if (infoPtr->notifyFormat != NFR_ANSI)
4342 FIXME (listview, "ANSI notify format is NOT used\n");
4345 /* initialize color information */
4346 infoPtr->clrBk = GetSysColor(COLOR_WINDOW);
4347 infoPtr->clrText = GetSysColor(COLOR_WINDOWTEXT);
4348 infoPtr->clrTextBk = GetSysColor(COLOR_WINDOW);
4350 /* set default values */
4351 infoPtr->uCallbackMask = 0;
4352 infoPtr->nFocusedItem = -1;
4353 infoPtr->nSelectionMark = -1;
4354 infoPtr->iconSize.cx = GetSystemMetrics(SM_CXSMICON);
4355 infoPtr->iconSize.cy = GetSystemMetrics(SM_CYSMICON);
4356 ZeroMemory(&infoPtr->rcList, sizeof(RECT));
4358 /* get default font (icon title) */
4359 SystemParametersInfoA(SPI_GETICONTITLELOGFONT, 0, &logFont, 0);
4360 infoPtr->hDefaultFont = CreateFontIndirectA(&logFont);
4361 infoPtr->hFont = infoPtr->hDefaultFont;
4364 infoPtr->hwndHeader = CreateWindowA(WC_HEADERA, (LPCSTR)NULL,
4365 WS_CHILD | HDS_HORZ | HDS_BUTTONS ,
4366 0, 0, 0, 0, hwnd, (HMENU)0,
4367 lpcs->hInstance, NULL);
4369 /* set header font */
4370 SendMessageA(infoPtr->hwndHeader, WM_SETFONT, (WPARAM)infoPtr->hFont,
4373 switch (lpcs->style & LVS_TYPEMASK)
4377 hl.prc = &infoPtr->rcList;
4379 Header_Layout(infoPtr->hwndHeader, &hl);
4380 SetWindowPos(infoPtr->hwndHeader, hwnd, wp.x, wp.y, wp.cx, wp.cy,
4383 /* set new top coord */
4384 infoPtr->rcList.top = wp.cy;
4386 /* display header */
4387 ShowWindow(infoPtr->hwndHeader, SW_SHOWNORMAL);
4394 /* temporary (until there is support) */
4395 SetWindowLongA(hwnd, GWL_STYLE,
4396 (lpcs->style & ~LVS_TYPEMASK) | LVS_LIST);
4400 LISTVIEW_UnsupportedStyles(lpcs->style);
4402 /* allocate memory */
4403 infoPtr->hdpaItems = DPA_Create(10);
4405 /* set view dependent information */
4406 LISTVIEW_SetViewInfo(hwnd);
4414 * Destroys the window
4417 * [I] HWND : window handle
4422 static LRESULT LISTVIEW_Destroy(HWND hwnd)
4424 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO*)GetWindowLongA(hwnd, 0);
4426 /* delete all items */
4427 LISTVIEW_DeleteAllItems(hwnd);
4430 DPA_Destroy(infoPtr->hdpaItems);
4432 /* destroy header */
4433 if (infoPtr->hwndHeader)
4435 DestroyWindow(infoPtr->hwndHeader);
4439 infoPtr->hFont = (HFONT)0;
4440 if (infoPtr->hDefaultFont)
4442 DeleteObject(infoPtr->hDefaultFont);
4450 * Erases the background of the listview control
4453 * [I] HWND : window handle
4454 * [I] WPARAM : device context handle
4455 * [I] LPARAM : not used
4461 static LRESULT LISTVIEW_EraseBackground(HWND hwnd, WPARAM wParam,
4464 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
4467 if (infoPtr->clrBk == CLR_NONE)
4469 bResult = SendMessageA(GetParent(hwnd), WM_ERASEBKGND, wParam, lParam);
4473 HBRUSH hBrush = CreateSolidBrush(infoPtr->clrBk);
4474 FillRect((HDC)wParam, &infoPtr->rcList, hBrush);
4475 DeleteObject(hBrush);
4484 * Gets the listview control font.
4487 * [I] HWND : window handle
4492 static LRESULT LISTVIEW_GetFont(HWND hwnd)
4494 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
4496 return infoPtr->hFont;
4501 * Performs horizontal scrolling.
4504 * [I] HWND : window handle
4505 * [I] INT : scroll code
4506 * [I] INT : scroll position
4507 * [I] HWND : scrollbar control window handle
4512 static LRESULT LISTVIEW_VScroll(HWND hwnd, INT nScrollCode,
4513 INT nScroll, HWND hScrollWnd)
4515 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
4516 LONG lStyle = GetWindowLongA(hwnd, GWL_STYLE);
4517 INT nScrollPos, nOldScrollPos;
4521 GetScrollRange(hwnd, SB_VERT, &nMinRange, &nMaxRange);
4522 nOldScrollPos = nScrollPos = GetScrollPos(hwnd, SB_VERT);
4524 switch (LVS_TYPEMASK & lStyle)
4527 switch (nScrollCode)
4530 if (nScrollPos > nMinRange)
4536 if (nScrollPos < nMaxRange)
4542 if (nScrollPos > nMinRange + infoPtr->nCountPerColumn)
4544 nScrollPos -= infoPtr->nCountPerColumn;
4548 nScrollPos = nMinRange;
4552 if (nScrollPos < nMaxRange - infoPtr->nCountPerColumn)
4554 nScrollPos += infoPtr->nCountPerColumn;
4558 nScrollPos = nMaxRange;
4561 case SB_THUMBPOSITION:
4562 nScrollPos = nScroll;
4571 /* set new scroll position */
4572 if (nScrollPos != nOldScrollPos)
4574 SetScrollPos(hwnd, SB_VERT, nScrollPos, TRUE);
4576 /* refresh client area */
4577 InvalidateRect(hwnd, NULL, TRUE);
4586 * Performs horizontal scrolling.
4589 * [I] HWND : window handle
4590 * [I] INT : scroll code
4591 * [I] INT : scroll position
4592 * [I] HWND : scrollbar control window handle
4597 static LRESULT LISTVIEW_HScroll(HWND hwnd, INT nScrollCode,
4598 INT nScroll, HWND hScrollWnd)
4600 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
4601 LONG lStyle = GetWindowLongA(hwnd, GWL_STYLE);
4602 INT nScrollPos, nOldScrollPos;
4606 GetScrollRange(hwnd, SB_HORZ, &nMinRange, &nMaxRange);
4607 nOldScrollPos = nScrollPos = GetScrollPos(hwnd, SB_HORZ);
4609 switch (LVS_TYPEMASK & lStyle)
4613 /* list display mode horizontal scrolling */
4614 switch (nScrollCode)
4617 if (nScrollPos > nMinRange)
4623 if (nScrollPos < nMaxRange)
4629 if (nScrollPos > nMinRange)
4631 nScrollPos = max(nMinRange, nScrollPos - infoPtr->nCountPerRow);
4635 nScrollPos = nMinRange;
4639 if (nScrollPos < nMaxRange - 1)
4641 nScrollPos = min(nMaxRange, nScrollPos + infoPtr->nCountPerRow);
4645 nScrollPos = nMaxRange;
4648 case SB_THUMBPOSITION:
4649 nScrollPos = nScroll;
4656 /* report/details display mode horizontal scrolling */
4657 switch (nScrollCode)
4660 if (nScrollPos > nMinRange)
4666 if (nScrollPos < nMaxRange)
4672 if (nScrollPos > nMinRange)
4674 nScrollPos = max(nMinRange, nScrollPos - infoPtr->rcList.right);
4678 nScrollPos = nMinRange;
4682 if (nScrollPos < nMaxRange)
4684 nScrollPos = min(nMaxRange, nScrollPos + infoPtr->rcList.right);
4688 nScrollPos = nMaxRange;
4691 case SB_THUMBPOSITION:
4692 nScrollPos = nScroll;
4701 /* set new scroll position */
4702 if (nScrollPos != nOldScrollPos)
4704 SetScrollPos(hwnd, SB_HORZ, nScrollPos, TRUE);
4706 /* refresh client area */
4707 InvalidateRect(hwnd, NULL, TRUE);
4718 * [I] HWND : window handle
4719 * [I] INT : virtual key
4720 * [I] LONG : key data
4725 static LRESULT LISTVIEW_KeyDown(HWND hwnd, INT nVirtualKey, LONG lKeyData)
4727 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
4728 LONG lStyle = GetWindowLongA(hwnd, GWL_STYLE);
4729 INT nCtrlId = GetWindowLongA(hwnd, GWL_ID);
4730 HWND hwndParent = GetParent(hwnd);
4731 NMLVKEYDOWN nmKeyDown;
4734 /* send LVN_KEYDOWN notification */
4735 ZeroMemory(&nmKeyDown, sizeof(NMLVKEYDOWN));
4736 nmKeyDown.hdr.hwndFrom = hwnd;
4737 nmKeyDown.hdr.idFrom = nCtrlId;
4738 nmKeyDown.hdr.code = LVN_KEYDOWN;
4739 nmKeyDown.wVKey = nVirtualKey;
4740 nmKeyDown.flags = 0;
4741 SendMessageA(hwndParent, WM_NOTIFY, (WPARAM)nCtrlId, (LPARAM)&nmKeyDown);
4744 nmh.hwndFrom = hwnd;
4745 nmh.idFrom = nCtrlId;
4747 switch (nVirtualKey)
4750 if ((GETITEMCOUNT(infoPtr) > 0) && (infoPtr->nFocusedItem != -1))
4752 /* send NM_RETURN notification */
4753 nmh.code = NM_RETURN;
4754 ListView_Notify(hwndParent, nCtrlId, &nmh);
4756 /* send LVN_ITEMACTIVATE notification */
4757 nmh.code = LVN_ITEMACTIVATE;
4758 ListView_Notify(hwndParent, nCtrlId, &nmh);
4763 if (GETITEMCOUNT(infoPtr) > 0)
4765 LISTVIEW_KeySelection(hwnd, 0);
4770 if (GETITEMCOUNT(infoPtr) > 0)
4772 LISTVIEW_KeySelection(hwnd, GETITEMCOUNT(infoPtr) - 1);
4777 switch (LVS_TYPEMASK & lStyle)
4780 if (infoPtr->nFocusedItem >= infoPtr->nCountPerColumn)
4782 LISTVIEW_KeySelection(hwnd, infoPtr->nFocusedItem - infoPtr->nCountPerColumn);
4789 if (infoPtr->nFocusedItem % infoPtr->nCountPerRow != 0)
4791 LISTVIEW_SetSelection(hwnd, infoPtr->nFocusedItem - 1);
4797 switch (LVS_TYPEMASK & lStyle)
4801 if (infoPtr->nFocusedItem > 0)
4803 LISTVIEW_KeySelection(hwnd, infoPtr->nFocusedItem - 1);
4808 if (infoPtr->nFocusedItem >= infoPtr->nCountPerRow)
4810 LISTVIEW_SetSelection(hwnd, infoPtr->nFocusedItem -
4811 infoPtr->nCountPerRow);
4817 switch (LVS_TYPEMASK & lStyle)
4820 if (infoPtr->nFocusedItem <
4821 (GETITEMCOUNT(infoPtr) - infoPtr->nCountPerColumn))
4823 LISTVIEW_KeySelection(hwnd, infoPtr->nFocusedItem +
4824 infoPtr->nCountPerColumn);
4830 if (infoPtr->nCountPerRow > 0)
4837 switch (LVS_TYPEMASK & lStyle)
4841 if (infoPtr->nFocusedItem < GETITEMCOUNT(infoPtr) - 1)
4843 LISTVIEW_KeySelection(hwnd, infoPtr->nFocusedItem + 1);
4846 if (infoPtr->nCountPerRow > 0)
4859 /* refresh client area */
4860 InvalidateRect(hwnd, NULL, TRUE);
4870 * [I] HWND : window handle
4875 static LRESULT LISTVIEW_KillFocus(HWND hwnd)
4877 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO*)GetWindowLongA(hwnd, 0);
4878 INT nCtrlId = GetWindowLongA(hwnd, GWL_ID);
4881 /* send NM_KILLFOCUS notification */
4882 nmh.hwndFrom = hwnd;
4883 nmh.idFrom = nCtrlId;
4884 nmh.code = NM_KILLFOCUS;
4885 ListView_Notify(GetParent(hwnd), nCtrlId, &nmh);
4887 /* set window focus flag */
4888 infoPtr->bFocus = FALSE;
4895 * Left mouse button double click.
4898 * [I] HWND : window handle
4899 * [I] WORD : key flag
4900 * [I] WORD : x coordinate
4901 * [I] WORD : y coordinate
4906 static LRESULT LISTVIEW_LButtonDblClk(HWND hwnd, WORD wKey, WORD wPosX,
4909 LONG nCtrlId = GetWindowLongA(hwnd, GWL_ID);
4912 /* send NM_DBLCLK notification */
4913 nmh.hwndFrom = hwnd;
4914 nmh.idFrom = nCtrlId;
4915 nmh.code = NM_DBLCLK;
4916 ListView_Notify(GetParent(hwnd), nCtrlId, &nmh);
4918 /* send LVN_ITEMACTIVATE notification */
4919 nmh.code = LVN_ITEMACTIVATE;
4920 ListView_Notify(GetParent(hwnd), nCtrlId, &nmh);
4927 * Left mouse button down.
4930 * [I] HWND : window handle
4931 * [I] WORD : key flag
4932 * [I] WORD : x coordinate
4933 * [I] WORD : y coordinate
4938 static LRESULT LISTVIEW_LButtonDown(HWND hwnd, WORD wKey, WORD wPosX,
4941 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
4942 INT nCtrlId = GetWindowLongA(hwnd, GWL_ID);
4943 LVHITTESTINFO hitTestInfo;
4946 static BOOL bGroupSelect = TRUE;
4948 /* send NM_RELEASEDCAPTURE notification */
4949 nmh.hwndFrom = hwnd;
4950 nmh.idFrom = nCtrlId;
4951 nmh.code = NM_RELEASEDCAPTURE;
4952 ListView_Notify(GetParent(hwnd), nCtrlId, &nmh);
4954 if (infoPtr->bFocus == FALSE)
4959 /* set left button down flag */
4960 infoPtr->bLButtonDown = TRUE;
4962 /* set left button hit coordinates */
4963 hitTestInfo.pt.x = wPosX;
4964 hitTestInfo.pt.y = wPosY;
4966 /* perform hit test */
4967 nItem = ListView_HitTest(hwnd, &hitTestInfo);
4968 if ((nItem >= 0) && (nItem < GETITEMCOUNT(infoPtr)))
4970 if ((wKey & MK_CONTROL) && (wKey & MK_SHIFT))
4972 if (bGroupSelect == TRUE)
4974 LISTVIEW_AddGroupSelection(hwnd, nItem);
4978 LISTVIEW_AddSelection(hwnd, nItem);
4981 else if (wKey & MK_CONTROL)
4983 bGroupSelect = LISTVIEW_ToggleSelection(hwnd, nItem);
4985 else if (wKey & MK_SHIFT)
4987 LISTVIEW_SetGroupSelection(hwnd, nItem);
4991 LISTVIEW_SetSelection(hwnd, nItem);
4996 /* remove all selections */
4997 LISTVIEW_RemoveSelections(hwnd, 0, GETITEMCOUNT(infoPtr));
5000 InvalidateRect(hwnd, NULL, TRUE);
5007 * Left mouse button up.
5010 * [I] HWND : window handle
5011 * [I] WORD : key flag
5012 * [I] WORD : x coordinate
5013 * [I] WORD : y coordinate
5018 static LRESULT LISTVIEW_LButtonUp(HWND hwnd, WORD wKey, WORD wPosX,
5021 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
5022 INT nCtrlId = GetWindowLongA(hwnd, GWL_ID);
5025 if (infoPtr->bLButtonDown == TRUE)
5027 /* send NM_CLICK notification */
5028 nmh.hwndFrom = hwnd;
5029 nmh.idFrom = nCtrlId;
5030 nmh.code = NM_CLICK;
5031 ListView_Notify(GetParent(hwnd), nCtrlId, &nmh);
5033 /* set left button flag */
5034 infoPtr->bLButtonDown = FALSE;
5042 * Creates the listview control (called before WM_CREATE).
5045 * [I] HWND : window handle
5046 * [I] WPARAM : unhandled
5047 * [I] LPARAM : widow creation info
5052 static LRESULT LISTVIEW_NCCreate(HWND hwnd, WPARAM wParam, LPARAM lParam)
5054 LISTVIEW_INFO *infoPtr;
5056 /* allocate memory for info structure */
5057 infoPtr = (LISTVIEW_INFO *)COMCTL32_Alloc(sizeof(LISTVIEW_INFO));
5058 SetWindowLongA(hwnd, 0, (LONG)infoPtr);
5059 if (infoPtr == NULL)
5061 ERR(listview, "could not allocate info memory!\n");
5065 if ((LISTVIEW_INFO *)GetWindowLongA(hwnd, 0) != infoPtr)
5067 ERR(listview, "pointer assignment error!\n");
5071 return DefWindowProcA(hwnd, WM_NCCREATE, wParam, lParam);
5076 * Destroys the listview control (called after WM_DESTROY).
5079 * [I] HWND : window handle
5084 static LRESULT LISTVIEW_NCDestroy(HWND hwnd)
5086 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
5088 /* free listview info */
5089 COMCTL32_Free(infoPtr);
5096 * Handles notification from children.
5099 * [I] HWND : window handle
5100 * [I] INT : control identifier
5101 * [I] LPNMHDR : notification information
5106 static LRESULT LISTVIEW_Notify(HWND hwnd, INT nCtrlId, LPNMHDR lpnmh)
5108 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
5110 if (lpnmh->hwndFrom == infoPtr->hwndHeader)
5112 /* handle notification from header control */
5113 if (lpnmh->code == HDN_ENDTRACKA)
5115 InvalidateRect(hwnd, NULL, TRUE);
5122 static LRESULT LISTVIEW_NotifyFormat(HWND hwndFrom, HWND hwnd, INT nCommand)
5124 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
5126 if (nCommand == NF_REQUERY)
5128 /* determine the type of structures to use */
5129 infoPtr->notifyFormat = SendMessageA(hwndFrom, WM_NOTIFYFORMAT,
5130 (WPARAM)hwnd, (LPARAM)NF_QUERY);
5131 if (infoPtr->notifyFormat == NFR_UNICODE)
5133 FIXME (listview, "NO support for unicode structures");
5142 * Draws the listview control.
5145 * [I] HWND : window handle
5146 * [I] HDC : device context handle
5151 static LRESULT LISTVIEW_Paint(HWND hwnd, HDC hdc)
5157 hdc = BeginPaint(hwnd, &ps);
5158 LISTVIEW_Refresh(hwnd, hdc);
5159 EndPaint(hwnd, &ps);
5163 LISTVIEW_Refresh(hwnd, hdc);
5171 * Right mouse button double click.
5174 * [I] HWND : window handle
5175 * [I] WORD : key flag
5176 * [I] WORD : x coordinate
5177 * [I] WORD : y coordinate
5182 static LRESULT LISTVIEW_RButtonDblClk(HWND hwnd, WORD wKey, WORD wPosX,
5185 INT nCtrlId = GetWindowLongA(hwnd, GWL_ID);
5188 /* send NM_RELEASEDCAPTURE notification */
5189 nmh.hwndFrom = hwnd;
5190 nmh.idFrom = nCtrlId;
5191 nmh.code = NM_RELEASEDCAPTURE;
5192 ListView_Notify(GetParent(hwnd), nCtrlId, &nmh);
5194 /* send NM_RDBLCLK notification */
5195 nmh.code = NM_RDBLCLK;
5196 ListView_Notify(GetParent(hwnd), nCtrlId, &nmh);
5203 * Right mouse button input.
5206 * [I] HWND : window handle
5207 * [I] WORD : key flag
5208 * [I] WORD : x coordinate
5209 * [I] WORD : y coordinate
5214 static LRESULT LISTVIEW_RButtonDown(HWND hwnd, WORD wKey, WORD wPosX,
5217 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
5218 INT nCtrlId = GetWindowLongA(hwnd, GWL_ID);
5219 LVHITTESTINFO hitTestInfo;
5223 /* send NM_RELEASEDCAPTURE notification */
5224 nmh.hwndFrom = hwnd;
5225 nmh.idFrom = nCtrlId;
5226 nmh.code = NM_RELEASEDCAPTURE;
5227 ListView_Notify(GetParent(hwnd), nCtrlId, &nmh);
5229 /* make sure the listview control window has the focus */
5230 if (infoPtr->bFocus == FALSE)
5235 /* set right button down flag */
5236 infoPtr->bRButtonDown = TRUE;
5238 /* set hit coordinates */
5239 hitTestInfo.pt.x = wPosX;
5240 hitTestInfo.pt.y = wPosY;
5242 /* perform hit test */
5243 nItem = ListView_HitTest(hwnd, &hitTestInfo);
5244 if ((nItem >= 0) && (nItem < GETITEMCOUNT(infoPtr)))
5246 if (!((wKey & MK_SHIFT) || (wKey & MK_CONTROL)))
5248 LISTVIEW_SetSelection(hwnd, nItem);
5253 LISTVIEW_RemoveSelections(hwnd, 0, GETITEMCOUNT(infoPtr));
5261 * Right mouse button up.
5264 * [I] HWND : window handle
5265 * [I] WORD : key flag
5266 * [I] WORD : x coordinate
5267 * [I] WORD : y coordinate
5272 static LRESULT LISTVIEW_RButtonUp(HWND hwnd, WORD wKey, WORD wPosX,
5275 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
5276 INT nCtrlId = GetWindowLongA(hwnd, GWL_ID);
5279 if (infoPtr->bRButtonDown == TRUE)
5281 /* send NM_RClICK notification */
5282 ZeroMemory(&nmh, sizeof(NMHDR));
5283 nmh.hwndFrom = hwnd;
5284 nmh.idFrom = nCtrlId;
5285 nmh.code = NM_RCLICK;
5286 ListView_Notify(GetParent(hwnd), nCtrlId, &nmh);
5288 /* set button flag */
5289 infoPtr->bRButtonDown = FALSE;
5300 * [I] HWND : window handle
5301 * [I] HWND : window handle of previously focused window
5306 static LRESULT LISTVIEW_SetFocus(HWND hwnd, HWND hwndLoseFocus)
5308 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
5309 INT nCtrlId = GetWindowLongA(hwnd, GWL_ID);
5312 /* send NM_SETFOCUS notification */
5313 nmh.hwndFrom = hwnd;
5314 nmh.idFrom = nCtrlId;
5315 nmh.code = NM_SETFOCUS;
5316 ListView_Notify(GetParent(hwnd), nCtrlId, &nmh);
5318 /* set window focus flag */
5319 infoPtr->bFocus = TRUE;
5329 * [I] HWND : window handle
5330 * [I] HFONT : font handle
5331 * [I] WORD : redraw flag
5336 static LRESULT LISTVIEW_SetFont(HWND hwnd, HFONT hFont, WORD fRedraw)
5338 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
5339 LONG lStyle = GetWindowLongA(hwnd, GWL_STYLE);
5343 infoPtr->hFont = infoPtr->hDefaultFont;
5347 infoPtr->hFont = hFont;
5350 if ((LVS_TYPEMASK & lStyle ) == LVS_REPORT)
5352 /* set header font */
5353 SendMessageA(infoPtr->hwndHeader, WM_SETFONT, (WPARAM)hFont,
5354 MAKELPARAM(fRedraw, 0));
5357 /* invalidate listview control client area */
5358 InvalidateRect(hwnd, NULL, FALSE);
5360 if (fRedraw == TRUE)
5370 * Resizes the listview control.
5373 * [I] HWND : window handle
5374 * [I] WORD : new width
5375 * [I] WORD : new height
5380 static LRESULT LISTVIEW_Size(HWND hwnd, WORD wWidth, WORD wHeight)
5382 LISTVIEW_SetSize(hwnd, GetWindowLongA(hwnd, GWL_STYLE), wWidth, wHeight);
5383 LISTVIEW_SetViewInfo(hwnd);
5384 LISTVIEW_SetScroll(hwnd);
5386 /* invalidate + erase background */
5387 InvalidateRect(hwnd, NULL, TRUE);
5394 * Sets the size information for a given style.
5397 * [I] HWND : window handle
5398 * [I] LONG : window style
5399 * [I] WORD : new width
5400 * [I] WORD : new height
5405 static VOID LISTVIEW_SetSize(HWND hwnd, LONG lStyle, LONG lWidth, LONG lHeight)
5407 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
5413 switch (lStyle & LVS_TYPEMASK)
5416 if ((lStyle & LVS_TYPEMASK) == LVS_LIST)
5418 if (!(lStyle & WS_HSCROLL))
5422 nHScrollHeight = GetSystemMetrics(SM_CYHSCROLL);
5423 if (lHeight > nHScrollHeight)
5425 lHeight -= nHScrollHeight;
5435 rc.bottom = lHeight;
5438 Header_Layout(infoPtr->hwndHeader, &hl);
5443 infoPtr->rcList.top = lTop;
5444 infoPtr->rcList.left = 0;
5445 infoPtr->rcList.bottom = lHeight;
5446 infoPtr->rcList.right = lWidth;
5451 * Notification sent when the window style is modified.
5454 * [I] HWND : window handle
5455 * [I] WPARAM : window style type (normal or extended)
5456 * [I] LPSTYLESTRUCT : window style information
5461 static INT LISTVIEW_StyleChanged(HWND hwnd, WPARAM wStyleType,
5464 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
5471 if (wStyleType == GWL_STYLE)
5473 /* remove vertical scrollbar */
5474 if (lpss->styleOld & WS_VSCROLL)
5476 ShowScrollBar(hwnd, SB_VERT, FALSE);
5479 /* remove horizontal scrollbar */
5480 if (lpss->styleOld & WS_HSCROLL)
5482 ShowScrollBar(hwnd, SB_HORZ, FALSE);
5485 if ((LVS_TYPEMASK & lpss->styleOld) == LVS_REPORT)
5488 ShowWindow(infoPtr->hwndHeader, SW_HIDE);
5491 /* erase everything */
5492 GetClientRect(hwnd, &rc);
5494 hBrush = CreateSolidBrush(infoPtr->clrBk);
5495 FillRect(hdc, &rc, hBrush);
5496 DeleteObject(hBrush);
5497 ReleaseDC(hwnd, hdc);
5499 if ((lpss->styleNew & LVS_TYPEMASK) == LVS_REPORT)
5503 Header_Layout(infoPtr->hwndHeader, &hl);
5504 SetWindowPos(infoPtr->hwndHeader, hwnd, wp.x, wp.y, wp.cx, wp.cy,
5506 ShowWindow(infoPtr->hwndHeader, SW_SHOWNORMAL);
5508 else if (((lpss->styleNew & LVS_TYPEMASK) == LVS_ICON) ||
5509 ((lpss->styleNew & LVS_TYPEMASK) == LVS_SMALLICON))
5511 /* for NOW (it's only temporary) */
5512 SetWindowLongA(hwnd, GWL_STYLE, (lpss->styleNew&~LVS_TYPEMASK)|LVS_LIST);
5516 LISTVIEW_UnsupportedStyles(lpss->styleNew);
5519 LISTVIEW_SetSize(hwnd, lpss->styleNew, rc.right, rc.bottom);
5521 /* recalculate attributes */
5522 LISTVIEW_SetViewInfo(hwnd);
5524 /* set scrollbars, if needed */
5525 LISTVIEW_SetScroll(hwnd);
5527 /* invalidate + erase background */
5528 InvalidateRect(hwnd, NULL, TRUE);
5536 * Window procedure of the listview control.
5547 LRESULT WINAPI LISTVIEW_WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam,
5552 case LVM_APPROXIMATEVIEWRECT:
5553 return LISTVIEW_ApproximateViewRect(hwnd, (INT)wParam,
5554 LOWORD(lParam), HIWORD(lParam));
5556 return LISTVIEW_Arrange(hwnd, (INT)wParam);
5558 /* case LVM_CREATEDRAGIMAGE: */
5560 case LVM_DELETEALLITEMS:
5561 return LISTVIEW_DeleteAllItems(hwnd);
5563 case LVM_DELETECOLUMN:
5564 return LISTVIEW_DeleteColumn(hwnd, (INT)wParam);
5566 case LVM_DELETEITEM:
5567 return LISTVIEW_DeleteItem(hwnd, (INT)wParam);
5569 /* case LVM_EDITLABEL: */
5571 case LVM_ENSUREVISIBLE:
5572 return LISTVIEW_EnsureVisible(hwnd, (INT)wParam, (BOOL)lParam);
5575 return LISTVIEW_FindItem(hwnd, (INT)wParam, (LPLVFINDINFO)lParam);
5577 case LVM_GETBKCOLOR:
5578 return LISTVIEW_GetBkColor(hwnd);
5580 /* case LVM_GETBKIMAGE: */
5582 case LVM_GETCALLBACKMASK:
5583 return LISTVIEW_GetCallbackMask(hwnd);
5585 case LVM_GETCOLUMNA:
5586 return LISTVIEW_GetColumnA(hwnd, (INT)wParam, (LPLVCOLUMNA)lParam);
5588 /* case LVM_GETCOLUMNW: */
5589 /* case LVM_GETCOLUMNORDERARRAY: */
5591 case LVM_GETCOLUMNWIDTH:
5592 return LISTVIEW_GetColumnWidth(hwnd, (INT)wParam);
5594 case LVM_GETCOUNTPERPAGE:
5595 return LISTVIEW_GetCountPerPage(hwnd);
5597 /* case LVM_GETEDITCONTROL: */
5598 /* case LVM_GETEXTENDEDLISTVIEWSTYLE: */
5601 return LISTVIEW_GetHeader(hwnd);
5603 /* case LVM_GETHOTCURSOR: */
5604 /* case LVM_GETHOTITEM: */
5605 /* case LVM_GETHOVERTIME: */
5607 case LVM_GETIMAGELIST:
5608 return LISTVIEW_GetImageList(hwnd, (INT)wParam);
5610 /* case LVM_GETISEARCHSTRING: */
5613 return LISTVIEW_GetItemA(hwnd, (LPLVITEMA)lParam);
5615 /* case LVM_GETITEMW: */
5617 case LVM_GETITEMCOUNT:
5618 return LISTVIEW_GetItemCount(hwnd);
5620 case LVM_GETITEMPOSITION:
5621 return LISTVIEW_GetItemPosition(hwnd, (INT)wParam, (LPPOINT)lParam);
5623 case LVM_GETITEMRECT:
5624 return LISTVIEW_GetItemRect(hwnd, (INT)wParam, (LPRECT)lParam);
5626 case LVM_GETITEMSPACING:
5627 return LISTVIEW_GetItemSpacing(hwnd, (BOOL)wParam);
5629 case LVM_GETITEMSTATE:
5630 return LISTVIEW_GetItemState(hwnd, (INT)wParam, (UINT)lParam);
5632 case LVM_GETITEMTEXTA:
5633 LISTVIEW_GetItemTextA(hwnd, (INT)wParam, (LPLVITEMA)lParam);
5636 /* case LVM_GETITEMTEXTW: */
5638 case LVM_GETNEXTITEM:
5639 return LISTVIEW_GetNextItem(hwnd, (INT)wParam, LOWORD(lParam));
5641 /* case LVM_GETNUMBEROFWORKAREAS: */
5643 return LISTVIEW_GetOrigin(hwnd, (LPPOINT)lParam);
5645 case LVM_GETSELECTEDCOUNT:
5646 return LISTVIEW_GetSelectedCount(hwnd);
5648 case LVM_GETSELECTIONMARK:
5649 return LISTVIEW_GetSelectionMark(hwnd);
5651 case LVM_GETSTRINGWIDTHA:
5652 return LISTVIEW_GetStringWidthA (hwnd, (LPCSTR)lParam);
5654 /* case LVM_GETSTRINGWIDTHW: */
5655 /* case LVM_GETSUBITEMRECT: */
5657 case LVM_GETTEXTBKCOLOR:
5658 return LISTVIEW_GetTextBkColor(hwnd);
5660 case LVM_GETTEXTCOLOR:
5661 return LISTVIEW_GetTextColor(hwnd);
5663 /* case LVM_GETTOOLTIPS: */
5665 case LVM_GETTOPINDEX:
5666 return LISTVIEW_GetTopIndex(hwnd);
5668 /* case LVM_GETUNICODEFORMAT: */
5670 case LVM_GETVIEWRECT:
5671 return LISTVIEW_GetViewRect(hwnd, (LPRECT)lParam);
5673 /* case LVM_GETWORKAREAS: */
5676 return LISTVIEW_HitTest(hwnd, (LPLVHITTESTINFO)lParam);
5678 case LVM_INSERTCOLUMNA:
5679 return LISTVIEW_InsertColumnA(hwnd, (INT)wParam,
5680 (LPLVCOLUMNA)lParam);
5682 /* case LVM_INSERTCOLUMNW: */
5684 case LVM_INSERTITEMA:
5685 return LISTVIEW_InsertItemA(hwnd, (LPLVITEMA)lParam);
5687 /* case LVM_INSERTITEMW: */
5689 case LVM_REDRAWITEMS:
5690 return LISTVIEW_RedrawItems(hwnd, (INT)wParam, (INT)lParam);
5693 return LISTVIEW_Scroll(hwnd, (INT)wParam, (INT)lParam);
5695 case LVM_SETBKCOLOR:
5696 return LISTVIEW_SetBkColor(hwnd, (COLORREF)lParam);
5698 /* case LVM_SETBKIMAGE: */
5700 case LVM_SETCALLBACKMASK:
5701 return LISTVIEW_SetCallbackMask(hwnd, (UINT)wParam);
5703 case LVM_SETCOLUMNA:
5704 return LISTVIEW_SetColumnA(hwnd, (INT)wParam, (LPLVCOLUMNA)lParam);
5706 /* case LVM_SETCOLUMNW: */
5707 /* case LVM_SETCOLUMNORDERARRAY: */
5708 /* case LVM_SETCOLUMNWIDTH: */
5709 /* case LVM_SETEXTENDEDLISTVIEWSTYLE: */
5710 /* case LVM_SETHOTCURSOR: */
5711 /* case LVM_SETHOTITEM: */
5712 /* case LVM_SETHOVERTIME: */
5713 /* case LVM_SETICONSPACING: */
5715 case LVM_SETIMAGELIST:
5716 return LISTVIEW_SetImageList(hwnd, (INT)wParam, (HIMAGELIST)lParam);
5719 return LISTVIEW_SetItemA(hwnd, (LPLVITEMA)lParam);
5721 /* case LVM_SETITEMW: */
5723 case LVM_SETITEMCOUNT:
5724 LISTVIEW_SetItemCount(hwnd, (INT)wParam);
5727 case LVM_SETITEMPOSITION:
5728 return LISTVIEW_SetItemPosition(hwnd, (INT)wParam, (INT)LOWORD(lParam),
5729 (INT)HIWORD(lParam));
5731 /* case LVM_SETITEMPOSITION: */
5733 case LVM_SETITEMSTATE:
5734 return LISTVIEW_SetItemState(hwnd, (INT)wParam, (LPLVITEMA)lParam);
5736 case LVM_SETITEMTEXTA:
5737 return LISTVIEW_SetItemTextA(hwnd, (INT)wParam, (LPLVITEMA)lParam);
5739 /* case LVM_SETSELECTIONMARK: */
5741 case LVM_SETTEXTBKCOLOR:
5742 return LISTVIEW_SetTextBkColor(hwnd, (COLORREF)lParam);
5744 case LVM_SETTEXTCOLOR:
5745 return LISTVIEW_SetTextColor(hwnd, (COLORREF)lParam);
5747 /* case LVM_SETTOOLTIPS: */
5748 /* case LVM_SETUNICODEFORMAT: */
5749 /* case LVM_SETWORKAREAS: */
5752 return LISTVIEW_SortItems(hwnd, wParam, lParam);
5754 /* case LVM_SUBITEMHITTEST: */
5757 return LISTVIEW_Update(hwnd, (INT)wParam);
5760 /* case WM_COMMAND: */
5763 return LISTVIEW_Create(hwnd, wParam, lParam);
5766 return LISTVIEW_Destroy(hwnd);
5769 return LISTVIEW_EraseBackground(hwnd, wParam, lParam);
5772 return DLGC_WANTTAB | DLGC_WANTARROWS;
5775 return LISTVIEW_GetFont(hwnd);
5778 return LISTVIEW_HScroll(hwnd, (INT)LOWORD(wParam),
5779 (INT)HIWORD(wParam), (HWND)lParam);
5782 return LISTVIEW_KeyDown(hwnd, (INT)wParam, (LONG)lParam);
5785 return LISTVIEW_KillFocus(hwnd);
5787 case WM_LBUTTONDBLCLK:
5788 return LISTVIEW_LButtonDblClk(hwnd, (WORD)wParam, LOWORD(lParam),
5791 case WM_LBUTTONDOWN:
5792 return LISTVIEW_LButtonDown(hwnd, (WORD)wParam, LOWORD(lParam),
5795 return LISTVIEW_LButtonUp(hwnd, (WORD)wParam, LOWORD(lParam),
5798 /* case WM_MOUSEMOVE: */
5799 /* return LISTVIEW_MouseMove (hwnd, wParam, lParam); */
5802 return LISTVIEW_NCCreate(hwnd, wParam, lParam);
5805 return LISTVIEW_NCDestroy(hwnd);
5808 return LISTVIEW_Notify(hwnd, (INT)wParam, (LPNMHDR)lParam);
5810 case WM_NOTIFYFORMAT:
5811 return LISTVIEW_NotifyFormat(hwnd, (HWND)wParam, (INT)lParam);
5814 return LISTVIEW_Paint(hwnd, (HDC)wParam);
5816 case WM_RBUTTONDBLCLK:
5817 return LISTVIEW_RButtonDblClk(hwnd, (WORD)wParam, LOWORD(lParam),
5820 case WM_RBUTTONDOWN:
5821 return LISTVIEW_RButtonDown(hwnd, (WORD)wParam, LOWORD(lParam),
5825 return LISTVIEW_RButtonUp(hwnd, (WORD)wParam, LOWORD(lParam),
5829 return LISTVIEW_SetFocus(hwnd, (HWND)wParam);
5832 return LISTVIEW_SetFont(hwnd, (HFONT)wParam, (WORD)lParam);
5834 /* case WM_SETREDRAW: */
5837 return LISTVIEW_Size(hwnd, LOWORD(lParam), HIWORD(lParam));
5839 case WM_STYLECHANGED:
5840 return LISTVIEW_StyleChanged(hwnd, wParam, (LPSTYLESTRUCT)lParam);
5842 /* case WM_TIMER: */
5845 return LISTVIEW_VScroll(hwnd, (INT)LOWORD(wParam),
5846 (INT)HIWORD(wParam), (HWND)lParam);
5848 /* case WM_WINDOWPOSCHANGED: */
5849 /* case WM_WININICHANGE: */
5852 if (uMsg >= WM_USER)
5854 ERR(listview, "unknown msg %04x wp=%08x lp=%08lx\n",
5855 uMsg, wParam, lParam);
5858 /* call default window procedure */
5859 return DefWindowProcA(hwnd, uMsg, wParam, lParam);
5867 * Registers the window class.
5875 VOID LISTVIEW_Register(VOID)
5879 if (!GlobalFindAtomA(WC_LISTVIEWA))
5881 ZeroMemory(&wndClass, sizeof(WNDCLASSA));
5882 wndClass.style = CS_GLOBALCLASS | CS_DBLCLKS;
5883 wndClass.lpfnWndProc = (WNDPROC)LISTVIEW_WindowProc;
5884 wndClass.cbClsExtra = 0;
5885 wndClass.cbWndExtra = sizeof(LISTVIEW_INFO *);
5886 wndClass.hCursor = LoadCursorA(0, IDC_ARROWA);
5887 wndClass.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
5888 wndClass.lpszClassName = WC_LISTVIEWA;
5889 RegisterClassA (&wndClass);
5895 * Unregisters the window class.
5903 VOID LISTVIEW_Unregister(VOID)
5905 if (GlobalFindAtomA(WC_LISTVIEWA))
5906 UnregisterClassA(WC_LISTVIEWA, (HINSTANCE)NULL);