Return 32-bit module in GetModuleHandle16() if appropriate.
[wine/testsucceed.git] / dlls / comctl32 / listview.c
blob8835271c2807423d8d33ee0b3724944e292f588a
1 /*
2 * Listview control
4 * Copyright 1998 Eric Kohl
5 * Copyright 1999 Luc Tourangeau
7 * NOTES
8 * Listview control implementation.
10 * TODO:
12 * 1. Multiple selections in icon or small icon display modes DO NOT
13 * behave like the Microsoft control.
14 * 2. No horizontal scrolling when header is larger than the client area.
15 * 3. Implement LVM_FINDITEM for key selections.
16 * 4. Drawing optimizations.
18 * Notifications:
19 * LISTVIEW_Notify : most notifications from children (editbox and header)
21 * Data structure:
22 * LISTVIEW_SortItems : empty stub
23 * LISTVIEW_SetItemCount : empty stub
25 * Unicode:
26 * LISTVIEW_SetItem32W : no unicode support
27 * LISTVIEW_InsertItem32W : no unicode support
28 * LISTVIEW_InsertColumn32W : no unicode support
29 * LISTVIEW_GetColumnW : no unicode support
31 * Advanced functionality:
32 * LISTVIEW_GetNumberOfWorkAreas : not implemented
33 * LISTVIEW_GetNextItem : empty stub
34 * LISTVIEW_GetHotCursor : not implemented
35 * LISTVIEW_GetHotItem : not implemented
36 * LISTVIEW_GetHoverTime : not implemented
37 * LISTVIEW_GetISearchString : not implemented
38 * LISTVIEW_GetBkImage : not implemented
39 * LISTVIEW_EditLabel : REPORT (need to implement a timer)
40 * LISTVIEW_GetColumnOrderArray : not implemented
41 * LISTVIEW_Arrange : empty stub
42 * LISTVIEW_FindItem : empty stub
43 * LISTVIEW_ApproximateViewRect : incomplete
44 * LISTVIEW_Scroll : not implemented
45 * LISTVIEW_KeyDown : page up and page down + redo small icon and icon
46 * LISTVIEW_RedrawItems : empty stub
47 * LISTVIEW_Update : not completed
50 #include <string.h>
51 #include "winbase.h"
52 #include "commctrl.h"
53 #include "listview.h"
54 #include "debug.h"
56 DEFAULT_DEBUG_CHANNEL(listview)
59 * constants
62 /* maximum size of a label */
63 #define DISP_TEXT_SIZE 128
65 /* padding for items in list and small icon display modes */
66 #define WIDTH_PADDING 12
68 /* padding for items in list, report and small icon display modes */
69 #define HEIGHT_PADDING 1
71 /* offset of items in report display mode */
72 #define REPORT_MARGINX 2
74 /* padding for icon in large icon display mode */
75 #define ICON_TOP_PADDING 2
76 #define ICON_BOTTOM_PADDING 2
78 /* padding for label in large icon display mode */
79 #define LABEL_VERT_OFFSET 2
81 /* default label width for items in list and small icon display modes */
82 #define DEFAULT_LABEL_WIDTH 40
84 /* default column width for items in list display mode */
85 #define DEFAULT_COLUMN_WIDTH 96
87 /*
88 * macros
91 /* retrieve the number of items in the listview */
92 #define GETITEMCOUNT(infoPtr) ((infoPtr)->hdpaItems->nItemCount)
93 #define ListView_LVNotify(hwnd,lCtrlId,plvnm) \
94 (BOOL)SendMessageA((hwnd),WM_NOTIFY,(WPARAM)(INT)lCtrlId,(LPARAM)(LPNMLISTVIEW)(plvnm))
95 #define ListView_Notify(hwnd,lCtrlId,pnmh) \
96 (BOOL)SendMessageA((hwnd),WM_NOTIFY,(WPARAM)(INT)lCtrlId,(LPARAM)(LPNMHDR)(pnmh))
98 /*
99 * forward declarations
102 static VOID LISTVIEW_AlignLeft(HWND);
103 static VOID LISTVIEW_AlignTop(HWND);
104 static VOID LISTVIEW_AddGroupSelection(HWND, INT);
105 static VOID LISTVIEW_AddSelection(HWND, INT);
106 static BOOL LISTVIEW_AddSubItem(HWND, LPLVITEMA);
107 static INT LISTVIEW_FindInsertPosition(HDPA, INT);
108 static VOID LISTVIEW_GetItemDispInfo(HWND, INT, LISTVIEW_ITEM *lpItem, INT *,
109 UINT *, CHAR **, INT);
110 static INT LISTVIEW_GetItemHeight(HWND, LONG);
111 static BOOL LISTVIEW_GetItemPosition(HWND, INT, LPPOINT);
112 static LRESULT LISTVIEW_GetItemRect(HWND, INT, LPRECT);
113 static INT LISTVIEW_GetItemWidth(HWND, LONG);
114 static INT LISTVIEW_GetLabelWidth(HWND, INT);
115 static LRESULT LISTVIEW_GetOrigin(HWND, LPPOINT);
116 static LISTVIEW_SUBITEM* LISTVIEW_GetSubItem(HDPA, INT);
117 static VOID LISTVIEW_GetSubItemDispInfo(HWND hwnd, INT, LPARAM,
118 LISTVIEW_SUBITEM *, INT, INT *,
119 CHAR **, INT);
120 static LRESULT LISTVIEW_GetViewRect(HWND, LPRECT);
121 static BOOL LISTVIEW_InitItem(HWND, LISTVIEW_ITEM *, LPLVITEMA);
122 static BOOL LISTVIEW_InitSubItem(HWND, LISTVIEW_SUBITEM *, LPLVITEMA);
123 static LRESULT LISTVIEW_MouseSelection(HWND, INT, INT);
124 static BOOL LISTVIEW_RemoveColumn(HDPA, INT);
125 static VOID LISTVIEW_RemoveSelections(HWND, INT, INT);
126 static BOOL LISTVIEW_RemoveSubItem(HDPA, INT);
127 static BOOL LISTVIEW_ScrollView(HWND, INT, INT);
128 static VOID LISTVIEW_SetGroupSelection(HWND, INT);
129 static BOOL LISTVIEW_SetItem(HWND, LPLVITEMA);
130 static VOID LISTVIEW_SetItemFocus(HWND, INT);
131 static BOOL LISTVIEW_SetItemPosition(HWND, INT, INT, INT);
132 static VOID LISTVIEW_SetScroll(HWND, LONG);
133 static VOID LISTVIEW_SetSelection(HWND, INT);
134 static VOID LISTVIEW_SetSize(HWND, LONG, LONG, LONG);
135 static BOOL LISTVIEW_SetSubItem(HWND, LPLVITEMA);
136 static VOID LISTVIEW_SetViewInfo(HWND, LONG);
137 static LRESULT LISTVIEW_SetViewRect(HWND, LPRECT);
138 static BOOL LISTVIEW_ToggleSelection(HWND, INT);
139 static VOID LISTVIEW_UnsupportedStyles(LONG lStyle);
141 /***
142 * DESCRIPTION:
143 * Scrolls the content of the listview.
145 * PARAMETER(S):
146 * [I] HWND : window handle
147 * [I] INT : number of horizontal scroll positions
148 * (relative to the current scroll postioon)
149 * [I] INT : number of vertical scroll positions
150 * (relative to the current scroll postioon)
152 * RETURN:
153 * SUCCESS : TRUE
154 * FAILURE : FALSE
156 static BOOL LISTVIEW_ScrollView(HWND hwnd, INT nHScroll, INT nVScroll)
158 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
159 LONG lStyle = GetWindowLongA(hwnd, GWL_STYLE);
160 INT nListWidth = infoPtr->rcList.right - infoPtr->rcList.left;
161 INT nListHeight = infoPtr->rcList.bottom - infoPtr->rcList.top;
162 INT nHScrollPos = 0;
163 INT nVScrollPos = 0;
164 INT nHScrollInc = 0;
165 INT nVScrollInc = 0;
166 BOOL bResult = FALSE;
168 if (((lStyle & WS_HSCROLL) != 0) && (nHScroll != 0))
170 switch (LVS_TYPEMASK & lStyle)
172 case LVS_LIST:
173 nHScrollInc = nHScroll * infoPtr->nItemWidth;
174 break;
176 case LVS_REPORT:
177 /* TO DO : not implemented at this point. I experiences some
178 problems when performing child window scrolling. */
179 break;
181 case LVS_SMALLICON:
182 case LVS_ICON:
183 nHScrollInc = nHScroll * max(nListWidth, nListWidth / 10);
184 break;
187 nHScrollPos = GetScrollPos(hwnd, SB_HORZ) + nHScroll;
190 if (((lStyle & WS_VSCROLL) != 0) & (nVScroll != 0))
192 switch (LVS_TYPEMASK & lStyle)
194 case LVS_REPORT:
195 nVScrollInc = nVScroll * infoPtr->nItemHeight;
196 nVScrollPos = GetScrollPos(hwnd, SB_VERT) + nVScroll;
197 break;
199 case LVS_SMALLICON:
200 case LVS_ICON:
201 nVScrollInc = nVScroll * max(nListHeight, nListHeight / 10);
202 nVScrollPos = GetScrollPos(hwnd, SB_VERT) + nVScroll;
203 break;
207 /* perform scroll operation & set new scroll position */
208 if ((nHScrollInc != 0) || (nVScrollInc != 0))
210 RECT rc;
211 HDC hdc = GetDC(hwnd);
212 ScrollDC(hdc, -nHScrollInc, -nVScrollInc, &infoPtr->rcList, NULL,
213 (HRGN) NULL, &rc);
214 InvalidateRect(hwnd, &rc, TRUE);
215 SetScrollPos(hwnd, SB_HORZ, nHScrollPos, TRUE);
216 SetScrollPos(hwnd, SB_VERT, nVScrollPos, TRUE);
217 ReleaseDC(hwnd, hdc);
218 bResult = TRUE;
221 return bResult;
224 /***
225 * DESCRIPTION:
226 * Prints a message for unsupported window styles.
227 * A kind of TODO list for window styles.
229 * PARAMETER(S):
230 * [I] LONG : window style
232 * RETURN:
233 * None
235 static VOID LISTVIEW_UnsupportedStyles(LONG lStyle)
237 if ((LVS_TYPEMASK & lStyle) == LVS_EDITLABELS)
239 FIXME( listview, " LVS_EDITLABELS\n");
242 if ((LVS_TYPEMASK & lStyle) == LVS_NOCOLUMNHEADER)
244 FIXME( listview, " LVS_SORTDESCENDING\n");
247 if ((LVS_TYPEMASK & lStyle) == LVS_NOLABELWRAP)
249 FIXME( listview, " LVS_NOLABELWRAP\n");
252 if ((LVS_TYPEMASK & lStyle) == LVS_NOSCROLL)
254 FIXME( listview, " LVS_NOSCROLL\n");
257 if ((LVS_TYPEMASK & lStyle) == LVS_NOSORTHEADER)
259 FIXME( listview, " LVS_NOSORTHEADER\n");
262 if ((LVS_TYPEMASK & lStyle) == LVS_OWNERDRAWFIXED)
264 FIXME( listview, " LVS_OWNERDRAWFIXED\n");
267 if ((LVS_TYPEMASK & lStyle) == LVS_SHAREIMAGELISTS)
269 FIXME( listview, " LVS_SHAREIMAGELISTS\n");
272 if ((LVS_TYPEMASK & lStyle) == LVS_SHOWSELALWAYS)
274 FIXME( listview, " LVS_SHOWSELALWAYS\n");
277 if ((LVS_TYPEMASK & lStyle) == LVS_SINGLESEL)
279 FIXME( listview, " LVS_SINGLESEL\n");
282 if ((LVS_TYPEMASK & lStyle) == LVS_SORTASCENDING)
284 FIXME( listview, " LVS_SORTASCENDING\n");
287 if ((LVS_TYPEMASK & lStyle) == LVS_SORTDESCENDING)
289 FIXME( listview, " LVS_SORTDESCENDING\n");
293 /***
294 * DESCRIPTION:
295 * Aligns the items with the top edge of the window.
297 * PARAMETER(S):
298 * [I] HWND : window handle
300 * RETURN:
301 * None
303 static VOID LISTVIEW_AlignTop(HWND hwnd)
305 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
306 LONG lStyle = GetWindowLongA(hwnd, GWL_STYLE);
307 INT nListWidth = infoPtr->rcList.right - infoPtr->rcList.left;
308 POINT ptItem;
309 RECT rcView;
310 INT i;
312 switch (LVS_TYPEMASK & lStyle)
314 case LVS_SMALLICON:
315 case LVS_ICON:
316 ZeroMemory(&ptItem, sizeof(POINT));
317 ZeroMemory(&rcView, sizeof(RECT));
318 if (nListWidth > infoPtr->nItemWidth)
320 for (i = 0; i < GETITEMCOUNT(infoPtr); i++)
322 if (ptItem.x + infoPtr->nItemWidth > nListWidth)
324 ptItem.x = 0;
325 ptItem.y += infoPtr->nItemHeight;
328 LISTVIEW_SetItemPosition(hwnd, i, ptItem.x, ptItem.y);
329 ptItem.x += infoPtr->nItemWidth;
330 rcView.right = max(rcView.right, ptItem.x);
333 else
335 for (i = 0; i < GETITEMCOUNT(infoPtr); i++)
337 LISTVIEW_SetItemPosition(hwnd, i, ptItem.x, ptItem.y);
338 ptItem.x += infoPtr->nItemWidth;
340 rcView.right = ptItem.x;
341 rcView.bottom = infoPtr->nItemHeight;
344 rcView.bottom = ptItem.y + infoPtr->nItemHeight;
345 LISTVIEW_SetViewRect(hwnd, &rcView);
349 /***
350 * DESCRIPTION:
351 * Aligns the items with the left edge of the window.
353 * PARAMETER(S):
354 * [I] HWND : window handle
356 * RETURN:
357 * None
359 static VOID LISTVIEW_AlignLeft(HWND hwnd)
361 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
362 LONG lStyle = GetWindowLongA(hwnd, GWL_STYLE);
363 INT nListHeight = infoPtr->rcList.bottom - infoPtr->rcList.top;
364 POINT ptItem;
365 RECT rcView;
366 INT i;
368 switch (LVS_TYPEMASK & lStyle)
370 case LVS_SMALLICON:
371 case LVS_ICON:
372 ZeroMemory(&ptItem, sizeof(POINT));
373 ZeroMemory(&rcView, sizeof(RECT));
374 if (nListHeight > infoPtr->nItemHeight)
376 for (i = 0; i < GETITEMCOUNT(infoPtr); i++)
378 if (ptItem.y + infoPtr->nItemHeight > nListHeight)
380 ptItem.y = 0;
381 ptItem.x += infoPtr->nItemWidth;
384 LISTVIEW_SetItemPosition(hwnd, i, ptItem.x, ptItem.y);
385 ptItem.y += infoPtr->nItemHeight;
386 rcView.bottom = max(rcView.bottom, ptItem.y);
389 else
391 for (i = 0; i < GETITEMCOUNT(infoPtr); i++)
393 LISTVIEW_SetItemPosition(hwnd, i, ptItem.x, ptItem.y);
394 ptItem.y += infoPtr->nItemHeight;
396 rcView.bottom = ptItem.y;
397 rcView.right = infoPtr->nItemWidth;
400 rcView.right = ptItem.x + infoPtr->nItemWidth;
401 LISTVIEW_SetViewRect(hwnd, &rcView);
402 break;
406 /***
407 * DESCRIPTION:
408 * Retrieves display information.
410 * PARAMETER(S):
411 * [I] HWND : window handle
412 * [I] INT : item index
413 * [I] LISTVIEW_ITEM* : listview control item
414 * [O] INT : image index
415 * [O] UINT : state value
416 * [O] CHAR** : string
417 * [I] INT : size of string
419 * RETURN:
420 * None
422 static VOID LISTVIEW_GetItemDispInfo(HWND hwnd, INT nItem,
423 LISTVIEW_ITEM *lpItem, INT *pnDispImage,
424 UINT *puState, CHAR **ppszDispText,
425 INT nDispTextSize)
427 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
428 LONG lCtrlId = GetWindowLongA(hwnd, GWL_ID);
429 NMLVDISPINFOA dispInfo;
430 ZeroMemory(&dispInfo, sizeof(NMLVDISPINFOA));
432 if ((pnDispImage != NULL) && (lpItem->iImage == I_IMAGECALLBACK))
434 dispInfo.item.mask |= LVIF_IMAGE;
437 if ((ppszDispText != NULL) && (lpItem->pszText == LPSTR_TEXTCALLBACKA))
439 ZeroMemory(*ppszDispText, sizeof(CHAR)*nDispTextSize);
440 dispInfo.item.mask |= LVIF_TEXT;
441 dispInfo.item.pszText = *ppszDispText;
442 dispInfo.item.cchTextMax = nDispTextSize;
445 if ((puState != NULL) && (infoPtr->uCallbackMask != 0))
447 dispInfo.item.mask |= LVIF_STATE;
448 dispInfo.item.stateMask = infoPtr->uCallbackMask;
451 if (dispInfo.item.mask != 0)
453 dispInfo.hdr.hwndFrom = hwnd;
454 dispInfo.hdr.idFrom = lCtrlId;
455 dispInfo.hdr.code = LVN_GETDISPINFOA;
456 dispInfo.item.iItem = nItem;
457 dispInfo.item.iSubItem = 0;
458 dispInfo.item.lParam = lpItem->lParam;
459 ListView_Notify(GetParent(hwnd), lCtrlId, &dispInfo);
462 if (pnDispImage != NULL)
464 if (dispInfo.item.mask & LVIF_IMAGE)
466 *pnDispImage = dispInfo.item.iImage;
468 else
470 *pnDispImage = lpItem->iImage;
474 if (ppszDispText != NULL)
476 if (dispInfo.item.mask & LVIF_TEXT)
478 if (dispInfo.item.mask & LVIF_DI_SETITEM)
480 Str_SetPtrA(&lpItem->pszText, dispInfo.item.pszText);
482 *ppszDispText = dispInfo.item.pszText;
484 else
486 *ppszDispText = lpItem->pszText;
490 if (puState != NULL)
492 if (dispInfo.item.mask & LVIF_STATE)
494 *puState = lpItem->state;
495 *puState &= ~dispInfo.item.stateMask;
496 *puState |= (dispInfo.item.state & dispInfo.item.stateMask);
498 else
500 *puState = lpItem->state;
505 /***
506 * DESCRIPTION:
507 * Retrieves subitem display information.
509 * PARAMETER(S):
510 * [I] HWND : window handle
511 * [I] INT : item index
512 * [I] LONG : LPARAM of item
513 * [I] LISTVIEW_SUBITEM* : listview control subitem
514 * [I] INT : subitem position/order
515 * [O] INT : image index
516 * [O] UINT : state value
517 * [O] CHAR** : display string
518 * [I] INT : size of string
520 * RETURN:
521 * None
523 static VOID LISTVIEW_GetSubItemDispInfo(HWND hwnd, INT nItem, LPARAM lParam,
524 LISTVIEW_SUBITEM *lpSubItem,
525 INT nSubItemPos, INT *pnDispImage,
526 CHAR **ppszDispText, INT nDispTextSize)
528 LONG lCtrlId = GetWindowLongA(hwnd, GWL_ID);
529 NMLVDISPINFOA dispInfo;
530 ZeroMemory(&dispInfo, sizeof(NMLVDISPINFOA));
532 if (lpSubItem == NULL)
534 ZeroMemory(*ppszDispText, sizeof(CHAR)*nDispTextSize);
535 dispInfo.item.mask |= LVIF_TEXT;
536 dispInfo.item.pszText = *ppszDispText;
537 dispInfo.item.cchTextMax = nDispTextSize;
538 dispInfo.hdr.hwndFrom = hwnd;
539 dispInfo.hdr.idFrom = lCtrlId;
540 dispInfo.hdr.code = LVN_GETDISPINFOA;
541 dispInfo.item.iItem = nItem;
542 dispInfo.item.iSubItem = nSubItemPos;
543 dispInfo.item.lParam = lParam;
544 ListView_Notify(GetParent(hwnd), lCtrlId, &dispInfo);
545 if (dispInfo.item.mask & LVIF_DI_SETITEM)
547 Str_SetPtrA(&lpSubItem->pszText, dispInfo.item.pszText);
549 *ppszDispText = dispInfo.item.pszText;
551 else
553 if ((pnDispImage != NULL) && (lpSubItem->iImage == I_IMAGECALLBACK))
555 dispInfo.item.mask |= LVIF_IMAGE;
558 if ((ppszDispText != NULL) && (lpSubItem->pszText == LPSTR_TEXTCALLBACKA))
560 ZeroMemory(*ppszDispText, sizeof(CHAR)*nDispTextSize);
561 dispInfo.item.mask |= LVIF_TEXT;
562 dispInfo.item.pszText = *ppszDispText;
563 dispInfo.item.cchTextMax = nDispTextSize;
566 if (dispInfo.item.mask != 0)
568 dispInfo.hdr.hwndFrom = hwnd;
569 dispInfo.hdr.idFrom = lCtrlId;
570 dispInfo.hdr.code = LVN_GETDISPINFOA;
571 dispInfo.item.iItem = nItem;
572 dispInfo.item.iSubItem = lpSubItem->iSubItem;
573 dispInfo.item.lParam = lParam;
574 ListView_Notify(GetParent(hwnd), lCtrlId, &dispInfo);
577 if (pnDispImage != NULL)
579 if (dispInfo.item.mask & LVIF_IMAGE)
581 *pnDispImage = dispInfo.item.iImage;
583 else
585 *pnDispImage = lpSubItem->iImage;
589 if (ppszDispText != NULL)
591 if (dispInfo.item.mask & LVIF_TEXT)
593 if (dispInfo.item.mask & LVIF_DI_SETITEM)
595 Str_SetPtrA(&lpSubItem->pszText, dispInfo.item.pszText);
597 *ppszDispText = dispInfo.item.pszText;
599 else
601 *ppszDispText = lpSubItem->pszText;
607 /***
608 * DESCRIPTION:
609 * Calculates the width of an item.
611 * PARAMETER(S):
612 * [I] HWND : window handle
613 * [I] LONG : window style
615 * RETURN:
616 * Returns item width.
618 static INT LISTVIEW_GetItemWidth(HWND hwnd, LONG lStyle)
620 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
621 INT nHeaderItemCount;
622 RECT rcHeaderItem;
623 INT nItemWidth = 0;
624 INT nLabelWidth;
625 INT i;
627 TRACE(listview, "(hwnd=%x,lStyle=%lx)\n", hwnd, lStyle);
629 switch (LVS_TYPEMASK & lStyle)
631 case LVS_ICON:
632 nItemWidth = infoPtr->iconSpacing.cx;
633 break;
635 case LVS_REPORT:
636 /* calculate width of header */
637 nHeaderItemCount = Header_GetItemCount(infoPtr->hwndHeader);
638 for (i = 0; i < nHeaderItemCount; i++)
640 if (Header_GetItemRect(infoPtr->hwndHeader, i, &rcHeaderItem) != 0)
642 nItemWidth += (rcHeaderItem.right - rcHeaderItem.left);
645 break;
647 case LVS_SMALLICON:
648 case LVS_LIST:
649 for (i = 0; i < GETITEMCOUNT(infoPtr); i++)
651 nLabelWidth = LISTVIEW_GetLabelWidth(hwnd, i);
652 nItemWidth = max(nItemWidth, nLabelWidth);
655 /* default label size */
656 if (GETITEMCOUNT(infoPtr) == 0)
658 nItemWidth = DEFAULT_COLUMN_WIDTH;
660 else
662 if (nItemWidth == 0)
664 nItemWidth = DEFAULT_LABEL_WIDTH;
666 else
668 /* add padding */
669 nItemWidth += WIDTH_PADDING;
671 if (infoPtr->himlSmall != NULL)
673 nItemWidth += infoPtr->iconSize.cx;
676 if (infoPtr->himlState != NULL)
678 nItemWidth += infoPtr->iconSize.cx;
682 break;
686 return nItemWidth;
689 /***
690 * DESCRIPTION:
691 * Calculates the height of an item.
693 * PARAMETER(S):
694 * [I] HWND : window handle
695 * [I] LONG : window style
697 * RETURN:
698 * Returns item width.
700 static INT LISTVIEW_GetItemHeight(HWND hwnd, LONG lStyle)
702 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
703 INT nItemHeight = 0;
704 TEXTMETRICA tm;
705 HFONT hOldFont;
706 HDC hdc;
708 switch (LVS_TYPEMASK & lStyle)
710 case LVS_ICON:
711 nItemHeight = infoPtr->iconSpacing.cy;
712 break;
714 case LVS_SMALLICON:
715 case LVS_REPORT:
716 case LVS_LIST:
717 hdc = GetDC(hwnd);
718 hOldFont = SelectObject(hdc, infoPtr->hFont);
719 GetTextMetricsA(hdc, &tm);
720 nItemHeight = max(tm.tmHeight, infoPtr->iconSize.cy) + HEIGHT_PADDING;
721 SelectObject(hdc, hOldFont);
722 ReleaseDC(hwnd, hdc);
723 break;
726 return nItemHeight;
729 /***
730 * DESCRIPTION:
731 * Sets diplay information (needed for drawing operations).
733 * PARAMETER(S):
734 * [I] HWND : window handle
736 * RETURN:
737 * None
739 static VOID LISTVIEW_SetViewInfo(HWND hwnd, LONG lStyle)
741 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
742 INT nListHeight = infoPtr->rcList.bottom - infoPtr->rcList.top;
743 INT nListWidth = infoPtr->rcList.right - infoPtr->rcList.left;
745 switch (LVS_TYPEMASK & lStyle)
747 case LVS_REPORT:
748 /* get number of fully visible items per column */
749 infoPtr->nCountPerColumn = max(1, nListHeight / infoPtr->nItemHeight);
750 break;
752 case LVS_LIST:
753 /* get number of fully visible items per column */
754 infoPtr->nCountPerColumn = max(1, nListHeight / infoPtr->nItemHeight);
756 /* get number of fully visible items per row */
757 infoPtr->nCountPerRow = max(1, nListWidth / infoPtr->nItemWidth);
758 break;
762 /***
763 * DESCRIPTION:
764 * Adds a block of selections.
766 * PARAMETER(S):
767 * [I] HWND : window handle
768 * [I] INT : item index
770 * RETURN:
771 * None
773 static VOID LISTVIEW_AddGroupSelection(HWND hwnd, INT nItem)
775 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
776 INT nFirst = min(infoPtr->nSelectionMark, nItem);
777 INT nLast = max(infoPtr->nSelectionMark, nItem);
778 LVITEMA lvItem;
779 INT i;
781 lvItem.state = LVIS_SELECTED;
782 lvItem.stateMask= LVIS_SELECTED;
784 for (i = nFirst; i <= nLast; i++)
786 ListView_SetItemState(hwnd, i, &lvItem);
789 LISTVIEW_SetItemFocus(hwnd, nItem);
790 infoPtr->nSelectionMark = nItem;
793 /***
794 * DESCRIPTION:
795 * Adds a single selection.
797 * PARAMETER(S):
798 * [I] HWND : window handle
799 * [I] INT : item index
801 * RETURN:
802 * None
804 static VOID LISTVIEW_AddSelection(HWND hwnd, INT nItem)
806 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
807 LVITEMA lvItem;
809 lvItem.state = LVIS_SELECTED;
810 lvItem.stateMask= LVIS_SELECTED;
812 ListView_SetItemState(hwnd, nItem, &lvItem);
814 LISTVIEW_SetItemFocus(hwnd, nItem);
815 infoPtr->nSelectionMark = nItem;
818 /***
819 * DESCRIPTION:
820 * Selects or unselects an item.
822 * PARAMETER(S):
823 * [I] HWND : window handle
824 * [I] INT : item index
826 * RETURN:
827 * SELECT: TRUE
828 * UNSELECT : FALSE
830 static BOOL LISTVIEW_ToggleSelection(HWND hwnd, INT nItem)
832 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
833 BOOL bResult;
834 LVITEMA lvItem;
836 lvItem.stateMask= LVIS_SELECTED;
838 if (ListView_GetItemState(hwnd, nItem, LVIS_SELECTED) & LVIS_SELECTED)
840 lvItem.state = 0;
841 ListView_SetItemState(hwnd, nItem, &lvItem);
842 bResult = FALSE;
844 else
846 lvItem.state = LVIS_SELECTED;
847 ListView_SetItemState(hwnd, nItem, &lvItem);
848 bResult = TRUE;
851 LISTVIEW_SetItemFocus(hwnd, nItem);
852 infoPtr->nSelectionMark = nItem;
854 return bResult;
857 /***
858 * DESCRIPTION:
859 * Sets a single group selection.
861 * PARAMETER(S):
862 * [I] HWND : window handle
863 * [I] INT : item index
865 * RETURN:
866 * None
868 static VOID LISTVIEW_SetGroupSelection(HWND hwnd, INT nItem)
870 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
871 INT nFirst = min(infoPtr->nSelectionMark, nItem);
872 INT nLast = max(infoPtr->nSelectionMark, nItem);
873 LVITEMA lvItem;
874 INT i;
876 if (nFirst > 0)
878 LISTVIEW_RemoveSelections(hwnd, 0, nFirst - 1);
881 if (nLast < GETITEMCOUNT(infoPtr))
883 LISTVIEW_RemoveSelections(hwnd, nLast + 1, GETITEMCOUNT(infoPtr));
886 lvItem.state = LVIS_SELECTED;
887 lvItem.stateMask = LVIS_SELECTED;
889 for (i = nFirst; i <= nLast; i++)
891 ListView_SetItemState(hwnd, i, &lvItem);
894 LISTVIEW_SetItemFocus(hwnd, nItem);
897 /***
898 * DESCRIPTION:
899 * Manages the item focus.
901 * PARAMETER(S):
902 * [I] HWND : window handle
903 * [I] INT : item index
905 * RETURN:
906 * None
908 static VOID LISTVIEW_SetItemFocus(HWND hwnd, INT nItem)
910 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
911 LVITEMA lvItem;
913 lvItem.state = 0;
914 lvItem.stateMask = LVIS_FOCUSED;
915 ListView_SetItemState(hwnd, infoPtr->nFocusedItem, &lvItem);
917 lvItem.state = LVIS_FOCUSED;
918 lvItem.stateMask = LVIS_FOCUSED;
919 ListView_SetItemState(hwnd, nItem, &lvItem);
921 infoPtr->nFocusedItem = nItem;
923 /* if multiple selection is allowed */
924 ListView_EnsureVisible(hwnd, nItem, FALSE);
927 /***
928 * DESCRIPTION:
929 * Sets a single selection.
931 * PARAMETER(S):
932 * [I] HWND : window handle
933 * [I] INT : item index
935 * RETURN:
936 * None
938 static VOID LISTVIEW_SetSelection(HWND hwnd, INT nItem)
940 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
941 LVITEMA lvItem;
943 if (nItem > 0)
945 LISTVIEW_RemoveSelections(hwnd, 0, nItem - 1);
948 if (nItem < GETITEMCOUNT(infoPtr))
950 LISTVIEW_RemoveSelections(hwnd, nItem + 1, GETITEMCOUNT(infoPtr));
953 lvItem.state = 0;
954 lvItem.stateMask = LVIS_FOCUSED;
955 ListView_SetItemState(hwnd, infoPtr->nFocusedItem, &lvItem);
957 lvItem.state = LVIS_SELECTED | LVIS_FOCUSED;
958 lvItem.stateMask = LVIS_SELECTED | LVIS_FOCUSED;
959 ListView_SetItemState(hwnd, nItem, &lvItem);
961 infoPtr->nFocusedItem = nItem;
962 infoPtr->nSelectionMark = nItem;
965 /***
966 * DESCRIPTION:
967 * Set selection(s) with keyboard.
969 * PARAMETER(S):
970 * [I] HWND : window handle
971 * [I] INT : item index
973 * RETURN:
974 * None
976 static VOID LISTVIEW_KeySelection(HWND hwnd, INT nItem)
978 WORD wShift = HIWORD(GetKeyState(VK_SHIFT));
979 WORD wCtrl = HIWORD(GetKeyState(VK_CONTROL));
981 if (wShift)
983 LISTVIEW_SetGroupSelection(hwnd, nItem);
985 else if (wCtrl)
987 LISTVIEW_SetItemFocus(hwnd, nItem);
989 else
991 LISTVIEW_SetSelection(hwnd, nItem);
993 /* if multiple selection is allowed */
994 ListView_EnsureVisible(hwnd, nItem, FALSE);
998 /***
999 * DESCRIPTION:
1000 * Determines the selected item.
1002 * PARAMETER(S):
1003 * [I] HWND : window handle
1004 * [I] INT : x ccordinate
1005 * [I] INT : y coordinate
1007 * RETURN:
1008 * SUCCESS : item index
1009 * FAILURE : -1
1011 static LRESULT LISTVIEW_MouseSelection(HWND hwnd, INT nPosX, INT nPosY)
1013 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
1014 RECT rcItem;
1015 INT i;
1017 for (i = 0; i < GETITEMCOUNT(infoPtr); i++)
1019 rcItem.left = LVIR_SELECTBOUNDS;
1020 if (LISTVIEW_GetItemRect(hwnd, i, &rcItem) == TRUE)
1022 if ((rcItem.left <= nPosX) && (nPosX <= rcItem.right) &&
1023 (rcItem.top <= nPosY) && (nPosY <= rcItem.bottom))
1025 return i;
1030 return -1;
1033 /***
1034 * DESCRIPTION:
1035 * Removes all selection states.
1037 * PARAMETER(S):
1038 * [I] HWND : window handle
1039 * [I] INT : item index
1041 * RETURN:
1042 * SUCCCESS : TRUE
1043 * FAILURE : FALSE
1045 static VOID LISTVIEW_RemoveSelections(HWND hwnd, INT nFirst, INT nLast)
1047 LVITEMA lvItem;
1048 INT i;
1050 lvItem.state = 0;
1051 lvItem.stateMask = LVIS_SELECTED;
1053 for (i = nFirst; i <= nLast; i++)
1055 ListView_SetItemState(hwnd, i, &lvItem);
1059 /***
1060 * DESCRIPTION:
1061 * Removes a column.
1063 * PARAMETER(S):
1064 * [IO] HDPA : dynamic pointer array handle
1065 * [I] INT : column index (subitem index)
1067 * RETURN:
1068 * SUCCCESS : TRUE
1069 * FAILURE : FALSE
1071 static BOOL LISTVIEW_RemoveColumn(HDPA hdpaItems, INT nSubItem)
1073 BOOL bResult = TRUE;
1074 HDPA hdpaSubItems;
1075 INT i;
1077 for (i = 0; i < hdpaItems->nItemCount; i++)
1079 hdpaSubItems = (HDPA)DPA_GetPtr(hdpaItems, i);
1080 if (hdpaSubItems != NULL)
1082 if (LISTVIEW_RemoveSubItem(hdpaSubItems, nSubItem) == FALSE)
1084 bResult = FALSE;
1089 return bResult;
1092 /***
1093 * DESCRIPTION:
1094 * Removes a subitem at a given position.
1096 * PARAMETER(S):
1097 * [IO] HDPA : dynamic pointer array handle
1098 * [I] INT : subitem index
1100 * RETURN:
1101 * SUCCCESS : TRUE
1102 * FAILURE : FALSE
1104 static BOOL LISTVIEW_RemoveSubItem(HDPA hdpaSubItems, INT nSubItem)
1106 LISTVIEW_SUBITEM *lpSubItem;
1107 INT i;
1109 for (i = 1; i < hdpaSubItems->nItemCount; i++)
1111 lpSubItem = (LISTVIEW_SUBITEM *)DPA_GetPtr(hdpaSubItems, i);
1112 if (lpSubItem != NULL)
1114 if (lpSubItem->iSubItem == nSubItem)
1116 /* free string */
1117 if ((lpSubItem->pszText != NULL) &&
1118 (lpSubItem->pszText != LPSTR_TEXTCALLBACKA))
1120 COMCTL32_Free(lpSubItem->pszText);
1123 /* free item */
1124 COMCTL32_Free(lpSubItem);
1126 /* free dpa memory */
1127 if (DPA_DeletePtr(hdpaSubItems, i) == NULL)
1129 return FALSE;
1132 else if (lpSubItem->iSubItem > nSubItem)
1134 return TRUE;
1139 return TRUE;
1142 /***
1143 * DESCRIPTION:
1144 * Compares the item information.
1146 * PARAMETER(S):
1147 * [I] LISTVIEW_ITEM *: destination item
1148 * [I] LPLVITEM : source item
1150 * RETURN:
1151 * SUCCCESS : TRUE (EQUAL)
1152 * FAILURE : FALSE (NOT EQUAL)
1154 static UINT LISTVIEW_GetItemChanges(LISTVIEW_ITEM *lpItem, LPLVITEMA lpLVItem)
1156 UINT uChanged = 0;
1158 if ((lpItem != NULL) && (lpLVItem != NULL))
1160 if (lpLVItem->mask & LVIF_STATE)
1162 if ((lpItem->state & lpLVItem->stateMask) !=
1163 (lpLVItem->state & lpLVItem->stateMask))
1165 uChanged |= LVIF_STATE;
1169 if (lpLVItem->mask & LVIF_IMAGE)
1171 if (lpItem->iImage != lpLVItem->iImage)
1173 uChanged |= LVIF_IMAGE;
1177 if (lpLVItem->mask & LVIF_PARAM)
1179 if (lpItem->lParam != lpLVItem->lParam)
1181 uChanged |= LVIF_PARAM;
1185 if (lpLVItem->mask & LVIF_INDENT)
1187 if (lpItem->iIndent != lpLVItem->iIndent)
1189 uChanged |= LVIF_INDENT;
1193 if (lpLVItem->mask & LVIF_TEXT)
1195 if (lpLVItem->pszText == LPSTR_TEXTCALLBACKA)
1197 if (lpItem->pszText != LPSTR_TEXTCALLBACKA)
1199 uChanged |= LVIF_TEXT;
1202 else
1204 if (lpItem->pszText == LPSTR_TEXTCALLBACKA)
1206 uChanged |= LVIF_TEXT;
1212 return uChanged;
1215 /***
1216 * DESCRIPTION:
1217 * Initializes item attributes.
1219 * PARAMETER(S):
1220 * [I] HWND : window handle
1221 * [O] LISTVIEW_ITEM *: destination item
1222 * [I] LPLVITEM : source item
1224 * RETURN:
1225 * SUCCCESS : TRUE
1226 * FAILURE : FALSE
1228 static BOOL LISTVIEW_InitItem(HWND hwnd, LISTVIEW_ITEM *lpItem,
1229 LPLVITEMA lpLVItem)
1231 LONG lStyle = GetWindowLongA(hwnd, GWL_STYLE);
1232 BOOL bResult = FALSE;
1234 if ((lpItem != NULL) && (lpLVItem != NULL))
1236 bResult = TRUE;
1238 if (lpLVItem->mask & LVIF_STATE)
1240 lpItem->state &= ~lpLVItem->stateMask;
1241 lpItem->state |= (lpLVItem->state & lpLVItem->stateMask);
1244 if (lpLVItem->mask & LVIF_IMAGE)
1246 lpItem->iImage = lpLVItem->iImage;
1249 if (lpLVItem->mask & LVIF_PARAM)
1251 lpItem->lParam = lpLVItem->lParam;
1254 if (lpLVItem->mask & LVIF_INDENT)
1256 lpItem->iIndent = lpLVItem->iIndent;
1259 if (lpLVItem->mask & LVIF_TEXT)
1261 if (lpLVItem->pszText == LPSTR_TEXTCALLBACKA)
1263 if ((lStyle & LVS_SORTASCENDING) || (lStyle & LVS_SORTDESCENDING))
1265 return FALSE;
1268 if ((lpItem->pszText != NULL) &&
1269 (lpItem->pszText != LPSTR_TEXTCALLBACKA))
1271 COMCTL32_Free(lpItem->pszText);
1274 lpItem->pszText = LPSTR_TEXTCALLBACKA;
1276 else
1278 if (lpItem->pszText == LPSTR_TEXTCALLBACKA)
1280 lpItem->pszText = NULL;
1283 bResult = Str_SetPtrA(&lpItem->pszText, lpLVItem->pszText);
1288 return bResult;
1291 /***
1292 * DESCRIPTION:
1293 * Initializes subitem attributes.
1295 * NOTE: the documentation specifies that the operation fails if the user
1296 * tries to set the indent of a subitem.
1298 * PARAMETER(S):
1299 * [I] HWND : window handle
1300 * [O] LISTVIEW_SUBITEM *: destination subitem
1301 * [I] LPLVITEM : source subitem
1303 * RETURN:
1304 * SUCCCESS : TRUE
1305 * FAILURE : FALSE
1307 static BOOL LISTVIEW_InitSubItem(HWND hwnd, LISTVIEW_SUBITEM *lpSubItem,
1308 LPLVITEMA lpLVItem)
1310 LONG lStyle = GetWindowLongA(hwnd, GWL_STYLE);
1311 BOOL bResult = FALSE;
1313 if ((lpSubItem != NULL) && (lpLVItem != NULL))
1315 if (!(lpLVItem->mask & LVIF_INDENT))
1317 bResult = TRUE;
1318 ZeroMemory(lpSubItem, sizeof(LISTVIEW_SUBITEM));
1320 lpSubItem->iSubItem = lpLVItem->iSubItem;
1322 if (lpLVItem->mask & LVIF_IMAGE)
1324 lpSubItem->iImage = lpLVItem->iImage;
1327 if (lpLVItem->mask & LVIF_TEXT)
1329 if (lpLVItem->pszText == LPSTR_TEXTCALLBACKA)
1331 if ((lStyle & LVS_SORTASCENDING) || (lStyle & LVS_SORTDESCENDING))
1333 return FALSE;
1336 if ((lpSubItem->pszText != NULL) &&
1337 (lpSubItem->pszText != LPSTR_TEXTCALLBACKA))
1339 COMCTL32_Free(lpSubItem->pszText);
1342 lpSubItem->pszText = LPSTR_TEXTCALLBACKA;
1344 else
1346 if (lpSubItem->pszText == LPSTR_TEXTCALLBACKA)
1348 lpSubItem->pszText = NULL;
1351 bResult = Str_SetPtrA(&lpSubItem->pszText, lpLVItem->pszText);
1357 return bResult;
1360 /***
1361 * DESCRIPTION:
1362 * Adds a subitem at a given position (column index).
1364 * PARAMETER(S):
1365 * [I] HWND : window handle
1366 * [I] LPLVITEM : new subitem atttributes
1368 * RETURN:
1369 * SUCCESS : TRUE
1370 * FAILURE : FALSE
1372 static BOOL LISTVIEW_AddSubItem(HWND hwnd, LPLVITEMA lpLVItem)
1374 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
1375 LISTVIEW_SUBITEM *lpSubItem = NULL;
1376 BOOL bResult = FALSE;
1377 HDPA hdpaSubItems;
1378 INT nPosition, nItem;
1380 if (lpLVItem != NULL)
1382 hdpaSubItems = (HDPA)DPA_GetPtr(infoPtr->hdpaItems, lpLVItem->iItem);
1383 if (hdpaSubItems != NULL)
1385 lpSubItem = (LISTVIEW_SUBITEM *)COMCTL32_Alloc(sizeof(LISTVIEW_SUBITEM));
1386 if (lpSubItem != NULL)
1388 if (LISTVIEW_InitSubItem(hwnd, lpSubItem, lpLVItem) != FALSE)
1390 nPosition = LISTVIEW_FindInsertPosition(hdpaSubItems,
1391 lpSubItem->iSubItem);
1392 nItem = DPA_InsertPtr(hdpaSubItems, nPosition, lpSubItem);
1393 if (nItem != -1)
1395 bResult = TRUE;
1402 /* cleanup if unsuccessful */
1403 if ((bResult == FALSE) && (lpSubItem != NULL))
1405 COMCTL32_Free(lpSubItem);
1408 return bResult;
1411 /***
1412 * DESCRIPTION:
1413 * Finds the dpa insert position (array index).
1415 * PARAMETER(S):
1416 * [I] HWND : window handle
1417 * [I] INT : subitem index
1419 * RETURN:
1420 * SUCCESS : TRUE
1421 * FAILURE : FALSE
1423 static INT LISTVIEW_FindInsertPosition(HDPA hdpaSubItems, INT nSubItem)
1425 LISTVIEW_SUBITEM *lpSubItem;
1426 INT i;
1428 for (i = 1; i < hdpaSubItems->nItemCount; i++)
1430 lpSubItem = (LISTVIEW_SUBITEM *)DPA_GetPtr(hdpaSubItems, i);
1431 if (lpSubItem != NULL)
1433 if (lpSubItem->iSubItem > nSubItem)
1435 return i;
1440 return hdpaSubItems->nItemCount;
1443 /***
1444 * DESCRIPTION:
1445 * Retrieves a listview subitem at a given position (column index).
1447 * PARAMETER(S):
1448 * [I] HWND : window handle
1449 * [I] INT : subitem index
1451 * RETURN:
1452 * SUCCESS : TRUE
1453 * FAILURE : FALSE
1455 static LISTVIEW_SUBITEM* LISTVIEW_GetSubItem(HDPA hdpaSubItems, INT nSubItem)
1457 LISTVIEW_SUBITEM *lpSubItem;
1458 INT i;
1460 for (i = 1; i < hdpaSubItems->nItemCount; i++)
1462 lpSubItem = (LISTVIEW_SUBITEM *)DPA_GetPtr(hdpaSubItems, i);
1463 if (lpSubItem != NULL)
1465 if (lpSubItem->iSubItem == nSubItem)
1467 return lpSubItem;
1469 else if (lpSubItem->iSubItem > nSubItem)
1471 return NULL;
1476 return NULL;
1479 /***
1480 * DESCRIPTION:
1481 * Sets item attributes.
1483 * PARAMETER(S):
1484 * [I] HWND : window handle
1485 * [I] LPLVITEM : new item atttributes
1487 * RETURN:
1488 * SUCCESS : TRUE
1489 * FAILURE : FALSE
1491 static BOOL LISTVIEW_SetItem(HWND hwnd, LPLVITEMA lpLVItem)
1493 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
1494 BOOL bResult = FALSE;
1495 HDPA hdpaSubItems;
1496 LISTVIEW_ITEM *lpItem;
1497 NMLISTVIEW nmlv;
1498 UINT uChanged;
1499 LONG lCtrlId = GetWindowLongA(hwnd, GWL_ID);
1501 if (lpLVItem != NULL)
1503 if (lpLVItem->iSubItem == 0)
1505 hdpaSubItems = (HDPA)DPA_GetPtr(infoPtr->hdpaItems, lpLVItem->iItem);
1506 if (hdpaSubItems != NULL)
1508 lpItem = (LISTVIEW_ITEM *)DPA_GetPtr(hdpaSubItems, lpLVItem->iSubItem);
1509 if (lpItem != NULL)
1511 ZeroMemory(&nmlv, sizeof(NMLISTVIEW));
1512 nmlv.hdr.hwndFrom = hwnd;
1513 nmlv.hdr.idFrom = lCtrlId;
1514 nmlv.hdr.code = LVN_ITEMCHANGING;
1515 nmlv.lParam = lpItem->lParam;
1516 uChanged = LISTVIEW_GetItemChanges(lpItem, lpLVItem);
1517 if (uChanged != 0)
1519 if (uChanged & LVIF_STATE)
1521 nmlv.uNewState = lpLVItem->state & lpLVItem->stateMask;
1522 nmlv.uOldState = lpItem->state & lpLVItem->stateMask;
1525 nmlv.uChanged = uChanged;
1526 nmlv.iItem = lpLVItem->iItem;
1527 nmlv.lParam = lpItem->lParam;
1528 /* send LVN_ITEMCHANGING notification */
1529 ListView_LVNotify(GetParent(hwnd), lCtrlId, &nmlv);
1531 /* copy information */
1532 bResult = LISTVIEW_InitItem(hwnd, lpItem, lpLVItem);
1534 /* send LVN_ITEMCHANGED notification */
1535 nmlv.hdr.code = LVN_ITEMCHANGED;
1536 ListView_LVNotify(GetParent(hwnd), lCtrlId, &nmlv);
1538 else
1540 bResult = TRUE;
1543 InvalidateRect(hwnd, NULL, FALSE);
1549 return bResult;
1552 /***
1553 * DESCRIPTION:
1554 * Sets subitem attributes.
1556 * PARAMETER(S):
1557 * [I] HWND : window handle
1558 * [I] LPLVITEM : new subitem atttributes
1560 * RETURN:
1561 * SUCCESS : TRUE
1562 * FAILURE : FALSE
1564 static BOOL LISTVIEW_SetSubItem(HWND hwnd, LPLVITEMA lpLVItem)
1566 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
1567 BOOL bResult = FALSE;
1568 HDPA hdpaSubItems;
1569 LISTVIEW_SUBITEM *lpSubItem;
1571 if (lpLVItem != NULL)
1573 if (lpLVItem->iSubItem > 0)
1575 hdpaSubItems = (HDPA)DPA_GetPtr(infoPtr->hdpaItems, lpLVItem->iItem);
1576 if (hdpaSubItems != NULL)
1578 /* set subitem only if column is present */
1579 if (Header_GetItemCount(infoPtr->hwndHeader) > lpLVItem->iSubItem)
1581 lpSubItem = LISTVIEW_GetSubItem(hdpaSubItems, lpLVItem->iSubItem);
1582 if (lpSubItem != NULL)
1584 bResult = LISTVIEW_InitSubItem(hwnd, lpSubItem, lpLVItem);
1586 else
1588 bResult = LISTVIEW_AddSubItem(hwnd, lpLVItem);
1591 InvalidateRect(hwnd, NULL, FALSE);
1597 return bResult;
1600 /***
1601 * DESCRIPTION:
1602 * Retrieves the index of the item at coordinate (0, 0) of the client area.
1604 * PARAMETER(S):
1605 * [I] HWND : window handle
1607 * RETURN:
1608 * item index
1610 static INT LISTVIEW_GetTopIndex(HWND hwnd)
1612 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *) GetWindowLongA(hwnd, 0);
1613 LONG lStyle = GetWindowLongA(hwnd, GWL_STYLE);
1614 INT nItem = 0;
1616 switch (LVS_TYPEMASK & lStyle)
1618 case LVS_LIST:
1619 if (lStyle & WS_HSCROLL)
1621 nItem = GetScrollPos(hwnd, SB_HORZ) * infoPtr->nCountPerColumn;
1623 break;
1625 case LVS_REPORT:
1626 if (lStyle & WS_VSCROLL)
1628 nItem = GetScrollPos(hwnd, SB_VERT);
1630 break;
1633 return nItem;
1636 /***
1637 * DESCRIPTION:
1638 * Evaluates if scrollbars are needed & sets the scroll range/position.
1640 * PARAMETER(S):
1641 * [I] HWND : window handle
1642 * [I] LONG : window style
1644 * RETURN:
1645 * None
1647 static VOID LISTVIEW_SetScroll(HWND hwnd, LONG lStyle)
1649 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
1650 INT nListWidth = infoPtr->rcList.right - infoPtr->rcList.left;
1651 INT nListHeight = infoPtr->rcList.bottom - infoPtr->rcList.top;
1652 INT nHScrollHeight = GetSystemMetrics(SM_CYHSCROLL);
1653 INT nVScrollWidth = GetSystemMetrics(SM_CXVSCROLL);
1654 INT nHiddenWidth;
1655 INT nHiddenHeight;
1656 INT nHiddenItemCount;
1657 INT nScrollPos;
1658 INT nMaxRange;
1659 INT nCountPerPage;
1660 INT nPixPerScrollPos;
1661 RECT rcView;
1663 TRACE(listview, "(hwnd=%x,lStyle=%lx)\n", hwnd, lStyle);
1665 switch (LVS_TYPEMASK & lStyle)
1667 case LVS_LIST:
1668 nCountPerPage = infoPtr->nCountPerRow * infoPtr->nCountPerColumn;
1669 if (nCountPerPage < GETITEMCOUNT(infoPtr))
1671 /* display horizontal scrollbar */
1672 if ((lStyle & WS_HSCROLL) == 0)
1674 ShowScrollBar(hwnd, SB_HORZ, TRUE);
1677 /* calculate new scrollbar range */
1678 nHiddenItemCount = GETITEMCOUNT(infoPtr) - nCountPerPage;
1679 if ((nHiddenItemCount % infoPtr->nCountPerColumn) == 0)
1681 nMaxRange = nHiddenItemCount / infoPtr->nCountPerColumn;
1683 else
1685 nMaxRange = nHiddenItemCount / infoPtr->nCountPerColumn + 1;
1688 SetScrollRange(hwnd, SB_HORZ, 0, nMaxRange, FALSE);
1689 nScrollPos = ListView_GetTopIndex(hwnd) / infoPtr->nCountPerColumn;
1690 SetScrollPos(hwnd, SB_HORZ, nScrollPos, TRUE);
1692 else
1694 /* hide scrollbar */
1695 if ((lStyle & WS_HSCROLL) != 0)
1697 ShowScrollBar(hwnd, SB_HORZ, FALSE);
1700 break;
1702 case LVS_REPORT:
1704 * This section was commented out because I experienced some problems
1705 * with the scrolling of the header control. The idea was to add a
1706 * horizontal scrollbar when the width of the client area was smaller
1707 * than the width of the header control.
1710 /* if (infoPtr->nItemWidth > nListWidth) */
1711 /* { */
1712 /* if ((lStyle & WS_HSCROLL) == 0) */
1713 /* { */
1714 /* ShowScrollBar(hwnd, SB_HORZ, TRUE); */
1715 /* LISTVIEW_SetSize(hwnd, lStyle, -1, -1); */
1716 /* LISTVIEW_SetViewInfo(hwnd, lStyle); */
1717 /* } */
1719 /* nListWidth = infoPtr->rcList.right - infoPtr->rcList.left; */
1720 /* nHiddenWidth = infoPtr->nItemWidth - nListWidth; */
1721 /* nPixPerScrollPos = max(1, nListWidth / 10); */
1723 /* if ((nHiddenWidth % nPixPerScrollPos) == 0) */
1724 /* { */
1725 /* nMaxRange = nHiddenWidth / nPixPerScrollPos; */
1726 /* } */
1727 /* else */
1728 /* { */
1729 /* nMaxRange = nHiddenWidth / nPixPerScrollPos + 1; */
1730 /* } */
1732 /* SetScrollRange(hwnd, SB_HORZ, 0, nMaxRange, FALSE); */
1733 /* SetScrollPos(hwnd, SB_HORZ, 0, TRUE); */
1734 /* } */
1735 /* else */
1736 /* { */
1737 /* if ((lStyle & WS_HSCROLL) != 0) */
1738 /* { */
1739 /* ShowScrollBar(hwnd, SB_HORZ, FASLE); */
1740 /* LISTVIEW_SetSize(hwnd, lStyle, -1, -1); */
1741 /* LISTVIEW_SetViewInfo(hwnd, lStyle); */
1742 /* } */
1743 /* } */
1745 if (infoPtr->nCountPerColumn < GETITEMCOUNT(infoPtr))
1747 if ((lStyle & WS_VSCROLL) == 0)
1749 if (nListWidth > nVScrollWidth)
1751 ShowScrollBar(hwnd, SB_VERT, TRUE);
1752 nListWidth -= nVScrollWidth;
1756 /* vertical range & position */
1757 nMaxRange = GETITEMCOUNT(infoPtr) - infoPtr->nCountPerColumn;
1758 SetScrollRange(hwnd, SB_VERT, 0, nMaxRange, FALSE);
1759 SetScrollPos(hwnd, SB_VERT, ListView_GetTopIndex(hwnd), TRUE);
1761 else
1763 if ((lStyle & WS_VSCROLL) != 0)
1765 ShowScrollBar(hwnd, SB_VERT, FALSE);
1766 nListWidth += nVScrollWidth;
1769 break;
1771 case LVS_ICON:
1772 case LVS_SMALLICON:
1773 if (LISTVIEW_GetViewRect(hwnd, &rcView) != FALSE)
1775 if (rcView.right - rcView.left > nListWidth)
1777 if ((lStyle & WS_HSCROLL) == 0)
1779 if (nListHeight > nHScrollHeight)
1781 ShowScrollBar(hwnd, SB_HORZ, TRUE);
1782 nListHeight -= nHScrollHeight;
1786 /* calculate size of hidden items */
1787 nHiddenWidth = rcView.right - rcView.left - nListWidth;
1788 nPixPerScrollPos = max(1, nListWidth / 10);
1790 /* vertical range & position */
1791 if ((nHiddenWidth % nPixPerScrollPos) == 0)
1793 nMaxRange = nHiddenWidth / nPixPerScrollPos;
1795 else
1797 nMaxRange = nHiddenWidth / nPixPerScrollPos + 1;
1800 /* set range and position */
1801 SetScrollRange(hwnd, SB_HORZ, 0, nMaxRange, FALSE);
1802 SetScrollPos(hwnd, SB_HORZ, 0, TRUE);
1804 else
1806 if ((lStyle & WS_HSCROLL) != 0)
1808 ShowScrollBar(hwnd, SB_HORZ, FALSE);
1809 nListHeight += nHScrollHeight;
1813 if (rcView.bottom - rcView.top > nListHeight)
1815 if ((lStyle & WS_VSCROLL) == 0)
1817 if (nListWidth > nVScrollWidth)
1819 ShowScrollBar(hwnd, SB_VERT, TRUE);
1820 nListWidth -= nVScrollWidth;
1824 /* calculate size of hidden items */
1825 nHiddenHeight = rcView.bottom - rcView.top - nListHeight;
1826 nPixPerScrollPos = max(1, nListHeight / 10);
1828 /* set vertical range & position */
1829 if ((nHiddenHeight % nPixPerScrollPos) == 0)
1831 nMaxRange = nHiddenHeight / nPixPerScrollPos;
1833 else
1835 nMaxRange = nHiddenHeight / nPixPerScrollPos + 1;
1838 /* set range and position */
1839 SetScrollRange(hwnd, SB_VERT, 0, nMaxRange, FALSE);
1840 SetScrollPos(hwnd, SB_VERT, 0, TRUE);
1842 else
1844 if ((lStyle & WS_VSCROLL) != 0)
1846 ShowScrollBar(hwnd, SB_VERT, FALSE);
1847 nListWidth += nVScrollWidth;
1851 break;
1855 /***
1856 * DESCRIPTION:
1857 * Draws a subitem.
1859 * PARAMETER(S):
1860 * [I] HWND : window handle
1861 * [I] HDC : device context handle
1862 * [I] INT : item index
1863 * [I] LPARAM : item lparam
1864 * [I] LISTVIEW_SUBITEM * : item
1865 * [I] INT : column index (header index)
1866 * [I] RECT * : clipping rectangle
1868 * RETURN:
1869 * None
1871 static VOID LISTVIEW_DrawSubItem(HWND hwnd, HDC hdc, INT nItem, LPARAM lParam,
1872 LISTVIEW_SUBITEM *lpSubItem, INT nColumn,
1873 RECT *lprc)
1875 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
1876 CHAR szDispText[DISP_TEXT_SIZE];
1877 LPSTR pszDispText = NULL;
1879 /* set item colors */
1880 SetBkColor(hdc, infoPtr->clrTextBk);
1881 SetTextColor(hdc, infoPtr->clrText);
1883 pszDispText = szDispText;
1884 LISTVIEW_GetSubItemDispInfo(hwnd, nItem, lParam, lpSubItem, nColumn, NULL,
1885 &pszDispText, DISP_TEXT_SIZE);
1887 /* draw text : using arbitrary offset of 10 pixels */
1889 ExtTextOutA(hdc, lprc->left, lprc->top, ETO_OPAQUE|ETO_CLIPPED,
1890 lprc, pszDispText, lstrlenA(pszDispText), NULL);
1893 /***
1894 * DESCRIPTION:
1895 * Draws an item.
1897 * PARAMETER(S):
1898 * [I] HWND : window handle
1899 * [I] HDC : device context handle
1900 * [I] LISTVIEW_ITEM * : item
1901 * [I] INT : item index
1902 * [I] RECT * : clipping rectangle
1904 * RETURN:
1905 * None
1907 static VOID LISTVIEW_DrawItem(HWND hwnd, HDC hdc, LISTVIEW_ITEM *lpItem,
1908 INT nItem, RECT rc)
1910 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
1911 CHAR szDispText[DISP_TEXT_SIZE];
1912 LPSTR pszDispText = NULL;
1913 BOOL bSelected;
1914 INT nLabelWidth;
1915 INT nImage;
1916 UINT uState;
1918 TRACE(listview, "(hwnd=%x,hdc=%x,lpItem=%p,nItem=%d,rc.left=%d,rctop=%d,rc.right=%d,rc.bottom=%d)\n", hwnd, hdc, lpItem, nItem, rc.left, rc.top, rc.right, rc.bottom);
1920 pszDispText = szDispText;
1921 LISTVIEW_GetItemDispInfo(hwnd, nItem, lpItem, &nImage, &uState, &pszDispText,
1922 DISP_TEXT_SIZE);
1924 if (uState & LVIS_SELECTED)
1926 bSelected = TRUE;
1928 /* set item colors */
1929 SetBkColor(hdc, GetSysColor(COLOR_HIGHLIGHT));
1930 SetTextColor(hdc, GetSysColor(COLOR_HIGHLIGHTTEXT));
1932 /* set raster mode */
1933 SetROP2(hdc, R2_XORPEN);
1935 else
1937 bSelected = FALSE;
1939 /* set item colors */
1940 SetBkColor(hdc, infoPtr->clrTextBk);
1941 SetTextColor(hdc, infoPtr->clrText);
1943 /* set raster mode */
1944 SetROP2(hdc, R2_COPYPEN);
1947 /* state icons */
1948 if (infoPtr->himlState != NULL)
1950 /* right shift 12 bits to obtain index in image list */
1951 if (bSelected != FALSE)
1953 ImageList_Draw(infoPtr->himlState, uState >> 12, hdc, rc.left,
1954 rc.top, ILD_SELECTED);
1956 else
1958 ImageList_Draw(infoPtr->himlState, uState >> 12, hdc, rc.left,
1959 rc.top, ILD_NORMAL);
1962 rc.left += infoPtr->iconSize.cx;
1965 /* small icons */
1966 if (infoPtr->himlSmall != NULL)
1968 if (bSelected != FALSE)
1970 ImageList_Draw(infoPtr->himlSmall, nImage, hdc, rc.left,
1971 rc.top, ILD_SELECTED);
1973 else
1975 ImageList_Draw(infoPtr->himlSmall, nImage, hdc, rc.left,
1976 rc.top, ILD_NORMAL);
1979 rc.left += infoPtr->iconSize.cx;
1982 nLabelWidth = ListView_GetStringWidthA(hwnd, pszDispText);
1983 if (rc.left + nLabelWidth < rc.right)
1985 rc.right = rc.left + nLabelWidth;
1988 /* draw label */
1989 ExtTextOutA(hdc, rc.left, rc.top, ETO_OPAQUE|ETO_CLIPPED,
1990 &rc, pszDispText, lstrlenA(pszDispText), NULL);
1992 if (lpItem->state & LVIS_FOCUSED)
1994 Rectangle(hdc, rc.left, rc.top, rc.right, rc.bottom);
1998 /***
1999 * DESCRIPTION:
2000 * Draws an item when in large icon display mode.
2002 * PARAMETER(S):
2003 * [I] HWND : window handle
2004 * [I] HDC : device context handle
2005 * [I] LISTVIEW_ITEM * : item
2006 * [I] INT : item index
2007 * [I] RECT * : clipping rectangle
2009 * RETURN:
2010 * None
2012 static VOID LISTVIEW_DrawLargeItem(HWND hwnd, HDC hdc, LISTVIEW_ITEM *lpItem,
2013 INT nItem, RECT rc)
2015 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
2016 CHAR szDispText[DISP_TEXT_SIZE];
2017 LPSTR pszDispText = NULL;
2018 BOOL bSelected;
2019 INT nLabelWidth;
2020 INT nImage;
2021 UINT uState;
2022 INT nDrawPosX = 0;
2023 TEXTMETRICA tm;
2025 TRACE(listview, "(hwnd=%x,hdc=%x,lpItem=%p,nItem=%d,rc.left=%d,rctop=%d,rc.right=%d,rc.bottom=%d)\n", hwnd, hdc, lpItem, nItem, rc.left, rc.top, rc.right, rc.bottom);
2027 pszDispText = szDispText;
2028 LISTVIEW_GetItemDispInfo(hwnd, nItem, lpItem, &nImage, &uState, &pszDispText,
2029 DISP_TEXT_SIZE);
2030 if (uState & LVIS_SELECTED)
2032 bSelected = TRUE;
2034 /* set item colors */
2035 SetBkColor(hdc, GetSysColor(COLOR_HIGHLIGHT));
2036 SetTextColor(hdc, GetSysColor(COLOR_HIGHLIGHTTEXT));
2038 /* set raster mode */
2039 SetROP2(hdc, R2_XORPEN);
2041 else
2043 bSelected = FALSE;
2045 /* set item colors */
2046 SetBkColor(hdc, infoPtr->clrTextBk);
2047 SetTextColor(hdc, infoPtr->clrText);
2049 /* set raster mode */
2050 SetROP2(hdc, R2_COPYPEN);
2053 if (infoPtr->himlNormal != NULL)
2055 rc.top += ICON_TOP_PADDING;
2056 nDrawPosX = rc.left + (infoPtr->iconSpacing.cx - infoPtr->iconSize.cx) / 2;
2057 if (bSelected != FALSE)
2059 ImageList_Draw(infoPtr->himlNormal, nImage, hdc, nDrawPosX, rc.top,
2060 ILD_SELECTED);
2062 else
2064 ImageList_Draw(infoPtr->himlNormal, nImage, hdc, nDrawPosX, rc.top,
2065 ILD_NORMAL);
2069 rc.top += infoPtr->iconSize.cy + ICON_BOTTOM_PADDING;
2070 nLabelWidth = ListView_GetStringWidthA(hwnd, pszDispText);
2071 nDrawPosX = infoPtr->iconSpacing.cx - nLabelWidth;
2072 if (nDrawPosX > 1)
2074 rc.left += nDrawPosX / 2;
2075 rc.right = rc.left + nLabelWidth;
2077 else
2079 rc.left += 1;
2080 rc.right = rc.left + infoPtr->iconSpacing.cx - 1;
2083 /* draw label */
2084 GetTextMetricsA(hdc, &tm);
2085 rc.bottom = rc.top + tm.tmHeight + HEIGHT_PADDING;
2086 ExtTextOutA(hdc, rc.left, rc.top, ETO_OPAQUE|ETO_CLIPPED,
2087 &rc, pszDispText, lstrlenA(pszDispText), NULL);
2089 if (lpItem->state & LVIS_FOCUSED)
2091 Rectangle(hdc, rc.left, rc.top, rc.right, rc.bottom);
2095 /***
2096 * DESCRIPTION:
2097 * Draws listview items when in report display mode.
2099 * PARAMETER(S):
2100 * [I] HWND : window handle
2101 * [I] HDC : device context handle
2103 * RETURN:
2104 * None
2106 static VOID LISTVIEW_RefreshReport(HWND hwnd, HDC hdc)
2108 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd,0);
2109 INT nDrawPosY = infoPtr->rcList.top;
2110 LISTVIEW_ITEM *lpItem;
2111 LISTVIEW_SUBITEM *lpSubItem = NULL;
2112 BOOL bNeedSubItem = TRUE;
2113 INT nColumnCount;
2114 HDPA hdpaSubItems;
2115 RECT rcItem;
2116 INT j, k;
2117 INT nItem;
2118 INT nLast;
2120 nItem = ListView_GetTopIndex(hwnd);
2121 nLast = nItem + infoPtr->nCountPerColumn;
2122 while (nItem <= nLast)
2124 hdpaSubItems = (HDPA)DPA_GetPtr(infoPtr->hdpaItems, nItem);
2125 if (hdpaSubItems != NULL)
2127 lpItem = (LISTVIEW_ITEM *)DPA_GetPtr(hdpaSubItems, 0);
2128 if (lpItem != NULL)
2130 /* the width of the header items will determine the size of the
2131 listview items */
2132 Header_GetItemRect(infoPtr->hwndHeader, 0, &rcItem);
2133 rcItem.left += REPORT_MARGINX;
2134 rcItem.right = max(rcItem.left, rcItem.right - REPORT_MARGINX);
2135 rcItem.top = nDrawPosY;
2136 rcItem.bottom = rcItem.top + infoPtr->nItemHeight;
2137 LISTVIEW_DrawItem(hwnd, hdc, lpItem, nItem, rcItem);
2140 nColumnCount = Header_GetItemCount(infoPtr->hwndHeader);
2141 for (k = 1, j = 1; j < nColumnCount; j++)
2143 Header_GetItemRect(infoPtr->hwndHeader, j, &rcItem);
2144 rcItem.left += REPORT_MARGINX;
2145 rcItem.right = max(rcItem.left, rcItem.right - REPORT_MARGINX);
2146 rcItem.top = nDrawPosY;
2147 rcItem.bottom = rcItem.top + infoPtr->nItemHeight;
2149 if (k < hdpaSubItems->nItemCount)
2151 if (bNeedSubItem != FALSE)
2153 lpSubItem = (LISTVIEW_SUBITEM *)DPA_GetPtr(hdpaSubItems, k);
2154 k++;
2157 if (lpSubItem != NULL)
2159 if (lpSubItem->iSubItem == j)
2161 LISTVIEW_DrawSubItem(hwnd, hdc, nItem, lpItem->lParam, lpSubItem,
2162 j, &rcItem);
2163 bNeedSubItem = TRUE;
2165 else
2167 LISTVIEW_DrawSubItem(hwnd, hdc, nItem, lpItem->lParam, NULL, j,
2168 &rcItem);
2169 bNeedSubItem = FALSE;
2172 else
2174 LISTVIEW_DrawSubItem(hwnd, hdc, nItem, lpItem->lParam, NULL, j,
2175 &rcItem);
2176 bNeedSubItem = TRUE;
2179 else
2181 LISTVIEW_DrawSubItem(hwnd, hdc, nItem, lpItem->lParam, NULL, j,
2182 &rcItem);
2187 nDrawPosY += infoPtr->nItemHeight;
2188 nItem++;
2192 /***
2193 * DESCRIPTION:
2194 * Draws listview items when in list display mode.
2196 * PARAMETER(S):
2197 * [I] HWND : window handle
2198 * [I] HDC : device context handle
2200 * RETURN:
2201 * None
2203 static VOID LISTVIEW_RefreshList(HWND hwnd, HDC hdc)
2205 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
2206 LISTVIEW_ITEM *lpItem;
2207 HDPA hdpaSubItems;
2208 RECT rc;
2209 INT i, j;
2210 INT nColumnCount;
2211 INT nItem = ListView_GetTopIndex(hwnd);
2213 if (infoPtr->rcList.right > 0)
2215 /* get number of display columns */
2216 if (infoPtr->rcList.right % infoPtr->nItemWidth == 0)
2218 nColumnCount = infoPtr->rcList.right / infoPtr->nItemWidth;
2220 else
2222 nColumnCount = infoPtr->rcList.right / infoPtr->nItemWidth + 1;
2225 for (i = 0; i < nColumnCount; i++)
2227 j = 0;
2228 while ((nItem < GETITEMCOUNT(infoPtr)) &&
2229 (j<infoPtr->nCountPerColumn))
2231 hdpaSubItems = (HDPA)DPA_GetPtr(infoPtr->hdpaItems, nItem);
2232 if (hdpaSubItems != NULL)
2234 lpItem = (LISTVIEW_ITEM *)DPA_GetPtr(hdpaSubItems, 0);
2235 if (lpItem != NULL)
2237 rc.top = j * infoPtr->nItemHeight;
2238 rc.left = i * infoPtr->nItemWidth;
2239 rc.bottom = rc.top + infoPtr->nItemHeight;
2240 rc.right = rc.left + infoPtr->nItemWidth;
2241 LISTVIEW_DrawItem(hwnd, hdc, lpItem, nItem, rc);
2245 nItem++;
2246 j++;
2252 /***
2253 * DESCRIPTION:
2254 * Draws listview items when in icon or small icon display mode.
2256 * PARAMETER(S):
2257 * [I] HWND : window handle
2258 * [I] HDC : device context handle
2260 * RETURN:
2261 * None
2263 static VOID LISTVIEW_RefreshIcon(HWND hwnd, HDC hdc, BOOL bSmall)
2265 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
2266 LISTVIEW_ITEM *lpItem;
2267 HDPA hdpaSubItems;
2268 POINT ptPosition;
2269 POINT ptOrigin;
2270 RECT rc;
2271 INT i;
2273 LISTVIEW_GetOrigin(hwnd, &ptOrigin);
2275 for (i = 0; i < GETITEMCOUNT(infoPtr); i++)
2277 LISTVIEW_GetItemPosition(hwnd, i, &ptPosition);
2278 ptPosition.x += ptOrigin.x;
2279 ptPosition.y += ptOrigin.y;
2281 if (ptPosition.y + infoPtr->nItemHeight > infoPtr->rcList.top)
2283 if (ptPosition.x + infoPtr->nItemWidth > infoPtr->rcList.left)
2285 if (ptPosition.y < infoPtr->rcList.bottom)
2287 if (ptPosition.x < infoPtr->rcList.right)
2289 hdpaSubItems = (HDPA)DPA_GetPtr(infoPtr->hdpaItems, i);
2290 if (hdpaSubItems != NULL)
2292 lpItem = (LISTVIEW_ITEM *)DPA_GetPtr(hdpaSubItems, 0);
2293 if (lpItem != NULL)
2295 rc.top = ptPosition.y;
2296 rc.left = ptPosition.x;
2297 rc.bottom = rc.top + infoPtr->nItemHeight;
2298 rc.right = rc.left + infoPtr->nItemWidth;
2299 if (bSmall == FALSE)
2301 LISTVIEW_DrawLargeItem(hwnd, hdc, lpItem, i, rc);
2303 else
2305 LISTVIEW_DrawItem(hwnd, hdc, lpItem, i, rc);
2316 /***
2317 * DESCRIPTION:
2318 * Draws listview items.
2320 * PARAMETER(S):
2321 * [I] HWND : window handle
2322 * [I] HDC : device context handle
2324 * RETURN:
2325 * NoneX
2327 static VOID LISTVIEW_Refresh(HWND hwnd, HDC hdc)
2329 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
2330 LONG lStyle = GetWindowLongA(hwnd, GWL_STYLE);
2331 HFONT hOldFont;
2332 HPEN hPen, hOldPen;
2334 /* select font */
2335 hOldFont = SelectObject(hdc, infoPtr->hFont);
2337 /* select the doted pen (for drawing the focus box) */
2338 hPen = CreatePen(PS_DOT, 1, 0);
2339 hOldPen = SelectObject(hdc, hPen);
2341 /* select transparent brush (for drawing the focus box) */
2342 SelectObject(hdc, GetStockObject(NULL_BRUSH));
2344 switch (LVS_TYPEMASK & lStyle)
2346 case LVS_LIST:
2347 LISTVIEW_RefreshList(hwnd, hdc);
2348 break;
2349 case LVS_REPORT:
2350 LISTVIEW_RefreshReport(hwnd, hdc);
2351 break;
2352 case LVS_SMALLICON:
2353 LISTVIEW_RefreshIcon(hwnd, hdc, TRUE);
2354 break;
2355 case LVS_ICON:
2356 LISTVIEW_RefreshIcon(hwnd, hdc, FALSE);
2359 /* unselect objects */
2360 SelectObject(hdc, hOldFont);
2361 SelectObject(hdc, hOldPen);
2363 /* delete pen */
2364 DeleteObject(hPen);
2368 /***
2369 * DESCRIPTION:
2370 * Calculates the approximate width and height of a given number of items.
2372 * PARAMETER(S):
2373 * [I] HWND : window handle
2374 * [I] INT : number of items
2375 * [I] INT : width
2376 * [I] INT : height
2378 * RETURN:
2379 * Returns a DWORD. The width in the low word and the height in high word.
2381 static LRESULT LISTVIEW_ApproximateViewRect(HWND hwnd, INT nItemCount,
2382 WORD wWidth, WORD wHeight)
2384 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
2385 LONG lStyle = GetWindowLongA(hwnd, GWL_STYLE);
2386 INT nItemCountPerColumn = 1;
2387 INT nColumnCount = 0;
2388 DWORD dwViewRect = 0;
2390 if (nItemCount == -1)
2391 nItemCount = GETITEMCOUNT(infoPtr);
2393 if (lStyle & LVS_LIST)
2395 if (wHeight == 0xFFFF)
2397 /* use current height */
2398 wHeight = infoPtr->rcList.bottom;
2401 if (wHeight < infoPtr->nItemHeight)
2403 wHeight = infoPtr->nItemHeight;
2406 if (nItemCount > 0)
2408 if (infoPtr->nItemHeight > 0)
2410 nItemCountPerColumn = wHeight / infoPtr->nItemHeight;
2411 if (nItemCountPerColumn == 0)
2412 nItemCountPerColumn = 1;
2414 if (nItemCount % nItemCountPerColumn != 0)
2415 nColumnCount = nItemCount / nItemCountPerColumn;
2416 else
2417 nColumnCount = nItemCount / nItemCountPerColumn + 1;
2421 /* Microsoft padding magic */
2422 wHeight = nItemCountPerColumn * infoPtr->nItemHeight + 2;
2423 wWidth = nColumnCount * infoPtr->nItemWidth + 2;
2425 dwViewRect = MAKELONG(wWidth, wHeight);
2427 else if (lStyle & LVS_REPORT)
2429 /* TO DO */
2431 else if (lStyle & LVS_SMALLICON)
2433 /* TO DO */
2435 else if (lStyle & LVS_ICON)
2437 /* TO DO */
2440 return dwViewRect;
2443 /***
2444 * DESCRIPTION:
2445 * Arranges listview items in icon display mode.
2447 * PARAMETER(S):
2448 * [I] HWND : window handle
2449 * [I] INT : alignment code
2451 * RETURN:
2452 * SUCCESS : TRUE
2453 * FAILURE : FALSE
2455 static LRESULT LISTVIEW_Arrange(HWND hwnd, INT nAlignCode)
2457 LONG lStyle = GetWindowLongA(hwnd, GWL_STYLE);
2458 BOOL bResult = FALSE;
2460 if (((LVS_TYPEMASK & lStyle) == LVS_ICON) ||
2461 ((LVS_TYPEMASK & lStyle) == LVS_SMALLICON))
2463 switch (nAlignCode)
2465 case LVA_ALIGNLEFT:
2466 /* TO DO */
2467 break;
2468 case LVA_ALIGNTOP:
2469 /* TO DO */
2470 break;
2471 case LVA_DEFAULT:
2472 /* TO DO */
2473 break;
2474 case LVA_SNAPTOGRID:
2475 /* TO DO */
2476 break;
2480 return bResult;
2483 /* << LISTVIEW_CreateDragImage >> */
2485 /***
2486 * DESCRIPTION:
2487 * Removes all listview items and subitems.
2489 * PARAMETER(S):
2490 * [I] HWND : window handle
2492 * RETURN:
2493 * SUCCESS : TRUE
2494 * FAILURE : FALSE
2496 static LRESULT LISTVIEW_DeleteAllItems(HWND hwnd)
2498 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
2499 LONG lCtrlId = GetWindowLongA(hwnd, GWL_ID);
2500 LONG lStyle = GetWindowLongA(hwnd, GWL_STYLE);
2501 LISTVIEW_ITEM *lpItem;
2502 LISTVIEW_SUBITEM *lpSubItem;
2503 NMLISTVIEW nmlv;
2504 BOOL bSuppress;
2505 BOOL bResult = FALSE;
2506 INT i;
2507 INT j;
2508 HDPA hdpaSubItems;
2510 TRACE(listview, "(hwnd=%x,)\n", hwnd);
2512 if (GETITEMCOUNT(infoPtr) > 0)
2514 /* initialize memory */
2515 ZeroMemory(&nmlv, sizeof(NMLISTVIEW));
2517 /* send LVN_DELETEALLITEMS notification */
2518 nmlv.hdr.hwndFrom = hwnd;
2519 nmlv.hdr.idFrom = lCtrlId;
2520 nmlv.hdr.code = LVN_DELETEALLITEMS;
2521 nmlv.iItem = -1;
2523 /* verify if subsequent LVN_DELETEITEM notifications should be
2524 suppressed */
2525 bSuppress = ListView_LVNotify(GetParent(hwnd), lCtrlId, &nmlv);
2527 for (i = 0; i < GETITEMCOUNT(infoPtr); i++)
2529 hdpaSubItems = (HDPA)DPA_GetPtr(infoPtr->hdpaItems, i);
2530 if (hdpaSubItems != NULL)
2532 for (j = 1; j < hdpaSubItems->nItemCount; j++)
2534 lpSubItem = (LISTVIEW_SUBITEM *)DPA_GetPtr(hdpaSubItems, j);
2535 if (lpSubItem != NULL)
2537 /* free subitem string */
2538 if ((lpSubItem->pszText != NULL) &&
2539 (lpSubItem->pszText != LPSTR_TEXTCALLBACKA))
2541 COMCTL32_Free(lpSubItem->pszText);
2544 /* free subitem */
2545 COMCTL32_Free(lpSubItem);
2549 lpItem = (LISTVIEW_ITEM *)DPA_GetPtr(hdpaSubItems, 0);
2550 if (lpItem != NULL)
2552 if (bSuppress == FALSE)
2554 /* send LVN_DELETEITEM notification */
2555 nmlv.hdr.code = LVN_DELETEITEM;
2556 nmlv.iItem = i;
2557 nmlv.lParam = lpItem->lParam;
2558 ListView_LVNotify(GetParent(hwnd), lCtrlId, &nmlv);
2561 /* free item string */
2562 if ((lpItem->pszText != NULL) &&
2563 (lpItem->pszText != LPSTR_TEXTCALLBACKA))
2565 COMCTL32_Free(lpItem->pszText);
2568 /* free item */
2569 COMCTL32_Free(lpItem);
2572 DPA_Destroy(hdpaSubItems);
2576 /* reinitialize listview memory */
2577 bResult = DPA_DeleteAllPtrs(infoPtr->hdpaItems);
2579 /* align items (set position of each item) */
2580 switch (lStyle & LVS_TYPEMASK)
2582 case LVS_ICON:
2583 case LVS_SMALLICON:
2584 if (lStyle & LVS_ALIGNLEFT)
2586 LISTVIEW_AlignLeft(hwnd);
2588 else
2590 LISTVIEW_AlignTop(hwnd);
2592 break;
2595 LISTVIEW_SetScroll(hwnd, lStyle);
2597 /* invalidate client area (optimization needed) */
2598 InvalidateRect(hwnd, NULL, TRUE);
2601 return bResult;
2604 /***
2605 * DESCRIPTION:
2606 * Removes a column from the listview control.
2608 * PARAMETER(S):
2609 * [I] HWND : window handle
2610 * [I] INT : column index
2612 * RETURN:
2613 * SUCCESS : TRUE
2614 * FAILURE : FALSE
2616 static LRESULT LISTVIEW_DeleteColumn(HWND hwnd, INT nColumn)
2618 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
2619 LONG lStyle = GetWindowLongA(hwnd, GWL_STYLE);
2620 BOOL bResult = FALSE;
2622 if (Header_DeleteItem(infoPtr->hwndHeader, nColumn) != FALSE)
2624 bResult = LISTVIEW_RemoveColumn(infoPtr->hdpaItems, nColumn);
2626 /* reset scroll parameters */
2627 if ((lStyle & LVS_TYPEMASK) == LVS_REPORT)
2629 LISTVIEW_SetViewInfo(hwnd, lStyle);
2630 LISTVIEW_SetScroll(hwnd, lStyle);
2633 /* refresh client area */
2634 InvalidateRect(hwnd, NULL, FALSE);
2637 return bResult;
2640 /***
2641 * DESCRIPTION:
2642 * Removes an item from the listview control.
2644 * PARAMETER(S):
2645 * [I] HWND : window handle
2646 * [I] INT : item index
2648 * RETURN:
2649 * SUCCESS : TRUE
2650 * FAILURE : FALSE
2652 static LRESULT LISTVIEW_DeleteItem(HWND hwnd, INT nItem)
2654 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
2655 LONG lStyle = GetWindowLongA(hwnd, GWL_STYLE);
2656 LONG lCtrlId = GetWindowLongA(hwnd, GWL_ID);
2657 NMLISTVIEW nmlv;
2658 BOOL bResult = FALSE;
2659 HDPA hdpaSubItems;
2660 LISTVIEW_ITEM *lpItem;
2661 LISTVIEW_SUBITEM *lpSubItem;
2662 INT i;
2664 TRACE(listview, "(hwnd=%x,nItem=%d)\n", hwnd, nItem);
2666 if ((nItem >= 0) && (nItem < GETITEMCOUNT(infoPtr)))
2668 /* initialize memory */
2669 ZeroMemory(&nmlv, sizeof(NMLISTVIEW));
2671 hdpaSubItems = (HDPA)DPA_DeletePtr(infoPtr->hdpaItems, nItem);
2672 if (hdpaSubItems != NULL)
2674 for (i = 1; i < hdpaSubItems->nItemCount; i++)
2676 lpSubItem = (LISTVIEW_SUBITEM *)DPA_GetPtr(hdpaSubItems, i);
2677 if (lpSubItem != NULL)
2679 /* free item string */
2680 if ((lpSubItem->pszText != NULL) &&
2681 (lpSubItem->pszText != LPSTR_TEXTCALLBACKA))
2683 COMCTL32_Free(lpSubItem->pszText);
2686 /* free item */
2687 COMCTL32_Free(lpSubItem);
2691 lpItem = (LISTVIEW_ITEM *)DPA_GetPtr(hdpaSubItems, 0);
2692 if (lpItem != NULL)
2694 /* send LVN_DELETEITEM notification */
2695 nmlv.hdr.hwndFrom = hwnd;
2696 nmlv.hdr.idFrom = lCtrlId;
2697 nmlv.hdr.code = LVN_DELETEITEM;
2698 nmlv.iItem = nItem;
2699 nmlv.lParam = lpItem->lParam;
2700 SendMessageA(GetParent(hwnd), WM_NOTIFY, (WPARAM)lCtrlId,
2701 (LPARAM)&nmlv);
2703 /* free item string */
2704 if ((lpItem->pszText != NULL) &&
2705 (lpItem->pszText != LPSTR_TEXTCALLBACKA))
2707 COMCTL32_Free(lpItem->pszText);
2710 /* free item */
2711 COMCTL32_Free(lpItem);
2714 bResult = DPA_Destroy(hdpaSubItems);
2717 /* align items (set position of each item) */
2718 switch(lStyle & LVS_TYPEMASK)
2720 case LVS_ICON:
2721 case LVS_SMALLICON:
2722 if (lStyle & LVS_ALIGNLEFT)
2724 LISTVIEW_AlignLeft(hwnd);
2726 else
2728 LISTVIEW_AlignTop(hwnd);
2730 break;
2733 LISTVIEW_SetScroll(hwnd, lStyle);
2735 /* refresh client area */
2736 InvalidateRect(hwnd, NULL, TRUE);
2739 return bResult;
2742 /* LISTVIEW_EditLabel */
2744 /***
2745 * DESCRIPTION:
2746 * Ensures the specified item is visible, scrolling into view if necessary.
2748 * PARAMETER(S):
2749 * [I] HWND : window handle
2750 * [I] INT : item index
2751 * [I] BOOL : partially or entirely visible
2753 * RETURN:
2754 * SUCCESS : TRUE
2755 * FAILURE : FALSE
2757 static BOOL LISTVIEW_EnsureVisible(HWND hwnd, INT nItem, BOOL bPartial)
2759 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
2760 LONG lStyle = GetWindowLongA(hwnd, GWL_STYLE);
2761 INT nListHeight = infoPtr->rcList.bottom - infoPtr->rcList.top;
2762 INT nListWidth = infoPtr->rcList.right - infoPtr->rcList.left;
2763 INT nHScrollPos = 0;
2764 INT nVScrollPos = 0;
2765 INT nScrollPosHeight = 0;
2766 INT nScrollPosWidth = 0;
2767 RECT rcItem;
2768 BOOL bResult = FALSE;
2770 /* ALWAYS bPartial == FALSE, FOR NOW! */
2772 rcItem.left = LVIR_BOUNDS;
2773 if (LISTVIEW_GetItemRect(hwnd, nItem, &rcItem) != FALSE)
2775 if (rcItem.left < infoPtr->rcList.left)
2777 /* scroll left */
2778 switch (LVS_TYPEMASK & lStyle)
2780 case LVS_LIST:
2781 rcItem.left += infoPtr->rcList.left;
2782 nScrollPosWidth = infoPtr->nItemWidth;
2783 break;
2785 case LVS_SMALLICON:
2786 case LVS_ICON:
2787 nScrollPosWidth = max(1, nListWidth / 10);
2788 rcItem.left += infoPtr->rcList.left;
2789 break;
2792 if (rcItem.left % nScrollPosWidth == 0)
2794 nHScrollPos = rcItem.left / nScrollPosWidth;
2796 else
2798 nHScrollPos = rcItem.left / nScrollPosWidth - 1;
2801 else if (rcItem.right > infoPtr->rcList.right)
2803 /* scroll right */
2804 switch (LVS_TYPEMASK & lStyle)
2806 case LVS_LIST:
2807 rcItem.right -= infoPtr->rcList.right;
2808 nScrollPosWidth = infoPtr->nItemWidth;
2809 break;
2811 case LVS_SMALLICON:
2812 case LVS_ICON:
2813 nScrollPosWidth = max(1, nListWidth / 10);
2814 rcItem.right -= infoPtr->rcList.right;
2815 break;
2818 if (rcItem.right % nScrollPosWidth == 0)
2820 nHScrollPos = rcItem.right / nScrollPosWidth;
2822 else
2824 nHScrollPos = rcItem.right / nScrollPosWidth + 1;
2828 if (rcItem.top < infoPtr->rcList.top)
2830 /* scroll up */
2831 switch (LVS_TYPEMASK & lStyle)
2833 case LVS_REPORT:
2834 rcItem.top -= infoPtr->rcList.top;
2835 nScrollPosHeight = infoPtr->nItemHeight;
2836 break;
2838 case LVS_SMALLICON:
2839 case LVS_ICON:
2840 nScrollPosHeight = max(1, nListHeight / 10);
2841 rcItem.top += infoPtr->rcList.top;
2842 break;
2845 if (rcItem.top % nScrollPosHeight == 0)
2847 nVScrollPos = rcItem.top / nScrollPosHeight;
2849 else
2851 nVScrollPos = rcItem.top / nScrollPosHeight - 1;
2854 else if (rcItem.bottom > infoPtr->rcList.bottom)
2856 switch (LVS_TYPEMASK & lStyle)
2858 case LVS_REPORT:
2859 rcItem.bottom -= infoPtr->rcList.bottom;
2860 nScrollPosHeight = infoPtr->nItemHeight;
2861 break;
2863 case LVS_SMALLICON:
2864 case LVS_ICON:
2865 nScrollPosHeight = max(1, nListHeight / 10);
2866 rcItem.bottom -= infoPtr->rcList.bottom;
2867 break;
2870 if (rcItem.bottom % nScrollPosHeight == 0)
2872 nVScrollPos = rcItem.bottom / nScrollPosHeight;
2874 else
2876 nVScrollPos = rcItem.bottom / nScrollPosHeight + 1;
2880 bResult = LISTVIEW_ScrollView(hwnd, nHScrollPos, nVScrollPos);
2883 return bResult;
2886 /***
2887 * DESCRIPTION:
2888 * Searches for an item with specific characteristics.
2890 * PARAMETER(S):
2891 * [I] HWND : window handle
2892 * [I] INT : base item index
2893 * [I] LPLVFINDINFO : item information to look for
2895 * RETURN:
2896 * SUCCESS : index of item
2897 * FAILURE : -1
2899 static LRESULT LISTVIEW_FindItem(HWND hwnd, INT nStart,
2900 LPLVFINDINFO lpFindInfo)
2902 FIXME (listview, "empty stub!\n");
2904 return -1;
2907 /***
2908 * DESCRIPTION:
2909 * Retrieves the background color of the listview control.
2911 * PARAMETER(S):
2912 * [I] HWND : window handle
2914 * RETURN:
2915 * COLORREF associated with the background.
2917 static LRESULT LISTVIEW_GetBkColor(HWND hwnd)
2919 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
2921 return infoPtr->clrBk;
2924 /***
2925 * DESCRIPTION:
2926 * Retrieves the background image of the listview control.
2928 * PARAMETER(S):
2929 * [I] HWND : window handle
2930 * [O] LPLVMKBIMAGE : background image attributes
2932 * RETURN:
2933 * SUCCESS : TRUE
2934 * FAILURE : FALSE`
2936 /* static LRESULT LISTVIEW_GetBkImage(HWND hwnd, LPLVBKIMAGE lpBkImage) */
2937 /* { */
2938 /* FIXME (listview, "empty stub!\n"); */
2939 /* return FALSE; */
2940 /* } */
2942 /***
2943 * DESCRIPTION:
2944 * Retrieves the callback mask.
2946 * PARAMETER(S):
2947 * [I] HWND : window handle
2949 * RETURN:
2950 * Value of mask
2952 static UINT LISTVIEW_GetCallbackMask(HWND hwnd)
2954 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
2956 return infoPtr->uCallbackMask;
2959 /***
2960 * DESCRIPTION:
2961 * Retrieves column attributes.
2963 * PARAMETER(S):
2964 * [I] HWND : window handle
2965 * [I] INT : column index
2966 * [IO] LPLVCOLUMNA : column information
2968 * RETURN:
2969 * SUCCESS : TRUE
2970 * FAILURE : FALSE
2972 static LRESULT LISTVIEW_GetColumnA(HWND hwnd, INT nItem,
2973 LPLVCOLUMNA lpColumn)
2975 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
2976 HDITEMA hdi;
2977 BOOL bResult = FALSE;
2979 if (lpColumn != NULL)
2981 /* initialize memory */
2982 ZeroMemory(&hdi, sizeof(HDITEMA));
2984 if (lpColumn->mask & LVCF_FMT)
2986 hdi.mask |= HDI_FORMAT;
2989 if (lpColumn->mask & LVCF_WIDTH)
2991 hdi.mask |= HDI_WIDTH;
2994 if (lpColumn->mask & LVCF_TEXT)
2996 hdi.mask |= (HDI_TEXT | HDI_FORMAT);
2999 if (lpColumn->mask & LVCF_IMAGE)
3001 hdi.mask |= HDI_IMAGE;
3004 if (lpColumn->mask & LVCF_ORDER)
3006 hdi.mask |= HDI_ORDER;
3009 bResult = Header_GetItemA(infoPtr->hwndHeader, nItem, &hdi);
3010 if (bResult != FALSE)
3012 if (lpColumn->mask & LVCF_FMT)
3014 lpColumn->fmt = 0;
3016 if (hdi.fmt & HDF_LEFT)
3018 lpColumn->fmt |= LVCFMT_LEFT;
3020 else if (hdi.fmt & HDF_RIGHT)
3022 lpColumn->fmt |= LVCFMT_RIGHT;
3024 else if (hdi.fmt & HDF_CENTER)
3026 lpColumn->fmt |= LVCFMT_CENTER;
3029 if (hdi.fmt & HDF_IMAGE)
3031 lpColumn->fmt |= LVCFMT_COL_HAS_IMAGES;
3035 if (lpColumn->mask & LVCF_WIDTH)
3037 lpColumn->cx = hdi.cxy;
3040 if ((lpColumn->mask & LVCF_TEXT) && (lpColumn->pszText) && (hdi.pszText))
3042 lstrcpynA (lpColumn->pszText, hdi.pszText, lpColumn->cchTextMax);
3045 if (lpColumn->mask & LVCF_IMAGE)
3047 lpColumn->iImage = hdi.iImage;
3050 if (lpColumn->mask & LVCF_ORDER)
3052 lpColumn->iOrder = hdi.iOrder;
3057 return bResult;
3060 /* LISTVIEW_GetColumnW */
3061 /* LISTVIEW_GetColumnOrderArray */
3063 /***
3064 * DESCRIPTION:
3065 * Retrieves the column width.
3067 * PARAMETER(S):
3068 * [I] HWND : window handle
3069 * [I] int : column index
3071 * RETURN:
3072 * SUCCESS : column width
3073 * FAILURE : zero
3075 static LRESULT LISTVIEW_GetColumnWidth(HWND hwnd, INT nColumn)
3077 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
3078 LONG lStyle = GetWindowLongA(hwnd, GWL_STYLE);
3079 HDITEMA hdi;
3080 INT nColumnWidth = 0;
3082 switch (LVS_TYPEMASK & lStyle)
3084 case LVS_LIST:
3085 nColumnWidth = infoPtr->nItemWidth;
3086 break;
3088 case LVS_REPORT:
3089 /* get column width from header */
3090 ZeroMemory(&hdi, sizeof(HDITEMA));
3091 hdi.mask = HDI_WIDTH;
3092 if (Header_GetItemA(infoPtr->hwndHeader, nColumn, &hdi) != FALSE)
3094 nColumnWidth = hdi.cxy;
3096 break;
3099 return nColumnWidth;
3102 /***
3103 * DESCRIPTION:
3104 * In list or report display mode, retrieves the number of items that can fit
3105 * vertically in the visible area. In icon or small icon display mode,
3106 * retrieves the total number of visible items.
3108 * PARAMETER(S):
3109 * [I] HWND : window handle
3111 * RETURN:
3112 * Number of fully visible items.
3114 static LRESULT LISTVIEW_GetCountPerPage(HWND hwnd)
3116 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
3117 LONG lStyle = GetWindowLongA(hwnd, GWL_STYLE);
3118 INT nItemCount = 0;
3120 switch (LVS_TYPEMASK & lStyle)
3122 case LVS_LIST:
3123 if (infoPtr->rcList.right / infoPtr->nItemWidth)
3125 nItemCount = infoPtr->nCountPerRow * infoPtr->nCountPerColumn;
3127 break;
3129 case LVS_REPORT:
3130 nItemCount = infoPtr->nCountPerColumn;
3131 break;
3133 case LVS_SMALLICON:
3134 case LVS_ICON:
3135 nItemCount = GETITEMCOUNT(infoPtr);
3136 break;
3139 return nItemCount;
3142 /* LISTVIEW_GetEditControl */
3143 /* LISTVIEW_GetExtendedListViewStyle */
3145 /***
3146 * DESCRIPTION:
3147 * Retrieves the handle to the header control.
3149 * PARAMETER(S):
3150 * [I] HWND : window handle
3152 * RETURN:
3153 * Header handle.
3155 static LRESULT LISTVIEW_GetHeader(HWND hwnd)
3157 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
3159 return infoPtr->hwndHeader;
3162 /* LISTVIEW_GetHotCursor */
3163 /* LISTVIEW_GetHotItem */
3164 /* LISTVIEW_GetHoverTime */
3166 /***
3167 * DESCRIPTION:
3168 * Retrieves an image list handle.
3170 * PARAMETER(S):
3171 * [I] HWND : window handle
3172 * [I] INT : image list identifier
3174 * RETURN:
3175 * SUCCESS : image list handle
3176 * FAILURE : NULL
3178 static LRESULT LISTVIEW_GetImageList(HWND hwnd, INT nImageList)
3180 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
3181 HIMAGELIST himl = NULL;
3183 switch (nImageList)
3185 case LVSIL_NORMAL:
3186 himl = infoPtr->himlNormal;
3187 break;
3188 case LVSIL_SMALL:
3189 himl = infoPtr->himlSmall;
3190 break;
3191 case LVSIL_STATE:
3192 himl = infoPtr->himlState;
3193 break;
3196 return (LRESULT)himl;
3199 /* LISTVIEW_GetISearchString */
3201 /***
3202 * DESCRIPTION:
3203 * Retrieves item attributes.
3205 * PARAMETER(S):
3206 * [I] HWND : window handle
3207 * [IO] LPLVITEMA : item info
3209 * RETURN:
3210 * SUCCESS : TRUE
3211 * FAILURE : FALSE
3213 static LRESULT LISTVIEW_GetItemA(HWND hwnd, LPLVITEMA lpLVItem)
3215 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
3216 LISTVIEW_ITEM *lpItem;
3217 LISTVIEW_SUBITEM *lpSubItem;
3218 HDPA hdpaSubItems;
3219 BOOL bResult = FALSE;
3221 TRACE(listview, "(hwnd=%x,lpLVItem=%p)\n", hwnd, lpLVItem);
3223 if (lpLVItem != NULL)
3225 if ((lpLVItem->iItem >= 0) && (lpLVItem->iItem < GETITEMCOUNT(infoPtr)))
3227 hdpaSubItems = (HDPA)DPA_GetPtr(infoPtr->hdpaItems, lpLVItem->iItem);
3228 if (hdpaSubItems != NULL)
3230 if (lpLVItem->iSubItem == 0)
3232 lpItem = (LISTVIEW_ITEM *)DPA_GetPtr(hdpaSubItems, 0);
3233 if (lpItem != NULL)
3235 bResult = TRUE;
3237 /* retrieve valid data */
3238 if (lpLVItem->mask & LVIF_STATE)
3240 lpLVItem->state = lpItem->state & lpLVItem->stateMask;
3243 if (lpLVItem->mask & LVIF_TEXT)
3245 if (lpItem->pszText == LPSTR_TEXTCALLBACKA)
3247 lpLVItem->pszText = LPSTR_TEXTCALLBACKA;
3249 else
3251 bResult = Str_GetPtrA(lpItem->pszText, lpLVItem->pszText,
3252 lpLVItem->cchTextMax);
3256 if (lpLVItem->mask & LVIF_IMAGE)
3258 lpLVItem->iImage = lpItem->iImage;
3261 if (lpLVItem->mask & LVIF_PARAM)
3263 lpLVItem->lParam = lpItem->lParam;
3266 if (lpLVItem->mask & LVIF_INDENT)
3268 lpLVItem->iIndent = lpItem->iIndent;
3272 else
3274 lpSubItem = (LISTVIEW_SUBITEM *)DPA_GetPtr(hdpaSubItems,
3275 lpLVItem->iSubItem);
3276 if (lpSubItem != NULL)
3278 bResult = TRUE;
3280 if (lpLVItem->mask & LVIF_TEXT)
3282 if (lpSubItem->pszText == LPSTR_TEXTCALLBACKA)
3284 lpLVItem->pszText = LPSTR_TEXTCALLBACKA;
3286 else
3288 bResult = Str_GetPtrA(lpSubItem->pszText, lpLVItem->pszText,
3289 lpLVItem->cchTextMax);
3293 if (lpLVItem->mask & LVIF_IMAGE)
3295 lpLVItem->iImage = lpSubItem->iImage;
3303 return bResult;
3306 /* LISTVIEW_GetItemW */
3307 /* LISTVIEW_GetHotCursor */
3308 /* LISTVIEW_GetHotItem */
3309 /* LISTVIEW_GetHoverTime> */
3311 /***
3312 * DESCRIPTION:
3313 * Retrieves the number of items in the listview control.
3315 * PARAMETER(S):
3316 * [I] HWND : window handle
3318 * RETURN:
3319 * Number of items.
3321 static LRESULT LISTVIEW_GetItemCount(HWND hwnd)
3323 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
3325 return GETITEMCOUNT(infoPtr);
3328 /***
3329 * DESCRIPTION:
3330 * Retrieves the position (upper-left) of the listview control item.
3332 * PARAMETER(S):
3333 * [I] HWND : window handle
3334 * [I] INT : item index
3335 * [O] LPPOINT : coordinate information
3337 * RETURN:
3338 * SUCCESS : TRUE
3339 * FAILURE : FALSE
3341 static BOOL LISTVIEW_GetItemPosition(HWND hwnd, INT nItem,
3342 LPPOINT lpptPosition)
3344 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
3345 LONG lStyle = GetWindowLongA(hwnd, GWL_STYLE);
3346 BOOL bResult = FALSE;
3347 HDPA hdpaSubItems;
3348 LISTVIEW_ITEM *lpItem;
3349 INT nRow;
3351 TRACE(listview, "(hwnd=%x,nItem=%d,lpptPosition=%p)\n", hwnd, nItem,
3352 lpptPosition);
3354 if ((nItem >= 0) && (nItem < GETITEMCOUNT(infoPtr)) &&
3355 (lpptPosition != NULL))
3357 switch (LVS_TYPEMASK & lStyle)
3359 case LVS_LIST:
3360 bResult = TRUE;
3361 nItem = nItem - ListView_GetTopIndex(hwnd);
3362 if (nItem < 0)
3364 nRow = nItem % infoPtr->nCountPerColumn;
3365 if (nRow == 0)
3367 lpptPosition->x = (nItem / infoPtr->nCountPerColumn *
3368 infoPtr->nItemWidth);
3369 lpptPosition->y = 0;
3371 else
3373 lpptPosition->x = ((nItem / infoPtr->nCountPerColumn - 1) *
3374 infoPtr->nItemWidth);
3375 lpptPosition->y = ((nRow + infoPtr->nCountPerColumn) *
3376 infoPtr->nItemHeight);
3379 else
3381 lpptPosition->x = (nItem / infoPtr->nCountPerColumn *
3382 infoPtr->nItemWidth);
3383 lpptPosition->y = (nItem % infoPtr->nCountPerColumn *
3384 infoPtr->nItemHeight);
3386 break;
3388 case LVS_REPORT:
3389 bResult = TRUE;
3390 lpptPosition->x = REPORT_MARGINX;
3391 lpptPosition->y = ((nItem - ListView_GetTopIndex(hwnd)) *
3392 infoPtr->nItemHeight) + infoPtr->rcList.top;
3393 break;
3395 case LVS_SMALLICON:
3396 case LVS_ICON:
3397 hdpaSubItems = (HDPA)DPA_GetPtr(infoPtr->hdpaItems, nItem);
3398 if (hdpaSubItems != NULL)
3400 lpItem = (LISTVIEW_ITEM *)DPA_GetPtr(hdpaSubItems, 0);
3401 if (lpItem != NULL)
3403 bResult = TRUE;
3404 lpptPosition->x = lpItem->ptPosition.x;
3405 lpptPosition->y = lpItem->ptPosition.y;
3408 break;
3412 return bResult;
3415 /***
3416 * DESCRIPTION:
3417 * Retrieves the bounding rectangle for a listview control item.
3419 * PARAMETER(S):
3420 * [I] HWND : window handle
3421 * [I] INT : item index
3422 * [IO] LPRECT : bounding rectangle coordinates
3424 * RETURN:
3425 * SUCCESS : TRUE
3426 * FAILURE : FALSE
3428 static LRESULT LISTVIEW_GetItemRect(HWND hwnd, INT nItem, LPRECT lprc)
3430 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
3431 LONG lStyle = GetWindowLongA(hwnd, GWL_STYLE);
3432 BOOL bResult = FALSE;
3433 POINT ptOrigin;
3434 POINT ptItem;
3435 HDC hdc;
3436 HFONT hOldFont;
3437 INT nMaxWidth;
3438 INT nLabelWidth;
3439 TEXTMETRICA tm;
3441 TRACE(listview, "(hwnd=%x,nItem=%d,lprc=%p)\n", hwnd, nItem, lprc);
3443 if ((nItem >= 0) && (nItem < GETITEMCOUNT(infoPtr)) && (lprc != NULL))
3445 if (ListView_GetItemPosition(hwnd, nItem, &ptItem) != FALSE)
3447 switch(lprc->left)
3449 case LVIR_ICON:
3450 switch (LVS_TYPEMASK & lStyle)
3452 case LVS_ICON:
3453 if (infoPtr->himlNormal != NULL)
3455 if (LISTVIEW_GetOrigin(hwnd, &ptOrigin) != FALSE)
3457 bResult = TRUE;
3458 lprc->left = ptItem.x + ptOrigin.x;
3459 lprc->top = ptItem.y + ptOrigin.y;
3460 lprc->right = lprc->left + infoPtr->iconSize.cx;
3461 lprc->bottom = (lprc->top + infoPtr->iconSize.cy +
3462 ICON_BOTTOM_PADDING + ICON_TOP_PADDING);
3465 break;
3467 case LVS_SMALLICON:
3468 if (LISTVIEW_GetOrigin(hwnd, &ptOrigin) != FALSE)
3470 bResult = TRUE;
3471 lprc->left = ptItem.x + ptOrigin.x;
3472 lprc->top = ptItem.y + ptOrigin.y;
3473 lprc->bottom = lprc->top + infoPtr->nItemHeight;
3475 if (infoPtr->himlState != NULL)
3477 lprc->left += infoPtr->iconSize.cx;
3480 if (infoPtr->himlSmall != NULL)
3482 lprc->right = lprc->left + infoPtr->iconSize.cx;
3484 else
3486 lprc->right = lprc->left;
3489 break;
3491 case LVS_REPORT:
3492 case LVS_LIST:
3493 bResult = TRUE;
3494 lprc->left = ptItem.x;
3495 lprc->top = ptItem.y;
3496 lprc->bottom = lprc->top + infoPtr->nItemHeight;
3498 if (infoPtr->himlState != NULL)
3500 lprc->left += infoPtr->iconSize.cx;
3503 if (infoPtr->himlSmall != NULL)
3505 lprc->right = lprc->left + infoPtr->iconSize.cx;
3507 else
3509 lprc->right = lprc->left;
3511 break;
3513 break;
3515 case LVIR_LABEL:
3516 switch (LVS_TYPEMASK & lStyle)
3518 case LVS_ICON:
3519 if (infoPtr->himlNormal != NULL)
3521 if (LISTVIEW_GetOrigin(hwnd, &ptOrigin) != FALSE)
3523 bResult = TRUE;
3524 lprc->left = ptItem.x + ptOrigin.x;
3525 lprc->top = (ptItem.y + ptOrigin.y + infoPtr->iconSize.cy +
3526 ICON_BOTTOM_PADDING + ICON_TOP_PADDING);
3527 nLabelWidth = LISTVIEW_GetLabelWidth(hwnd, nItem);
3528 if (infoPtr->iconSpacing.cx - nLabelWidth > 1)
3530 lprc->left += (infoPtr->iconSpacing.cx - nLabelWidth) / 2;
3531 lprc->right = lprc->left + nLabelWidth;
3533 else
3535 lprc->left += 1;
3536 lprc->right = lprc->left + infoPtr->iconSpacing.cx - 1;
3539 hdc = GetDC(hwnd);
3540 hOldFont = SelectObject(hdc, infoPtr->hFont);
3541 GetTextMetricsA(hdc, &tm);
3542 lprc->bottom = lprc->top + tm.tmHeight + HEIGHT_PADDING;
3543 SelectObject(hdc, hOldFont);
3544 ReleaseDC(hwnd, hdc);
3547 break;
3549 case LVS_SMALLICON:
3550 if (LISTVIEW_GetOrigin(hwnd, &ptOrigin) != FALSE)
3552 bResult = TRUE;
3553 nMaxWidth = lprc->left = ptItem.x + ptOrigin.x;
3554 lprc->top = ptItem.y + ptOrigin.y;
3555 lprc->bottom = lprc->top + infoPtr->nItemHeight;
3557 if (infoPtr->himlState != NULL)
3559 lprc->left += infoPtr->iconSize.cx;
3562 if (infoPtr->himlSmall != NULL)
3564 lprc->left += infoPtr->iconSize.cx;
3567 nLabelWidth = LISTVIEW_GetLabelWidth(hwnd, nItem);
3568 if (lprc->left + nLabelWidth < nMaxWidth + infoPtr->nItemWidth)
3570 lprc->right = lprc->left + nLabelWidth;
3572 else
3574 lprc->right = nMaxWidth + infoPtr->nItemWidth;
3577 break;
3579 case LVS_REPORT:
3580 case LVS_LIST:
3581 bResult = TRUE;
3582 lprc->left = ptItem.x;
3583 lprc->top = ptItem.y;
3584 lprc->bottom = lprc->top + infoPtr->nItemHeight;
3586 if (infoPtr->himlState != NULL)
3588 lprc->left += infoPtr->iconSize.cx;
3591 if (infoPtr->himlSmall != NULL)
3593 lprc->left += infoPtr->iconSize.cx;
3596 lprc->right = lprc->left + LISTVIEW_GetLabelWidth(hwnd, nItem);
3597 break;
3599 break;
3601 case LVIR_BOUNDS:
3602 switch (LVS_TYPEMASK & lStyle)
3604 case LVS_ICON:
3605 if (infoPtr->himlNormal != NULL)
3607 if (LISTVIEW_GetOrigin(hwnd, &ptOrigin) != FALSE)
3609 bResult = TRUE;
3610 lprc->left = ptItem.x + ptOrigin.x;
3611 lprc->top = ptItem.y + ptOrigin.y;
3612 lprc->right = lprc->left + infoPtr->iconSpacing.cx;
3613 lprc->bottom = lprc->top + infoPtr->iconSpacing.cy;
3616 break;
3618 case LVS_SMALLICON:
3619 if (LISTVIEW_GetOrigin(hwnd, &ptOrigin) != FALSE)
3621 bResult = TRUE;
3622 lprc->left = ptItem.x +ptOrigin.x;
3623 lprc->right = lprc->left;
3624 lprc->top = ptItem.y + ptOrigin.y;
3625 lprc->bottom = lprc->top + infoPtr->nItemHeight;
3627 if (infoPtr->himlState != NULL)
3629 lprc->right += infoPtr->iconSize.cx;
3632 if (infoPtr->himlSmall != NULL)
3634 lprc->right += infoPtr->iconSize.cx;
3637 lprc->right += LISTVIEW_GetLabelWidth(hwnd, nItem);
3639 break;
3641 case LVS_REPORT:
3642 case LVS_LIST:
3643 bResult = TRUE;
3644 lprc->left = ptItem.x;
3645 lprc->right = lprc->left;
3646 lprc->top = ptItem.y;
3647 lprc->bottom = lprc->top + infoPtr->nItemHeight;
3649 if (infoPtr->himlState != NULL)
3651 lprc->right += infoPtr->iconSize.cx;
3654 if (infoPtr->himlSmall != NULL)
3656 lprc->right += infoPtr->iconSize.cx;
3659 lprc->right += LISTVIEW_GetLabelWidth(hwnd, nItem);
3660 break;
3662 break;
3664 case LVIR_SELECTBOUNDS:
3665 switch (LVS_TYPEMASK & lStyle)
3667 case LVS_ICON:
3668 if (infoPtr->himlNormal != NULL)
3670 if (LISTVIEW_GetOrigin(hwnd, &ptOrigin) != FALSE)
3672 bResult = TRUE;
3673 lprc->left = ptItem.x + ptOrigin.x;
3674 lprc->top = ptItem.y + ptOrigin.y;
3675 lprc->right = lprc->left + infoPtr->iconSpacing.cx;
3676 lprc->bottom = lprc->top + infoPtr->iconSpacing.cy;
3679 break;
3681 case LVS_SMALLICON:
3682 if (LISTVIEW_GetOrigin(hwnd, &ptOrigin) != FALSE)
3684 bResult = TRUE;
3685 lprc->left = ptItem.x + ptOrigin.x;
3686 lprc->top = ptItem.y + ptOrigin.y;
3687 lprc->bottom = lprc->top + infoPtr->nItemHeight;
3689 if (infoPtr->himlState != NULL)
3691 lprc->left += infoPtr->iconSize.cx;
3694 lprc->right = lprc->left;
3696 if (infoPtr->himlSmall != NULL)
3698 lprc->right += infoPtr->iconSize.cx;
3701 lprc->right += LISTVIEW_GetLabelWidth(hwnd, nItem);
3703 break;
3705 case LVS_REPORT:
3706 case LVS_LIST:
3707 bResult = TRUE;
3708 lprc->left = ptItem.x;
3709 lprc->top = ptItem.y;
3710 lprc->bottom = lprc->top + infoPtr->nItemHeight;
3712 if (infoPtr->himlState != NULL)
3714 lprc->left += infoPtr->iconSize.cx;
3717 lprc->right = lprc->left;
3719 if (infoPtr->himlSmall != NULL)
3721 lprc->right += infoPtr->iconSize.cx;
3724 lprc->right += LISTVIEW_GetLabelWidth(hwnd, nItem);
3725 break;
3727 break;
3732 return bResult;
3735 /***
3736 * DESCRIPTION:
3737 * Retrieves the width of a label.
3739 * PARAMETER(S):
3740 * [I] HWND : window handle
3742 * RETURN:
3743 * SUCCESS : string width (in pixels)
3744 * FAILURE : zero
3747 static INT LISTVIEW_GetLabelWidth(HWND hwnd, INT nItem)
3749 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
3750 LISTVIEW_ITEM *lpItem;
3751 HDPA hdpaSubItems;
3752 INT nLabelWidth = 0;
3754 TRACE(listview, "(hwnd=%x,nItem=%d)\n", hwnd, nItem);
3756 hdpaSubItems = (HDPA)DPA_GetPtr(infoPtr->hdpaItems, nItem);
3757 if (hdpaSubItems != NULL)
3759 lpItem = (LISTVIEW_ITEM *)DPA_GetPtr(hdpaSubItems, 0);
3760 if (lpItem != NULL)
3762 CHAR szDispText[DISP_TEXT_SIZE];
3763 LPSTR pszDispText = NULL;
3764 pszDispText = szDispText;
3765 LISTVIEW_GetItemDispInfo(hwnd, nItem, lpItem, NULL, NULL, &pszDispText,
3766 DISP_TEXT_SIZE);
3767 nLabelWidth = ListView_GetStringWidthA(hwnd, pszDispText);
3771 return nLabelWidth;
3774 /***
3775 * DESCRIPTION:
3776 * Retrieves the spacing between listview control items.
3778 * PARAMETER(S):
3779 * [I] HWND : window handle
3780 * [I] BOOL : flag for small or large icon
3782 * RETURN:
3783 * Horizontal + vertical spacing
3785 static LRESULT LISTVIEW_GetItemSpacing(HWND hwnd, BOOL bSmall)
3787 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
3788 LONG lResult;
3790 if (bSmall == FALSE)
3792 lResult = MAKELONG(infoPtr->iconSpacing.cx, infoPtr->iconSpacing.cy);
3794 else
3796 /* TODO: need to store width of smallicon item */
3797 lResult = MAKELONG(0, infoPtr->nItemHeight);
3800 return lResult;
3803 /***
3804 * DESCRIPTION:
3805 * Retrieves the state of a listview control item.
3807 * PARAMETER(S):
3808 * [I] HWND : window handle
3809 * [I] INT : item index
3810 * [I] UINT : state mask
3812 * RETURN:
3813 * State specified by the mask.
3815 static LRESULT LISTVIEW_GetItemState(HWND hwnd, INT nItem, UINT uMask)
3817 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
3818 LVITEMA lvItem;
3819 UINT uState = 0;
3821 if ((nItem >= 0) && (nItem < GETITEMCOUNT(infoPtr)))
3823 ZeroMemory(&lvItem, sizeof(LVITEMA));
3824 lvItem.iItem = nItem;
3825 lvItem.stateMask = uMask;
3826 lvItem.mask = LVIF_STATE;
3827 if (ListView_GetItemA(hwnd, &lvItem) != FALSE)
3829 uState = lvItem.state;
3833 return uState;
3836 /***
3837 * DESCRIPTION:
3838 * Retrieves the text of a listview control item or subitem.
3840 * PARAMETER(S):
3841 * [I] HWND : window handle
3842 * [I] INT : item index
3843 * [IO] LPLVITEMA : item information
3845 * RETURN:
3846 * None
3848 static LRESULT LISTVIEW_GetItemTextA(HWND hwnd, INT nItem, LPLVITEMA lpLVItem)
3850 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
3851 LISTVIEW_ITEM *lpItem;
3852 LISTVIEW_SUBITEM *lpSubItem;
3853 HDPA hdpaSubItems;
3854 INT nLength = 0;
3856 if (lpLVItem != NULL)
3858 if ((nItem >= 0) && (nItem < GETITEMCOUNT(infoPtr)))
3860 hdpaSubItems = (HDPA)DPA_GetPtr(infoPtr->hdpaItems, lpLVItem->iItem);
3861 if (hdpaSubItems != NULL)
3863 if (lpLVItem->iSubItem == 0)
3865 lpItem = (LISTVIEW_ITEM *)DPA_GetPtr(hdpaSubItems, 0);
3866 if (lpItem != NULL)
3868 if (lpLVItem->mask & LVIF_TEXT)
3870 if (lpItem->pszText == LPSTR_TEXTCALLBACKA)
3872 lpLVItem->pszText = LPSTR_TEXTCALLBACKA;
3874 else
3876 nLength = Str_GetPtrA(lpItem->pszText, lpLVItem->pszText,
3877 lpLVItem->cchTextMax);
3882 else
3884 lpSubItem = (LISTVIEW_SUBITEM *)DPA_GetPtr(hdpaSubItems,
3885 lpLVItem->iSubItem);
3886 if (lpSubItem != NULL)
3888 if (lpLVItem->mask & LVIF_TEXT)
3890 if (lpSubItem->pszText == LPSTR_TEXTCALLBACKA)
3892 lpLVItem->pszText = LPSTR_TEXTCALLBACKA;
3894 else
3896 nLength = Str_GetPtrA(lpSubItem->pszText, lpLVItem->pszText,
3897 lpLVItem->cchTextMax);
3906 return nLength;
3909 /***
3910 * DESCRIPTION:
3911 * Searches for an item based on properties + relationships.
3913 * PARAMETER(S):
3914 * [I] HWND : window handle
3915 * [I] INT : item index
3916 * [I] UINT : relationship flag
3918 * RETURN:
3919 * SUCCESS : item index
3920 * FAILURE : -1
3922 static LRESULT LISTVIEW_GetNextItem(HWND hwnd, INT nItem, UINT uFlags)
3924 FIXME (listview, "empty stub!\n");
3926 return -1;
3929 /* LISTVIEW_GetNumberOfWorkAreas */
3931 /***
3932 * DESCRIPTION:
3933 * Retrieves the origin coordinates when in icon or small icon display mode.
3935 * PARAMETER(S):
3936 * [I] HWND : window handle
3937 * [O] LPPOINT : coordinate information
3939 * RETURN:
3940 * SUCCESS : TRUE
3941 * FAILURE : FALSE
3943 static LRESULT LISTVIEW_GetOrigin(HWND hwnd, LPPOINT lpptOrigin)
3945 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
3946 LONG lStyle = GetWindowLongA(hwnd, GWL_STYLE);
3947 INT nListWidth = infoPtr->rcList.right - infoPtr->rcList.left;
3948 INT nListHeight = infoPtr->rcList.bottom - infoPtr->rcList.top;
3949 BOOL bResult = FALSE;
3951 TRACE(listview, "(hwnd=%x,lpptOrigin=%p)\n", hwnd, lpptOrigin);
3953 switch (LVS_TYPEMASK & lStyle)
3955 case LVS_ICON:
3956 case LVS_SMALLICON:
3957 if ((lStyle & WS_HSCROLL) != 0)
3959 lpptOrigin->x = -GetScrollPos(hwnd, SB_HORZ) * nListWidth / 10;
3961 else
3963 lpptOrigin->x = 0;
3966 if ((lStyle & WS_VSCROLL) != 0)
3968 lpptOrigin->y = -GetScrollPos(hwnd, SB_VERT) * nListHeight / 10;
3970 else
3972 lpptOrigin->y = 0;
3975 bResult = TRUE;
3976 break;
3979 return bResult;
3982 /***
3983 * DESCRIPTION:
3984 * Retrieves the number of items that are marked as selected.
3986 * PARAMETER(S):
3987 * [I] HWND : window handle
3989 * RETURN:
3990 * Number of items selected.
3992 static LRESULT LISTVIEW_GetSelectedCount(HWND hwnd)
3994 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
3995 INT nSelectedCount = 0;
3996 INT i;
3998 for (i = 0; i < GETITEMCOUNT(infoPtr); i++)
4000 if (ListView_GetItemState(hwnd, i, LVIS_SELECTED) & LVIS_SELECTED)
4002 nSelectedCount++;
4006 return nSelectedCount;
4009 /***
4010 * DESCRIPTION:
4011 * Retrieves item index that marks the start of a multiple selection.
4013 * PARAMETER(S):
4014 * [I] HWND : window handle
4016 * RETURN:
4017 * Index number or -1 if there is no selection mark.
4019 static LRESULT LISTVIEW_GetSelectionMark(HWND hwnd)
4021 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
4023 return infoPtr->nSelectionMark;
4026 /***
4027 * DESCRIPTION:
4028 * Retrieves the width of a string.
4030 * PARAMETER(S):
4031 * [I] HWND : window handle
4033 * RETURN:
4034 * SUCCESS : string width (in pixels)
4035 * FAILURE : zero
4037 static LRESULT LISTVIEW_GetStringWidthA(HWND hwnd, LPCSTR lpszText)
4039 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
4040 HFONT hFont, hOldFont;
4041 SIZE stringSize;
4042 HDC hdc;
4044 ZeroMemory(&stringSize, sizeof(SIZE));
4045 if (lpszText != NULL)
4047 hFont = infoPtr->hFont ? infoPtr->hFont : infoPtr->hDefaultFont;
4048 hdc = GetDC(hwnd);
4049 hOldFont = SelectObject(hdc, hFont);
4050 GetTextExtentPointA(hdc, lpszText, lstrlenA(lpszText), &stringSize);
4051 SelectObject(hdc, hOldFont);
4052 ReleaseDC(hwnd, hdc);
4055 return stringSize.cx;
4058 /***
4059 * DESCRIPTION:
4060 * Retrieves the text backgound color.
4062 * PARAMETER(S):
4063 * [I] HWND : window handle
4065 * RETURN:
4066 * COLORREF associated with the the background.
4068 static LRESULT LISTVIEW_GetTextBkColor(HWND hwnd)
4070 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO*)GetWindowLongA(hwnd, 0);
4072 return infoPtr->clrTextBk;
4075 /***
4076 * DESCRIPTION:
4077 * Retrieves the text color.
4079 * PARAMETER(S):
4080 * [I] HWND : window handle
4082 * RETURN:
4083 * COLORREF associated with the text.
4085 static LRESULT LISTVIEW_GetTextColor(HWND hwnd)
4087 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO*)GetWindowLongA(hwnd, 0);
4089 return infoPtr->clrText;
4092 /***
4093 * DESCRIPTION:
4094 * Set the bounding rectangle of all the items.
4096 * PARAMETER(S):
4097 * [I] HWND : window handle
4098 * [I] LPRECT : bounding rectangle
4100 * RETURN:
4101 * SUCCESS : TRUE
4102 * FAILURE : FALSE
4104 static LRESULT LISTVIEW_SetViewRect(HWND hwnd, LPRECT lprcView)
4106 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO*)GetWindowLongA(hwnd, 0);
4107 LONG lStyle = GetWindowLongA(hwnd, GWL_STYLE);
4108 BOOL bResult = FALSE;
4110 TRACE(listview, "(hwnd=%x,lprcView->left=%d,lprcView->top=%d,lprcView->right=%d,lprcView->bottom=%d)\n", hwnd, lprcView->left, lprcView->top, lprcView->right, lprcView->bottom);
4112 if (lprcView != NULL)
4114 switch (lStyle & LVS_TYPEMASK)
4116 case LVS_ICON:
4117 case LVS_SMALLICON:
4118 bResult = TRUE;
4119 infoPtr->rcView.left = lprcView->left;
4120 infoPtr->rcView.top = lprcView->top;
4121 infoPtr->rcView.right = lprcView->right;
4122 infoPtr->rcView.bottom = lprcView->bottom;
4123 break;
4127 return bResult;
4130 /***
4131 * DESCRIPTION:
4132 * Retrieves the bounding rectangle of all the items.
4134 * PARAMETER(S):
4135 * [I] HWND : window handle
4136 * [O] LPRECT : bounding rectangle
4138 * RETURN:
4139 * SUCCESS : TRUE
4140 * FAILURE : FALSE
4142 static LRESULT LISTVIEW_GetViewRect(HWND hwnd, LPRECT lprcView)
4144 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO*)GetWindowLongA(hwnd, 0);
4145 BOOL bResult = FALSE;
4146 POINT ptOrigin;
4148 TRACE(listview, "(hwnd=%x,lprcView=%p)\n", hwnd, lprcView);
4150 if (lprcView != NULL)
4152 bResult = LISTVIEW_GetOrigin(hwnd, &ptOrigin);
4153 if (bResult != FALSE)
4155 lprcView->left = infoPtr->rcView.left + ptOrigin.x;
4156 lprcView->top = infoPtr->rcView.top + ptOrigin.y;
4157 lprcView->right = infoPtr->rcView.right + ptOrigin.x;
4158 lprcView->bottom = infoPtr->rcView.bottom + ptOrigin.y;
4161 TRACE(listview, "(lprcView->left=%d,lprcView->top=%d,lprcView->right=%d,lprcView->bottom=%d)\n", lprcView->left, lprcView->top, lprcView->right, lprcView->bottom);
4165 return bResult;
4168 /***
4169 * DESCRIPTION:
4170 * Determines which section of the item was selected (if any).
4172 * PARAMETER(S):
4173 * [I] HWND : window handle
4174 * [IO] LPLVHITTESTINFO : hit test information
4176 * RETURN:
4177 * SUCCESS : item index
4178 * FAILURE : -1
4180 static INT LISTVIEW_HitTestItem(HWND hwnd, LPLVHITTESTINFO lpHitTestInfo)
4182 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
4183 RECT rcItem;
4184 INT i;
4186 for (i = 0; i < GETITEMCOUNT(infoPtr); i++)
4188 rcItem.left = LVIR_BOUNDS;
4189 if (LISTVIEW_GetItemRect(hwnd, i, &rcItem) != FALSE)
4191 rcItem.left = LVIR_ICON;
4192 if (LISTVIEW_GetItemRect(hwnd, i, &rcItem) != FALSE)
4194 if ((lpHitTestInfo->pt.x >= rcItem.left) &&
4195 (lpHitTestInfo->pt.x <= rcItem.right) &&
4196 (lpHitTestInfo->pt.y >= rcItem.top) &&
4197 (lpHitTestInfo->pt.y <= rcItem.bottom))
4199 lpHitTestInfo->flags = LVHT_ONITEMICON | LVHT_ONITEM;
4200 lpHitTestInfo->iItem = i;
4201 lpHitTestInfo->iSubItem = 0;
4202 return i;
4206 rcItem.left = LVIR_LABEL;
4207 if (LISTVIEW_GetItemRect(hwnd, i, &rcItem) != FALSE)
4209 if ((lpHitTestInfo->pt.x >= rcItem.left) &&
4210 (lpHitTestInfo->pt.x <= rcItem.right) &&
4211 (lpHitTestInfo->pt.y >= rcItem.top) &&
4212 (lpHitTestInfo->pt.y <= rcItem.bottom))
4214 lpHitTestInfo->flags = LVHT_ONITEMLABEL | LVHT_ONITEM;
4215 lpHitTestInfo->iItem = i;
4216 lpHitTestInfo->iSubItem = 0;
4217 return i;
4221 lpHitTestInfo->flags = LVHT_ONITEMSTATEICON | LVHT_ONITEM;
4222 lpHitTestInfo->iItem = i;
4223 lpHitTestInfo->iSubItem = 0;
4224 return i;
4228 lpHitTestInfo->flags = LVHT_NOWHERE;
4230 return -1;
4233 /***
4234 * DESCRIPTION:
4235 * Determines wich listview item is located at the specified position.
4237 * PARAMETER(S):
4238 * [I] HWND : window handle
4239 * [IO} LPLVHITTESTINFO : hit test information
4241 * RETURN:
4242 * SUCCESS : item index
4243 * FAILURE : -1
4245 static LRESULT LISTVIEW_HitTest(HWND hwnd, LPLVHITTESTINFO lpHitTestInfo)
4247 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
4248 INT nItem = -1;
4250 lpHitTestInfo->flags = 0;
4251 if (infoPtr->rcList.left > lpHitTestInfo->pt.x)
4253 lpHitTestInfo->flags = LVHT_TOLEFT;
4255 else if (infoPtr->rcList.right < lpHitTestInfo->pt.x)
4257 lpHitTestInfo->flags = LVHT_TORIGHT;
4260 if (infoPtr->rcList.top > lpHitTestInfo->pt.y)
4262 lpHitTestInfo->flags |= LVHT_ABOVE;
4264 else if (infoPtr->rcList.bottom < lpHitTestInfo->pt.y)
4266 lpHitTestInfo->flags |= LVHT_BELOW;
4269 if (lpHitTestInfo->flags == 0)
4271 nItem = LISTVIEW_HitTestItem(hwnd, lpHitTestInfo);
4274 return nItem;
4277 /***
4278 * DESCRIPTION:
4279 * Inserts a new column.
4281 * PARAMETER(S):
4282 * [I] HWND : window handle
4283 * [I] INT : column index
4284 * [I] LPLVCOLUMNA : column information
4286 * RETURN:
4287 * SUCCESS : new column index
4288 * FAILURE : -1
4290 static LRESULT LISTVIEW_InsertColumnA(HWND hwnd, INT nColumn,
4291 LPLVCOLUMNA lpColumn)
4293 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
4294 LONG lStyle = GetWindowLongA(hwnd, GWL_STYLE);
4295 HDITEMA hdi;
4296 INT nNewColumn = -1;
4298 TRACE(listview,"(hwnd=%x,nColumn=%d,lpColumn=%p)\n",hwnd, nColumn, lpColumn);
4300 if (lpColumn != NULL)
4302 /* initialize memory */
4303 ZeroMemory(&hdi, sizeof(HDITEMA));
4305 if (lpColumn->mask & LVCF_FMT)
4307 /* format member is valid */
4308 hdi.mask |= HDI_FORMAT;
4310 /* set text alignment (leftmost column must be left-aligned) */
4311 if (nColumn == 0)
4313 hdi.fmt |= HDF_LEFT;
4315 else
4317 if (lpColumn->fmt & LVCFMT_LEFT)
4319 hdi.fmt |= HDF_LEFT;
4321 else if (lpColumn->fmt & LVCFMT_RIGHT)
4323 hdi.fmt |= HDF_RIGHT;
4325 else if (lpColumn->fmt & LVCFMT_CENTER)
4327 hdi.fmt |= HDF_CENTER;
4331 if (lpColumn->fmt & LVCFMT_BITMAP_ON_RIGHT)
4333 hdi.fmt |= HDF_BITMAP_ON_RIGHT;
4334 /* ??? */
4337 if (lpColumn->fmt & LVCFMT_COL_HAS_IMAGES)
4339 /* ??? */
4342 if (lpColumn->fmt & LVCFMT_IMAGE)
4344 hdi.fmt |= HDF_IMAGE;
4345 hdi.iImage = I_IMAGECALLBACK;
4349 if (lpColumn->mask & LVCF_WIDTH)
4351 hdi.mask |= HDI_WIDTH;
4352 hdi.cxy = lpColumn->cx;
4355 if (lpColumn->mask & LVCF_TEXT)
4357 hdi.mask |= HDI_TEXT | HDI_FORMAT;
4358 hdi.pszText = lpColumn->pszText;
4359 hdi.cchTextMax = lstrlenA(lpColumn->pszText);
4360 hdi.fmt |= HDF_STRING;
4363 if (lpColumn->mask & LVCF_IMAGE)
4365 hdi.mask |= HDI_IMAGE;
4366 hdi.iImage = lpColumn->iImage;
4369 if (lpColumn->mask & LVCF_ORDER)
4371 hdi.mask |= HDI_ORDER;
4372 hdi.iOrder = lpColumn->iOrder;
4375 /* insert item in header control */
4376 nNewColumn = SendMessageA(infoPtr->hwndHeader, HDM_INSERTITEMA,
4377 (WPARAM)nColumn, (LPARAM)&hdi);
4379 LISTVIEW_SetScroll(hwnd, lStyle);
4380 InvalidateRect(hwnd, NULL, FALSE);
4383 return nNewColumn;
4386 /* LISTVIEW_InsertColumnW */
4388 /***
4389 * DESCRIPTION:
4390 * Inserts a new item in the listview control.
4392 * PARAMETER(S):
4393 * [I] HWND : window handle
4394 * [I] LPLVITEMA : item information
4396 * RETURN:
4397 * SUCCESS : new item index
4398 * FAILURE : -1
4400 static LRESULT LISTVIEW_InsertItemA(HWND hwnd, LPLVITEMA lpLVItem)
4402 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
4403 LONG lStyle = GetWindowLongA(hwnd, GWL_STYLE);
4404 LONG lCtrlId = GetWindowLongA(hwnd, GWL_ID);
4405 NMLISTVIEW nmlv;
4406 INT nItem = -1;
4407 HDPA hdpaSubItems;
4408 LISTVIEW_ITEM *lpItem = NULL;
4410 TRACE(listview, "(hwnd=%x,lpLVItem=%p)\n", hwnd, lpLVItem);
4412 if (lpLVItem != NULL)
4414 /* make sure it's not a subitem; cannot insert a subitem */
4415 if (lpLVItem->iSubItem == 0)
4417 lpItem = (LISTVIEW_ITEM *)COMCTL32_Alloc(sizeof(LISTVIEW_ITEM));
4418 if (lpItem != NULL)
4420 ZeroMemory(lpItem, sizeof(LISTVIEW_ITEM));
4421 if (LISTVIEW_InitItem(hwnd, lpItem, lpLVItem) != FALSE)
4423 /* insert item in listview control data structure */
4424 hdpaSubItems = DPA_Create(8);
4425 if (hdpaSubItems != NULL)
4427 nItem = DPA_InsertPtr(hdpaSubItems, 0, lpItem);
4428 if (nItem != -1)
4430 nItem = DPA_InsertPtr(infoPtr->hdpaItems, lpLVItem->iItem,
4431 hdpaSubItems);
4432 if (nItem != -1)
4434 /* manage item focus */
4435 if (lpLVItem->mask & LVIF_STATE)
4437 if (lpLVItem->stateMask & LVIS_FOCUSED)
4439 LISTVIEW_SetItemFocus(hwnd, nItem);
4443 /* send LVN_INSERTITEM notification */
4444 ZeroMemory(&nmlv, sizeof(NMLISTVIEW));
4445 nmlv.hdr.hwndFrom = hwnd;
4446 nmlv.hdr.idFrom = lCtrlId;
4447 nmlv.hdr.code = LVN_INSERTITEM;
4448 nmlv.iItem = nItem;
4449 nmlv.lParam = lpItem->lParam;;
4450 ListView_LVNotify(GetParent(hwnd), lCtrlId, &nmlv);
4452 /* align items (set position of each item) */
4453 switch (lStyle & LVS_TYPEMASK)
4455 case LVS_ICON:
4456 case LVS_SMALLICON:
4457 if (lStyle & LVS_ALIGNLEFT)
4459 LISTVIEW_AlignLeft(hwnd);
4461 else
4463 LISTVIEW_AlignTop(hwnd);
4465 break;
4468 LISTVIEW_SetScroll(hwnd, lStyle);
4469 /* refresh client area */
4470 InvalidateRect(hwnd, NULL, FALSE);
4479 /* free memory if unsuccessful */
4480 if ((nItem == -1) && (lpItem != NULL))
4482 COMCTL32_Free(lpItem);
4485 return nItem;
4488 /* LISTVIEW_InsertItemW */
4490 /***
4491 * DESCRIPTION:
4492 * Redraws a range of items.
4494 * PARAMETER(S):
4495 * [I] HWND : window handle
4496 * [I] INT : first item
4497 * [I] INT : last item
4499 * RETURN:
4500 * SUCCESS : TRUE
4501 * FAILURE : FALSE
4503 static LRESULT LISTVIEW_RedrawItems(HWND hwnd, INT nFirst, INT nLast)
4505 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
4506 BOOL bResult = FALSE;
4507 RECT rc;
4509 if (nFirst <= nLast)
4511 if ((nFirst >= 0) && (nFirst < GETITEMCOUNT(infoPtr)))
4513 if ((nLast >= 0) && (nLast < GETITEMCOUNT(infoPtr)))
4515 /* bResult = */
4516 InvalidateRect(hwnd, &rc, FALSE);
4521 return bResult;
4524 /* LISTVIEW_Scroll */
4526 /***
4527 * DESCRIPTION:
4528 * Sets the background color.
4530 * PARAMETER(S):
4531 * [I] HWND : window handle
4532 * [I] COLORREF : background color
4534 * RETURN:
4535 * SUCCESS : TRUE
4536 * FAILURE : FALSE
4538 static LRESULT LISTVIEW_SetBkColor(HWND hwnd, COLORREF clrBk)
4540 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
4542 infoPtr->clrBk = clrBk;
4543 InvalidateRect(hwnd, NULL, TRUE);
4545 return TRUE;
4548 /***
4549 * DESCRIPTION:
4550 * Sets the callback mask. This mask will be used when the parent
4551 * window stores state information (some or all).
4553 * PARAMETER(S):
4554 * [I] HWND : window handle
4555 * [I] UINT : state mask
4557 * RETURN:
4558 * SUCCESS : TRUE
4559 * FAILURE : FALSE
4561 static BOOL LISTVIEW_SetCallbackMask(HWND hwnd, UINT uMask)
4563 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
4565 infoPtr->uCallbackMask = uMask;
4567 return TRUE;
4570 /***
4571 * DESCRIPTION:
4572 * Sets the attributes of a header item.
4574 * PARAMETER(S):
4575 * [I] HWND : window handle
4576 * [I] INT : column index
4577 * [I] LPLVCOLUMNA : column attributes
4579 * RETURN:
4580 * SUCCESS : TRUE
4581 * FAILURE : FALSE
4583 static LRESULT LISTVIEW_SetColumnA(HWND hwnd, INT nColumn,
4584 LPLVCOLUMNA lpColumn)
4586 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
4587 BOOL bResult = FALSE;
4588 HDITEMA hdi;
4590 if ((lpColumn != NULL) && (nColumn >= 0) &&
4591 (nColumn < Header_GetItemCount(infoPtr->hwndHeader)))
4593 /* initialize memory */
4594 ZeroMemory(&hdi, sizeof(HDITEMA));
4596 if (lpColumn->mask & LVCF_FMT)
4598 /* format member is valid */
4599 hdi.mask |= HDI_FORMAT;
4601 /* set text alignment (leftmost column must be left-aligned) */
4602 if (nColumn == 0)
4604 hdi.fmt |= HDF_LEFT;
4606 else
4608 if (lpColumn->fmt & LVCFMT_LEFT)
4610 hdi.fmt |= HDF_LEFT;
4612 else if (lpColumn->fmt & LVCFMT_RIGHT)
4614 hdi.fmt |= HDF_RIGHT;
4616 else if (lpColumn->fmt & LVCFMT_CENTER)
4618 hdi.fmt |= HDF_CENTER;
4622 if (lpColumn->fmt & LVCFMT_BITMAP_ON_RIGHT)
4624 hdi.fmt |= HDF_BITMAP_ON_RIGHT;
4627 if (lpColumn->fmt & LVCFMT_COL_HAS_IMAGES)
4629 hdi.fmt |= HDF_IMAGE;
4632 if (lpColumn->fmt & LVCFMT_IMAGE)
4634 hdi.fmt |= HDF_IMAGE;
4635 hdi.iImage = I_IMAGECALLBACK;
4639 if (lpColumn->mask & LVCF_WIDTH)
4641 hdi.mask |= HDI_WIDTH;
4642 hdi.cxy = lpColumn->cx;
4645 if (lpColumn->mask & LVCF_TEXT)
4647 hdi.mask |= HDI_TEXT | HDI_FORMAT;
4648 hdi.pszText = lpColumn->pszText;
4649 hdi.cchTextMax = lstrlenA(lpColumn->pszText);
4650 hdi.fmt |= HDF_STRING;
4653 if (lpColumn->mask & LVCF_IMAGE)
4655 hdi.mask |= HDI_IMAGE;
4656 hdi.iImage = lpColumn->iImage;
4659 if (lpColumn->mask & LVCF_ORDER)
4661 hdi.mask |= HDI_ORDER;
4662 hdi.iOrder = lpColumn->iOrder;
4665 /* set header item attributes */
4666 bResult = Header_SetItemA(infoPtr->hwndHeader, nColumn, &hdi);
4669 return bResult;
4672 /***
4673 * DESCRIPTION:
4674 * Sets the width of a column
4676 * PARAMETERS:
4677 * [I] HWND : window handle
4678 * [I] INT : column index
4679 * [I] INT : column width
4681 * RETURN:
4682 * SUCCESS : TRUE
4683 * FAILURE : FALSE
4685 static LRESULT LISTVIEW_SetColumnWidth(HWND hwnd, INT iCol, INT cx)
4687 LISTVIEW_INFO *infoPtr;
4688 HDITEMA hdi;
4689 LRESULT lret;
4690 LONG lStyle;
4692 // set column width only if in report mode
4693 lStyle = GetWindowLongA(hwnd, GWL_STYLE);
4694 if ((lStyle & LVS_TYPEMASK) != LVS_REPORT)
4695 return (FALSE);
4697 // make sure we can get the listview info
4698 if (!(infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0)))
4699 return (FALSE);
4700 if (!infoPtr->hwndHeader) // make sure we have a header
4701 return (FALSE);
4703 // FIXME: currently ignoring LVSCW_AUTOSIZE (-1) and
4704 // LVSCV_AUTOSIZE_USEHEADER (-2)
4705 if (cx < 0)
4706 return (FALSE);
4708 hdi.mask = HDI_WIDTH;
4709 hdi.cxy = cx;
4711 // call header to update the column change
4712 lret = Header_SetItemA(infoPtr->hwndHeader, (WPARAM)iCol, (LPARAM)&hdi);
4714 infoPtr->nItemWidth = LISTVIEW_GetItemWidth(hwnd, LVS_REPORT);
4716 InvalidateRect(hwnd, NULL, TRUE); // force redraw of the listview
4718 return lret;
4721 /***
4722 * DESCRIPTION:
4723 * Sets image lists.
4725 * PARAMETER(S):
4726 * [I] HWND : window handle
4727 * [I] INT : image list type
4728 * [I] HIMAGELIST : image list handle
4730 * RETURN:
4731 * SUCCESS : old image list
4732 * FAILURE : NULL
4734 static LRESULT LISTVIEW_SetImageList(HWND hwnd, INT nType, HIMAGELIST himl)
4736 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
4737 HIMAGELIST himlTemp = 0;
4739 switch (nType)
4741 case LVSIL_NORMAL:
4742 himlTemp = infoPtr->himlNormal;
4743 infoPtr->himlNormal = himl;
4744 return (LRESULT)himlTemp;
4746 case LVSIL_SMALL:
4747 himlTemp = infoPtr->himlSmall;
4748 infoPtr->himlSmall = himl;
4749 return (LRESULT)himlTemp;
4751 case LVSIL_STATE:
4752 himlTemp = infoPtr->himlState;
4753 infoPtr->himlState = himl;
4754 return (LRESULT)himlTemp;
4757 return (LRESULT)NULL;
4761 /***
4762 * DESCRIPTION:
4763 * Sets the attributes of an item.
4765 * PARAMETER(S):
4766 * [I] HWND : window handle
4767 * [I] LPLVITEM : item information
4769 * RETURN:
4770 * SUCCESS : TRUE
4771 * FAILURE : FALSE
4773 static LRESULT LISTVIEW_SetItemA(HWND hwnd, LPLVITEMA lpLVItem)
4775 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
4776 BOOL bResult = FALSE;
4778 if (lpLVItem != NULL)
4780 if ((lpLVItem->iItem >= 0) && (lpLVItem->iItem < GETITEMCOUNT(infoPtr)))
4782 if (lpLVItem->iSubItem == 0)
4784 bResult = LISTVIEW_SetItem(hwnd, lpLVItem);
4786 else
4788 bResult = LISTVIEW_SetSubItem(hwnd, lpLVItem);
4794 return bResult;
4797 /* LISTVIEW_SetItemW */
4799 /***
4800 * DESCRIPTION:
4801 * Preallocates memory.
4803 * PARAMETER(S):
4804 * [I] HWND : window handle
4805 * [I] INT : item count (prjected number of items)
4807 * RETURN:
4808 * None
4810 static VOID LISTVIEW_SetItemCount(HWND hwnd, INT nItemCount)
4812 FIXME (listview, "empty stub!\n");
4815 /***
4816 * DESCRIPTION:
4817 * Sets the position of an item.
4819 * PARAMETER(S):
4820 * [I] HWND : window handle
4821 * [I] INT : item index
4822 * [I] INT : x coordinate
4823 * [I] INT : y coordinate
4825 * RETURN:
4826 * SUCCESS : TRUE
4827 * FAILURE : FALSE
4829 static BOOL LISTVIEW_SetItemPosition(HWND hwnd, INT nItem,
4830 INT nPosX, INT nPosY)
4832 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO*)GetWindowLongA(hwnd, 0);
4833 LONG lStyle = GetWindowLongA(hwnd, GWL_STYLE);
4834 LISTVIEW_ITEM *lpItem;
4835 HDPA hdpaSubItems;
4836 BOOL bResult = FALSE;
4838 TRACE(listview, "(hwnd=%x,nItem=%d,X=%d,Y=%d)\n", hwnd, nItem, nPosX, nPosY);
4840 if ((nItem >= 0) || (nItem < GETITEMCOUNT(infoPtr)))
4842 switch (lStyle & LVS_TYPEMASK)
4844 case LVS_ICON:
4845 case LVS_SMALLICON:
4846 hdpaSubItems = (HDPA)DPA_GetPtr(infoPtr->hdpaItems, nItem);
4847 if (hdpaSubItems != NULL)
4849 lpItem = (LISTVIEW_ITEM *)DPA_GetPtr(hdpaSubItems, 0);
4850 if (lpItem != NULL)
4852 bResult = TRUE;
4853 lpItem->ptPosition.x = nPosX;
4854 lpItem->ptPosition.y = nPosY;
4857 break;
4861 return bResult;
4864 /***
4865 * DESCRIPTION:
4866 * Sets the state of one or many items.
4868 * PARAMETER(S):
4869 * [I] HWND : window handle
4870 * [I]INT : item index
4871 * [I] LPLVITEM : item or subitem info
4873 * RETURN:
4874 * SUCCESS : TRUE
4875 * FAILURE : FALSE
4877 static LRESULT LISTVIEW_SetItemState(HWND hwnd, INT nItem, LPLVITEMA lpLVItem)
4879 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
4880 BOOL bResult = FALSE;
4881 LVITEMA lvItem;
4882 INT i;
4884 if (nItem == -1)
4886 bResult = TRUE;
4887 ZeroMemory(&lvItem, sizeof(LVITEMA));
4888 lvItem.mask = LVIF_STATE;
4889 lvItem.state = lpLVItem->state;
4890 lvItem.stateMask = lpLVItem->stateMask;
4892 /* apply to all items */
4893 for (i = 0; i< GETITEMCOUNT(infoPtr); i++)
4895 lvItem.iItem = i;
4896 if (ListView_SetItemA(hwnd, &lvItem) == FALSE)
4898 bResult = FALSE;
4902 else
4904 ZeroMemory(&lvItem, sizeof(LVITEMA));
4905 lvItem.mask = LVIF_STATE;
4906 lvItem.state = lpLVItem->state;
4907 lvItem.stateMask = lpLVItem->stateMask;
4908 lvItem.iItem = nItem;
4909 bResult = ListView_SetItemA(hwnd, &lvItem);
4912 return bResult;
4915 /***
4916 * DESCRIPTION:
4917 * Sets the text of an item or subitem.
4919 * PARAMETER(S):
4920 * [I] HWND : window handle
4921 * [I] INT : item index
4922 * [I] LPLVITEMA : item or subitem info
4924 * RETURN:
4925 * SUCCESS : TRUE
4926 * FAILURE : FALSE
4928 static BOOL LISTVIEW_SetItemTextA(HWND hwnd, INT nItem, LPLVITEMA lpLVItem)
4930 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
4931 BOOL bResult = FALSE;
4932 LVITEMA lvItem;
4934 if ((nItem >= 0) && (nItem < GETITEMCOUNT(infoPtr)))
4936 ZeroMemory(&lvItem, sizeof(LVITEMA));
4937 lvItem.mask = LVIF_TEXT;
4938 lvItem.pszText = lpLVItem->pszText;
4939 lvItem.iItem = nItem;
4940 lvItem.iSubItem = lpLVItem->iSubItem;
4941 bResult = ListView_SetItemA(hwnd, &lvItem);
4944 return bResult;
4947 /***
4948 * DESCRIPTION:
4949 * Sets the text background color.
4951 * PARAMETER(S):
4952 * [I] HWND : window handle
4953 * [I] COLORREF : text background color
4955 * RETURN:
4956 * SUCCESS : TRUE
4957 * FAILURE : FALSE
4959 static LRESULT LISTVIEW_SetTextBkColor(HWND hwnd, COLORREF clrTextBk)
4961 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
4963 infoPtr->clrTextBk = clrTextBk;
4964 InvalidateRect(hwnd, NULL, TRUE);
4966 return TRUE;
4969 /***
4970 * DESCRIPTION:
4971 * Sets the text foreground color.
4973 * PARAMETER(S):
4974 * [I] HWND : window handle
4975 * [I] COLORREF : text color
4977 * RETURN:
4978 * SUCCESS : TRUE
4979 * FAILURE : FALSE
4981 static LRESULT LISTVIEW_SetTextColor (HWND hwnd, COLORREF clrText)
4983 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
4985 infoPtr->clrText = clrText;
4986 InvalidateRect(hwnd, NULL, TRUE);
4988 return TRUE;
4991 /***
4992 * DESCRIPTION:
4993 * Sorts the listview items.
4995 * PARAMETER(S):
4996 * [I] HWND : window handle
4998 * RETURN:
4999 * SUCCESS : TRUE
5000 * FAILURE : FALSE
5002 static LRESULT LISTVIEW_SortItems(HWND hwnd, WPARAM wParam, LPARAM lParam)
5004 FIXME (listview, "empty stub!\n");
5006 return TRUE;
5009 /***
5010 * DESCRIPTION:
5011 * Updates an items or rearranges the listview control.
5013 * PARAMETER(S):
5014 * [I] HWND : window handle
5015 * [I] INT : item index
5017 * RETURN:
5018 * SUCCESS : TRUE
5019 * FAILURE : FALSE
5021 static LRESULT LISTVIEW_Update(HWND hwnd, INT nItem)
5023 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
5024 LONG lStyle = GetWindowLongA(hwnd, GWL_STYLE);
5025 BOOL bResult = FALSE;
5026 RECT rc;
5028 if ((nItem >= 0) && (nItem < GETITEMCOUNT(infoPtr)))
5030 bResult = TRUE;
5032 /* rearrange with default alignment style */
5033 if ((lStyle & LVS_AUTOARRANGE) && (((lStyle & LVS_TYPEMASK) == LVS_ICON) ||
5034 ((lStyle & LVS_TYPEMASK) == LVS_SMALLICON)))
5036 ListView_Arrange(hwnd, 0);
5038 else
5040 /* get item bounding rectangle */
5041 rc.left = LVIR_BOUNDS;
5042 ListView_GetItemRect(hwnd, nItem, &rc);
5043 InvalidateRect(hwnd, &rc, FALSE);
5047 return bResult;
5050 /***
5051 * DESCRIPTION:
5052 * Creates the listview control.
5054 * PARAMETER(S):
5055 * [I] HWND : window handle
5057 * RETURN:
5058 * Zero
5060 static LRESULT LISTVIEW_Create(HWND hwnd, WPARAM wParam, LPARAM lParam)
5062 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
5063 LPCREATESTRUCTA lpcs = (LPCREATESTRUCTA)lParam;
5064 LOGFONTA logFont;
5066 /* initialize info pointer */
5067 ZeroMemory(infoPtr, sizeof(LISTVIEW_INFO));
5069 /* determine the type of structures to use */
5070 infoPtr->notifyFormat = SendMessageA(GetParent(hwnd), WM_NOTIFYFORMAT,
5071 (WPARAM)hwnd, (LPARAM)NF_QUERY);
5072 if (infoPtr->notifyFormat != NFR_ANSI)
5074 FIXME (listview, "ANSI notify format is NOT used\n");
5077 /* initialize color information */
5078 infoPtr->clrBk = GetSysColor(COLOR_WINDOW);
5079 infoPtr->clrText = GetSysColor(COLOR_WINDOWTEXT);
5080 infoPtr->clrTextBk = GetSysColor(COLOR_WINDOW);
5082 /* set default values */
5083 infoPtr->uCallbackMask = 0;
5084 infoPtr->nFocusedItem = -1;
5085 infoPtr->nSelectionMark = -1;
5086 infoPtr->iconSpacing.cx = GetSystemMetrics(SM_CXICONSPACING);
5087 infoPtr->iconSpacing.cy = GetSystemMetrics(SM_CYICONSPACING);
5088 ZeroMemory(&infoPtr->rcList, sizeof(RECT));
5090 /* get default font (icon title) */
5091 SystemParametersInfoA(SPI_GETICONTITLELOGFONT, 0, &logFont, 0);
5092 infoPtr->hDefaultFont = CreateFontIndirectA(&logFont);
5093 infoPtr->hFont = infoPtr->hDefaultFont;
5095 /* create header */
5096 infoPtr->hwndHeader = CreateWindowA(WC_HEADERA, (LPCSTR)NULL,
5097 WS_CHILD | HDS_HORZ | HDS_BUTTONS,
5098 0, 0, 0, 0, hwnd, (HMENU)0,
5099 lpcs->hInstance, NULL);
5101 /* set header font */
5102 SendMessageA(infoPtr->hwndHeader, WM_SETFONT, (WPARAM)infoPtr->hFont,
5103 (LPARAM)TRUE);
5106 switch (lpcs->style & LVS_TYPEMASK)
5108 case LVS_ICON:
5109 infoPtr->iconSize.cx = GetSystemMetrics(SM_CXICON);
5110 infoPtr->iconSize.cy = GetSystemMetrics(SM_CYICON);
5111 break;
5113 case LVS_REPORT:
5114 ShowWindow(infoPtr->hwndHeader, SW_SHOWNORMAL);
5115 case LVS_SMALLICON:
5116 case LVS_LIST:
5117 infoPtr->iconSize.cx = GetSystemMetrics(SM_CXSMICON);
5118 infoPtr->iconSize.cy = GetSystemMetrics(SM_CYSMICON);
5119 break;
5122 /* display unsupported listview window styles */
5123 LISTVIEW_UnsupportedStyles(lpcs->style);
5125 /* allocate memory for the data structure */
5126 infoPtr->hdpaItems = DPA_Create(10);
5128 /* initialize size of items */
5129 infoPtr->nItemWidth = LISTVIEW_GetItemWidth(hwnd, lpcs->style);
5130 infoPtr->nItemHeight = LISTVIEW_GetItemHeight(hwnd, lpcs->style);
5132 return 0;
5135 /***
5136 * DESCRIPTION:
5137 * Erases the background of the listview control.
5139 * PARAMETER(S):
5140 * [I] HWND : window handle
5141 * [I] WPARAM : device context handle
5142 * [I] LPARAM : not used
5144 * RETURN:
5145 * SUCCESS : TRUE
5146 * FAILURE : FALSE
5148 static LRESULT LISTVIEW_EraseBackground(HWND hwnd, WPARAM wParam,
5149 LPARAM lParam)
5151 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
5152 BOOL bResult;
5154 if (infoPtr->clrBk == CLR_NONE)
5156 bResult = SendMessageA(GetParent(hwnd), WM_ERASEBKGND, wParam, lParam);
5158 else
5160 RECT rc;
5161 HBRUSH hBrush = CreateSolidBrush(infoPtr->clrBk);
5162 GetClientRect(hwnd, &rc);
5163 FillRect((HDC)wParam, &rc, hBrush);
5164 DeleteObject(hBrush);
5165 bResult = TRUE;
5168 return bResult;
5171 /***
5172 * DESCRIPTION:
5173 * Retrieves the listview control font.
5175 * PARAMETER(S):
5176 * [I] HWND : window handle
5178 * RETURN:
5179 * Font handle.
5181 static LRESULT LISTVIEW_GetFont(HWND hwnd)
5183 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
5185 return infoPtr->hFont;
5188 /***
5189 * DESCRIPTION:
5190 * Performs vertical scrolling.
5192 * PARAMETER(S):
5193 * [I] HWND : window handle
5194 * [I] INT : scroll code
5195 * [I] INT : scroll position
5196 * [I] HWND : scrollbar control window handle
5198 * RETURN:
5199 * Zero
5201 static LRESULT LISTVIEW_VScroll(HWND hwnd, INT nScrollCode, INT nScroll,
5202 HWND hScrollWnd)
5204 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
5205 LONG lStyle = GetWindowLongA(hwnd, GWL_STYLE);
5206 INT nScrollPosInc = 0;
5207 INT nScrollPos;
5208 INT nMinRange;
5209 INT nMaxRange;
5211 GetScrollRange(hwnd, SB_VERT, &nMinRange, &nMaxRange);
5212 nScrollPos = GetScrollPos(hwnd, SB_VERT);
5214 switch (nScrollCode)
5216 case SB_LINEUP:
5217 if (nScrollPos > nMinRange)
5219 nScrollPosInc = -1;
5221 break;
5223 case SB_LINEDOWN:
5224 if (nScrollPos < nMaxRange)
5226 nScrollPosInc = 1;
5228 break;
5230 case SB_PAGEUP:
5231 switch (LVS_TYPEMASK & lStyle)
5233 case LVS_REPORT:
5234 if (nScrollPos > nMinRange + infoPtr->nCountPerColumn)
5236 nScrollPosInc = -infoPtr->nCountPerColumn;
5238 else
5240 nScrollPosInc = nMinRange - nScrollPos;
5242 break;
5244 case LVS_SMALLICON:
5245 case LVS_ICON:
5246 if (nScrollPos > nMinRange + 10)
5248 nScrollPosInc = -10;
5250 else
5252 nScrollPosInc = nMinRange - nScrollPos;
5254 break;
5256 break;
5258 case SB_PAGEDOWN:
5259 switch (LVS_TYPEMASK & lStyle)
5261 case LVS_REPORT:
5262 if (nScrollPos < nMaxRange - infoPtr->nCountPerColumn)
5264 nScrollPosInc = infoPtr->nCountPerColumn;
5266 else
5268 nScrollPosInc = nMaxRange - nScrollPos;
5270 break;
5272 case LVS_SMALLICON:
5273 case LVS_ICON:
5274 if (nScrollPos < nMaxRange - 10)
5276 nScrollPosInc = 10;
5278 else
5280 nScrollPosInc = nMaxRange - nScrollPos;
5282 break;
5284 break;
5286 case SB_THUMBPOSITION:
5287 nScrollPosInc = nScroll - nScrollPos;
5288 break;
5291 if (nScrollPosInc != 0)
5293 LISTVIEW_ScrollView(hwnd, 0, nScrollPosInc);
5296 return 0;
5300 /***
5301 * DESCRIPTION:
5302 * Performs horizontal scrolling.
5304 * PARAMETER(S):
5305 * [I] HWND : window handle
5306 * [I] INT : scroll code
5307 * [I] INT : scroll position
5308 * [I] HWND : scrollbar control window handle
5310 * RETURN:
5311 * Zero
5313 static LRESULT LISTVIEW_HScroll(HWND hwnd, INT nScrollCode,
5314 INT nScroll, HWND hScrollWnd)
5316 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
5317 LONG lStyle = GetWindowLongA(hwnd, GWL_STYLE);
5318 INT nScrollPosInc = 0;
5319 INT nScrollPos;
5320 INT nMinRange;
5321 INT nMaxRange;
5323 GetScrollRange(hwnd, SB_HORZ, &nMinRange, &nMaxRange);
5324 nScrollPos = GetScrollPos(hwnd, SB_HORZ);
5326 switch (nScrollCode)
5328 case SB_LINELEFT:
5329 if (nScrollPos > nMinRange)
5331 nScrollPosInc = -1;
5333 break;
5335 case SB_LINERIGHT:
5336 if (nScrollPos < nMaxRange)
5338 nScrollPosInc = 1;
5340 break;
5342 case SB_PAGELEFT:
5343 switch (LVS_TYPEMASK & lStyle)
5345 case LVS_LIST:
5346 if (nScrollPos > nMinRange + infoPtr->nCountPerRow)
5348 nScrollPosInc = -infoPtr->nCountPerRow;
5350 else
5352 nScrollPosInc = nMinRange - nScrollPos;
5354 break;
5356 case LVS_REPORT:
5357 case LVS_SMALLICON:
5358 case LVS_ICON:
5359 if (nScrollPos > nMinRange + 10)
5361 nScrollPosInc = -10;
5363 else
5365 nScrollPosInc = nMinRange - nScrollPos;
5367 break;
5369 break;
5371 case SB_PAGERIGHT:
5372 switch (LVS_TYPEMASK & lStyle)
5374 case LVS_LIST:
5375 if (nScrollPos < nMaxRange - infoPtr->nCountPerRow)
5377 nScrollPosInc = infoPtr->nCountPerRow;
5379 else
5381 nScrollPosInc = nMaxRange - nScrollPos;
5383 break;
5385 case LVS_REPORT:
5386 case LVS_SMALLICON:
5387 case LVS_ICON:
5388 if (nScrollPos < nMaxRange - 10)
5390 nScrollPosInc = 10;
5392 else
5394 nScrollPosInc = nMaxRange - nScrollPos;
5396 break;
5398 break;
5400 case SB_THUMBPOSITION:
5401 nScrollPosInc = nScroll - nScrollPos;
5402 break;
5405 if (nScrollPosInc != 0)
5407 LISTVIEW_ScrollView(hwnd, nScrollPosInc, 0);
5410 return 0;
5413 /***
5414 * DESCRIPTION:
5415 * ???
5417 * PARAMETER(S):
5418 * [I] HWND : window handle
5419 * [I] INT : virtual key
5420 * [I] LONG : key data
5422 * RETURN:
5423 * Zero
5425 static LRESULT LISTVIEW_KeyDown(HWND hwnd, INT nVirtualKey, LONG lKeyData)
5427 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
5428 LONG lStyle = GetWindowLongA(hwnd, GWL_STYLE);
5429 INT nCtrlId = GetWindowLongA(hwnd, GWL_ID);
5430 INT nCountPerColumn;
5431 INT nCountPerRow;
5432 HWND hwndParent = GetParent(hwnd);
5433 NMLVKEYDOWN nmKeyDown;
5434 NMHDR nmh;
5436 /* send LVN_KEYDOWN notification */
5437 ZeroMemory(&nmKeyDown, sizeof(NMLVKEYDOWN));
5438 nmKeyDown.hdr.hwndFrom = hwnd;
5439 nmKeyDown.hdr.idFrom = nCtrlId;
5440 nmKeyDown.hdr.code = LVN_KEYDOWN;
5441 nmKeyDown.wVKey = nVirtualKey;
5442 nmKeyDown.flags = 0;
5443 SendMessageA(hwndParent, WM_NOTIFY, (WPARAM)nCtrlId, (LPARAM)&nmKeyDown);
5445 /* initialize */
5446 nmh.hwndFrom = hwnd;
5447 nmh.idFrom = nCtrlId;
5449 switch (nVirtualKey)
5451 case VK_RETURN:
5452 if ((GETITEMCOUNT(infoPtr) > 0) && (infoPtr->nFocusedItem != -1))
5454 /* send NM_RETURN notification */
5455 nmh.code = NM_RETURN;
5456 ListView_Notify(hwndParent, nCtrlId, &nmh);
5458 /* send LVN_ITEMACTIVATE notification */
5459 nmh.code = LVN_ITEMACTIVATE;
5460 ListView_Notify(hwndParent, nCtrlId, &nmh);
5462 break;
5464 case VK_HOME:
5465 if (GETITEMCOUNT(infoPtr) > 0)
5467 LISTVIEW_KeySelection(hwnd, 0);
5469 break;
5471 case VK_END:
5472 if (GETITEMCOUNT(infoPtr) > 0)
5474 LISTVIEW_KeySelection(hwnd, GETITEMCOUNT(infoPtr) - 1);
5476 break;
5478 case VK_LEFT:
5479 switch (LVS_TYPEMASK & lStyle)
5481 case LVS_LIST:
5482 if (infoPtr->nFocusedItem >= infoPtr->nCountPerColumn)
5484 LISTVIEW_KeySelection(hwnd, infoPtr->nFocusedItem -
5485 infoPtr->nCountPerColumn);
5487 break;
5489 case LVS_SMALLICON:
5490 case LVS_ICON:
5491 if (lStyle & LVS_ALIGNLEFT)
5493 nCountPerColumn = max((infoPtr->rcList.bottom - infoPtr->rcList.top) /
5494 infoPtr->nItemHeight, 1);
5495 if (infoPtr->nFocusedItem >= nCountPerColumn)
5497 LISTVIEW_KeySelection(hwnd, infoPtr->nFocusedItem - nCountPerColumn);
5500 else
5502 nCountPerRow = max((infoPtr->rcList.right - infoPtr->rcList.left) /
5503 infoPtr->nItemWidth, 1);
5504 if (infoPtr->nFocusedItem % nCountPerRow != 0)
5506 LISTVIEW_SetSelection(hwnd, infoPtr->nFocusedItem - 1);
5509 break;
5511 break;
5513 case VK_UP:
5514 switch (LVS_TYPEMASK & lStyle)
5516 case LVS_LIST:
5517 case LVS_REPORT:
5518 if (infoPtr->nFocusedItem > 0)
5520 LISTVIEW_KeySelection(hwnd, infoPtr->nFocusedItem - 1);
5522 break;
5524 default:
5525 if (lStyle & LVS_ALIGNLEFT)
5527 nCountPerColumn = max((infoPtr->rcList.bottom - infoPtr->rcList.top) /
5528 infoPtr->nItemHeight, 1);
5529 if (infoPtr->nFocusedItem % nCountPerColumn != 0)
5531 LISTVIEW_KeySelection(hwnd, infoPtr->nFocusedItem - 1);
5534 else
5536 nCountPerRow = max((infoPtr->rcList.right - infoPtr->rcList.left) /
5537 infoPtr->nItemWidth, 1);
5538 if (infoPtr->nFocusedItem >= nCountPerRow)
5540 LISTVIEW_KeySelection(hwnd, infoPtr->nFocusedItem - nCountPerRow);
5544 break;
5546 case VK_RIGHT:
5547 switch (LVS_TYPEMASK & lStyle)
5549 case LVS_LIST:
5550 if (infoPtr->nFocusedItem < GETITEMCOUNT(infoPtr) -
5551 infoPtr->nCountPerColumn)
5553 LISTVIEW_KeySelection(hwnd, infoPtr->nFocusedItem +
5554 infoPtr->nCountPerColumn);
5556 break;
5558 case LVS_ICON:
5559 case LVS_SMALLICON:
5560 if (lStyle & LVS_ALIGNLEFT)
5562 nCountPerColumn = max((infoPtr->rcList.bottom - infoPtr->rcList.top) /
5563 infoPtr->nItemHeight, 1);
5564 if (infoPtr->nFocusedItem < GETITEMCOUNT(infoPtr) - nCountPerColumn)
5566 LISTVIEW_KeySelection(hwnd, infoPtr->nFocusedItem + nCountPerColumn);
5569 else
5571 nCountPerRow = max((infoPtr->rcList.right - infoPtr->rcList.left) /
5572 infoPtr->nItemWidth, 1);
5573 if ((infoPtr->nFocusedItem % nCountPerRow != nCountPerRow - 1) &&
5574 (infoPtr->nFocusedItem < GETITEMCOUNT(infoPtr) - 1))
5576 LISTVIEW_KeySelection(hwnd, infoPtr->nFocusedItem + 1);
5580 break;
5582 case VK_DOWN:
5583 switch (LVS_TYPEMASK & lStyle)
5585 case LVS_LIST:
5586 case LVS_REPORT:
5587 if (infoPtr->nFocusedItem < GETITEMCOUNT(infoPtr) - 1)
5589 LISTVIEW_KeySelection(hwnd, infoPtr->nFocusedItem + 1);
5591 break;
5593 case LVS_SMALLICON:
5594 case LVS_ICON:
5595 if (lStyle & LVS_ALIGNLEFT)
5597 nCountPerColumn = max((infoPtr->rcList.bottom - infoPtr->rcList.top) /
5598 infoPtr->nItemHeight, 1);
5599 if (infoPtr->nFocusedItem % nCountPerColumn != nCountPerColumn - 1)
5601 LISTVIEW_KeySelection(hwnd, infoPtr->nFocusedItem + 1);
5604 else
5606 nCountPerRow = max((infoPtr->rcList.right - infoPtr->rcList.left) /
5607 infoPtr->nItemWidth, 1);
5608 if (infoPtr->nFocusedItem < GETITEMCOUNT(infoPtr) - nCountPerRow)
5610 LISTVIEW_KeySelection(hwnd, infoPtr->nFocusedItem + nCountPerRow);
5614 break;
5616 case VK_PRIOR:
5617 break;
5619 case VK_NEXT:
5620 break;
5623 /* refresh client area */
5624 InvalidateRect(hwnd, NULL, TRUE);
5626 return 0;
5629 /***
5630 * DESCRIPTION:
5631 * Kills the focus.
5633 * PARAMETER(S):
5634 * [I] HWND : window handle
5636 * RETURN:
5637 * Zero
5639 static LRESULT LISTVIEW_KillFocus(HWND hwnd)
5641 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO*)GetWindowLongA(hwnd, 0);
5642 INT nCtrlId = GetWindowLongA(hwnd, GWL_ID);
5643 NMHDR nmh;
5645 /* send NM_KILLFOCUS notification */
5646 nmh.hwndFrom = hwnd;
5647 nmh.idFrom = nCtrlId;
5648 nmh.code = NM_KILLFOCUS;
5649 ListView_Notify(GetParent(hwnd), nCtrlId, &nmh);
5651 /* set window focus flag */
5652 infoPtr->bFocus = FALSE;
5654 return 0;
5657 /***
5658 * DESCRIPTION:
5659 * Processes double click messages (left mouse button).
5661 * PARAMETER(S):
5662 * [I] HWND : window handle
5663 * [I] WORD : key flag
5664 * [I] WORD : x coordinate
5665 * [I] WORD : y coordinate
5667 * RETURN:
5668 * Zero
5670 static LRESULT LISTVIEW_LButtonDblClk(HWND hwnd, WORD wKey, WORD wPosX,
5671 WORD wPosY)
5673 LONG nCtrlId = GetWindowLongA(hwnd, GWL_ID);
5674 NMHDR nmh;
5676 TRACE(listview, "(hwnd=%x,key=%hu,X=%hu,Y=%hu)\n", hwnd, wKey, wPosX, wPosY);
5678 /* send NM_DBLCLK notification */
5679 nmh.hwndFrom = hwnd;
5680 nmh.idFrom = nCtrlId;
5681 nmh.code = NM_DBLCLK;
5682 ListView_Notify(GetParent(hwnd), nCtrlId, &nmh);
5684 /* send LVN_ITEMACTIVATE notification */
5685 nmh.code = LVN_ITEMACTIVATE;
5686 ListView_Notify(GetParent(hwnd), nCtrlId, &nmh);
5688 return 0;
5691 /***
5692 * DESCRIPTION:
5693 * Processes mouse down messages (left mouse button).
5695 * PARAMETER(S):
5696 * [I] HWND : window handle
5697 * [I] WORD : key flag
5698 * [I] WORD : x coordinate
5699 * [I] WORD : y coordinate
5701 * RETURN:
5702 * Zero
5704 static LRESULT LISTVIEW_LButtonDown(HWND hwnd, WORD wKey, WORD wPosX,
5705 WORD wPosY)
5707 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
5708 INT nCtrlId = GetWindowLongA(hwnd, GWL_ID);
5709 static BOOL bGroupSelect = TRUE;
5710 NMHDR nmh;
5711 INT nItem;
5713 TRACE(listview, "(hwnd=%x,key=%hu,X=%hu,Y=%hu)\n", hwnd, wKey, wPosX, wPosY);
5715 /* send NM_RELEASEDCAPTURE notification */
5716 nmh.hwndFrom = hwnd;
5717 nmh.idFrom = nCtrlId;
5718 nmh.code = NM_RELEASEDCAPTURE;
5719 ListView_Notify(GetParent(hwnd), nCtrlId, &nmh);
5721 if (infoPtr->bFocus == FALSE)
5723 SetFocus(hwnd);
5726 /* set left button down flag */
5727 infoPtr->bLButtonDown = TRUE;
5729 nItem = LISTVIEW_MouseSelection(hwnd, wPosX, wPosY);
5730 if ((nItem >= 0) && (nItem < GETITEMCOUNT(infoPtr)))
5732 if ((wKey & MK_CONTROL) && (wKey & MK_SHIFT))
5734 if (bGroupSelect != FALSE)
5736 LISTVIEW_AddGroupSelection(hwnd, nItem);
5738 else
5740 LISTVIEW_AddSelection(hwnd, nItem);
5743 else if (wKey & MK_CONTROL)
5745 bGroupSelect = LISTVIEW_ToggleSelection(hwnd, nItem);
5747 else if (wKey & MK_SHIFT)
5749 LISTVIEW_SetGroupSelection(hwnd, nItem);
5751 else
5753 LISTVIEW_SetSelection(hwnd, nItem);
5756 else
5758 /* remove all selections */
5759 LISTVIEW_RemoveSelections(hwnd, 0, GETITEMCOUNT(infoPtr));
5762 InvalidateRect(hwnd, NULL, TRUE);
5764 return 0;
5767 /***
5768 * DESCRIPTION:
5769 * Processes mouse up messages (left mouse button).
5771 * PARAMETER(S):
5772 * [I] HWND : window handle
5773 * [I] WORD : key flag
5774 * [I] WORD : x coordinate
5775 * [I] WORD : y coordinate
5777 * RETURN:
5778 * Zero
5780 static LRESULT LISTVIEW_LButtonUp(HWND hwnd, WORD wKey, WORD wPosX,
5781 WORD wPosY)
5783 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
5785 TRACE(listview, "(hwnd=%x,key=%hu,X=%hu,Y=%hu)\n", hwnd, wKey, wPosX, wPosY);
5787 if (infoPtr->bLButtonDown != FALSE)
5789 INT nCtrlId = GetWindowLongA(hwnd, GWL_ID);
5790 NMHDR nmh;
5792 /* send NM_CLICK notification */
5793 nmh.hwndFrom = hwnd;
5794 nmh.idFrom = nCtrlId;
5795 nmh.code = NM_CLICK;
5796 ListView_Notify(GetParent(hwnd), nCtrlId, &nmh);
5798 /* set left button flag */
5799 infoPtr->bLButtonDown = FALSE;
5802 return 0;
5805 /***
5806 * DESCRIPTION:
5807 * Creates the listview control (called before WM_CREATE).
5809 * PARAMETER(S):
5810 * [I] HWND : window handle
5811 * [I] WPARAM : unhandled
5812 * [I] LPARAM : widow creation info
5814 * RETURN:
5815 * Zero
5817 static LRESULT LISTVIEW_NCCreate(HWND hwnd, WPARAM wParam, LPARAM lParam)
5819 LISTVIEW_INFO *infoPtr;
5821 TRACE(listview, "(hwnd=%x,wParam=%x,lParam=%lx)\n", hwnd, wParam, lParam);
5823 /* allocate memory for info structure */
5824 infoPtr = (LISTVIEW_INFO *)COMCTL32_Alloc(sizeof(LISTVIEW_INFO));
5825 SetWindowLongA(hwnd, 0, (LONG)infoPtr);
5826 if (infoPtr == NULL)
5828 ERR(listview, "could not allocate info memory!\n");
5829 return 0;
5832 if ((LISTVIEW_INFO *)GetWindowLongA(hwnd, 0) != infoPtr)
5834 ERR(listview, "pointer assignment error!\n");
5835 return 0;
5838 return DefWindowProcA(hwnd, WM_NCCREATE, wParam, lParam);
5841 /***
5842 * DESCRIPTION:
5843 * Destroys the listview control (called after WM_DESTROY).
5845 * PARAMETER(S):
5846 * [I] HWND : window handle
5848 * RETURN:
5849 * Zero
5851 static LRESULT LISTVIEW_NCDestroy(HWND hwnd)
5853 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
5855 TRACE(listview, "(hwnd=%x)\n", hwnd);
5857 /* delete all items */
5858 LISTVIEW_DeleteAllItems(hwnd);
5860 /* destroy data structure */
5861 DPA_Destroy(infoPtr->hdpaItems);
5863 /* destroy font */
5864 infoPtr->hFont = (HFONT)0;
5865 if (infoPtr->hDefaultFont)
5867 DeleteObject(infoPtr->hDefaultFont);
5870 /* free listview info pointer*/
5871 COMCTL32_Free(infoPtr);
5873 return 0;
5876 /***
5877 * DESCRIPTION:
5878 * Handles notifications from children.
5880 * PARAMETER(S):
5881 * [I] HWND : window handle
5882 * [I] INT : control identifier
5883 * [I] LPNMHDR : notification information
5885 * RETURN:
5886 * Zero
5888 static LRESULT LISTVIEW_Notify(HWND hwnd, INT nCtrlId, LPNMHDR lpnmh)
5890 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
5892 if (lpnmh->hwndFrom == infoPtr->hwndHeader)
5894 /* handle notification from header control */
5895 if (lpnmh->code == HDN_ENDTRACKA)
5897 infoPtr->nItemWidth = LISTVIEW_GetItemWidth(hwnd, LVS_REPORT);
5898 InvalidateRect(hwnd, NULL, TRUE);
5902 return 0;
5905 /***
5906 * DESCRIPTION:
5907 * Determines the type of structure to use.
5909 * PARAMETER(S):
5910 * [I] HWND : window handle of the sender
5911 * [I] HWND : listview window handle
5912 * [I] INT : command specifying the nature of the WM_NOTIFYFORMAT
5914 * RETURN:
5915 * Zero
5917 static LRESULT LISTVIEW_NotifyFormat(HWND hwndFrom, HWND hwnd, INT nCommand)
5919 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
5921 if (nCommand == NF_REQUERY)
5923 /* determine the type of structure to use */
5924 infoPtr->notifyFormat = SendMessageA(hwndFrom, WM_NOTIFYFORMAT,
5925 (WPARAM)hwnd, (LPARAM)NF_QUERY);
5926 if (infoPtr->notifyFormat == NFR_UNICODE)
5928 FIXME (listview, "NO support for unicode structures");
5932 return 0;
5935 /***
5936 * DESCRIPTION:
5937 * Paints/Repaints the listview control.
5939 * PARAMETER(S):
5940 * [I] HWND : window handle
5941 * [I] HDC : device context handle
5943 * RETURN:
5944 * Zero
5946 static LRESULT LISTVIEW_Paint(HWND hwnd, HDC hdc)
5948 PAINTSTRUCT ps;
5950 TRACE(listview, "(hwnd=%x,hdc=%x)\n", hwnd, hdc);
5952 if (hdc == 0)
5954 hdc = BeginPaint(hwnd, &ps);
5955 LISTVIEW_Refresh(hwnd, hdc);
5956 EndPaint(hwnd, &ps);
5958 else
5960 LISTVIEW_Refresh(hwnd, hdc);
5963 return 0;
5966 /***
5967 * DESCRIPTION:
5968 * Processes double click messages (right mouse button).
5970 * PARAMETER(S):
5971 * [I] HWND : window handle
5972 * [I] WORD : key flag
5973 * [I] WORD : x coordinate
5974 * [I] WORD : y coordinate
5976 * RETURN:
5977 * Zero
5979 static LRESULT LISTVIEW_RButtonDblClk(HWND hwnd, WORD wKey, WORD wPosX,
5980 WORD wPosY)
5982 INT nCtrlId = GetWindowLongA(hwnd, GWL_ID);
5983 NMHDR nmh;
5985 TRACE(listview, "(hwnd=%x,key=%hu,X=%hu,Y=%hu)\n", hwnd, wKey, wPosX, wPosY);
5987 /* send NM_RELEASEDCAPTURE notification */
5988 nmh.hwndFrom = hwnd;
5989 nmh.idFrom = nCtrlId;
5990 nmh.code = NM_RELEASEDCAPTURE;
5991 ListView_Notify(GetParent(hwnd), nCtrlId, &nmh);
5993 /* send NM_RDBLCLK notification */
5994 nmh.code = NM_RDBLCLK;
5995 ListView_Notify(GetParent(hwnd), nCtrlId, &nmh);
5997 return 0;
6000 /***
6001 * DESCRIPTION:
6002 * Processes mouse down messages (right mouse button).
6004 * PARAMETER(S):
6005 * [I] HWND : window handle
6006 * [I] WORD : key flag
6007 * [I] WORD : x coordinate
6008 * [I] WORD : y coordinate
6010 * RETURN:
6011 * Zero
6013 static LRESULT LISTVIEW_RButtonDown(HWND hwnd, WORD wKey, WORD wPosX,
6014 WORD wPosY)
6016 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
6017 INT nCtrlId = GetWindowLongA(hwnd, GWL_ID);
6018 NMHDR nmh;
6019 INT nItem;
6021 TRACE(listview, "(hwnd=%x,key=%hu,X=%hu,Y=%hu)\n", hwnd, wKey, wPosX, wPosY);
6023 /* send NM_RELEASEDCAPTURE notification */
6024 nmh.hwndFrom = hwnd;
6025 nmh.idFrom = nCtrlId;
6026 nmh.code = NM_RELEASEDCAPTURE;
6027 ListView_Notify(GetParent(hwnd), nCtrlId, &nmh);
6029 /* make sure the listview control window has the focus */
6030 if (infoPtr->bFocus == FALSE)
6032 SetFocus(hwnd);
6035 /* set right button down flag */
6036 infoPtr->bRButtonDown = TRUE;
6038 /* determine the index of the selected item */
6039 nItem = LISTVIEW_MouseSelection(hwnd, wPosX, wPosY);
6040 if ((nItem >= 0) && (nItem < GETITEMCOUNT(infoPtr)))
6042 if (!((wKey & MK_SHIFT) || (wKey & MK_CONTROL)))
6044 LISTVIEW_SetSelection(hwnd, nItem);
6047 else
6049 LISTVIEW_RemoveSelections(hwnd, 0, GETITEMCOUNT(infoPtr));
6052 return 0;
6055 /***
6056 * DESCRIPTION:
6057 * Processes mouse up messages (right mouse button).
6059 * PARAMETER(S):
6060 * [I] HWND : window handle
6061 * [I] WORD : key flag
6062 * [I] WORD : x coordinate
6063 * [I] WORD : y coordinate
6065 * RETURN:
6066 * Zero
6068 static LRESULT LISTVIEW_RButtonUp(HWND hwnd, WORD wKey, WORD wPosX,
6069 WORD wPosY)
6071 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
6072 INT nCtrlId = GetWindowLongA(hwnd, GWL_ID);
6073 NMHDR nmh;
6075 TRACE(listview, "(hwnd=%x,key=%hu,X=%hu,Y=%hu)\n", hwnd, wKey, wPosX, wPosY);
6077 if (infoPtr->bRButtonDown != FALSE)
6079 /* send NM_RClICK notification */
6080 ZeroMemory(&nmh, sizeof(NMHDR));
6081 nmh.hwndFrom = hwnd;
6082 nmh.idFrom = nCtrlId;
6083 nmh.code = NM_RCLICK;
6084 ListView_Notify(GetParent(hwnd), nCtrlId, &nmh);
6086 /* set button flag */
6087 infoPtr->bRButtonDown = FALSE;
6090 return 0;
6093 /***
6094 * DESCRIPTION:
6095 * Sets the focus.
6097 * PARAMETER(S):
6098 * [I] HWND : window handle
6099 * [I] HWND : window handle of previously focused window
6101 * RETURN:
6102 * Zero
6104 static LRESULT LISTVIEW_SetFocus(HWND hwnd, HWND hwndLoseFocus)
6106 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
6107 INT nCtrlId = GetWindowLongA(hwnd, GWL_ID);
6108 NMHDR nmh;
6110 /* send NM_SETFOCUS notification */
6111 nmh.hwndFrom = hwnd;
6112 nmh.idFrom = nCtrlId;
6113 nmh.code = NM_SETFOCUS;
6114 ListView_Notify(GetParent(hwnd), nCtrlId, &nmh);
6116 /* set window focus flag */
6117 infoPtr->bFocus = TRUE;
6119 return 0;
6122 /***
6123 * DESCRIPTION:
6124 * Sets the font.
6126 * PARAMETER(S):
6127 * [I] HWND : window handle
6128 * [I] HFONT : font handle
6129 * [I] WORD : redraw flag
6131 * RETURN:
6132 * Zero
6134 static LRESULT LISTVIEW_SetFont(HWND hwnd, HFONT hFont, WORD fRedraw)
6136 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
6137 LONG lStyle = GetWindowLongA(hwnd, GWL_STYLE);
6139 TRACE(listview, "(hwnd=%x,hfont=%x,redraw=%hu)\n", hwnd, hFont, fRedraw);
6141 if (hFont == 0)
6143 infoPtr->hFont = infoPtr->hDefaultFont;
6145 else
6147 infoPtr->hFont = hFont;
6150 if ((LVS_TYPEMASK & lStyle ) == LVS_REPORT)
6152 /* set header font */
6153 SendMessageA(infoPtr->hwndHeader, WM_SETFONT, (WPARAM)hFont,
6154 MAKELPARAM(fRedraw, 0));
6157 /* invalidate listview control client area */
6158 InvalidateRect(hwnd, NULL, TRUE);
6160 if (fRedraw != FALSE)
6162 UpdateWindow(hwnd);
6165 return 0;
6168 /***
6169 * DESCRIPTION:
6170 * Resizes the listview control. This function processes WM_SIZE
6171 * messages. At this time, the width and height are not used.
6173 * PARAMETER(S):
6174 * [I] HWND : window handle
6175 * [I] WORD : new width
6176 * [I] WORD : new height
6178 * RETURN:
6179 * Zero
6181 static LRESULT LISTVIEW_Size(HWND hwnd, int Width, int Height)
6183 LONG lStyle = GetWindowLongA(hwnd, GWL_STYLE);
6185 TRACE(listview, "(hwnd=%x,width=%d,height=%d)\n",hwnd, Width, Height);
6187 LISTVIEW_SetSize(hwnd, lStyle, -1, -1);
6188 switch (lStyle & LVS_TYPEMASK)
6190 case LVS_LIST:
6191 case LVS_REPORT:
6192 LISTVIEW_SetViewInfo(hwnd, lStyle);
6193 break;
6195 case LVS_ICON:
6196 case LVS_SMALLICON:
6197 if (lStyle & LVS_ALIGNLEFT)
6199 LISTVIEW_AlignLeft(hwnd);
6201 else
6203 LISTVIEW_AlignTop(hwnd);
6205 break;
6208 LISTVIEW_SetScroll(hwnd, lStyle);
6210 /* invalidate + erase background */
6211 InvalidateRect(hwnd, NULL, TRUE);
6213 return 0;
6216 /***
6217 * DESCRIPTION:
6218 * Sets the size information for a given style.
6220 * PARAMETER(S):
6221 * [I] HWND : window handle
6222 * [I] LONG : window style
6223 * [I] WORD : new width
6224 * [I] WORD : new height
6226 * RETURN:
6227 * Zero
6229 static VOID LISTVIEW_SetSize(HWND hwnd, LONG lStyle, LONG lWidth, LONG lHeight)
6231 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
6232 HDLAYOUT hl;
6233 WINDOWPOS wp;
6234 RECT rcList;
6236 GetClientRect(hwnd, &rcList);
6237 if (lWidth == -1)
6239 infoPtr->rcList.left = max(rcList.left, 0);
6240 infoPtr->rcList.right = max(rcList.right, 0);
6242 else
6244 infoPtr->rcList.left = max(rcList.left, 0);
6245 infoPtr->rcList.right = infoPtr->rcList.left + max(lWidth, 0);
6248 if (lHeight == -1)
6250 infoPtr->rcList.top = max(rcList.top, 0);
6251 infoPtr->rcList.bottom = max(rcList.bottom, 0);
6253 else
6255 infoPtr->rcList.top = max(rcList.top, 0);
6256 infoPtr->rcList.bottom = infoPtr->rcList.top + max(lHeight, 0);
6259 switch (lStyle & LVS_TYPEMASK)
6261 case LVS_LIST:
6262 if ((lStyle & WS_HSCROLL) == 0)
6264 INT nHScrollHeight;
6265 nHScrollHeight = GetSystemMetrics(SM_CYHSCROLL);
6266 if (infoPtr->rcList.bottom > nHScrollHeight)
6268 infoPtr->rcList.bottom -= nHScrollHeight;
6271 break;
6273 case LVS_REPORT:
6274 hl.prc = &rcList;
6275 hl.pwpos = &wp;
6276 Header_Layout(infoPtr->hwndHeader, &hl);
6277 infoPtr->rcList.top = max(wp.cy, 0);
6278 break;
6282 /***
6283 * DESCRIPTION:
6284 * Processes WM_STYLECHANGED messages.
6286 * PARAMETER(S):
6287 * [I] HWND : window handle
6288 * [I] WPARAM : window style type (normal or extended)
6289 * [I] LPSTYLESTRUCT : window style information
6291 * RETURN:
6292 * Zero
6294 static INT LISTVIEW_StyleChanged(HWND hwnd, WPARAM wStyleType,
6295 LPSTYLESTRUCT lpss)
6297 LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
6298 RECT rcList = infoPtr->rcList;
6299 HDLAYOUT hl;
6300 WINDOWPOS wp;
6302 TRACE(listview, "(hwnd=%x,styletype=%x,stylestruct=%p)\n",
6303 hwnd, wStyleType, lpss);
6305 if (wStyleType == GWL_STYLE)
6307 if ((lpss->styleOld & WS_HSCROLL) != 0)
6309 ShowScrollBar(hwnd, SB_HORZ, FALSE);
6312 if ((lpss->styleOld & WS_VSCROLL) != 0)
6314 ShowScrollBar(hwnd, SB_VERT, FALSE);
6317 if ((LVS_TYPEMASK & lpss->styleOld) == LVS_REPORT)
6319 /* remove header */
6320 ShowWindow(infoPtr->hwndHeader, SW_HIDE);
6323 switch (lpss->styleNew & LVS_TYPEMASK)
6325 case LVS_ICON:
6326 infoPtr->iconSize.cx = GetSystemMetrics(SM_CXICON);
6327 infoPtr->iconSize.cy = GetSystemMetrics(SM_CYICON);
6328 LISTVIEW_SetSize(hwnd, lpss->styleNew, -1, -1);
6329 infoPtr->nItemWidth = LISTVIEW_GetItemWidth(hwnd, lpss->styleNew);
6330 infoPtr->nItemHeight = LISTVIEW_GetItemHeight(hwnd, lpss->styleNew);
6331 if (lpss->styleNew & LVS_ALIGNLEFT)
6333 LISTVIEW_AlignLeft(hwnd);
6335 else
6337 LISTVIEW_AlignTop(hwnd);
6339 break;
6341 case LVS_REPORT:
6342 hl.prc = &rcList;
6343 hl.pwpos = &wp;
6344 Header_Layout(infoPtr->hwndHeader, &hl);
6345 SetWindowPos(infoPtr->hwndHeader, hwnd, wp.x, wp.y, wp.cx,
6346 wp.cy, wp.flags);
6347 ShowWindow(infoPtr->hwndHeader, SW_SHOWNORMAL);
6348 infoPtr->iconSize.cx = GetSystemMetrics(SM_CXSMICON);
6349 infoPtr->iconSize.cy = GetSystemMetrics(SM_CYSMICON);
6350 infoPtr->nItemWidth = LISTVIEW_GetItemWidth(hwnd, lpss->styleNew);
6351 infoPtr->nItemHeight = LISTVIEW_GetItemHeight(hwnd, lpss->styleNew);
6352 LISTVIEW_SetSize(hwnd, lpss->styleNew, -1, -1);
6353 LISTVIEW_SetViewInfo(hwnd, lpss->styleNew);
6354 break;
6356 case LVS_LIST:
6357 infoPtr->iconSize.cx = GetSystemMetrics(SM_CXSMICON);
6358 infoPtr->iconSize.cy = GetSystemMetrics(SM_CYSMICON);
6359 infoPtr->nItemWidth = LISTVIEW_GetItemWidth(hwnd, lpss->styleNew);
6360 infoPtr->nItemHeight = LISTVIEW_GetItemHeight(hwnd, lpss->styleNew);
6361 LISTVIEW_SetSize(hwnd, lpss->styleNew, -1, -1);
6362 LISTVIEW_SetViewInfo(hwnd, lpss->styleNew);
6363 break;
6365 case LVS_SMALLICON:
6366 infoPtr->iconSize.cx = GetSystemMetrics(SM_CXSMICON);
6367 infoPtr->iconSize.cy = GetSystemMetrics(SM_CYSMICON);
6368 LISTVIEW_SetSize(hwnd, lpss->styleNew, -1, -1);
6369 infoPtr->nItemWidth = LISTVIEW_GetItemWidth(hwnd, lpss->styleNew);
6370 infoPtr->nItemHeight = LISTVIEW_GetItemHeight(hwnd, lpss->styleNew);
6371 if (lpss->styleNew & LVS_ALIGNLEFT)
6373 LISTVIEW_AlignLeft(hwnd);
6375 else
6377 LISTVIEW_AlignTop(hwnd);
6379 break;
6382 LISTVIEW_SetScroll(hwnd, lpss->styleNew);
6384 /* print unsupported styles */
6385 LISTVIEW_UnsupportedStyles(lpss->styleNew);
6387 /* invalidate client area */
6388 InvalidateRect(hwnd, NULL, TRUE);
6391 return 0;
6394 /***
6395 * DESCRIPTION:
6396 * Window procedure of the listview control.
6398 * PARAMETER(S):
6399 * [I] HWND :
6400 * [I] UINT :
6401 * [I] WPARAM :
6402 * [I] LPARAM :
6404 * RETURN:
6407 LRESULT WINAPI LISTVIEW_WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam,
6408 LPARAM lParam)
6410 switch (uMsg)
6412 case LVM_APPROXIMATEVIEWRECT:
6413 return LISTVIEW_ApproximateViewRect(hwnd, (INT)wParam,
6414 LOWORD(lParam), HIWORD(lParam));
6415 case LVM_ARRANGE:
6416 return LISTVIEW_Arrange(hwnd, (INT)wParam);
6418 /* case LVM_CREATEDRAGIMAGE: */
6420 case LVM_DELETEALLITEMS:
6421 return LISTVIEW_DeleteAllItems(hwnd);
6423 case LVM_DELETECOLUMN:
6424 return LISTVIEW_DeleteColumn(hwnd, (INT)wParam);
6426 case LVM_DELETEITEM:
6427 return LISTVIEW_DeleteItem(hwnd, (INT)wParam);
6429 /* case LVM_EDITLABEL: */
6431 case LVM_ENSUREVISIBLE:
6432 return LISTVIEW_EnsureVisible(hwnd, (INT)wParam, (BOOL)lParam);
6434 case LVM_FINDITEMA:
6435 return LISTVIEW_FindItem(hwnd, (INT)wParam, (LPLVFINDINFO)lParam);
6437 case LVM_GETBKCOLOR:
6438 return LISTVIEW_GetBkColor(hwnd);
6440 /* case LVM_GETBKIMAGE: */
6442 case LVM_GETCALLBACKMASK:
6443 return LISTVIEW_GetCallbackMask(hwnd);
6445 case LVM_GETCOLUMNA:
6446 return LISTVIEW_GetColumnA(hwnd, (INT)wParam, (LPLVCOLUMNA)lParam);
6448 /* case LVM_GETCOLUMNW: */
6449 /* case LVM_GETCOLUMNORDERARRAY: */
6451 case LVM_GETCOLUMNWIDTH:
6452 return LISTVIEW_GetColumnWidth(hwnd, (INT)wParam);
6454 case LVM_GETCOUNTPERPAGE:
6455 return LISTVIEW_GetCountPerPage(hwnd);
6457 /* case LVM_GETEDITCONTROL: */
6458 /* case LVM_GETEXTENDEDLISTVIEWSTYLE: */
6460 case LVM_GETHEADER:
6461 return LISTVIEW_GetHeader(hwnd);
6463 /* case LVM_GETHOTCURSOR: */
6464 /* case LVM_GETHOTITEM: */
6465 /* case LVM_GETHOVERTIME: */
6467 case LVM_GETIMAGELIST:
6468 return LISTVIEW_GetImageList(hwnd, (INT)wParam);
6470 /* case LVM_GETISEARCHSTRING: */
6472 case LVM_GETITEMA:
6473 return LISTVIEW_GetItemA(hwnd, (LPLVITEMA)lParam);
6475 /* case LVM_GETITEMW: */
6477 case LVM_GETITEMCOUNT:
6478 return LISTVIEW_GetItemCount(hwnd);
6480 case LVM_GETITEMPOSITION:
6481 return LISTVIEW_GetItemPosition(hwnd, (INT)wParam, (LPPOINT)lParam);
6483 case LVM_GETITEMRECT:
6484 return LISTVIEW_GetItemRect(hwnd, (INT)wParam, (LPRECT)lParam);
6486 case LVM_GETITEMSPACING:
6487 return LISTVIEW_GetItemSpacing(hwnd, (BOOL)wParam);
6489 case LVM_GETITEMSTATE:
6490 return LISTVIEW_GetItemState(hwnd, (INT)wParam, (UINT)lParam);
6492 case LVM_GETITEMTEXTA:
6493 LISTVIEW_GetItemTextA(hwnd, (INT)wParam, (LPLVITEMA)lParam);
6494 break;
6496 /* case LVM_GETITEMTEXTW: */
6498 case LVM_GETNEXTITEM:
6499 return LISTVIEW_GetNextItem(hwnd, (INT)wParam, LOWORD(lParam));
6501 /* case LVM_GETNUMBEROFWORKAREAS: */
6503 case LVM_GETORIGIN:
6504 return LISTVIEW_GetOrigin(hwnd, (LPPOINT)lParam);
6506 case LVM_GETSELECTEDCOUNT:
6507 return LISTVIEW_GetSelectedCount(hwnd);
6509 case LVM_GETSELECTIONMARK:
6510 return LISTVIEW_GetSelectionMark(hwnd);
6512 case LVM_GETSTRINGWIDTHA:
6513 return LISTVIEW_GetStringWidthA (hwnd, (LPCSTR)lParam);
6515 /* case LVM_GETSTRINGWIDTHW: */
6516 /* case LVM_GETSUBITEMRECT: */
6518 case LVM_GETTEXTBKCOLOR:
6519 return LISTVIEW_GetTextBkColor(hwnd);
6521 case LVM_GETTEXTCOLOR:
6522 return LISTVIEW_GetTextColor(hwnd);
6524 /* case LVM_GETTOOLTIPS: */
6526 case LVM_GETTOPINDEX:
6527 return LISTVIEW_GetTopIndex(hwnd);
6529 /* case LVM_GETUNICODEFORMAT: */
6531 case LVM_GETVIEWRECT:
6532 return LISTVIEW_GetViewRect(hwnd, (LPRECT)lParam);
6534 /* case LVM_GETWORKAREAS: */
6536 case LVM_HITTEST:
6537 return LISTVIEW_HitTest(hwnd, (LPLVHITTESTINFO)lParam);
6539 case LVM_INSERTCOLUMNA:
6540 return LISTVIEW_InsertColumnA(hwnd, (INT)wParam,
6541 (LPLVCOLUMNA)lParam);
6543 /* case LVM_INSERTCOLUMNW: */
6545 case LVM_INSERTITEMA:
6546 return LISTVIEW_InsertItemA(hwnd, (LPLVITEMA)lParam);
6548 /* case LVM_INSERTITEMW: */
6550 case LVM_REDRAWITEMS:
6551 return LISTVIEW_RedrawItems(hwnd, (INT)wParam, (INT)lParam);
6553 /* case LVM_SCROLL: */
6554 /* return LISTVIEW_Scroll(hwnd, (INT)wParam, (INT)lParam); */
6556 case LVM_SETBKCOLOR:
6557 return LISTVIEW_SetBkColor(hwnd, (COLORREF)lParam);
6559 /* case LVM_SETBKIMAGE: */
6561 case LVM_SETCALLBACKMASK:
6562 return LISTVIEW_SetCallbackMask(hwnd, (UINT)wParam);
6564 case LVM_SETCOLUMNA:
6565 return LISTVIEW_SetColumnA(hwnd, (INT)wParam, (LPLVCOLUMNA)lParam);
6567 /* case LVM_SETCOLUMNW: */
6568 /* case LVM_SETCOLUMNORDERARRAY: */
6570 case LVM_SETCOLUMNWIDTH:
6571 return LISTVIEW_SetColumnWidth(hwnd, (INT)wParam, (INT)lParam);
6573 /* case LVM_SETEXTENDEDLISTVIEWSTYLE: */
6574 /* case LVM_SETHOTCURSOR: */
6575 /* case LVM_SETHOTITEM: */
6576 /* case LVM_SETHOVERTIME: */
6577 /* case LVM_SETICONSPACING: */
6579 case LVM_SETIMAGELIST:
6580 return LISTVIEW_SetImageList(hwnd, (INT)wParam, (HIMAGELIST)lParam);
6582 case LVM_SETITEMA:
6583 return LISTVIEW_SetItemA(hwnd, (LPLVITEMA)lParam);
6585 /* case LVM_SETITEMW: */
6587 case LVM_SETITEMCOUNT:
6588 LISTVIEW_SetItemCount(hwnd, (INT)wParam);
6589 break;
6591 case LVM_SETITEMPOSITION:
6592 return LISTVIEW_SetItemPosition(hwnd, (INT)wParam, (INT)LOWORD(lParam),
6593 (INT)HIWORD(lParam));
6595 /* case LVM_SETITEMPOSITION: */
6597 case LVM_SETITEMSTATE:
6598 return LISTVIEW_SetItemState(hwnd, (INT)wParam, (LPLVITEMA)lParam);
6600 case LVM_SETITEMTEXTA:
6601 return LISTVIEW_SetItemTextA(hwnd, (INT)wParam, (LPLVITEMA)lParam);
6603 /* case LVM_SETSELECTIONMARK: */
6605 case LVM_SETTEXTBKCOLOR:
6606 return LISTVIEW_SetTextBkColor(hwnd, (COLORREF)lParam);
6608 case LVM_SETTEXTCOLOR:
6609 return LISTVIEW_SetTextColor(hwnd, (COLORREF)lParam);
6611 /* case LVM_SETTOOLTIPS: */
6612 /* case LVM_SETUNICODEFORMAT: */
6613 /* case LVM_SETWORKAREAS: */
6615 case LVM_SORTITEMS:
6616 return LISTVIEW_SortItems(hwnd, wParam, lParam);
6618 /* case LVM_SUBITEMHITTEST: */
6620 case LVM_UPDATE:
6621 return LISTVIEW_Update(hwnd, (INT)wParam);
6623 /* case WM_CHAR: */
6624 /* case WM_COMMAND: */
6626 case WM_CREATE:
6627 return LISTVIEW_Create(hwnd, wParam, lParam);
6629 case WM_ERASEBKGND:
6630 return LISTVIEW_EraseBackground(hwnd, wParam, lParam);
6632 case WM_GETDLGCODE:
6633 return DLGC_WANTTAB | DLGC_WANTARROWS;
6635 case WM_GETFONT:
6636 return LISTVIEW_GetFont(hwnd);
6638 case WM_HSCROLL:
6639 return LISTVIEW_HScroll(hwnd, (INT)LOWORD(wParam),
6640 (INT)HIWORD(wParam), (HWND)lParam);
6642 case WM_KEYDOWN:
6643 return LISTVIEW_KeyDown(hwnd, (INT)wParam, (LONG)lParam);
6645 case WM_KILLFOCUS:
6646 return LISTVIEW_KillFocus(hwnd);
6648 case WM_LBUTTONDBLCLK:
6649 return LISTVIEW_LButtonDblClk(hwnd, (WORD)wParam, LOWORD(lParam),
6650 HIWORD(lParam));
6652 case WM_LBUTTONDOWN:
6653 return LISTVIEW_LButtonDown(hwnd, (WORD)wParam, LOWORD(lParam),
6654 HIWORD(lParam));
6655 case WM_LBUTTONUP:
6656 return LISTVIEW_LButtonUp(hwnd, (WORD)wParam, LOWORD(lParam),
6657 HIWORD(lParam));
6659 /* case WM_MOUSEMOVE: */
6660 /* return LISTVIEW_MouseMove (hwnd, wParam, lParam); */
6662 case WM_NCCREATE:
6663 return LISTVIEW_NCCreate(hwnd, wParam, lParam);
6665 case WM_NCDESTROY:
6666 return LISTVIEW_NCDestroy(hwnd);
6668 case WM_NOTIFY:
6669 return LISTVIEW_Notify(hwnd, (INT)wParam, (LPNMHDR)lParam);
6671 case WM_NOTIFYFORMAT:
6672 return LISTVIEW_NotifyFormat(hwnd, (HWND)wParam, (INT)lParam);
6674 case WM_PAINT:
6675 return LISTVIEW_Paint(hwnd, (HDC)wParam);
6677 case WM_RBUTTONDBLCLK:
6678 return LISTVIEW_RButtonDblClk(hwnd, (WORD)wParam, LOWORD(lParam),
6679 HIWORD(lParam));
6681 case WM_RBUTTONDOWN:
6682 return LISTVIEW_RButtonDown(hwnd, (WORD)wParam, LOWORD(lParam),
6683 HIWORD(lParam));
6685 case WM_RBUTTONUP:
6686 return LISTVIEW_RButtonUp(hwnd, (WORD)wParam, LOWORD(lParam),
6687 HIWORD(lParam));
6689 case WM_SETFOCUS:
6690 return LISTVIEW_SetFocus(hwnd, (HWND)wParam);
6692 case WM_SETFONT:
6693 return LISTVIEW_SetFont(hwnd, (HFONT)wParam, (WORD)lParam);
6695 /* case WM_SETREDRAW: */
6697 case WM_SIZE:
6698 return LISTVIEW_Size(hwnd, (int)SLOWORD(lParam), (int)SHIWORD(lParam));
6700 case WM_STYLECHANGED:
6701 return LISTVIEW_StyleChanged(hwnd, wParam, (LPSTYLESTRUCT)lParam);
6703 /* case WM_TIMER: */
6705 case WM_VSCROLL:
6706 return LISTVIEW_VScroll(hwnd, (INT)LOWORD(wParam),
6707 (INT)HIWORD(wParam), (HWND)lParam);
6709 /* case WM_WINDOWPOSCHANGED: */
6710 /* case WM_WININICHANGE: */
6712 default:
6713 if (uMsg >= WM_USER)
6715 ERR(listview, "unknown msg %04x wp=%08x lp=%08lx\n", uMsg, wParam,
6716 lParam);
6719 /* call default window procedure */
6720 return DefWindowProcA(hwnd, uMsg, wParam, lParam);
6723 return 0;
6726 /***
6727 * DESCRIPTION:
6728 * Registers the window class.
6730 * PARAMETER(S):
6731 * None
6733 * RETURN:
6734 * None
6736 VOID LISTVIEW_Register(VOID)
6738 WNDCLASSA wndClass;
6740 if (!GlobalFindAtomA(WC_LISTVIEWA))
6742 ZeroMemory(&wndClass, sizeof(WNDCLASSA));
6743 wndClass.style = CS_GLOBALCLASS | CS_DBLCLKS;
6744 wndClass.lpfnWndProc = (WNDPROC)LISTVIEW_WindowProc;
6745 wndClass.cbClsExtra = 0;
6746 wndClass.cbWndExtra = sizeof(LISTVIEW_INFO *);
6747 wndClass.hCursor = LoadCursorA(0, IDC_ARROWA);
6748 wndClass.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
6749 wndClass.lpszClassName = WC_LISTVIEWA;
6750 RegisterClassA(&wndClass);
6754 /***
6755 * DESCRIPTION:
6756 * Unregisters the window class.
6758 * PARAMETER(S):
6759 * None
6761 * RETURN:
6762 * None
6764 VOID LISTVIEW_Unregister(VOID)
6766 if (GlobalFindAtomA(WC_LISTVIEWA))
6768 UnregisterClassA(WC_LISTVIEWA, (HINSTANCE)NULL);