4 * Copyright 1998 Eric Kohl
5 * Copyright 1999 Luc Tourangeau
8 * Listview control implementation. The behavior conforms to version 4.70
9 * and earlier of the listview contol.
12 * Most messages and notifications
13 * Report, small icon and icon display modes
24 static INT32 LISTVIEW_GetItemCountPerColumn(HWND32 hwnd);
25 static INT32 LISTVIEW_GetItemCountPerRow(HWND32 hwnd);
26 static INT32 LISTVIEW_GetFirstVisibleItem(HWND32 hwnd);
27 static VOID LISTVIEW_SetVisible(HWND32 hwnd, INT32 nItem);
32 * Scrolls the specified item into the visible area.
35 * [I] HWND32 : window handle
36 * [I] INT32 : item index
41 static VOID LISTVIEW_SetVisible(HWND32 hwnd, INT32 nItem)
43 LONG lStyle = GetWindowLong32A(hwnd, GWL_STYLE);
44 INT32 nItemCountPerRow;
45 INT32 nItemCountPerColumn;
51 /* retrieve the index of the first visible fully item */
52 nFirstItem = LISTVIEW_GetFirstVisibleItem(hwnd);
54 /* nunber of fully visible items per row */
55 nItemCountPerRow = LISTVIEW_GetItemCountPerRow(hwnd);
57 /* nunber of fully visible items per column */
58 nItemCountPerColumn = LISTVIEW_GetItemCountPerColumn(hwnd);
60 if ((nItemCountPerRow > 0) && (nItemCountPerColumn > 0))
62 if (lStyle & LVS_LIST)
64 if (lStyle & WS_HSCROLL)
66 /* last visible item index */
67 nLastItem = nItemCountPerColumn * nItemCountPerRow + nFirstItem - 1;
68 if (nItem > nLastItem)
70 /* calculate new scroll position based on item index */
71 if (((nItem - nLastItem) % nItemCountPerColumn) == 0)
72 nHScrollPos = (nItem - nLastItem) / nItemCountPerColumn;
74 nHScrollPos = (nItem - nLastItem) / nItemCountPerColumn + 1;
75 SendMessage32A(hwnd, LVM_SCROLL, (WPARAM32)nHScrollPos, (LPARAM)0);
77 else if (nItem < nFirstItem)
79 /* calculate new scroll position based on item index */
80 if (((nItem - nFirstItem) % nItemCountPerColumn) == 0)
81 nHScrollPos = (nItem - nFirstItem) / nItemCountPerColumn;
83 nHScrollPos = (nItem - nFirstItem) / nItemCountPerColumn - 1;
84 SendMessage32A(hwnd, LVM_SCROLL, (WPARAM32)nHScrollPos, (LPARAM)0);
88 else if (lStyle & LVS_REPORT)
90 if (lStyle & WS_VSCROLL)
94 nLastItem = nItemCountPerColumn + nFirstItem;
98 nLastItem = nItemCountPerColumn + nFirstItem - 1;
101 if (nItem > nLastItem)
103 /* calculate new scroll position based on item index */
104 nVScrollPos = nItem - nLastItem;
105 SendMessage32A(hwnd, LVM_SCROLL, (WPARAM32)0, (LPARAM)nVScrollPos);
107 else if (nItem < nFirstItem)
109 /* calculate new scroll position based on item index */
110 nVScrollPos = nItem - nFirstItem;
111 SendMessage32A(hwnd, LVM_SCROLL, (WPARAM32)0, (LPARAM)nVScrollPos);
115 else if ((lStyle & LVS_SMALLICON) || (lStyle & LVS_ICON))
117 if (lStyle & WS_VSCROLL)
119 /* last visible item index */
120 nLastItem = nItemCountPerColumn * nItemCountPerRow + nFirstItem - 1;
121 if (nItem > nLastItem)
123 /* calculate new scroll position based on item index */
124 nVScrollPos = (nItem - nLastItem) / nItemCountPerRow + 1;
125 SendMessage32A(hwnd, LVM_SCROLL, (WPARAM32)0, (LPARAM)nVScrollPos);
127 else if (nItem < nFirstItem)
129 /* calculate new scroll position based on item index */
130 nHScrollPos = (nItem - nFirstItem) / nItemCountPerRow - 1;
131 SendMessage32A(hwnd, LVM_SCROLL, (WPARAM32)0, (LPARAM)nHScrollPos);
136 /* refresh display */
137 InvalidateRect32(hwnd, NULL, FALSE);
138 UpdateWindow32(hwnd);
145 * Retrieves the index of the item at coordinate (0, 0) of the client area.
148 * [I] HWND32 : window handle
153 static INT32 LISTVIEW_GetFirstVisibleItem(HWND32 hwnd)
155 LONG lStyle = GetWindowLong32A(hwnd, GWL_STYLE);
156 INT32 nItemCountPerRow;
157 INT32 nItemCountPerColumn;
161 /* INT32 nVScrollPos; */
164 /* get number of items per column */
165 nItemCountPerColumn = LISTVIEW_GetItemCountPerColumn(hwnd);
167 /* get number of fully visble items per row */
168 nItemCountPerRow = LISTVIEW_GetItemCountPerRow(hwnd);
170 if ((nItemCountPerRow > 0) && (nItemCountPerColumn > 0))
172 if (lStyle & LVS_LIST)
174 if (lStyle & WS_HSCROLL)
176 GetScrollRange32(hwnd, SB_HORZ, &nMinRange, &nMaxRange);
177 nHScrollPos = GetScrollPos32(hwnd, SB_HORZ);
178 if (nMinRange < nHScrollPos)
180 nItem = ((nHScrollPos - nMinRange) * nItemCountPerColumn *
185 else if (lStyle & LVS_REPORT)
189 else if (lStyle & LVS_SMALLICON)
193 else if (lStyle & LVS_ICON)
204 * Retrieves the number of items per row. In other words, the number
205 * visible display columns.
208 * [I] HWND32 : window handle
211 * Number of items per row.
213 static INT32 LISTVIEW_GetItemCountPerRow(HWND32 hwnd)
215 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLong32A(hwnd, 0);
216 LONG lStyle = GetWindowLong32A(hwnd, GWL_STYLE);
217 INT32 nItemCountPerRow = 0;
219 if (infoPtr->nWidth > 0)
221 if (lStyle & LVS_LIST)
223 if (infoPtr->nColumnWidth > 0)
225 nItemCountPerRow = infoPtr->nWidth / infoPtr->nColumnWidth;
226 if (nItemCountPerRow == 0)
227 nItemCountPerRow = 1;
230 else if (lStyle & LVS_REPORT)
234 else if (lStyle & LVS_SMALLICON)
238 else if (lStyle & LVS_ICON)
244 return nItemCountPerRow;
249 * Retrieves the number of items that can be displayed vertically in
253 * [I] HWND32 : window handle
256 * Number of items per column.
258 static INT32 LISTVIEW_GetItemCountPerColumn(HWND32 hwnd)
260 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLong32A(hwnd, 0);
261 LONG lStyle = GetWindowLong32A(hwnd, GWL_STYLE);
262 INT32 nItemCountPerColumn = 0;
264 if (infoPtr->nHeight > 0)
266 if (lStyle & LVS_LIST)
268 if (infoPtr->nItemHeight > 0)
269 nItemCountPerColumn = infoPtr->nHeight / infoPtr->nItemHeight;
271 else if (lStyle & LVS_REPORT)
275 else if (lStyle & LVS_SMALLICON)
279 else if (lStyle & LVS_ICON)
285 return nItemCountPerColumn;
290 * Retrieves the number of columns needed to display
291 * all the items in listview.
294 * [I] HWND32 : window handle
299 static INT32 LISTVIEW_GetColumnCount(HWND32 hwnd)
301 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLong32A(hwnd, 0);
302 LONG lStyle = GetWindowLong32A(hwnd, GWL_STYLE);
303 INT32 nColumnCount = 0;
304 INT32 nItemCountPerColumn;
306 nItemCountPerColumn = LISTVIEW_GetItemCountPerColumn(hwnd);
308 if ((infoPtr->nItemCount > 0) && (nItemCountPerColumn > 0))
310 if (lStyle & LVS_LIST)
312 if ((infoPtr->nItemCount % nItemCountPerColumn) == 0)
314 nColumnCount = infoPtr->nItemCount / nItemCountPerColumn ;
318 nColumnCount = infoPtr->nItemCount / nItemCountPerColumn + 1;
321 else if (lStyle & LVS_REPORT)
325 else if (lStyle & LVS_SMALLICON)
329 else if (lStyle & LVS_ICON)
340 * Sets the scrolling parameters.
343 * [I] HWND32 : window handle
348 static VOID LISTVIEW_SetScroll(HWND32 hwnd)
350 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLong32A(hwnd, 0);
351 LONG lStyle = GetWindowLong32A(hwnd, GWL_STYLE);
353 INT32 nItemCountPerRow;
354 INT32 nItemCountPerColumn;
355 INT32 nMinRange, nMaxRange;
357 /* INT32 nVScrollPos; */
359 nItemCountPerColumn = LISTVIEW_GetItemCountPerColumn(hwnd);
360 nItemCountPerRow = LISTVIEW_GetItemCountPerRow(hwnd);
362 if ((nItemCountPerColumn > 0) && (nItemCountPerRow > 0))
364 if (lStyle & LVS_LIST)
366 /* get number of columns needed to display all the listview items */
367 nColumnCount = LISTVIEW_GetColumnCount(hwnd);
368 if (nColumnCount > 0)
370 if (nColumnCount > nItemCountPerRow)
372 /* add scrollbar if not already present */
373 if (!(lStyle & WS_HSCROLL))
375 /* display scrollbar */
376 ShowScrollBar32(hwnd, SB_HORZ, TRUE);
378 /* set scrollbar range and position */
379 nMaxRange = nColumnCount - nItemCountPerRow;
380 SetScrollRange32(hwnd, SB_HORZ, 0, nMaxRange, FALSE);
381 SetScrollPos32(hwnd, SB_HORZ, 0, TRUE);
385 nHScrollPos = GetScrollPos32(hwnd, SB_HORZ);
386 GetScrollRange32(hwnd, SB_HORZ, &nMinRange, &nMaxRange);
387 if (nMaxRange != nColumnCount - nItemCountPerRow)
389 nMaxRange = nColumnCount - nItemCountPerRow;
390 SetScrollRange32(hwnd, SB_HORZ, nMinRange, nMaxRange, FALSE);
392 if (nHScrollPos > nMaxRange)
393 nHScrollPos = nMaxRange;
395 SetScrollPos32(hwnd, SB_HORZ, nHScrollPos, TRUE);
399 /* refresh the client area */
400 InvalidateRect32(hwnd,NULL, TRUE);
401 UpdateWindow32(hwnd);
405 /* remove scrollbar if present */
406 if (lStyle & WS_HSCROLL)
409 ShowScrollBar32(hwnd, SB_HORZ, FALSE);
411 /* refresh the client area */
412 InvalidateRect32(hwnd,NULL, TRUE);
413 UpdateWindow32(hwnd);
418 else if (lStyle & LVS_REPORT)
426 rc.right = infoPtr->nWidth;
427 rc.bottom = infoPtr->nHeight;
431 SendMessage32A(infoPtr->hwndHeader, HDM_LAYOUT, 0, (LPARAM)&hl);
433 SetWindowPos32(infoPtr->hwndHeader, hwnd,
434 wp.x, wp.y, wp.cx, wp.cy, wp.flags);
436 /* infoPtr->rcList.top += wp.cy; */
438 else if (lStyle & LVS_SMALLICON)
442 else if (lStyle & LVS_ICON)
451 * Modifies the state (selected and focused) of the listview items.
454 * [I] HWND32 : window handle
455 * [I] INT32 : focused item index
456 * [I] BOOL32 : flag for determining weither the control keys are used or not
457 * [I] BOOL32 : flag for determining the input type (mouse or keyboard)
462 static VOID LISTVIEW_SetItemStates(HWND32 hwnd, INT32 nFocusedItem,
463 BOOL32 bVirtualKeys, BOOL32 bMouseInput)
465 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLong32A(hwnd, 0);
466 WORD wShift = HIWORD(GetKeyState32(VK_SHIFT));
467 WORD wCtrl = HIWORD(GetKeyState32(VK_CONTROL));
471 /* initialize memory */
472 ZeroMemory(&lvItem, sizeof(LVITEM32A));
474 if (wShift && (bVirtualKeys == TRUE))
476 /* reset the selected and focused states of all the items */
477 lvItem.stateMask = LVIS_SELECTED | LVIS_FOCUSED;
479 SendMessage32A(hwnd, LVM_SETITEMSTATE, (WPARAM32)-1, (LPARAM)&lvItem);
481 if (infoPtr->nSelectionMark > nFocusedItem)
483 for (i = infoPtr->nSelectionMark; i > nFocusedItem; i--)
486 lvItem.stateMask = LVIS_SELECTED;
487 lvItem.state = LVIS_SELECTED;
488 SendMessage32A(hwnd, LVM_SETITEMSTATE, (WPARAM32)i, (LPARAM)&lvItem);
493 for (i = infoPtr->nSelectionMark; i < nFocusedItem; i++)
496 lvItem.stateMask = LVIS_SELECTED;
497 lvItem.state = LVIS_SELECTED;
498 SendMessage32A(hwnd, LVM_SETITEMSTATE, (WPARAM32)i, (LPARAM)&lvItem);
502 /* select anf focus item */
503 lvItem.stateMask = LVIS_SELECTED | LVIS_FOCUSED;
504 lvItem.state = LVIS_SELECTED | LVIS_FOCUSED;
505 SendMessage32A(hwnd, LVM_SETITEMSTATE, (WPARAM32)i, (LPARAM)&lvItem);
509 if (wCtrl && (bVirtualKeys == TRUE))
511 /* make sure the focus is lost */
512 lvItem.stateMask = LVIS_FOCUSED;
514 SendMessage32A(hwnd, LVM_SETITEMSTATE, (WPARAM32)-1, (LPARAM)&lvItem);
516 if (bMouseInput == TRUE)
518 if (SendMessage32A(hwnd, LVM_GETITEMSTATE, (WPARAM32)nFocusedItem,
519 (LPARAM)LVIS_SELECTED) & LVIS_SELECTED)
521 /* focus and unselect (toggle selection) */
522 lvItem.stateMask = LVIS_SELECTED | LVIS_FOCUSED;
523 lvItem.state = LVIS_FOCUSED;
524 SendMessage32A(hwnd, LVM_SETITEMSTATE, (WPARAM32)nFocusedItem,
529 /* select and focus */
530 lvItem.stateMask = LVIS_SELECTED | LVIS_FOCUSED;
531 lvItem.state = LVIS_SELECTED | LVIS_FOCUSED;
532 SendMessage32A(hwnd, LVM_SETITEMSTATE, (WPARAM32)nFocusedItem,
536 /* set the group selection start position */
537 infoPtr->nSelectionMark = nFocusedItem;
542 lvItem.stateMask = LVIS_FOCUSED;
543 lvItem.state = LVIS_FOCUSED;
544 SendMessage32A(hwnd, LVM_SETITEMSTATE, (WPARAM32)nFocusedItem,
550 /* clear selection and focus for all the items */
551 lvItem.stateMask = LVIS_SELECTED | LVIS_FOCUSED;
553 SendMessage32A(hwnd, LVM_SETITEMSTATE, (WPARAM32)-1, (LPARAM)&lvItem);
555 /* set select and focus for this particular item */
556 lvItem.stateMask = LVIS_FOCUSED | LVIS_SELECTED;
557 lvItem.state = LVIS_FOCUSED | LVIS_SELECTED;
558 SendMessage32A(hwnd, LVM_SETITEMSTATE, (WPARAM32)nFocusedItem,
561 /* set the new group selection start position */
562 infoPtr->nSelectionMark = nFocusedItem;
569 * Draws listview items when in list display maode.
572 * [I] HWND32 : window handle
573 * [I] HDC32 : device context handle
578 static VOID LISTVIEW_RefreshList(HWND32 hwnd, HDC32 hdc)
580 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLong32A(hwnd, 0);
581 LISTVIEW_ITEM *lpItem;
583 HPEN32 hPen, hOldPen;
584 INT32 nItemCountPerColumn;
585 INT32 nItemCountPerRow;
586 INT32 nSmallIconWidth;
591 RECT32 rcBoundingBox;
592 COLORREF clrHighlight;
593 COLORREF clrHighlightText;
599 /* get number of items per column */
600 nItemCountPerColumn = LISTVIEW_GetItemCountPerColumn(hwnd);
602 /* get number of items per row */
603 nItemCountPerRow = LISTVIEW_GetItemCountPerColumn(hwnd);
605 if ((nItemCountPerColumn > 0) && (nItemCountPerRow > 0))
608 hOldFont = SelectObject32(hdc, infoPtr->hFont);
610 /* inititialize system dependent information */
611 clrHighlight = GetSysColor32(COLOR_HIGHLIGHT);
612 clrHighlightText = GetSysColor32(COLOR_HIGHLIGHTTEXT);
613 nSmallIconWidth = GetSystemMetrics32(SM_CXSMICON);
615 /* select transparent brush (for drawing the focus box) */
616 SelectObject32(hdc, GetStockObject32(NULL_BRUSH));
618 /* select the doted pen (for drawing the focus box) */
619 hPen = CreatePen32(PS_DOT, 1, 0);
620 hOldPen = SelectObject32(hdc, hPen);
622 /* get starting index */
623 i = LISTVIEW_GetFirstVisibleItem(hwnd);
626 for (j = 0; i < infoPtr->nItemCount; i++, j++)
628 /* set draw position for current item */
629 nRow = j % nItemCountPerColumn;
630 nColumn = j / nItemCountPerColumn;
634 nDrawPosY += infoPtr->nItemHeight;
636 nDrawPosX = nColumn * infoPtr->nColumnWidth;
639 lpItem = (LISTVIEW_ITEM *)DPA_GetPtr(infoPtr->hdpaItems, i);
642 if (lpItem->state & LVIS_SELECTED)
646 /* set item colors */
647 SetBkColor32(hdc, clrHighlight);
648 SetTextColor32(hdc, clrHighlightText);
650 /* set raster mode */
651 SetROP232(hdc, R2_XORPEN);
657 /* set item colors */
658 SetBkColor32(hdc, infoPtr->clrTextBk);
659 SetTextColor32(hdc, infoPtr->clrText);
661 /* set raster mode */
662 SetROP232(hdc, R2_COPYPEN);
666 if (infoPtr->himlState != NULL)
668 /* right shift 12 bits to obtain index in image list */
669 if (bSelected == TRUE)
670 ImageList_Draw(infoPtr->himlState, lpItem->state >> 12, hdc,
671 nDrawPosX, nDrawPosY, ILD_SELECTED);
673 ImageList_Draw(infoPtr->himlState, lpItem->state >> 12, hdc,
674 nDrawPosX, nDrawPosY, ILD_NORMAL);
676 nDrawPosX += nSmallIconWidth;
680 if (infoPtr->himlSmall != NULL)
682 if (bSelected == TRUE)
683 ImageList_Draw(infoPtr->himlSmall, lpItem->iImage, hdc, nDrawPosX,
684 nDrawPosY, ILD_SELECTED);
686 ImageList_Draw(infoPtr->himlSmall, lpItem->iImage, hdc, nDrawPosX,
687 nDrawPosY, ILD_NORMAL);
689 nDrawPosX += nSmallIconWidth;
692 /* get string size (in pixels) */
693 GetTextExtentPoint32A(hdc, lpItem->pszText,
694 lstrlen32A(lpItem->pszText), &labelSize);
696 /* define a bounding box */
697 rcBoundingBox.left = nDrawPosX;
698 rcBoundingBox.top = nDrawPosY;
700 /* 2 pixels for padding purposes */
701 rcBoundingBox.right = nDrawPosX + labelSize.cx + 2;
703 /* padding already included in infoPtr->nItemHeight */
704 rcBoundingBox.bottom = nDrawPosY + infoPtr->nItemHeight;
707 ExtTextOut32A(hdc, nDrawPosX + 1, nDrawPosY+ 1,
708 ETO_OPAQUE|ETO_CLIPPED, &rcBoundingBox,
709 lpItem->pszText, lstrlen32A(lpItem->pszText), NULL);
711 if (lpItem->state & LVIS_FOCUSED)
712 Rectangle32(hdc, rcBoundingBox.left, rcBoundingBox.top,
713 rcBoundingBox.right, rcBoundingBox.bottom);
717 /* unselect objects */
718 SelectObject32(hdc, hOldFont);
719 SelectObject32(hdc, hOldPen);
722 DeleteObject32(hPen);
728 * Draws listview items when in report display mode.
731 * [I] HWND32 : window handle
732 * [I] HDC32 : device context handle
737 static VOID LISTVIEW_RefreshReport(HWND32 hwnd, HDC32 hdc)
744 * Draws listview items when in small icon display mode.
747 * [I] HWND32 : window handle
748 * [I] HDC32 : device context handle
753 static VOID LISTVIEW_RefreshSmallIcon(HWND32 hwnd, HDC32 hdc)
760 * Draws listview items when in icon display mode.
763 * [I] HWND32 : window handle
764 * [I] HDC32 : device context handle
769 static VOID LISTVIEW_RefreshIcon(HWND32 hwnd, HDC32 hdc)
776 * Draws listview items.
779 * [I] HWND32 : window handle
780 * [I] HDC32 : device context handle
785 static VOID LISTVIEW_Refresh(HWND32 hwnd, HDC32 hdc)
787 LONG lStyle = GetWindowLong32A(hwnd, GWL_STYLE);
789 if (lStyle & LVS_LIST)
791 LISTVIEW_RefreshList(hwnd, hdc);
793 else if (lStyle & LVS_REPORT)
795 LISTVIEW_RefreshReport(hwnd, hdc);
797 else if (lStyle & LVS_SMALLICON)
799 LISTVIEW_RefreshSmallIcon(hwnd, hdc);
801 else if (lStyle & LVS_ICON)
803 LISTVIEW_RefreshIcon(hwnd, hdc);
810 * Calculates the approximate width and height of a given number of items.
813 * [I] HWND32 : window handle
814 * [I] INT32 : number of items
819 * Returns a DWORD. The width in the low word and the height in high word.
821 static LRESULT LISTVIEW_ApproximateViewRect(HWND32 hwnd, INT32 nItemCount,
822 WORD wWidth, WORD wHeight)
824 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLong32A(hwnd, 0);
825 LONG lStyle = GetWindowLong32A(hwnd, GWL_STYLE);
826 INT32 nItemCountPerColumn = 1;
827 INT32 nColumnCount = 0;
828 DWORD dwViewRect = 0;
830 if (nItemCount == -1)
831 nItemCount = infoPtr->nItemCount;
833 if (lStyle & LVS_LIST)
835 if (wHeight == 0xFFFF)
837 /* use current height */
838 wHeight = infoPtr->nHeight;
841 if (wHeight < infoPtr->nItemHeight)
843 wHeight = infoPtr->nItemHeight;
848 if (infoPtr->nItemHeight > 0)
850 nItemCountPerColumn = wHeight / infoPtr->nItemHeight;
851 if (nItemCountPerColumn == 0)
852 nItemCountPerColumn = 1;
854 if (nItemCount % nItemCountPerColumn != 0)
855 nColumnCount = nItemCount / nItemCountPerColumn;
857 nColumnCount = nItemCount / nItemCountPerColumn + 1;
861 wHeight = nItemCountPerColumn * infoPtr->nItemHeight + 2;
862 wWidth = nColumnCount * infoPtr->nColumnWidth + 2;
864 dwViewRect = MAKELONG(wWidth, wHeight);
866 else if (lStyle & LVS_REPORT)
870 else if (lStyle & LVS_SMALLICON)
874 else if (lStyle & LVS_ICON)
884 * Arranges listview items in icon display mode.
887 * [I] HWND32 : window handle
888 * [I] INT32 : alignment code
894 static LRESULT LISTVIEW_Arrange(HWND32 hwnd, INT32 nAlignCode)
896 /* LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLong32A(hwnd, 0); */
897 LONG lStyle = GetWindowLong32A(hwnd, GWL_STYLE);
898 BOOL32 bResult = FALSE;
900 if (lStyle & LVS_ICON)
921 /* << LISTVIEW_CreateDragImage >> */
925 * Removes all listview items.
928 * [I] HWND32 : window handle
934 static LRESULT LISTVIEW_DeleteAllItems(HWND32 hwnd)
936 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLong32A(hwnd, 0);
937 LONG lCtrlId = GetWindowLong32A(hwnd, GWL_ID);
938 LISTVIEW_ITEM *lpItem;
942 BOOL32 bResult = TRUE;
944 if (infoPtr->nItemCount > 0)
946 /* send LVN_DELETEALLITEMS notification */
947 ZeroMemory (&nmlv, sizeof (NMLISTVIEW));
948 nmlv.hdr.hwndFrom = hwnd;
949 nmlv.hdr.idFrom = lCtrlId;
950 nmlv.hdr.code = LVN_DELETEALLITEMS;
952 bNotify = !(BOOL32)SendMessage32A(GetParent32(hwnd), WM_NOTIFY,
953 (WPARAM32)lCtrlId, (LPARAM)&nmlv);
955 nmlv.hdr.code = LVN_DELETEITEM;
957 for (i = 0; i < infoPtr->nItemCount; i++)
961 /* send LVN_DELETEITEM notification */
963 SendMessage32A(GetParent32(hwnd), WM_NOTIFY, (WPARAM32)lCtrlId,
968 lpItem = (LISTVIEW_ITEM *)DPA_GetPtr(infoPtr->hdpaItems, i);
971 /* free item string */
972 if ((lpItem->pszText != NULL) &&
973 (lpItem->pszText != LPSTR_TEXTCALLBACK32A))
974 COMCTL32_Free (lpItem->pszText);
977 COMCTL32_Free (lpItem);
981 /* ???? needs follow up */
982 DPA_DeleteAllPtrs (infoPtr->hdpaItems);
984 /* reset item counter */
985 infoPtr->nItemCount = 0;
987 /* reset scrollbar */
988 LISTVIEW_SetScroll(hwnd);
996 * Removes a column from the listview control.
999 * [I] HWND32 : window handle
1000 * [I] INT32 : column index
1006 static LRESULT LISTVIEW_DeleteColumn(HWND32 hwnd, INT32 nColumn)
1008 /* LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLong32A(hwnd, 0); */
1011 /* if (infoPtr->nItemCount > 0) */
1013 /* if (!SendMessage32A(infoPtr->hwndHeader, HDM_DELETEITEM, wParam, 0)) */
1015 /* infoPtr->nColumnCount--; */
1016 /* FIXME (listview, "semi stub!\n"); */
1023 * Removes an item from the listview control.
1026 * [I] HWND32 : window handle
1027 * [I] INT32 : item index
1033 static LRESULT LISTVIEW_DeleteItem(HWND32 hwnd, INT32 nItem)
1035 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLong32A(hwnd, 0);
1036 LONG lCtrlId = GetWindowLong32A(hwnd, GWL_ID);
1037 LISTVIEW_ITEM *lpItem;
1039 BOOL32 bResult = FALSE;
1041 if ((nItem >= 0) && (nItem < infoPtr->nItemCount))
1043 /* send LVN_DELETEITEM notification */
1044 ZeroMemory (&nmlv, sizeof (NMLISTVIEW));
1045 nmlv.hdr.hwndFrom = hwnd;
1046 nmlv.hdr.idFrom = lCtrlId;
1047 nmlv.hdr.code = LVN_DELETEITEM;
1049 SendMessage32A(GetParent32(hwnd), WM_NOTIFY, (WPARAM32)lCtrlId,
1053 lpItem = (LISTVIEW_ITEM*)DPA_DeletePtr (infoPtr->hdpaItems, nItem);
1056 /* free item string */
1057 if ((lpItem->pszText != NULL) &&
1058 (lpItem->pszText != LPSTR_TEXTCALLBACK32A))
1059 COMCTL32_Free (lpItem->pszText);
1062 COMCTL32_Free (lpItem);
1065 /* decrement item counter */
1066 infoPtr->nItemCount--;
1068 /* reset some of the draw data */
1069 LISTVIEW_SetScroll(hwnd);
1077 /* << LISTVIEW_EditLabel >> */
1078 /* << LISTVIEW_EnsureVisible >> */
1082 * Searches for an item with specific characteristics.
1085 * [I] HWND32 : window handle
1086 * [I] INT32 : base item index
1087 * [I] LPLVFINDINFO : item information to look for
1090 * SUCCESS : index of item
1093 static LRESULT LISTVIEW_FindItem(HWND32 hwnd, INT32 nStart,
1094 LPLVFINDINFO lpFindInfo)
1096 /* LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLong32A(hwnd, 0); */
1097 /* LISTVIEW_ITEM *lpItem; */
1099 /* INT32 nEnd = infoPtr->nItemCount; */
1100 /* BOOL32 bWrap = FALSE; */
1101 /* if (nStart == -1) */
1105 /* if (lpFindInfo->flags & LVFI_PARAM) */
1107 /* for (nItem = nStart; nItem < nEnd; nItem++) */
1109 /* get item pointer */
1110 /* lpItem = (LISTVIEW_ITEM *)DPA_GetPtr(infoPtr->hdpaItems, nItem); */
1111 /* if (lpItem != NULL) */
1113 /* if (lpFindInfo->lParam == lpItem->lParam) */
1120 /* if (lpFindInfo->flags & LVFI_PARTIAL) */
1122 /* for (nItem = nStart; nItem < nEnd; nItem++) */
1124 /* get item pointer */
1125 /* lpItem = (LISTVIEW_ITEM *)DPA_GetPtr(infoPtr->hdpaItems, nItem); */
1128 /* if (strncmp(lpItem->pszText, lpFindInfo->psz, strlen(lpFindInfo->psz)) */
1135 /* if (lpFindInfo->flags & LVFI_STRING) */
1137 /* for (nItem = nStart; nItem < nEnd; nItem++) */
1139 /* get item pointer */
1140 /* lpItem = (LISTVIEW_ITEM *)DPA_GetPtr(infoPtr->hdpaItems, nItem); */
1141 /* if (lpItem != NULL) */
1143 /* if (strcmp(lpItem->pszText, lpFindInfo->psz) == 0) */
1149 /* if ((lpFindInfo->flags & LVFI_WRAP) && nStart) */
1151 /* nEnd = nStart; */
1156 /* bWrap = FALSE; */
1163 * Retrieves the background color of the listview control.
1166 * [I] HWND32 : window handle
1169 * COLORREF associated with the background.
1171 static LRESULT LISTVIEW_GetBkColor(HWND32 hwnd)
1173 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLong32A(hwnd, 0);
1175 return infoPtr->clrBk;
1180 * Retrieves the background image of the listview control.
1183 * [I] HWND32 : window handle
1184 * [O] LPLVMKBIMAGE : background image information
1190 /* static LRESULT LISTVIEW_GetBkImage(HWND32 hwnd, LPLVBKIMAGE lpBkImage) */
1195 /* << LISTVIEW_GetCallbackMask >> */
1199 * Retrieves column attributes.
1202 * [I] HWND32 : window handle
1203 * [I] INT32 : column index
1204 * [IO] LPLVCOLUMN32A : column information
1210 static LRESULT LISTVIEW_GetColumn32A(HWND32 hwnd, INT32 nIndex,
1211 LPLVCOLUMN32A lpColumn)
1213 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLong32A(hwnd, 0);
1216 if (lpColumn == NULL)
1219 ZeroMemory (&hdi, sizeof(HDITEM32A));
1221 if (lpColumn->mask & LVCF_FMT)
1222 hdi.mask |= HDI_FORMAT;
1224 if (lpColumn->mask & LVCF_WIDTH)
1225 hdi.mask |= HDI_WIDTH;
1227 if (lpColumn->mask & LVCF_TEXT)
1228 hdi.mask |= (HDI_TEXT | HDI_FORMAT);
1230 if (lpColumn->mask & LVCF_IMAGE)
1231 hdi.mask |= HDI_IMAGE;
1233 if (lpColumn->mask & LVCF_ORDER)
1234 hdi.mask |= HDI_ORDER;
1236 if (!SendMessage32A (infoPtr->hwndHeader, HDM_GETITEM32A,
1237 (WPARAM32)nIndex, (LPARAM)&hdi))
1240 if (lpColumn->mask & LVCF_FMT)
1244 if (hdi.fmt & HDF_LEFT)
1245 lpColumn->fmt |= LVCFMT_LEFT;
1246 else if (hdi.fmt & HDF_RIGHT)
1247 lpColumn->fmt |= LVCFMT_RIGHT;
1248 else if (hdi.fmt & HDF_CENTER)
1249 lpColumn->fmt |= LVCFMT_CENTER;
1251 if (hdi.fmt & HDF_IMAGE)
1252 lpColumn->fmt |= LVCFMT_COL_HAS_IMAGES;
1255 if (lpColumn->mask & LVCF_WIDTH)
1256 lpColumn->cx = hdi.cxy;
1258 if ((lpColumn->mask & LVCF_TEXT) && (lpColumn->pszText) && (hdi.pszText))
1259 lstrcpyn32A (lpColumn->pszText, hdi.pszText, lpColumn->cchTextMax);
1261 if (lpColumn->mask & LVCF_IMAGE)
1262 lpColumn->iImage = hdi.iImage;
1264 if (lpColumn->mask & LVCF_ORDER)
1265 lpColumn->iOrder = hdi.iOrder;
1270 /* << LISTVIEW_GetColumn32W >> */
1271 /* << LISTVIEW_GetColumnOrderArray >> */
1275 * Retrieves the column width when list or report display mode.
1278 * [I] HWND32 : window handle
1279 * [I] int32 : column index
1282 * SUCCESS : column width
1285 static LRESULT LISTVIEW_GetColumnWidth(HWND32 hwnd, INT32 nColumn)
1287 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLong32A(hwnd, 0);
1288 LONG lStyle = GetWindowLong32A(hwnd, GWL_STYLE);
1290 INT32 nColumnWidth = 0;
1292 if ((lStyle & LVS_LIST) || (lStyle & LVS_SMALLICON) || (lStyle & LVS_ICON))
1294 nColumnWidth = infoPtr->nColumnWidth;
1296 else if (lStyle & LVS_REPORT)
1298 /* verify validity of index */
1299 if ((nColumn >= 0) && (nColumn < infoPtr->nColumnCount))
1301 /* get column width from header */
1302 hdi.mask = HDI_WIDTH;
1303 if (SendMessage32A (infoPtr->hwndHeader, HDM_GETITEM32A,
1304 (WPARAM32)nColumn, (LPARAM)&hdi))
1305 nColumnWidth = hdi.cxy;
1309 return nColumnWidth;
1314 * In list or report display mode, retrieves the number of items that can fit
1315 * vertically in the visible area. In icon or small icon display mode,
1316 * retrieves the total number of visible items.
1319 * [I] HWND32 : window handle
1322 * Number of fully visible items.
1324 static LRESULT LISTVIEW_GetCountPerPage(HWND32 hwnd)
1326 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLong32A(hwnd, 0);
1327 LONG lStyle = GetWindowLong32A(hwnd, GWL_STYLE);
1328 INT32 nItemCount = 0;
1329 INT32 nItemCountPerRow = LISTVIEW_GetItemCountPerRow(hwnd);
1330 INT32 nItemCountPerColumn = LISTVIEW_GetItemCountPerColumn(hwnd);
1332 if (lStyle & LVS_LIST)
1334 if ((nItemCountPerRow > 0) && (nItemCountPerColumn > 0))
1336 nItemCount = nItemCountPerRow * nItemCountPerColumn;
1339 else if (lStyle & LVS_REPORT)
1341 nItemCount = nItemCountPerColumn;
1343 else if ((lStyle & LVS_SMALLICON) || (lStyle & LVS_ICON))
1345 nItemCount = infoPtr->nItemCount;
1351 /* << LISTVIEW_GetEditControl >> */
1352 /* << LISTVIEW_GetExtendedListViewStyle >> */
1356 * Retrieves a header handle.
1359 * [I] HWND32 : window handle
1364 static LRESULT LISTVIEW_GetHeader(HWND32 hwnd)
1366 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLong32A(hwnd, 0);
1368 return infoPtr->hwndHeader;
1371 /* << LISTVIEW_GetHotCursor >> */
1372 /* << LISTVIEW_GetHotItem >> */
1373 /* << LISTVIEW_GetHoverTime >> */
1377 * Retrieves an image list handle.
1380 * [I] HWND32 : window handle
1381 * [I] INT32 : image list identifier
1384 * SUCCESS : image list handle
1387 static LRESULT LISTVIEW_GetImageList(HWND32 hwnd, INT32 nImageList)
1389 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLong32A(hwnd, 0);
1390 HIMAGELIST himl = NULL;
1395 himl = infoPtr->himlNormal;
1397 himl = infoPtr->himlSmall;
1399 himl = infoPtr->himlState;
1402 return (LRESULT)himl;
1406 /* << LISTVIEW_GetISearchString >> */
1410 * Retrieves item attributes.
1413 * [I] HWND32 : window handle
1414 * [IO] LPLVITEM32A : item info
1420 static LRESULT LISTVIEW_GetItem32A(HWND32 hwnd, LPLVITEM32A lpItem)
1422 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLong32A(hwnd, 0);
1423 LISTVIEW_ITEM *lpListItem;
1424 BOOL32 bResult = FALSE;
1428 if ((lpItem->iItem >= 0) && (lpItem->iItem < infoPtr->nItemCount))
1431 lpListItem = DPA_GetPtr(infoPtr->hdpaItems, lpItem->iItem);
1432 if (lpListItem != NULL)
1434 /* not tested for subitem > 0 */
1435 lpListItem += lpItem->iSubItem;
1436 if (lpListItem != NULL)
1438 /* retrieve valid data */
1439 if (lpItem->mask & LVIF_STATE)
1440 lpItem->state = lpListItem->state & lpItem->stateMask;
1442 if (lpItem->mask & LVIF_TEXT)
1444 if (lpListItem->pszText == LPSTR_TEXTCALLBACK32A)
1445 lpItem->pszText = LPSTR_TEXTCALLBACK32A;
1447 Str_GetPtr32A(lpListItem->pszText, lpItem->pszText,
1448 lpItem->cchTextMax);
1451 if (lpItem->mask & LVIF_IMAGE)
1452 lpItem->iImage = lpListItem->iImage;
1454 if (lpItem->mask & LVIF_PARAM)
1455 lpItem->lParam = lpListItem->lParam;
1457 if (lpItem->mask & LVIF_INDENT)
1458 lpItem->iIndent = lpListItem->iIndent;
1469 /* << LISTVIEW_GetItem32W >> */
1470 /* << LISTVIEW_GetHotCursor >> */
1471 /* << LISTVIEW_GetHotItem >> */
1472 /* << LISTVIEW_GetHoverTime >> */
1476 * Retrieves the number of items in the listview control.
1479 * [I] HWND32 : window handle
1484 static LRESULT LISTVIEW_GetItemCount(HWND32 hwnd)
1486 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO*)GetWindowLong32A(hwnd, 0);
1488 return infoPtr->nItemCount;
1493 * Retrieves the position (upper-left) of the listview control item.
1496 * [I] HWND32 : window handle
1497 * [I] INT32 : item index
1498 * [O] LPPOINT32 : coordinate information
1504 static LRESULT LISTVIEW_GetItemPosition(HWND32 hwnd, INT32 nItem,
1507 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLong32A(hwnd, 0);
1508 LONG lStyle = GetWindowLong32A(hwnd, GWL_STYLE);
1511 BOOL32 bResult = FALSE;
1512 INT32 nItemCountPerColumn;
1513 INT32 nItemCountPerRow;
1517 if ((nItem >= 0) && (nItem < infoPtr->nItemCount) && (lpPt != NULL))
1519 if (lStyle & LVS_LIST)
1521 nItemCountPerColumn = LISTVIEW_GetItemCountPerColumn(hwnd);
1522 nItemCountPerRow = LISTVIEW_GetItemCountPerRow(hwnd);
1524 if ((nItemCountPerColumn > 0) && (nItemCountPerRow > 0))
1526 nFirstItem = LISTVIEW_GetFirstVisibleItem(hwnd);
1527 nLastItem = nFirstItem + nItemCountPerRow * nItemCountPerRow - 1;
1529 if ((nItem >= nFirstItem) || (nItem <= nLastItem))
1531 nItem -= nFirstItem;
1534 nColumn = nItem / nItemCountPerColumn;
1537 nRow = nItem % nItemCountPerColumn;
1539 /* X coordinate of the column */
1540 lpPt->x = nColumn * infoPtr->nColumnWidth;
1542 /* Y coordinate of the item */
1543 lpPt->y = nRow * infoPtr->nItemHeight;
1548 else if (lStyle & LVS_REPORT)
1552 else if (lStyle & LVS_SMALLICON)
1556 else if (lStyle & LVS_ICON)
1568 * Retrieves the bounding rectangle for a listview control item.
1571 * [I] HWND32 : window handle
1572 * [I] INT32 : item index
1573 * [IO] LPRECT32 : bounding rectangle coordinates
1579 static LRESULT LISTVIEW_GetItemRect(HWND32 hwnd, INT32 nItem, LPRECT32 lpRect)
1581 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLong32A(hwnd, 0);
1582 LISTVIEW_ITEM *lpItem;
1585 BOOL32 bResult = FALSE;
1586 INT32 nSmallIconWidth;
1588 nSmallIconWidth = GetSystemMetrics32(SM_CXSMICON);
1590 if ((nItem < 0) || (nItem >= infoPtr->nItemCount) || (lpRect == NULL))
1594 lpItem = (LISTVIEW_ITEM *)DPA_GetPtr(infoPtr->hdpaItems, nItem);
1598 if (!SendMessage32A(hwnd, LVM_GETITEMPOSITION, (WPARAM32)nItem, (LPARAM)&pt))
1601 nLabelWidth = SendMessage32A(hwnd, LVM_GETSTRINGWIDTH32A, (WPARAM32)0,
1602 (LPARAM)lpItem->pszText);
1603 switch(lpRect->left)
1606 lpRect->left = pt.x;
1608 lpRect->right = lpRect->left + nSmallIconWidth + nLabelWidth;
1609 lpRect->bottom = lpRect->top + infoPtr->nItemHeight;
1613 lpRect->left = pt.x;
1615 lpRect->right = lpRect->left + nSmallIconWidth;
1616 lpRect->bottom = lpRect->top + infoPtr->nItemHeight;
1620 lpRect->left = pt.x + nSmallIconWidth;
1622 lpRect->right = lpRect->left + nLabelWidth;
1623 lpRect->bottom = infoPtr->nItemHeight;
1626 case LVIR_SELECTBOUNDS:
1636 * Retrieves the spacing between listview control items.
1639 * [I] HWND32 : window handle
1640 * [I] BOOL32 : small icon (TRUE) or large icon (FALSE)
1643 * Horizontal + vertical spacing
1645 static LRESULT LISTVIEW_GetItemSpacing(HWND32 hwnd, BOOL32 bSmall)
1647 INT32 nSmallIconHSpacing;
1648 INT32 nSmallIconVSpacing;
1649 INT32 nIconHSpacing;
1650 INT32 nIconVSpacing;
1656 nSmallIconHSpacing = 0;
1657 nSmallIconVSpacing = 0;
1658 lResult = MAKELONG(nSmallIconHSpacing, nSmallIconVSpacing);
1662 nIconHSpacing = GetSystemMetrics32(SM_CXICONSPACING);
1663 nIconVSpacing = GetSystemMetrics32(SM_CYICONSPACING);
1664 lResult = MAKELONG(nIconHSpacing, nIconVSpacing);
1672 * Retrieves the state of a listview control item.
1675 * [I] HWND32 : window handle
1676 * [I] INT32 : item index
1677 * [I] UINT32 : state mask
1680 * State specified by the mask.
1682 static LRESULT LISTVIEW_GetItemState(HWND32 hwnd, INT32 nItem, UINT32 uMask)
1684 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLong32A(hwnd, 0);
1685 LISTVIEW_ITEM *lpItem;
1688 if ((nItem >= 0) && (nItem < infoPtr->nItemCount))
1690 lpItem = (LISTVIEW_ITEM *)DPA_GetPtr(infoPtr->hdpaItems, nItem);
1692 nState = lpItem->state & uMask;
1700 * Retrieves the text of a listview control item or subitem.
1703 * [I] HWND32 : window handle
1704 * [I] INT32 : item index
1705 * [IO] LPLVITEM32A : item information
1710 static VOID LISTVIEW_GetItemText32A(HWND32 hwnd, INT32 nItem,
1713 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLong32A(hwnd, 0);
1714 LISTVIEW_ITEM *lpListItem;
1716 if ((nItem < 0) || (nItem >= infoPtr->nItemCount) || (lpItem == NULL))
1719 lpListItem = (LISTVIEW_ITEM *)DPA_GetPtr(infoPtr->hdpaItems, nItem);
1720 if (lpListItem == NULL)
1723 lpListItem += lpItem->iSubItem;
1724 if (lpListItem == NULL)
1727 if (lpListItem->pszText == LPSTR_TEXTCALLBACK32A)
1728 lpItem->pszText = LPSTR_TEXTCALLBACK32A;
1730 Str_GetPtr32A(lpListItem->pszText, lpItem->pszText, lpItem->cchTextMax);
1735 * Searches for an item based on properties + relationships.
1738 * [I] HWND32 : window handle
1739 * [I] INT32 : item index
1740 * [I] UINT32 : relationship flag
1743 * SUCCESS : item index
1746 static LRESULT LISTVIEW_GetNextItem (HWND32 hwnd, INT32 nItem, UINT32 uFlags)
1748 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLong32A(hwnd, 0);
1751 /* start at begin */
1755 if ((nItem >= 0) && (nItem < infoPtr->nItemCount))
1763 /* << LISTVIEW_GetNumberOfWorkAreas >> */
1767 * Retrieves the current origin when in icon or small icon display mode.
1770 * [I] HWND32 : window handle
1771 * [O] LPPOINT32 : coordinate information
1777 static LRESULT LISTVIEW_GetOrigin(HWND32 hwnd, LPPOINT32 lpOrigin)
1779 LONG lStyle = GetWindowLong32A(hwnd, GWL_ID);
1780 BOOL32 bResult = FALSE;
1782 if (lStyle & LVS_SMALLICON)
1786 else if (lStyle & LVS_ICON)
1796 * Retrieves the number of items that are marked as selected.
1799 * [I] HWND32 : window handle
1802 * Number of items selected.
1804 static LRESULT LISTVIEW_GetSelectedCount(HWND32 hwnd)
1806 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLong32A(hwnd, 0);
1807 LISTVIEW_ITEM *lpItem;
1808 INT32 nSelectedCount = 0;
1811 for (i = 0; i < infoPtr->nItemCount; i++)
1813 lpItem = (LISTVIEW_ITEM *)DPA_GetPtr(infoPtr->hdpaItems, i);
1816 if (lpItem->state & LVIS_SELECTED)
1821 return nSelectedCount;
1826 * Retrieves item index that marks the start of a multiple selection.
1829 * [I] HWND32 : window handle
1832 * Index number or -1 if there is no selection mark.
1834 static LRESULT LISTVIEW_GetSelectionMark(HWND32 hwnd)
1836 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLong32A(hwnd, 0);
1839 if (SendMessage32A(hwnd, LVM_GETSELECTEDCOUNT, (WPARAM32)0, (LPARAM)0) != 0)
1840 nResult = infoPtr->nSelectionMark;
1847 * Retrieves the width of a string.
1850 * [I] HWND32 : window handle
1853 * SUCCESS : string width (in pixels)
1856 static LRESULT LISTVIEW_GetStringWidth32A(HWND32 hwnd, LPCSTR lpsz)
1858 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLong32A(hwnd, 0);
1859 HFONT32 hFont, hOldFont;
1866 hFont = infoPtr->hFont ? infoPtr->hFont : GetStockObject32 (SYSTEM_FONT);
1867 hdc = GetDC32(hwnd);
1868 hOldFont = SelectObject32 (hdc, hFont);
1869 GetTextExtentPoint32A(hdc, lpsz, lstrlen32A(lpsz), &textSize);
1870 SelectObject32 (hdc, hOldFont);
1871 ReleaseDC32(hwnd, hdc);
1872 nResult = textSize.cx;
1880 * Retrieves the text backgound color.
1883 * [I] HWND32 : window handle
1886 * COLORREF associated with the the background.
1888 static LRESULT LISTVIEW_GetTextBkColor(HWND32 hwnd)
1890 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO*)GetWindowLong32A(hwnd, 0);
1892 return infoPtr->clrTextBk;
1897 * Retrieves the text color.
1900 * [I] HWND32 : window handle
1903 * COLORREF associated with the text.
1905 static LRESULT LISTVIEW_GetTextColor(HWND32 hwnd)
1907 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO*)GetWindowLong32A(hwnd, 0);
1909 return infoPtr->clrText;
1914 * Retrieves the bounding rectangle of all the items.
1917 * [I] HWND32 : window handle
1918 * [O] LPRECT32 : bounding rectangle
1924 static LRESULT LISTVIEW_GetViewRect(HWND32 hwnd, LPRECT32 lpBoundingRect)
1926 /* LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLong32A(hwnd, 0); */
1927 LONG lStyle = GetWindowLong32A(hwnd, GWL_STYLE);
1928 BOOL32 bResult = FALSE;
1930 if (lpBoundingRect != NULL)
1932 if ((lStyle & LVS_ICON) || (lStyle & LVS_SMALLICON))
1943 * Determines item index when in small icon view.
1946 * [I] HWND32 : window handle
1947 * [IO] LPLVHITTESTINFO : hit test information
1950 * SUCCESS : item index
1953 static LRESULT HitTestSmallIconView(HWND32 hwnd, LPLVHITTESTINFO lpHitTestInfo)
1955 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLong32A(hwnd, 0);
1956 LISTVIEW_ITEM *lpItem;
1963 INT32 nSmallIconWidth;
1964 INT32 nItemCountPerRow;
1967 nColumn = lpHitTestInfo->pt.x / infoPtr->nColumnWidth;
1970 nRow = lpHitTestInfo->pt.y / infoPtr->nItemHeight;
1972 /* calculate offset from start of column (in pixels) */
1973 nOffset = lpHitTestInfo->pt.x % infoPtr->nColumnWidth;
1975 /* get recommended width of a small icon */
1976 nSmallIconWidth = GetSystemMetrics32(SM_CXSMICON);
1978 /* calculate index */
1979 nItemCountPerRow = LISTVIEW_GetItemCountPerRow(hwnd);
1980 nItem = nRow * nItemCountPerRow + LISTVIEW_GetFirstVisibleItem(hwnd) + nColumn;
1982 /* verify existance of item */
1983 if (nItem < infoPtr->nItemCount)
1986 lpItem = (LISTVIEW_ITEM *)DPA_GetPtr(infoPtr->hdpaItems, nItem);
1989 if (infoPtr->himlState != NULL)
1991 nPosX += nSmallIconWidth;
1992 if (nOffset <= nPosX)
1994 lpHitTestInfo->flags = LVHT_ONITEMSTATEICON | LVHT_ONITEM;
1995 lpHitTestInfo->iItem = nItem;
1996 lpHitTestInfo->iSubItem = 0;
2001 if (infoPtr->himlSmall != NULL)
2003 nPosX += nSmallIconWidth;
2004 if (nOffset <= nPosX)
2006 lpHitTestInfo->flags = LVHT_ONITEMICON | LVHT_ONITEM;
2007 lpHitTestInfo->iItem = nItem;
2008 lpHitTestInfo->iSubItem = 0;
2013 /* get width of label in pixels */
2014 nLabelWidth = SendMessage32A(hwnd, LVM_GETSTRINGWIDTH32A, (WPARAM32)0,
2015 (LPARAM)lpItem->pszText);
2016 nLabelWidth += nPosX;
2018 if (nOffset <= nLabelWidth)
2020 lpHitTestInfo->flags = LVHT_ONITEMLABEL | LVHT_ONITEM;
2021 lpHitTestInfo->iItem = nItem;
2022 lpHitTestInfo->iSubItem = 0;
2028 /* hit is not on an item */
2029 lpHitTestInfo->flags = LVHT_NOWHERE;
2036 * Determines item index when in list display mode.
2039 * [I] HWND32 : window handle
2040 * [IO] LPLVHITTESTINFO : hit test information
2043 * SUCCESS : item index
2046 static LRESULT HitTestListView(HWND32 hwnd, LPLVHITTESTINFO lpHitTestInfo)
2048 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLong32A(hwnd, 0);
2049 LISTVIEW_ITEM *lpItem;
2056 INT32 nSmallIconWidth;
2057 INT32 nItemCountPerColumn;
2060 nColumn = lpHitTestInfo->pt.x / infoPtr->nColumnWidth;
2063 nRow = lpHitTestInfo->pt.y / infoPtr->nItemHeight;
2065 /* calculate offset from start of column (in pixels) */
2066 nOffset = lpHitTestInfo->pt.x % infoPtr->nColumnWidth;
2068 /* get recommended width of a small icon */
2069 nSmallIconWidth = GetSystemMetrics32(SM_CXSMICON);
2071 /* calculate index */
2072 nItemCountPerColumn = LISTVIEW_GetItemCountPerColumn(hwnd);
2073 nItem = (nColumn * nItemCountPerColumn + LISTVIEW_GetFirstVisibleItem(hwnd)
2076 /* verify existance of item */
2077 if (nItem < infoPtr->nItemCount)
2080 lpItem = (LISTVIEW_ITEM *)DPA_GetPtr(infoPtr->hdpaItems, nItem);
2083 if (infoPtr->himlState != NULL)
2085 nPosX += nSmallIconWidth;
2086 if (nOffset <= nPosX)
2088 lpHitTestInfo->flags = LVHT_ONITEMSTATEICON | LVHT_ONITEM;
2089 lpHitTestInfo->iItem = nItem;
2090 lpHitTestInfo->iSubItem = 0;
2095 if (infoPtr->himlSmall != NULL)
2097 nPosX += nSmallIconWidth;
2098 if (nOffset <= nPosX)
2100 lpHitTestInfo->flags = LVHT_ONITEMICON | LVHT_ONITEM;
2101 lpHitTestInfo->iItem = nItem;
2102 lpHitTestInfo->iSubItem = 0;
2107 /* get width of label in pixels */
2108 nLabelWidth = SendMessage32A(hwnd, LVM_GETSTRINGWIDTH32A, (WPARAM32)0,
2109 (LPARAM)lpItem->pszText);
2110 nLabelWidth += nPosX;
2112 if (nOffset <= nLabelWidth)
2114 lpHitTestInfo->flags = LVHT_ONITEMLABEL | LVHT_ONITEM;
2115 lpHitTestInfo->iItem = nItem;
2116 lpHitTestInfo->iSubItem = 0;
2122 /* hit is not on an item */
2123 lpHitTestInfo->flags = LVHT_NOWHERE;
2130 * Determines wich listview item is located at the specified position.
2133 * [I] HWND32 : window handle
2134 * [IO} LPLVHITTESTINFO : hit test information
2137 * SUCCESS : item index
2140 static LRESULT LISTVIEW_HitTest(HWND32 hwnd, LPLVHITTESTINFO lpHitTestInfo)
2142 LONG lStyle = GetWindowLong32A(hwnd, GWL_STYLE);
2144 if (lStyle & LVS_LIST)
2145 return HitTestListView(hwnd, lpHitTestInfo);
2146 else if (lStyle & LVS_REPORT)
2150 else if (lStyle & LVS_SMALLICON)
2152 return HitTestSmallIconView(hwnd, lpHitTestInfo);
2154 else if (lStyle & LVS_ICON)
2164 * Inserts a new column.
2167 * [I] HWND32 : window handle
2168 * [I] INT32 : column index
2169 * [I] LPLVCOLUMN32A : column information
2172 * SUCCESS : new column index
2175 static LRESULT LISTVIEW_InsertColumn32A(HWND32 hwnd, INT32 nIndex,
2176 LPLVCOLUMN32A lpColumn)
2178 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO*)GetWindowLong32A(hwnd, 0);
2182 if ((lpColumn == NULL) || (infoPtr->nItemCount > 0))
2185 FIXME (listview, "(%d %p): semi stub!\n", nIndex, lpColumn);
2187 /* initialize memory */
2188 ZeroMemory (&hdi, sizeof(HDITEM32A));
2190 if (lpColumn->mask & LVCF_FMT)
2193 hdi.fmt |= HDF_LEFT;
2194 else if (lpColumn->fmt & LVCFMT_LEFT)
2195 hdi.fmt |= HDF_LEFT;
2196 else if (lpColumn->fmt & LVCFMT_RIGHT)
2197 hdi.fmt |= HDF_RIGHT;
2198 else if (lpColumn->fmt & LVCFMT_CENTER)
2199 hdi.fmt |= HDF_CENTER;
2200 if (lpColumn->fmt & LVCFMT_COL_HAS_IMAGES)
2201 hdi.fmt |= HDF_IMAGE;
2203 hdi.mask |= HDI_FORMAT;
2206 if (lpColumn->mask & LVCF_WIDTH)
2208 hdi.mask |= HDI_WIDTH;
2209 hdi.cxy = lpColumn->cx;
2212 if (lpColumn->mask & LVCF_TEXT)
2214 hdi.mask |= (HDI_TEXT | HDI_FORMAT);
2215 hdi.pszText = lpColumn->pszText;
2216 hdi.fmt |= HDF_STRING;
2219 if (lpColumn->mask & LVCF_IMAGE)
2221 hdi.mask |= HDI_IMAGE;
2222 hdi.iImage = lpColumn->iImage;
2225 if (lpColumn->mask & LVCF_ORDER)
2227 hdi.mask |= HDI_ORDER;
2228 hdi.iOrder = lpColumn->iOrder;
2231 nResult = SendMessage32A (infoPtr->hwndHeader, HDM_INSERTITEM32A,
2232 (WPARAM32)nIndex, (LPARAM)&hdi);
2236 /* increment column counter */
2237 infoPtr->nColumnCount++;
2242 /* << LISTVIEW_InsertColumn32W >> */
2246 * Inserts a new item in the listview control.
2249 * [I] HWND32 : window handle
2250 * [I] LPLVITEM32A : item information
2253 * SUCCESS : new item index
2256 static LRESULT LISTVIEW_InsertItem32A(HWND32 hwnd, LPLVITEM32A lpItem)
2258 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLong32A(hwnd, 0);
2259 LONG lStyle = GetWindowLong32A(hwnd, GWL_STYLE);
2260 LONG lCtrlId = GetWindowLong32A(hwnd, GWL_ID);
2261 LISTVIEW_ITEM *lpListItem;
2265 INT32 nColumnWidth = 0;
2266 INT32 nSmallIconWidth;
2271 if (lpItem->iSubItem != 0)
2274 /* allocate memory */
2275 lpListItem = (LISTVIEW_ITEM *)COMCTL32_Alloc(sizeof(LISTVIEW_ITEM));
2276 if (lpListItem == NULL)
2279 nSmallIconWidth = GetSystemMetrics32(SM_CXSMICON);
2281 /* initialize listview control item */
2282 ZeroMemory(lpListItem, sizeof(LISTVIEW_ITEM));
2284 /* copy only valid data */
2285 if (lpItem->mask & LVIF_TEXT)
2287 if (lpItem->pszText == LPSTR_TEXTCALLBACK32A)
2289 if ((lStyle & LVS_SORTASCENDING) || (lStyle & LVS_SORTDESCENDING))
2292 lpListItem->pszText = LPSTR_TEXTCALLBACK32A;
2296 nColumnWidth = SendMessage32A(hwnd, LVM_GETSTRINGWIDTH32A,
2297 (WPARAM32)0, (LPARAM)lpItem->pszText);
2299 /* add padding for separating columns */
2302 /* calculate column width; make sure it's at least 96 pixels */
2303 if (nColumnWidth < 96)
2306 Str_SetPtr32A(&lpListItem->pszText, lpItem->pszText);
2310 if (lpItem->mask & LVIF_STATE)
2312 if (lpItem->stateMask & LVIS_FOCUSED)
2314 /* clear LVIS_FOCUSED states */
2315 ZeroMemory(&lvItem, sizeof(LVITEM32A));
2316 lvItem.stateMask = LVIS_FOCUSED;
2318 SendMessage32A(hwnd, LVM_SETITEMSTATE, (WPARAM32)-1, (LPARAM)&lvItem);
2320 /* set focused item index */
2321 infoPtr->nFocusedItem = lpItem->iItem;
2324 lpListItem->state = lpItem->state & lpItem->stateMask;
2327 if (lpItem->mask & LVIF_IMAGE)
2328 lpListItem->iImage = lpItem->iImage;
2330 if (lpItem->mask & LVIF_PARAM)
2331 lpListItem->lParam = lpItem->lParam;
2333 if (lpItem->mask & LVIF_INDENT)
2334 lpListItem->iIndent = lpItem->iIndent;
2336 /* insert item in listview control data structure */
2337 nItem = DPA_InsertPtr(infoPtr->hdpaItems, lpItem->iItem, lpListItem);
2341 /* increment item counter */
2342 infoPtr->nItemCount++;
2344 /* calculate column width */
2345 if (infoPtr->himlSmall != NULL)
2346 nColumnWidth += nSmallIconWidth;
2348 /* calculate column width */
2349 if (infoPtr->himlState != NULL)
2350 nColumnWidth += nSmallIconWidth;
2352 /* set column width */
2353 if (nColumnWidth > infoPtr->nColumnWidth)
2354 infoPtr->nColumnWidth = nColumnWidth;
2356 /* set drawing data */
2357 LISTVIEW_SetScroll(hwnd);
2359 /* send LVN_INSERTITEM notification */
2360 ZeroMemory (&nmlv, sizeof (NMLISTVIEW));
2361 nmlv.hdr.hwndFrom = hwnd;
2362 nmlv.hdr.idFrom = lCtrlId;
2363 nmlv.hdr.code = LVN_INSERTITEM;
2365 SendMessage32A(GetParent32 (hwnd), WM_NOTIFY, (WPARAM32)lCtrlId,
2368 InvalidateRect32(hwnd, NULL, FALSE);
2369 UpdateWindow32(hwnd);
2374 /* << LISTVIEW_InsertItem32W >> */
2378 * Redraws a range of items.
2381 * [I] HWND32 : window handle
2382 * [I] INT32 : first item
2383 * [I] INT32 : last item
2389 static LRESULT LISTVIEW_RedrawItems(HWND32 hwnd, INT32 nFirst, INT32 nLast)
2391 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLong32A(hwnd, 0);
2396 if ((nFirst < 0) || (nFirst >= infoPtr->nItemCount))
2399 if ((nLast < 0) || (nLast >= infoPtr->nItemCount))
2409 * Scrolls the content of a listview.
2412 * [I] HWND32 : window handle
2413 * [I] INT32 : amount of horizontal scrolling
2414 * [I] INT32 : amount of vertical scrolling
2420 static LRESULT LISTVIEW_Scroll(HWND32 hwnd, INT32 nHScroll, INT32 nVScroll)
2422 LONG lStyle = GetWindowLong32A(hwnd, GWL_STYLE);
2423 BOOL32 bResult = FALSE;
2428 if (lStyle & LVS_LIST)
2430 nHScrollPos = GetScrollPos32(hwnd, SB_HORZ);
2431 GetScrollRange32(hwnd, SB_HORZ, &nMinRange, &nMaxRange);
2433 if ((nMinRange <= nHScrollPos + nHScroll) &&
2434 (nHScrollPos + nHScroll <= nMaxRange))
2437 nHScrollPos += nHScroll;
2438 SetScrollPos32(hwnd, SB_HORZ, nHScrollPos, TRUE);
2440 /* refresh client area */
2441 InvalidateRect32(hwnd, NULL, TRUE);
2442 UpdateWindow32(hwnd);
2445 else if (lStyle & LVS_REPORT)
2449 else if (lStyle & LVS_SMALLICON)
2453 else if (lStyle & LVS_ICON)
2463 * Sets the background color.
2466 * [I] HWND32 : window handle
2467 * [I] COLORREF : background color
2473 static LRESULT LISTVIEW_SetBkColor(HWND32 hwnd, COLORREF clrBk)
2475 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLong32A(hwnd, 0);
2477 infoPtr->clrBk = clrBk;
2478 InvalidateRect32(hwnd, NULL, TRUE);
2485 * Sets column attributes.
2488 * [I] HWND32 : window handle
2489 * [I] INT32 : column index
2490 * [I] LPLVCOLUMN32A : column information
2496 static LRESULT LISTVIEW_SetColumn32A(HWND32 hwnd, INT32 nIndex,
2497 LPLVCOLUMN32A lpColumn)
2499 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLong32A(hwnd, 0);
2502 if (lpColumn == NULL)
2505 /* initialize memory */
2506 ZeroMemory (&hdi, sizeof(HDITEM32A));
2508 if (lpColumn->mask & LVCF_FMT)
2511 hdi.fmt |= HDF_LEFT;
2512 else if (lpColumn->fmt & LVCFMT_LEFT)
2513 hdi.fmt |= HDF_LEFT;
2514 else if (lpColumn->fmt & LVCFMT_RIGHT)
2515 hdi.fmt |= HDF_RIGHT;
2516 else if (lpColumn->fmt & LVCFMT_CENTER)
2517 hdi.fmt |= HDF_CENTER;
2519 if (lpColumn->fmt & LVCFMT_COL_HAS_IMAGES)
2520 hdi.fmt |= HDF_IMAGE;
2522 hdi.mask |= HDI_FORMAT;
2525 if (lpColumn->mask & LVCF_WIDTH)
2527 hdi.mask |= HDI_WIDTH;
2528 hdi.cxy = lpColumn->cx;
2531 if (lpColumn->mask & LVCF_TEXT)
2533 hdi.mask |= (HDI_TEXT | HDI_FORMAT);
2534 hdi.pszText = lpColumn->pszText;
2535 hdi.fmt |= HDF_STRING;
2538 if (lpColumn->mask & LVCF_IMAGE)
2540 hdi.mask |= HDI_IMAGE;
2541 hdi.iImage = lpColumn->iImage;
2544 if (lpColumn->mask & LVCF_ORDER)
2546 hdi.mask |= HDI_ORDER;
2547 hdi.iOrder = lpColumn->iOrder;
2550 return (LRESULT)SendMessage32A (infoPtr->hwndHeader, HDM_SETITEM32A,
2551 (WPARAM32)nIndex, (LPARAM)&hdi);
2559 * [I] HWND32 : window handle
2560 * [I] INT32 : image list type
2561 * [I] HIMAGELIST : image list handle
2564 * SUCCESS : old image list
2567 static LRESULT LISTVIEW_SetImageList(HWND32 hwnd, INT32 nType, HIMAGELIST himl)
2569 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLong32A(hwnd, 0);
2570 HIMAGELIST himlTemp = 0;
2575 himlTemp = infoPtr->himlNormal;
2576 infoPtr->himlNormal = himl;
2577 return (LRESULT)himlTemp;
2579 himlTemp = infoPtr->himlSmall;
2580 infoPtr->himlSmall = himl;
2581 return (LRESULT)himlTemp;
2583 himlTemp = infoPtr->himlState;
2584 infoPtr->himlState = himl;
2585 return (LRESULT)himlTemp;
2588 return (LRESULT)NULL;
2594 * Sets item attributes.
2597 * [I] HWND32 : window handle
2598 * [I] LPLVITEM32 : item information
2604 static LRESULT LISTVIEW_SetItem32A(HWND32 hwnd, LPLVITEM32A lpItem)
2606 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLong32A(hwnd, 0);
2607 LONG lCtrlId = GetWindowLong32A(hwnd, GWL_ID);
2608 LISTVIEW_ITEM *lpListItem;
2614 if ((lpItem->iItem < 0) || (lpItem->iItem >= infoPtr->nItemCount))
2617 /* send LVN_ITEMCHANGING notification */
2618 ZeroMemory (&nmlv, sizeof (NMLISTVIEW));
2619 nmlv.hdr.hwndFrom = hwnd;
2620 nmlv.hdr.idFrom = lCtrlId;
2621 nmlv.hdr.code = LVN_ITEMCHANGING;
2622 nmlv.iItem = lpItem->iItem;
2623 nmlv.iSubItem = lpItem->iSubItem;
2624 nmlv.uChanged = lpItem->mask;
2625 if (SendMessage32A(GetParent32(hwnd), WM_NOTIFY, (WPARAM32)lCtrlId,
2626 (LPARAM)&nmlv) == FALSE)
2630 lpListItem = DPA_GetPtr(infoPtr->hdpaItems, lpItem->iItem);
2631 if (lpListItem == NULL)
2634 /* copy valid data */
2635 if (lpItem->iSubItem > 0)
2637 /* verify existance of sub-item */
2638 lpListItem += lpItem->iSubItem;
2639 if (lpListItem == NULL)
2642 /* exit if indent attribute is valid */
2643 if (lpItem->mask & LVIF_INDENT)
2646 if (lpItem->mask & LVIF_IMAGE)
2648 /* set sub-item attribute */
2654 if (lpItem->mask & LVIF_STATE)
2656 lpListItem->state &= ~lpItem->stateMask;
2657 lpListItem->state |= (lpItem->state & lpItem->stateMask);
2660 if (lpItem->mask & LVIF_IMAGE)
2661 lpListItem->iImage = lpItem->iImage;
2663 if (lpItem->mask & LVIF_PARAM)
2664 lpListItem->lParam = lpItem->lParam;
2666 if (lpItem->mask & LVIF_INDENT)
2667 lpListItem->iIndent = lpItem->iIndent;
2670 if (lpItem->mask & LVIF_TEXT)
2672 if (lpItem->pszText == LPSTR_TEXTCALLBACK32A)
2674 if ((lpListItem->pszText != NULL) &&
2675 (lpListItem->pszText != LPSTR_TEXTCALLBACK32A))
2676 COMCTL32_Free (lpListItem->pszText);
2678 lpListItem->pszText = LPSTR_TEXTCALLBACK32A;
2682 if (lpListItem->pszText == LPSTR_TEXTCALLBACK32A)
2683 lpListItem->pszText = NULL;
2685 if (Str_SetPtr32A(&lpListItem->pszText, lpItem->pszText) == FALSE)
2690 /* send LVN_ITEMCHANGED notification */
2691 nmlv.hdr.code = LVN_ITEMCHANGED;
2692 SendMessage32A(GetParent32(hwnd), WM_NOTIFY, (WPARAM32)lCtrlId,
2698 /* << LISTVIEW_SetItem32W >> */
2700 /* LISTVIEW_SetItemCount*/
2704 * Sets item position.
2707 * [I] HWND32 : window handle
2708 * [I] INT32 : item index
2709 * [I] INT32 : x coordinate
2710 * [I] INT32 : y coordinate
2716 static LRESULT LISTVIEW_SetItemPosition(HWND32 hwnd, INT32 nItem,
2717 INT32 nPosX, INT32 nPosY)
2719 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO*)GetWindowLong32A(hwnd, 0);
2720 LONG lStyle = GetWindowLong32A(hwnd, GWL_STYLE);
2722 if ((nItem < 0) || (nItem >= infoPtr->nItemCount))
2725 if ((lStyle & LVS_ICON) && (lStyle & LVS_SMALLICON))
2729 /* set position of item */
2732 if (lStyle & LVS_AUTOARRANGE)
2734 InvalidateRect32(hwnd, NULL, FALSE);
2735 UpdateWindow32(hwnd);
2746 * Sets the state of one or many items.
2749 * [I] HWND32 : window handle
2750 * [I]INT32 : item index
2751 * [I] LPLVITEM32 : item information
2757 static LRESULT LISTVIEW_SetItemState(HWND32 hwnd, INT32 nItem,
2760 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLong32A(hwnd, 0);
2761 LISTVIEW_ITEM *lpListItem;
2766 /* apply to all the items */
2767 for (i = 0; i< infoPtr->nItemCount; i++)
2769 lpListItem = (LISTVIEW_ITEM *)DPA_GetPtr(infoPtr->hdpaItems, i);
2770 if (lpListItem == NULL)
2773 lpListItem->state &= ~lpItem->stateMask;
2774 lpListItem->state |= (lpItem->state & lpItem->stateMask);
2777 else if ((nItem >= 0) && (nItem < infoPtr->nItemCount))
2779 lpListItem = (LISTVIEW_ITEM *)DPA_GetPtr(infoPtr->hdpaItems, nItem);
2780 if (lpListItem == NULL)
2784 lpListItem->state &= ~lpItem->stateMask;
2785 lpListItem->state |= (lpItem->state & lpItem->stateMask);
2795 * Sets the text background color.
2798 * [I] HWND32 : window handle
2799 * [I] COLORREF : text background color
2805 static LRESULT LISTVIEW_SetTextBkColor(HWND32 hwnd, COLORREF clrTextBk)
2807 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLong32A(hwnd, 0);
2809 infoPtr->clrTextBk = clrTextBk;
2816 * Sets the text background color.
2819 * [I] HWND32 : window handle
2820 * [I] COLORREF : text color
2826 static LRESULT LISTVIEW_SetTextColor (HWND32 hwnd, COLORREF clrText)
2828 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLong32A(hwnd, 0);
2830 infoPtr->clrText = clrText;
2840 * [I] HWND32 : window handle
2846 static LRESULT LISTVIEW_SortItems(HWND32 hwnd, WPARAM32 wParam, LPARAM lParam)
2848 /* LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO*)GetWindowLong32A(hwnd, 0); */
2850 FIXME (listview, "empty stub!\n");
2860 * [I] HWND32 : window handle
2861 * [I] INT32 : item index
2867 static LRESULT LISTVIEW_Update(HWND32 hwnd, INT32 nItem)
2869 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO*)GetWindowLong32A(hwnd, 0);
2870 LONG lStyle = GetWindowLong32A(hwnd, GWL_STYLE);
2872 BOOL32 bResult = FALSE;
2874 if ((nItem >= 0) || (nItem < infoPtr->nItemCount))
2876 /* get item bounding rectangle */
2877 rcItemRect.left = LVIR_BOUNDS;
2878 SendMessage32A(hwnd, LVM_GETITEMRECT, (WPARAM32)nItem,
2879 (LPARAM)&rcItemRect);
2881 InvalidateRect32(hwnd, &rcItemRect, FALSE);
2883 /* rearrange with default alignment style */
2884 if ((lStyle & LVS_AUTOARRANGE) &&
2885 ((lStyle & LVS_ICON) || (lStyle & LVS_SMALLICON)))
2886 SendMessage32A(hwnd, LVM_ARRANGE, (WPARAM32)LVA_DEFAULT, (LPARAM)0);
2894 * Creates a listview control.
2897 * [I] HWND32 : window handle
2902 static LRESULT LISTVIEW_Create(HWND32 hwnd, WPARAM32 wParam, LPARAM lParam)
2904 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLong32A(hwnd, 0);
2905 LONG lStyle = GetWindowLong32A(hwnd, GWL_STYLE);
2910 INT32 nSmallIconHeight;
2912 /* initialize color information */
2913 infoPtr->clrBk = GetSysColor32(COLOR_WINDOW);
2914 infoPtr->clrText = GetSysColor32(COLOR_WINDOWTEXT);
2915 infoPtr->clrTextBk = GetSysColor32(COLOR_WINDOW);
2917 /* get default font (icon title) */
2918 SystemParametersInfo32A (SPI_GETICONTITLELOGFONT, 0, &logFont, 0);
2919 infoPtr->hDefaultFont = CreateFontIndirect32A (&logFont);
2920 infoPtr->hFont = infoPtr->hDefaultFont;
2922 /* initialize column width */
2923 infoPtr->nColumnWidth = 96;
2925 /* get text height */
2926 hdc = GetDC32(hwnd);
2927 hOldFont = SelectObject32(hdc, infoPtr->hFont);
2928 GetTextMetrics32A(hdc, &tm);
2930 /* initialize item height with padding */
2931 if (!(lStyle & LVS_ICON))
2933 nSmallIconHeight = GetSystemMetrics32(SM_CYSMICON);
2934 infoPtr->nItemHeight = max(tm.tmHeight, nSmallIconHeight) + 2;
2937 SelectObject32(hdc, hOldFont);
2938 ReleaseDC32(hwnd, hdc);
2941 infoPtr->hwndHeader = CreateWindow32A(WC_HEADER32A, "", lStyle, 0, 0, 0, 0,
2943 GetWindowLong32A(hwnd, GWL_HINSTANCE),
2945 /* set header font */
2946 SendMessage32A(infoPtr->hwndHeader, WM_SETFONT, (WPARAM32)infoPtr->hFont,
2949 /* allocate memory */
2950 infoPtr->hdpaItems = DPA_Create (10);
2957 LISTVIEW_Destroy (HWND32 hwnd, WPARAM32 wParam, LPARAM lParam)
2959 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO*)GetWindowLong32A(hwnd, 0);
2961 /* delete all items */
2962 LISTVIEW_DeleteAllItems(hwnd);
2965 DPA_Destroy (infoPtr->hdpaItems);
2967 /* destroy header */
2968 if (infoPtr->hwndHeader)
2969 DestroyWindow32 (infoPtr->hwndHeader);
2972 infoPtr->hFont = (HFONT32)0;
2973 if (infoPtr->hDefaultFont)
2974 DeleteObject32 (infoPtr->hDefaultFont);
2976 infoPtr->nColumnWidth = 96;
2983 * Erases the background of the listview control
2986 * [I] HWND32 : window handle
2992 static LRESULT LISTVIEW_EraseBackground(HWND32 hwnd, WPARAM32 wParam, LPARAM lParam)
2994 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLong32A(hwnd, 0);
2997 if (infoPtr->clrBk == CLR_NONE)
2998 bResult = SendMessage32A(GetParent32(hwnd), WM_ERASEBKGND, wParam, lParam);
3001 HBRUSH32 hBrush = CreateSolidBrush32(infoPtr->clrBk);
3004 GetClientRect32(hwnd, &clientRect);
3005 FillRect32((HDC32)wParam, &clientRect, hBrush);
3006 DeleteObject32(hBrush);
3015 * Gets the listview control font.
3018 * [I] HWND32 : window handle
3023 static LRESULT LISTVIEW_GetFont(HWND32 hwnd)
3025 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLong32A(hwnd, 0);
3027 return infoPtr->hFont;
3032 * Performs horizontal scrolling.
3035 * [I] HWND32 : window handle
3036 * [I] INT32 : scroll code
3037 * [I] INT32 : scroll position
3038 * [I] HWND32 : scrollbar control window handle
3043 static LRESULT LISTVIEW_HScroll(HWND32 hwnd, INT32 nScrollCode,
3044 INT32 nScrollPos, HWND32 hScrollWnd)
3046 LONG lStyle = GetWindowLong32A(hwnd, GWL_STYLE);
3051 GetScrollRange32(hwnd, SB_HORZ, &nMinRange, &nMaxRange);
3052 nHScrollPos = GetScrollPos32(hwnd, SB_HORZ);
3054 if (lStyle & LVS_LIST)
3056 switch (nScrollCode)
3059 if (nHScrollPos > nMinRange)
3063 if (nHScrollPos < nMaxRange)
3067 if (nHScrollPos > nMinRange)
3071 if (nHScrollPos < nMaxRange)
3074 case SB_THUMBPOSITION:
3075 nHScrollPos = nScrollPos;
3079 SetScrollPos32(hwnd, SB_HORZ, nHScrollPos, TRUE);
3081 /* refresh client area */
3082 InvalidateRect32(hwnd, NULL, TRUE);
3083 UpdateWindow32(hwnd);
3094 * [I] HWND32 : window handle
3095 * [I] INT32 : virtual key
3096 * [I] LONG : key data
3101 static LRESULT LISTVIEW_KeyDown(HWND32 hwnd, INT32 nVirtualKey, LONG lKeyData)
3103 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLong32A(hwnd, 0);
3104 LONG lStyle = GetWindowLong32A(hwnd, GWL_STYLE);
3105 LONG lCtrlId = GetWindowLong32A(hwnd, GWL_ID);
3106 HWND32 hwndParent = GetParent32(hwnd);
3107 INT32 nItemCountPerColumn;
3108 INT32 nItemCountPerRow;
3111 /* NMLVKEYDOWN nmKeyDown; */
3113 /* send LVN_KEYDOWN notification */
3114 /* nmh.hwndFrom = hwnd; */
3115 /* nmh.idFrom = lCtrlId; */
3116 /* nmh.code = LVN_KEYDOWN; */
3117 /* nmKeyDown.hdr = nmh; */
3118 /* nmKeyDown..wVKey = nVirtualKey; */
3119 /* nmKeyCode.flags = 0; */
3120 /* SendMessage32A(hwndParent, WM_NOTIFY, (WPARAM32)lCtrlId, (LPARAM)&nmKeyDown); */
3122 switch (nVirtualKey)
3125 if ((infoPtr->nItemCount > 0) && (infoPtr->nFocusedItem != -1))
3127 /* send NM_RETURN notification */
3128 nmh.code = NM_RETURN;
3129 SendMessage32A(hwndParent, WM_NOTIFY, (WPARAM32)lCtrlId, (LPARAM)&nmh);
3131 /* send LVN_ITEMACTIVATE notification */
3132 nmh.code = LVN_ITEMACTIVATE;
3133 SendMessage32A(hwndParent, WM_NOTIFY, (WPARAM32)lCtrlId, (LPARAM)&nmh);
3138 if (infoPtr->nItemCount > 0)
3140 /* set item state(s) */
3141 infoPtr->nFocusedItem = 0;
3142 LISTVIEW_SetItemStates(hwnd, infoPtr->nFocusedItem, TRUE, FALSE);
3144 /* make item visible */
3145 LISTVIEW_SetVisible(hwnd, infoPtr->nFocusedItem);
3150 if (infoPtr->nItemCount > 0)
3152 /* set item state(s) */
3153 infoPtr->nFocusedItem = infoPtr->nItemCount - 1;
3154 LISTVIEW_SetItemStates(hwnd, infoPtr->nFocusedItem, TRUE, FALSE);
3156 /* make item visible */
3157 LISTVIEW_SetVisible(hwnd, infoPtr->nFocusedItem);
3163 if (lStyle & LVS_LIST)
3165 nItemCountPerColumn = LISTVIEW_GetItemCountPerColumn(hwnd);
3166 if (infoPtr->nFocusedItem >= nItemCountPerColumn)
3168 /* set item state(s) */
3169 infoPtr->nFocusedItem -= nItemCountPerColumn;
3170 LISTVIEW_SetItemStates(hwnd, infoPtr->nFocusedItem, TRUE, FALSE);
3172 /* make item visible */
3173 LISTVIEW_SetVisible(hwnd, infoPtr->nFocusedItem);
3176 else if (lStyle & LVS_REPORT)
3178 /* TO DO ; does not affect the focused item, it only scrolls */
3180 else if ((lStyle & LVS_SMALLICON) || (lStyle & LVS_ICON))
3182 nItemCountPerRow = LISTVIEW_GetItemCountPerRow(hwnd);
3183 nColumn = infoPtr->nFocusedItem % nItemCountPerRow;
3186 infoPtr->nFocusedItem -= 1;
3187 LISTVIEW_SetItemStates(hwnd, infoPtr->nFocusedItem, TRUE, FALSE);
3189 /* refresh display */
3190 InvalidateRect32(hwnd, NULL, FALSE);
3191 UpdateWindow32(hwnd);
3197 if ((lStyle & LVS_LIST) || (lStyle & LVS_REPORT))
3199 if (infoPtr->nFocusedItem > 0)
3201 infoPtr->nFocusedItem -= 1;
3202 LISTVIEW_SetItemStates(hwnd, infoPtr->nFocusedItem, TRUE, FALSE);
3204 LISTVIEW_SetVisible(hwnd, infoPtr->nFocusedItem);
3207 else if ((lStyle & LVS_SMALLICON) || (lStyle & LVS_ICON))
3209 nItemCountPerRow = LISTVIEW_GetItemCountPerRow(hwnd);
3210 if (infoPtr->nFocusedItem >= nItemCountPerRow)
3212 infoPtr->nFocusedItem -= nItemCountPerRow;
3213 LISTVIEW_SetItemStates(hwnd, infoPtr->nFocusedItem, TRUE, FALSE);
3215 LISTVIEW_SetVisible(hwnd, infoPtr->nFocusedItem);
3221 if (lStyle & LVS_LIST)
3223 nItemCountPerColumn = LISTVIEW_GetItemCountPerColumn(hwnd);
3224 if (infoPtr->nFocusedItem < infoPtr->nItemCount - nItemCountPerColumn)
3226 infoPtr->nFocusedItem += nItemCountPerColumn;
3227 LISTVIEW_SetItemStates(hwnd, infoPtr->nFocusedItem, TRUE, FALSE);
3229 LISTVIEW_SetVisible(hwnd, infoPtr->nFocusedItem);
3232 else if (lStyle & LVS_REPORT)
3235 else if ((lStyle & LVS_SMALLICON) || (lStyle & LVS_ICON))
3237 nItemCountPerRow = LISTVIEW_GetItemCountPerRow(hwnd);
3238 nColumn = infoPtr->nFocusedItem % nItemCountPerRow;
3239 if (nColumn != nItemCountPerRow - 1)
3241 infoPtr->nFocusedItem += 1;
3242 LISTVIEW_SetItemStates(hwnd, infoPtr->nFocusedItem, TRUE, FALSE);
3244 /* refresh display */
3245 InvalidateRect32(hwnd, NULL, FALSE);
3246 UpdateWindow32(hwnd);
3253 if ((lStyle & LVS_LIST) || (lStyle & LVS_REPORT))
3255 if (infoPtr->nFocusedItem < infoPtr->nItemCount - 1)
3257 infoPtr->nFocusedItem += 1;
3258 LISTVIEW_SetItemStates(hwnd, infoPtr->nFocusedItem, TRUE, FALSE);
3260 LISTVIEW_SetVisible(hwnd, infoPtr->nFocusedItem);
3263 else if ((lStyle & LVS_SMALLICON) || (lStyle & LVS_ICON))
3265 nItemCountPerRow = LISTVIEW_GetItemCountPerRow(hwnd);
3266 if (infoPtr->nFocusedItem < infoPtr->nItemCount - nItemCountPerRow)
3268 infoPtr->nFocusedItem += nItemCountPerRow;
3269 LISTVIEW_SetItemStates(hwnd, infoPtr->nFocusedItem, TRUE, FALSE);
3271 LISTVIEW_SetVisible(hwnd, infoPtr->nFocusedItem);
3291 * [I] HWND32 : window handle
3296 static LRESULT LISTVIEW_KillFocus(HWND32 hwnd)
3298 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO*)GetWindowLong32A(hwnd, 0);
3299 LONG lCtrlId = GetWindowLong32A(hwnd, GWL_ID);
3302 nmh.hwndFrom = hwnd;
3303 nmh.idFrom = lCtrlId;
3304 nmh.code = NM_KILLFOCUS;
3305 SendMessage32A(GetParent32(hwnd), WM_NOTIFY, (WPARAM32)lCtrlId,
3308 /* set window focus flag */
3309 infoPtr->bFocus = FALSE;
3316 * Left mouse button double click.
3319 * [I] HWND32 : window handle
3320 * [I] WORD : key flag
3321 * [I] WORD : x coordinate
3322 * [I] WORD : y coordinate
3327 static LRESULT LISTVIEW_LButtonDblClk(HWND32 hwnd, WORD wKey, WORD wPosX,
3330 LONG lCtrlId = GetWindowLong32A(hwnd, GWL_ID);
3333 /* send NM_DBLCLK notification */
3334 nmh.hwndFrom = hwnd;
3335 nmh.idFrom = lCtrlId;
3336 nmh.code = NM_DBLCLK;
3337 SendMessage32A(GetParent32 (hwnd), WM_NOTIFY, (WPARAM32)lCtrlId,
3340 /* send LVN_ITEMACTIVATE notification */
3341 nmh.code = LVN_ITEMACTIVATE;
3342 SendMessage32A(GetParent32 (hwnd), WM_NOTIFY, (WPARAM32)lCtrlId,
3350 * Left mouse button down.
3353 * [I] HWND32 : window handle
3354 * [I] WORD : key flag
3355 * [I] WORD : x coordinate
3356 * [I] WORD : y coordinate
3361 static LRESULT LISTVIEW_LButtonDown(HWND32 hwnd, WORD wKey, WORD wPosX,
3364 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLong32A(hwnd, 0);
3365 LONG lCtrlId = GetWindowLong32A(hwnd, GWL_ID);
3366 LVHITTESTINFO hitTestInfo;
3371 /* send NM_RELEASEDCAPTURE notification */
3372 nmh.hwndFrom = hwnd;
3373 nmh.idFrom = lCtrlId;
3374 nmh.code = NM_RELEASEDCAPTURE;
3375 SendMessage32A(GetParent32(hwnd), WM_NOTIFY, (WPARAM32)lCtrlId,
3378 if (infoPtr->bFocus == FALSE)
3381 /* set left button down flag */
3382 infoPtr->bLButtonDown = TRUE;
3384 /* set left button hit coordinates */
3385 hitTestInfo.pt.x = wPosX;
3386 hitTestInfo.pt.y = wPosY;
3388 /* perform hit test */
3389 nItem = SendMessage32A(hwnd, LVM_HITTEST, (WPARAM32)0, (LPARAM)&hitTestInfo);
3390 if ((nItem >= 0) && (nItem < infoPtr->nItemCount))
3392 /* perform state changes (selection and focus) */
3393 infoPtr->nFocusedItem = nItem;
3394 LISTVIEW_SetItemStates(hwnd, infoPtr->nFocusedItem, TRUE, TRUE);
3396 /* scroll intem into view if doing a multiple selection */
3398 if ((wKey & MK_CONTROL) || (wKey & MK_SHIFT))
3400 LISTVIEW_SetVisible(hwnd, infoPtr->nFocusedItem);
3404 /* refresh display */
3405 InvalidateRect32(hwnd, NULL, FALSE);
3406 UpdateWindow32(hwnd);
3411 /* clear selection(s) */
3412 ZeroMemory(&lvItem, sizeof(LVITEM32A));
3413 lvItem.stateMask = LVIS_SELECTED;
3415 SendMessage32A(hwnd, LVM_SETITEMSTATE, (WPARAM32)-1, (LPARAM)&lvItem);
3417 /* repaint everything */
3418 InvalidateRect32(hwnd, NULL, FALSE);
3419 UpdateWindow32(hwnd);
3427 * Left mouse button up.
3430 * [I] HWND32 : window handle
3431 * [I] WORD : key flag
3432 * [I] WORD : x coordinate
3433 * [I] WORD : y coordinate
3438 static LRESULT LISTVIEW_LButtonUp(HWND32 hwnd, WORD wKey, WORD wPosX,
3441 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLong32A(hwnd, 0);
3442 LONG lCtrlId = GetWindowLong32A(hwnd, GWL_ID);
3445 if (infoPtr->bLButtonDown == TRUE)
3447 /* send NM_CLICK notification */
3448 nmh.hwndFrom = hwnd;
3449 nmh.idFrom = lCtrlId;
3450 nmh.code = NM_CLICK;
3451 SendMessage32A(GetParent32 (hwnd), WM_NOTIFY, (WPARAM32)lCtrlId,
3455 /* set left button flag */
3456 infoPtr->bLButtonDown = FALSE;
3463 * Creates the listview control (called before WM_CREATE).
3466 * [I] HWND32 : window handle
3467 * [I] WPARAM32 : unhandled
3468 * [I] LPARAM : widow creation info
3473 static LRESULT LISTVIEW_NCCreate(HWND32 hwnd, WPARAM32 wParam, LPARAM lParam)
3475 LISTVIEW_INFO *infoPtr;
3477 /* allocate memory for info structure */
3478 infoPtr = (LISTVIEW_INFO *)COMCTL32_Alloc (sizeof(LISTVIEW_INFO));
3479 SetWindowLong32A(hwnd, 0, (LONG)infoPtr);
3480 if (infoPtr == NULL)
3482 ERR (listview, "could not allocate info memory!\n");
3486 if ((LISTVIEW_INFO *)GetWindowLong32A(hwnd, 0) != infoPtr)
3488 ERR (listview, "pointer assignment error!\n");
3492 return DefWindowProc32A(hwnd, WM_NCCREATE, wParam, lParam);
3497 * Destroys the listview control (called after WM_DESTROY).
3500 * [I] HWND32 : window handle
3505 static LRESULT LISTVIEW_NCDestroy(HWND32 hwnd)
3507 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLong32A(hwnd, 0);
3509 /* free list view info data */
3510 COMCTL32_Free (infoPtr);
3517 * Handles notification from children.
3520 * [I] HWND32 : window handle
3521 * [I] INT32 : control identifier
3522 * [I] LPNMHDR : notification information
3527 static LRESULT LISTVIEW_Notify(HWND32 hwnd, INT32 nCtrlId, LPNMHDR lpnmh)
3529 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLong32A(hwnd, 0);
3531 if (lpnmh->hwndFrom == infoPtr->hwndHeader)
3533 /* handle notification from header control */
3534 FIXME (listview, "WM_NOTIFY from header!\n");
3538 /* handle notification from unknown source */
3539 FIXME (listview, "WM_NOTIFY from unknown source!\n");
3547 * Draws the listview control.
3550 * [I] HWND32 : window handle
3551 * [I] HDC32 : device context handle
3556 static LRESULT LISTVIEW_Paint(HWND32 hwnd, HDC32 hdc)
3562 hdc = BeginPaint32(hwnd, &ps);
3563 LISTVIEW_Refresh(hwnd, hdc);
3564 EndPaint32(hwnd, &ps);
3567 LISTVIEW_Refresh(hwnd, hdc);
3574 * Right mouse button double clisk.
3577 * [I] HWND32 : window handle
3578 * [I] WORD : key flag
3579 * [I] WORD : x coordinate
3580 * [I] WORD : y coordinate
3585 static LRESULT LISTVIEW_RButtonDblClk(HWND32 hwnd, WORD wKey, WORD wPosX,
3588 LONG lCtrlId = GetWindowLong32A(hwnd, GWL_ID);
3591 /* send NM_RELEASEDCAPTURE notification */
3592 nmh.hwndFrom = hwnd;
3593 nmh.idFrom = lCtrlId;
3594 nmh.code = NM_RELEASEDCAPTURE;
3595 SendMessage32A(GetParent32(hwnd), WM_NOTIFY, (WPARAM32)lCtrlId,
3598 /* send NM_RDBLCLK notification */
3599 nmh.code = NM_RDBLCLK;
3600 SendMessage32A(GetParent32(hwnd), WM_NOTIFY, (WPARAM32)lCtrlId,
3608 * Right mouse button input.
3611 * [I] HWND32 : window handle
3612 * [I] WORD : key flag
3613 * [I] WORD : x coordinate
3614 * [I] WORD : y coordinate
3619 static LRESULT LISTVIEW_RButtonDown(HWND32 hwnd, WORD wKey, WORD wPosX,
3622 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLong32A(hwnd, 0);
3623 LONG lCtrlId = GetWindowLong32A(hwnd, GWL_ID);
3624 LVHITTESTINFO hitTestInfo;
3629 /* The syslistview32 control sends a NM_RELEASEDCAPTURE notification.
3630 I do not know why, but I decided to send it as well for compatibility
3632 ZeroMemory(&nmh, sizeof(NMHDR));
3633 nmh.hwndFrom = hwnd;
3634 nmh.idFrom = lCtrlId;
3635 nmh.code = NM_RELEASEDCAPTURE;
3636 SendMessage32A(GetParent32(hwnd), WM_NOTIFY, (WPARAM32)lCtrlId,
3639 /* make sure listview control has focus */
3640 if (infoPtr->bFocus == FALSE)
3643 /* set left button down flag */
3644 infoPtr->bRButtonDown = TRUE;
3646 /* set hit coordinates */
3647 hitTestInfo.pt.x = wPosX;
3648 hitTestInfo.pt.y = wPosY;
3650 /* perform hit test */
3651 nItem = SendMessage32A(hwnd, LVM_HITTEST, (WPARAM32)0, (LPARAM)&hitTestInfo);
3652 if ((nItem >= 0) && (nItem < infoPtr->nItemCount))
3654 /* perform state changes (selection and focus) */
3655 infoPtr->nFocusedItem = nItem;
3656 LISTVIEW_SetItemStates(hwnd, infoPtr->nFocusedItem, FALSE, TRUE);
3660 /* clear selection(s) */
3661 ZeroMemory(&lvItem, sizeof(LVITEM32A));
3662 lvItem.stateMask = LVIS_SELECTED;
3664 SendMessage32A(hwnd, LVM_SETITEMSTATE, (WPARAM32)-1, (LPARAM)&lvItem);
3667 /* repaint everything */
3668 InvalidateRect32(hwnd, NULL, FALSE);
3669 UpdateWindow32(hwnd);
3676 * Right mouse button up.
3679 * [I] HWND32 : window handle
3680 * [I] WORD : key flag
3681 * [I] WORD : x coordinate
3682 * [I] WORD : y coordinate
3687 static LRESULT LISTVIEW_RButtonUp(HWND32 hwnd, WORD wKey, WORD wPosX,
3690 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLong32A(hwnd, 0);
3691 LONG lCtrlId = GetWindowLong32A(hwnd, GWL_ID);
3694 if (infoPtr->bRButtonDown == TRUE)
3696 /* initialize notification information */
3697 ZeroMemory(&nmh, sizeof(NMHDR));
3698 nmh.hwndFrom = hwnd;
3699 nmh.idFrom = lCtrlId;
3700 nmh.code = NM_RCLICK;
3701 SendMessage32A(GetParent32 (hwnd), WM_NOTIFY, (WPARAM32)lCtrlId,
3705 /* set button flag */
3706 infoPtr->bRButtonDown = FALSE;
3716 * [I] HWND32 : window handle
3717 * [I] HWND32 : window handle of previously focused window
3722 static LRESULT LISTVIEW_SetFocus(HWND32 hwnd, HWND32 hwndLoseFocus)
3724 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLong32A(hwnd, 0);
3725 LONG lCtrlId = GetWindowLong32A(hwnd, GWL_ID);
3728 /* send NM_SETFOCUS notification */
3729 nmh.hwndFrom = hwnd;
3730 nmh.idFrom = lCtrlId;
3731 nmh.code = NM_SETFOCUS;
3732 SendMessage32A(GetParent32(hwnd), WM_NOTIFY, (WPARAM32)lCtrlId,
3735 /* set window focus flag */
3736 infoPtr->bFocus = TRUE;
3746 * [I] HWND32 : window handle
3747 * [I] HFONT32 : font handle
3748 * [I] WORD : redraw flag
3753 static LRESULT LISTVIEW_SetFont(HWND32 hwnd, HFONT32 hFont, WORD fRedraw)
3755 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLong32A(hwnd, 0);
3756 LONG lStyle = GetWindowLong32A(hwnd, GWL_STYLE);
3760 infoPtr->hFont = infoPtr->hDefaultFont;
3764 infoPtr->hFont = hFont;
3767 if (lStyle & LVS_REPORT)
3769 /* set font of header */
3770 SendMessage32A(infoPtr->hwndHeader, WM_SETFONT, (WPARAM32)hFont,
3771 MAKELPARAM(fRedraw, 0));
3774 /* invalidate listview control client area */
3775 InvalidateRect32(hwnd, NULL, FALSE);
3777 if (fRedraw == TRUE)
3778 UpdateWindow32(hwnd);
3785 * Resizes the listview control.
3788 * [I] HWND32 : window handle
3789 * [I] WORD : new width
3790 * [I] WORD : new height
3795 static LRESULT LISTVIEW_Size(HWND32 hwnd, WORD wWidth, WORD wHeight)
3797 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLong32A(hwnd, 0);
3798 LONG lStyle = GetWindowLong32A(hwnd, GWL_STYLE);
3799 INT32 nHScrollHeight;
3801 if (lStyle & LVS_LIST)
3803 if (!(lStyle & WS_HSCROLL))
3805 nHScrollHeight = GetSystemMetrics32(SM_CYHSCROLL);
3806 if (wHeight > nHScrollHeight)
3807 wHeight -= nHScrollHeight;
3810 infoPtr->nHeight = (INT32)wHeight;
3811 infoPtr->nWidth = (INT32)wWidth;
3814 /* set scrollbar(s) if needed */
3815 LISTVIEW_SetScroll(hwnd);
3817 /* refresh client area */
3818 InvalidateRect32(hwnd, NULL, TRUE);
3819 UpdateWindow32(hwnd);
3826 * Window procedure of the listview control.
3837 LRESULT WINAPI LISTVIEW_WindowProc(HWND32 hwnd, UINT32 uMsg, WPARAM32 wParam,
3842 case LVM_APPROXIMATEVIEWRECT:
3843 return LISTVIEW_ApproximateViewRect(hwnd, (INT32)wParam,
3844 LOWORD(lParam), HIWORD(lParam));
3846 return LISTVIEW_Arrange(hwnd, (INT32)wParam);
3848 /* case LVM_CREATEDRAGIMAGE: */
3850 case LVM_DELETEALLITEMS:
3851 return LISTVIEW_DeleteAllItems(hwnd);
3853 case LVM_DELETECOLUMN:
3854 return LISTVIEW_DeleteColumn(hwnd, (INT32)wParam);
3856 case LVM_DELETEITEM:
3857 return LISTVIEW_DeleteItem(hwnd, (INT32)wParam);
3859 /* case LVM_EDITLABEL: */
3860 /* case LVM_ENSUREVISIBLE: */
3862 case LVM_FINDITEM32A:
3863 return LISTVIEW_FindItem(hwnd, (INT32)wParam, (LPLVFINDINFO)lParam);
3865 case LVM_GETBKCOLOR:
3866 return LISTVIEW_GetBkColor(hwnd);
3868 /* case LVM_GETBKIMAGE: */
3869 /* case LVM_GETCALLBACKMASK: */
3871 case LVM_GETCOLUMN32A:
3872 return LISTVIEW_GetColumn32A(hwnd, (INT32)wParam, (LPLVCOLUMN32A)lParam);
3874 /* case LVM_GETCOLUMN32W: */
3875 /* case LVM_GETCOLUMNORDERARRAY: */
3877 case LVM_GETCOLUMNWIDTH:
3878 return LISTVIEW_GetColumnWidth(hwnd, (INT32)wParam);
3880 case LVM_GETCOUNTPERPAGE:
3881 return LISTVIEW_GetCountPerPage(hwnd);
3883 /* case LVM_GETEDITCONTROL: */
3884 /* case LVM_GETEXTENDEDLISTVIEWSTYLE: */
3887 return LISTVIEW_GetHeader(hwnd);
3889 /* case LVM_GETHOTCURSOR: */
3890 /* case LVM_GETHOTITEM: */
3891 /* case LVM_GETHOVERTIME: */
3893 case LVM_GETIMAGELIST:
3894 return LISTVIEW_GetImageList(hwnd, (INT32)wParam);
3896 /* case LVM_GETISEARCHSTRING: */
3898 case LVM_GETITEM32A:
3899 return LISTVIEW_GetItem32A(hwnd, (LPLVITEM32A)lParam);
3901 /* case LVM_GETITEM32W: */
3903 case LVM_GETITEMCOUNT:
3904 return LISTVIEW_GetItemCount(hwnd);
3906 case LVM_GETITEMPOSITION:
3907 return LISTVIEW_GetItemPosition(hwnd, (INT32)wParam, (LPPOINT32)lParam);
3909 case LVM_GETITEMRECT:
3910 return LISTVIEW_GetItemRect(hwnd, (INT32)wParam, (LPRECT32)lParam);
3912 case LVM_GETITEMSPACING:
3913 return LISTVIEW_GetItemSpacing(hwnd, (BOOL32)wParam);
3915 case LVM_GETITEMSTATE:
3916 return LISTVIEW_GetItemState(hwnd, (INT32)wParam, (UINT32)lParam);
3918 case LVM_GETITEMTEXT32A:
3919 LISTVIEW_GetItemText32A(hwnd, (INT32)wParam, (LPLVITEM32A)lParam);
3922 /* case LVM_GETITEMTEXT32W: */
3924 case LVM_GETNEXTITEM:
3925 return LISTVIEW_GetNextItem(hwnd, (INT32)wParam, LOWORD(lParam));
3927 /* case LVM_GETNUMBEROFWORKAREAS: */
3929 return LISTVIEW_GetOrigin(hwnd, (LPPOINT32)lParam);
3931 case LVM_GETSELECTEDCOUNT:
3932 return LISTVIEW_GetSelectedCount(hwnd);
3934 case LVM_GETSELECTIONMARK:
3935 return LISTVIEW_GetSelectionMark(hwnd);
3937 case LVM_GETSTRINGWIDTH32A:
3938 return LISTVIEW_GetStringWidth32A (hwnd, (LPCSTR)lParam);
3940 /* case LVM_GETSTRINGWIDTH32W: */
3941 /* case LVM_GETSUBITEMRECT: */
3943 case LVM_GETTEXTBKCOLOR:
3944 return LISTVIEW_GetTextBkColor(hwnd);
3946 case LVM_GETTEXTCOLOR:
3947 return LISTVIEW_GetTextColor(hwnd);
3949 /* case LVM_GETTOOLTIPS: */
3950 /* case LVM_GETTOPINDEX: */
3951 /* case LVM_GETUNICODEFORMAT: */
3953 case LVM_GETVIEWRECT:
3954 return LISTVIEW_GetViewRect(hwnd, (LPRECT32)lParam);
3956 /* case LVM_GETWORKAREAS: */
3959 return LISTVIEW_HitTest(hwnd, (LPLVHITTESTINFO)lParam);
3961 case LVM_INSERTCOLUMN32A:
3962 return LISTVIEW_InsertColumn32A(hwnd, (INT32)wParam,
3963 (LPLVCOLUMN32A)lParam);
3965 /* case LVM_INSERTCOLUMN32W: */
3967 case LVM_INSERTITEM32A:
3968 return LISTVIEW_InsertItem32A(hwnd, (LPLVITEM32A)lParam);
3970 /* case LVM_INSERTITEM32W: */
3972 case LVM_REDRAWITEMS:
3973 return LISTVIEW_RedrawItems(hwnd, (INT32)wParam, (INT32)lParam);
3976 return LISTVIEW_Scroll(hwnd, (INT32)wParam, (INT32)lParam);
3978 case LVM_SETBKCOLOR:
3979 return LISTVIEW_SetBkColor(hwnd, (COLORREF)lParam);
3981 /* case LVM_SETBKIMAGE: */
3982 /* case LVM_SETCALLBACKMASK: */
3984 case LVM_SETCOLUMN32A:
3985 return LISTVIEW_SetColumn32A(hwnd, (INT32)wParam, (LPLVCOLUMN32A)lParam);
3987 /* case LVM_SETCOLUMN32W: */
3988 /* case LVM_SETCOLUMNORDERARRAY: */
3989 /* case LVM_SETCOLUMNWIDTH: */
3990 /* case LVM_SETEXTENDEDLISTVIEWSTYLE: */
3991 /* case LVM_SETHOTCURSOR: */
3992 /* case LVM_SETHOTITEM: */
3993 /* case LVM_SETHOVERTIME: */
3994 /* case LVM_SETICONSPACING: */
3996 case LVM_SETIMAGELIST:
3997 return LISTVIEW_SetImageList(hwnd, (INT32)wParam, (HIMAGELIST)lParam);
3999 case LVM_SETITEM32A:
4000 return LISTVIEW_SetItem32A(hwnd, (LPLVITEM32A)lParam);
4002 /* case LVM_SETITEM32W: */
4003 /* case LVM_SETITEMCOUNT: */
4005 case LVM_SETITEMPOSITION:
4006 return LISTVIEW_SetItemPosition(hwnd, (INT32)wParam,
4007 (INT32)LOWORD(lParam),
4008 (INT32) HIWORD(lParam));
4010 /* case LVM_SETITEMPOSITION32: */
4012 case LVM_SETITEMSTATE:
4013 return LISTVIEW_SetItemState(hwnd, (INT32)wParam, (LPLVITEM32A)lParam);
4015 /* case LVM_SETITEMTEXT: */
4016 /* case LVM_SETSELECTIONMARK: */
4018 case LVM_SETTEXTBKCOLOR:
4019 return LISTVIEW_SetTextBkColor(hwnd, (COLORREF)lParam);
4021 case LVM_SETTEXTCOLOR:
4022 return LISTVIEW_SetTextColor(hwnd, (COLORREF)lParam);
4024 /* case LVM_SETTOOLTIPS: */
4025 /* case LVM_SETUNICODEFORMAT: */
4026 /* case LVM_SETWORKAREAS: */
4029 return LISTVIEW_SortItems(hwnd, wParam, lParam);
4031 /* case LVM_SUBITEMHITTEST: */
4034 return LISTVIEW_Update(hwnd, (INT32)wParam);
4037 /* case WM_COMMAND: */
4040 return LISTVIEW_Create(hwnd, wParam, lParam);
4043 return LISTVIEW_Destroy(hwnd, wParam, lParam);
4046 return LISTVIEW_EraseBackground (hwnd, wParam, lParam);
4049 return DLGC_WANTTAB | DLGC_WANTARROWS;
4052 return LISTVIEW_GetFont(hwnd);
4055 return LISTVIEW_HScroll(hwnd, (INT32)LOWORD(wParam),
4056 (INT32)HIWORD(wParam), (HWND32)lParam);
4059 return LISTVIEW_KeyDown(hwnd, (INT32)wParam, (LONG)lParam);
4062 return LISTVIEW_KillFocus(hwnd);
4064 case WM_LBUTTONDBLCLK:
4065 return LISTVIEW_LButtonDblClk(hwnd, (WORD)wParam, LOWORD(lParam),
4068 case WM_LBUTTONDOWN:
4069 return LISTVIEW_LButtonDown(hwnd, (WORD)wParam, LOWORD(lParam),
4072 return LISTVIEW_LButtonUp(hwnd, (WORD)wParam, LOWORD(lParam),
4075 /* case WM_MOUSEMOVE: */
4076 /* return LISTVIEW_MouseMove (hwnd, wParam, lParam); */
4079 return LISTVIEW_NCCreate(hwnd, wParam, lParam);
4082 return LISTVIEW_NCDestroy(hwnd);
4085 return LISTVIEW_Notify(hwnd, (INT32)wParam, (LPNMHDR)lParam);
4088 return LISTVIEW_Paint(hwnd, (HDC32)wParam);
4090 case WM_RBUTTONDBLCLK:
4091 return LISTVIEW_RButtonDblClk(hwnd, (WORD)wParam, LOWORD(lParam),
4094 case WM_RBUTTONDOWN:
4095 return LISTVIEW_RButtonDown(hwnd, (WORD)wParam, LOWORD(lParam),
4099 return LISTVIEW_RButtonUp(hwnd, (WORD)wParam, LOWORD(lParam),
4103 return LISTVIEW_SetFocus(hwnd, (HWND32)wParam);
4106 return LISTVIEW_SetFont(hwnd, (HFONT32)wParam, (WORD)lParam);
4108 /* case WM_SETREDRAW: */
4111 return LISTVIEW_Size(hwnd, LOWORD(lParam), HIWORD(lParam));
4113 /* case WM_TIMER: */
4114 /* case WM_VSCROLL: */
4115 /* case WM_WINDOWPOSCHANGED: */
4116 /* case WM_WININICHANGE: */
4119 if (uMsg >= WM_USER)
4120 ERR (listview, "unknown msg %04x wp=%08x lp=%08lx\n",
4121 uMsg, wParam, lParam);
4123 /* call default window procedure */
4124 return DefWindowProc32A (hwnd, uMsg, wParam, lParam);
4132 * Registers the window class.
4140 VOID LISTVIEW_Register(VOID)
4142 WNDCLASS32A wndClass;
4144 if (!GlobalFindAtom32A(WC_LISTVIEW32A))
4146 ZeroMemory (&wndClass, sizeof(WNDCLASS32A));
4147 wndClass.style = CS_GLOBALCLASS | CS_DBLCLKS;
4148 wndClass.lpfnWndProc = (WNDPROC32)LISTVIEW_WindowProc;
4149 wndClass.cbClsExtra = 0;
4150 wndClass.cbWndExtra = sizeof(LISTVIEW_INFO *);
4151 wndClass.hCursor = LoadCursor32A (0, IDC_ARROW32A);
4152 wndClass.hbrBackground = (HBRUSH32)(COLOR_WINDOW + 1);
4153 wndClass.lpszClassName = WC_LISTVIEW32A;
4154 RegisterClass32A (&wndClass);
4160 * Unregisters the window class.
4168 VOID LISTVIEW_Unregister(VOID)
4170 if (GlobalFindAtom32A (WC_LISTVIEW32A))
4171 UnregisterClass32A (WC_LISTVIEW32A, (HINSTANCE32)NULL);