Large-scale renaming of all Win32 functions and types to use the
[wine.git] / dlls / comctl32 / listview.c
blob157af47f9829cc0c01b52e011983da9f031ee02c
1 /*
2 * Listview control
4 * Copyright 1998 Eric Kohl
5 * Copyright 1999 Luc Tourangeau
7 * NOTES
8 * Listview control implementation. The behavior conforms to version 4.70
9 * and earlier of the listview contol.
11 * TODO:
12 * Most messages and notifications
13 * Report, small icon and icon display modes
16 #include <string.h>
17 #include "commctrl.h"
18 #include "listview.h"
19 #include "win.h"
20 #include "debug.h"
21 #include "winuser.h"
23 /* prototypes */
24 static INT LISTVIEW_GetItemCountPerColumn(HWND hwnd);
25 static INT LISTVIEW_GetItemCountPerRow(HWND hwnd);
26 static INT LISTVIEW_GetFirstVisibleItem(HWND hwnd);
27 static VOID LISTVIEW_SetVisible(HWND hwnd, INT nItem);
30 /***
31 * DESCRIPTION:
32 * Scrolls the specified item into the visible area.
34 * PARAMETER(S):
35 * [I] HWND32 : window handle
36 * [I] INT32 : item index
38 * RETURN:
39 * None
41 static VOID LISTVIEW_SetVisible(HWND hwnd, INT nItem)
43 LONG lStyle = GetWindowLongA(hwnd, GWL_STYLE);
44 INT nItemCountPerRow;
45 INT nItemCountPerColumn;
46 INT nLastItem;
47 INT nFirstItem;
48 INT nHScrollPos;
49 INT nVScrollPos;
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;
73 else
74 nHScrollPos = (nItem - nLastItem) / nItemCountPerColumn + 1;
75 SendMessageA(hwnd, LVM_SCROLL, (WPARAM)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;
82 else
83 nHScrollPos = (nItem - nFirstItem) / nItemCountPerColumn - 1;
84 SendMessageA(hwnd, LVM_SCROLL, (WPARAM)nHScrollPos, (LPARAM)0);
88 else if (lStyle & LVS_REPORT)
90 if (lStyle & WS_VSCROLL)
92 if (nFirstItem > 0)
94 nLastItem = nItemCountPerColumn + nFirstItem;
96 else
98 nLastItem = nItemCountPerColumn + nFirstItem - 1;
101 if (nItem > nLastItem)
103 /* calculate new scroll position based on item index */
104 nVScrollPos = nItem - nLastItem;
105 SendMessageA(hwnd, LVM_SCROLL, (WPARAM)0, (LPARAM)nVScrollPos);
107 else if (nItem < nFirstItem)
109 /* calculate new scroll position based on item index */
110 nVScrollPos = nItem - nFirstItem;
111 SendMessageA(hwnd, LVM_SCROLL, (WPARAM)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 SendMessageA(hwnd, LVM_SCROLL, (WPARAM)0, (LPARAM)nVScrollPos);
127 else if (nItem < nFirstItem)
129 /* calculate new scroll position based on item index */
130 nHScrollPos = (nItem - nFirstItem) / nItemCountPerRow - 1;
131 SendMessageA(hwnd, LVM_SCROLL, (WPARAM)0, (LPARAM)nHScrollPos);
136 /* refresh display */
137 InvalidateRect(hwnd, NULL, FALSE);
138 UpdateWindow(hwnd);
143 /***
144 * DESCRIPTION:
145 * Retrieves the index of the item at coordinate (0, 0) of the client area.
147 * PARAMETER(S):
148 * [I] HWND32 : window handle
150 * RETURN:
151 * item index
153 static INT LISTVIEW_GetFirstVisibleItem(HWND hwnd)
155 LONG lStyle = GetWindowLongA(hwnd, GWL_STYLE);
156 INT nItemCountPerRow;
157 INT nItemCountPerColumn;
158 INT nMinRange;
159 INT nMaxRange;
160 INT nHScrollPos;
161 /* INT32 nVScrollPos; */
162 INT nItem = 0;
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 GetScrollRange(hwnd, SB_HORZ, &nMinRange, &nMaxRange);
177 nHScrollPos = GetScrollPos(hwnd, SB_HORZ);
178 if (nMinRange < nHScrollPos)
180 nItem = ((nHScrollPos - nMinRange) * nItemCountPerColumn *
181 nItemCountPerRow);
185 else if (lStyle & LVS_REPORT)
187 /* TO DO */
189 else if (lStyle & LVS_SMALLICON)
191 /* TO DO */
193 else if (lStyle & LVS_ICON)
195 /* TO DO */
199 return nItem;
202 /***
203 * DESCRIPTION:
204 * Retrieves the number of items per row. In other words, the number
205 * visible display columns.
207 * PARAMETER(S):
208 * [I] HWND32 : window handle
210 * RETURN:
211 * Number of items per row.
213 static INT LISTVIEW_GetItemCountPerRow(HWND hwnd)
215 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
216 LONG lStyle = GetWindowLongA(hwnd, GWL_STYLE);
217 INT 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)
232 /* TO DO */
234 else if (lStyle & LVS_SMALLICON)
236 /* TO DO */
238 else if (lStyle & LVS_ICON)
240 /* TO DO */
244 return nItemCountPerRow;
247 /***
248 * DESCRIPTION:
249 * Retrieves the number of items that can be displayed vertically in
250 * the listview.
252 * PARAMETER(S):
253 * [I] HWND32 : window handle
255 * RETURN:
256 * Number of items per column.
258 static INT LISTVIEW_GetItemCountPerColumn(HWND hwnd)
260 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
261 LONG lStyle = GetWindowLongA(hwnd, GWL_STYLE);
262 INT 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)
273 /* TO DO */
275 else if (lStyle & LVS_SMALLICON)
277 /* TO DO */
279 else if (lStyle & LVS_ICON)
281 /* TO DO */
285 return nItemCountPerColumn;
288 /***
289 * DESCRIPTION:
290 * Retrieves the number of columns needed to display
291 * all the items in listview.
293 * PARAMETER(S):
294 * [I] HWND32 : window handle
296 * RETURN:
297 * Number of columns.
299 static INT LISTVIEW_GetColumnCount(HWND hwnd)
301 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
302 LONG lStyle = GetWindowLongA(hwnd, GWL_STYLE);
303 INT nColumnCount = 0;
304 INT 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 ;
316 else
318 nColumnCount = infoPtr->nItemCount / nItemCountPerColumn + 1;
321 else if (lStyle & LVS_REPORT)
323 /* TO DO */
325 else if (lStyle & LVS_SMALLICON)
327 /* TO DO */
329 else if (lStyle & LVS_ICON)
331 /* TO DO */
335 return nColumnCount;
338 /***
339 * DESCRIPTION:
340 * Sets the scrolling parameters.
342 * PARAMETER(S):
343 * [I] HWND32 : window handle
345 * RETURN:
346 * None
348 static VOID LISTVIEW_SetScroll(HWND hwnd)
350 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
351 LONG lStyle = GetWindowLongA(hwnd, GWL_STYLE);
352 INT nColumnCount;
353 INT nItemCountPerRow;
354 INT nItemCountPerColumn;
355 INT nMinRange, nMaxRange;
356 INT nHScrollPos;
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 ShowScrollBar(hwnd, SB_HORZ, TRUE);
378 /* set scrollbar range and position */
379 nMaxRange = nColumnCount - nItemCountPerRow;
380 SetScrollRange(hwnd, SB_HORZ, 0, nMaxRange, FALSE);
381 SetScrollPos(hwnd, SB_HORZ, 0, TRUE);
383 else
385 nHScrollPos = GetScrollPos(hwnd, SB_HORZ);
386 GetScrollRange(hwnd, SB_HORZ, &nMinRange, &nMaxRange);
387 if (nMaxRange != nColumnCount - nItemCountPerRow)
389 nMaxRange = nColumnCount - nItemCountPerRow;
390 SetScrollRange(hwnd, SB_HORZ, nMinRange, nMaxRange, FALSE);
392 if (nHScrollPos > nMaxRange)
393 nHScrollPos = nMaxRange;
395 SetScrollPos(hwnd, SB_HORZ, nHScrollPos, TRUE);
399 /* refresh the client area */
400 InvalidateRect(hwnd,NULL, TRUE);
401 UpdateWindow(hwnd);
403 else
405 /* remove scrollbar if present */
406 if (lStyle & WS_HSCROLL)
408 /* hide scrollbar */
409 ShowScrollBar(hwnd, SB_HORZ, FALSE);
411 /* refresh the client area */
412 InvalidateRect(hwnd,NULL, TRUE);
413 UpdateWindow(hwnd);
418 else if (lStyle & LVS_REPORT)
420 HDLAYOUT hl;
421 WINDOWPOS wp;
422 RECT rc;
424 rc.top = 0;
425 rc.left = 0;
426 rc.right = infoPtr->nWidth;
427 rc.bottom = infoPtr->nHeight;
429 hl.prc = &rc;
430 hl.pwpos = &wp;
431 SendMessageA(infoPtr->hwndHeader, HDM_LAYOUT, 0, (LPARAM)&hl);
433 SetWindowPos(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)
440 /* TO DO */
442 else if (lStyle & LVS_ICON)
444 /* TO DO */
449 /***
450 * DESCRIPTION:
451 * Modifies the state (selected and focused) of the listview items.
453 * PARAMETER(S):
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)
459 * RETURN:
460 * None
462 static VOID LISTVIEW_SetItemStates(HWND hwnd, INT nFocusedItem,
463 BOOL bVirtualKeys, BOOL bMouseInput)
465 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
466 WORD wShift = HIWORD(GetKeyState(VK_SHIFT));
467 WORD wCtrl = HIWORD(GetKeyState(VK_CONTROL));
468 INT i;
469 LVITEMA lvItem;
471 /* initialize memory */
472 ZeroMemory(&lvItem, sizeof(LVITEMA));
474 if (wShift && (bVirtualKeys == TRUE))
476 /* reset the selected and focused states of all the items */
477 lvItem.stateMask = LVIS_SELECTED | LVIS_FOCUSED;
478 lvItem.state = 0;
479 SendMessageA(hwnd, LVM_SETITEMSTATE, (WPARAM)-1, (LPARAM)&lvItem);
481 if (infoPtr->nSelectionMark > nFocusedItem)
483 for (i = infoPtr->nSelectionMark; i > nFocusedItem; i--)
485 /* select items */
486 lvItem.stateMask = LVIS_SELECTED;
487 lvItem.state = LVIS_SELECTED;
488 SendMessageA(hwnd, LVM_SETITEMSTATE, (WPARAM)i, (LPARAM)&lvItem);
491 else
493 for (i = infoPtr->nSelectionMark; i < nFocusedItem; i++)
495 /* select items */
496 lvItem.stateMask = LVIS_SELECTED;
497 lvItem.state = LVIS_SELECTED;
498 SendMessageA(hwnd, LVM_SETITEMSTATE, (WPARAM)i, (LPARAM)&lvItem);
502 /* select anf focus item */
503 lvItem.stateMask = LVIS_SELECTED | LVIS_FOCUSED;
504 lvItem.state = LVIS_SELECTED | LVIS_FOCUSED;
505 SendMessageA(hwnd, LVM_SETITEMSTATE, (WPARAM)i, (LPARAM)&lvItem);
507 else
509 if (wCtrl && (bVirtualKeys == TRUE))
511 /* make sure the focus is lost */
512 lvItem.stateMask = LVIS_FOCUSED;
513 lvItem.state = 0;
514 SendMessageA(hwnd, LVM_SETITEMSTATE, (WPARAM)-1, (LPARAM)&lvItem);
516 if (bMouseInput == TRUE)
518 if (SendMessageA(hwnd, LVM_GETITEMSTATE, (WPARAM)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 SendMessageA(hwnd, LVM_SETITEMSTATE, (WPARAM)nFocusedItem,
525 (LPARAM)&lvItem);
527 else
529 /* select and focus */
530 lvItem.stateMask = LVIS_SELECTED | LVIS_FOCUSED;
531 lvItem.state = LVIS_SELECTED | LVIS_FOCUSED;
532 SendMessageA(hwnd, LVM_SETITEMSTATE, (WPARAM)nFocusedItem,
533 (LPARAM)&lvItem);
536 /* set the group selection start position */
537 infoPtr->nSelectionMark = nFocusedItem;
539 else
541 /* focus */
542 lvItem.stateMask = LVIS_FOCUSED;
543 lvItem.state = LVIS_FOCUSED;
544 SendMessageA(hwnd, LVM_SETITEMSTATE, (WPARAM)nFocusedItem,
545 (LPARAM)&lvItem);
548 else
550 /* clear selection and focus for all the items */
551 lvItem.stateMask = LVIS_SELECTED | LVIS_FOCUSED;
552 lvItem.state = 0;
553 SendMessageA(hwnd, LVM_SETITEMSTATE, (WPARAM)-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 SendMessageA(hwnd, LVM_SETITEMSTATE, (WPARAM)nFocusedItem,
559 (LPARAM)&lvItem);
561 /* set the new group selection start position */
562 infoPtr->nSelectionMark = nFocusedItem;
567 /***
568 * DESCRIPTION:
569 * Draws listview items when in list display maode.
571 * PARAMETER(S):
572 * [I] HWND32 : window handle
573 * [I] HDC32 : device context handle
575 * RETURN:
576 * None
578 static VOID LISTVIEW_RefreshList(HWND hwnd, HDC hdc)
580 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
581 LISTVIEW_ITEM *lpItem;
582 HFONT hOldFont;
583 HPEN hPen, hOldPen;
584 INT nItemCountPerColumn;
585 INT nItemCountPerRow;
586 INT nSmallIconWidth;
587 SIZE labelSize;
588 INT nDrawPosX = 0;
589 INT nDrawPosY = 0;
590 BOOL bSelected;
591 RECT rcBoundingBox;
592 COLORREF clrHighlight;
593 COLORREF clrHighlightText;
594 INT i;
595 INT nColumn = 0;
596 INT nRow;
597 INT j;
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))
607 /* select font */
608 hOldFont = SelectObject(hdc, infoPtr->hFont);
610 /* inititialize system dependent information */
611 clrHighlight = GetSysColor(COLOR_HIGHLIGHT);
612 clrHighlightText = GetSysColor(COLOR_HIGHLIGHTTEXT);
613 nSmallIconWidth = GetSystemMetrics(SM_CXSMICON);
615 /* select transparent brush (for drawing the focus box) */
616 SelectObject(hdc, GetStockObject(NULL_BRUSH));
618 /* select the doted pen (for drawing the focus box) */
619 hPen = CreatePen(PS_DOT, 1, 0);
620 hOldPen = SelectObject(hdc, hPen);
622 /* get starting index */
623 i = LISTVIEW_GetFirstVisibleItem(hwnd);
625 /* DRAW ITEMS */
626 for (j = 0; i < infoPtr->nItemCount; i++, j++)
628 /* set draw position for current item */
629 nRow = j % nItemCountPerColumn;
630 nColumn = j / nItemCountPerColumn;
631 if (nRow == 0)
632 nDrawPosY = 0;
633 else
634 nDrawPosY += infoPtr->nItemHeight;
636 nDrawPosX = nColumn * infoPtr->nColumnWidth;
638 /* get item */
639 lpItem = (LISTVIEW_ITEM *)DPA_GetPtr(infoPtr->hdpaItems, i);
640 if (lpItem != NULL)
642 if (lpItem->state & LVIS_SELECTED)
644 bSelected = TRUE;
646 /* set item colors */
647 SetBkColor(hdc, clrHighlight);
648 SetTextColor(hdc, clrHighlightText);
650 /* set raster mode */
651 SetROP2(hdc, R2_XORPEN);
653 else
655 bSelected = FALSE;
657 /* set item colors */
658 SetBkColor(hdc, infoPtr->clrTextBk);
659 SetTextColor(hdc, infoPtr->clrText);
661 /* set raster mode */
662 SetROP2(hdc, R2_COPYPEN);
665 /* state images */
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);
672 else
673 ImageList_Draw(infoPtr->himlState, lpItem->state >> 12, hdc,
674 nDrawPosX, nDrawPosY, ILD_NORMAL);
676 nDrawPosX += nSmallIconWidth;
679 /* small icons */
680 if (infoPtr->himlSmall != NULL)
682 if (bSelected == TRUE)
683 ImageList_Draw(infoPtr->himlSmall, lpItem->iImage, hdc, nDrawPosX,
684 nDrawPosY, ILD_SELECTED);
685 else
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 lstrlenA(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;
706 /* draw text */
707 ExtTextOutA(hdc, nDrawPosX + 1, nDrawPosY+ 1,
708 ETO_OPAQUE|ETO_CLIPPED, &rcBoundingBox,
709 lpItem->pszText, lstrlenA(lpItem->pszText), NULL);
711 if (lpItem->state & LVIS_FOCUSED)
712 Rectangle(hdc, rcBoundingBox.left, rcBoundingBox.top,
713 rcBoundingBox.right, rcBoundingBox.bottom);
717 /* unselect objects */
718 SelectObject(hdc, hOldFont);
719 SelectObject(hdc, hOldPen);
721 /* delete pen */
722 DeleteObject(hPen);
726 /***
727 * DESCRIPTION:
728 * Draws listview items when in report display mode.
730 * PARAMETER(S):
731 * [I] HWND32 : window handle
732 * [I] HDC32 : device context handle
734 * RETURN:
735 * None
737 static VOID LISTVIEW_RefreshReport(HWND hwnd, HDC hdc)
739 /* TO DO */
742 /***
743 * DESCRIPTION:
744 * Draws listview items when in small icon display mode.
746 * PARAMETER(S):
747 * [I] HWND32 : window handle
748 * [I] HDC32 : device context handle
750 * RETURN:
751 * None
753 static VOID LISTVIEW_RefreshSmallIcon(HWND hwnd, HDC hdc)
755 /* TO DO */
758 /***
759 * DESCRIPTION:
760 * Draws listview items when in icon display mode.
762 * PARAMETER(S):
763 * [I] HWND32 : window handle
764 * [I] HDC32 : device context handle
766 * RETURN:
767 * None
769 static VOID LISTVIEW_RefreshIcon(HWND hwnd, HDC hdc)
771 /* TO DO */
774 /***
775 * DESCRIPTION:
776 * Draws listview items.
778 * PARAMETER(S):
779 * [I] HWND32 : window handle
780 * [I] HDC32 : device context handle
782 * RETURN:
783 * None
785 static VOID LISTVIEW_Refresh(HWND hwnd, HDC hdc)
787 LONG lStyle = GetWindowLongA(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);
808 /***
809 * DESCRIPTION:
810 * Calculates the approximate width and height of a given number of items.
812 * PARAMETER(S):
813 * [I] HWND32 : window handle
814 * [I] INT32 : number of items
815 * [I] INT32 : width
816 * [I] INT32 : height
818 * RETURN:
819 * Returns a DWORD. The width in the low word and the height in high word.
821 static LRESULT LISTVIEW_ApproximateViewRect(HWND hwnd, INT nItemCount,
822 WORD wWidth, WORD wHeight)
824 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
825 LONG lStyle = GetWindowLongA(hwnd, GWL_STYLE);
826 INT nItemCountPerColumn = 1;
827 INT 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;
846 if (nItemCount > 0)
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;
856 else
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)
868 /* TO DO */
870 else if (lStyle & LVS_SMALLICON)
872 /* TO DO */
874 else if (lStyle & LVS_ICON)
876 /* TO DO */
879 return dwViewRect;
882 /***
883 * DESCRIPTION:
884 * Arranges listview items in icon display mode.
886 * PARAMETER(S):
887 * [I] HWND32 : window handle
888 * [I] INT32 : alignment code
890 * RETURN:
891 * SUCCESS : TRUE
892 * FAILURE : FALSE
894 static LRESULT LISTVIEW_Arrange(HWND hwnd, INT nAlignCode)
896 /* LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLong32A(hwnd, 0); */
897 LONG lStyle = GetWindowLongA(hwnd, GWL_STYLE);
898 BOOL bResult = FALSE;
900 if (lStyle & LVS_ICON)
902 switch (nAlignCode)
904 case LVA_ALIGNLEFT:
905 /* TO DO */
906 break;
907 case LVA_ALIGNTOP:
908 /* TO DO */
909 break;
910 case LVA_DEFAULT:
911 /* TO DO */
912 break;
913 case LVA_SNAPTOGRID:
914 /* TO DO */
918 return bResult;
921 /* << LISTVIEW_CreateDragImage >> */
923 /***
924 * DESCRIPTION:
925 * Removes all listview items.
927 * PARAMETER(S):
928 * [I] HWND32 : window handle
930 * RETURN:
931 * SUCCESS : TRUE
932 * FAILURE : FALSE
934 static LRESULT LISTVIEW_DeleteAllItems(HWND hwnd)
936 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
937 LONG lCtrlId = GetWindowLongA(hwnd, GWL_ID);
938 LISTVIEW_ITEM *lpItem;
939 NMLISTVIEW nmlv;
940 BOOL bNotify;
941 INT i;
942 BOOL 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;
951 nmlv.iItem = -1;
952 bNotify = !(BOOL)SendMessageA(GetParent(hwnd), WM_NOTIFY,
953 (WPARAM)lCtrlId, (LPARAM)&nmlv);
955 nmlv.hdr.code = LVN_DELETEITEM;
957 for (i = 0; i < infoPtr->nItemCount; i++)
959 if (bNotify == TRUE)
961 /* send LVN_DELETEITEM notification */
962 nmlv.iItem = i;
963 SendMessageA(GetParent(hwnd), WM_NOTIFY, (WPARAM)lCtrlId,
964 (LPARAM)&nmlv);
967 /* get item */
968 lpItem = (LISTVIEW_ITEM *)DPA_GetPtr(infoPtr->hdpaItems, i);
969 if (lpItem != NULL)
971 /* free item string */
972 if ((lpItem->pszText != NULL) &&
973 (lpItem->pszText != LPSTR_TEXTCALLBACKA))
974 COMCTL32_Free (lpItem->pszText);
976 /* free item */
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);
991 return bResult;
994 /***
995 * DESCRIPTION:
996 * Removes a column from the listview control.
998 * PARAMETER(S):
999 * [I] HWND32 : window handle
1000 * [I] INT32 : column index
1002 * RETURN:
1003 * SUCCESS : TRUE
1004 * FAILURE : FALSE
1006 static LRESULT LISTVIEW_DeleteColumn(HWND hwnd, INT nColumn)
1008 /* LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLong32A(hwnd, 0); */
1010 /* FIXME ??? */
1011 /* if (infoPtr->nItemCount > 0) */
1012 /* return FALSE; */
1013 /* if (!SendMessage32A(infoPtr->hwndHeader, HDM_DELETEITEM, wParam, 0)) */
1014 /* return FALSE; */
1015 /* infoPtr->nColumnCount--; */
1016 /* FIXME (listview, "semi stub!\n"); */
1018 return TRUE;
1021 /***
1022 * DESCRIPTION:
1023 * Removes an item from the listview control.
1025 * PARAMETER(S):
1026 * [I] HWND32 : window handle
1027 * [I] INT32 : item index
1029 * RETURN:
1030 * SUCCESS : TRUE
1031 * FAILURE : FALSE
1033 static LRESULT LISTVIEW_DeleteItem(HWND hwnd, INT nItem)
1035 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
1036 LONG lCtrlId = GetWindowLongA(hwnd, GWL_ID);
1037 LISTVIEW_ITEM *lpItem;
1038 NMLISTVIEW nmlv;
1039 BOOL 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;
1048 nmlv.iItem = nItem;
1049 SendMessageA(GetParent(hwnd), WM_NOTIFY, (WPARAM)lCtrlId,
1050 (LPARAM)&nmlv);
1052 /* remove item */
1053 lpItem = (LISTVIEW_ITEM*)DPA_DeletePtr (infoPtr->hdpaItems, nItem);
1054 if (lpItem != NULL)
1056 /* free item string */
1057 if ((lpItem->pszText != NULL) &&
1058 (lpItem->pszText != LPSTR_TEXTCALLBACKA))
1059 COMCTL32_Free (lpItem->pszText);
1061 /* free item */
1062 COMCTL32_Free (lpItem);
1065 /* decrement item counter */
1066 infoPtr->nItemCount--;
1068 /* reset some of the draw data */
1069 LISTVIEW_SetScroll(hwnd);
1071 bResult = TRUE;
1074 return bResult;
1077 /* << LISTVIEW_EditLabel >> */
1078 /* << LISTVIEW_EnsureVisible >> */
1080 /***
1081 * DESCRIPTION:
1082 * Searches for an item with specific characteristics.
1084 * PARAMETER(S):
1085 * [I] HWND32 : window handle
1086 * [I] INT32 : base item index
1087 * [I] LPLVFINDINFO : item information to look for
1089 * RETURN:
1090 * SUCCESS : index of item
1091 * FAILURE : -1
1093 static LRESULT LISTVIEW_FindItem(HWND hwnd, INT nStart,
1094 LPLVFINDINFO lpFindInfo)
1096 /* LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLong32A(hwnd, 0); */
1097 /* LISTVIEW_ITEM *lpItem; */
1098 /* INT32 nItem; */
1099 /* INT32 nEnd = infoPtr->nItemCount; */
1100 /* BOOL32 bWrap = FALSE; */
1101 /* if (nStart == -1) */
1102 /* nStart = 0; */
1103 /* else */
1104 /* nStart++ ; */
1105 /* if (lpFindInfo->flags & LVFI_PARAM) */
1106 /* { */
1107 /* for (nItem = nStart; nItem < nEnd; nItem++) */
1108 /* { */
1109 /* get item pointer */
1110 /* lpItem = (LISTVIEW_ITEM *)DPA_GetPtr(infoPtr->hdpaItems, nItem); */
1111 /* if (lpItem != NULL) */
1112 /* { */
1113 /* if (lpFindInfo->lParam == lpItem->lParam) */
1114 /* return nItem; */
1115 /* } */
1116 /* } */
1117 /* } */
1118 /* else */
1119 /* { */
1120 /* if (lpFindInfo->flags & LVFI_PARTIAL) */
1121 /* { */
1122 /* for (nItem = nStart; nItem < nEnd; nItem++) */
1123 /* { */
1124 /* get item pointer */
1125 /* lpItem = (LISTVIEW_ITEM *)DPA_GetPtr(infoPtr->hdpaItems, nItem); */
1126 /* if (lpItem) */
1127 /* { */
1128 /* if (strncmp(lpItem->pszText, lpFindInfo->psz, strlen(lpFindInfo->psz)) */
1129 /* == 0) */
1130 /* return nItem; */
1131 /* } */
1132 /* } */
1133 /* } */
1135 /* if (lpFindInfo->flags & LVFI_STRING) */
1136 /* { */
1137 /* for (nItem = nStart; nItem < nEnd; nItem++) */
1138 /* { */
1139 /* get item pointer */
1140 /* lpItem = (LISTVIEW_ITEM *)DPA_GetPtr(infoPtr->hdpaItems, nItem); */
1141 /* if (lpItem != NULL) */
1142 /* { */
1143 /* if (strcmp(lpItem->pszText, lpFindInfo->psz) == 0) */
1144 /* return nItem; */
1145 /* } */
1146 /* } */
1147 /* } */
1149 /* if ((lpFindInfo->flags & LVFI_WRAP) && nStart) */
1150 /* { */
1151 /* nEnd = nStart; */
1152 /* nStart = 0; */
1153 /* bWrap = TRUE; */
1154 /* } */
1155 /* else */
1156 /* bWrap = FALSE; */
1158 return -1;
1161 /***
1162 * DESCRIPTION:
1163 * Retrieves the background color of the listview control.
1165 * PARAMETER(S):
1166 * [I] HWND32 : window handle
1168 * RETURN:
1169 * COLORREF associated with the background.
1171 static LRESULT LISTVIEW_GetBkColor(HWND hwnd)
1173 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
1175 return infoPtr->clrBk;
1178 /***
1179 * DESCRIPTION:
1180 * Retrieves the background image of the listview control.
1182 * PARAMETER(S):
1183 * [I] HWND32 : window handle
1184 * [O] LPLVMKBIMAGE : background image information
1186 * RETURN:
1187 * SUCCESS : TRUE
1188 * FAILURE : FALSE
1190 /* static LRESULT LISTVIEW_GetBkImage(HWND32 hwnd, LPLVBKIMAGE lpBkImage) */
1191 /* { */
1192 /* return FALSE; */
1193 /* } */
1195 /* << LISTVIEW_GetCallbackMask >> */
1197 /***
1198 * DESCRIPTION:
1199 * Retrieves column attributes.
1201 * PARAMETER(S):
1202 * [I] HWND32 : window handle
1203 * [I] INT32 : column index
1204 * [IO] LPLVCOLUMN32A : column information
1206 * RETURN:
1207 * SUCCESS : TRUE
1208 * FAILURE : FALSE
1210 static LRESULT LISTVIEW_GetColumnA(HWND hwnd, INT nIndex,
1211 LPLVCOLUMNA lpColumn)
1213 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
1214 HDITEMA hdi;
1216 if (lpColumn == NULL)
1217 return FALSE;
1219 ZeroMemory (&hdi, sizeof(HDITEMA));
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 (!SendMessageA (infoPtr->hwndHeader, HDM_GETITEMA,
1237 (WPARAM)nIndex, (LPARAM)&hdi))
1238 return FALSE;
1240 if (lpColumn->mask & LVCF_FMT)
1242 lpColumn->fmt = 0;
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 lstrcpynA (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;
1267 return TRUE;
1270 /* << LISTVIEW_GetColumn32W >> */
1271 /* << LISTVIEW_GetColumnOrderArray >> */
1273 /***
1274 * DESCRIPTION:
1275 * Retrieves the column width when list or report display mode.
1277 * PARAMETER(S):
1278 * [I] HWND32 : window handle
1279 * [I] int32 : column index
1281 * RETURN:
1282 * SUCCESS : column width
1283 * FAILURE : zero
1285 static LRESULT LISTVIEW_GetColumnWidth(HWND hwnd, INT nColumn)
1287 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
1288 LONG lStyle = GetWindowLongA(hwnd, GWL_STYLE);
1289 HDITEMA hdi;
1290 INT 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 (SendMessageA (infoPtr->hwndHeader, HDM_GETITEMA,
1304 (WPARAM)nColumn, (LPARAM)&hdi))
1305 nColumnWidth = hdi.cxy;
1309 return nColumnWidth;
1312 /***
1313 * DESCRIPTION:
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.
1318 * PARAMETER(S):
1319 * [I] HWND32 : window handle
1321 * RETURN:
1322 * Number of fully visible items.
1324 static LRESULT LISTVIEW_GetCountPerPage(HWND hwnd)
1326 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
1327 LONG lStyle = GetWindowLongA(hwnd, GWL_STYLE);
1328 INT nItemCount = 0;
1329 INT nItemCountPerRow = LISTVIEW_GetItemCountPerRow(hwnd);
1330 INT 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;
1348 return nItemCount;
1351 /* << LISTVIEW_GetEditControl >> */
1352 /* << LISTVIEW_GetExtendedListViewStyle >> */
1354 /***
1355 * DESCRIPTION:
1356 * Retrieves a header handle.
1358 * PARAMETER(S):
1359 * [I] HWND32 : window handle
1361 * RETURN:
1362 * Header handle.
1364 static LRESULT LISTVIEW_GetHeader(HWND hwnd)
1366 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
1368 return infoPtr->hwndHeader;
1371 /* << LISTVIEW_GetHotCursor >> */
1372 /* << LISTVIEW_GetHotItem >> */
1373 /* << LISTVIEW_GetHoverTime >> */
1375 /***
1376 * DESCRIPTION:
1377 * Retrieves an image list handle.
1379 * PARAMETER(S):
1380 * [I] HWND32 : window handle
1381 * [I] INT32 : image list identifier
1383 * RETURN:
1384 * SUCCESS : image list handle
1385 * FAILURE : NULL
1387 static LRESULT LISTVIEW_GetImageList(HWND hwnd, INT nImageList)
1389 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
1390 HIMAGELIST himl = NULL;
1392 switch (nImageList)
1394 case LVSIL_NORMAL:
1395 himl = infoPtr->himlNormal;
1396 case LVSIL_SMALL:
1397 himl = infoPtr->himlSmall;
1398 case LVSIL_STATE:
1399 himl = infoPtr->himlState;
1402 return (LRESULT)himl;
1406 /* << LISTVIEW_GetISearchString >> */
1408 /***
1409 * DESCRIPTION:
1410 * Retrieves item attributes.
1412 * PARAMETER(S):
1413 * [I] HWND32 : window handle
1414 * [IO] LPLVITEM32A : item info
1416 * RETURN:
1417 * SUCCESS : TRUE
1418 * FAILURE : FALSE
1420 static LRESULT LISTVIEW_GetItemA(HWND hwnd, LPLVITEMA lpItem)
1422 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
1423 LISTVIEW_ITEM *lpListItem;
1424 BOOL bResult = FALSE;
1426 if (lpItem != NULL)
1428 if ((lpItem->iItem >= 0) && (lpItem->iItem < infoPtr->nItemCount))
1430 /* get item */
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_TEXTCALLBACKA)
1445 lpItem->pszText = LPSTR_TEXTCALLBACKA;
1446 else
1447 Str_GetPtrA(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;
1460 bResult = TRUE;
1466 return bResult;
1469 /* << LISTVIEW_GetItem32W >> */
1470 /* << LISTVIEW_GetHotCursor >> */
1471 /* << LISTVIEW_GetHotItem >> */
1472 /* << LISTVIEW_GetHoverTime >> */
1474 /***
1475 * DESCRIPTION:
1476 * Retrieves the number of items in the listview control.
1478 * PARAMETER(S):
1479 * [I] HWND32 : window handle
1481 * RETURN:
1482 * Number of items.
1484 static LRESULT LISTVIEW_GetItemCount(HWND hwnd)
1486 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO*)GetWindowLongA(hwnd, 0);
1488 return infoPtr->nItemCount;
1491 /***
1492 * DESCRIPTION:
1493 * Retrieves the position (upper-left) of the listview control item.
1495 * PARAMETER(S):
1496 * [I] HWND32 : window handle
1497 * [I] INT32 : item index
1498 * [O] LPPOINT32 : coordinate information
1500 * RETURN:
1501 * SUCCESS : TRUE
1502 * FAILURE : FALSE
1504 static LRESULT LISTVIEW_GetItemPosition(HWND hwnd, INT nItem,
1505 LPPOINT lpPt)
1507 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
1508 LONG lStyle = GetWindowLongA(hwnd, GWL_STYLE);
1509 INT nColumn;
1510 INT nRow;
1511 BOOL bResult = FALSE;
1512 INT nItemCountPerColumn;
1513 INT nItemCountPerRow;
1514 INT nFirstItem;
1515 INT nLastItem;
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;
1533 /* get column */
1534 nColumn = nItem / nItemCountPerColumn;
1536 /* get row */
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;
1545 bResult = TRUE;
1548 else if (lStyle & LVS_REPORT)
1550 /* TO DO */
1552 else if (lStyle & LVS_SMALLICON)
1554 /* TO DO */
1556 else if (lStyle & LVS_ICON)
1558 /* TO DO */
1563 return bResult;
1566 /***
1567 * DESCRIPTION:
1568 * Retrieves the bounding rectangle for a listview control item.
1570 * PARAMETER(S):
1571 * [I] HWND32 : window handle
1572 * [I] INT32 : item index
1573 * [IO] LPRECT32 : bounding rectangle coordinates
1575 * RETURN:
1576 * SUCCESS : TRUE
1577 * FAILURE : FALSE
1579 static LRESULT LISTVIEW_GetItemRect(HWND hwnd, INT nItem, LPRECT lpRect)
1581 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
1582 LISTVIEW_ITEM *lpItem;
1583 POINT pt;
1584 INT nLabelWidth;
1585 BOOL bResult = FALSE;
1586 INT nSmallIconWidth;
1588 nSmallIconWidth = GetSystemMetrics(SM_CXSMICON);
1590 if ((nItem < 0) || (nItem >= infoPtr->nItemCount) || (lpRect == NULL))
1591 return FALSE;
1593 /* get item */
1594 lpItem = (LISTVIEW_ITEM *)DPA_GetPtr(infoPtr->hdpaItems, nItem);
1595 if (lpItem == NULL)
1596 return FALSE;
1598 if (!SendMessageA(hwnd, LVM_GETITEMPOSITION, (WPARAM)nItem, (LPARAM)&pt))
1599 return FALSE;
1601 nLabelWidth = SendMessageA(hwnd, LVM_GETSTRINGWIDTHA, (WPARAM)0,
1602 (LPARAM)lpItem->pszText);
1603 switch(lpRect->left)
1605 case LVIR_BOUNDS:
1606 lpRect->left = pt.x;
1607 lpRect->top = pt.y;
1608 lpRect->right = lpRect->left + nSmallIconWidth + nLabelWidth;
1609 lpRect->bottom = lpRect->top + infoPtr->nItemHeight;
1610 bResult = TRUE;
1611 break;
1612 case LVIR_ICON:
1613 lpRect->left = pt.x;
1614 lpRect->top = pt.y;
1615 lpRect->right = lpRect->left + nSmallIconWidth;
1616 lpRect->bottom = lpRect->top + infoPtr->nItemHeight;
1617 bResult = TRUE;
1618 break;
1619 case LVIR_LABEL:
1620 lpRect->left = pt.x + nSmallIconWidth;
1621 lpRect->top = pt.y;
1622 lpRect->right = lpRect->left + nLabelWidth;
1623 lpRect->bottom = infoPtr->nItemHeight;
1624 bResult = TRUE;
1625 break;
1626 case LVIR_SELECTBOUNDS:
1627 /* TO DO */
1628 break;
1631 return bResult;
1634 /***
1635 * DESCRIPTION:
1636 * Retrieves the spacing between listview control items.
1638 * PARAMETER(S):
1639 * [I] HWND32 : window handle
1640 * [I] BOOL32 : small icon (TRUE) or large icon (FALSE)
1642 * RETURN:
1643 * Horizontal + vertical spacing
1645 static LRESULT LISTVIEW_GetItemSpacing(HWND hwnd, BOOL bSmall)
1647 INT nSmallIconHSpacing;
1648 INT nSmallIconVSpacing;
1649 INT nIconHSpacing;
1650 INT nIconVSpacing;
1651 LONG lResult = 0;
1653 if (bSmall == TRUE)
1655 /* ??? */
1656 nSmallIconHSpacing = 0;
1657 nSmallIconVSpacing = 0;
1658 lResult = MAKELONG(nSmallIconHSpacing, nSmallIconVSpacing);
1660 else
1662 nIconHSpacing = GetSystemMetrics(SM_CXICONSPACING);
1663 nIconVSpacing = GetSystemMetrics(SM_CYICONSPACING);
1664 lResult = MAKELONG(nIconHSpacing, nIconVSpacing);
1667 return lResult;
1670 /***
1671 * DESCRIPTION:
1672 * Retrieves the state of a listview control item.
1674 * PARAMETER(S):
1675 * [I] HWND32 : window handle
1676 * [I] INT32 : item index
1677 * [I] UINT32 : state mask
1679 * RETURN:
1680 * State specified by the mask.
1682 static LRESULT LISTVIEW_GetItemState(HWND hwnd, INT nItem, UINT uMask)
1684 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
1685 LISTVIEW_ITEM *lpItem;
1686 INT nState = 0;
1688 if ((nItem >= 0) && (nItem < infoPtr->nItemCount))
1690 lpItem = (LISTVIEW_ITEM *)DPA_GetPtr(infoPtr->hdpaItems, nItem);
1691 if (lpItem != NULL)
1692 nState = lpItem->state & uMask;
1695 return nState;
1698 /***
1699 * DESCRIPTION:
1700 * Retrieves the text of a listview control item or subitem.
1702 * PARAMETER(S):
1703 * [I] HWND32 : window handle
1704 * [I] INT32 : item index
1705 * [IO] LPLVITEM32A : item information
1707 * RETURN:
1708 * None
1710 static VOID LISTVIEW_GetItemTextA(HWND hwnd, INT nItem,
1711 LPLVITEMA lpItem)
1713 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
1714 LISTVIEW_ITEM *lpListItem;
1716 if ((nItem < 0) || (nItem >= infoPtr->nItemCount) || (lpItem == NULL))
1717 return;
1719 lpListItem = (LISTVIEW_ITEM *)DPA_GetPtr(infoPtr->hdpaItems, nItem);
1720 if (lpListItem == NULL)
1721 return;
1723 lpListItem += lpItem->iSubItem;
1724 if (lpListItem == NULL)
1725 return;
1727 if (lpListItem->pszText == LPSTR_TEXTCALLBACKA)
1728 lpItem->pszText = LPSTR_TEXTCALLBACKA;
1729 else
1730 Str_GetPtrA(lpListItem->pszText, lpItem->pszText, lpItem->cchTextMax);
1733 /***
1734 * DESCRIPTION:
1735 * Searches for an item based on properties + relationships.
1737 * PARAMETER(S):
1738 * [I] HWND32 : window handle
1739 * [I] INT32 : item index
1740 * [I] UINT32 : relationship flag
1742 * RETURN:
1743 * SUCCESS : item index
1744 * FAILURE : -1
1746 static LRESULT LISTVIEW_GetNextItem (HWND hwnd, INT nItem, UINT uFlags)
1748 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
1749 INT nResult = -1;
1751 /* start at begin */
1752 if (nItem == -1)
1753 nItem = 0;
1755 if ((nItem >= 0) && (nItem < infoPtr->nItemCount))
1757 /* TO DO */
1760 return nResult;
1763 /* << LISTVIEW_GetNumberOfWorkAreas >> */
1765 /***
1766 * DESCRIPTION:
1767 * Retrieves the current origin when in icon or small icon display mode.
1769 * PARAMETER(S):
1770 * [I] HWND32 : window handle
1771 * [O] LPPOINT32 : coordinate information
1773 * RETURN:
1774 * SUCCESS : TRUE
1775 * FAILURE : FALSE
1777 static LRESULT LISTVIEW_GetOrigin(HWND hwnd, LPPOINT lpOrigin)
1779 LONG lStyle = GetWindowLongA(hwnd, GWL_ID);
1780 BOOL bResult = FALSE;
1782 if (lStyle & LVS_SMALLICON)
1784 /* TO DO */
1786 else if (lStyle & LVS_ICON)
1788 /* TO DO */
1791 return bResult;
1794 /***
1795 * DESCRIPTION:
1796 * Retrieves the number of items that are marked as selected.
1798 * PARAMETER(S):
1799 * [I] HWND32 : window handle
1801 * RETURN:
1802 * Number of items selected.
1804 static LRESULT LISTVIEW_GetSelectedCount(HWND hwnd)
1806 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
1807 LISTVIEW_ITEM *lpItem;
1808 INT nSelectedCount = 0;
1809 INT i;
1811 for (i = 0; i < infoPtr->nItemCount; i++)
1813 lpItem = (LISTVIEW_ITEM *)DPA_GetPtr(infoPtr->hdpaItems, i);
1814 if (lpItem != NULL)
1816 if (lpItem->state & LVIS_SELECTED)
1817 nSelectedCount++;
1821 return nSelectedCount;
1824 /***
1825 * DESCRIPTION:
1826 * Retrieves item index that marks the start of a multiple selection.
1828 * PARAMETER(S):
1829 * [I] HWND32 : window handle
1831 * RETURN:
1832 * Index number or -1 if there is no selection mark.
1834 static LRESULT LISTVIEW_GetSelectionMark(HWND hwnd)
1836 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
1837 INT nResult = -1;
1839 if (SendMessageA(hwnd, LVM_GETSELECTEDCOUNT, (WPARAM)0, (LPARAM)0) != 0)
1840 nResult = infoPtr->nSelectionMark;
1842 return nResult;
1845 /***
1846 * DESCRIPTION:
1847 * Retrieves the width of a string.
1849 * PARAMETER(S):
1850 * [I] HWND32 : window handle
1852 * RETURN:
1853 * SUCCESS : string width (in pixels)
1854 * FAILURE : zero
1856 static LRESULT LISTVIEW_GetStringWidthA(HWND hwnd, LPCSTR lpsz)
1858 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
1859 HFONT hFont, hOldFont;
1860 HDC hdc;
1861 SIZE textSize;
1862 INT nResult = 0;
1864 if (lpsz != NULL)
1866 hFont = infoPtr->hFont ? infoPtr->hFont : GetStockObject (SYSTEM_FONT);
1867 hdc = GetDC(hwnd);
1868 hOldFont = SelectObject (hdc, hFont);
1869 GetTextExtentPoint32A(hdc, lpsz, lstrlenA(lpsz), &textSize);
1870 SelectObject (hdc, hOldFont);
1871 ReleaseDC(hwnd, hdc);
1872 nResult = textSize.cx;
1875 return nResult;
1878 /***
1879 * DESCRIPTION:
1880 * Retrieves the text backgound color.
1882 * PARAMETER(S):
1883 * [I] HWND32 : window handle
1885 * RETURN:
1886 * COLORREF associated with the the background.
1888 static LRESULT LISTVIEW_GetTextBkColor(HWND hwnd)
1890 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO*)GetWindowLongA(hwnd, 0);
1892 return infoPtr->clrTextBk;
1895 /***
1896 * DESCRIPTION:
1897 * Retrieves the text color.
1899 * PARAMETER(S):
1900 * [I] HWND32 : window handle
1902 * RETURN:
1903 * COLORREF associated with the text.
1905 static LRESULT LISTVIEW_GetTextColor(HWND hwnd)
1907 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO*)GetWindowLongA(hwnd, 0);
1909 return infoPtr->clrText;
1912 /***
1913 * DESCRIPTION:
1914 * Retrieves the bounding rectangle of all the items.
1916 * PARAMETER(S):
1917 * [I] HWND32 : window handle
1918 * [O] LPRECT32 : bounding rectangle
1920 * RETURN:
1921 * SUCCESS : TRUE
1922 * FAILURE : FALSE
1924 static LRESULT LISTVIEW_GetViewRect(HWND hwnd, LPRECT lpBoundingRect)
1926 /* LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLong32A(hwnd, 0); */
1927 LONG lStyle = GetWindowLongA(hwnd, GWL_STYLE);
1928 BOOL bResult = FALSE;
1930 if (lpBoundingRect != NULL)
1932 if ((lStyle & LVS_ICON) || (lStyle & LVS_SMALLICON))
1934 /* TO DO */
1938 return bResult;
1941 /***
1942 * DESCRIPTION:
1943 * Determines item index when in small icon view.
1945 * PARAMETER(S):
1946 * [I] HWND32 : window handle
1947 * [IO] LPLVHITTESTINFO : hit test information
1949 * RETURN:
1950 * SUCCESS : item index
1951 * FAILURE : -1
1953 static LRESULT HitTestSmallIconView(HWND hwnd, LPLVHITTESTINFO lpHitTestInfo)
1955 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
1956 LISTVIEW_ITEM *lpItem;
1957 INT nColumn;
1958 INT nRow;
1959 INT nItem = 0;
1960 INT nLabelWidth;
1961 INT nOffset;
1962 INT nPosX = 0;
1963 INT nSmallIconWidth;
1964 INT nItemCountPerRow;
1966 /* get column */
1967 nColumn = lpHitTestInfo->pt.x / infoPtr->nColumnWidth;
1969 /* get row */
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 = GetSystemMetrics(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)
1985 /* get item */
1986 lpItem = (LISTVIEW_ITEM *)DPA_GetPtr(infoPtr->hdpaItems, nItem);
1987 if (lpItem != NULL)
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;
1997 return nItem;
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;
2009 return nItem;
2013 /* get width of label in pixels */
2014 nLabelWidth = SendMessageA(hwnd, LVM_GETSTRINGWIDTHA, (WPARAM)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;
2023 return nItem;
2028 /* hit is not on an item */
2029 lpHitTestInfo->flags = LVHT_NOWHERE;
2031 return -1;
2034 /***
2035 * DESCRIPTION:
2036 * Determines item index when in list display mode.
2038 * PARAMETER(S):
2039 * [I] HWND32 : window handle
2040 * [IO] LPLVHITTESTINFO : hit test information
2042 * RETURN:
2043 * SUCCESS : item index
2044 * FAILURE : -1
2046 static LRESULT HitTestListView(HWND hwnd, LPLVHITTESTINFO lpHitTestInfo)
2048 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
2049 LISTVIEW_ITEM *lpItem;
2050 INT nColumn;
2051 INT nRow;
2052 INT nItem = 0;
2053 INT nLabelWidth;
2054 INT nOffset;
2055 INT nPosX = 0;
2056 INT nSmallIconWidth;
2057 INT nItemCountPerColumn;
2059 /* get column */
2060 nColumn = lpHitTestInfo->pt.x / infoPtr->nColumnWidth;
2062 /* get row */
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 = GetSystemMetrics(SM_CXSMICON);
2071 /* calculate index */
2072 nItemCountPerColumn = LISTVIEW_GetItemCountPerColumn(hwnd);
2073 nItem = (nColumn * nItemCountPerColumn + LISTVIEW_GetFirstVisibleItem(hwnd)
2074 + nRow);
2076 /* verify existance of item */
2077 if (nItem < infoPtr->nItemCount)
2079 /* get item */
2080 lpItem = (LISTVIEW_ITEM *)DPA_GetPtr(infoPtr->hdpaItems, nItem);
2081 if (lpItem != NULL)
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;
2091 return nItem;
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;
2103 return nItem;
2107 /* get width of label in pixels */
2108 nLabelWidth = SendMessageA(hwnd, LVM_GETSTRINGWIDTHA, (WPARAM)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;
2117 return nItem;
2122 /* hit is not on an item */
2123 lpHitTestInfo->flags = LVHT_NOWHERE;
2125 return -1;
2128 /***
2129 * DESCRIPTION:
2130 * Determines wich listview item is located at the specified position.
2132 * PARAMETER(S):
2133 * [I] HWND32 : window handle
2134 * [IO} LPLVHITTESTINFO : hit test information
2136 * RETURN:
2137 * SUCCESS : item index
2138 * FAILURE : -1
2140 static LRESULT LISTVIEW_HitTest(HWND hwnd, LPLVHITTESTINFO lpHitTestInfo)
2142 LONG lStyle = GetWindowLongA(hwnd, GWL_STYLE);
2144 if (lStyle & LVS_LIST)
2145 return HitTestListView(hwnd, lpHitTestInfo);
2146 else if (lStyle & LVS_REPORT)
2148 /* TO DO */
2150 else if (lStyle & LVS_SMALLICON)
2152 return HitTestSmallIconView(hwnd, lpHitTestInfo);
2154 else if (lStyle & LVS_ICON)
2156 /* TO DO */
2159 return -1;
2162 /***
2163 * DESCRIPTION:
2164 * Inserts a new column.
2166 * PARAMETER(S):
2167 * [I] HWND32 : window handle
2168 * [I] INT32 : column index
2169 * [I] LPLVCOLUMN32A : column information
2171 * RETURN:
2172 * SUCCESS : new column index
2173 * FAILURE : -1
2175 static LRESULT LISTVIEW_InsertColumnA(HWND hwnd, INT nIndex,
2176 LPLVCOLUMNA lpColumn)
2178 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO*)GetWindowLongA(hwnd, 0);
2179 HDITEMA hdi;
2180 INT nResult;
2182 if ((lpColumn == NULL) || (infoPtr->nItemCount > 0))
2183 return -1;
2185 FIXME (listview, "(%d %p): semi stub!\n", nIndex, lpColumn);
2187 /* initialize memory */
2188 ZeroMemory (&hdi, sizeof(HDITEMA));
2190 if (lpColumn->mask & LVCF_FMT)
2192 if (nIndex == 0)
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 = SendMessageA (infoPtr->hwndHeader, HDM_INSERTITEMA,
2232 (WPARAM)nIndex, (LPARAM)&hdi);
2233 if (nResult == -1)
2234 return -1;
2236 /* increment column counter */
2237 infoPtr->nColumnCount++;
2239 return nResult;
2242 /* << LISTVIEW_InsertColumn32W >> */
2244 /***
2245 * DESCRIPTION:
2246 * Inserts a new item in the listview control.
2248 * PARAMETER(S):
2249 * [I] HWND32 : window handle
2250 * [I] LPLVITEM32A : item information
2252 * RETURN:
2253 * SUCCESS : new item index
2254 * FAILURE : -1
2256 static LRESULT LISTVIEW_InsertItemA(HWND hwnd, LPLVITEMA lpItem)
2258 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
2259 LONG lStyle = GetWindowLongA(hwnd, GWL_STYLE);
2260 LONG lCtrlId = GetWindowLongA(hwnd, GWL_ID);
2261 LISTVIEW_ITEM *lpListItem;
2262 INT nItem;
2263 NMLISTVIEW nmlv;
2264 LVITEMA lvItem;
2265 INT nColumnWidth = 0;
2266 INT nSmallIconWidth;
2268 if (lpItem == NULL)
2269 return -1;
2271 if (lpItem->iSubItem != 0)
2272 return -1;
2274 /* allocate memory */
2275 lpListItem = (LISTVIEW_ITEM *)COMCTL32_Alloc(sizeof(LISTVIEW_ITEM));
2276 if (lpListItem == NULL)
2277 return -1;
2279 nSmallIconWidth = GetSystemMetrics(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_TEXTCALLBACKA)
2289 if ((lStyle & LVS_SORTASCENDING) || (lStyle & LVS_SORTDESCENDING))
2290 return -1;
2292 lpListItem->pszText = LPSTR_TEXTCALLBACKA;
2294 else
2296 nColumnWidth = SendMessageA(hwnd, LVM_GETSTRINGWIDTHA,
2297 (WPARAM)0, (LPARAM)lpItem->pszText);
2299 /* add padding for separating columns */
2300 nColumnWidth += 10;
2302 /* calculate column width; make sure it's at least 96 pixels */
2303 if (nColumnWidth < 96)
2304 nColumnWidth = 96;
2306 Str_SetPtrA(&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(LVITEMA));
2316 lvItem.stateMask = LVIS_FOCUSED;
2317 lvItem.state = 0;
2318 SendMessageA(hwnd, LVM_SETITEMSTATE, (WPARAM)-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);
2338 if (nItem == -1)
2339 return -1;
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;
2364 nmlv.iItem = nItem;
2365 SendMessageA(GetParent (hwnd), WM_NOTIFY, (WPARAM)lCtrlId,
2366 (LPARAM)&nmlv);
2368 InvalidateRect(hwnd, NULL, FALSE);
2369 UpdateWindow(hwnd);
2371 return nItem;
2374 /* << LISTVIEW_InsertItem32W >> */
2376 /***
2377 * DESCRIPTION:
2378 * Redraws a range of items.
2380 * PARAMETER(S):
2381 * [I] HWND32 : window handle
2382 * [I] INT32 : first item
2383 * [I] INT32 : last item
2385 * RETURN:
2386 * SUCCESS : TRUE
2387 * FAILURE : FALSE
2389 static LRESULT LISTVIEW_RedrawItems(HWND hwnd, INT nFirst, INT nLast)
2391 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
2393 if (nFirst > nLast)
2394 return FALSE;
2396 if ((nFirst < 0) || (nFirst >= infoPtr->nItemCount))
2397 return FALSE;
2399 if ((nLast < 0) || (nLast >= infoPtr->nItemCount))
2400 return FALSE;
2402 /* TO DO */
2404 return TRUE;
2407 /***
2408 * DESCRIPTION:
2409 * Scrolls the content of a listview.
2411 * PARAMETER(S):
2412 * [I] HWND32 : window handle
2413 * [I] INT32 : amount of horizontal scrolling
2414 * [I] INT32 : amount of vertical scrolling
2416 * RETURN:
2417 * SUCCESS : TRUE
2418 * FAILURE : FALSE
2420 static LRESULT LISTVIEW_Scroll(HWND hwnd, INT nHScroll, INT nVScroll)
2422 LONG lStyle = GetWindowLongA(hwnd, GWL_STYLE);
2423 BOOL bResult = FALSE;
2424 INT nHScrollPos;
2425 INT nMinRange;
2426 INT nMaxRange;
2428 if (lStyle & LVS_LIST)
2430 nHScrollPos = GetScrollPos(hwnd, SB_HORZ);
2431 GetScrollRange(hwnd, SB_HORZ, &nMinRange, &nMaxRange);
2433 if ((nMinRange <= nHScrollPos + nHScroll) &&
2434 (nHScrollPos + nHScroll <= nMaxRange))
2436 bResult = TRUE;
2437 nHScrollPos += nHScroll;
2438 SetScrollPos(hwnd, SB_HORZ, nHScrollPos, TRUE);
2440 /* refresh client area */
2441 InvalidateRect(hwnd, NULL, TRUE);
2442 UpdateWindow(hwnd);
2445 else if (lStyle & LVS_REPORT)
2447 /* TO DO */
2449 else if (lStyle & LVS_SMALLICON)
2451 /* TO DO */
2453 else if (lStyle & LVS_ICON)
2455 /* TO DO */
2458 return bResult;
2461 /***
2462 * DESCRIPTION:
2463 * Sets the background color.
2465 * PARAMETER(S):
2466 * [I] HWND32 : window handle
2467 * [I] COLORREF : background color
2469 * RETURN:
2470 * SUCCESS : TRUE
2471 * FAILURE : FALSE
2473 static LRESULT LISTVIEW_SetBkColor(HWND hwnd, COLORREF clrBk)
2475 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
2477 infoPtr->clrBk = clrBk;
2478 InvalidateRect(hwnd, NULL, TRUE);
2480 return TRUE;
2483 /***
2484 * DESCRIPTION:
2485 * Sets column attributes.
2487 * PARAMETER(S):
2488 * [I] HWND32 : window handle
2489 * [I] INT32 : column index
2490 * [I] LPLVCOLUMN32A : column information
2492 * RETURN:
2493 * SUCCESS : TRUE
2494 * FAILURE : FALSE
2496 static LRESULT LISTVIEW_SetColumnA(HWND hwnd, INT nIndex,
2497 LPLVCOLUMNA lpColumn)
2499 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
2500 HDITEMA hdi;
2502 if (lpColumn == NULL)
2503 return -1;
2505 /* initialize memory */
2506 ZeroMemory (&hdi, sizeof(HDITEMA));
2508 if (lpColumn->mask & LVCF_FMT)
2510 if (nIndex == 0)
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)SendMessageA (infoPtr->hwndHeader, HDM_SETITEMA,
2551 (WPARAM)nIndex, (LPARAM)&hdi);
2554 /***
2555 * DESCRIPTION:
2556 * Sets image list.
2558 * PARAMETER(S):
2559 * [I] HWND32 : window handle
2560 * [I] INT32 : image list type
2561 * [I] HIMAGELIST : image list handle
2563 * RETURN:
2564 * SUCCESS : old image list
2565 * FAILURE : NULL
2567 static LRESULT LISTVIEW_SetImageList(HWND hwnd, INT nType, HIMAGELIST himl)
2569 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
2570 HIMAGELIST himlTemp = 0;
2572 switch (nType)
2574 case LVSIL_NORMAL:
2575 himlTemp = infoPtr->himlNormal;
2576 infoPtr->himlNormal = himl;
2577 return (LRESULT)himlTemp;
2578 case LVSIL_SMALL:
2579 himlTemp = infoPtr->himlSmall;
2580 infoPtr->himlSmall = himl;
2581 return (LRESULT)himlTemp;
2582 case LVSIL_STATE:
2583 himlTemp = infoPtr->himlState;
2584 infoPtr->himlState = himl;
2585 return (LRESULT)himlTemp;
2588 return (LRESULT)NULL;
2592 /***
2593 * DESCRIPTION:
2594 * Sets item attributes.
2596 * PARAMETER(S):
2597 * [I] HWND32 : window handle
2598 * [I] LPLVITEM32 : item information
2600 * RETURN:
2601 * SUCCESS : TRUE
2602 * FAILURE : FALSE
2604 static LRESULT LISTVIEW_SetItemA(HWND hwnd, LPLVITEMA lpItem)
2606 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
2607 LONG lCtrlId = GetWindowLongA(hwnd, GWL_ID);
2608 LISTVIEW_ITEM *lpListItem;
2609 NMLISTVIEW nmlv;
2611 if (lpItem == NULL)
2612 return FALSE;
2614 if ((lpItem->iItem < 0) || (lpItem->iItem >= infoPtr->nItemCount))
2615 return FALSE;
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 (SendMessageA(GetParent(hwnd), WM_NOTIFY, (WPARAM)lCtrlId,
2626 (LPARAM)&nmlv) == FALSE)
2627 return FALSE;
2629 /* get item */
2630 lpListItem = DPA_GetPtr(infoPtr->hdpaItems, lpItem->iItem);
2631 if (lpListItem == NULL)
2632 return FALSE;
2634 /* copy valid data */
2635 if (lpItem->iSubItem > 0)
2637 /* verify existance of sub-item */
2638 lpListItem += lpItem->iSubItem;
2639 if (lpListItem == NULL)
2640 return FALSE;
2642 /* exit if indent attribute is valid */
2643 if (lpItem->mask & LVIF_INDENT)
2644 return FALSE;
2646 if (lpItem->mask & LVIF_IMAGE)
2648 /* set sub-item attribute */
2652 else
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_TEXTCALLBACKA)
2674 if ((lpListItem->pszText != NULL) &&
2675 (lpListItem->pszText != LPSTR_TEXTCALLBACKA))
2676 COMCTL32_Free (lpListItem->pszText);
2678 lpListItem->pszText = LPSTR_TEXTCALLBACKA;
2680 else
2682 if (lpListItem->pszText == LPSTR_TEXTCALLBACKA)
2683 lpListItem->pszText = NULL;
2685 if (Str_SetPtrA(&lpListItem->pszText, lpItem->pszText) == FALSE)
2686 return FALSE;
2690 /* send LVN_ITEMCHANGED notification */
2691 nmlv.hdr.code = LVN_ITEMCHANGED;
2692 SendMessageA(GetParent(hwnd), WM_NOTIFY, (WPARAM)lCtrlId,
2693 (LPARAM)&nmlv);
2695 return TRUE;
2698 /* << LISTVIEW_SetItem32W >> */
2700 /* LISTVIEW_SetItemCount*/
2702 /***
2703 * DESCRIPTION:
2704 * Sets item position.
2706 * PARAMETER(S):
2707 * [I] HWND32 : window handle
2708 * [I] INT32 : item index
2709 * [I] INT32 : x coordinate
2710 * [I] INT32 : y coordinate
2712 * RETURN:
2713 * SUCCESS : TRUE
2714 * FAILURE : FALSE
2716 static LRESULT LISTVIEW_SetItemPosition(HWND hwnd, INT nItem,
2717 INT nPosX, INT nPosY)
2719 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO*)GetWindowLongA(hwnd, 0);
2720 LONG lStyle = GetWindowLongA(hwnd, GWL_STYLE);
2722 if ((nItem < 0) || (nItem >= infoPtr->nItemCount))
2723 return FALSE;
2725 if ((lStyle & LVS_ICON) && (lStyle & LVS_SMALLICON))
2727 /* get item */
2729 /* set position of item */
2731 /* refresh */
2732 if (lStyle & LVS_AUTOARRANGE)
2734 InvalidateRect(hwnd, NULL, FALSE);
2735 UpdateWindow(hwnd);
2738 return TRUE;
2741 return FALSE;
2744 /***
2745 * DESCRIPTION:
2746 * Sets the state of one or many items.
2748 * PARAMETER(S):
2749 * [I] HWND32 : window handle
2750 * [I]INT32 : item index
2751 * [I] LPLVITEM32 : item information
2753 * RETURN:
2754 * SUCCESS : TRUE
2755 * FAILURE : FALSE
2757 static LRESULT LISTVIEW_SetItemState(HWND hwnd, INT nItem,
2758 LPLVITEMA lpItem)
2760 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
2761 LISTVIEW_ITEM *lpListItem;
2762 INT i;
2764 if (nItem == -1)
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)
2771 return FALSE;
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)
2781 return FALSE;
2783 /* set state */
2784 lpListItem->state &= ~lpItem->stateMask;
2785 lpListItem->state |= (lpItem->state & lpItem->stateMask);
2787 else
2788 return FALSE;
2790 return TRUE;
2793 /***
2794 * DESCRIPTION:
2795 * Sets the text background color.
2797 * PARAMETER(S):
2798 * [I] HWND32 : window handle
2799 * [I] COLORREF : text background color
2801 * RETURN:
2802 * SUCCESS : TRUE
2803 * FAILURE : FALSE
2805 static LRESULT LISTVIEW_SetTextBkColor(HWND hwnd, COLORREF clrTextBk)
2807 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
2809 infoPtr->clrTextBk = clrTextBk;
2811 return TRUE;
2814 /***
2815 * DESCRIPTION:
2816 * Sets the text background color.
2818 * PARAMETER(S):
2819 * [I] HWND32 : window handle
2820 * [I] COLORREF : text color
2822 * RETURN:
2823 * SUCCESS : TRUE
2824 * FAILURE : FALSE
2826 static LRESULT LISTVIEW_SetTextColor (HWND hwnd, COLORREF clrText)
2828 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
2830 infoPtr->clrText = clrText;
2832 return TRUE;
2835 /***
2836 * DESCRIPTION:
2837 * ??
2839 * PARAMETER(S):
2840 * [I] HWND32 : window handle
2842 * RETURN:
2843 * SUCCESS : TRUE
2844 * FAILURE : FALSE
2846 static LRESULT LISTVIEW_SortItems(HWND hwnd, WPARAM wParam, LPARAM lParam)
2848 /* LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO*)GetWindowLong32A(hwnd, 0); */
2850 FIXME (listview, "empty stub!\n");
2852 return TRUE;
2855 /***
2856 * DESCRIPTION:
2857 * Updates an items.
2859 * PARAMETER(S):
2860 * [I] HWND32 : window handle
2861 * [I] INT32 : item index
2863 * RETURN:
2864 * SUCCESS : TRUE
2865 * FAILURE : FALSE
2867 static LRESULT LISTVIEW_Update(HWND hwnd, INT nItem)
2869 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO*)GetWindowLongA(hwnd, 0);
2870 LONG lStyle = GetWindowLongA(hwnd, GWL_STYLE);
2871 RECT rcItemRect;
2872 BOOL bResult = FALSE;
2874 if ((nItem >= 0) || (nItem < infoPtr->nItemCount))
2876 /* get item bounding rectangle */
2877 rcItemRect.left = LVIR_BOUNDS;
2878 SendMessageA(hwnd, LVM_GETITEMRECT, (WPARAM)nItem,
2879 (LPARAM)&rcItemRect);
2881 InvalidateRect(hwnd, &rcItemRect, FALSE);
2883 /* rearrange with default alignment style */
2884 if ((lStyle & LVS_AUTOARRANGE) &&
2885 ((lStyle & LVS_ICON) || (lStyle & LVS_SMALLICON)))
2886 SendMessageA(hwnd, LVM_ARRANGE, (WPARAM)LVA_DEFAULT, (LPARAM)0);
2889 return bResult;
2892 /***
2893 * DESCRIPTION:
2894 * Creates a listview control.
2896 * PARAMETER(S):
2897 * [I] HWND32 : window handle
2899 * RETURN:
2900 * Zero
2902 static LRESULT LISTVIEW_Create(HWND hwnd, WPARAM wParam, LPARAM lParam)
2904 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
2905 LONG lStyle = GetWindowLongA(hwnd, GWL_STYLE);
2906 LOGFONTA logFont;
2907 HFONT hOldFont;
2908 HDC hdc;
2909 TEXTMETRICA tm;
2910 INT nSmallIconHeight;
2912 /* initialize color information */
2913 infoPtr->clrBk = GetSysColor(COLOR_WINDOW);
2914 infoPtr->clrText = GetSysColor(COLOR_WINDOWTEXT);
2915 infoPtr->clrTextBk = GetSysColor(COLOR_WINDOW);
2917 /* get default font (icon title) */
2918 SystemParametersInfoA (SPI_GETICONTITLELOGFONT, 0, &logFont, 0);
2919 infoPtr->hDefaultFont = CreateFontIndirectA (&logFont);
2920 infoPtr->hFont = infoPtr->hDefaultFont;
2922 /* initialize column width */
2923 infoPtr->nColumnWidth = 96;
2925 /* get text height */
2926 hdc = GetDC(hwnd);
2927 hOldFont = SelectObject(hdc, infoPtr->hFont);
2928 GetTextMetricsA(hdc, &tm);
2930 /* initialize item height with padding */
2931 if (!(lStyle & LVS_ICON))
2933 nSmallIconHeight = GetSystemMetrics(SM_CYSMICON);
2934 infoPtr->nItemHeight = max(tm.tmHeight, nSmallIconHeight) + 2;
2937 SelectObject(hdc, hOldFont);
2938 ReleaseDC(hwnd, hdc);
2940 /* create header */
2941 infoPtr->hwndHeader = CreateWindowA(WC_HEADERA, "", lStyle, 0, 0, 0, 0,
2942 hwnd, (HMENU)0,
2943 GetWindowLongA(hwnd, GWL_HINSTANCE),
2944 NULL);
2945 /* set header font */
2946 SendMessageA(infoPtr->hwndHeader, WM_SETFONT, (WPARAM)infoPtr->hFont,
2947 (LPARAM)TRUE);
2949 /* allocate memory */
2950 infoPtr->hdpaItems = DPA_Create (10);
2952 return 0;
2956 static LRESULT
2957 LISTVIEW_Destroy (HWND hwnd, WPARAM wParam, LPARAM lParam)
2959 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO*)GetWindowLongA(hwnd, 0);
2961 /* delete all items */
2962 LISTVIEW_DeleteAllItems(hwnd);
2964 /* destroy dpa */
2965 DPA_Destroy (infoPtr->hdpaItems);
2967 /* destroy header */
2968 if (infoPtr->hwndHeader)
2969 DestroyWindow (infoPtr->hwndHeader);
2971 /* destroy font */
2972 infoPtr->hFont = (HFONT)0;
2973 if (infoPtr->hDefaultFont)
2974 DeleteObject (infoPtr->hDefaultFont);
2976 infoPtr->nColumnWidth = 96;
2978 return 0;
2981 /***
2982 * DESCRIPTION:
2983 * Erases the background of the listview control
2985 * PARAMETER(S):
2986 * [I] HWND32 : window handle
2988 * RETURN:
2989 * SUCCESS : TRUE
2990 * FAILURE : FALSE
2992 static LRESULT LISTVIEW_EraseBackground(HWND hwnd, WPARAM wParam, LPARAM lParam)
2994 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
2995 BOOL bResult;
2997 if (infoPtr->clrBk == CLR_NONE)
2998 bResult = SendMessageA(GetParent(hwnd), WM_ERASEBKGND, wParam, lParam);
2999 else
3001 HBRUSH hBrush = CreateSolidBrush(infoPtr->clrBk);
3002 RECT clientRect;
3004 GetClientRect(hwnd, &clientRect);
3005 FillRect((HDC)wParam, &clientRect, hBrush);
3006 DeleteObject(hBrush);
3007 bResult = TRUE;
3010 return bResult;
3013 /***
3014 * DESCRIPTION:
3015 * Gets the listview control font.
3017 * PARAMETER(S):
3018 * [I] HWND32 : window handle
3020 * RETURN:
3021 * Font handle.
3023 static LRESULT LISTVIEW_GetFont(HWND hwnd)
3025 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
3027 return infoPtr->hFont;
3030 /***
3031 * DESCRIPTION:
3032 * Performs horizontal scrolling.
3034 * PARAMETER(S):
3035 * [I] HWND32 : window handle
3036 * [I] INT32 : scroll code
3037 * [I] INT32 : scroll position
3038 * [I] HWND32 : scrollbar control window handle
3040 * RETURN:
3041 * Zero
3043 static LRESULT LISTVIEW_HScroll(HWND hwnd, INT nScrollCode,
3044 INT nScrollPos, HWND hScrollWnd)
3046 LONG lStyle = GetWindowLongA(hwnd, GWL_STYLE);
3047 INT nHScrollPos;
3048 INT nMinRange;
3049 INT nMaxRange;
3051 GetScrollRange(hwnd, SB_HORZ, &nMinRange, &nMaxRange);
3052 nHScrollPos = GetScrollPos(hwnd, SB_HORZ);
3054 if (lStyle & LVS_LIST)
3056 switch (nScrollCode)
3058 case SB_LINELEFT:
3059 if (nHScrollPos > nMinRange)
3060 nHScrollPos--;
3061 break;
3062 case SB_LINERIGHT:
3063 if (nHScrollPos < nMaxRange)
3064 nHScrollPos++;
3065 break;
3066 case SB_PAGELEFT:
3067 if (nHScrollPos > nMinRange)
3068 nHScrollPos--;
3069 break;
3070 case SB_PAGERIGHT:
3071 if (nHScrollPos < nMaxRange)
3072 nHScrollPos++;
3073 break;
3074 case SB_THUMBPOSITION:
3075 nHScrollPos = nScrollPos;
3076 break;
3079 SetScrollPos(hwnd, SB_HORZ, nHScrollPos, TRUE);
3081 /* refresh client area */
3082 InvalidateRect(hwnd, NULL, TRUE);
3083 UpdateWindow(hwnd);
3086 return 0;
3089 /***
3090 * DESCRIPTION:
3091 * ?????
3093 * PARAMETER(S):
3094 * [I] HWND32 : window handle
3095 * [I] INT32 : virtual key
3096 * [I] LONG : key data
3098 * RETURN:
3099 * Zero
3101 static LRESULT LISTVIEW_KeyDown(HWND hwnd, INT nVirtualKey, LONG lKeyData)
3103 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
3104 LONG lStyle = GetWindowLongA(hwnd, GWL_STYLE);
3105 LONG lCtrlId = GetWindowLongA(hwnd, GWL_ID);
3106 HWND hwndParent = GetParent(hwnd);
3107 INT nItemCountPerColumn;
3108 INT nItemCountPerRow;
3109 NMHDR nmh;
3110 INT nColumn;
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)
3124 case VK_RETURN:
3125 if ((infoPtr->nItemCount > 0) && (infoPtr->nFocusedItem != -1))
3127 /* send NM_RETURN notification */
3128 nmh.code = NM_RETURN;
3129 SendMessageA(hwndParent, WM_NOTIFY, (WPARAM)lCtrlId, (LPARAM)&nmh);
3131 /* send LVN_ITEMACTIVATE notification */
3132 nmh.code = LVN_ITEMACTIVATE;
3133 SendMessageA(hwndParent, WM_NOTIFY, (WPARAM)lCtrlId, (LPARAM)&nmh);
3135 break;
3137 case VK_HOME:
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);
3147 break;
3149 case VK_END:
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);
3160 break;
3162 case VK_LEFT:
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;
3184 if (nColumn != 0)
3186 infoPtr->nFocusedItem -= 1;
3187 LISTVIEW_SetItemStates(hwnd, infoPtr->nFocusedItem, TRUE, FALSE);
3189 /* refresh display */
3190 InvalidateRect(hwnd, NULL, FALSE);
3191 UpdateWindow(hwnd);
3194 break;
3196 case VK_UP:
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);
3218 break;
3220 case VK_RIGHT:
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 InvalidateRect(hwnd, NULL, FALSE);
3246 UpdateWindow(hwnd);
3250 break;
3252 case VK_DOWN:
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);
3274 break;
3276 case VK_PRIOR:
3277 break;
3279 case VK_NEXT:
3280 break;
3283 return 0;
3286 /***
3287 * DESCRIPTION:
3288 * Kills the focus.
3290 * PARAMETER(S):
3291 * [I] HWND32 : window handle
3293 * RETURN:
3294 * Zero
3296 static LRESULT LISTVIEW_KillFocus(HWND hwnd)
3298 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO*)GetWindowLongA(hwnd, 0);
3299 LONG lCtrlId = GetWindowLongA(hwnd, GWL_ID);
3300 NMHDR nmh;
3302 nmh.hwndFrom = hwnd;
3303 nmh.idFrom = lCtrlId;
3304 nmh.code = NM_KILLFOCUS;
3305 SendMessageA(GetParent(hwnd), WM_NOTIFY, (WPARAM)lCtrlId,
3306 (LPARAM)&nmh);
3308 /* set window focus flag */
3309 infoPtr->bFocus = FALSE;
3311 return 0;
3314 /***
3315 * DESCRIPTION:
3316 * Left mouse button double click.
3318 * PARAMETER(S):
3319 * [I] HWND32 : window handle
3320 * [I] WORD : key flag
3321 * [I] WORD : x coordinate
3322 * [I] WORD : y coordinate
3324 * RETURN:
3325 * Zero
3327 static LRESULT LISTVIEW_LButtonDblClk(HWND hwnd, WORD wKey, WORD wPosX,
3328 WORD wPosY)
3330 LONG lCtrlId = GetWindowLongA(hwnd, GWL_ID);
3331 NMHDR nmh;
3333 /* send NM_DBLCLK notification */
3334 nmh.hwndFrom = hwnd;
3335 nmh.idFrom = lCtrlId;
3336 nmh.code = NM_DBLCLK;
3337 SendMessageA(GetParent (hwnd), WM_NOTIFY, (WPARAM)lCtrlId,
3338 (LPARAM)&nmh);
3340 /* send LVN_ITEMACTIVATE notification */
3341 nmh.code = LVN_ITEMACTIVATE;
3342 SendMessageA(GetParent (hwnd), WM_NOTIFY, (WPARAM)lCtrlId,
3343 (LPARAM)&nmh);
3345 return 0;
3348 /***
3349 * DESCRIPTION:
3350 * Left mouse button down.
3352 * PARAMETER(S):
3353 * [I] HWND32 : window handle
3354 * [I] WORD : key flag
3355 * [I] WORD : x coordinate
3356 * [I] WORD : y coordinate
3358 * RETURN:
3359 * Zero
3361 static LRESULT LISTVIEW_LButtonDown(HWND hwnd, WORD wKey, WORD wPosX,
3362 WORD wPosY)
3364 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
3365 LONG lCtrlId = GetWindowLongA(hwnd, GWL_ID);
3366 LVHITTESTINFO hitTestInfo;
3367 LVITEMA lvItem;
3368 NMHDR nmh;
3369 INT nItem;
3371 /* send NM_RELEASEDCAPTURE notification */
3372 nmh.hwndFrom = hwnd;
3373 nmh.idFrom = lCtrlId;
3374 nmh.code = NM_RELEASEDCAPTURE;
3375 SendMessageA(GetParent(hwnd), WM_NOTIFY, (WPARAM)lCtrlId,
3376 (LPARAM)&nmh);
3378 if (infoPtr->bFocus == FALSE)
3379 SetFocus(hwnd);
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 = SendMessageA(hwnd, LVM_HITTEST, (WPARAM)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);
3402 else
3404 /* refresh display */
3405 InvalidateRect(hwnd, NULL, FALSE);
3406 UpdateWindow(hwnd);
3409 else
3411 /* clear selection(s) */
3412 ZeroMemory(&lvItem, sizeof(LVITEMA));
3413 lvItem.stateMask = LVIS_SELECTED;
3414 lvItem.state = 0;
3415 SendMessageA(hwnd, LVM_SETITEMSTATE, (WPARAM)-1, (LPARAM)&lvItem);
3417 /* repaint everything */
3418 InvalidateRect(hwnd, NULL, FALSE);
3419 UpdateWindow(hwnd);
3422 return 0;
3425 /***
3426 * DESCRIPTION:
3427 * Left mouse button up.
3429 * PARAMETER(S):
3430 * [I] HWND32 : window handle
3431 * [I] WORD : key flag
3432 * [I] WORD : x coordinate
3433 * [I] WORD : y coordinate
3435 * RETURN:
3436 * Zero
3438 static LRESULT LISTVIEW_LButtonUp(HWND hwnd, WORD wKey, WORD wPosX,
3439 WORD wPosY)
3441 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
3442 LONG lCtrlId = GetWindowLongA(hwnd, GWL_ID);
3443 NMHDR nmh;
3445 if (infoPtr->bLButtonDown == TRUE)
3447 /* send NM_CLICK notification */
3448 nmh.hwndFrom = hwnd;
3449 nmh.idFrom = lCtrlId;
3450 nmh.code = NM_CLICK;
3451 SendMessageA(GetParent (hwnd), WM_NOTIFY, (WPARAM)lCtrlId,
3452 (LPARAM)&nmh);
3455 /* set left button flag */
3456 infoPtr->bLButtonDown = FALSE;
3458 return 0;
3461 /***
3462 * DESCRIPTION:
3463 * Creates the listview control (called before WM_CREATE).
3465 * PARAMETER(S):
3466 * [I] HWND32 : window handle
3467 * [I] WPARAM32 : unhandled
3468 * [I] LPARAM : widow creation info
3470 * RETURN:
3471 * Zero
3473 static LRESULT LISTVIEW_NCCreate(HWND hwnd, WPARAM wParam, LPARAM lParam)
3475 LISTVIEW_INFO *infoPtr;
3477 /* allocate memory for info structure */
3478 infoPtr = (LISTVIEW_INFO *)COMCTL32_Alloc (sizeof(LISTVIEW_INFO));
3479 SetWindowLongA(hwnd, 0, (LONG)infoPtr);
3480 if (infoPtr == NULL)
3482 ERR (listview, "could not allocate info memory!\n");
3483 return 0;
3486 if ((LISTVIEW_INFO *)GetWindowLongA(hwnd, 0) != infoPtr)
3488 ERR (listview, "pointer assignment error!\n");
3489 return 0;
3492 return DefWindowProcA(hwnd, WM_NCCREATE, wParam, lParam);
3495 /***
3496 * DESCRIPTION:
3497 * Destroys the listview control (called after WM_DESTROY).
3499 * PARAMETER(S):
3500 * [I] HWND32 : window handle
3502 * RETURN:
3503 * Zero
3505 static LRESULT LISTVIEW_NCDestroy(HWND hwnd)
3507 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
3509 /* free list view info data */
3510 COMCTL32_Free (infoPtr);
3512 return 0;
3515 /***
3516 * DESCRIPTION:
3517 * Handles notification from children.
3519 * PARAMETER(S):
3520 * [I] HWND32 : window handle
3521 * [I] INT32 : control identifier
3522 * [I] LPNMHDR : notification information
3524 * RETURN:
3525 * Zero
3527 static LRESULT LISTVIEW_Notify(HWND hwnd, INT nCtrlId, LPNMHDR lpnmh)
3529 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
3531 if (lpnmh->hwndFrom == infoPtr->hwndHeader)
3533 /* handle notification from header control */
3534 FIXME (listview, "WM_NOTIFY from header!\n");
3536 else
3538 /* handle notification from unknown source */
3539 FIXME (listview, "WM_NOTIFY from unknown source!\n");
3542 return 0;
3545 /***
3546 * DESCRIPTION:
3547 * Draws the listview control.
3549 * PARAMETER(S):
3550 * [I] HWND32 : window handle
3551 * [I] HDC32 : device context handle
3553 * RETURN:
3554 * Zero
3556 static LRESULT LISTVIEW_Paint(HWND hwnd, HDC hdc)
3558 PAINTSTRUCT ps;
3560 if (hdc == 0)
3562 hdc = BeginPaint(hwnd, &ps);
3563 LISTVIEW_Refresh(hwnd, hdc);
3564 EndPaint(hwnd, &ps);
3566 else
3567 LISTVIEW_Refresh(hwnd, hdc);
3569 return 0;
3572 /***
3573 * DESCRIPTION:
3574 * Right mouse button double clisk.
3576 * PARAMETER(S):
3577 * [I] HWND32 : window handle
3578 * [I] WORD : key flag
3579 * [I] WORD : x coordinate
3580 * [I] WORD : y coordinate
3582 * RETURN:
3583 * Zero
3585 static LRESULT LISTVIEW_RButtonDblClk(HWND hwnd, WORD wKey, WORD wPosX,
3586 WORD wPosY)
3588 LONG lCtrlId = GetWindowLongA(hwnd, GWL_ID);
3589 NMHDR nmh;
3591 /* send NM_RELEASEDCAPTURE notification */
3592 nmh.hwndFrom = hwnd;
3593 nmh.idFrom = lCtrlId;
3594 nmh.code = NM_RELEASEDCAPTURE;
3595 SendMessageA(GetParent(hwnd), WM_NOTIFY, (WPARAM)lCtrlId,
3596 (LPARAM)&nmh);
3598 /* send NM_RDBLCLK notification */
3599 nmh.code = NM_RDBLCLK;
3600 SendMessageA(GetParent(hwnd), WM_NOTIFY, (WPARAM)lCtrlId,
3601 (LPARAM)&nmh);
3603 return 0;
3606 /***
3607 * DESCRIPTION:
3608 * Right mouse button input.
3610 * PARAMETER(S):
3611 * [I] HWND32 : window handle
3612 * [I] WORD : key flag
3613 * [I] WORD : x coordinate
3614 * [I] WORD : y coordinate
3616 * RETURN:
3617 * Zero
3619 static LRESULT LISTVIEW_RButtonDown(HWND hwnd, WORD wKey, WORD wPosX,
3620 WORD wPosY)
3622 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
3623 LONG lCtrlId = GetWindowLongA(hwnd, GWL_ID);
3624 LVHITTESTINFO hitTestInfo;
3625 NMHDR nmh;
3626 LVITEMA lvItem;
3627 INT nItem;
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
3631 purposes. */
3632 ZeroMemory(&nmh, sizeof(NMHDR));
3633 nmh.hwndFrom = hwnd;
3634 nmh.idFrom = lCtrlId;
3635 nmh.code = NM_RELEASEDCAPTURE;
3636 SendMessageA(GetParent(hwnd), WM_NOTIFY, (WPARAM)lCtrlId,
3637 (LPARAM)&nmh);
3639 /* make sure listview control has focus */
3640 if (infoPtr->bFocus == FALSE)
3641 SetFocus(hwnd);
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 = SendMessageA(hwnd, LVM_HITTEST, (WPARAM)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);
3658 else
3660 /* clear selection(s) */
3661 ZeroMemory(&lvItem, sizeof(LVITEMA));
3662 lvItem.stateMask = LVIS_SELECTED;
3663 lvItem.state = 0;
3664 SendMessageA(hwnd, LVM_SETITEMSTATE, (WPARAM)-1, (LPARAM)&lvItem);
3667 /* repaint everything */
3668 InvalidateRect(hwnd, NULL, FALSE);
3669 UpdateWindow(hwnd);
3671 return 0;
3674 /***
3675 * DESCRIPTION:
3676 * Right mouse button up.
3678 * PARAMETER(S):
3679 * [I] HWND32 : window handle
3680 * [I] WORD : key flag
3681 * [I] WORD : x coordinate
3682 * [I] WORD : y coordinate
3684 * RETURN:
3685 * Zero
3687 static LRESULT LISTVIEW_RButtonUp(HWND hwnd, WORD wKey, WORD wPosX,
3688 WORD wPosY)
3690 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
3691 LONG lCtrlId = GetWindowLongA(hwnd, GWL_ID);
3692 NMHDR nmh;
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 SendMessageA(GetParent (hwnd), WM_NOTIFY, (WPARAM)lCtrlId,
3702 (LPARAM)&nmh);
3705 /* set button flag */
3706 infoPtr->bRButtonDown = FALSE;
3708 return 0;
3711 /***
3712 * DESCRIPTION:
3713 * Sets the focus.
3715 * PARAMETER(S):
3716 * [I] HWND32 : window handle
3717 * [I] HWND32 : window handle of previously focused window
3719 * RETURN:
3720 * Zero
3722 static LRESULT LISTVIEW_SetFocus(HWND hwnd, HWND hwndLoseFocus)
3724 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
3725 LONG lCtrlId = GetWindowLongA(hwnd, GWL_ID);
3726 NMHDR nmh;
3728 /* send NM_SETFOCUS notification */
3729 nmh.hwndFrom = hwnd;
3730 nmh.idFrom = lCtrlId;
3731 nmh.code = NM_SETFOCUS;
3732 SendMessageA(GetParent(hwnd), WM_NOTIFY, (WPARAM)lCtrlId,
3733 (LPARAM)&nmh);
3735 /* set window focus flag */
3736 infoPtr->bFocus = TRUE;
3738 return 0;
3741 /***
3742 * DESCRIPTION:
3743 * Sets the font.
3745 * PARAMETER(S):
3746 * [I] HWND32 : window handle
3747 * [I] HFONT32 : font handle
3748 * [I] WORD : redraw flag
3750 * RETURN:
3751 * Zero
3753 static LRESULT LISTVIEW_SetFont(HWND hwnd, HFONT hFont, WORD fRedraw)
3755 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
3756 LONG lStyle = GetWindowLongA(hwnd, GWL_STYLE);
3758 if (hFont == 0)
3760 infoPtr->hFont = infoPtr->hDefaultFont;
3762 else
3764 infoPtr->hFont = hFont;
3767 if (lStyle & LVS_REPORT)
3769 /* set font of header */
3770 SendMessageA(infoPtr->hwndHeader, WM_SETFONT, (WPARAM)hFont,
3771 MAKELPARAM(fRedraw, 0));
3774 /* invalidate listview control client area */
3775 InvalidateRect(hwnd, NULL, FALSE);
3777 if (fRedraw == TRUE)
3778 UpdateWindow(hwnd);
3780 return 0;
3783 /***
3784 * DESCRIPTION:
3785 * Resizes the listview control.
3787 * PARAMETER(S):
3788 * [I] HWND32 : window handle
3789 * [I] WORD : new width
3790 * [I] WORD : new height
3792 * RETURN:
3793 * Zero
3795 static LRESULT LISTVIEW_Size(HWND hwnd, WORD wWidth, WORD wHeight)
3797 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
3798 LONG lStyle = GetWindowLongA(hwnd, GWL_STYLE);
3799 INT nHScrollHeight;
3801 if (lStyle & LVS_LIST)
3803 if (!(lStyle & WS_HSCROLL))
3805 nHScrollHeight = GetSystemMetrics(SM_CYHSCROLL);
3806 if (wHeight > nHScrollHeight)
3807 wHeight -= nHScrollHeight;
3810 infoPtr->nHeight = (INT)wHeight;
3811 infoPtr->nWidth = (INT)wWidth;
3814 /* set scrollbar(s) if needed */
3815 LISTVIEW_SetScroll(hwnd);
3817 /* refresh client area */
3818 InvalidateRect(hwnd, NULL, TRUE);
3819 UpdateWindow(hwnd);
3821 return 0;
3824 /***
3825 * DESCRIPTION:
3826 * Window procedure of the listview control.
3828 * PARAMETER(S):
3829 * [I] HWND32 :
3830 * [I] UINT32 :
3831 * [I] WPARAM32 :
3832 * [I] LPARAM :
3834 * RETURN:
3837 LRESULT WINAPI LISTVIEW_WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam,
3838 LPARAM lParam)
3840 switch (uMsg)
3842 case LVM_APPROXIMATEVIEWRECT:
3843 return LISTVIEW_ApproximateViewRect(hwnd, (INT)wParam,
3844 LOWORD(lParam), HIWORD(lParam));
3845 case LVM_ARRANGE:
3846 return LISTVIEW_Arrange(hwnd, (INT)wParam);
3848 /* case LVM_CREATEDRAGIMAGE: */
3850 case LVM_DELETEALLITEMS:
3851 return LISTVIEW_DeleteAllItems(hwnd);
3853 case LVM_DELETECOLUMN:
3854 return LISTVIEW_DeleteColumn(hwnd, (INT)wParam);
3856 case LVM_DELETEITEM:
3857 return LISTVIEW_DeleteItem(hwnd, (INT)wParam);
3859 /* case LVM_EDITLABEL: */
3860 /* case LVM_ENSUREVISIBLE: */
3862 case LVM_FINDITEMA:
3863 return LISTVIEW_FindItem(hwnd, (INT)wParam, (LPLVFINDINFO)lParam);
3865 case LVM_GETBKCOLOR:
3866 return LISTVIEW_GetBkColor(hwnd);
3868 /* case LVM_GETBKIMAGE: */
3869 /* case LVM_GETCALLBACKMASK: */
3871 case LVM_GETCOLUMNA:
3872 return LISTVIEW_GetColumnA(hwnd, (INT)wParam, (LPLVCOLUMNA)lParam);
3874 /* case LVM_GETCOLUMN32W: */
3875 /* case LVM_GETCOLUMNORDERARRAY: */
3877 case LVM_GETCOLUMNWIDTH:
3878 return LISTVIEW_GetColumnWidth(hwnd, (INT)wParam);
3880 case LVM_GETCOUNTPERPAGE:
3881 return LISTVIEW_GetCountPerPage(hwnd);
3883 /* case LVM_GETEDITCONTROL: */
3884 /* case LVM_GETEXTENDEDLISTVIEWSTYLE: */
3886 case LVM_GETHEADER:
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, (INT)wParam);
3896 /* case LVM_GETISEARCHSTRING: */
3898 case LVM_GETITEMA:
3899 return LISTVIEW_GetItemA(hwnd, (LPLVITEMA)lParam);
3901 /* case LVM_GETITEM32W: */
3903 case LVM_GETITEMCOUNT:
3904 return LISTVIEW_GetItemCount(hwnd);
3906 case LVM_GETITEMPOSITION:
3907 return LISTVIEW_GetItemPosition(hwnd, (INT)wParam, (LPPOINT)lParam);
3909 case LVM_GETITEMRECT:
3910 return LISTVIEW_GetItemRect(hwnd, (INT)wParam, (LPRECT)lParam);
3912 case LVM_GETITEMSPACING:
3913 return LISTVIEW_GetItemSpacing(hwnd, (BOOL)wParam);
3915 case LVM_GETITEMSTATE:
3916 return LISTVIEW_GetItemState(hwnd, (INT)wParam, (UINT)lParam);
3918 case LVM_GETITEMTEXTA:
3919 LISTVIEW_GetItemTextA(hwnd, (INT)wParam, (LPLVITEMA)lParam);
3920 break;
3922 /* case LVM_GETITEMTEXT32W: */
3924 case LVM_GETNEXTITEM:
3925 return LISTVIEW_GetNextItem(hwnd, (INT)wParam, LOWORD(lParam));
3927 /* case LVM_GETNUMBEROFWORKAREAS: */
3928 case LVM_GETORIGIN:
3929 return LISTVIEW_GetOrigin(hwnd, (LPPOINT)lParam);
3931 case LVM_GETSELECTEDCOUNT:
3932 return LISTVIEW_GetSelectedCount(hwnd);
3934 case LVM_GETSELECTIONMARK:
3935 return LISTVIEW_GetSelectionMark(hwnd);
3937 case LVM_GETSTRINGWIDTHA:
3938 return LISTVIEW_GetStringWidthA (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, (LPRECT)lParam);
3956 /* case LVM_GETWORKAREAS: */
3958 case LVM_HITTEST:
3959 return LISTVIEW_HitTest(hwnd, (LPLVHITTESTINFO)lParam);
3961 case LVM_INSERTCOLUMNA:
3962 return LISTVIEW_InsertColumnA(hwnd, (INT)wParam,
3963 (LPLVCOLUMNA)lParam);
3965 /* case LVM_INSERTCOLUMN32W: */
3967 case LVM_INSERTITEMA:
3968 return LISTVIEW_InsertItemA(hwnd, (LPLVITEMA)lParam);
3970 /* case LVM_INSERTITEM32W: */
3972 case LVM_REDRAWITEMS:
3973 return LISTVIEW_RedrawItems(hwnd, (INT)wParam, (INT)lParam);
3975 case LVM_SCROLL:
3976 return LISTVIEW_Scroll(hwnd, (INT)wParam, (INT)lParam);
3978 case LVM_SETBKCOLOR:
3979 return LISTVIEW_SetBkColor(hwnd, (COLORREF)lParam);
3981 /* case LVM_SETBKIMAGE: */
3982 /* case LVM_SETCALLBACKMASK: */
3984 case LVM_SETCOLUMNA:
3985 return LISTVIEW_SetColumnA(hwnd, (INT)wParam, (LPLVCOLUMNA)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, (INT)wParam, (HIMAGELIST)lParam);
3999 case LVM_SETITEMA:
4000 return LISTVIEW_SetItemA(hwnd, (LPLVITEMA)lParam);
4002 /* case LVM_SETITEM32W: */
4003 /* case LVM_SETITEMCOUNT: */
4005 case LVM_SETITEMPOSITION16:
4006 return LISTVIEW_SetItemPosition(hwnd, (INT)wParam,
4007 (INT)LOWORD(lParam),
4008 (INT) HIWORD(lParam));
4010 /* case LVM_SETITEMPOSITION32: */
4012 case LVM_SETITEMSTATE:
4013 return LISTVIEW_SetItemState(hwnd, (INT)wParam, (LPLVITEMA)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: */
4028 case LVM_SORTITEMS:
4029 return LISTVIEW_SortItems(hwnd, wParam, lParam);
4031 /* case LVM_SUBITEMHITTEST: */
4033 case LVM_UPDATE:
4034 return LISTVIEW_Update(hwnd, (INT)wParam);
4036 /* case WM_CHAR: */
4037 /* case WM_COMMAND: */
4039 case WM_CREATE:
4040 return LISTVIEW_Create(hwnd, wParam, lParam);
4042 case WM_DESTROY:
4043 return LISTVIEW_Destroy(hwnd, wParam, lParam);
4045 case WM_ERASEBKGND:
4046 return LISTVIEW_EraseBackground (hwnd, wParam, lParam);
4048 case WM_GETDLGCODE:
4049 return DLGC_WANTTAB | DLGC_WANTARROWS;
4051 case WM_GETFONT:
4052 return LISTVIEW_GetFont(hwnd);
4054 case WM_HSCROLL:
4055 return LISTVIEW_HScroll(hwnd, (INT)LOWORD(wParam),
4056 (INT)HIWORD(wParam), (HWND)lParam);
4058 case WM_KEYDOWN:
4059 return LISTVIEW_KeyDown(hwnd, (INT)wParam, (LONG)lParam);
4061 case WM_KILLFOCUS:
4062 return LISTVIEW_KillFocus(hwnd);
4064 case WM_LBUTTONDBLCLK:
4065 return LISTVIEW_LButtonDblClk(hwnd, (WORD)wParam, LOWORD(lParam),
4066 HIWORD(lParam));
4068 case WM_LBUTTONDOWN:
4069 return LISTVIEW_LButtonDown(hwnd, (WORD)wParam, LOWORD(lParam),
4070 HIWORD(lParam));
4071 case WM_LBUTTONUP:
4072 return LISTVIEW_LButtonUp(hwnd, (WORD)wParam, LOWORD(lParam),
4073 HIWORD(lParam));
4075 /* case WM_MOUSEMOVE: */
4076 /* return LISTVIEW_MouseMove (hwnd, wParam, lParam); */
4078 case WM_NCCREATE:
4079 return LISTVIEW_NCCreate(hwnd, wParam, lParam);
4081 case WM_NCDESTROY:
4082 return LISTVIEW_NCDestroy(hwnd);
4084 case WM_NOTIFY:
4085 return LISTVIEW_Notify(hwnd, (INT)wParam, (LPNMHDR)lParam);
4087 case WM_PAINT:
4088 return LISTVIEW_Paint(hwnd, (HDC)wParam);
4090 case WM_RBUTTONDBLCLK:
4091 return LISTVIEW_RButtonDblClk(hwnd, (WORD)wParam, LOWORD(lParam),
4092 HIWORD(lParam));
4094 case WM_RBUTTONDOWN:
4095 return LISTVIEW_RButtonDown(hwnd, (WORD)wParam, LOWORD(lParam),
4096 HIWORD(lParam));
4098 case WM_RBUTTONUP:
4099 return LISTVIEW_RButtonUp(hwnd, (WORD)wParam, LOWORD(lParam),
4100 HIWORD(lParam));
4102 case WM_SETFOCUS:
4103 return LISTVIEW_SetFocus(hwnd, (HWND)wParam);
4105 case WM_SETFONT:
4106 return LISTVIEW_SetFont(hwnd, (HFONT)wParam, (WORD)lParam);
4108 /* case WM_SETREDRAW: */
4110 case WM_SIZE:
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: */
4118 default:
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 DefWindowProcA (hwnd, uMsg, wParam, lParam);
4127 return 0;
4130 /***
4131 * DESCRIPTION:`
4132 * Registers the window class.
4134 * PARAMETER(S):
4135 * None
4137 * RETURN:
4138 * None
4140 VOID LISTVIEW_Register(VOID)
4142 WNDCLASSA wndClass;
4144 if (!GlobalFindAtomA(WC_LISTVIEWA))
4146 ZeroMemory (&wndClass, sizeof(WNDCLASSA));
4147 wndClass.style = CS_GLOBALCLASS | CS_DBLCLKS;
4148 wndClass.lpfnWndProc = (WNDPROC)LISTVIEW_WindowProc;
4149 wndClass.cbClsExtra = 0;
4150 wndClass.cbWndExtra = sizeof(LISTVIEW_INFO *);
4151 wndClass.hCursor = LoadCursorA (0, IDC_ARROWA);
4152 wndClass.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
4153 wndClass.lpszClassName = WC_LISTVIEWA;
4154 RegisterClassA (&wndClass);
4158 /***
4159 * DESCRIPTION:
4160 * Unregisters the window class.
4162 * PARAMETER(S):
4163 * None
4165 * RETURN:
4166 * None
4168 VOID LISTVIEW_Unregister(VOID)
4170 if (GlobalFindAtomA (WC_LISTVIEWA))
4171 UnregisterClassA (WC_LISTVIEWA, (HINSTANCE)NULL);