Fixed a silly VGA-emulation palette bug.
[wine/multimedia.git] / dlls / comctl32 / listview.c
blobc0fdf1fac233dbb0377ca987a5ee0b6e4e2176a8
1 /*
2 * Listview control
4 * Copyright 1998 Eric Kohl
5 * Copyright 1999 Luc Tourangeau
7 * NOTES
8 * Listview control implementation.
10 * TODO:
11 * LISTVIEW_GetMaxItemWidth : large icon view
12 * LISTVIEW_Notify : notification from children
13 * LISTVIEW_KeyDown : key press messages
14 * LISTVIEW_HScroll : small icon and icon
15 * LISTVIEW_VScroll : small icon and icon
16 * LISTVIEW_SortItems : empty stub
17 * LISTVIEW_SetItemPosition : small icon and icon
18 * LISTVIEW_SetItemCount : empty stub
19 * LISTVIEW_SetItem32W : no unicode yet!
20 * LISTVIEW_SetColumn32A : DOUBLE CHECK
21 * LISTVIEW_Scroll : scrolling in pixels
22 * LISTVIEW_RedrawItems : define bounding rect
23 * LISTVIEW_InsertItem32W : no unicode yet!
24 * LISTVIEW_InsertColumn32W : no unicode yet!
25 * LISTVIEW_GetViewRect : small icon and icon
26 * LISTVIEW_GetOrigin : small icon and icon
27 * LISTVIEW_GetNumberOfWorkAreas : small icon and icon
28 * LISTVIEW_GetNextItem : all
29 * LISTVIEW_SetScroll : scrolling in pixels
30 * LISTVIEW_GetItemRect : all
31 * LISTVIEW_GetHotCursor : all
32 * LISTVIEW_GetHotItem : all
33 * LISTVIEW_GetHoverTime : all
34 * LISTVIEW_GetISearchString : all
35 * LISTVIEW_GetBkImage : all
36 * LISTVIEW_FindItem : all
37 * LISTVIEW_EnsureVisible : some
38 * LISTVIEW_EditLabel : REPORT (need to implement a timer)
39 * LISTVIEW_GetItemPosition : small icon and icon
40 * LISTVIEW_GetItemRect : some
41 * LISTVIEW_Arrange : small icon and icon
42 * LISTVIEW_ApproximateViewRect : report, small icon and icon
43 * LISTVIEW_RefreshIcon : large icon draw function
46 #include <string.h>
47 #include "windows.h"
48 #include "commctrl.h"
49 #include "listview.h"
50 #include "win.h"
51 #include "debug.h"
52 #include "winuser.h"
54 /* constants */
55 #define DISP_TEXT_SIZE 128
56 #define WIDTH_PADDING 12
57 #define HEIGHT_PADDING 2
58 #define MIN_COLUMN_WIDTH 96
60 /* macro section */
61 #define GETITEMCOUNT(infoPtr) ((infoPtr)->hdpaItems->nItemCount)
62 #define ListView_LVNotify(hwnd,lCtrlId,plvnm) \
63 (BOOL)SendMessageA((hwnd),WM_NOTIFY,(WPARAM)(INT)lCtrlId,(LPARAM)(LPNMLISTVIEW)(plvnm))
64 #define ListView_Notify(hwnd,lCtrlId,pnmh) \
65 (BOOL)SendMessageA((hwnd),WM_NOTIFY,(WPARAM)(INT)lCtrlId,(LPARAM)(LPNMHDR)(pnmh))
67 /* forward declarations */
68 static VOID LISTVIEW_SetSize(HWND hwnd, LONG lStyle, LONG lWidth,
69 LONG lHeight);
70 static VOID LISTVIEW_SetViewInfo(HWND hwnd);
71 static VOID LISTVIEW_SetScroll(HWND hwnd);
72 static VOID LISTVIEW_AddGroupSelection(HWND hwnd, INT nItem);
73 static VOID LISTVIEW_AddSelection(HWND hwnd, INT nItem);
74 static BOOL LISTVIEW_ToggleSelection(HWND hwnd, INT nItem);
75 static VOID LISTVIEW_SetGroupSelection(HWND hwnd, INT nItem);
76 static VOID LISTVIEW_SetSelection(HWND hwnd, INT nItem);
77 static VOID LISTVIEW_RemoveSelections(HWND hwnd, INT nFirst, INT nLast);
78 static VOID LISTVIEW_SetItemFocus(HWND hwnd, INT nItem);
79 static BOOL LISTVIEW_RemoveSubItem(HDPA hdpaSubItems, INT nSubItem);
80 static BOOL LISTVIEW_RemoveColumn(HDPA hdpaItems, INT nColumn);
81 static BOOL LISTVIEW_InitItem(HWND hwnd, LISTVIEW_ITEM *lpItem,
82 LPLVITEMA lpLVItem);
83 static BOOL LISTVIEW_InitSubItem(HWND hwnd, LISTVIEW_SUBITEM *lpSubItem,
84 LPLVITEMA lpLVItem);
85 static BOOL LISTVIEW_AddSubItem(HWND hwnd, LPLVITEMA lpLVItem);
86 static BOOL LISTVIEW_SetItem(HWND hwnd, LPLVITEMA lpLVItem);
87 static BOOL LISTVIEW_SetSubItem(HWND hwnd, LPLVITEMA lpLVItem);
88 static INT LISTVIEW_FindInsertPosition(HDPA hdpaSubItems, INT nSubItem);
89 static LISTVIEW_SUBITEM* LISTVIEW_GetSubItem(HDPA hdpaSubItems, INT nSubItem);
92 /***
93 * DESCRIPTION:
94 * Prints a message for unsupported window styles.
96 * PARAMETER(S):
97 * [I] LONG : window style
99 * RETURN:
100 * None
102 static VOID LISTVIEW_UnsupportedStyles(LONG lStyle)
104 if ((LVS_TYPEMASK & lStyle) == LVS_ALIGNLEFT)
106 FIXME(listview, " LVS_ALIGNLEFT\n");
109 if ((LVS_TYPEMASK & lStyle) == LVS_ALIGNTOP)
111 FIXME(listview, " LVS_ALIGNTOP\n");
114 if ((LVS_TYPEMASK & lStyle) == LVS_AUTOARRANGE)
116 FIXME(listview, " LVS_AUTOARRANGE\n");
119 if ((LVS_TYPEMASK & lStyle) == LVS_EDITLABELS)
121 FIXME(listview, " LVS_EDITLABELS\n");
124 if ((LVS_TYPEMASK & lStyle) == LVS_ICON)
126 FIXME(listview, " LVS_ICON\n");
129 if ((LVS_TYPEMASK & lStyle) == LVS_NOCOLUMNHEADER)
131 FIXME(listview, " LVS_SORTDESCENDING\n");
134 if ((LVS_TYPEMASK & lStyle) == LVS_NOLABELWRAP)
136 FIXME(listview, " LVS_NOLABELWRAP\n");
139 if ((LVS_TYPEMASK & lStyle) == LVS_NOSCROLL)
141 FIXME(listview, " LVS_NOSCROLL\n");
144 if ((LVS_TYPEMASK & lStyle) == LVS_NOSORTHEADER)
146 FIXME(listview, " LVS_NOSORTHEADER\n");
149 if ((LVS_TYPEMASK & lStyle) == LVS_OWNERDRAWFIXED)
151 FIXME(listview, " LVS_OWNERDRAWFIXED\n");
154 if ((LVS_TYPEMASK & lStyle) == LVS_SHAREIMAGELISTS)
156 FIXME(listview, " LVS_SHAREIMAGELISTS\n");
159 if ((LVS_TYPEMASK & lStyle) == LVS_SHOWSELALWAYS)
161 FIXME(listview, " LVS_SHOWSELALWAYS\n");
164 if ((LVS_TYPEMASK & lStyle) == LVS_SINGLESEL)
166 FIXME(listview, " LVS_SINGLESEL\n");
169 if ((LVS_TYPEMASK & lStyle) == LVS_SMALLICON)
171 FIXME(listview, " LVS_SMALLICON\n");
174 if ((LVS_TYPEMASK & lStyle) == LVS_SORTDESCENDING)
176 FIXME(listview, " LVS_SORTDESCENDING\n");
179 if ((LVS_TYPEMASK & lStyle) == LVS_SORTDESCENDING)
181 FIXME(listview, " LVS_SORTDESCENDING\n");
185 /***
186 * DESCRIPTION:
187 * Retrieves display information.
189 * PARAMETER(S):
190 * [I] HWND : window handle
191 * [I] LISTVIEW_ITEM* : listview control item
192 * [O] INT : image index
193 * [O] UINT : state value
194 * [O] CHAR** : string
195 * [I] INT : size of string
197 * RETURN:
198 * None
200 static VOID LISTVIEW_GetItemDispInfo(HWND hwnd, INT nItem,
201 LISTVIEW_ITEM *lpItem, INT *pnDispImage,
202 UINT *puState, CHAR **ppszDispText,
203 INT nDispTextSize)
205 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
206 LONG lCtrlId = GetWindowLongA(hwnd, GWL_ID);
207 NMLVDISPINFOA dispInfo;
208 ZeroMemory(&dispInfo, sizeof(NMLVDISPINFOA));
210 if ((pnDispImage != NULL) && (lpItem->iImage == I_IMAGECALLBACK))
212 dispInfo.item.mask |= LVIF_IMAGE;
215 if ((ppszDispText != NULL) && (lpItem->pszText == LPSTR_TEXTCALLBACKA))
217 ZeroMemory(*ppszDispText, sizeof(CHAR)*nDispTextSize);
218 dispInfo.item.mask |= LVIF_TEXT;
219 dispInfo.item.pszText = *ppszDispText;
220 dispInfo.item.cchTextMax = nDispTextSize;
223 if ((puState != NULL) && (infoPtr->uCallbackMask != 0))
225 dispInfo.item.mask |= LVIF_STATE;
226 dispInfo.item.stateMask = infoPtr->uCallbackMask;
229 if (dispInfo.item.mask != 0)
231 dispInfo.hdr.hwndFrom = hwnd;
232 dispInfo.hdr.idFrom = lCtrlId;
233 dispInfo.hdr.code = LVN_GETDISPINFOA;
234 dispInfo.item.iItem = nItem;
235 dispInfo.item.iSubItem = 0;
236 dispInfo.item.lParam = lpItem->lParam;
237 ListView_Notify(GetParent(hwnd), lCtrlId, &dispInfo);
240 if (pnDispImage != NULL)
242 if (dispInfo.item.mask & LVIF_IMAGE)
244 *pnDispImage = dispInfo.item.iImage;
246 else
248 *pnDispImage = lpItem->iImage;
252 if (ppszDispText != NULL)
254 if (dispInfo.item.mask & LVIF_TEXT)
256 if (dispInfo.item.mask & LVIF_DI_SETITEM)
258 Str_SetPtrA(&lpItem->pszText, dispInfo.item.pszText);
260 *ppszDispText = dispInfo.item.pszText;
262 else
264 *ppszDispText = lpItem->pszText;
268 if (puState != NULL)
270 if (dispInfo.item.mask & LVIF_STATE)
272 *puState = lpItem->state;
273 *puState &= ~dispInfo.item.stateMask;
274 *puState |= (dispInfo.item.state & dispInfo.item.stateMask);
276 else
278 *puState = lpItem->state;
283 /***
284 * DESCRIPTION:
285 * Retrieves display information.
287 * PARAMETER(S):
288 * [I] HWND : window handle
289 * [I] LISTVIEW_SUBITEM* : listview control subitem
290 * [O] INT : image index
291 * [O] UINT : state value
292 * [O] CHAR** : string
293 * [I] INT : size of string
295 * RETURN:
296 * None
298 static VOID LISTVIEW_GetSubItemDispInfo(HWND hwnd, INT nItem, LPARAM lParam,
299 LISTVIEW_SUBITEM *lpSubItem,
300 INT nColumn, INT *pnDispImage,
301 CHAR **ppszDispText, INT nDispTextSize)
303 LONG lCtrlId = GetWindowLongA(hwnd, GWL_ID);
304 NMLVDISPINFOA dispInfo;
305 ZeroMemory(&dispInfo, sizeof(NMLVDISPINFOA));
307 if (lpSubItem == NULL)
309 ZeroMemory(*ppszDispText, sizeof(CHAR)*nDispTextSize);
310 dispInfo.item.mask |= LVIF_TEXT;
311 dispInfo.item.pszText = *ppszDispText;
312 dispInfo.item.cchTextMax = nDispTextSize;
313 dispInfo.hdr.hwndFrom = hwnd;
314 dispInfo.hdr.idFrom = lCtrlId;
315 dispInfo.hdr.code = LVN_GETDISPINFOA;
316 dispInfo.item.iItem = nItem;
317 dispInfo.item.iSubItem = nColumn;
318 dispInfo.item.lParam = lParam;
319 ListView_Notify(GetParent(hwnd), lCtrlId, &dispInfo);
320 if (dispInfo.item.mask & LVIF_DI_SETITEM)
322 Str_SetPtrA(&lpSubItem->pszText, dispInfo.item.pszText);
324 *ppszDispText = dispInfo.item.pszText;
326 else
328 if ((pnDispImage != NULL) && (lpSubItem->iImage == I_IMAGECALLBACK))
330 dispInfo.item.mask |= LVIF_IMAGE;
333 if ((ppszDispText != NULL) && (lpSubItem->pszText == LPSTR_TEXTCALLBACKA))
335 ZeroMemory(*ppszDispText, sizeof(CHAR)*nDispTextSize);
336 dispInfo.item.mask |= LVIF_TEXT;
337 dispInfo.item.pszText = *ppszDispText;
338 dispInfo.item.cchTextMax = nDispTextSize;
341 if (dispInfo.item.mask != 0)
343 dispInfo.hdr.hwndFrom = hwnd;
344 dispInfo.hdr.idFrom = lCtrlId;
345 dispInfo.hdr.code = LVN_GETDISPINFOA;
346 dispInfo.item.iItem = nItem;
347 dispInfo.item.iSubItem = lpSubItem->iSubItem;
348 dispInfo.item.lParam = lParam;
349 ListView_Notify(GetParent(hwnd), lCtrlId, &dispInfo);
352 if (pnDispImage != NULL)
354 if (dispInfo.item.mask & LVIF_IMAGE)
356 *pnDispImage = dispInfo.item.iImage;
358 else
360 *pnDispImage = lpSubItem->iImage;
364 if (ppszDispText != NULL)
366 if (dispInfo.item.mask & LVIF_TEXT)
368 if (dispInfo.item.mask & LVIF_DI_SETITEM)
370 Str_SetPtrA(&lpSubItem->pszText, dispInfo.item.pszText);
372 *ppszDispText = dispInfo.item.pszText;
374 else
376 *ppszDispText = lpSubItem->pszText;
382 /***
383 * DESCRIPTION:
384 * Calculates a new column width.
386 * PARAMETER(S):
387 * [I] HWND : window handle
389 * RETURN:
390 * Returns item width.
392 static INT LISTVIEW_GetMaxItemWidth(HWND hwnd)
394 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
395 LONG lStyle = GetWindowLongA(hwnd, GWL_STYLE);
396 LISTVIEW_ITEM *lpItem;
397 HDPA hdpaSubItems;
398 INT nStringWidth;
399 INT nMaxItemWidth = 0;
400 INT i;
402 if ((LVS_TYPEMASK & lStyle) == LVS_ICON)
404 /* TO DO */
406 else
408 for (i = 0; i < GETITEMCOUNT(infoPtr); i++)
410 hdpaSubItems = (HDPA)DPA_GetPtr(infoPtr->hdpaItems, i);
411 if (hdpaSubItems != NULL)
413 lpItem = (LISTVIEW_ITEM *)DPA_GetPtr(hdpaSubItems, 0);
414 if (lpItem != NULL)
416 CHAR szDispText[DISP_TEXT_SIZE];
417 LPSTR pszDispText;
418 pszDispText = szDispText;
419 LISTVIEW_GetItemDispInfo(hwnd, i, lpItem, NULL, NULL, &pszDispText,
420 DISP_TEXT_SIZE);
421 nStringWidth = ListView_GetStringWidthA(hwnd, pszDispText);
422 nMaxItemWidth = max(nMaxItemWidth, nStringWidth);
427 /* add arbitrary padding for separating columns */
428 nMaxItemWidth += WIDTH_PADDING;
430 if (infoPtr->himlSmall != NULL)
432 nMaxItemWidth += infoPtr->iconSize.cx;
435 if (infoPtr->himlState != NULL)
437 nMaxItemWidth += infoPtr->iconSize.cx;
441 nMaxItemWidth = max(MIN_COLUMN_WIDTH, nMaxItemWidth);
443 return nMaxItemWidth;
446 /***
447 * DESCRIPTION:
448 * Sets diplay information (needed for drawing and calculations).
450 * PARAMETER(S):
451 * [I] HWND : window handle
453 * RETURN:
454 * None
456 static VOID LISTVIEW_SetViewInfo(HWND hwnd)
458 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
459 LONG lStyle = GetWindowLongA(hwnd, GWL_STYLE);
460 INT nHeight;
461 INT nWidth;
462 HDC hdc;
463 HFONT hOldFont;
464 TEXTMETRICA tm;
466 /* get text height */
467 hdc = GetDC(hwnd);
468 hOldFont = SelectObject(hdc, infoPtr->hFont);
469 GetTextMetricsA(hdc, &tm);
471 nHeight = infoPtr->rcList.bottom - infoPtr->rcList.top;
472 nWidth = infoPtr->rcList.right - infoPtr->rcList.left;
474 switch (LVS_TYPEMASK & lStyle)
476 case LVS_LIST:
477 infoPtr->nColumnWidth = LISTVIEW_GetMaxItemWidth(hwnd);
478 infoPtr->nItemHeight = (max(tm.tmHeight, infoPtr->iconSize.cy) +
479 HEIGHT_PADDING);
481 infoPtr->nCountPerColumn = nHeight / infoPtr->nItemHeight;
482 if (infoPtr->nCountPerColumn == 0)
484 infoPtr->nCountPerColumn = 1;
487 infoPtr->nCountPerRow = nWidth / infoPtr->nColumnWidth;
488 if (infoPtr->nCountPerRow == 0)
490 infoPtr->nCountPerRow = 1;
492 break;
494 case LVS_REPORT:
495 infoPtr->nItemHeight = (max(tm.tmHeight, infoPtr->iconSize.cy) +
496 HEIGHT_PADDING);
497 infoPtr->nCountPerRow = 1;
498 infoPtr->nCountPerColumn = nHeight / infoPtr->nItemHeight;
499 if (infoPtr->nCountPerColumn == 0)
501 infoPtr->nCountPerColumn = 1;
503 break;
507 SelectObject(hdc, hOldFont);
508 ReleaseDC(hwnd, hdc);
511 /***
512 * DESCRIPTION:
513 * Adds a block of selections.
515 * PARAMETER(S):
516 * [I] HWND : window handle
517 * [I] INT : item index
519 * RETURN:
520 * None
522 static VOID LISTVIEW_AddGroupSelection(HWND hwnd, INT nItem)
524 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
525 INT nFirst = min(infoPtr->nSelectionMark, nItem);
526 INT nLast = max(infoPtr->nSelectionMark, nItem);
527 LVITEMA lvItem;
528 INT i;
530 lvItem.state = LVIS_SELECTED;
531 lvItem.stateMask= LVIS_SELECTED;
533 for (i = nFirst; i <= nLast; i++)
535 ListView_SetItemState(hwnd, i, &lvItem);
538 LISTVIEW_SetItemFocus(hwnd, nItem);
539 infoPtr->nSelectionMark = nItem;
542 /***
543 * DESCRIPTION:
544 * Adds a single selection.
546 * PARAMETER(S):
547 * [I] HWND : window handle
548 * [I] INT : item index
550 * RETURN:
551 * None
553 static VOID LISTVIEW_AddSelection(HWND hwnd, INT nItem)
555 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
556 LVITEMA lvItem;
558 lvItem.state = LVIS_SELECTED;
559 lvItem.stateMask= LVIS_SELECTED;
561 ListView_SetItemState(hwnd, nItem, &lvItem);
563 LISTVIEW_SetItemFocus(hwnd, nItem);
564 infoPtr->nSelectionMark = nItem;
567 /***
568 * DESCRIPTION:
569 * Selects or unselects an item.
571 * PARAMETER(S):
572 * [I] HWND : window handle
573 * [I] INT : item index
575 * RETURN:
576 * SELECT: TRUE
577 * UNSELECT : FALSE
579 static BOOL LISTVIEW_ToggleSelection(HWND hwnd, INT nItem)
581 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
582 BOOL bResult;
583 LVITEMA lvItem;
585 lvItem.stateMask= LVIS_SELECTED;
587 if (ListView_GetItemState(hwnd, nItem, LVIS_SELECTED) & LVIS_SELECTED)
589 lvItem.state = 0;
590 ListView_SetItemState(hwnd, nItem, &lvItem);
591 bResult = FALSE;
593 else
595 lvItem.state = LVIS_SELECTED;
596 ListView_SetItemState(hwnd, nItem, &lvItem);
597 bResult = TRUE;
600 LISTVIEW_SetItemFocus(hwnd, nItem);
601 infoPtr->nSelectionMark = nItem;
603 return bResult;
606 /***
607 * DESCRIPTION:
608 * Reinitilizes the listview items.
610 * PARAMETER(S):
611 * [I] HWND : window handle
612 * [I] INT : item index
614 * RETURN:
615 * None
617 static VOID LISTVIEW_SetGroupSelection(HWND hwnd, INT nItem)
619 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
620 INT nFirst = min(infoPtr->nSelectionMark, nItem);
621 INT nLast = max(infoPtr->nSelectionMark, nItem);
622 LVITEMA lvItem;
623 INT i;
625 if (nFirst > 0)
627 LISTVIEW_RemoveSelections(hwnd, 0, nFirst - 1);
630 if (nLast < GETITEMCOUNT(infoPtr))
632 LISTVIEW_RemoveSelections(hwnd, nLast + 1, GETITEMCOUNT(infoPtr));
635 lvItem.state = LVIS_SELECTED;
636 lvItem.stateMask = LVIS_SELECTED;
638 for (i = nFirst; i <= nLast; i++)
640 ListView_SetItemState(hwnd, i, &lvItem);
643 LISTVIEW_SetItemFocus(hwnd, nItem);
646 /***
647 * DESCRIPTION:
648 * Manages the item focus.
650 * PARAMETER(S):
651 * [I] HWND : window handle
652 * [I] INT : item index
654 * RETURN:
655 * None
657 static VOID LISTVIEW_SetItemFocus(HWND hwnd, INT nItem)
659 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
660 LVITEMA lvItem;
662 lvItem.state = 0;
663 lvItem.stateMask = LVIS_FOCUSED;
664 ListView_SetItemState(hwnd, infoPtr->nFocusedItem, &lvItem);
666 lvItem.state = LVIS_FOCUSED;
667 lvItem.stateMask = LVIS_FOCUSED;
668 ListView_SetItemState(hwnd, nItem, &lvItem);
670 infoPtr->nFocusedItem = nItem;
672 /* if multiple selection is allowed */
673 ListView_EnsureVisible(hwnd, nItem, FALSE);
676 /***
677 * DESCRIPTION:
678 * Reinitilizes the listview items.
680 * PARAMETER(S):
681 * [I] HWND : window handle
682 * [I] INT : item index
684 * RETURN:
685 * None
687 static VOID LISTVIEW_SetSelection(HWND hwnd, INT nItem)
689 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
690 LVITEMA lvItem;
692 if (nItem > 0)
694 LISTVIEW_RemoveSelections(hwnd, 0, nItem - 1);
697 if (nItem < GETITEMCOUNT(infoPtr))
699 LISTVIEW_RemoveSelections(hwnd, nItem + 1, GETITEMCOUNT(infoPtr));
702 lvItem.state = 0;
703 lvItem.stateMask = LVIS_FOCUSED;
704 ListView_SetItemState(hwnd, infoPtr->nFocusedItem, &lvItem);
706 lvItem.state = LVIS_SELECTED | LVIS_FOCUSED;
707 lvItem.stateMask = LVIS_SELECTED | LVIS_FOCUSED;
708 ListView_SetItemState(hwnd, nItem, &lvItem);
710 infoPtr->nFocusedItem = nItem;
711 infoPtr->nSelectionMark = nItem;
714 /***
715 * DESCRIPTION:
716 * Reinitilizes the listview items.
718 * PARAMETER(S):
719 * [I] HWND : window handle
720 * [I] INT : item index
722 * RETURN:
723 * None
725 static VOID LISTVIEW_KeySelection(HWND hwnd, INT nItem)
727 WORD wShift = HIWORD(GetKeyState(VK_SHIFT));
728 WORD wCtrl = HIWORD(GetKeyState(VK_CONTROL));
730 if (wShift)
732 LISTVIEW_SetGroupSelection(hwnd, nItem);
734 else if (wCtrl)
736 LISTVIEW_SetItemFocus(hwnd, nItem);
738 else
740 LISTVIEW_SetSelection(hwnd, nItem);
742 /* if multiple selection is allowed */
743 ListView_EnsureVisible(hwnd, nItem, FALSE);
747 /***
748 * DESCRIPTION:
749 * Removes all selection states.
751 * PARAMETER(S):
752 * [I] HWND : window handle
753 * [I] INT : item index
755 * RETURN:
756 * SUCCCESS : TRUE
757 * FAILURE : FALSE
759 static VOID LISTVIEW_RemoveSelections(HWND hwnd, INT nFirst, INT nLast)
761 LVITEMA lvItem;
762 INT i;
764 lvItem.state = 0;
765 lvItem.stateMask = LVIS_SELECTED;
767 for (i = nFirst; i <= nLast; i++)
769 ListView_SetItemState(hwnd, i, &lvItem);
773 /***
774 * DESCRIPTION:
775 * Removes a column.
777 * PARAMETER(S):
778 * [IO] HDPA : dynamic pointer array handle
779 * [I] INT : column index (subitem index)
781 * RETURN:
782 * SUCCCESS : TRUE
783 * FAILURE : FALSE
785 static BOOL LISTVIEW_RemoveColumn(HDPA hdpaItems, INT nSubItem)
787 BOOL bResult = TRUE;
788 HDPA hdpaSubItems;
789 INT i;
791 for (i = 0; i < hdpaItems->nItemCount; i++)
793 hdpaSubItems = (HDPA)DPA_GetPtr(hdpaItems, i);
794 if (hdpaSubItems != NULL)
796 if (LISTVIEW_RemoveSubItem(hdpaSubItems, nSubItem) == FALSE)
798 bResult = FALSE;
803 return bResult;
806 /***
807 * DESCRIPTION:
808 * Removes a subitem at a given position.
810 * PARAMETER(S):
811 * [IO] HDPA : dynamic pointer array handle
812 * [I] INT : subitem index
814 * RETURN:
815 * SUCCCESS : TRUE
816 * FAILURE : FALSE
818 static BOOL LISTVIEW_RemoveSubItem(HDPA hdpaSubItems, INT nSubItem)
820 LISTVIEW_SUBITEM *lpSubItem;
821 INT i;
823 for (i = 1; i < hdpaSubItems->nItemCount; i++)
825 lpSubItem = (LISTVIEW_SUBITEM *)DPA_GetPtr(hdpaSubItems, i);
826 if (lpSubItem != NULL)
828 if (lpSubItem->iSubItem == nSubItem)
830 /* free string */
831 if ((lpSubItem->pszText != NULL) &&
832 (lpSubItem->pszText != LPSTR_TEXTCALLBACKA))
834 COMCTL32_Free(lpSubItem->pszText);
837 /* free item */
838 COMCTL32_Free(lpSubItem);
840 /* free dpa memory */
841 if (DPA_DeletePtr(hdpaSubItems, i) == NULL)
843 return FALSE;
846 else if (lpSubItem->iSubItem > nSubItem)
848 return TRUE;
853 return TRUE;
856 /***
857 * DESCRIPTION:
858 * Compares the item information.
860 * PARAMETER(S):
861 * [I] LISTVIEW_ITEM *: destination item
862 * [I] LPLVITEM : source item
864 * RETURN:
865 * SUCCCESS : TRUE (EQUAL)
866 * FAILURE : FALSE (NOT EQUAL)
868 static UINT LISTVIEW_GetItemChanges(LISTVIEW_ITEM *lpItem, LPLVITEMA lpLVItem)
870 UINT uChanged = 0;
872 if ((lpItem != NULL) && (lpLVItem != NULL))
874 if (lpLVItem->mask & LVIF_STATE)
876 if ((lpItem->state & lpLVItem->stateMask) !=
877 (lpLVItem->state & lpLVItem->stateMask))
879 uChanged |= LVIF_STATE;
883 if (lpLVItem->mask & LVIF_IMAGE)
885 if (lpItem->iImage != lpLVItem->iImage)
887 uChanged |= LVIF_IMAGE;
891 if (lpLVItem->mask & LVIF_PARAM)
893 if (lpItem->lParam != lpLVItem->lParam)
895 uChanged |= LVIF_PARAM;
899 if (lpLVItem->mask & LVIF_INDENT)
901 if (lpItem->iIndent != lpLVItem->iIndent)
903 uChanged |= LVIF_INDENT;
907 if (lpLVItem->mask & LVIF_TEXT)
909 if (lpLVItem->pszText == LPSTR_TEXTCALLBACKA)
911 if (lpItem->pszText != LPSTR_TEXTCALLBACKA)
913 uChanged |= LVIF_TEXT;
916 else
918 if (lpItem->pszText == LPSTR_TEXTCALLBACKA)
920 uChanged |= LVIF_TEXT;
926 return uChanged;
929 /***
930 * DESCRIPTION:
931 * Initializes item attributes.
933 * PARAMETER(S):
934 * [I] HWND : window handle
935 * [O] LISTVIEW_ITEM *: destination item
936 * [I] LPLVITEM : source item
938 * RETURN:
939 * SUCCCESS : TRUE
940 * FAILURE : FALSE
942 static BOOL LISTVIEW_InitItem(HWND hwnd, LISTVIEW_ITEM *lpItem,
943 LPLVITEMA lpLVItem)
945 LONG lStyle = GetWindowLongA(hwnd, GWL_STYLE);
946 BOOL bResult = FALSE;
948 if ((lpItem != NULL) && (lpLVItem != NULL))
950 bResult = TRUE;
952 if (lpLVItem->mask & LVIF_STATE)
954 lpItem->state &= ~lpLVItem->stateMask;
955 lpItem->state |= (lpLVItem->state & lpLVItem->stateMask);
958 if (lpLVItem->mask & LVIF_IMAGE)
960 lpItem->iImage = lpLVItem->iImage;
963 if (lpLVItem->mask & LVIF_PARAM)
965 lpItem->lParam = lpLVItem->lParam;
968 if (lpLVItem->mask & LVIF_INDENT)
970 lpItem->iIndent = lpLVItem->iIndent;
973 if (lpLVItem->mask & LVIF_TEXT)
975 if (lpLVItem->pszText == LPSTR_TEXTCALLBACKA)
977 if ((lStyle & LVS_SORTASCENDING) || (lStyle & LVS_SORTDESCENDING))
979 return FALSE;
982 if ((lpItem->pszText != NULL) &&
983 (lpItem->pszText != LPSTR_TEXTCALLBACKA))
985 COMCTL32_Free(lpItem->pszText);
988 lpItem->pszText = LPSTR_TEXTCALLBACKA;
990 else
992 if (lpItem->pszText == LPSTR_TEXTCALLBACKA)
994 lpItem->pszText = NULL;
997 bResult = Str_SetPtrA(&lpItem->pszText, lpLVItem->pszText);
1002 return bResult;
1005 /***
1006 * DESCRIPTION:
1007 * Initializes subitem attributes.
1009 * NOTE: the documentation specifies that the operation fails if the user
1010 * tries to set the indent of a subitem.
1012 * PARAMETER(S):
1013 * [I] HWND : window handle
1014 * [O] LISTVIEW_SUBITEM *: destination subitem
1015 * [I] LPLVITEM : source subitem
1017 * RETURN:
1018 * SUCCCESS : TRUE
1019 * FAILURE : FALSE
1021 static BOOL LISTVIEW_InitSubItem(HWND hwnd, LISTVIEW_SUBITEM *lpSubItem,
1022 LPLVITEMA lpLVItem)
1024 LONG lStyle = GetWindowLongA(hwnd, GWL_STYLE);
1025 BOOL bResult = FALSE;
1027 if ((lpSubItem != NULL) && (lpLVItem != NULL))
1029 if (!(lpLVItem->mask & LVIF_INDENT))
1031 bResult = TRUE;
1032 ZeroMemory(lpSubItem, sizeof(LISTVIEW_SUBITEM));
1034 lpSubItem->iSubItem = lpLVItem->iSubItem;
1036 if (lpLVItem->mask & LVIF_IMAGE)
1038 lpSubItem->iImage = lpLVItem->iImage;
1041 if (lpLVItem->mask & LVIF_TEXT)
1043 if (lpLVItem->pszText == LPSTR_TEXTCALLBACKA)
1045 if ((lStyle & LVS_SORTASCENDING) || (lStyle & LVS_SORTDESCENDING))
1047 return FALSE;
1050 if ((lpSubItem->pszText != NULL) &&
1051 (lpSubItem->pszText != LPSTR_TEXTCALLBACKA))
1053 COMCTL32_Free(lpSubItem->pszText);
1056 lpSubItem->pszText = LPSTR_TEXTCALLBACKA;
1058 else
1060 if (lpSubItem->pszText == LPSTR_TEXTCALLBACKA)
1062 lpSubItem->pszText = NULL;
1065 bResult = Str_SetPtrA(&lpSubItem->pszText, lpLVItem->pszText);
1071 return bResult;
1074 /***
1075 * DESCRIPTION:
1076 * Adds a subitem at a given position (column index).
1078 * PARAMETER(S):
1079 * [I] HWND : window handle
1080 * [I] LPLVITEM : new subitem atttributes
1082 * RETURN:
1083 * SUCCESS : TRUE
1084 * FAILURE : FALSE
1086 static BOOL LISTVIEW_AddSubItem(HWND hwnd, LPLVITEMA lpLVItem)
1088 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
1089 BOOL bResult = FALSE;
1090 HDPA hdpaSubItems;
1091 LISTVIEW_SUBITEM *lpSubItem = NULL;
1092 INT nPosition, nItem;
1094 if (lpLVItem != NULL)
1096 hdpaSubItems = (HDPA)DPA_GetPtr(infoPtr->hdpaItems, lpLVItem->iItem);
1097 if (hdpaSubItems != NULL)
1099 lpSubItem = (LISTVIEW_SUBITEM *)COMCTL32_Alloc(sizeof(LISTVIEW_SUBITEM));
1100 if (lpSubItem != NULL)
1102 if (LISTVIEW_InitSubItem(hwnd, lpSubItem, lpLVItem) == TRUE)
1104 nPosition = LISTVIEW_FindInsertPosition(hdpaSubItems,
1105 lpSubItem->iSubItem);
1106 nItem = DPA_InsertPtr(hdpaSubItems, nPosition, lpSubItem);
1107 if (nItem != -1)
1109 bResult = TRUE;
1116 /* cleanup if unsuccessful */
1117 if ((bResult == FALSE) && (lpSubItem != NULL))
1119 COMCTL32_Free(lpSubItem);
1122 return bResult;
1125 /***
1126 * DESCRIPTION:
1127 * Finds the dpa insert position (array index).
1129 * PARAMETER(S):
1130 * [I] HWND : window handle
1131 * [I] INT : subitem index
1133 * RETURN:
1134 * SUCCESS : TRUE
1135 * FAILURE : FALSE
1137 static INT LISTVIEW_FindInsertPosition(HDPA hdpaSubItems, INT nSubItem)
1139 LISTVIEW_SUBITEM *lpSubItem;
1140 INT i;
1142 for (i = 1; i < hdpaSubItems->nItemCount; i++)
1144 lpSubItem = (LISTVIEW_SUBITEM *)DPA_GetPtr(hdpaSubItems, i);
1145 if (lpSubItem != NULL)
1147 if (lpSubItem->iSubItem > nSubItem)
1149 return i;
1154 return hdpaSubItems->nItemCount;
1157 /***
1158 * DESCRIPTION:
1159 * Retrieves a listview subitem at a given position (column index).
1161 * PARAMETER(S):
1162 * [I] HWND : window handle
1163 * [I] INT : subitem index
1165 * RETURN:
1166 * SUCCESS : TRUE
1167 * FAILURE : FALSE
1169 static LISTVIEW_SUBITEM* LISTVIEW_GetSubItem(HDPA hdpaSubItems, INT nSubItem)
1171 LISTVIEW_SUBITEM *lpSubItem;
1172 INT i;
1174 for (i = 1; i < hdpaSubItems->nItemCount; i++)
1176 lpSubItem = (LISTVIEW_SUBITEM *)DPA_GetPtr(hdpaSubItems, i);
1177 if (lpSubItem != NULL)
1179 if (lpSubItem->iSubItem == nSubItem)
1181 return lpSubItem;
1183 else if (lpSubItem->iSubItem > nSubItem)
1185 return NULL;
1190 return NULL;
1193 /***
1194 * DESCRIPTION:
1195 * Sets item attributes.
1197 * PARAMETER(S):
1198 * [I] HWND : window handle
1199 * [I] LPLVITEM : new item atttributes
1201 * RETURN:
1202 * SUCCESS : TRUE
1203 * FAILURE : FALSE
1205 static BOOL LISTVIEW_SetItem(HWND hwnd, LPLVITEMA lpLVItem)
1207 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
1208 BOOL bResult = FALSE;
1209 HDPA hdpaSubItems;
1210 LISTVIEW_ITEM *lpItem;
1211 NMLISTVIEW nmlv;
1212 UINT uChanged;
1213 LONG lCtrlId = GetWindowLongA(hwnd, GWL_ID);
1215 if (lpLVItem != NULL)
1217 if (lpLVItem->iSubItem == 0)
1219 hdpaSubItems = (HDPA)DPA_GetPtr(infoPtr->hdpaItems, lpLVItem->iItem);
1220 if (hdpaSubItems != NULL)
1222 lpItem = (LISTVIEW_ITEM *)DPA_GetPtr(hdpaSubItems, lpLVItem->iSubItem);
1223 if (lpItem != NULL)
1225 ZeroMemory(&nmlv, sizeof(NMLISTVIEW));
1226 nmlv.hdr.hwndFrom = hwnd;
1227 nmlv.hdr.idFrom = lCtrlId;
1228 nmlv.hdr.code = LVN_ITEMCHANGING;
1229 nmlv.lParam = lpItem->lParam;
1230 uChanged = LISTVIEW_GetItemChanges(lpItem, lpLVItem);
1231 if (uChanged != 0)
1233 if (uChanged & LVIF_STATE)
1235 nmlv.uNewState = lpLVItem->state & lpLVItem->stateMask;
1236 nmlv.uOldState = lpItem->state & lpLVItem->stateMask;
1239 nmlv.uChanged = uChanged;
1240 nmlv.iItem = lpLVItem->iItem;
1241 nmlv.lParam = lpItem->lParam;
1242 /* send LVN_ITEMCHANGING notification */
1243 ListView_LVNotify(GetParent(hwnd), lCtrlId, &nmlv);
1245 /* copy information */
1246 bResult = LISTVIEW_InitItem(hwnd, lpItem, lpLVItem);
1248 /* send LVN_ITEMCHANGED notification */
1249 nmlv.hdr.code = LVN_ITEMCHANGED;
1250 ListView_LVNotify(GetParent(hwnd), lCtrlId, &nmlv);
1252 else
1254 bResult = TRUE;
1257 InvalidateRect(hwnd, NULL, FALSE);
1263 return bResult;
1266 /***
1267 * DESCRIPTION:
1268 * Sets subitem attributes.
1270 * PARAMETER(S):
1271 * [I] HWND : window handle
1272 * [I] LPLVITEM : new subitem atttributes
1274 * RETURN:
1275 * SUCCESS : TRUE
1276 * FAILURE : FALSE
1278 static BOOL LISTVIEW_SetSubItem(HWND hwnd, LPLVITEMA lpLVItem)
1280 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
1281 BOOL bResult = FALSE;
1282 HDPA hdpaSubItems;
1283 LISTVIEW_SUBITEM *lpSubItem;
1285 if (lpLVItem != NULL)
1287 if (lpLVItem->iSubItem > 0)
1289 hdpaSubItems = (HDPA)DPA_GetPtr(infoPtr->hdpaItems, lpLVItem->iItem);
1290 if (hdpaSubItems != NULL)
1292 /* set subitem only if column is present */
1293 if (Header_GetItemCount(infoPtr->hwndHeader) > lpLVItem->iSubItem)
1295 lpSubItem = LISTVIEW_GetSubItem(hdpaSubItems, lpLVItem->iSubItem);
1296 if (lpSubItem != NULL)
1298 bResult = LISTVIEW_InitSubItem(hwnd, lpSubItem, lpLVItem);
1300 else
1302 bResult = LISTVIEW_AddSubItem(hwnd, lpLVItem);
1305 InvalidateRect(hwnd, NULL, FALSE);
1311 return bResult;
1314 /***
1315 * DESCRIPTION:
1316 * Retrieves the index of the item at coordinate (0, 0) of the client area.
1318 * PARAMETER(S):
1319 * [I] HWND : window handle
1321 * RETURN:
1322 * item index
1324 static INT LISTVIEW_GetTopIndex(HWND hwnd)
1326 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *) GetWindowLongA(hwnd, 0);
1327 LONG lStyle = GetWindowLongA(hwnd, GWL_STYLE);
1328 INT nItem = 0;
1330 switch (LVS_TYPEMASK & lStyle)
1332 case LVS_LIST:
1333 if (lStyle & WS_HSCROLL)
1335 nItem = GetScrollPos(hwnd, SB_HORZ) * infoPtr->nCountPerColumn;
1337 break;
1339 case LVS_REPORT:
1340 if (lStyle & WS_VSCROLL)
1342 nItem = GetScrollPos(hwnd, SB_VERT);
1344 break;
1347 return nItem;
1350 /***
1351 * DESCRIPTION:
1352 * Sets scrollbar(s).
1354 * PARAMETER(S):
1355 * [I] HWND : window handle
1357 * RETURN:
1358 * TRUE if scrollbars were added, modified or removed.
1360 static VOID LISTVIEW_SetVScroll(HWND hwnd)
1362 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
1363 LONG lStyle = GetWindowLongA(hwnd, GWL_STYLE);
1364 INT nScrollPos;
1365 INT nMaxRange;
1367 switch (LVS_TYPEMASK & lStyle)
1369 case LVS_REPORT:
1370 nMaxRange = GETITEMCOUNT(infoPtr) - infoPtr->nCountPerColumn;
1371 SetScrollRange(hwnd, SB_VERT, 0, nMaxRange, FALSE);
1372 nScrollPos = ListView_GetTopIndex(hwnd);
1373 SetScrollPos(hwnd, SB_VERT, nScrollPos, TRUE);
1374 break;
1376 default:
1377 /* TO DO */
1381 static VOID LISTVIEW_SetHScroll(HWND hwnd)
1383 /* LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0); */
1384 LONG lStyle = GetWindowLongA(hwnd, GWL_STYLE);
1385 /* INT nScrollPos; */
1386 /* INT nMaxRange; */
1388 switch (LVS_TYPEMASK & lStyle)
1390 case LVS_REPORT:
1391 /* TO DO */
1392 break;
1394 default:
1395 /* TO DO */
1399 static VOID LISTVIEW_SetScroll(HWND hwnd)
1401 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
1402 LONG lStyle = GetWindowLongA(hwnd, GWL_STYLE);
1403 INT nHiddenItemCount;
1404 INT nScrollPos;
1405 INT nMaxRange;
1406 INT nCountPerPage;
1407 RECT rc;
1408 BOOL bHScroll = FALSE;
1409 BOOL bVScroll = FALSE;
1410 INT nHeaderWidth = 0;
1411 INT nItemCount;
1412 INT i;
1414 switch (LVS_TYPEMASK & lStyle)
1416 case LVS_LIST:
1417 nCountPerPage = infoPtr->nCountPerRow * infoPtr->nCountPerColumn;
1418 if (nCountPerPage < GETITEMCOUNT(infoPtr))
1420 /* add scrollbar if not already present */
1421 if (!(lStyle & WS_HSCROLL))
1423 ShowScrollBar(hwnd, SB_HORZ, TRUE);
1426 /* calculate new scrollbar range */
1427 nHiddenItemCount = GETITEMCOUNT(infoPtr) - nCountPerPage;
1428 if ((nHiddenItemCount % infoPtr->nCountPerColumn) == 0)
1430 nMaxRange = nHiddenItemCount / infoPtr->nCountPerColumn;
1432 else
1434 nMaxRange = nHiddenItemCount / infoPtr->nCountPerColumn + 1;
1437 SetScrollRange(hwnd, SB_HORZ, 0, nMaxRange, FALSE);
1438 nScrollPos = ListView_GetTopIndex(hwnd) / infoPtr->nCountPerColumn;
1439 SetScrollPos(hwnd, SB_HORZ, nScrollPos, TRUE);
1441 else
1443 /* remove scrollbar if present */
1444 if (lStyle & WS_HSCROLL)
1446 /* hide scrollbar */
1447 ShowScrollBar(hwnd, SB_HORZ, FALSE);
1450 break;
1452 case LVS_REPORT:
1453 nItemCount = Header_GetItemCount(infoPtr->hwndHeader);
1454 for (i = 0; i < nItemCount; i++)
1456 if (Header_GetItemRect(infoPtr->hwndHeader, i, &rc) != 0)
1458 nHeaderWidth += (rc.right - rc.left);
1462 if (nHeaderWidth > (infoPtr->rcList.right - infoPtr->rcList.left))
1464 bHScroll = TRUE;
1466 /* add horizontal scrollbar if not present */
1467 if (!(lStyle & WS_HSCROLL))
1469 /* display scrollbar */
1470 ShowScrollBar(hwnd, SB_HORZ, TRUE);
1473 else
1475 /* remove scrollbar if present */
1476 if (lStyle & WS_HSCROLL)
1478 /* hide scrollbar */
1479 ShowScrollBar(hwnd, SB_HORZ, FALSE);
1483 if (infoPtr->nCountPerColumn < GETITEMCOUNT(infoPtr))
1485 bVScroll = TRUE;
1487 /* add scrollbar if not already present */
1488 if (!(lStyle & WS_VSCROLL))
1490 /* display scrollbar */
1491 ShowScrollBar(hwnd, SB_VERT, TRUE);
1494 else
1496 /* remove scrollbar if present */
1497 if (lStyle & WS_VSCROLL)
1499 /* hide scrollbar */
1500 ShowScrollBar(hwnd, SB_VERT, FALSE);
1503 break;
1505 default:
1506 /* TO DO */
1509 /* set range and position */
1510 GetClientRect(hwnd, &rc);
1511 if ((bHScroll == TRUE) || (bVScroll == TRUE))
1513 LISTVIEW_SetSize(hwnd, lStyle, rc.right, rc.bottom);
1514 LISTVIEW_SetViewInfo(hwnd);
1515 if (bHScroll == TRUE)
1517 LISTVIEW_SetHScroll(hwnd);
1520 if (bVScroll == TRUE)
1522 LISTVIEW_SetVScroll(hwnd);
1527 /***
1528 * DESCRIPTION:
1529 * Draws a subitem.
1531 * PARAMETER(S):
1532 * [I] HDC : device context handle
1533 * [I] LISTVIEW_INFO * : listview information
1534 * [I] LISTVIEW_SUBITEM * : subitem
1535 * [I] RECT * : clipping rectangle
1537 * RETURN:
1538 * None
1540 static VOID LISTVIEW_DrawSubItem(HWND hwnd, HDC hdc, INT nItem, LPARAM lParam,
1541 LISTVIEW_SUBITEM *lpSubItem, INT nColumn,
1542 RECT *lprc)
1544 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
1545 CHAR szDispText[DISP_TEXT_SIZE];
1546 LPSTR pszDispText = NULL;
1548 /* set item colors */
1549 SetBkColor(hdc, infoPtr->clrTextBk);
1550 SetTextColor(hdc, infoPtr->clrText);
1552 pszDispText = szDispText;
1553 LISTVIEW_GetSubItemDispInfo(hwnd, nItem, lParam, lpSubItem, nColumn, NULL,
1554 &pszDispText, DISP_TEXT_SIZE);
1556 /* draw text : using arbitrary offset of 10 pixels */
1557 ExtTextOutA(hdc, lprc->left + 10, lprc->top, ETO_OPAQUE|ETO_CLIPPED,
1558 lprc, pszDispText, lstrlenA(pszDispText), NULL);
1561 /***
1562 * DESCRIPTION:
1563 * Draws an item.
1565 * PARAMETER(S):
1566 * [I] HDC : device context handle
1567 * [I] LISTVIEW_INFO * : listview information
1568 * [I] LISTVIEW_ITEM * : item
1569 * [I] RECT * : clipping rectangle
1571 * RETURN:
1572 * None
1574 static VOID LISTVIEW_DrawItem(HWND hwnd, HDC hdc, LISTVIEW_ITEM *lpItem,
1575 INT nItem, RECT *lprc)
1577 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
1578 BOOL bSelected;
1579 INT nLabelWidth;
1580 INT nImage;
1581 CHAR szDispText[DISP_TEXT_SIZE];
1582 LPSTR pszDispText = NULL;
1583 UINT uState;
1585 pszDispText = szDispText;
1586 LISTVIEW_GetItemDispInfo(hwnd, nItem, lpItem, &nImage, &uState, &pszDispText,
1587 DISP_TEXT_SIZE);
1588 if (uState & LVIS_SELECTED)
1590 bSelected = TRUE;
1592 /* set item colors */
1593 SetBkColor(hdc, GetSysColor(COLOR_HIGHLIGHT));
1594 SetTextColor(hdc, GetSysColor(COLOR_HIGHLIGHTTEXT));
1596 /* set raster mode */
1597 SetROP2(hdc, R2_XORPEN);
1599 else
1601 bSelected = FALSE;
1603 /* set item colors */
1604 SetBkColor(hdc, infoPtr->clrTextBk);
1605 SetTextColor(hdc, infoPtr->clrText);
1607 /* set raster mode */
1608 SetROP2(hdc, R2_COPYPEN);
1611 /* state icons */
1612 if (infoPtr->himlState != NULL)
1614 /* right shift 12 bits to obtain index in image list */
1615 if (bSelected == TRUE)
1617 ImageList_Draw(infoPtr->himlState, uState >> 12, hdc, lprc->left,
1618 lprc->top, ILD_SELECTED);
1620 else
1622 ImageList_Draw(infoPtr->himlState, uState >> 12, hdc, lprc->left,
1623 lprc->top, ILD_NORMAL);
1626 lprc->left += infoPtr->iconSize.cx;
1629 /* small icons */
1630 if (infoPtr->himlSmall != NULL)
1632 if (bSelected == TRUE)
1634 ImageList_Draw(infoPtr->himlSmall, nImage, hdc, lprc->left,
1635 lprc->top, ILD_SELECTED);
1637 else
1639 ImageList_Draw(infoPtr->himlSmall, nImage, hdc, lprc->left,
1640 lprc->top, ILD_NORMAL);
1643 lprc->left += infoPtr->iconSize.cx;
1646 nLabelWidth = ListView_GetStringWidthA(hwnd, pszDispText);
1647 if (lprc->left + nLabelWidth < lprc->right)
1649 lprc->right = lprc->left + nLabelWidth;
1652 /* draw text */
1653 ExtTextOutA(hdc, lprc->left + 1, lprc->top + 1, ETO_OPAQUE|ETO_CLIPPED,
1654 lprc, pszDispText, lstrlenA(pszDispText), NULL);
1656 if (lpItem->state & LVIS_FOCUSED)
1658 Rectangle(hdc, lprc->left, lprc->top, lprc->right, lprc->bottom);
1662 /***
1663 * DESCRIPTION:
1664 * Draws listview items when in report display mode.
1666 * PARAMETER(S):
1667 * [I] HWND : window handle
1668 * [I] HDC : device context handle
1670 * RETURN:
1671 * None
1673 static VOID LISTVIEW_RefreshReport(HWND hwnd, HDC hdc)
1675 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd,0);
1676 INT nDrawPosY = infoPtr->rcList.top;
1677 LISTVIEW_ITEM *lpItem;
1678 LISTVIEW_SUBITEM *lpSubItem = NULL;
1679 INT nColumnCount;
1680 HDPA hdpaSubItems;
1681 RECT rc;
1682 INT j, k;
1683 INT nItem;
1684 INT nLast;
1685 BOOL bNeedSubItem = TRUE;
1687 nItem = ListView_GetTopIndex(hwnd);
1688 nLast = nItem + infoPtr->nCountPerColumn;
1689 while (nItem <= nLast)
1691 hdpaSubItems = (HDPA)DPA_GetPtr(infoPtr->hdpaItems, nItem);
1692 if (hdpaSubItems != NULL)
1694 lpItem = (LISTVIEW_ITEM *)DPA_GetPtr(hdpaSubItems, 0);
1695 if (lpItem != NULL)
1697 Header_GetItemRect(infoPtr->hwndHeader, 0, &rc);
1698 rc.top = nDrawPosY;
1699 rc.bottom = rc.top + infoPtr->nItemHeight;
1701 /* draw state icon + icon + text */
1702 LISTVIEW_DrawItem(hwnd, hdc, lpItem, nItem, &rc);
1705 nColumnCount = Header_GetItemCount(infoPtr->hwndHeader);
1706 for (k = 1, j = 1; j < nColumnCount; j++)
1708 Header_GetItemRect(infoPtr->hwndHeader, j, &rc);
1709 rc.top = nDrawPosY;
1710 rc.bottom = rc.top + infoPtr->nItemHeight;
1712 if (k < hdpaSubItems->nItemCount)
1714 if (bNeedSubItem == TRUE)
1716 lpSubItem = (LISTVIEW_SUBITEM *)DPA_GetPtr(hdpaSubItems, k);
1717 k++;
1720 if (lpSubItem != NULL)
1722 if (lpSubItem->iSubItem == j)
1724 LISTVIEW_DrawSubItem(hwnd, hdc, nItem, lpItem->lParam, lpSubItem,
1725 j, &rc);
1726 bNeedSubItem = TRUE;
1728 else
1730 LISTVIEW_DrawSubItem(hwnd, hdc, nItem, lpItem->lParam, NULL, j,
1731 &rc);
1732 bNeedSubItem = FALSE;
1735 else
1737 LISTVIEW_DrawSubItem(hwnd, hdc, nItem, lpItem->lParam, NULL, j,
1738 &rc);
1739 bNeedSubItem = TRUE;
1742 else
1744 LISTVIEW_DrawSubItem(hwnd, hdc, nItem, lpItem->lParam, NULL, j, &rc);
1749 nDrawPosY += infoPtr->nItemHeight;
1750 nItem++;
1754 /***
1755 * DESCRIPTION:
1756 * Draws listview items when in list display mode.
1758 * PARAMETER(S):
1759 * [I] HWND : window handle
1760 * [I] HDC : device context handle
1762 * RETURN:
1763 * None
1765 static VOID LISTVIEW_RefreshList(HWND hwnd, HDC hdc)
1767 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
1768 LISTVIEW_ITEM *lpItem;
1769 HDPA hdpaSubItems;
1770 RECT rc;
1771 INT i, j;
1772 INT nColumnCount;
1773 INT nItem = ListView_GetTopIndex(hwnd);
1775 if (infoPtr->rcList.right > 0)
1777 /* get number of display columns */
1778 if (infoPtr->rcList.right % infoPtr->nColumnWidth == 0)
1780 nColumnCount = infoPtr->rcList.right / infoPtr->nColumnWidth;
1782 else
1784 nColumnCount = infoPtr->rcList.right / infoPtr->nColumnWidth + 1;
1787 for (i = 0; i < nColumnCount; i++)
1789 j = 0;
1790 while ((nItem < GETITEMCOUNT(infoPtr)) && (j < infoPtr->nCountPerColumn))
1792 hdpaSubItems = (HDPA)DPA_GetPtr(infoPtr->hdpaItems, nItem);
1793 if (hdpaSubItems != NULL)
1795 lpItem = (LISTVIEW_ITEM *)DPA_GetPtr(hdpaSubItems, 0);
1796 if (lpItem != NULL)
1798 rc.top = j * infoPtr->nItemHeight;
1799 rc.left = i * infoPtr->nColumnWidth;
1800 rc.bottom = rc.top + infoPtr->nItemHeight;
1801 rc.right = rc.left + infoPtr->nColumnWidth;
1803 /* draw state icon + icon + text */
1804 LISTVIEW_DrawItem(hwnd, hdc, lpItem, nItem, &rc);
1808 nItem++;
1809 j++;
1815 /***
1816 * DESCRIPTION:
1817 * Draws listview items when in small icon display mode.
1819 * PARAMETER(S):
1820 * [I] HWND : window handle
1821 * [I] HDC : device context handle
1823 * RETURN:
1824 * None
1826 static VOID LISTVIEW_RefreshSmallIcon(HWND hwnd, HDC hdc)
1828 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
1829 LISTVIEW_ITEM *lpItem;
1830 HDPA hdpaSubItems;
1831 RECT rc;
1832 INT i, j;
1833 INT nItem = ListView_GetTopIndex(hwnd);
1835 for (i = 0; i < infoPtr->nCountPerColumn; i++)
1837 j = 0;
1838 while ((nItem < GETITEMCOUNT(infoPtr)) && (j < infoPtr->nCountPerRow))
1840 hdpaSubItems = (HDPA)DPA_GetPtr(infoPtr->hdpaItems, nItem);
1841 if (hdpaSubItems != NULL)
1843 lpItem = (LISTVIEW_ITEM *)DPA_GetPtr(hdpaSubItems, 0);
1844 if (lpItem != NULL)
1846 rc.top = i * infoPtr->nItemHeight;
1847 rc.left = j * infoPtr->nColumnWidth;
1848 rc.bottom = rc.top + infoPtr->nItemHeight;
1849 rc.right = rc.left + infoPtr->nColumnWidth;
1851 /* draw state icon + icon + text */
1852 LISTVIEW_DrawItem(hwnd, hdc, lpItem, nItem, &rc);
1856 nItem++;
1857 j++;
1862 /***
1863 * DESCRIPTION:
1864 * Draws listview items when in icon display mode.
1866 * PARAMETER(S):
1867 * [I] HWND : window handle
1868 * [I] HDC : device context handle
1870 * RETURN:
1871 * None
1873 static VOID LISTVIEW_RefreshIcon(HWND hwnd, HDC hdc)
1875 /* TO DO */
1878 /***
1879 * DESCRIPTION:
1880 * Draws listview items.
1882 * PARAMETER(S):
1883 * [I] HWND : window handle
1884 * [I] HDC : device context handle
1886 * RETURN:
1887 * NoneX
1889 static VOID LISTVIEW_Refresh(HWND hwnd, HDC hdc)
1891 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
1892 LONG lStyle = GetWindowLongA(hwnd, GWL_STYLE);
1893 HFONT hOldFont;
1894 HPEN hPen, hOldPen;
1896 /* select font */
1897 hOldFont = SelectObject(hdc, infoPtr->hFont);
1899 /* select the doted pen (for drawing the focus box) */
1900 hPen = CreatePen(PS_DOT, 1, 0);
1901 hOldPen = SelectObject(hdc, hPen);
1903 /* select transparent brush (for drawing the focus box) */
1904 SelectObject(hdc, GetStockObject(NULL_BRUSH));
1906 switch (LVS_TYPEMASK & lStyle)
1908 case LVS_LIST:
1909 LISTVIEW_RefreshList(hwnd, hdc);
1910 break;
1911 case LVS_REPORT:
1912 LISTVIEW_RefreshReport(hwnd, hdc);
1913 break;
1914 case LVS_SMALLICON:
1915 LISTVIEW_RefreshSmallIcon(hwnd, hdc);
1916 break;
1917 case LVS_ICON:
1918 LISTVIEW_RefreshIcon(hwnd, hdc);
1921 /* unselect objects */
1922 SelectObject(hdc, hOldFont);
1923 SelectObject(hdc, hOldPen);
1925 /* delete pen */
1926 DeleteObject(hPen);
1930 /***
1931 * DESCRIPTION:
1932 * Calculates the approximate width and height of a given number of items.
1934 * PARAMETER(S):
1935 * [I] HWND : window handle
1936 * [I] INT : number of items
1937 * [I] INT : width
1938 * [I] INT : height
1940 * RETURN:
1941 * Returns a DWORD. The width in the low word and the height in high word.
1943 static LRESULT LISTVIEW_ApproximateViewRect(HWND hwnd, INT nItemCount,
1944 WORD wWidth, WORD wHeight)
1946 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
1947 LONG lStyle = GetWindowLongA(hwnd, GWL_STYLE);
1948 INT nItemCountPerColumn = 1;
1949 INT nColumnCount = 0;
1950 DWORD dwViewRect = 0;
1952 if (nItemCount == -1)
1953 nItemCount = GETITEMCOUNT(infoPtr);
1955 if (lStyle & LVS_LIST)
1957 if (wHeight == 0xFFFF)
1959 /* use current height */
1960 wHeight = infoPtr->rcList.bottom;
1963 if (wHeight < infoPtr->nItemHeight)
1965 wHeight = infoPtr->nItemHeight;
1968 if (nItemCount > 0)
1970 if (infoPtr->nItemHeight > 0)
1972 nItemCountPerColumn = wHeight / infoPtr->nItemHeight;
1973 if (nItemCountPerColumn == 0)
1974 nItemCountPerColumn = 1;
1976 if (nItemCount % nItemCountPerColumn != 0)
1977 nColumnCount = nItemCount / nItemCountPerColumn;
1978 else
1979 nColumnCount = nItemCount / nItemCountPerColumn + 1;
1983 /* Microsoft padding magic */
1984 wHeight = nItemCountPerColumn * infoPtr->nItemHeight + 2;
1985 wWidth = nColumnCount * infoPtr->nColumnWidth + 2;
1987 dwViewRect = MAKELONG(wWidth, wHeight);
1989 else if (lStyle & LVS_REPORT)
1991 /* TO DO */
1993 else if (lStyle & LVS_SMALLICON)
1995 /* TO DO */
1997 else if (lStyle & LVS_ICON)
1999 /* TO DO */
2002 return dwViewRect;
2005 /***
2006 * DESCRIPTION:
2007 * Arranges listview items in icon display mode.
2009 * PARAMETER(S):
2010 * [I] HWND : window handle
2011 * [I] INT : alignment code
2013 * RETURN:
2014 * SUCCESS : TRUE
2015 * FAILURE : FALSE
2017 static LRESULT LISTVIEW_Arrange(HWND hwnd, INT nAlignCode)
2019 LONG lStyle = GetWindowLongA(hwnd, GWL_STYLE);
2020 BOOL bResult = FALSE;
2022 if (((LVS_TYPEMASK & lStyle) == LVS_ICON) ||
2023 ((LVS_TYPEMASK & lStyle) == LVS_SMALLICON))
2025 switch (nAlignCode)
2027 case LVA_ALIGNLEFT:
2028 /* TO DO */
2029 break;
2030 case LVA_ALIGNTOP:
2031 /* TO DO */
2032 break;
2033 case LVA_DEFAULT:
2034 /* TO DO */
2035 break;
2036 case LVA_SNAPTOGRID:
2037 /* TO DO */
2041 return bResult;
2044 /* << LISTVIEW_CreateDragImage >> */
2046 /***
2047 * DESCRIPTION:
2048 * Removes all listview items and subitems.
2050 * PARAMETER(S):
2051 * [I] HWND : window handle
2053 * RETURN:
2054 * SUCCESS : TRUE
2055 * FAILURE : FALSE
2057 static LRESULT LISTVIEW_DeleteAllItems(HWND hwnd)
2059 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
2060 LONG lCtrlId = GetWindowLongA(hwnd, GWL_ID);
2061 LISTVIEW_ITEM *lpItem;
2062 LISTVIEW_SUBITEM *lpSubItem;
2063 NMLISTVIEW nmlv;
2064 BOOL bSuppress;
2065 BOOL bResult = FALSE;
2066 INT i;
2067 INT j;
2068 HDPA hdpaSubItems;
2070 if (GETITEMCOUNT(infoPtr) > 0)
2072 /* initialize memory */
2073 ZeroMemory(&nmlv, sizeof(NMLISTVIEW));
2075 /* send LVN_DELETEALLITEMS notification */
2076 nmlv.hdr.hwndFrom = hwnd;
2077 nmlv.hdr.idFrom = lCtrlId;
2078 nmlv.hdr.code = LVN_DELETEALLITEMS;
2079 nmlv.iItem = -1;
2081 /* verify if subsequent LVN_DELETEITEM notifications should be
2082 suppressed */
2083 bSuppress = ListView_LVNotify(GetParent(hwnd), lCtrlId, &nmlv);
2085 for (i = 0; i < GETITEMCOUNT(infoPtr); i++)
2087 hdpaSubItems = (HDPA)DPA_GetPtr(infoPtr->hdpaItems, i);
2088 if (hdpaSubItems != NULL)
2090 for (j = 1; j < hdpaSubItems->nItemCount; j++)
2092 lpSubItem = (LISTVIEW_SUBITEM *)DPA_GetPtr(hdpaSubItems, j);
2093 if (lpSubItem != NULL)
2095 /* free subitem string */
2096 if ((lpSubItem->pszText != NULL) &&
2097 (lpSubItem->pszText != LPSTR_TEXTCALLBACKA))
2099 COMCTL32_Free(lpSubItem->pszText);
2102 /* free subitem */
2103 COMCTL32_Free(lpSubItem);
2107 lpItem = (LISTVIEW_ITEM *)DPA_GetPtr(hdpaSubItems, 0);
2108 if (lpItem != NULL)
2110 if (bSuppress == FALSE)
2112 /* send LVN_DELETEITEM notification */
2113 nmlv.hdr.code = LVN_DELETEITEM;
2114 nmlv.iItem = i;
2115 nmlv.lParam = lpItem->lParam;
2116 ListView_LVNotify(GetParent(hwnd), lCtrlId, &nmlv);
2119 /* free item string */
2120 if ((lpItem->pszText != NULL) &&
2121 (lpItem->pszText != LPSTR_TEXTCALLBACKA))
2123 COMCTL32_Free(lpItem->pszText);
2126 /* free item */
2127 COMCTL32_Free(lpItem);
2130 DPA_Destroy(hdpaSubItems);
2134 /* reinitialize listview memory */
2135 bResult = DPA_DeleteAllPtrs(infoPtr->hdpaItems);
2137 /* reset scroll parameters */
2138 LISTVIEW_SetScroll(hwnd);
2140 /* invalidate client area (optimization needed) */
2141 InvalidateRect(hwnd, NULL, FALSE);
2144 return bResult;
2147 /***
2148 * DESCRIPTION:
2149 * Removes a column from the listview control.
2151 * PARAMETER(S):
2152 * [I] HWND : window handle
2153 * [I] INT : column index
2155 * RETURN:
2156 * SUCCESS : TRUE
2157 * FAILURE : FALSE
2159 static LRESULT LISTVIEW_DeleteColumn(HWND hwnd, INT nColumn)
2161 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
2162 BOOL bResult = FALSE;
2164 if (Header_DeleteItem(infoPtr->hwndHeader, nColumn) == TRUE)
2166 bResult = LISTVIEW_RemoveColumn(infoPtr->hdpaItems, nColumn);
2169 /* reset scroll parameters */
2170 LISTVIEW_SetScroll(hwnd);
2172 /* refresh client area */
2173 InvalidateRect(hwnd, NULL, FALSE);
2175 return bResult;
2178 /***
2179 * DESCRIPTION:
2180 * Removes an item from the listview control.
2182 * PARAMETER(S):
2183 * [I] HWND : window handle
2184 * [I] INT : item index
2186 * RETURN:
2187 * SUCCESS : TRUE
2188 * FAILURE : FALSE
2190 static LRESULT LISTVIEW_DeleteItem(HWND hwnd, INT nItem)
2192 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
2193 LONG lCtrlId = GetWindowLongA(hwnd, GWL_ID);
2194 NMLISTVIEW nmlv;
2195 BOOL bResult = FALSE;
2196 HDPA hdpaSubItems;
2197 LISTVIEW_ITEM *lpItem;
2198 LISTVIEW_SUBITEM *lpSubItem;
2199 INT i;
2201 if ((nItem >= 0) && (nItem < GETITEMCOUNT(infoPtr)))
2203 /* initialize memory */
2204 ZeroMemory(&nmlv, sizeof(NMLISTVIEW));
2206 hdpaSubItems = (HDPA)DPA_DeletePtr(infoPtr->hdpaItems, nItem);
2207 if (hdpaSubItems != NULL)
2209 for (i = 1; i < hdpaSubItems->nItemCount; i++)
2211 lpSubItem = (LISTVIEW_SUBITEM *)DPA_GetPtr(hdpaSubItems, i);
2212 if (lpSubItem != NULL)
2214 /* free item string */
2215 if ((lpSubItem->pszText != NULL) &&
2216 (lpSubItem->pszText != LPSTR_TEXTCALLBACKA))
2218 COMCTL32_Free(lpSubItem->pszText);
2221 /* free item */
2222 COMCTL32_Free(lpSubItem);
2226 lpItem = (LISTVIEW_ITEM *)DPA_GetPtr(hdpaSubItems, 0);
2227 if (lpItem != NULL)
2229 /* send LVN_DELETEITEM notification */
2230 nmlv.hdr.hwndFrom = hwnd;
2231 nmlv.hdr.idFrom = lCtrlId;
2232 nmlv.hdr.code = LVN_DELETEITEM;
2233 nmlv.iItem = nItem;
2234 nmlv.lParam = lpItem->lParam;
2235 SendMessageA(GetParent(hwnd), WM_NOTIFY, (WPARAM)lCtrlId,
2236 (LPARAM)&nmlv);
2238 /* free item string */
2239 if ((lpItem->pszText != NULL) &&
2240 (lpItem->pszText != LPSTR_TEXTCALLBACKA))
2242 COMCTL32_Free(lpItem->pszText);
2245 /* free item */
2246 COMCTL32_Free(lpItem);
2249 bResult = DPA_Destroy(hdpaSubItems);
2252 /* refresh client area */
2253 InvalidateRect(hwnd, NULL, FALSE);
2256 return bResult;
2259 /* << LISTVIEW_EditLabel >> */
2261 /***
2262 * DESCRIPTION:
2263 * Ensures the specified item is visible, scrolling into view if necessary.
2265 * PARAMETER(S):
2266 * [I] HWND : window handle
2267 * [I] INT : item index
2268 * [I] BOOL : partially or entirely visible
2270 * RETURN:
2271 * SUCCESS : TRUE
2272 * FAILURE : FALSE
2274 static BOOL LISTVIEW_EnsureVisible(HWND hwnd, INT nItem, BOOL bPartial)
2276 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
2277 LONG lStyle = GetWindowLongA(hwnd, GWL_STYLE);
2278 INT nLast;
2279 INT nFirst;
2280 INT nScrollPos;
2281 BOOL bResult = TRUE;
2283 switch (LVS_TYPEMASK & lStyle)
2285 case LVS_LIST:
2286 if (lStyle & WS_HSCROLL)
2288 nFirst = ListView_GetTopIndex(hwnd);
2290 /* calculate last fully visible item index */
2291 nLast = infoPtr->nCountPerColumn * infoPtr->nCountPerRow + nFirst - 1;
2293 if (nItem > nLast)
2295 /* calculate new scroll position based on item index */
2296 if (((nItem - nLast) % infoPtr->nCountPerColumn) == 0)
2298 nScrollPos = (nItem - nLast) / infoPtr->nCountPerColumn;
2300 else
2302 nScrollPos = (nItem - nLast) / infoPtr->nCountPerColumn + 1;
2305 bResult = ListView_Scroll(hwnd, nScrollPos, 0);
2307 else if (nItem < nFirst)
2309 /* calculate new scroll position based on item index */
2310 if (((nItem - nFirst) % infoPtr->nCountPerColumn) == 0)
2312 nScrollPos = (nItem - nFirst) / infoPtr->nCountPerColumn;
2314 else
2316 nScrollPos = (nItem - nFirst) / infoPtr->nCountPerColumn -1;
2319 bResult = ListView_Scroll(hwnd, nScrollPos, 0);
2322 break;
2324 case LVS_REPORT:
2325 if (lStyle & WS_VSCROLL)
2327 nFirst = ListView_GetTopIndex(hwnd);
2329 /* calculate last fully visible item index */
2330 nLast = infoPtr->nCountPerColumn + nFirst - 1;
2331 if (nItem > nLast)
2333 nScrollPos = nItem - nLast;
2334 bResult = ListView_Scroll(hwnd, 0, nScrollPos);
2336 else if (nItem < nFirst)
2338 nScrollPos = nItem - nFirst;
2339 bResult = ListView_Scroll(hwnd, 0, nScrollPos);
2342 break;
2344 case LVS_SMALLICON:
2345 /* TO DO */
2346 break;
2348 case LVS_ICON:
2349 /* TO DO */
2350 break;
2353 return bResult;
2355 /***
2356 * DESCRIPTION:
2357 * Searches for an item with specific characteristics.
2359 * PARAMETER(S):
2360 * [I] HWND : window handle
2361 * [I] INT : base item index
2362 * [I] LPLVFINDINFO : item information to look for
2364 * RETURN:
2365 * SUCCESS : index of item
2366 * FAILURE : -1
2368 static LRESULT LISTVIEW_FindItem(HWND hwnd, INT nStart,
2369 LPLVFINDINFO lpFindInfo)
2371 /* LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0); */
2372 /* LISTVIEW_ITEM *lpItem; */
2373 /* INT nItem; */
2374 /* INT nEnd = GETITEMCOUNT(infoPtr); */
2375 /* BOOL bWrap = FALSE; */
2376 /* if (nStart == -1) */
2377 /* nStart = 0; */
2378 /* else */
2379 /* nStart++ ; */
2380 /* if (lpFindInfo->flags & LVFI_PARAM) */
2381 /* { */
2382 /* for (nItem = nStart; nItem < nEnd; nItem++) */
2383 /* { */
2384 /* get item pointer */
2385 /* lpItem = (LISTVIEW_ITEM *)DPA_GetPtr(infoPtr->hdpaItems, nItem); */
2386 /* if (lpItem != NULL) */
2387 /* { */
2388 /* if (lpFindInfo->lParam == lpItem->lParam) */
2389 /* return nItem; */
2390 /* } */
2391 /* } */
2392 /* } */
2393 /* else */
2394 /* { */
2395 /* if (lpFindInfo->flags & LVFI_PARTIAL) */
2396 /* { */
2397 /* for (nItem = nStart; nItem < nEnd; nItem++) */
2398 /* { */
2399 /* get item pointer */
2400 /* lpItem = (LISTVIEW_ITEM *)DPA_GetPtr(infoPtr->hdpaItems, nItem); */
2401 /* if (lpItem) */
2402 /* { */
2403 /* if (strncmp(lpItem->pszText, lpFindInfo->psz, strlen(lpFindInfo->psz)) */
2404 /* == 0) */
2405 /* return nItem; */
2406 /* } */
2407 /* } */
2408 /* } */
2410 /* if (lpFindInfo->flags & LVFI_STRING) */
2411 /* { */
2412 /* for (nItem = nStart; nItem < nEnd; nItem++) */
2413 /* { */
2414 /* get item pointer */
2415 /* lpItem = (LISTVIEW_ITEM *)DPA_GetPtr(infoPtr->hdpaItems, nItem); */
2416 /* if (lpItem != NULL) */
2417 /* { */
2418 /* if (strcmp(lpItem->pszText, lpFindInfo->psz) == 0) */
2419 /* return nItem; */
2420 /* } */
2421 /* } */
2422 /* } */
2424 /* if ((lpFindInfo->flags & LVFI_WRAP) && nStart) */
2425 /* { */
2426 /* nEnd = nStart; */
2427 /* nStart = 0; */
2428 /* bWrap = TRUE; */
2429 /* } */
2430 /* else */
2431 /* bWrap = FALSE; */
2433 return -1;
2436 /***
2437 * DESCRIPTION:
2438 * Retrieves the background color of the listview control.
2440 * PARAMETER(S):
2441 * [I] HWND : window handle
2443 * RETURN:
2444 * COLORREF associated with the background.
2446 static LRESULT LISTVIEW_GetBkColor(HWND hwnd)
2448 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
2450 return infoPtr->clrBk;
2453 /***
2454 * DESCRIPTION:
2455 * Retrieves the background image of the listview control.
2457 * PARAMETER(S):
2458 * [I] HWND : window handle
2459 * [O] LPLVMKBIMAGE : background image attributes
2461 * RETURN:
2462 * SUCCESS : TRUE
2463 * FAILURE : FALSE`
2465 /* static LRESULT LISTVIEW_GetBkImage(HWND hwnd, LPLVBKIMAGE lpBkImage) */
2466 /* { */
2467 /* return FALSE; */
2468 /* } */
2470 /***
2471 * DESCRIPTION:
2472 * Retrieves the callback mask.
2474 * PARAMETER(S):
2475 * [I] HWND : window handle
2477 * RETURN:
2478 * Value of mask
2480 static UINT LISTVIEW_GetCallbackMask(HWND hwnd)
2482 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
2484 return infoPtr->uCallbackMask;
2487 /***
2488 * DESCRIPTION:
2489 * Retrieves column attributes.
2491 * PARAMETER(S):
2492 * [I] HWND : window handle
2493 * [I] INT : column index
2494 * [IO] LPLVCOLUMNA : column information
2496 * RETURN:
2497 * SUCCESS : TRUE
2498 * FAILURE : FALSE
2500 static LRESULT LISTVIEW_GetColumnA(HWND hwnd, INT nItem,
2501 LPLVCOLUMNA lpColumn)
2503 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
2504 HDITEMA hdi;
2505 BOOL bResult = FALSE;
2507 if (lpColumn != NULL)
2509 /* initialize memory */
2510 ZeroMemory(&hdi, sizeof(HDITEMA));
2512 if (lpColumn->mask & LVCF_FMT)
2514 hdi.mask |= HDI_FORMAT;
2517 if (lpColumn->mask & LVCF_WIDTH)
2519 hdi.mask |= HDI_WIDTH;
2522 if (lpColumn->mask & LVCF_TEXT)
2524 hdi.mask |= (HDI_TEXT | HDI_FORMAT);
2527 if (lpColumn->mask & LVCF_IMAGE)
2529 hdi.mask |= HDI_IMAGE;
2532 if (lpColumn->mask & LVCF_ORDER)
2534 hdi.mask |= HDI_ORDER;
2537 bResult = Header_GetItemA(infoPtr->hwndHeader, nItem, &hdi);
2538 if (bResult == TRUE)
2540 if (lpColumn->mask & LVCF_FMT)
2542 lpColumn->fmt = 0;
2544 if (hdi.fmt & HDF_LEFT)
2546 lpColumn->fmt |= LVCFMT_LEFT;
2548 else if (hdi.fmt & HDF_RIGHT)
2550 lpColumn->fmt |= LVCFMT_RIGHT;
2552 else if (hdi.fmt & HDF_CENTER)
2554 lpColumn->fmt |= LVCFMT_CENTER;
2557 if (hdi.fmt & HDF_IMAGE)
2559 lpColumn->fmt |= LVCFMT_COL_HAS_IMAGES;
2563 if (lpColumn->mask & LVCF_WIDTH)
2565 lpColumn->cx = hdi.cxy;
2568 if ((lpColumn->mask & LVCF_TEXT) && (lpColumn->pszText) && (hdi.pszText))
2570 lstrcpynA (lpColumn->pszText, hdi.pszText, lpColumn->cchTextMax);
2573 if (lpColumn->mask & LVCF_IMAGE)
2575 lpColumn->iImage = hdi.iImage;
2578 if (lpColumn->mask & LVCF_ORDER)
2580 lpColumn->iOrder = hdi.iOrder;
2585 return bResult;
2588 /* << LISTVIEW_GetColumnW >> */
2589 /* << LISTVIEW_GetColumnOrderArray >> */
2591 /***
2592 * DESCRIPTION:
2593 * Retrieves the column width.
2595 * PARAMETER(S):
2596 * [I] HWND : window handle
2597 * [I] int : column index
2599 * RETURN:
2600 * SUCCESS : column width
2601 * FAILURE : zero
2603 static LRESULT LISTVIEW_GetColumnWidth(HWND hwnd, INT nColumn)
2605 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
2606 LONG lStyle = GetWindowLongA(hwnd, GWL_STYLE);
2607 HDITEMA hdi;
2608 INT nColumnWidth = 0;
2610 if ((LVS_TYPEMASK & lStyle) == LVS_LIST)
2612 nColumnWidth = infoPtr->nColumnWidth;
2614 else if ((LVS_TYPEMASK & lStyle) == LVS_REPORT)
2616 /* get column width from header */
2617 ZeroMemory(&hdi, sizeof(HDITEMA));
2618 hdi.mask = HDI_WIDTH;
2619 if (Header_GetItemA(infoPtr->hwndHeader, nColumn, &hdi) == TRUE)
2621 nColumnWidth = hdi.cxy;
2625 return nColumnWidth;
2628 /***
2629 * DESCRIPTION:
2630 * In list or report display mode, retrieves the number of items that can fit
2631 * vertically in the visible area. In icon or small icon display mode,
2632 * retrieves the total number of visible items.
2634 * PARAMETER(S):
2635 * [I] HWND : window handle
2637 * RETURN:
2638 * Number of fully visible items.
2640 static LRESULT LISTVIEW_GetCountPerPage(HWND hwnd)
2642 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
2643 LONG lStyle = GetWindowLongA(hwnd, GWL_STYLE);
2644 INT nItemCount = 0;
2646 switch (LVS_TYPEMASK & lStyle)
2648 case LVS_LIST:
2649 if (infoPtr->rcList.right / infoPtr->nColumnWidth)
2651 nItemCount = infoPtr->nCountPerRow * infoPtr->nCountPerColumn;
2653 break;
2655 case LVS_REPORT:
2656 nItemCount = infoPtr->nCountPerColumn;
2657 break;
2659 default:
2660 nItemCount = GETITEMCOUNT(infoPtr);
2663 return nItemCount;
2666 /* << LISTVIEW_GetEditControl >> */
2667 /* << LISTVIEW_GetExtendedListViewStyle >> */
2669 /***
2670 * DESCRIPTION:
2671 * Retrieves a header handle.
2673 * PARAMETER(S):
2674 * [I] HWND : window handle
2676 * RETURN:
2677 * Header handle.
2679 static LRESULT LISTVIEW_GetHeader(HWND hwnd)
2681 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
2683 return infoPtr->hwndHeader;
2686 /* << LISTVIEW_GetHotCursor >> */
2687 /* << LISTVIEW_GetHotItem >> */
2688 /* << LISTVIEW_GetHoverTime >> */
2690 /***
2691 * DESCRIPTION:
2692 * Retrieves an image list handle.
2694 * PARAMETER(S):
2695 * [I] HWND : window handle
2696 * [I] INT : image list identifier
2698 * RETURN:
2699 * SUCCESS : image list handle
2700 * FAILURE : NULL
2702 static LRESULT LISTVIEW_GetImageList(HWND hwnd, INT nImageList)
2704 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
2705 HIMAGELIST himl = NULL;
2707 switch (nImageList)
2709 case LVSIL_NORMAL:
2710 himl = infoPtr->himlNormal;
2711 break;
2712 case LVSIL_SMALL:
2713 himl = infoPtr->himlSmall;
2714 break;
2715 case LVSIL_STATE:
2716 himl = infoPtr->himlState;
2717 break;
2720 return (LRESULT)himl;
2723 /* << LISTVIEW_GetISearchString >> */
2725 /***
2726 * DESCRIPTION:
2727 * Retrieves item attributes.
2729 * PARAMETER(S):
2730 * [I] HWND : window handle
2731 * [IO] LPLVITEMA : item info
2733 * RETURN:
2734 * SUCCESS : TRUE
2735 * FAILURE : FALSE
2737 static LRESULT LISTVIEW_GetItemA(HWND hwnd, LPLVITEMA lpLVItem)
2739 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
2740 LISTVIEW_ITEM *lpItem;
2741 LISTVIEW_SUBITEM *lpSubItem;
2742 HDPA hdpaSubItems;
2743 BOOL bResult = FALSE;
2745 if (lpLVItem != NULL)
2747 if ((lpLVItem->iItem >= 0) && (lpLVItem->iItem < GETITEMCOUNT(infoPtr)))
2749 hdpaSubItems = (HDPA)DPA_GetPtr(infoPtr->hdpaItems, lpLVItem->iItem);
2750 if (hdpaSubItems != NULL)
2752 if (lpLVItem->iSubItem == 0)
2754 lpItem = (LISTVIEW_ITEM *)DPA_GetPtr(hdpaSubItems, 0);
2755 if (lpItem != NULL)
2757 bResult = TRUE;
2759 /* retrieve valid data */
2760 if (lpLVItem->mask & LVIF_STATE)
2762 lpLVItem->state = lpItem->state & lpLVItem->stateMask;
2765 if (lpLVItem->mask & LVIF_TEXT)
2767 if (lpItem->pszText == LPSTR_TEXTCALLBACKA)
2769 lpLVItem->pszText = LPSTR_TEXTCALLBACKA;
2771 else
2773 bResult = Str_GetPtrA(lpItem->pszText, lpLVItem->pszText,
2774 lpLVItem->cchTextMax);
2778 if (lpLVItem->mask & LVIF_IMAGE)
2780 lpLVItem->iImage = lpItem->iImage;
2783 if (lpLVItem->mask & LVIF_PARAM)
2785 lpLVItem->lParam = lpItem->lParam;
2788 if (lpLVItem->mask & LVIF_INDENT)
2790 lpLVItem->iIndent = lpItem->iIndent;
2794 else
2796 lpSubItem = (LISTVIEW_SUBITEM *)DPA_GetPtr(hdpaSubItems,
2797 lpLVItem->iSubItem);
2798 if (lpSubItem != NULL)
2800 bResult = TRUE;
2802 if (lpLVItem->mask & LVIF_TEXT)
2804 if (lpSubItem->pszText == LPSTR_TEXTCALLBACKA)
2806 lpLVItem->pszText = LPSTR_TEXTCALLBACKA;
2808 else
2810 bResult = Str_GetPtrA(lpSubItem->pszText, lpLVItem->pszText,
2811 lpLVItem->cchTextMax);
2815 if (lpLVItem->mask & LVIF_IMAGE)
2817 lpLVItem->iImage = lpSubItem->iImage;
2825 return bResult;
2828 /* << LISTVIEW_GetItemW >> */
2829 /* << LISTVIEW_GetHotCursor >> */
2830 /* << LISTVIEW_GetHotItem >> */
2831 /* << LISTVIEW_GetHoverTime >> */
2833 /***
2834 * DESCRIPTION:
2835 * Retrieves the number of items in the listview control.
2837 * PARAMETER(S):
2838 * [I] HWND : window handle
2840 * RETURN:
2841 * Number of items.
2843 static LRESULT LISTVIEW_GetItemCount(HWND hwnd)
2845 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
2847 return GETITEMCOUNT(infoPtr);
2850 /***
2851 * DESCRIPTION:
2852 * Retrieves the position (upper-left) of the listview control item.
2854 * PARAMETER(S):
2855 * [I] HWND : window handle
2856 * [I] INT : item index
2857 * [O] LPPOINT : coordinate information
2859 * RETURN:
2860 * SUCCESS : TRUE
2861 * FAILURE : FALSE
2863 static LRESULT LISTVIEW_GetItemPosition(HWND hwnd, INT nItem,
2864 LPPOINT lppt)
2866 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
2867 LONG lStyle = GetWindowLongA(hwnd, GWL_STYLE);
2868 INT nColumn;
2869 INT nRow;
2870 BOOL bResult = FALSE;
2871 INT nFirst;
2872 INT nLast;
2874 if ((nItem >= 0) && (nItem < GETITEMCOUNT(infoPtr)) && (lppt != NULL))
2876 switch (LVS_TYPEMASK & lStyle)
2878 case LVS_LIST:
2879 nFirst = ListView_GetTopIndex(hwnd);
2880 nLast = infoPtr->nCountPerColumn * infoPtr->nCountPerRow + nFirst - 1;
2882 if ((nItem >= nFirst) || (nItem <= nLast))
2884 nItem -= nFirst;
2886 /* get column */
2887 nColumn = nItem / infoPtr->nCountPerColumn;
2889 /* get row */
2890 nRow = nItem % infoPtr->nCountPerColumn;
2892 /* X coordinate of the column */
2893 lppt->x = nColumn * infoPtr->nColumnWidth + infoPtr->rcList.left;
2895 /* Y coordinate of the item */
2896 lppt->y = nRow * infoPtr->nItemHeight + infoPtr->rcList.top;
2898 bResult = TRUE;
2900 break;
2902 case LVS_REPORT:
2903 nFirst = ListView_GetTopIndex(hwnd);
2904 nLast = infoPtr->nCountPerColumn * infoPtr->nCountPerRow + nFirst - 1;
2906 /* get column */
2907 nColumn = nItem / infoPtr->nCountPerColumn;
2909 /* get row */
2910 nRow = nItem % infoPtr->nCountPerColumn;
2912 if ((nItem >= nFirst) || (nItem <= nLast))
2914 nItem -= nFirst;
2916 /* get column */
2917 nColumn = nItem / infoPtr->nCountPerColumn;
2919 /* get row */
2920 nRow = nItem % infoPtr->nCountPerColumn;
2922 /* X coordinate of the column */
2923 lppt->x = infoPtr->rcList.left;
2925 /* Y coordinate of the item */
2926 lppt->y = nRow * infoPtr->nItemHeight + infoPtr->rcList.top;
2928 bResult = TRUE;
2931 default:
2932 /* TO DO */
2936 return bResult;
2939 /***
2940 * DESCRIPTION:
2941 * Retrieves the bounding rectangle for a listview control item.
2943 * PARAMETER(S):
2944 * [I] HWND : window handle
2945 * [I] INT : item index
2946 * [IO] LPRECT : bounding rectangle coordinates
2948 * RETURN:
2949 * SUCCESS : TRUE
2950 * FAILURE : FALSE
2952 static LRESULT LISTVIEW_GetItemRect(HWND hwnd, INT nItem, LPRECT lprc)
2954 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
2955 LONG lStyle = GetWindowLongA(hwnd, GWL_STYLE);
2956 LISTVIEW_ITEM *lpItem;
2957 HDPA hdpaSubItems;
2958 INT nLabelWidth = 0;
2959 INT nStateWidth = 0;
2960 INT nIconWidth = 0;
2961 BOOL bResult = FALSE;
2962 CHAR szDispText[DISP_TEXT_SIZE];
2963 LPSTR pszDispText;
2964 POINT pt;
2966 /*init pointer */
2967 pszDispText = szDispText;
2969 if ((nItem >= 0) && (nItem < GETITEMCOUNT(infoPtr)) && (lprc != NULL))
2971 hdpaSubItems = (HDPA)DPA_GetPtr(infoPtr->hdpaItems, nItem);
2972 if (hdpaSubItems != NULL)
2974 lpItem = (LISTVIEW_ITEM *)DPA_GetPtr(hdpaSubItems, 0);
2975 if (lpItem != NULL)
2977 if ((LVS_TYPEMASK & lStyle) == LVS_ICON)
2981 else
2983 if (ListView_GetItemPosition(hwnd, nItem, &pt) == TRUE)
2985 /* get width of label in pixels */
2986 LISTVIEW_GetItemDispInfo(hwnd, nItem, lpItem, NULL, NULL,
2987 &pszDispText, DISP_TEXT_SIZE);
2988 nLabelWidth = ListView_GetStringWidthA(hwnd, pszDispText);
2991 if (infoPtr->himlState != NULL)
2993 nStateWidth = infoPtr->iconSize.cx;
2996 if (infoPtr->himlSmall == NULL)
2998 nIconWidth = infoPtr->iconSize.cx;
3001 switch(lprc->left)
3003 case LVIR_BOUNDS:
3004 lprc->left = pt.x;
3005 lprc->top = pt.y;
3006 lprc->right = lprc->left + nStateWidth + nIconWidth + nLabelWidth;
3007 lprc->bottom = lprc->top + infoPtr->nItemHeight;
3008 bResult = TRUE;
3009 break;
3010 case LVIR_ICON:
3011 lprc->left = pt.x + nStateWidth;
3012 lprc->top = pt.y;
3013 lprc->right = lprc->left + nIconWidth;
3014 lprc->bottom = lprc->top + infoPtr->nItemHeight;
3015 bResult = TRUE;
3016 break;
3017 case LVIR_LABEL:
3018 lprc->left = pt.x + nIconWidth + nStateWidth;
3019 lprc->top = pt.y;
3020 lprc->right = lprc->left + nLabelWidth;
3021 lprc->bottom = infoPtr->nItemHeight;
3022 bResult = TRUE;
3023 break;
3024 case LVIR_SELECTBOUNDS:
3025 lprc->left = pt.x + nStateWidth;
3026 lprc->top = pt.y;
3027 lprc->right = lprc->left + nIconWidth + nLabelWidth;
3028 lprc->bottom = lprc->top + infoPtr->nItemHeight;
3029 bResult = TRUE;
3036 return bResult;
3039 /***
3040 * DESCRIPTION:
3041 * Retrieves the spacing between listview control items.
3043 * PARAMETER(S):
3044 * [I] HWND : window handle
3045 * [I] BOOL : flag for small or large icon
3047 * RETURN:
3048 * Horizontal + vertical spacing
3050 static LRESULT LISTVIEW_GetItemSpacing(HWND hwnd, BOOL bSmall)
3052 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
3053 LONG lResult;
3055 if (bSmall == TRUE)
3057 lResult = MAKELONG(infoPtr->largeIconSpacing.cx,
3058 infoPtr->largeIconSpacing.cy);
3060 else
3062 lResult = MAKELONG(infoPtr->smallIconSpacing.cx,
3063 infoPtr->smallIconSpacing.cy);
3066 return lResult;
3069 /***
3070 * DESCRIPTION:
3071 * Retrieves the state of a listview control item.
3073 * PARAMETER(S):
3074 * [I] HWND : window handle
3075 * [I] INT : item index
3076 * [I] UINT : state mask
3078 * RETURN:
3079 * State specified by the mask.
3081 static LRESULT LISTVIEW_GetItemState(HWND hwnd, INT nItem, UINT uMask)
3083 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
3084 LVITEMA lvItem;
3085 UINT uState = 0;
3087 if ((nItem >= 0) && (nItem < GETITEMCOUNT(infoPtr)))
3089 ZeroMemory(&lvItem, sizeof(LVITEMA));
3090 lvItem.iItem = nItem;
3091 lvItem.stateMask = uMask;
3092 lvItem.mask = LVIF_STATE;
3093 if (ListView_GetItemA(hwnd, &lvItem) == TRUE)
3095 uState = lvItem.state;
3099 return uState;
3102 /***
3103 * DESCRIPTION:
3104 * Retrieves the text of a listview control item or subitem.
3106 * PARAMETER(S):
3107 * [I] HWND : window handle
3108 * [I] INT : item index
3109 * [IO] LPLVITEMA : item information
3111 * RETURN:
3112 * None
3114 static LRESULT LISTVIEW_GetItemTextA(HWND hwnd, INT nItem,
3115 LPLVITEMA lpLVItem)
3117 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
3118 LISTVIEW_ITEM *lpItem;
3119 LISTVIEW_SUBITEM *lpSubItem;
3120 HDPA hdpaSubItems;
3121 INT nLength = 0;
3123 if (lpLVItem != NULL)
3125 if ((nItem >= 0) && (nItem < GETITEMCOUNT(infoPtr)))
3127 hdpaSubItems = (HDPA)DPA_GetPtr(infoPtr->hdpaItems, lpLVItem->iItem);
3128 if (hdpaSubItems != NULL)
3130 if (lpLVItem->iSubItem == 0)
3132 lpItem = (LISTVIEW_ITEM *)DPA_GetPtr(hdpaSubItems, 0);
3133 if (lpItem != NULL)
3135 if (lpLVItem->mask & LVIF_TEXT)
3137 if (lpItem->pszText == LPSTR_TEXTCALLBACKA)
3139 lpLVItem->pszText = LPSTR_TEXTCALLBACKA;
3141 else
3143 nLength = Str_GetPtrA(lpItem->pszText, lpLVItem->pszText,
3144 lpLVItem->cchTextMax);
3149 else
3151 lpSubItem = (LISTVIEW_SUBITEM *)DPA_GetPtr(hdpaSubItems,
3152 lpLVItem->iSubItem);
3153 if (lpSubItem != NULL)
3155 if (lpLVItem->mask & LVIF_TEXT)
3157 if (lpSubItem->pszText == LPSTR_TEXTCALLBACKA)
3159 lpLVItem->pszText = LPSTR_TEXTCALLBACKA;
3161 else
3163 nLength = Str_GetPtrA(lpSubItem->pszText, lpLVItem->pszText,
3164 lpLVItem->cchTextMax);
3173 return nLength;
3176 /***
3177 * DESCRIPTION:
3178 * Searches for an item based on properties + relationships.
3180 * PARAMETER(S):
3181 * [I] HWND : window handle
3182 * [I] INT : item index
3183 * [I] UINT : relationship flag
3185 * RETURN:
3186 * SUCCESS : item index
3187 * FAILURE : -1
3189 static LRESULT LISTVIEW_GetNextItem(HWND hwnd, INT nItem, UINT uFlags)
3191 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
3192 INT nResult = -1;
3194 if (nItem == -1)
3196 /* start at begin */
3197 nItem = 0;
3199 else
3201 /* exclude specified item */
3202 nItem++;
3205 if ((nItem >= 0) && (nItem < GETITEMCOUNT(infoPtr)))
3207 /* TO DO */
3210 return nResult;
3213 /* << LISTVIEW_GetNumberOfWorkAreas >> */
3215 /***
3216 * DESCRIPTION:
3217 * Retrieves the current origin when in icon or small icon display mode.
3219 * PARAMETER(S):
3220 * [I] HWND : window handle
3221 * [O] LPPOINT : coordinate information
3223 * RETURN:
3224 * SUCCESS : TRUE
3225 * FAILURE : FALSE
3227 static LRESULT LISTVIEW_GetOrigin(HWND hwnd, LPPOINT lpOrigin)
3229 LONG lStyle = GetWindowLongA(hwnd, GWL_ID);
3230 BOOL bResult = FALSE;
3232 if ((lStyle & LVS_TYPEMASK) == LVS_SMALLICON)
3234 /* TO DO */
3235 lpOrigin->x = 0;
3236 lpOrigin->y = 0;
3238 else if ((lStyle & LVS_TYPEMASK) == LVS_ICON)
3240 /* TO DO */
3241 lpOrigin->x = 0;
3242 lpOrigin->y = 0;
3245 return bResult;
3248 /***
3249 * DESCRIPTION:
3250 * Retrieves the number of items that are marked as selected.
3252 * PARAMETER(S):
3253 * [I] HWND : window handle
3255 * RETURN:
3256 * Number of items selected.
3258 static LRESULT LISTVIEW_GetSelectedCount(HWND hwnd)
3260 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
3261 INT nSelectedCount = 0;
3262 INT i;
3264 for (i = 0; i < GETITEMCOUNT(infoPtr); i++)
3266 if (ListView_GetItemState(hwnd, i, LVIS_SELECTED) & LVIS_SELECTED)
3268 nSelectedCount++;
3272 return nSelectedCount;
3275 /***
3276 * DESCRIPTION:
3277 * Retrieves item index that marks the start of a multiple selection.
3279 * PARAMETER(S):
3280 * [I] HWND : window handle
3282 * RETURN:
3283 * Index number or -1 if there is no selection mark.
3285 static LRESULT LISTVIEW_GetSelectionMark(HWND hwnd)
3287 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
3289 return infoPtr->nSelectionMark;
3292 /***
3293 * DESCRIPTION:
3294 * Retrieves the width of a string.
3296 * PARAMETER(S):
3297 * [I] HWND : window handle
3299 * RETURN:
3300 * SUCCESS : string width (in pixels)
3301 * FAILURE : zero
3303 static LRESULT LISTVIEW_GetStringWidthA(HWND hwnd, LPCSTR lpsz)
3305 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
3306 HFONT hFont, hOldFont;
3307 HDC hdc;
3308 SIZE textSize;
3310 /* initialize */
3311 ZeroMemory(&textSize, sizeof(SIZE));
3312 if (lpsz != NULL)
3314 hFont = infoPtr->hFont ? infoPtr->hFont : infoPtr->hDefaultFont;
3315 hdc = GetDC(hwnd);
3316 hOldFont = SelectObject(hdc, hFont);
3317 GetTextExtentPointA(hdc, lpsz, lstrlenA(lpsz), &textSize);
3318 SelectObject(hdc, hOldFont);
3319 ReleaseDC(hwnd, hdc);
3322 return textSize.cx;
3325 /***
3326 * DESCRIPTION:
3327 * Retrieves the text backgound color.
3329 * PARAMETER(S):
3330 * [I] HWND : window handle
3332 * RETURN:
3333 * COLORREF associated with the the background.
3335 static LRESULT LISTVIEW_GetTextBkColor(HWND hwnd)
3337 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO*)GetWindowLongA(hwnd, 0);
3339 return infoPtr->clrTextBk;
3342 /***
3343 * DESCRIPTION:
3344 * Retrieves the text color.
3346 * PARAMETER(S):
3347 * [I] HWND : window handle
3349 * RETURN:
3350 * COLORREF associated with the text.
3352 static LRESULT LISTVIEW_GetTextColor(HWND hwnd)
3354 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO*)GetWindowLongA(hwnd, 0);
3356 return infoPtr->clrText;
3359 /***
3360 * DESCRIPTION:
3361 * Retrieves the bounding rectangle of all the items.
3363 * PARAMETER(S):
3364 * [I] HWND : window handle
3365 * [O] LPRECT : bounding rectangle
3367 * RETURN:
3368 * SUCCESS : TRUE
3369 * FAILURE : FALSE
3371 static LRESULT LISTVIEW_GetViewRect(HWND hwnd, LPRECT lprc)
3373 /* LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0); */
3374 LONG lStyle = GetWindowLongA(hwnd, GWL_STYLE);
3375 BOOL bResult = FALSE;
3377 if (lprc != NULL)
3379 if (((lStyle & LVS_TYPEMASK) == LVS_ICON) ||
3380 ((lStyle & LVS_TYPEMASK) == LVS_SMALLICON))
3382 /* TO DO */
3386 return bResult;
3389 /***
3390 * DESCRIPTION:
3391 * Determines which section of the item was selected (if any).
3393 * PARAMETER(S):
3394 * [I] HWND : window handle
3395 * [I] INT : item index
3396 * [IO] LPLVHITTESTINFO : hit test information
3398 * RETURN:
3399 * SUCCESS : item index
3400 * FAILURE : -1
3402 static INT LISTVIEW_HitTestItem(HWND hwnd, INT nItem,
3403 LPLVHITTESTINFO lpHitTestInfo)
3405 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
3406 LONG lStyle = GetWindowLongA(hwnd, GWL_STYLE);
3407 HDPA hdpaSubItems;
3408 LISTVIEW_ITEM *lpItem;
3409 INT nOffset;
3410 INT nLabelWidth;
3411 INT nPosX = 0;
3412 CHAR szDispText[DISP_TEXT_SIZE];
3413 LPSTR pszDispText;
3415 /*init pointer */
3416 pszDispText = szDispText;
3418 if ((LVS_TYPEMASK & lStyle) == LVS_LIST)
3420 /* calculate offset from start of item (in pixels) */
3421 nOffset = lpHitTestInfo->pt.x % infoPtr->nColumnWidth;
3423 else
3425 nOffset = lpHitTestInfo->pt.x;
3428 /* verify existance of item */
3429 if (nItem < GETITEMCOUNT(infoPtr))
3431 /* get item */
3432 hdpaSubItems = (HDPA)DPA_GetPtr(infoPtr->hdpaItems, nItem);
3433 if (hdpaSubItems != NULL)
3435 lpItem = (LISTVIEW_ITEM *)DPA_GetPtr(hdpaSubItems, 0);
3436 if (lpItem != NULL)
3438 if (infoPtr->himlState != NULL)
3440 nPosX += infoPtr->iconSize.cx;
3441 if (nOffset <= nPosX)
3443 lpHitTestInfo->flags = LVHT_ONITEMSTATEICON | LVHT_ONITEM;
3444 lpHitTestInfo->iItem = nItem;
3445 lpHitTestInfo->iSubItem = 0;
3446 return nItem;
3450 if (infoPtr->himlSmall != NULL)
3452 nPosX += infoPtr->iconSize.cx;
3453 if (nOffset <= nPosX)
3455 lpHitTestInfo->flags = LVHT_ONITEMICON | LVHT_ONITEM;
3456 lpHitTestInfo->iItem = nItem;
3457 lpHitTestInfo->iSubItem = 0;
3458 return nItem;
3462 /* get width of label in pixels */
3463 LISTVIEW_GetItemDispInfo(hwnd, nItem, lpItem, NULL, NULL,
3464 &pszDispText, DISP_TEXT_SIZE);
3465 nLabelWidth = ListView_GetStringWidthA(hwnd, pszDispText);
3466 nLabelWidth += nPosX;
3468 if (nOffset <= nLabelWidth)
3470 lpHitTestInfo->flags = LVHT_ONITEMLABEL | LVHT_ONITEM;
3471 lpHitTestInfo->iItem = nItem;
3472 lpHitTestInfo->iSubItem = 0;
3473 return nItem;
3479 /* hit is not on item */
3480 lpHitTestInfo->flags = LVHT_NOWHERE;
3482 return -1;
3485 /***
3486 * DESCRIPTION:
3487 * Determines wich listview item is located at the specified position.
3489 * PARAMETER(S):
3490 * [I] HWND : window handle
3491 * [IO} LPLVHITTESTINFO : hit test information
3493 * RETURN:
3494 * SUCCESS : item index
3495 * FAILURE : -1
3497 static LRESULT LISTVIEW_HitTest(HWND hwnd, LPLVHITTESTINFO lpHitTestInfo)
3499 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
3500 LONG lStyle = GetWindowLongA(hwnd, GWL_STYLE);
3501 INT nColumn;
3502 INT nRow;
3503 INT nTopIndex;
3504 INT nItem = -1;
3506 lpHitTestInfo->flags = 0;
3507 if (infoPtr->rcList.left > lpHitTestInfo->pt.x)
3509 lpHitTestInfo->flags = LVHT_TOLEFT;
3511 else if (infoPtr->rcList.right < lpHitTestInfo->pt.x)
3513 lpHitTestInfo->flags = LVHT_TORIGHT;
3516 if (infoPtr->rcList.top > lpHitTestInfo->pt.y)
3518 lpHitTestInfo->flags |= LVHT_ABOVE;
3520 else if (infoPtr->rcList.bottom < lpHitTestInfo->pt.y)
3522 lpHitTestInfo->flags |= LVHT_BELOW;
3525 if (lpHitTestInfo->flags == 0)
3527 switch (LVS_TYPEMASK & lStyle)
3529 case LVS_LIST:
3530 /* get current column */
3531 nColumn = lpHitTestInfo->pt.x / infoPtr->nColumnWidth;
3533 /* get current row */
3534 nRow = lpHitTestInfo->pt.y / infoPtr->nItemHeight;
3536 /* get the index of the first visible item */
3537 nTopIndex = ListView_GetTopIndex(hwnd);
3539 nItem = nColumn * infoPtr->nCountPerColumn + nTopIndex + nRow;
3540 nItem = LISTVIEW_HitTestItem(hwnd, nItem, lpHitTestInfo);
3541 break;
3543 case LVS_REPORT:
3544 /* get current row */
3545 nRow = ((lpHitTestInfo->pt.y - infoPtr->rcList.top) /
3546 infoPtr->nItemHeight);
3548 /* get the index of the first visible item */
3549 nTopIndex = ListView_GetTopIndex(hwnd);
3551 nItem = nTopIndex + nRow;
3552 nItem = LISTVIEW_HitTestItem(hwnd, nItem, lpHitTestInfo);
3553 break;
3555 default:
3556 /* nItem = LISTVIEW_HitTestItem(hwnd, nItem, lpHitTestInfo); */
3560 return nItem;
3563 /***
3564 * DESCRIPTION:
3565 * Inserts a new column.
3567 * PARAMETER(S):
3568 * [I] HWND : window handle
3569 * [I] INT : column index
3570 * [I] LPLVCOLUMNA : column information
3572 * RETURN:
3573 * SUCCESS : new column index
3574 * FAILURE : -1
3576 static LRESULT LISTVIEW_InsertColumnA(HWND hwnd, INT nColumn,
3577 LPLVCOLUMNA lpColumn)
3579 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
3580 HDITEMA hdi;
3581 INT nNewColumn = -1;
3583 if (lpColumn != NULL)
3585 /* initialize memory */
3586 ZeroMemory(&hdi, sizeof(HDITEMA));
3588 if (lpColumn->mask & LVCF_FMT)
3590 /* format member is valid */
3591 hdi.mask |= HDI_FORMAT;
3593 /* set text alignment (leftmost column must be left-aligned) */
3594 if (nColumn == 0)
3596 hdi.fmt |= HDF_LEFT;
3598 else
3600 if (lpColumn->fmt & LVCFMT_LEFT)
3602 hdi.fmt |= HDF_LEFT;
3604 else if (lpColumn->fmt & LVCFMT_RIGHT)
3606 hdi.fmt |= HDF_RIGHT;
3608 else if (lpColumn->fmt & LVCFMT_CENTER)
3610 hdi.fmt |= HDF_CENTER;
3614 if (lpColumn->fmt & LVCFMT_BITMAP_ON_RIGHT)
3616 hdi.fmt |= HDF_BITMAP_ON_RIGHT;
3617 /* ??? */
3620 if (lpColumn->fmt & LVCFMT_COL_HAS_IMAGES)
3622 /* ??? */
3625 if (lpColumn->fmt & LVCFMT_IMAGE)
3627 hdi.fmt |= HDF_IMAGE;
3628 hdi.iImage = I_IMAGECALLBACK;
3632 if (lpColumn->mask & LVCF_WIDTH)
3634 hdi.mask |= HDI_WIDTH;
3635 hdi.cxy = lpColumn->cx;
3638 if (lpColumn->mask & LVCF_TEXT)
3640 hdi.mask |= HDI_TEXT | HDI_FORMAT;
3641 hdi.pszText = lpColumn->pszText;
3642 hdi.cchTextMax = lstrlenA(lpColumn->pszText);
3643 hdi.fmt |= HDF_STRING;
3646 if (lpColumn->mask & LVCF_IMAGE)
3648 hdi.mask |= HDI_IMAGE;
3649 hdi.iImage = lpColumn->iImage;
3652 if (lpColumn->mask & LVCF_ORDER)
3654 hdi.mask |= HDI_ORDER;
3655 hdi.iOrder = lpColumn->iOrder;
3658 /* insert item in header control */
3659 nNewColumn = SendMessageA(infoPtr->hwndHeader, HDM_INSERTITEMA,
3660 (WPARAM)nColumn, (LPARAM)&hdi);
3662 LISTVIEW_SetScroll(hwnd);
3663 InvalidateRect(hwnd, NULL, FALSE);
3666 return nNewColumn;
3669 /* << LISTVIEW_InsertColumnW >> */
3671 /***
3672 * DESCRIPTION:
3673 * Inserts a new item in the listview control.
3675 * PARAMETER(S):
3676 * [I] HWND : window handle
3677 * [I] LPLVITEMA : item information
3679 * RETURN:
3680 * SUCCESS : new item index
3681 * FAILURE : -1
3683 static LRESULT LISTVIEW_InsertItemA(HWND hwnd, LPLVITEMA lpLVItem)
3685 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
3686 LONG lCtrlId = GetWindowLongA(hwnd, GWL_ID);
3687 NMLISTVIEW nmlv;
3688 INT nItem = -1;
3689 HDPA hdpaSubItems;
3690 LISTVIEW_ITEM *lpItem = NULL;
3692 if (lpLVItem != NULL)
3694 /* make sure it's not a subitem; cannot insert a subitem */
3695 if (lpLVItem->iSubItem == 0)
3697 lpItem = (LISTVIEW_ITEM *)COMCTL32_Alloc(sizeof(LISTVIEW_ITEM));
3698 if (lpItem != NULL)
3700 ZeroMemory(lpItem, sizeof(LISTVIEW_ITEM));
3701 if (LISTVIEW_InitItem(hwnd, lpItem, lpLVItem) == TRUE)
3703 /* insert item in listview control data structure */
3704 hdpaSubItems = DPA_Create(8);
3705 if (hdpaSubItems != NULL)
3707 nItem = DPA_InsertPtr(hdpaSubItems, 0, lpItem);
3708 if (nItem != -1)
3710 nItem = DPA_InsertPtr(infoPtr->hdpaItems, lpLVItem->iItem,
3711 hdpaSubItems);
3712 if (nItem != -1)
3714 /* manage item focus */
3715 if (lpLVItem->mask & LVIF_STATE)
3717 if (lpLVItem->stateMask & LVIS_FOCUSED)
3719 LISTVIEW_SetItemFocus(hwnd, nItem);
3723 /* send LVN_INSERTITEM notification */
3724 ZeroMemory(&nmlv, sizeof(NMLISTVIEW));
3725 nmlv.hdr.hwndFrom = hwnd;
3726 nmlv.hdr.idFrom = lCtrlId;
3727 nmlv.hdr.code = LVN_INSERTITEM;
3728 nmlv.iItem = nItem;
3729 nmlv.lParam = lpItem->lParam;;
3730 ListView_LVNotify(GetParent(hwnd), lCtrlId, &nmlv);
3732 /* set scrolling parameters */
3733 LISTVIEW_SetScroll(hwnd);
3735 /* refresh client area */
3736 InvalidateRect(hwnd, NULL, FALSE);
3745 /* free memory if unsuccessful */
3746 if ((nItem == -1) && (lpItem != NULL))
3748 COMCTL32_Free(lpItem);
3751 return nItem;
3754 /* << LISTVIEW_InsertItemW >> */
3756 /***
3757 * DESCRIPTION:
3758 * Redraws a range of items.
3760 * PARAMETER(S):
3761 * [I] HWND : window handle
3762 * [I] INT : first item
3763 * [I] INT : last item
3765 * RETURN:
3766 * SUCCESS : TRUE
3767 * FAILURE : FALSE
3769 static LRESULT LISTVIEW_RedrawItems(HWND hwnd, INT nFirst, INT nLast)
3771 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
3772 BOOL bResult = FALSE;
3773 RECT rc;
3775 if (nFirst <= nLast)
3777 if ((nFirst >= 0) && (nFirst < GETITEMCOUNT(infoPtr)))
3779 if ((nLast >= 0) && (nLast < GETITEMCOUNT(infoPtr)))
3781 /* bResult = */
3782 InvalidateRect(hwnd, &rc, FALSE);
3787 return bResult;
3790 /***
3791 * DESCRIPTION:
3792 * Scrolls the content of a listview.
3794 * PARAMETER(S):
3795 * [I] HWND : window handle
3796 * [I] INT : amount of horizontal scrolling
3797 * [I] INT : amount of vertical scrolling
3799 * RETURN:
3800 * SUCCESS : TRUE
3801 * FAILURE : FALSE
3803 static LRESULT LISTVIEW_Scroll(HWND hwnd, INT nHScroll, INT nVScroll)
3805 LONG lStyle = GetWindowLongA(hwnd, GWL_STYLE);
3806 INT nScrollPos = 0;
3807 BOOL bResult = FALSE;
3808 INT nMinRange;
3809 INT nMaxRange;
3811 if (lStyle & WS_HSCROLL)
3813 nScrollPos = GetScrollPos(hwnd, SB_HORZ);
3814 GetScrollRange(hwnd, SB_HORZ, &nMinRange, &nMaxRange);
3815 nScrollPos += nHScroll;
3817 if ((LVS_TYPEMASK & lStyle) == LVS_LIST)
3819 nScrollPos = GetScrollPos(hwnd, SB_HORZ);
3820 GetScrollRange(hwnd, SB_HORZ, &nMinRange, &nMaxRange);
3821 nScrollPos += nHScroll;
3822 if ((nMinRange <= nScrollPos) && (nScrollPos <= nMaxRange))
3824 bResult = TRUE;
3825 SetScrollPos(hwnd, SB_HORZ, nScrollPos, TRUE);
3828 else
3830 /* TO DO */
3834 if (lStyle & WS_VSCROLL)
3836 if ((LVS_TYPEMASK & lStyle) == LVS_REPORT)
3838 nScrollPos = GetScrollPos(hwnd, SB_VERT);
3839 GetScrollRange(hwnd, SB_VERT, &nMinRange, &nMaxRange);
3840 nScrollPos += nVScroll;
3841 if ((nMinRange <= nScrollPos) && (nScrollPos <= nMaxRange))
3843 bResult = TRUE;
3844 SetScrollPos(hwnd, SB_VERT, nScrollPos, TRUE);
3847 else
3849 /* TO DO */
3853 if (bResult == TRUE)
3855 /* refresh client area */
3856 InvalidateRect(hwnd, NULL, TRUE);
3859 return bResult;
3862 /***
3863 * DESCRIPTION:
3864 * Sets the background color.
3866 * PARAMETER(S):
3867 * [I] HWND : window handle
3868 * [I] COLORREF : background color
3870 * RETURN:
3871 * SUCCESS : TRUE
3872 * FAILURE : FALSE
3874 static LRESULT LISTVIEW_SetBkColor(HWND hwnd, COLORREF clrBk)
3876 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
3878 infoPtr->clrBk = clrBk;
3879 InvalidateRect(hwnd, NULL, TRUE);
3881 return TRUE;
3884 /***
3885 * DESCRIPTION:
3886 * Sets the callback mask. This mask will be used when the parent
3887 * window stores the state information (some or all).
3889 * PARAMETER(S):
3890 * [I] HWND : window handle
3891 * [I] UINT : state mask
3893 * RETURN:
3894 * SUCCESS : TRUE
3895 * FAILURE : FALSE
3897 static BOOL LISTVIEW_SetCallbackMask(HWND hwnd, UINT uMask)
3899 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
3901 infoPtr->uCallbackMask = uMask;
3903 return TRUE;
3906 /***
3907 * DESCRIPTION:
3908 * Sets column attributes.
3910 * PARAMETER(S):
3911 * [I] HWND : window handle
3912 * [I] INT : column index
3913 * [I] LPLVCOLUMNA : column attributes
3915 * RETURN:
3916 * SUCCESS : TRUE
3917 * FAILURE : FALSE
3919 static LRESULT LISTVIEW_SetColumnA(HWND hwnd, INT nColumn,
3920 LPLVCOLUMNA lpColumn)
3922 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
3923 HDITEMA hdi;
3924 BOOL bResult = FALSE;
3926 if ((lpColumn != NULL) && (nColumn >= 0) &&
3927 (nColumn < Header_GetItemCount(infoPtr->hwndHeader)))
3929 /* initialize memory */
3930 ZeroMemory(&hdi, sizeof(HDITEMA));
3932 if (lpColumn->mask & LVCF_FMT)
3934 /* format member is valid */
3935 hdi.mask |= HDI_FORMAT;
3937 /* set text alignment (leftmost column must be left-aligned) */
3938 if (nColumn == 0)
3940 hdi.fmt |= HDF_LEFT;
3942 else
3944 if (lpColumn->fmt & LVCFMT_LEFT)
3946 hdi.fmt |= HDF_LEFT;
3948 else if (lpColumn->fmt & LVCFMT_RIGHT)
3950 hdi.fmt |= HDF_RIGHT;
3952 else if (lpColumn->fmt & LVCFMT_CENTER)
3954 hdi.fmt |= HDF_CENTER;
3958 if (lpColumn->fmt & LVCFMT_BITMAP_ON_RIGHT)
3960 hdi.fmt |= HDF_BITMAP_ON_RIGHT;
3963 if (lpColumn->fmt & LVCFMT_COL_HAS_IMAGES)
3965 hdi.fmt |= HDF_IMAGE;
3968 if (lpColumn->fmt & LVCFMT_IMAGE)
3970 hdi.fmt |= HDF_IMAGE;
3971 hdi.iImage = I_IMAGECALLBACK;
3975 if (lpColumn->mask & LVCF_WIDTH)
3977 hdi.mask |= HDI_WIDTH;
3978 hdi.cxy = lpColumn->cx;
3981 if (lpColumn->mask & LVCF_TEXT)
3983 hdi.mask |= HDI_TEXT | HDI_FORMAT;
3984 hdi.pszText = lpColumn->pszText;
3985 hdi.cchTextMax = lstrlenA(lpColumn->pszText);
3986 hdi.fmt |= HDF_STRING;
3989 if (lpColumn->mask & LVCF_IMAGE)
3991 hdi.mask |= HDI_IMAGE;
3992 hdi.iImage = lpColumn->iImage;
3995 if (lpColumn->mask & LVCF_ORDER)
3997 hdi.mask |= HDI_ORDER;
3998 hdi.iOrder = lpColumn->iOrder;
4001 /* set header item attributes */
4002 bResult = Header_SetItemA(infoPtr->hwndHeader, nColumn, &hdi);
4005 return bResult;
4008 /***
4009 * DESCRIPTION:
4010 * Sets image list.
4012 * PARAMETER(S):
4013 * [I] HWND : window handle
4014 * [I] INT : image list type
4015 * [I] HIMAGELIST : image list handle
4017 * RETURN:
4018 * SUCCESS : old image list
4019 * FAILURE : NULL
4021 static LRESULT LISTVIEW_SetImageList(HWND hwnd, INT nType, HIMAGELIST himl)
4023 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
4024 HIMAGELIST himlTemp = 0;
4026 switch (nType)
4028 case LVSIL_NORMAL:
4029 himlTemp = infoPtr->himlNormal;
4030 infoPtr->himlNormal = himl;
4031 return (LRESULT)himlTemp;
4033 case LVSIL_SMALL:
4034 himlTemp = infoPtr->himlSmall;
4035 infoPtr->himlSmall = himl;
4036 return (LRESULT)himlTemp;
4038 case LVSIL_STATE:
4039 himlTemp = infoPtr->himlState;
4040 infoPtr->himlState = himl;
4041 return (LRESULT)himlTemp;
4044 return (LRESULT)NULL;
4048 /***
4049 * DESCRIPTION:
4050 * Sets item attributes.
4052 * PARAMETER(S):
4053 * [I] HWND : window handle
4054 * [I] LPLVITEM : item information
4056 * RETURN:
4057 * SUCCESS : TRUE
4058 * FAILURE : FALSE
4060 static LRESULT LISTVIEW_SetItemA(HWND hwnd, LPLVITEMA lpLVItem)
4062 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
4063 BOOL bResult = FALSE;
4065 if (lpLVItem != NULL)
4067 if ((lpLVItem->iItem >= 0) && (lpLVItem->iItem < GETITEMCOUNT(infoPtr)))
4069 if (lpLVItem->iSubItem == 0)
4071 bResult = LISTVIEW_SetItem(hwnd, lpLVItem);
4073 else
4075 bResult = LISTVIEW_SetSubItem(hwnd, lpLVItem);
4081 return bResult;
4084 /* << LISTVIEW_SetItemW >> */
4086 /***
4087 * DESCRIPTION:
4088 * Preallocates memory.
4090 * PARAMETER(S):
4091 * [I] HWND : window handle
4092 * [I] INT : item count (prjected number of items)
4094 * RETURN:
4095 * None
4097 static VOID LISTVIEW_SetItemCount(HWND hwnd, INT nItemCount)
4099 /* TO DO */
4102 /***
4103 * DESCRIPTION:
4104 * Sets item position.
4106 * PARAMETER(S):
4107 * [I] HWND : window handle
4108 * [I] INT : item index
4109 * [I] INT : x coordinate
4110 * [I] INT : y coordinate
4112 * RETURN:
4113 * SUCCESS : TRUE
4114 * FAILURE : FALSE
4116 static LRESULT LISTVIEW_SetItemPosition(HWND hwnd, INT nItem,
4117 INT nPosX, INT nPosY)
4119 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO*)GetWindowLongA(hwnd, 0);
4120 LONG lStyle = GetWindowLongA(hwnd, GWL_STYLE);
4121 BOOL bResult = FALSE;
4123 if ((nItem >= 0) || (nItem < GETITEMCOUNT(infoPtr)))
4125 if (((lStyle & LVS_TYPEMASK) == LVS_ICON) ||
4126 ((lStyle & LVS_TYPEMASK) == LVS_SMALLICON))
4128 /* TO DO */
4132 return bResult;
4135 /***
4136 * DESCRIPTION:
4137 * Sets the state of one or many items.
4139 * PARAMETER(S):
4140 * [I] HWND : window handle
4141 * [I]INT : item index
4142 * [I] LPLVITEM : item or subitem info
4144 * RETURN:
4145 * SUCCESS : TRUE
4146 * FAILURE : FALSE
4148 static LRESULT LISTVIEW_SetItemState(HWND hwnd, INT nItem,
4149 LPLVITEMA lpLVItem)
4151 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
4152 BOOL bResult = FALSE;
4153 LVITEMA lvItem;
4154 INT i;
4156 if (nItem == -1)
4158 bResult = TRUE;
4159 ZeroMemory(&lvItem, sizeof(LVITEMA));
4160 lvItem.mask = LVIF_STATE;
4161 lvItem.state = lpLVItem->state;
4162 lvItem.stateMask = lpLVItem->stateMask;
4164 /* apply to all items */
4165 for (i = 0; i< GETITEMCOUNT(infoPtr); i++)
4167 lvItem.iItem = i;
4168 if (ListView_SetItemA(hwnd, &lvItem) == FALSE)
4170 bResult = FALSE;
4174 else
4176 ZeroMemory(&lvItem, sizeof(LVITEMA));
4177 lvItem.mask = LVIF_STATE;
4178 lvItem.state = lpLVItem->state;
4179 lvItem.stateMask = lpLVItem->stateMask;
4180 lvItem.iItem = nItem;
4181 bResult = ListView_SetItemA(hwnd, &lvItem);
4184 return bResult;
4187 /***
4188 * DESCRIPTION:
4189 * Sets the text of an item or subitem.
4191 * PARAMETER(S):
4192 * [I] HWND : window handle
4193 * [I] INT : item index
4194 * [I] LPLVITEMA : item or subitem info
4196 * RETURN:
4197 * SUCCESS : TRUE
4198 * FAILURE : FALSE
4200 static BOOL LISTVIEW_SetItemTextA(HWND hwnd, INT nItem,
4201 LPLVITEMA lpLVItem)
4203 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
4204 BOOL bResult = FALSE;
4205 LVITEMA lvItem;
4207 if ((nItem >= 0) && (nItem < GETITEMCOUNT(infoPtr)))
4209 ZeroMemory(&lvItem, sizeof(LVITEMA));
4210 lvItem.mask = LVIF_TEXT;
4211 lvItem.pszText = lpLVItem->pszText;
4212 lvItem.iItem = nItem;
4213 lvItem.iSubItem = lpLVItem->iSubItem;
4214 bResult = ListView_SetItemA(hwnd, &lvItem);
4217 return bResult;
4220 /***
4221 * DESCRIPTION:
4222 * Sets the text background color.
4224 * PARAMETER(S):
4225 * [I] HWND : window handle
4226 * [I] COLORREF : text background color
4228 * RETURN:
4229 * SUCCESS : TRUE
4230 * FAILURE : FALSE
4232 static LRESULT LISTVIEW_SetTextBkColor(HWND hwnd, COLORREF clrTextBk)
4234 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
4236 infoPtr->clrTextBk = clrTextBk;
4238 return TRUE;
4241 /***
4242 * DESCRIPTION:
4243 * Sets the text background color.
4245 * PARAMETER(S):
4246 * [I] HWND : window handle
4247 * [I] COLORREF : text color
4249 * RETURN:
4250 * SUCCESS : TRUE
4251 * FAILURE : FALSE
4253 static LRESULT LISTVIEW_SetTextColor (HWND hwnd, COLORREF clrText)
4255 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
4257 infoPtr->clrText = clrText;
4259 return TRUE;
4262 /***
4263 * DESCRIPTION:
4264 * Sort items.
4266 * PARAMETER(S):
4267 * [I] HWND : window handle
4269 * RETURN:
4270 * SUCCESS : TRUE
4271 * FAILURE : FALSE
4273 static LRESULT LISTVIEW_SortItems(HWND hwnd, WPARAM wParam, LPARAM lParam)
4275 FIXME (listview, "empty stub!\n");
4277 return TRUE;
4280 /***
4281 * DESCRIPTION:
4282 * Updates an items or rearranges the listview control.
4284 * PARAMETER(S):
4285 * [I] HWND : window handle
4286 * [I] INT : item index
4288 * RETURN:
4289 * SUCCESS : TRUE
4290 * FAILURE : FALSE
4292 static LRESULT LISTVIEW_Update(HWND hwnd, INT nItem)
4294 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
4295 LONG lStyle = GetWindowLongA(hwnd, GWL_STYLE);
4296 BOOL bResult = FALSE;
4297 RECT rc;
4299 if ((nItem >= 0) && (nItem < GETITEMCOUNT(infoPtr)))
4301 bResult = TRUE;
4303 /* rearrange with default alignment style */
4304 if ((lStyle & LVS_AUTOARRANGE) && (((lStyle & LVS_TYPEMASK) == LVS_ICON) ||
4305 ((lStyle & LVS_TYPEMASK) == LVS_SMALLICON)))
4307 ListView_Arrange(hwnd, 0);
4309 else
4311 /* get item bounding rectangle */
4312 rc.left = LVIR_BOUNDS;
4313 ListView_GetItemRect(hwnd, nItem, &rc);
4314 InvalidateRect(hwnd, &rc, FALSE);
4318 return bResult;
4321 /***
4322 * DESCRIPTION:
4323 * Creates a listview control.
4325 * PARAMETER(S):
4326 * [I] HWND : window handle
4328 * RETURN:
4329 * Zero
4331 static LRESULT LISTVIEW_Create(HWND hwnd, WPARAM wParam, LPARAM lParam)
4333 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
4334 LPCREATESTRUCTA lpcs = (LPCREATESTRUCTA)lParam;
4335 LOGFONTA logFont;
4336 HDLAYOUT hl;
4337 WINDOWPOS wp;
4339 /* determine the type of structures to use */
4340 infoPtr->notifyFormat = SendMessageA(GetParent(hwnd), WM_NOTIFYFORMAT,
4341 (WPARAM)hwnd, (LPARAM)NF_QUERY);
4342 if (infoPtr->notifyFormat != NFR_ANSI)
4344 FIXME (listview, "ANSI notify format is NOT used\n");
4347 /* initialize color information */
4348 infoPtr->clrBk = GetSysColor(COLOR_WINDOW);
4349 infoPtr->clrText = GetSysColor(COLOR_WINDOWTEXT);
4350 infoPtr->clrTextBk = GetSysColor(COLOR_WINDOW);
4352 /* set default values */
4353 infoPtr->uCallbackMask = 0;
4354 infoPtr->nFocusedItem = -1;
4355 infoPtr->nSelectionMark = -1;
4356 infoPtr->iconSize.cx = GetSystemMetrics(SM_CXSMICON);
4357 infoPtr->iconSize.cy = GetSystemMetrics(SM_CYSMICON);
4358 ZeroMemory(&infoPtr->rcList, sizeof(RECT));
4360 /* get default font (icon title) */
4361 SystemParametersInfoA(SPI_GETICONTITLELOGFONT, 0, &logFont, 0);
4362 infoPtr->hDefaultFont = CreateFontIndirectA(&logFont);
4363 infoPtr->hFont = infoPtr->hDefaultFont;
4365 /* create header */
4366 infoPtr->hwndHeader = CreateWindowA(WC_HEADERA, (LPCSTR)NULL,
4367 WS_CHILD | HDS_HORZ | HDS_BUTTONS ,
4368 0, 0, 0, 0, hwnd, (HMENU)0,
4369 lpcs->hInstance, NULL);
4371 /* set header font */
4372 SendMessageA(infoPtr->hwndHeader, WM_SETFONT, (WPARAM)infoPtr->hFont,
4373 (LPARAM)TRUE);
4375 switch (lpcs->style & LVS_TYPEMASK)
4377 case LVS_REPORT:
4378 /* reset header */
4379 hl.prc = &infoPtr->rcList;
4380 hl.pwpos = &wp;
4381 Header_Layout(infoPtr->hwndHeader, &hl);
4382 SetWindowPos(infoPtr->hwndHeader, hwnd, wp.x, wp.y, wp.cx, wp.cy,
4383 wp.flags);
4385 /* set new top coord */
4386 infoPtr->rcList.top = wp.cy;
4388 /* display header */
4389 ShowWindow(infoPtr->hwndHeader, SW_SHOWNORMAL);
4390 break;
4392 case LVS_LIST:
4393 break;
4395 default:
4396 /* temporary (until there is support) */
4397 SetWindowLongA(hwnd, GWL_STYLE,
4398 (lpcs->style & ~LVS_TYPEMASK) | LVS_LIST);
4401 /* TEMPORARY */
4402 LISTVIEW_UnsupportedStyles(lpcs->style);
4404 /* allocate memory */
4405 infoPtr->hdpaItems = DPA_Create(10);
4407 /* set view dependent information */
4408 LISTVIEW_SetViewInfo(hwnd);
4410 return 0;
4414 /***
4415 * DESCRIPTION:
4416 * Destroys the window
4418 * PARAMETER(S):
4419 * [I] HWND : window handle
4421 * RETURN:
4422 * Zero
4424 static LRESULT LISTVIEW_Destroy(HWND hwnd)
4426 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO*)GetWindowLongA(hwnd, 0);
4428 /* delete all items */
4429 LISTVIEW_DeleteAllItems(hwnd);
4431 /* destroy dpa */
4432 DPA_Destroy(infoPtr->hdpaItems);
4434 /* destroy header */
4435 if (infoPtr->hwndHeader)
4437 DestroyWindow(infoPtr->hwndHeader);
4440 /* destroy font */
4441 infoPtr->hFont = (HFONT)0;
4442 if (infoPtr->hDefaultFont)
4444 DeleteObject(infoPtr->hDefaultFont);
4447 return 0;
4450 /***
4451 * DESCRIPTION:
4452 * Erases the background of the listview control
4454 * PARAMETER(S):
4455 * [I] HWND : window handle
4456 * [I] WPARAM : device context handle
4457 * [I] LPARAM : not used
4459 * RETURN:
4460 * SUCCESS : TRUE
4461 * FAILURE : FALSE
4463 static LRESULT LISTVIEW_EraseBackground(HWND hwnd, WPARAM wParam,
4464 LPARAM lParam)
4466 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
4467 BOOL bResult;
4469 if (infoPtr->clrBk == CLR_NONE)
4471 bResult = SendMessageA(GetParent(hwnd), WM_ERASEBKGND, wParam, lParam);
4473 else
4475 HBRUSH hBrush = CreateSolidBrush(infoPtr->clrBk);
4476 FillRect((HDC)wParam, &infoPtr->rcList, hBrush);
4477 DeleteObject(hBrush);
4478 bResult = TRUE;
4481 return bResult;
4484 /***
4485 * DESCRIPTION:
4486 * Gets the listview control font.
4488 * PARAMETER(S):
4489 * [I] HWND : window handle
4491 * RETURN:
4492 * Font handle.
4494 static LRESULT LISTVIEW_GetFont(HWND hwnd)
4496 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
4498 return infoPtr->hFont;
4501 /***
4502 * DESCRIPTION:
4503 * Performs horizontal scrolling.
4505 * PARAMETER(S):
4506 * [I] HWND : window handle
4507 * [I] INT : scroll code
4508 * [I] INT : scroll position
4509 * [I] HWND : scrollbar control window handle
4511 * RETURN:
4512 * Zero
4514 static LRESULT LISTVIEW_VScroll(HWND hwnd, INT nScrollCode,
4515 INT nScroll, HWND hScrollWnd)
4517 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
4518 LONG lStyle = GetWindowLongA(hwnd, GWL_STYLE);
4519 INT nScrollPos, nOldScrollPos;
4520 INT nMinRange;
4521 INT nMaxRange;
4523 GetScrollRange(hwnd, SB_VERT, &nMinRange, &nMaxRange);
4524 nOldScrollPos = nScrollPos = GetScrollPos(hwnd, SB_VERT);
4526 switch (LVS_TYPEMASK & lStyle)
4528 case LVS_REPORT:
4529 switch (nScrollCode)
4531 case SB_LINEUP:
4532 if (nScrollPos > nMinRange)
4534 nScrollPos--;
4536 break;
4537 case SB_LINEDOWN:
4538 if (nScrollPos < nMaxRange)
4540 nScrollPos++;
4542 break;
4543 case SB_PAGEUP:
4544 if (nScrollPos > nMinRange + infoPtr->nCountPerColumn)
4546 nScrollPos -= infoPtr->nCountPerColumn;
4548 else
4550 nScrollPos = nMinRange;
4552 break;
4553 case SB_PAGEDOWN:
4554 if (nScrollPos < nMaxRange - infoPtr->nCountPerColumn)
4556 nScrollPos += infoPtr->nCountPerColumn;
4558 else
4560 nScrollPos = nMaxRange;
4562 break;
4563 case SB_THUMBPOSITION:
4564 nScrollPos = nScroll;
4565 break;
4567 break;
4569 default:
4570 /* TO DO */
4573 /* set new scroll position */
4574 if (nScrollPos != nOldScrollPos)
4576 SetScrollPos(hwnd, SB_VERT, nScrollPos, TRUE);
4578 /* refresh client area */
4579 InvalidateRect(hwnd, NULL, TRUE);
4582 return 0;
4586 /***
4587 * DESCRIPTION:
4588 * Performs horizontal scrolling.
4590 * PARAMETER(S):
4591 * [I] HWND : window handle
4592 * [I] INT : scroll code
4593 * [I] INT : scroll position
4594 * [I] HWND : scrollbar control window handle
4596 * RETURN:
4597 * Zero
4599 static LRESULT LISTVIEW_HScroll(HWND hwnd, INT nScrollCode,
4600 INT nScroll, HWND hScrollWnd)
4602 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
4603 LONG lStyle = GetWindowLongA(hwnd, GWL_STYLE);
4604 INT nScrollPos, nOldScrollPos;
4605 INT nMinRange;
4606 INT nMaxRange;
4608 GetScrollRange(hwnd, SB_HORZ, &nMinRange, &nMaxRange);
4609 nOldScrollPos = nScrollPos = GetScrollPos(hwnd, SB_HORZ);
4611 switch (LVS_TYPEMASK & lStyle)
4613 case LVS_LIST:
4615 /* list display mode horizontal scrolling */
4616 switch (nScrollCode)
4618 case SB_LINELEFT:
4619 if (nScrollPos > nMinRange)
4621 nScrollPos--;
4623 break;
4624 case SB_LINERIGHT:
4625 if (nScrollPos < nMaxRange)
4627 nScrollPos++;
4629 break;
4630 case SB_PAGELEFT:
4631 if (nScrollPos > nMinRange)
4633 nScrollPos = max(nMinRange, nScrollPos - infoPtr->nCountPerRow);
4635 else
4637 nScrollPos = nMinRange;
4639 break;
4640 case SB_PAGERIGHT:
4641 if (nScrollPos < nMaxRange - 1)
4643 nScrollPos = min(nMaxRange, nScrollPos + infoPtr->nCountPerRow);
4645 else
4647 nScrollPos = nMaxRange;
4649 break;
4650 case SB_THUMBPOSITION:
4651 nScrollPos = nScroll;
4652 break;
4654 break;
4656 case LVS_REPORT:
4658 /* report/details display mode horizontal scrolling */
4659 switch (nScrollCode)
4661 case SB_LINELEFT:
4662 if (nScrollPos > nMinRange)
4664 nScrollPos--;
4666 break;
4667 case SB_LINERIGHT:
4668 if (nScrollPos < nMaxRange)
4670 nScrollPos++;
4672 break;
4673 case SB_PAGELEFT:
4674 if (nScrollPos > nMinRange)
4676 nScrollPos = max(nMinRange, nScrollPos - infoPtr->rcList.right);
4678 else
4680 nScrollPos = nMinRange;
4682 break;
4683 case SB_PAGERIGHT:
4684 if (nScrollPos < nMaxRange)
4686 nScrollPos = min(nMaxRange, nScrollPos + infoPtr->rcList.right);
4688 else
4690 nScrollPos = nMaxRange;
4692 break;
4693 case SB_THUMBPOSITION:
4694 nScrollPos = nScroll;
4695 break;
4697 break;
4699 default:
4700 /* TO DO */
4703 /* set new scroll position */
4704 if (nScrollPos != nOldScrollPos)
4706 SetScrollPos(hwnd, SB_HORZ, nScrollPos, TRUE);
4708 /* refresh client area */
4709 InvalidateRect(hwnd, NULL, TRUE);
4712 return 0;
4715 /***
4716 * DESCRIPTION:
4717 * ???
4719 * PARAMETER(S):
4720 * [I] HWND : window handle
4721 * [I] INT : virtual key
4722 * [I] LONG : key data
4724 * RETURN:
4725 * Zero
4727 static LRESULT LISTVIEW_KeyDown(HWND hwnd, INT nVirtualKey, LONG lKeyData)
4729 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
4730 LONG lStyle = GetWindowLongA(hwnd, GWL_STYLE);
4731 INT nCtrlId = GetWindowLongA(hwnd, GWL_ID);
4732 HWND hwndParent = GetParent(hwnd);
4733 NMLVKEYDOWN nmKeyDown;
4734 NMHDR nmh;
4736 /* send LVN_KEYDOWN notification */
4737 ZeroMemory(&nmKeyDown, sizeof(NMLVKEYDOWN));
4738 nmKeyDown.hdr.hwndFrom = hwnd;
4739 nmKeyDown.hdr.idFrom = nCtrlId;
4740 nmKeyDown.hdr.code = LVN_KEYDOWN;
4741 nmKeyDown.wVKey = nVirtualKey;
4742 nmKeyDown.flags = 0;
4743 SendMessageA(hwndParent, WM_NOTIFY, (WPARAM)nCtrlId, (LPARAM)&nmKeyDown);
4745 /* initialize */
4746 nmh.hwndFrom = hwnd;
4747 nmh.idFrom = nCtrlId;
4749 switch (nVirtualKey)
4751 case VK_RETURN:
4752 if ((GETITEMCOUNT(infoPtr) > 0) && (infoPtr->nFocusedItem != -1))
4754 /* send NM_RETURN notification */
4755 nmh.code = NM_RETURN;
4756 ListView_Notify(hwndParent, nCtrlId, &nmh);
4758 /* send LVN_ITEMACTIVATE notification */
4759 nmh.code = LVN_ITEMACTIVATE;
4760 ListView_Notify(hwndParent, nCtrlId, &nmh);
4762 break;
4764 case VK_HOME:
4765 if (GETITEMCOUNT(infoPtr) > 0)
4767 LISTVIEW_KeySelection(hwnd, 0);
4769 break;
4771 case VK_END:
4772 if (GETITEMCOUNT(infoPtr) > 0)
4774 LISTVIEW_KeySelection(hwnd, GETITEMCOUNT(infoPtr) - 1);
4776 break;
4778 case VK_LEFT:
4779 switch (LVS_TYPEMASK & lStyle)
4781 case LVS_LIST:
4782 if (infoPtr->nFocusedItem >= infoPtr->nCountPerColumn)
4784 LISTVIEW_KeySelection(hwnd, infoPtr->nFocusedItem - infoPtr->nCountPerColumn);
4786 break;
4787 case LVS_REPORT:
4788 break;
4790 default:
4791 if (infoPtr->nFocusedItem % infoPtr->nCountPerRow != 0)
4793 LISTVIEW_SetSelection(hwnd, infoPtr->nFocusedItem - 1);
4796 break;
4798 case VK_UP:
4799 switch (LVS_TYPEMASK & lStyle)
4801 case LVS_LIST:
4802 case LVS_REPORT:
4803 if (infoPtr->nFocusedItem > 0)
4805 LISTVIEW_KeySelection(hwnd, infoPtr->nFocusedItem - 1);
4807 break;
4809 default:
4810 if (infoPtr->nFocusedItem >= infoPtr->nCountPerRow)
4812 LISTVIEW_SetSelection(hwnd, infoPtr->nFocusedItem -
4813 infoPtr->nCountPerRow);
4816 break;
4818 case VK_RIGHT:
4819 switch (LVS_TYPEMASK & lStyle)
4821 case LVS_LIST:
4822 if (infoPtr->nFocusedItem <
4823 (GETITEMCOUNT(infoPtr) - infoPtr->nCountPerColumn))
4825 LISTVIEW_KeySelection(hwnd, infoPtr->nFocusedItem +
4826 infoPtr->nCountPerColumn);
4828 case LVS_REPORT:
4829 break;
4831 default:
4832 if (infoPtr->nCountPerRow > 0)
4836 break;
4838 case VK_DOWN:
4839 switch (LVS_TYPEMASK & lStyle)
4841 case LVS_LIST:
4842 case LVS_REPORT:
4843 if (infoPtr->nFocusedItem < GETITEMCOUNT(infoPtr) - 1)
4845 LISTVIEW_KeySelection(hwnd, infoPtr->nFocusedItem + 1);
4847 default:
4848 if (infoPtr->nCountPerRow > 0)
4852 break;
4854 case VK_PRIOR:
4855 break;
4857 case VK_NEXT:
4858 break;
4861 /* refresh client area */
4862 InvalidateRect(hwnd, NULL, TRUE);
4864 return 0;
4867 /***
4868 * DESCRIPTION:
4869 * Kills the focus.
4871 * PARAMETER(S):
4872 * [I] HWND : window handle
4874 * RETURN:
4875 * Zero
4877 static LRESULT LISTVIEW_KillFocus(HWND hwnd)
4879 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO*)GetWindowLongA(hwnd, 0);
4880 INT nCtrlId = GetWindowLongA(hwnd, GWL_ID);
4881 NMHDR nmh;
4883 /* send NM_KILLFOCUS notification */
4884 nmh.hwndFrom = hwnd;
4885 nmh.idFrom = nCtrlId;
4886 nmh.code = NM_KILLFOCUS;
4887 ListView_Notify(GetParent(hwnd), nCtrlId, &nmh);
4889 /* set window focus flag */
4890 infoPtr->bFocus = FALSE;
4892 return 0;
4895 /***
4896 * DESCRIPTION:
4897 * Left mouse button double click.
4899 * PARAMETER(S):
4900 * [I] HWND : window handle
4901 * [I] WORD : key flag
4902 * [I] WORD : x coordinate
4903 * [I] WORD : y coordinate
4905 * RETURN:
4906 * Zero
4908 static LRESULT LISTVIEW_LButtonDblClk(HWND hwnd, WORD wKey, WORD wPosX,
4909 WORD wPosY)
4911 LONG nCtrlId = GetWindowLongA(hwnd, GWL_ID);
4912 NMHDR nmh;
4914 /* send NM_DBLCLK notification */
4915 nmh.hwndFrom = hwnd;
4916 nmh.idFrom = nCtrlId;
4917 nmh.code = NM_DBLCLK;
4918 ListView_Notify(GetParent(hwnd), nCtrlId, &nmh);
4920 /* send LVN_ITEMACTIVATE notification */
4921 nmh.code = LVN_ITEMACTIVATE;
4922 ListView_Notify(GetParent(hwnd), nCtrlId, &nmh);
4924 return 0;
4927 /***
4928 * DESCRIPTION:
4929 * Left mouse button down.
4931 * PARAMETER(S):
4932 * [I] HWND : window handle
4933 * [I] WORD : key flag
4934 * [I] WORD : x coordinate
4935 * [I] WORD : y coordinate
4937 * RETURN:
4938 * Zero
4940 static LRESULT LISTVIEW_LButtonDown(HWND hwnd, WORD wKey, WORD wPosX,
4941 WORD wPosY)
4943 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
4944 INT nCtrlId = GetWindowLongA(hwnd, GWL_ID);
4945 LVHITTESTINFO hitTestInfo;
4946 NMHDR nmh;
4947 INT nItem;
4948 static BOOL bGroupSelect = TRUE;
4950 /* send NM_RELEASEDCAPTURE notification */
4951 nmh.hwndFrom = hwnd;
4952 nmh.idFrom = nCtrlId;
4953 nmh.code = NM_RELEASEDCAPTURE;
4954 ListView_Notify(GetParent(hwnd), nCtrlId, &nmh);
4956 if (infoPtr->bFocus == FALSE)
4958 SetFocus(hwnd);
4961 /* set left button down flag */
4962 infoPtr->bLButtonDown = TRUE;
4964 /* set left button hit coordinates */
4965 hitTestInfo.pt.x = wPosX;
4966 hitTestInfo.pt.y = wPosY;
4968 /* perform hit test */
4969 nItem = ListView_HitTest(hwnd, &hitTestInfo);
4970 if ((nItem >= 0) && (nItem < GETITEMCOUNT(infoPtr)))
4972 if ((wKey & MK_CONTROL) && (wKey & MK_SHIFT))
4974 if (bGroupSelect == TRUE)
4976 LISTVIEW_AddGroupSelection(hwnd, nItem);
4978 else
4980 LISTVIEW_AddSelection(hwnd, nItem);
4983 else if (wKey & MK_CONTROL)
4985 bGroupSelect = LISTVIEW_ToggleSelection(hwnd, nItem);
4987 else if (wKey & MK_SHIFT)
4989 LISTVIEW_SetGroupSelection(hwnd, nItem);
4991 else
4993 LISTVIEW_SetSelection(hwnd, nItem);
4996 else
4998 /* remove all selections */
4999 LISTVIEW_RemoveSelections(hwnd, 0, GETITEMCOUNT(infoPtr));
5002 InvalidateRect(hwnd, NULL, TRUE);
5004 return 0;
5007 /***
5008 * DESCRIPTION:
5009 * Left mouse button up.
5011 * PARAMETER(S):
5012 * [I] HWND : window handle
5013 * [I] WORD : key flag
5014 * [I] WORD : x coordinate
5015 * [I] WORD : y coordinate
5017 * RETURN:
5018 * Zero
5020 static LRESULT LISTVIEW_LButtonUp(HWND hwnd, WORD wKey, WORD wPosX,
5021 WORD wPosY)
5023 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
5024 INT nCtrlId = GetWindowLongA(hwnd, GWL_ID);
5025 NMHDR nmh;
5027 if (infoPtr->bLButtonDown == TRUE)
5029 /* send NM_CLICK notification */
5030 nmh.hwndFrom = hwnd;
5031 nmh.idFrom = nCtrlId;
5032 nmh.code = NM_CLICK;
5033 ListView_Notify(GetParent(hwnd), nCtrlId, &nmh);
5035 /* set left button flag */
5036 infoPtr->bLButtonDown = FALSE;
5039 return 0;
5042 /***
5043 * DESCRIPTION:
5044 * Creates the listview control (called before WM_CREATE).
5046 * PARAMETER(S):
5047 * [I] HWND : window handle
5048 * [I] WPARAM : unhandled
5049 * [I] LPARAM : widow creation info
5051 * RETURN:
5052 * Zero
5054 static LRESULT LISTVIEW_NCCreate(HWND hwnd, WPARAM wParam, LPARAM lParam)
5056 LISTVIEW_INFO *infoPtr;
5058 /* allocate memory for info structure */
5059 infoPtr = (LISTVIEW_INFO *)COMCTL32_Alloc(sizeof(LISTVIEW_INFO));
5060 SetWindowLongA(hwnd, 0, (LONG)infoPtr);
5061 if (infoPtr == NULL)
5063 ERR(listview, "could not allocate info memory!\n");
5064 return 0;
5067 if ((LISTVIEW_INFO *)GetWindowLongA(hwnd, 0) != infoPtr)
5069 ERR(listview, "pointer assignment error!\n");
5070 return 0;
5073 return DefWindowProcA(hwnd, WM_NCCREATE, wParam, lParam);
5076 /***
5077 * DESCRIPTION:
5078 * Destroys the listview control (called after WM_DESTROY).
5080 * PARAMETER(S):
5081 * [I] HWND : window handle
5083 * RETURN:
5084 * Zero
5086 static LRESULT LISTVIEW_NCDestroy(HWND hwnd)
5088 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
5090 /* free listview info */
5091 COMCTL32_Free(infoPtr);
5093 return 0;
5096 /***
5097 * DESCRIPTION:
5098 * Handles notification from children.
5100 * PARAMETER(S):
5101 * [I] HWND : window handle
5102 * [I] INT : control identifier
5103 * [I] LPNMHDR : notification information
5105 * RETURN:
5106 * Zero
5108 static LRESULT LISTVIEW_Notify(HWND hwnd, INT nCtrlId, LPNMHDR lpnmh)
5110 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
5112 if (lpnmh->hwndFrom == infoPtr->hwndHeader)
5114 /* handle notification from header control */
5115 if (lpnmh->code == HDN_ENDTRACKA)
5117 InvalidateRect(hwnd, NULL, TRUE);
5121 return 0;
5124 static LRESULT LISTVIEW_NotifyFormat(HWND hwndFrom, HWND hwnd, INT nCommand)
5126 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
5128 if (nCommand == NF_REQUERY)
5130 /* determine the type of structures to use */
5131 infoPtr->notifyFormat = SendMessageA(hwndFrom, WM_NOTIFYFORMAT,
5132 (WPARAM)hwnd, (LPARAM)NF_QUERY);
5133 if (infoPtr->notifyFormat == NFR_UNICODE)
5135 FIXME (listview, "NO support for unicode structures");
5139 return 0;
5142 /***
5143 * DESCRIPTION:
5144 * Draws the listview control.
5146 * PARAMETER(S):
5147 * [I] HWND : window handle
5148 * [I] HDC : device context handle
5150 * RETURN:
5151 * Zero
5153 static LRESULT LISTVIEW_Paint(HWND hwnd, HDC hdc)
5155 PAINTSTRUCT ps;
5157 if (hdc == 0)
5159 hdc = BeginPaint(hwnd, &ps);
5160 LISTVIEW_Refresh(hwnd, hdc);
5161 EndPaint(hwnd, &ps);
5163 else
5165 LISTVIEW_Refresh(hwnd, hdc);
5168 return 0;
5171 /***
5172 * DESCRIPTION:
5173 * Right mouse button double click.
5175 * PARAMETER(S):
5176 * [I] HWND : window handle
5177 * [I] WORD : key flag
5178 * [I] WORD : x coordinate
5179 * [I] WORD : y coordinate
5181 * RETURN:
5182 * Zero
5184 static LRESULT LISTVIEW_RButtonDblClk(HWND hwnd, WORD wKey, WORD wPosX,
5185 WORD wPosY)
5187 INT nCtrlId = GetWindowLongA(hwnd, GWL_ID);
5188 NMHDR nmh;
5190 /* send NM_RELEASEDCAPTURE notification */
5191 nmh.hwndFrom = hwnd;
5192 nmh.idFrom = nCtrlId;
5193 nmh.code = NM_RELEASEDCAPTURE;
5194 ListView_Notify(GetParent(hwnd), nCtrlId, &nmh);
5196 /* send NM_RDBLCLK notification */
5197 nmh.code = NM_RDBLCLK;
5198 ListView_Notify(GetParent(hwnd), nCtrlId, &nmh);
5200 return 0;
5203 /***
5204 * DESCRIPTION:
5205 * Right mouse button input.
5207 * PARAMETER(S):
5208 * [I] HWND : window handle
5209 * [I] WORD : key flag
5210 * [I] WORD : x coordinate
5211 * [I] WORD : y coordinate
5213 * RETURN:
5214 * Zero
5216 static LRESULT LISTVIEW_RButtonDown(HWND hwnd, WORD wKey, WORD wPosX,
5217 WORD wPosY)
5219 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
5220 INT nCtrlId = GetWindowLongA(hwnd, GWL_ID);
5221 LVHITTESTINFO hitTestInfo;
5222 NMHDR nmh;
5223 INT nItem;
5225 /* send NM_RELEASEDCAPTURE notification */
5226 nmh.hwndFrom = hwnd;
5227 nmh.idFrom = nCtrlId;
5228 nmh.code = NM_RELEASEDCAPTURE;
5229 ListView_Notify(GetParent(hwnd), nCtrlId, &nmh);
5231 /* make sure the listview control window has the focus */
5232 if (infoPtr->bFocus == FALSE)
5234 SetFocus(hwnd);
5237 /* set right button down flag */
5238 infoPtr->bRButtonDown = TRUE;
5240 /* set hit coordinates */
5241 hitTestInfo.pt.x = wPosX;
5242 hitTestInfo.pt.y = wPosY;
5244 /* perform hit test */
5245 nItem = ListView_HitTest(hwnd, &hitTestInfo);
5246 if ((nItem >= 0) && (nItem < GETITEMCOUNT(infoPtr)))
5248 if (!((wKey & MK_SHIFT) || (wKey & MK_CONTROL)))
5250 LISTVIEW_SetSelection(hwnd, nItem);
5253 else
5255 LISTVIEW_RemoveSelections(hwnd, 0, GETITEMCOUNT(infoPtr));
5258 return 0;
5261 /***
5262 * DESCRIPTION:
5263 * Right mouse button up.
5265 * PARAMETER(S):
5266 * [I] HWND : window handle
5267 * [I] WORD : key flag
5268 * [I] WORD : x coordinate
5269 * [I] WORD : y coordinate
5271 * RETURN:
5272 * Zero
5274 static LRESULT LISTVIEW_RButtonUp(HWND hwnd, WORD wKey, WORD wPosX,
5275 WORD wPosY)
5277 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
5278 INT nCtrlId = GetWindowLongA(hwnd, GWL_ID);
5279 NMHDR nmh;
5281 if (infoPtr->bRButtonDown == TRUE)
5283 /* send NM_RClICK notification */
5284 ZeroMemory(&nmh, sizeof(NMHDR));
5285 nmh.hwndFrom = hwnd;
5286 nmh.idFrom = nCtrlId;
5287 nmh.code = NM_RCLICK;
5288 ListView_Notify(GetParent(hwnd), nCtrlId, &nmh);
5290 /* set button flag */
5291 infoPtr->bRButtonDown = FALSE;
5294 return 0;
5297 /***
5298 * DESCRIPTION:
5299 * Sets the focus.
5301 * PARAMETER(S):
5302 * [I] HWND : window handle
5303 * [I] HWND : window handle of previously focused window
5305 * RETURN:
5306 * Zero
5308 static LRESULT LISTVIEW_SetFocus(HWND hwnd, HWND hwndLoseFocus)
5310 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
5311 INT nCtrlId = GetWindowLongA(hwnd, GWL_ID);
5312 NMHDR nmh;
5314 /* send NM_SETFOCUS notification */
5315 nmh.hwndFrom = hwnd;
5316 nmh.idFrom = nCtrlId;
5317 nmh.code = NM_SETFOCUS;
5318 ListView_Notify(GetParent(hwnd), nCtrlId, &nmh);
5320 /* set window focus flag */
5321 infoPtr->bFocus = TRUE;
5323 return 0;
5326 /***
5327 * DESCRIPTION:
5328 * Sets the font.
5330 * PARAMETER(S):
5331 * [I] HWND : window handle
5332 * [I] HFONT : font handle
5333 * [I] WORD : redraw flag
5335 * RETURN:
5336 * Zero
5338 static LRESULT LISTVIEW_SetFont(HWND hwnd, HFONT hFont, WORD fRedraw)
5340 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
5341 LONG lStyle = GetWindowLongA(hwnd, GWL_STYLE);
5343 if (hFont == 0)
5345 infoPtr->hFont = infoPtr->hDefaultFont;
5347 else
5349 infoPtr->hFont = hFont;
5352 if ((LVS_TYPEMASK & lStyle ) == LVS_REPORT)
5354 /* set header font */
5355 SendMessageA(infoPtr->hwndHeader, WM_SETFONT, (WPARAM)hFont,
5356 MAKELPARAM(fRedraw, 0));
5359 /* invalidate listview control client area */
5360 InvalidateRect(hwnd, NULL, FALSE);
5362 if (fRedraw == TRUE)
5364 UpdateWindow(hwnd);
5367 return 0;
5370 /***
5371 * DESCRIPTION:
5372 * Resizes the listview control.
5374 * PARAMETER(S):
5375 * [I] HWND : window handle
5376 * [I] WORD : new width
5377 * [I] WORD : new height
5379 * RETURN:
5380 * Zero
5382 static LRESULT LISTVIEW_Size(HWND hwnd, WORD wWidth, WORD wHeight)
5384 LISTVIEW_SetSize(hwnd, GetWindowLongA(hwnd, GWL_STYLE), wWidth, wHeight);
5385 LISTVIEW_SetViewInfo(hwnd);
5386 LISTVIEW_SetScroll(hwnd);
5388 /* invalidate + erase background */
5389 InvalidateRect(hwnd, NULL, TRUE);
5391 return 0;
5394 /***
5395 * DESCRIPTION:
5396 * Sets the size information for a given style.
5398 * PARAMETER(S):
5399 * [I] HWND : window handle
5400 * [I] LONG : window style
5401 * [I] WORD : new width
5402 * [I] WORD : new height
5404 * RETURN:
5405 * Zero
5407 static VOID LISTVIEW_SetSize(HWND hwnd, LONG lStyle, LONG lWidth, LONG lHeight)
5409 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
5410 HDLAYOUT hl;
5411 WINDOWPOS wp;
5412 INT lTop = 0;
5413 RECT rc;
5415 switch (lStyle & LVS_TYPEMASK)
5417 case LVS_LIST:
5418 if ((lStyle & LVS_TYPEMASK) == LVS_LIST)
5420 if (!(lStyle & WS_HSCROLL))
5422 INT nHScrollHeight;
5424 nHScrollHeight = GetSystemMetrics(SM_CYHSCROLL);
5425 if (lHeight > nHScrollHeight)
5427 lHeight -= nHScrollHeight;
5431 break;
5433 case LVS_REPORT:
5434 rc.left = 0;
5435 rc.top = 0;
5436 rc.right = lWidth;
5437 rc.bottom = lHeight;
5438 hl.prc = &rc;
5439 hl.pwpos = &wp;
5440 Header_Layout(infoPtr->hwndHeader, &hl);
5441 lTop = wp.cy;
5442 break;
5445 infoPtr->rcList.top = lTop;
5446 infoPtr->rcList.left = 0;
5447 infoPtr->rcList.bottom = lHeight;
5448 infoPtr->rcList.right = lWidth;
5451 /***
5452 * DESCRIPTION:
5453 * Notification sent when the window style is modified.
5455 * PARAMETER(S):
5456 * [I] HWND : window handle
5457 * [I] WPARAM : window style type (normal or extended)
5458 * [I] LPSTYLESTRUCT : window style information
5460 * RETURN:
5461 * Zero
5463 static INT LISTVIEW_StyleChanged(HWND hwnd, WPARAM wStyleType,
5464 LPSTYLESTRUCT lpss)
5466 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
5467 HDLAYOUT hl;
5468 WINDOWPOS wp;
5469 HDC hdc;
5470 RECT rc;
5471 HBRUSH hBrush;
5473 if (wStyleType == GWL_STYLE)
5475 /* remove vertical scrollbar */
5476 if (lpss->styleOld & WS_VSCROLL)
5478 ShowScrollBar(hwnd, SB_VERT, FALSE);
5481 /* remove horizontal scrollbar */
5482 if (lpss->styleOld & WS_HSCROLL)
5484 ShowScrollBar(hwnd, SB_HORZ, FALSE);
5487 if ((LVS_TYPEMASK & lpss->styleOld) == LVS_REPORT)
5489 /* hide header */
5490 ShowWindow(infoPtr->hwndHeader, SW_HIDE);
5493 /* erase everything */
5494 GetClientRect(hwnd, &rc);
5495 hdc = GetDC(hwnd);
5496 hBrush = CreateSolidBrush(infoPtr->clrBk);
5497 FillRect(hdc, &rc, hBrush);
5498 DeleteObject(hBrush);
5499 ReleaseDC(hwnd, hdc);
5501 if ((lpss->styleNew & LVS_TYPEMASK) == LVS_REPORT)
5503 hl.prc = &rc;
5504 hl.pwpos = &wp;
5505 Header_Layout(infoPtr->hwndHeader, &hl);
5506 SetWindowPos(infoPtr->hwndHeader, hwnd, wp.x, wp.y, wp.cx, wp.cy,
5507 wp.flags);
5508 ShowWindow(infoPtr->hwndHeader, SW_SHOWNORMAL);
5510 else if (((lpss->styleNew & LVS_TYPEMASK) == LVS_ICON) ||
5511 ((lpss->styleNew & LVS_TYPEMASK) == LVS_SMALLICON))
5513 /* for NOW (it's only temporary) */
5514 SetWindowLongA(hwnd, GWL_STYLE, (lpss->styleNew&~LVS_TYPEMASK)|LVS_LIST);
5517 /* TEMPORARY */
5518 LISTVIEW_UnsupportedStyles(lpss->styleNew);
5520 /* set new size */
5521 LISTVIEW_SetSize(hwnd, lpss->styleNew, rc.right, rc.bottom);
5523 /* recalculate attributes */
5524 LISTVIEW_SetViewInfo(hwnd);
5526 /* set scrollbars, if needed */
5527 LISTVIEW_SetScroll(hwnd);
5529 /* invalidate + erase background */
5530 InvalidateRect(hwnd, NULL, TRUE);
5533 return 0;
5536 /***
5537 * DESCRIPTION:
5538 * Window procedure of the listview control.
5540 * PARAMETER(S):
5541 * [I] HWND :
5542 * [I] UINT :
5543 * [I] WPARAM :
5544 * [I] LPARAM :
5546 * RETURN:
5549 LRESULT WINAPI LISTVIEW_WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam,
5550 LPARAM lParam)
5552 switch (uMsg)
5554 case LVM_APPROXIMATEVIEWRECT:
5555 return LISTVIEW_ApproximateViewRect(hwnd, (INT)wParam,
5556 LOWORD(lParam), HIWORD(lParam));
5557 case LVM_ARRANGE:
5558 return LISTVIEW_Arrange(hwnd, (INT)wParam);
5560 /* case LVM_CREATEDRAGIMAGE: */
5562 case LVM_DELETEALLITEMS:
5563 return LISTVIEW_DeleteAllItems(hwnd);
5565 case LVM_DELETECOLUMN:
5566 return LISTVIEW_DeleteColumn(hwnd, (INT)wParam);
5568 case LVM_DELETEITEM:
5569 return LISTVIEW_DeleteItem(hwnd, (INT)wParam);
5571 /* case LVM_EDITLABEL: */
5573 case LVM_ENSUREVISIBLE:
5574 return LISTVIEW_EnsureVisible(hwnd, (INT)wParam, (BOOL)lParam);
5576 case LVM_FINDITEMA:
5577 return LISTVIEW_FindItem(hwnd, (INT)wParam, (LPLVFINDINFO)lParam);
5579 case LVM_GETBKCOLOR:
5580 return LISTVIEW_GetBkColor(hwnd);
5582 /* case LVM_GETBKIMAGE: */
5584 case LVM_GETCALLBACKMASK:
5585 return LISTVIEW_GetCallbackMask(hwnd);
5587 case LVM_GETCOLUMNA:
5588 return LISTVIEW_GetColumnA(hwnd, (INT)wParam, (LPLVCOLUMNA)lParam);
5590 /* case LVM_GETCOLUMNW: */
5591 /* case LVM_GETCOLUMNORDERARRAY: */
5593 case LVM_GETCOLUMNWIDTH:
5594 return LISTVIEW_GetColumnWidth(hwnd, (INT)wParam);
5596 case LVM_GETCOUNTPERPAGE:
5597 return LISTVIEW_GetCountPerPage(hwnd);
5599 /* case LVM_GETEDITCONTROL: */
5600 /* case LVM_GETEXTENDEDLISTVIEWSTYLE: */
5602 case LVM_GETHEADER:
5603 return LISTVIEW_GetHeader(hwnd);
5605 /* case LVM_GETHOTCURSOR: */
5606 /* case LVM_GETHOTITEM: */
5607 /* case LVM_GETHOVERTIME: */
5609 case LVM_GETIMAGELIST:
5610 return LISTVIEW_GetImageList(hwnd, (INT)wParam);
5612 /* case LVM_GETISEARCHSTRING: */
5614 case LVM_GETITEMA:
5615 return LISTVIEW_GetItemA(hwnd, (LPLVITEMA)lParam);
5617 /* case LVM_GETITEMW: */
5619 case LVM_GETITEMCOUNT:
5620 return LISTVIEW_GetItemCount(hwnd);
5622 case LVM_GETITEMPOSITION:
5623 return LISTVIEW_GetItemPosition(hwnd, (INT)wParam, (LPPOINT)lParam);
5625 case LVM_GETITEMRECT:
5626 return LISTVIEW_GetItemRect(hwnd, (INT)wParam, (LPRECT)lParam);
5628 case LVM_GETITEMSPACING:
5629 return LISTVIEW_GetItemSpacing(hwnd, (BOOL)wParam);
5631 case LVM_GETITEMSTATE:
5632 return LISTVIEW_GetItemState(hwnd, (INT)wParam, (UINT)lParam);
5634 case LVM_GETITEMTEXTA:
5635 LISTVIEW_GetItemTextA(hwnd, (INT)wParam, (LPLVITEMA)lParam);
5636 break;
5638 /* case LVM_GETITEMTEXTW: */
5640 case LVM_GETNEXTITEM:
5641 return LISTVIEW_GetNextItem(hwnd, (INT)wParam, LOWORD(lParam));
5643 /* case LVM_GETNUMBEROFWORKAREAS: */
5644 case LVM_GETORIGIN:
5645 return LISTVIEW_GetOrigin(hwnd, (LPPOINT)lParam);
5647 case LVM_GETSELECTEDCOUNT:
5648 return LISTVIEW_GetSelectedCount(hwnd);
5650 case LVM_GETSELECTIONMARK:
5651 return LISTVIEW_GetSelectionMark(hwnd);
5653 case LVM_GETSTRINGWIDTHA:
5654 return LISTVIEW_GetStringWidthA (hwnd, (LPCSTR)lParam);
5656 /* case LVM_GETSTRINGWIDTHW: */
5657 /* case LVM_GETSUBITEMRECT: */
5659 case LVM_GETTEXTBKCOLOR:
5660 return LISTVIEW_GetTextBkColor(hwnd);
5662 case LVM_GETTEXTCOLOR:
5663 return LISTVIEW_GetTextColor(hwnd);
5665 /* case LVM_GETTOOLTIPS: */
5667 case LVM_GETTOPINDEX:
5668 return LISTVIEW_GetTopIndex(hwnd);
5670 /* case LVM_GETUNICODEFORMAT: */
5672 case LVM_GETVIEWRECT:
5673 return LISTVIEW_GetViewRect(hwnd, (LPRECT)lParam);
5675 /* case LVM_GETWORKAREAS: */
5677 case LVM_HITTEST:
5678 return LISTVIEW_HitTest(hwnd, (LPLVHITTESTINFO)lParam);
5680 case LVM_INSERTCOLUMNA:
5681 return LISTVIEW_InsertColumnA(hwnd, (INT)wParam,
5682 (LPLVCOLUMNA)lParam);
5684 /* case LVM_INSERTCOLUMNW: */
5686 case LVM_INSERTITEMA:
5687 return LISTVIEW_InsertItemA(hwnd, (LPLVITEMA)lParam);
5689 /* case LVM_INSERTITEMW: */
5691 case LVM_REDRAWITEMS:
5692 return LISTVIEW_RedrawItems(hwnd, (INT)wParam, (INT)lParam);
5694 case LVM_SCROLL:
5695 return LISTVIEW_Scroll(hwnd, (INT)wParam, (INT)lParam);
5697 case LVM_SETBKCOLOR:
5698 return LISTVIEW_SetBkColor(hwnd, (COLORREF)lParam);
5700 /* case LVM_SETBKIMAGE: */
5702 case LVM_SETCALLBACKMASK:
5703 return LISTVIEW_SetCallbackMask(hwnd, (UINT)wParam);
5705 case LVM_SETCOLUMNA:
5706 return LISTVIEW_SetColumnA(hwnd, (INT)wParam, (LPLVCOLUMNA)lParam);
5708 /* case LVM_SETCOLUMNW: */
5709 /* case LVM_SETCOLUMNORDERARRAY: */
5710 /* case LVM_SETCOLUMNWIDTH: */
5711 /* case LVM_SETEXTENDEDLISTVIEWSTYLE: */
5712 /* case LVM_SETHOTCURSOR: */
5713 /* case LVM_SETHOTITEM: */
5714 /* case LVM_SETHOVERTIME: */
5715 /* case LVM_SETICONSPACING: */
5717 case LVM_SETIMAGELIST:
5718 return LISTVIEW_SetImageList(hwnd, (INT)wParam, (HIMAGELIST)lParam);
5720 case LVM_SETITEMA:
5721 return LISTVIEW_SetItemA(hwnd, (LPLVITEMA)lParam);
5723 /* case LVM_SETITEMW: */
5725 case LVM_SETITEMCOUNT:
5726 LISTVIEW_SetItemCount(hwnd, (INT)wParam);
5727 break;
5729 case LVM_SETITEMPOSITION:
5730 return LISTVIEW_SetItemPosition(hwnd, (INT)wParam, (INT)LOWORD(lParam),
5731 (INT)HIWORD(lParam));
5733 /* case LVM_SETITEMPOSITION: */
5735 case LVM_SETITEMSTATE:
5736 return LISTVIEW_SetItemState(hwnd, (INT)wParam, (LPLVITEMA)lParam);
5738 case LVM_SETITEMTEXTA:
5739 return LISTVIEW_SetItemTextA(hwnd, (INT)wParam, (LPLVITEMA)lParam);
5741 /* case LVM_SETSELECTIONMARK: */
5743 case LVM_SETTEXTBKCOLOR:
5744 return LISTVIEW_SetTextBkColor(hwnd, (COLORREF)lParam);
5746 case LVM_SETTEXTCOLOR:
5747 return LISTVIEW_SetTextColor(hwnd, (COLORREF)lParam);
5749 /* case LVM_SETTOOLTIPS: */
5750 /* case LVM_SETUNICODEFORMAT: */
5751 /* case LVM_SETWORKAREAS: */
5753 case LVM_SORTITEMS:
5754 return LISTVIEW_SortItems(hwnd, wParam, lParam);
5756 /* case LVM_SUBITEMHITTEST: */
5758 case LVM_UPDATE:
5759 return LISTVIEW_Update(hwnd, (INT)wParam);
5761 /* case WM_CHAR: */
5762 /* case WM_COMMAND: */
5764 case WM_CREATE:
5765 return LISTVIEW_Create(hwnd, wParam, lParam);
5767 case WM_DESTROY:
5768 return LISTVIEW_Destroy(hwnd);
5770 case WM_ERASEBKGND:
5771 return LISTVIEW_EraseBackground(hwnd, wParam, lParam);
5773 case WM_GETDLGCODE:
5774 return DLGC_WANTTAB | DLGC_WANTARROWS;
5776 case WM_GETFONT:
5777 return LISTVIEW_GetFont(hwnd);
5779 case WM_HSCROLL:
5780 return LISTVIEW_HScroll(hwnd, (INT)LOWORD(wParam),
5781 (INT)HIWORD(wParam), (HWND)lParam);
5783 case WM_KEYDOWN:
5784 return LISTVIEW_KeyDown(hwnd, (INT)wParam, (LONG)lParam);
5786 case WM_KILLFOCUS:
5787 return LISTVIEW_KillFocus(hwnd);
5789 case WM_LBUTTONDBLCLK:
5790 return LISTVIEW_LButtonDblClk(hwnd, (WORD)wParam, LOWORD(lParam),
5791 HIWORD(lParam));
5793 case WM_LBUTTONDOWN:
5794 return LISTVIEW_LButtonDown(hwnd, (WORD)wParam, LOWORD(lParam),
5795 HIWORD(lParam));
5796 case WM_LBUTTONUP:
5797 return LISTVIEW_LButtonUp(hwnd, (WORD)wParam, LOWORD(lParam),
5798 HIWORD(lParam));
5800 /* case WM_MOUSEMOVE: */
5801 /* return LISTVIEW_MouseMove (hwnd, wParam, lParam); */
5803 case WM_NCCREATE:
5804 return LISTVIEW_NCCreate(hwnd, wParam, lParam);
5806 case WM_NCDESTROY:
5807 return LISTVIEW_NCDestroy(hwnd);
5809 case WM_NOTIFY:
5810 return LISTVIEW_Notify(hwnd, (INT)wParam, (LPNMHDR)lParam);
5812 case WM_NOTIFYFORMAT:
5813 return LISTVIEW_NotifyFormat(hwnd, (HWND)wParam, (INT)lParam);
5815 case WM_PAINT:
5816 return LISTVIEW_Paint(hwnd, (HDC)wParam);
5818 case WM_RBUTTONDBLCLK:
5819 return LISTVIEW_RButtonDblClk(hwnd, (WORD)wParam, LOWORD(lParam),
5820 HIWORD(lParam));
5822 case WM_RBUTTONDOWN:
5823 return LISTVIEW_RButtonDown(hwnd, (WORD)wParam, LOWORD(lParam),
5824 HIWORD(lParam));
5826 case WM_RBUTTONUP:
5827 return LISTVIEW_RButtonUp(hwnd, (WORD)wParam, LOWORD(lParam),
5828 HIWORD(lParam));
5830 case WM_SETFOCUS:
5831 return LISTVIEW_SetFocus(hwnd, (HWND)wParam);
5833 case WM_SETFONT:
5834 return LISTVIEW_SetFont(hwnd, (HFONT)wParam, (WORD)lParam);
5836 /* case WM_SETREDRAW: */
5838 case WM_SIZE:
5839 return LISTVIEW_Size(hwnd, LOWORD(lParam), HIWORD(lParam));
5841 case WM_STYLECHANGED:
5842 return LISTVIEW_StyleChanged(hwnd, wParam, (LPSTYLESTRUCT)lParam);
5844 /* case WM_TIMER: */
5846 case WM_VSCROLL:
5847 return LISTVIEW_VScroll(hwnd, (INT)LOWORD(wParam),
5848 (INT)HIWORD(wParam), (HWND)lParam);
5850 /* case WM_WINDOWPOSCHANGED: */
5851 /* case WM_WININICHANGE: */
5853 default:
5854 if (uMsg >= WM_USER)
5856 ERR(listview, "unknown msg %04x wp=%08x lp=%08lx\n",
5857 uMsg, wParam, lParam);
5860 /* call default window procedure */
5861 return DefWindowProcA(hwnd, uMsg, wParam, lParam);
5864 return 0;
5867 /***
5868 * DESCRIPTION:`
5869 * Registers the window class.
5871 * PARAMETER(S):
5872 * None
5874 * RETURN:
5875 * None
5877 VOID LISTVIEW_Register(VOID)
5879 WNDCLASSA wndClass;
5881 if (!GlobalFindAtomA(WC_LISTVIEWA))
5883 ZeroMemory(&wndClass, sizeof(WNDCLASSA));
5884 wndClass.style = CS_GLOBALCLASS | CS_DBLCLKS;
5885 wndClass.lpfnWndProc = (WNDPROC)LISTVIEW_WindowProc;
5886 wndClass.cbClsExtra = 0;
5887 wndClass.cbWndExtra = sizeof(LISTVIEW_INFO *);
5888 wndClass.hCursor = LoadCursorA(0, IDC_ARROWA);
5889 wndClass.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
5890 wndClass.lpszClassName = WC_LISTVIEWA;
5891 RegisterClassA (&wndClass);
5895 /***
5896 * DESCRIPTION:
5897 * Unregisters the window class.
5899 * PARAMETER(S):
5900 * None
5902 * RETURN:
5903 * None
5905 VOID LISTVIEW_Unregister(VOID)
5907 if (GlobalFindAtomA(WC_LISTVIEWA))
5908 UnregisterClassA(WC_LISTVIEWA, (HINSTANCE)NULL);