| /* |
| * Listview control |
| * |
| * Copyright 1998 Eric Kohl |
| * Copyright 1999 Luc Tourangeau |
| * |
| * NOTES |
| * Listview control implementation. |
| * |
| * TODO: |
| * LISTVIEW_GetMaxItemWidth : large icon view |
| * LISTVIEW_Notify : notification from children |
| * LISTVIEW_KeyDown : key press messages |
| * LISTVIEW_HScroll : small icon and icon |
| * LISTVIEW_VScroll : small icon and icon |
| * LISTVIEW_SortItems : empty stub |
| * LISTVIEW_SetItemPosition : small icon and icon |
| * LISTVIEW_SetItemCount : empty stub |
| * LISTVIEW_SetItem32W : no unicode yet! |
| * LISTVIEW_SetColumn32A : DOUBLE CHECK |
| * LISTVIEW_Scroll : scrolling in pixels |
| * LISTVIEW_RedrawItems : define bounding rect |
| * LISTVIEW_InsertItem32W : no unicode yet! |
| * LISTVIEW_InsertColumn32W : no unicode yet! |
| * LISTVIEW_GetViewRect : small icon and icon |
| * LISTVIEW_GetOrigin : small icon and icon |
| * LISTVIEW_GetNumberOfWorkAreas : small icon and icon |
| * LISTVIEW_GetNextItem : all |
| * LISTVIEW_SetScroll : scrolling in pixels |
| * LISTVIEW_GetItemRect : all |
| * LISTVIEW_GetHotCursor : all |
| * LISTVIEW_GetHotItem : all |
| * LISTVIEW_GetHoverTime : all |
| * LISTVIEW_GetISearchString : all |
| * LISTVIEW_GetBkImage : all |
| * LISTVIEW_FindItem : all |
| * LISTVIEW_EnsureVisible : some |
| * LISTVIEW_EditLabel : REPORT (need to implement a timer) |
| * LISTVIEW_GetItemPosition : small icon and icon |
| * LISTVIEW_GetItemRect : some |
| * LISTVIEW_Arrange : small icon and icon |
| * LISTVIEW_ApproximateViewRect : report, small icon and icon |
| * LISTVIEW_RefreshIcon : large icon draw function |
| */ |
| |
| #include "windows.h" |
| #include "commctrl.h" |
| #include "listview.h" |
| #include "win.h" |
| #include "debug.h" |
| #include "winuser.h" |
| #include "string.h" |
| |
| /* constants */ |
| #define DISP_TEXT_SIZE 128 |
| #define WIDTH_PADDING 12 |
| #define HEIGHT_PADDING 2 |
| #define MIN_COLUMN_WIDTH 96 |
| |
| /* macro section */ |
| #define GETITEMCOUNT(infoPtr) ((infoPtr)->hdpaItems->nItemCount) |
| #define ListView_LVNotify(hwnd,lCtrlId,plvnm) \ |
| (BOOL)SendMessageA((hwnd),WM_NOTIFY,(WPARAM)(INT)lCtrlId,(LPARAM)(LPNMLISTVIEW)(plvnm)) |
| #define ListView_Notify(hwnd,lCtrlId,pnmh) \ |
| (BOOL)SendMessageA((hwnd),WM_NOTIFY,(WPARAM)(INT)lCtrlId,(LPARAM)(LPNMHDR)(pnmh)) |
| |
| /* forward declarations */ |
| static VOID LISTVIEW_SetSize(HWND hwnd, LONG lStyle, LONG lWidth, |
| LONG lHeight); |
| static VOID LISTVIEW_SetViewInfo(HWND hwnd); |
| static VOID LISTVIEW_SetScroll(HWND hwnd); |
| static VOID LISTVIEW_AddGroupSelection(HWND hwnd, INT nItem); |
| static VOID LISTVIEW_AddSelection(HWND hwnd, INT nItem); |
| static BOOL LISTVIEW_ToggleSelection(HWND hwnd, INT nItem); |
| static VOID LISTVIEW_SetGroupSelection(HWND hwnd, INT nItem); |
| static VOID LISTVIEW_SetSelection(HWND hwnd, INT nItem); |
| static VOID LISTVIEW_RemoveSelections(HWND hwnd, INT nFirst, INT nLast); |
| static VOID LISTVIEW_SetItemFocus(HWND hwnd, INT nItem); |
| static BOOL LISTVIEW_RemoveSubItem(HDPA hdpaSubItems, INT nSubItem); |
| static BOOL LISTVIEW_RemoveColumn(HDPA hdpaItems, INT nColumn); |
| static BOOL LISTVIEW_InitItem(HWND hwnd, LISTVIEW_ITEM *lpItem, |
| LPLVITEMA lpLVItem); |
| static BOOL LISTVIEW_InitSubItem(HWND hwnd, LISTVIEW_SUBITEM *lpSubItem, |
| LPLVITEMA lpLVItem); |
| static BOOL LISTVIEW_AddSubItem(HWND hwnd, LPLVITEMA lpLVItem); |
| static BOOL LISTVIEW_SetItem(HWND hwnd, LPLVITEMA lpLVItem); |
| static BOOL LISTVIEW_SetSubItem(HWND hwnd, LPLVITEMA lpLVItem); |
| static INT LISTVIEW_FindInsertPosition(HDPA hdpaSubItems, INT nSubItem); |
| static LISTVIEW_SUBITEM* LISTVIEW_GetSubItem(HDPA hdpaSubItems, INT nSubItem); |
| |
| |
| /*** |
| * DESCRIPTION: |
| * Prints a message for unsupported window styles. |
| * |
| * PARAMETER(S): |
| * [I] LONG : window style |
| * |
| * RETURN: |
| * None |
| */ |
| static VOID LISTVIEW_UnsupportedStyles(LONG lStyle) |
| { |
| if ((LVS_TYPEMASK & lStyle) == LVS_ALIGNLEFT) |
| { |
| FIXME(listview, " LVS_ALIGNLEFT\n"); |
| } |
| |
| if ((LVS_TYPEMASK & lStyle) == LVS_ALIGNTOP) |
| { |
| FIXME(listview, " LVS_ALIGNTOP\n"); |
| } |
| |
| if ((LVS_TYPEMASK & lStyle) == LVS_AUTOARRANGE) |
| { |
| FIXME(listview, " LVS_AUTOARRANGE\n"); |
| } |
| |
| if ((LVS_TYPEMASK & lStyle) == LVS_EDITLABELS) |
| { |
| FIXME(listview, " LVS_EDITLABELS\n"); |
| } |
| |
| if ((LVS_TYPEMASK & lStyle) == LVS_ICON) |
| { |
| FIXME(listview, " LVS_ICON\n"); |
| } |
| |
| if ((LVS_TYPEMASK & lStyle) == LVS_NOCOLUMNHEADER) |
| { |
| FIXME(listview, " LVS_SORTDESCENDING\n"); |
| } |
| |
| if ((LVS_TYPEMASK & lStyle) == LVS_NOLABELWRAP) |
| { |
| FIXME(listview, " LVS_NOLABELWRAP\n"); |
| } |
| |
| if ((LVS_TYPEMASK & lStyle) == LVS_NOSCROLL) |
| { |
| FIXME(listview, " LVS_NOSCROLL\n"); |
| } |
| |
| if ((LVS_TYPEMASK & lStyle) == LVS_NOSORTHEADER) |
| { |
| FIXME(listview, " LVS_NOSORTHEADER\n"); |
| } |
| |
| if ((LVS_TYPEMASK & lStyle) == LVS_OWNERDRAWFIXED) |
| { |
| FIXME(listview, " LVS_OWNERDRAWFIXED\n"); |
| } |
| |
| if ((LVS_TYPEMASK & lStyle) == LVS_SHAREIMAGELISTS) |
| { |
| FIXME(listview, " LVS_SHAREIMAGELISTS\n"); |
| } |
| |
| if ((LVS_TYPEMASK & lStyle) == LVS_SHOWSELALWAYS) |
| { |
| FIXME(listview, " LVS_SHOWSELALWAYS\n"); |
| } |
| |
| if ((LVS_TYPEMASK & lStyle) == LVS_SINGLESEL) |
| { |
| FIXME(listview, " LVS_SINGLESEL\n"); |
| } |
| |
| if ((LVS_TYPEMASK & lStyle) == LVS_SMALLICON) |
| { |
| FIXME(listview, " LVS_SMALLICON\n"); |
| } |
| |
| if ((LVS_TYPEMASK & lStyle) == LVS_SORTDESCENDING) |
| { |
| FIXME(listview, " LVS_SORTDESCENDING\n"); |
| } |
| |
| if ((LVS_TYPEMASK & lStyle) == LVS_SORTDESCENDING) |
| { |
| FIXME(listview, " LVS_SORTDESCENDING\n"); |
| } |
| } |
| |
| /*** |
| * DESCRIPTION: |
| * Retrieves display information. |
| * |
| * PARAMETER(S): |
| * [I] HWND : window handle |
| * [I] LISTVIEW_ITEM* : listview control item |
| * [O] INT : image index |
| * [O] UINT : state value |
| * [O] CHAR** : string |
| * [I] INT : size of string |
| * |
| * RETURN: |
| * None |
| */ |
| static VOID LISTVIEW_GetItemDispInfo(HWND hwnd, INT nItem, |
| LISTVIEW_ITEM *lpItem, INT *pnDispImage, |
| UINT *puState, CHAR **ppszDispText, |
| INT nDispTextSize) |
| { |
| LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0); |
| LONG lCtrlId = GetWindowLongA(hwnd, GWL_ID); |
| NMLVDISPINFOA dispInfo; |
| ZeroMemory(&dispInfo, sizeof(NMLVDISPINFOA)); |
| |
| if ((pnDispImage != NULL) && (lpItem->iImage == I_IMAGECALLBACK)) |
| { |
| dispInfo.item.mask |= LVIF_IMAGE; |
| } |
| |
| if ((ppszDispText != NULL) && (lpItem->pszText == LPSTR_TEXTCALLBACKA)) |
| { |
| ZeroMemory(*ppszDispText, sizeof(CHAR)*nDispTextSize); |
| dispInfo.item.mask |= LVIF_TEXT; |
| dispInfo.item.pszText = *ppszDispText; |
| dispInfo.item.cchTextMax = nDispTextSize; |
| } |
| |
| if ((puState != NULL) && (infoPtr->uCallbackMask != 0)) |
| { |
| dispInfo.item.mask |= LVIF_STATE; |
| dispInfo.item.stateMask = infoPtr->uCallbackMask; |
| } |
| |
| if (dispInfo.item.mask != 0) |
| { |
| dispInfo.hdr.hwndFrom = hwnd; |
| dispInfo.hdr.idFrom = lCtrlId; |
| dispInfo.hdr.code = LVN_GETDISPINFOA; |
| dispInfo.item.iItem = nItem; |
| dispInfo.item.iSubItem = 0; |
| dispInfo.item.lParam = lpItem->lParam; |
| ListView_Notify(GetParent(hwnd), lCtrlId, &dispInfo); |
| } |
| |
| if (pnDispImage != NULL) |
| { |
| if (dispInfo.item.mask & LVIF_IMAGE) |
| { |
| *pnDispImage = dispInfo.item.iImage; |
| } |
| else |
| { |
| *pnDispImage = lpItem->iImage; |
| } |
| } |
| |
| if (ppszDispText != NULL) |
| { |
| if (dispInfo.item.mask & LVIF_TEXT) |
| { |
| if (dispInfo.item.mask & LVIF_DI_SETITEM) |
| { |
| Str_SetPtrA(&lpItem->pszText, dispInfo.item.pszText); |
| } |
| *ppszDispText = dispInfo.item.pszText; |
| } |
| else |
| { |
| *ppszDispText = lpItem->pszText; |
| } |
| } |
| |
| if (puState != NULL) |
| { |
| if (dispInfo.item.mask & LVIF_STATE) |
| { |
| *puState = lpItem->state; |
| *puState &= ~dispInfo.item.stateMask; |
| *puState |= (dispInfo.item.state & dispInfo.item.stateMask); |
| } |
| else |
| { |
| *puState = lpItem->state; |
| } |
| } |
| } |
| |
| /*** |
| * DESCRIPTION: |
| * Retrieves display information. |
| * |
| * PARAMETER(S): |
| * [I] HWND : window handle |
| * [I] LISTVIEW_SUBITEM* : listview control subitem |
| * [O] INT : image index |
| * [O] UINT : state value |
| * [O] CHAR** : string |
| * [I] INT : size of string |
| * |
| * RETURN: |
| * None |
| */ |
| static VOID LISTVIEW_GetSubItemDispInfo(HWND hwnd, INT nItem, LPARAM lParam, |
| LISTVIEW_SUBITEM *lpSubItem, |
| INT nColumn, INT *pnDispImage, |
| CHAR **ppszDispText, INT nDispTextSize) |
| { |
| LONG lCtrlId = GetWindowLongA(hwnd, GWL_ID); |
| NMLVDISPINFOA dispInfo; |
| ZeroMemory(&dispInfo, sizeof(NMLVDISPINFOA)); |
| |
| if (lpSubItem == NULL) |
| { |
| ZeroMemory(*ppszDispText, sizeof(CHAR)*nDispTextSize); |
| dispInfo.item.mask |= LVIF_TEXT; |
| dispInfo.item.pszText = *ppszDispText; |
| dispInfo.item.cchTextMax = nDispTextSize; |
| dispInfo.hdr.hwndFrom = hwnd; |
| dispInfo.hdr.idFrom = lCtrlId; |
| dispInfo.hdr.code = LVN_GETDISPINFOA; |
| dispInfo.item.iItem = nItem; |
| dispInfo.item.iSubItem = nColumn; |
| dispInfo.item.lParam = lParam; |
| ListView_Notify(GetParent(hwnd), lCtrlId, &dispInfo); |
| if (dispInfo.item.mask & LVIF_DI_SETITEM) |
| { |
| Str_SetPtrA(&lpSubItem->pszText, dispInfo.item.pszText); |
| } |
| *ppszDispText = dispInfo.item.pszText; |
| } |
| else |
| { |
| if ((pnDispImage != NULL) && (lpSubItem->iImage == I_IMAGECALLBACK)) |
| { |
| dispInfo.item.mask |= LVIF_IMAGE; |
| } |
| |
| if ((ppszDispText != NULL) && (lpSubItem->pszText == LPSTR_TEXTCALLBACKA)) |
| { |
| ZeroMemory(*ppszDispText, sizeof(CHAR)*nDispTextSize); |
| dispInfo.item.mask |= LVIF_TEXT; |
| dispInfo.item.pszText = *ppszDispText; |
| dispInfo.item.cchTextMax = nDispTextSize; |
| } |
| |
| if (dispInfo.item.mask != 0) |
| { |
| dispInfo.hdr.hwndFrom = hwnd; |
| dispInfo.hdr.idFrom = lCtrlId; |
| dispInfo.hdr.code = LVN_GETDISPINFOA; |
| dispInfo.item.iItem = nItem; |
| dispInfo.item.iSubItem = lpSubItem->iSubItem; |
| dispInfo.item.lParam = lParam; |
| ListView_Notify(GetParent(hwnd), lCtrlId, &dispInfo); |
| } |
| |
| if (pnDispImage != NULL) |
| { |
| if (dispInfo.item.mask & LVIF_IMAGE) |
| { |
| *pnDispImage = dispInfo.item.iImage; |
| } |
| else |
| { |
| *pnDispImage = lpSubItem->iImage; |
| } |
| } |
| |
| if (ppszDispText != NULL) |
| { |
| if (dispInfo.item.mask & LVIF_TEXT) |
| { |
| if (dispInfo.item.mask & LVIF_DI_SETITEM) |
| { |
| Str_SetPtrA(&lpSubItem->pszText, dispInfo.item.pszText); |
| } |
| *ppszDispText = dispInfo.item.pszText; |
| } |
| else |
| { |
| *ppszDispText = lpSubItem->pszText; |
| } |
| } |
| } |
| } |
| |
| /*** |
| * DESCRIPTION: |
| * Calculates a new column width. |
| * |
| * PARAMETER(S): |
| * [I] HWND : window handle |
| * |
| * RETURN: |
| * Returns item width. |
| */ |
| static INT LISTVIEW_GetMaxItemWidth(HWND hwnd) |
| { |
| LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0); |
| LONG lStyle = GetWindowLongA(hwnd, GWL_STYLE); |
| LISTVIEW_ITEM *lpItem; |
| HDPA hdpaSubItems; |
| INT nStringWidth; |
| INT nMaxItemWidth = 0; |
| INT i; |
| |
| if ((LVS_TYPEMASK & lStyle) == LVS_ICON) |
| { |
| /* TO DO */ |
| } |
| else |
| { |
| for (i = 0; i < GETITEMCOUNT(infoPtr); i++) |
| { |
| hdpaSubItems = (HDPA)DPA_GetPtr(infoPtr->hdpaItems, i); |
| if (hdpaSubItems != NULL) |
| { |
| lpItem = (LISTVIEW_ITEM *)DPA_GetPtr(hdpaSubItems, 0); |
| if (lpItem != NULL) |
| { |
| CHAR szDispText[DISP_TEXT_SIZE]; |
| LPSTR pszDispText; |
| pszDispText = szDispText; |
| LISTVIEW_GetItemDispInfo(hwnd, i, lpItem, NULL, NULL, &pszDispText, |
| DISP_TEXT_SIZE); |
| nStringWidth = ListView_GetStringWidthA(hwnd, pszDispText); |
| nMaxItemWidth = max(nMaxItemWidth, nStringWidth); |
| } |
| } |
| } |
| |
| /* add arbitrary padding for separating columns */ |
| nMaxItemWidth += WIDTH_PADDING; |
| |
| if (infoPtr->himlSmall != NULL) |
| { |
| nMaxItemWidth += infoPtr->iconSize.cx; |
| } |
| |
| if (infoPtr->himlState != NULL) |
| { |
| nMaxItemWidth += infoPtr->iconSize.cx; |
| } |
| } |
| |
| nMaxItemWidth = max(MIN_COLUMN_WIDTH, nMaxItemWidth); |
| |
| return nMaxItemWidth; |
| } |
| |
| /*** |
| * DESCRIPTION: |
| * Sets diplay information (needed for drawing and calculations). |
| * |
| * PARAMETER(S): |
| * [I] HWND : window handle |
| * |
| * RETURN: |
| * None |
| */ |
| static VOID LISTVIEW_SetViewInfo(HWND hwnd) |
| { |
| LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0); |
| LONG lStyle = GetWindowLongA(hwnd, GWL_STYLE); |
| INT nHeight; |
| INT nWidth; |
| HDC hdc; |
| HFONT hOldFont; |
| TEXTMETRICA tm; |
| |
| /* get text height */ |
| hdc = GetDC(hwnd); |
| hOldFont = SelectObject(hdc, infoPtr->hFont); |
| GetTextMetricsA(hdc, &tm); |
| |
| nHeight = infoPtr->rcList.bottom - infoPtr->rcList.top; |
| nWidth = infoPtr->rcList.right - infoPtr->rcList.left; |
| |
| switch (LVS_TYPEMASK & lStyle) |
| { |
| case LVS_LIST: |
| infoPtr->nColumnWidth = LISTVIEW_GetMaxItemWidth(hwnd); |
| infoPtr->nItemHeight = (max(tm.tmHeight, infoPtr->iconSize.cy) + |
| HEIGHT_PADDING); |
| |
| infoPtr->nCountPerColumn = nHeight / infoPtr->nItemHeight; |
| if (infoPtr->nCountPerColumn == 0) |
| { |
| infoPtr->nCountPerColumn = 1; |
| } |
| |
| infoPtr->nCountPerRow = nWidth / infoPtr->nColumnWidth; |
| if (infoPtr->nCountPerRow == 0) |
| { |
| infoPtr->nCountPerRow = 1; |
| } |
| break; |
| |
| case LVS_REPORT: |
| infoPtr->nItemHeight = (max(tm.tmHeight, infoPtr->iconSize.cy) + |
| HEIGHT_PADDING); |
| infoPtr->nCountPerRow = 1; |
| infoPtr->nCountPerColumn = nHeight / infoPtr->nItemHeight; |
| if (infoPtr->nCountPerColumn == 0) |
| { |
| infoPtr->nCountPerColumn = 1; |
| } |
| break; |
| |
| } |
| |
| SelectObject(hdc, hOldFont); |
| ReleaseDC(hwnd, hdc); |
| } |
| |
| /*** |
| * DESCRIPTION: |
| * Adds a block of selections. |
| * |
| * PARAMETER(S): |
| * [I] HWND : window handle |
| * [I] INT : item index |
| * |
| * RETURN: |
| * None |
| */ |
| static VOID LISTVIEW_AddGroupSelection(HWND hwnd, INT nItem) |
| { |
| LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0); |
| INT nFirst = min(infoPtr->nSelectionMark, nItem); |
| INT nLast = max(infoPtr->nSelectionMark, nItem); |
| LVITEMA lvItem; |
| INT i; |
| |
| lvItem.state = LVIS_SELECTED; |
| lvItem.stateMask= LVIS_SELECTED; |
| |
| for (i = nFirst; i <= nLast; i++) |
| { |
| ListView_SetItemState(hwnd, i, &lvItem); |
| } |
| |
| LISTVIEW_SetItemFocus(hwnd, nItem); |
| infoPtr->nSelectionMark = nItem; |
| } |
| |
| /*** |
| * DESCRIPTION: |
| * Adds a single selection. |
| * |
| * PARAMETER(S): |
| * [I] HWND : window handle |
| * [I] INT : item index |
| * |
| * RETURN: |
| * None |
| */ |
| static VOID LISTVIEW_AddSelection(HWND hwnd, INT nItem) |
| { |
| LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0); |
| LVITEMA lvItem; |
| |
| lvItem.state = LVIS_SELECTED; |
| lvItem.stateMask= LVIS_SELECTED; |
| |
| ListView_SetItemState(hwnd, nItem, &lvItem); |
| |
| LISTVIEW_SetItemFocus(hwnd, nItem); |
| infoPtr->nSelectionMark = nItem; |
| } |
| |
| /*** |
| * DESCRIPTION: |
| * Selects or unselects an item. |
| * |
| * PARAMETER(S): |
| * [I] HWND : window handle |
| * [I] INT : item index |
| * |
| * RETURN: |
| * SELECT: TRUE |
| * UNSELECT : FALSE |
| */ |
| static BOOL LISTVIEW_ToggleSelection(HWND hwnd, INT nItem) |
| { |
| LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0); |
| BOOL bResult; |
| LVITEMA lvItem; |
| |
| lvItem.stateMask= LVIS_SELECTED; |
| |
| if (ListView_GetItemState(hwnd, nItem, LVIS_SELECTED) & LVIS_SELECTED) |
| { |
| lvItem.state = 0; |
| ListView_SetItemState(hwnd, nItem, &lvItem); |
| bResult = FALSE; |
| } |
| else |
| { |
| lvItem.state = LVIS_SELECTED; |
| ListView_SetItemState(hwnd, nItem, &lvItem); |
| bResult = TRUE; |
| } |
| |
| LISTVIEW_SetItemFocus(hwnd, nItem); |
| infoPtr->nSelectionMark = nItem; |
| |
| return bResult; |
| } |
| |
| /*** |
| * DESCRIPTION: |
| * Reinitilizes the listview items. |
| * |
| * PARAMETER(S): |
| * [I] HWND : window handle |
| * [I] INT : item index |
| * |
| * RETURN: |
| * None |
| */ |
| static VOID LISTVIEW_SetGroupSelection(HWND hwnd, INT nItem) |
| { |
| LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0); |
| INT nFirst = min(infoPtr->nSelectionMark, nItem); |
| INT nLast = max(infoPtr->nSelectionMark, nItem); |
| LVITEMA lvItem; |
| INT i; |
| |
| if (nFirst > 0) |
| { |
| LISTVIEW_RemoveSelections(hwnd, 0, nFirst - 1); |
| } |
| |
| if (nLast < GETITEMCOUNT(infoPtr)) |
| { |
| LISTVIEW_RemoveSelections(hwnd, nLast + 1, GETITEMCOUNT(infoPtr)); |
| } |
| |
| lvItem.state = LVIS_SELECTED; |
| lvItem.stateMask = LVIS_SELECTED; |
| |
| for (i = nFirst; i <= nLast; i++) |
| { |
| ListView_SetItemState(hwnd, i, &lvItem); |
| } |
| |
| LISTVIEW_SetItemFocus(hwnd, nItem); |
| } |
| |
| /*** |
| * DESCRIPTION: |
| * Manages the item focus. |
| * |
| * PARAMETER(S): |
| * [I] HWND : window handle |
| * [I] INT : item index |
| * |
| * RETURN: |
| * None |
| */ |
| static VOID LISTVIEW_SetItemFocus(HWND hwnd, INT nItem) |
| { |
| LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0); |
| LVITEMA lvItem; |
| |
| lvItem.state = 0; |
| lvItem.stateMask = LVIS_FOCUSED; |
| ListView_SetItemState(hwnd, infoPtr->nFocusedItem, &lvItem); |
| |
| lvItem.state = LVIS_FOCUSED; |
| lvItem.stateMask = LVIS_FOCUSED; |
| ListView_SetItemState(hwnd, nItem, &lvItem); |
| |
| infoPtr->nFocusedItem = nItem; |
| |
| /* if multiple selection is allowed */ |
| ListView_EnsureVisible(hwnd, nItem, FALSE); |
| } |
| |
| /*** |
| * DESCRIPTION: |
| * Reinitilizes the listview items. |
| * |
| * PARAMETER(S): |
| * [I] HWND : window handle |
| * [I] INT : item index |
| * |
| * RETURN: |
| * None |
| */ |
| static VOID LISTVIEW_SetSelection(HWND hwnd, INT nItem) |
| { |
| LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0); |
| LVITEMA lvItem; |
| |
| if (nItem > 0) |
| { |
| LISTVIEW_RemoveSelections(hwnd, 0, nItem - 1); |
| } |
| |
| if (nItem < GETITEMCOUNT(infoPtr)) |
| { |
| LISTVIEW_RemoveSelections(hwnd, nItem + 1, GETITEMCOUNT(infoPtr)); |
| } |
| |
| lvItem.state = 0; |
| lvItem.stateMask = LVIS_FOCUSED; |
| ListView_SetItemState(hwnd, infoPtr->nFocusedItem, &lvItem); |
| |
| lvItem.state = LVIS_SELECTED | LVIS_FOCUSED; |
| lvItem.stateMask = LVIS_SELECTED | LVIS_FOCUSED; |
| ListView_SetItemState(hwnd, nItem, &lvItem); |
| |
| infoPtr->nFocusedItem = nItem; |
| infoPtr->nSelectionMark = nItem; |
| } |
| |
| /*** |
| * DESCRIPTION: |
| * Reinitilizes the listview items. |
| * |
| * PARAMETER(S): |
| * [I] HWND : window handle |
| * [I] INT : item index |
| * |
| * RETURN: |
| * None |
| */ |
| static VOID LISTVIEW_KeySelection(HWND hwnd, INT nItem) |
| { |
| WORD wShift = HIWORD(GetKeyState(VK_SHIFT)); |
| WORD wCtrl = HIWORD(GetKeyState(VK_CONTROL)); |
| |
| if (wShift) |
| { |
| LISTVIEW_SetGroupSelection(hwnd, nItem); |
| } |
| else if (wCtrl) |
| { |
| LISTVIEW_SetItemFocus(hwnd, nItem); |
| } |
| else |
| { |
| LISTVIEW_SetSelection(hwnd, nItem); |
| |
| /* if multiple selection is allowed */ |
| ListView_EnsureVisible(hwnd, nItem, FALSE); |
| } |
| } |
| |
| /*** |
| * DESCRIPTION: |
| * Removes all selection states. |
| * |
| * PARAMETER(S): |
| * [I] HWND : window handle |
| * [I] INT : item index |
| * |
| * RETURN: |
| * SUCCCESS : TRUE |
| * FAILURE : FALSE |
| */ |
| static VOID LISTVIEW_RemoveSelections(HWND hwnd, INT nFirst, INT nLast) |
| { |
| LVITEMA lvItem; |
| INT i; |
| |
| lvItem.state = 0; |
| lvItem.stateMask = LVIS_SELECTED; |
| |
| for (i = nFirst; i <= nLast; i++) |
| { |
| ListView_SetItemState(hwnd, i, &lvItem); |
| } |
| } |
| |
| /*** |
| * DESCRIPTION: |
| * Removes a column. |
| * |
| * PARAMETER(S): |
| * [IO] HDPA : dynamic pointer array handle |
| * [I] INT : column index (subitem index) |
| * |
| * RETURN: |
| * SUCCCESS : TRUE |
| * FAILURE : FALSE |
| */ |
| static BOOL LISTVIEW_RemoveColumn(HDPA hdpaItems, INT nSubItem) |
| { |
| BOOL bResult = TRUE; |
| HDPA hdpaSubItems; |
| INT i; |
| |
| for (i = 0; i < hdpaItems->nItemCount; i++) |
| { |
| hdpaSubItems = (HDPA)DPA_GetPtr(hdpaItems, i); |
| if (hdpaSubItems != NULL) |
| { |
| if (LISTVIEW_RemoveSubItem(hdpaSubItems, nSubItem) == FALSE) |
| { |
| bResult = FALSE; |
| } |
| } |
| } |
| |
| return bResult; |
| } |
| |
| /*** |
| * DESCRIPTION: |
| * Removes a subitem at a given position. |
| * |
| * PARAMETER(S): |
| * [IO] HDPA : dynamic pointer array handle |
| * [I] INT : subitem index |
| * |
| * RETURN: |
| * SUCCCESS : TRUE |
| * FAILURE : FALSE |
| */ |
| static BOOL LISTVIEW_RemoveSubItem(HDPA hdpaSubItems, INT nSubItem) |
| { |
| LISTVIEW_SUBITEM *lpSubItem; |
| INT i; |
| |
| for (i = 1; i < hdpaSubItems->nItemCount; i++) |
| { |
| lpSubItem = (LISTVIEW_SUBITEM *)DPA_GetPtr(hdpaSubItems, i); |
| if (lpSubItem != NULL) |
| { |
| if (lpSubItem->iSubItem == nSubItem) |
| { |
| /* free string */ |
| if ((lpSubItem->pszText != NULL) && |
| (lpSubItem->pszText != LPSTR_TEXTCALLBACKA)) |
| { |
| COMCTL32_Free(lpSubItem->pszText); |
| } |
| |
| /* free item */ |
| COMCTL32_Free(lpSubItem); |
| |
| /* free dpa memory */ |
| if (DPA_DeletePtr(hdpaSubItems, i) == NULL) |
| { |
| return FALSE; |
| } |
| } |
| else if (lpSubItem->iSubItem > nSubItem) |
| { |
| return TRUE; |
| } |
| } |
| } |
| |
| return TRUE; |
| } |
| |
| /*** |
| * DESCRIPTION: |
| * Compares the item information. |
| * |
| * PARAMETER(S): |
| * [I] LISTVIEW_ITEM *: destination item |
| * [I] LPLVITEM : source item |
| * |
| * RETURN: |
| * SUCCCESS : TRUE (EQUAL) |
| * FAILURE : FALSE (NOT EQUAL) |
| */ |
| static UINT LISTVIEW_GetItemChanges(LISTVIEW_ITEM *lpItem, LPLVITEMA lpLVItem) |
| { |
| UINT uChanged = 0; |
| |
| if ((lpItem != NULL) && (lpLVItem != NULL)) |
| { |
| if (lpLVItem->mask & LVIF_STATE) |
| { |
| if ((lpItem->state & lpLVItem->stateMask) != |
| (lpLVItem->state & lpLVItem->stateMask)) |
| { |
| uChanged |= LVIF_STATE; |
| } |
| } |
| |
| if (lpLVItem->mask & LVIF_IMAGE) |
| { |
| if (lpItem->iImage != lpLVItem->iImage) |
| { |
| uChanged |= LVIF_IMAGE; |
| } |
| } |
| |
| if (lpLVItem->mask & LVIF_PARAM) |
| { |
| if (lpItem->lParam != lpLVItem->lParam) |
| { |
| uChanged |= LVIF_PARAM; |
| } |
| } |
| |
| if (lpLVItem->mask & LVIF_INDENT) |
| { |
| if (lpItem->iIndent != lpLVItem->iIndent) |
| { |
| uChanged |= LVIF_INDENT; |
| } |
| } |
| |
| if (lpLVItem->mask & LVIF_TEXT) |
| { |
| if (lpLVItem->pszText == LPSTR_TEXTCALLBACKA) |
| { |
| if (lpItem->pszText != LPSTR_TEXTCALLBACKA) |
| { |
| uChanged |= LVIF_TEXT; |
| } |
| } |
| else |
| { |
| if (lpItem->pszText == LPSTR_TEXTCALLBACKA) |
| { |
| uChanged |= LVIF_TEXT; |
| } |
| } |
| } |
| } |
| |
| return uChanged; |
| } |
| |
| /*** |
| * DESCRIPTION: |
| * Initializes item attributes. |
| * |
| * PARAMETER(S): |
| * [I] HWND : window handle |
| * [O] LISTVIEW_ITEM *: destination item |
| * [I] LPLVITEM : source item |
| * |
| * RETURN: |
| * SUCCCESS : TRUE |
| * FAILURE : FALSE |
| */ |
| static BOOL LISTVIEW_InitItem(HWND hwnd, LISTVIEW_ITEM *lpItem, |
| LPLVITEMA lpLVItem) |
| { |
| LONG lStyle = GetWindowLongA(hwnd, GWL_STYLE); |
| BOOL bResult = FALSE; |
| |
| if ((lpItem != NULL) && (lpLVItem != NULL)) |
| { |
| bResult = TRUE; |
| |
| if (lpLVItem->mask & LVIF_STATE) |
| { |
| lpItem->state &= ~lpLVItem->stateMask; |
| lpItem->state |= (lpLVItem->state & lpLVItem->stateMask); |
| } |
| |
| if (lpLVItem->mask & LVIF_IMAGE) |
| { |
| lpItem->iImage = lpLVItem->iImage; |
| } |
| |
| if (lpLVItem->mask & LVIF_PARAM) |
| { |
| lpItem->lParam = lpLVItem->lParam; |
| } |
| |
| if (lpLVItem->mask & LVIF_INDENT) |
| { |
| lpItem->iIndent = lpLVItem->iIndent; |
| } |
| |
| if (lpLVItem->mask & LVIF_TEXT) |
| { |
| if (lpLVItem->pszText == LPSTR_TEXTCALLBACKA) |
| { |
| if ((lStyle & LVS_SORTASCENDING) || (lStyle & LVS_SORTDESCENDING)) |
| { |
| return FALSE; |
| } |
| |
| if ((lpItem->pszText != NULL) && |
| (lpItem->pszText != LPSTR_TEXTCALLBACKA)) |
| { |
| COMCTL32_Free(lpItem->pszText); |
| } |
| |
| lpItem->pszText = LPSTR_TEXTCALLBACKA; |
| } |
| else |
| { |
| if (lpItem->pszText == LPSTR_TEXTCALLBACKA) |
| { |
| lpItem->pszText = NULL; |
| } |
| |
| bResult = Str_SetPtrA(&lpItem->pszText, lpLVItem->pszText); |
| } |
| } |
| } |
| |
| return bResult; |
| } |
| |
| /*** |
| * DESCRIPTION: |
| * Initializes subitem attributes. |
| * |
| * NOTE: the documentation specifies that the operation fails if the user |
| * tries to set the indent of a subitem. |
| * |
| * PARAMETER(S): |
| * [I] HWND : window handle |
| * [O] LISTVIEW_SUBITEM *: destination subitem |
| * [I] LPLVITEM : source subitem |
| * |
| * RETURN: |
| * SUCCCESS : TRUE |
| * FAILURE : FALSE |
| */ |
| static BOOL LISTVIEW_InitSubItem(HWND hwnd, LISTVIEW_SUBITEM *lpSubItem, |
| LPLVITEMA lpLVItem) |
| { |
| LONG lStyle = GetWindowLongA(hwnd, GWL_STYLE); |
| BOOL bResult = FALSE; |
| |
| if ((lpSubItem != NULL) && (lpLVItem != NULL)) |
| { |
| if (!(lpLVItem->mask & LVIF_INDENT)) |
| { |
| bResult = TRUE; |
| ZeroMemory(lpSubItem, sizeof(LISTVIEW_SUBITEM)); |
| |
| lpSubItem->iSubItem = lpLVItem->iSubItem; |
| |
| if (lpLVItem->mask & LVIF_IMAGE) |
| { |
| lpSubItem->iImage = lpLVItem->iImage; |
| } |
| |
| if (lpLVItem->mask & LVIF_TEXT) |
| { |
| if (lpLVItem->pszText == LPSTR_TEXTCALLBACKA) |
| { |
| if ((lStyle & LVS_SORTASCENDING) || (lStyle & LVS_SORTDESCENDING)) |
| { |
| return FALSE; |
| } |
| |
| if ((lpSubItem->pszText != NULL) && |
| (lpSubItem->pszText != LPSTR_TEXTCALLBACKA)) |
| { |
| COMCTL32_Free(lpSubItem->pszText); |
| } |
| |
| lpSubItem->pszText = LPSTR_TEXTCALLBACKA; |
| } |
| else |
| { |
| if (lpSubItem->pszText == LPSTR_TEXTCALLBACKA) |
| { |
| lpSubItem->pszText = NULL; |
| } |
| |
| bResult = Str_SetPtrA(&lpSubItem->pszText, lpLVItem->pszText); |
| } |
| } |
| } |
| } |
| |
| return bResult; |
| } |
| |
| /*** |
| * DESCRIPTION: |
| * Adds a subitem at a given position (column index). |
| * |
| * PARAMETER(S): |
| * [I] HWND : window handle |
| * [I] LPLVITEM : new subitem atttributes |
| * |
| * RETURN: |
| * SUCCESS : TRUE |
| * FAILURE : FALSE |
| */ |
| static BOOL LISTVIEW_AddSubItem(HWND hwnd, LPLVITEMA lpLVItem) |
| { |
| LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0); |
| BOOL bResult = FALSE; |
| HDPA hdpaSubItems; |
| LISTVIEW_SUBITEM *lpSubItem = NULL; |
| INT nPosition, nItem; |
| |
| if (lpLVItem != NULL) |
| { |
| hdpaSubItems = (HDPA)DPA_GetPtr(infoPtr->hdpaItems, lpLVItem->iItem); |
| if (hdpaSubItems != NULL) |
| { |
| lpSubItem = (LISTVIEW_SUBITEM *)COMCTL32_Alloc(sizeof(LISTVIEW_SUBITEM)); |
| if (lpSubItem != NULL) |
| { |
| if (LISTVIEW_InitSubItem(hwnd, lpSubItem, lpLVItem) == TRUE) |
| { |
| nPosition = LISTVIEW_FindInsertPosition(hdpaSubItems, |
| lpSubItem->iSubItem); |
| nItem = DPA_InsertPtr(hdpaSubItems, nPosition, lpSubItem); |
| if (nItem != -1) |
| { |
| bResult = TRUE; |
| } |
| } |
| } |
| } |
| } |
| |
| /* cleanup if unsuccessful */ |
| if ((bResult == FALSE) && (lpSubItem != NULL)) |
| { |
| COMCTL32_Free(lpSubItem); |
| } |
| |
| return bResult; |
| } |
| |
| /*** |
| * DESCRIPTION: |
| * Finds the dpa insert position (array index). |
| * |
| * PARAMETER(S): |
| * [I] HWND : window handle |
| * [I] INT : subitem index |
| * |
| * RETURN: |
| * SUCCESS : TRUE |
| * FAILURE : FALSE |
| */ |
| static INT LISTVIEW_FindInsertPosition(HDPA hdpaSubItems, INT nSubItem) |
| { |
| LISTVIEW_SUBITEM *lpSubItem; |
| INT i; |
| |
| for (i = 1; i < hdpaSubItems->nItemCount; i++) |
| { |
| lpSubItem = (LISTVIEW_SUBITEM *)DPA_GetPtr(hdpaSubItems, i); |
| if (lpSubItem != NULL) |
| { |
| if (lpSubItem->iSubItem > nSubItem) |
| { |
| return i; |
| } |
| } |
| } |
| |
| return hdpaSubItems->nItemCount; |
| } |
| |
| /*** |
| * DESCRIPTION: |
| * Retrieves a listview subitem at a given position (column index). |
| * |
| * PARAMETER(S): |
| * [I] HWND : window handle |
| * [I] INT : subitem index |
| * |
| * RETURN: |
| * SUCCESS : TRUE |
| * FAILURE : FALSE |
| */ |
| static LISTVIEW_SUBITEM* LISTVIEW_GetSubItem(HDPA hdpaSubItems, INT nSubItem) |
| { |
| LISTVIEW_SUBITEM *lpSubItem; |
| INT i; |
| |
| for (i = 1; i < hdpaSubItems->nItemCount; i++) |
| { |
| lpSubItem = (LISTVIEW_SUBITEM *)DPA_GetPtr(hdpaSubItems, i); |
| if (lpSubItem != NULL) |
| { |
| if (lpSubItem->iSubItem == nSubItem) |
| { |
| return lpSubItem; |
| } |
| else if (lpSubItem->iSubItem > nSubItem) |
| { |
| return NULL; |
| } |
| } |
| } |
| |
| return NULL; |
| } |
| |
| /*** |
| * DESCRIPTION: |
| * Sets item attributes. |
| * |
| * PARAMETER(S): |
| * [I] HWND : window handle |
| * [I] LPLVITEM : new item atttributes |
| * |
| * RETURN: |
| * SUCCESS : TRUE |
| * FAILURE : FALSE |
| */ |
| static BOOL LISTVIEW_SetItem(HWND hwnd, LPLVITEMA lpLVItem) |
| { |
| LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0); |
| BOOL bResult = FALSE; |
| HDPA hdpaSubItems; |
| LISTVIEW_ITEM *lpItem; |
| NMLISTVIEW nmlv; |
| UINT uChanged; |
| LONG lCtrlId = GetWindowLongA(hwnd, GWL_ID); |
| |
| if (lpLVItem != NULL) |
| { |
| if (lpLVItem->iSubItem == 0) |
| { |
| hdpaSubItems = (HDPA)DPA_GetPtr(infoPtr->hdpaItems, lpLVItem->iItem); |
| if (hdpaSubItems != NULL) |
| { |
| lpItem = (LISTVIEW_ITEM *)DPA_GetPtr(hdpaSubItems, lpLVItem->iSubItem); |
| if (lpItem != NULL) |
| { |
| ZeroMemory(&nmlv, sizeof(NMLISTVIEW)); |
| nmlv.hdr.hwndFrom = hwnd; |
| nmlv.hdr.idFrom = lCtrlId; |
| nmlv.hdr.code = LVN_ITEMCHANGING; |
| nmlv.lParam = lpItem->lParam; |
| uChanged = LISTVIEW_GetItemChanges(lpItem, lpLVItem); |
| if (uChanged != 0) |
| { |
| if (uChanged & LVIF_STATE) |
| { |
| nmlv.uNewState = lpLVItem->state & lpLVItem->stateMask; |
| nmlv.uOldState = lpItem->state & lpLVItem->stateMask; |
| } |
| |
| nmlv.uChanged = uChanged; |
| nmlv.iItem = lpLVItem->iItem; |
| nmlv.lParam = lpItem->lParam; |
| /* send LVN_ITEMCHANGING notification */ |
| ListView_LVNotify(GetParent(hwnd), lCtrlId, &nmlv); |
| |
| /* copy information */ |
| bResult = LISTVIEW_InitItem(hwnd, lpItem, lpLVItem); |
| |
| /* send LVN_ITEMCHANGED notification */ |
| nmlv.hdr.code = LVN_ITEMCHANGED; |
| ListView_LVNotify(GetParent(hwnd), lCtrlId, &nmlv); |
| } |
| else |
| { |
| bResult = TRUE; |
| } |
| |
| InvalidateRect(hwnd, NULL, FALSE); |
| } |
| } |
| } |
| } |
| |
| return bResult; |
| } |
| |
| /*** |
| * DESCRIPTION: |
| * Sets subitem attributes. |
| * |
| * PARAMETER(S): |
| * [I] HWND : window handle |
| * [I] LPLVITEM : new subitem atttributes |
| * |
| * RETURN: |
| * SUCCESS : TRUE |
| * FAILURE : FALSE |
| */ |
| static BOOL LISTVIEW_SetSubItem(HWND hwnd, LPLVITEMA lpLVItem) |
| { |
| LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0); |
| BOOL bResult = FALSE; |
| HDPA hdpaSubItems; |
| LISTVIEW_SUBITEM *lpSubItem; |
| |
| if (lpLVItem != NULL) |
| { |
| if (lpLVItem->iSubItem > 0) |
| { |
| hdpaSubItems = (HDPA)DPA_GetPtr(infoPtr->hdpaItems, lpLVItem->iItem); |
| if (hdpaSubItems != NULL) |
| { |
| /* set subitem only if column is present */ |
| if (Header_GetItemCount(infoPtr->hwndHeader) > lpLVItem->iSubItem) |
| { |
| lpSubItem = LISTVIEW_GetSubItem(hdpaSubItems, lpLVItem->iSubItem); |
| if (lpSubItem != NULL) |
| { |
| bResult = LISTVIEW_InitSubItem(hwnd, lpSubItem, lpLVItem); |
| } |
| else |
| { |
| bResult = LISTVIEW_AddSubItem(hwnd, lpLVItem); |
| } |
| |
| InvalidateRect(hwnd, NULL, FALSE); |
| } |
| } |
| } |
| } |
| |
| return bResult; |
| } |
| |
| /*** |
| * DESCRIPTION: |
| * Retrieves the index of the item at coordinate (0, 0) of the client area. |
| * |
| * PARAMETER(S): |
| * [I] HWND : window handle |
| * |
| * RETURN: |
| * item index |
| */ |
| static INT LISTVIEW_GetTopIndex(HWND hwnd) |
| { |
| LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *) GetWindowLongA(hwnd, 0); |
| LONG lStyle = GetWindowLongA(hwnd, GWL_STYLE); |
| INT nItem = 0; |
| |
| switch (LVS_TYPEMASK & lStyle) |
| { |
| case LVS_LIST: |
| if (lStyle & WS_HSCROLL) |
| { |
| nItem = GetScrollPos(hwnd, SB_HORZ) * infoPtr->nCountPerColumn; |
| } |
| break; |
| |
| case LVS_REPORT: |
| if (lStyle & WS_VSCROLL) |
| { |
| nItem = GetScrollPos(hwnd, SB_VERT); |
| } |
| break; |
| } |
| |
| return nItem; |
| } |
| |
| /*** |
| * DESCRIPTION: |
| * Sets scrollbar(s). |
| * |
| * PARAMETER(S): |
| * [I] HWND : window handle |
| * |
| * RETURN: |
| * TRUE if scrollbars were added, modified or removed. |
| */ |
| static VOID LISTVIEW_SetVScroll(HWND hwnd) |
| { |
| LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0); |
| LONG lStyle = GetWindowLongA(hwnd, GWL_STYLE); |
| INT nScrollPos; |
| INT nMaxRange; |
| |
| switch (LVS_TYPEMASK & lStyle) |
| { |
| case LVS_REPORT: |
| nMaxRange = GETITEMCOUNT(infoPtr) - infoPtr->nCountPerColumn; |
| SetScrollRange(hwnd, SB_VERT, 0, nMaxRange, FALSE); |
| nScrollPos = ListView_GetTopIndex(hwnd); |
| SetScrollPos(hwnd, SB_VERT, nScrollPos, TRUE); |
| break; |
| |
| default: |
| /* TO DO */ |
| } |
| } |
| |
| static VOID LISTVIEW_SetHScroll(HWND hwnd) |
| { |
| /* LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0); */ |
| LONG lStyle = GetWindowLongA(hwnd, GWL_STYLE); |
| /* INT nScrollPos; */ |
| /* INT nMaxRange; */ |
| |
| switch (LVS_TYPEMASK & lStyle) |
| { |
| case LVS_REPORT: |
| /* TO DO */ |
| break; |
| |
| default: |
| /* TO DO */ |
| } |
| } |
| |
| static VOID LISTVIEW_SetScroll(HWND hwnd) |
| { |
| LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0); |
| LONG lStyle = GetWindowLongA(hwnd, GWL_STYLE); |
| INT nHiddenItemCount; |
| INT nScrollPos; |
| INT nMaxRange; |
| INT nCountPerPage; |
| RECT rc; |
| BOOL bHScroll = FALSE; |
| BOOL bVScroll = FALSE; |
| INT nHeaderWidth = 0; |
| INT nItemCount; |
| INT i; |
| |
| switch (LVS_TYPEMASK & lStyle) |
| { |
| case LVS_LIST: |
| nCountPerPage = infoPtr->nCountPerRow * infoPtr->nCountPerColumn; |
| if (nCountPerPage < GETITEMCOUNT(infoPtr)) |
| { |
| /* add scrollbar if not already present */ |
| if (!(lStyle & WS_HSCROLL)) |
| { |
| ShowScrollBar(hwnd, SB_HORZ, TRUE); |
| } |
| |
| /* calculate new scrollbar range */ |
| nHiddenItemCount = GETITEMCOUNT(infoPtr) - nCountPerPage; |
| if ((nHiddenItemCount % infoPtr->nCountPerColumn) == 0) |
| { |
| nMaxRange = nHiddenItemCount / infoPtr->nCountPerColumn; |
| } |
| else |
| { |
| nMaxRange = nHiddenItemCount / infoPtr->nCountPerColumn + 1; |
| } |
| |
| SetScrollRange(hwnd, SB_HORZ, 0, nMaxRange, FALSE); |
| nScrollPos = ListView_GetTopIndex(hwnd) / infoPtr->nCountPerColumn; |
| SetScrollPos(hwnd, SB_HORZ, nScrollPos, TRUE); |
| } |
| else |
| { |
| /* remove scrollbar if present */ |
| if (lStyle & WS_HSCROLL) |
| { |
| /* hide scrollbar */ |
| ShowScrollBar(hwnd, SB_HORZ, FALSE); |
| } |
| } |
| break; |
| |
| case LVS_REPORT: |
| nItemCount = Header_GetItemCount(infoPtr->hwndHeader); |
| for (i = 0; i < nItemCount; i++) |
| { |
| if (Header_GetItemRect(infoPtr->hwndHeader, i, &rc) != 0) |
| { |
| nHeaderWidth += (rc.right - rc.left); |
| } |
| } |
| |
| if (nHeaderWidth > (infoPtr->rcList.right - infoPtr->rcList.left)) |
| { |
| bHScroll = TRUE; |
| |
| /* add horizontal scrollbar if not present */ |
| if (!(lStyle & WS_HSCROLL)) |
| { |
| /* display scrollbar */ |
| ShowScrollBar(hwnd, SB_HORZ, TRUE); |
| } |
| } |
| else |
| { |
| /* remove scrollbar if present */ |
| if (lStyle & WS_HSCROLL) |
| { |
| /* hide scrollbar */ |
| ShowScrollBar(hwnd, SB_HORZ, FALSE); |
| } |
| } |
| |
| if (infoPtr->nCountPerColumn < GETITEMCOUNT(infoPtr)) |
| { |
| bVScroll = TRUE; |
| |
| /* add scrollbar if not already present */ |
| if (!(lStyle & WS_VSCROLL)) |
| { |
| /* display scrollbar */ |
| ShowScrollBar(hwnd, SB_VERT, TRUE); |
| } |
| } |
| else |
| { |
| /* remove scrollbar if present */ |
| if (lStyle & WS_VSCROLL) |
| { |
| /* hide scrollbar */ |
| ShowScrollBar(hwnd, SB_VERT, FALSE); |
| } |
| } |
| break; |
| |
| default: |
| /* TO DO */ |
| } |
| |
| /* set range and position */ |
| GetClientRect(hwnd, &rc); |
| if ((bHScroll == TRUE) || (bVScroll == TRUE)) |
| { |
| LISTVIEW_SetSize(hwnd, lStyle, rc.right, rc.bottom); |
| LISTVIEW_SetViewInfo(hwnd); |
| if (bHScroll == TRUE) |
| { |
| LISTVIEW_SetHScroll(hwnd); |
| } |
| |
| if (bVScroll == TRUE) |
| { |
| LISTVIEW_SetVScroll(hwnd); |
| } |
| } |
| } |
| |
| /*** |
| * DESCRIPTION: |
| * Draws a subitem. |
| * |
| * PARAMETER(S): |
| * [I] HDC : device context handle |
| * [I] LISTVIEW_INFO * : listview information |
| * [I] LISTVIEW_SUBITEM * : subitem |
| * [I] RECT * : clipping rectangle |
| * |
| * RETURN: |
| * None |
| */ |
| static VOID LISTVIEW_DrawSubItem(HWND hwnd, HDC hdc, INT nItem, LPARAM lParam, |
| LISTVIEW_SUBITEM *lpSubItem, INT nColumn, |
| RECT *lprc) |
| { |
| LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0); |
| CHAR szDispText[DISP_TEXT_SIZE]; |
| LPSTR pszDispText = NULL; |
| |
| /* set item colors */ |
| SetBkColor(hdc, infoPtr->clrTextBk); |
| SetTextColor(hdc, infoPtr->clrText); |
| |
| pszDispText = szDispText; |
| LISTVIEW_GetSubItemDispInfo(hwnd, nItem, lParam, lpSubItem, nColumn, NULL, |
| &pszDispText, DISP_TEXT_SIZE); |
| |
| /* draw text : using arbitrary offset of 10 pixels */ |
| ExtTextOutA(hdc, lprc->left + 10, lprc->top, ETO_OPAQUE|ETO_CLIPPED, |
| lprc, pszDispText, lstrlenA(pszDispText), NULL); |
| } |
| |
| /*** |
| * DESCRIPTION: |
| * Draws an item. |
| * |
| * PARAMETER(S): |
| * [I] HDC : device context handle |
| * [I] LISTVIEW_INFO * : listview information |
| * [I] LISTVIEW_ITEM * : item |
| * [I] RECT * : clipping rectangle |
| * |
| * RETURN: |
| * None |
| */ |
| static VOID LISTVIEW_DrawItem(HWND hwnd, HDC hdc, LISTVIEW_ITEM *lpItem, |
| INT nItem, RECT *lprc) |
| { |
| LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0); |
| BOOL bSelected; |
| INT nLabelWidth; |
| INT nImage; |
| CHAR szDispText[DISP_TEXT_SIZE]; |
| LPSTR pszDispText = NULL; |
| UINT uState; |
| |
| pszDispText = szDispText; |
| LISTVIEW_GetItemDispInfo(hwnd, nItem, lpItem, &nImage, &uState, &pszDispText, |
| DISP_TEXT_SIZE); |
| if (uState & LVIS_SELECTED) |
| { |
| bSelected = TRUE; |
| |
| /* set item colors */ |
| SetBkColor(hdc, GetSysColor(COLOR_HIGHLIGHT)); |
| SetTextColor(hdc, GetSysColor(COLOR_HIGHLIGHTTEXT)); |
| |
| /* set raster mode */ |
| SetROP2(hdc, R2_XORPEN); |
| } |
| else |
| { |
| bSelected = FALSE; |
| |
| /* set item colors */ |
| SetBkColor(hdc, infoPtr->clrTextBk); |
| SetTextColor(hdc, infoPtr->clrText); |
| |
| /* set raster mode */ |
| SetROP2(hdc, R2_COPYPEN); |
| } |
| |
| /* state icons */ |
| if (infoPtr->himlState != NULL) |
| { |
| /* right shift 12 bits to obtain index in image list */ |
| if (bSelected == TRUE) |
| { |
| ImageList_Draw(infoPtr->himlState, uState >> 12, hdc, lprc->left, |
| lprc->top, ILD_SELECTED); |
| } |
| else |
| { |
| ImageList_Draw(infoPtr->himlState, uState >> 12, hdc, lprc->left, |
| lprc->top, ILD_NORMAL); |
| } |
| |
| lprc->left += infoPtr->iconSize.cx; |
| } |
| |
| /* small icons */ |
| if (infoPtr->himlSmall != NULL) |
| { |
| if (bSelected == TRUE) |
| { |
| ImageList_Draw(infoPtr->himlSmall, nImage, hdc, lprc->left, |
| lprc->top, ILD_SELECTED); |
| } |
| else |
| { |
| ImageList_Draw(infoPtr->himlSmall, nImage, hdc, lprc->left, |
| lprc->top, ILD_NORMAL); |
| } |
| |
| lprc->left += infoPtr->iconSize.cx; |
| } |
| |
| nLabelWidth = ListView_GetStringWidthA(hwnd, pszDispText); |
| if (lprc->left + nLabelWidth < lprc->right) |
| { |
| lprc->right = lprc->left + nLabelWidth; |
| } |
| |
| /* draw text */ |
| ExtTextOutA(hdc, lprc->left + 1, lprc->top + 1, ETO_OPAQUE|ETO_CLIPPED, |
| lprc, pszDispText, lstrlenA(pszDispText), NULL); |
| |
| if (lpItem->state & LVIS_FOCUSED) |
| { |
| Rectangle(hdc, lprc->left, lprc->top, lprc->right, lprc->bottom); |
| } |
| } |
| |
| /*** |
| * DESCRIPTION: |
| * Draws listview items when in report display mode. |
| * |
| * PARAMETER(S): |
| * [I] HWND : window handle |
| * [I] HDC : device context handle |
| * |
| * RETURN: |
| * None |
| */ |
| static VOID LISTVIEW_RefreshReport(HWND hwnd, HDC hdc) |
| { |
| LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd,0); |
| INT nDrawPosY = infoPtr->rcList.top; |
| LISTVIEW_ITEM *lpItem; |
| LISTVIEW_SUBITEM *lpSubItem = NULL; |
| INT nColumnCount; |
| HDPA hdpaSubItems; |
| RECT rc; |
| INT j, k; |
| INT nItem; |
| INT nLast; |
| BOOL bNeedSubItem = TRUE; |
| |
| nItem = ListView_GetTopIndex(hwnd); |
| nLast = nItem + infoPtr->nCountPerColumn; |
| while (nItem <= nLast) |
| { |
| hdpaSubItems = (HDPA)DPA_GetPtr(infoPtr->hdpaItems, nItem); |
| if (hdpaSubItems != NULL) |
| { |
| lpItem = (LISTVIEW_ITEM *)DPA_GetPtr(hdpaSubItems, 0); |
| if (lpItem != NULL) |
| { |
| Header_GetItemRect(infoPtr->hwndHeader, 0, &rc); |
| rc.top = nDrawPosY; |
| rc.bottom = rc.top + infoPtr->nItemHeight; |
| |
| /* draw state icon + icon + text */ |
| LISTVIEW_DrawItem(hwnd, hdc, lpItem, nItem, &rc); |
| } |
| |
| nColumnCount = Header_GetItemCount(infoPtr->hwndHeader); |
| for (k = 1, j = 1; j < nColumnCount; j++) |
| { |
| Header_GetItemRect(infoPtr->hwndHeader, j, &rc); |
| rc.top = nDrawPosY; |
| rc.bottom = rc.top + infoPtr->nItemHeight; |
| |
| if (k < hdpaSubItems->nItemCount) |
| { |
| if (bNeedSubItem == TRUE) |
| { |
| lpSubItem = (LISTVIEW_SUBITEM *)DPA_GetPtr(hdpaSubItems, k); |
| k++; |
| } |
| |
| if (lpSubItem != NULL) |
| { |
| if (lpSubItem->iSubItem == j) |
| { |
| LISTVIEW_DrawSubItem(hwnd, hdc, nItem, lpItem->lParam, lpSubItem, |
| j, &rc); |
| bNeedSubItem = TRUE; |
| } |
| else |
| { |
| LISTVIEW_DrawSubItem(hwnd, hdc, nItem, lpItem->lParam, NULL, j, |
| &rc); |
| bNeedSubItem = FALSE; |
| } |
| } |
| else |
| { |
| LISTVIEW_DrawSubItem(hwnd, hdc, nItem, lpItem->lParam, NULL, j, |
| &rc); |
| bNeedSubItem = TRUE; |
| } |
| } |
| else |
| { |
| LISTVIEW_DrawSubItem(hwnd, hdc, nItem, lpItem->lParam, NULL, j, &rc); |
| } |
| } |
| } |
| |
| nDrawPosY += infoPtr->nItemHeight; |
| nItem++; |
| } |
| } |
| |
| /*** |
| * DESCRIPTION: |
| * Draws listview items when in list display mode. |
| * |
| * PARAMETER(S): |
| * [I] HWND : window handle |
| * [I] HDC : device context handle |
| * |
| * RETURN: |
| * None |
| */ |
| static VOID LISTVIEW_RefreshList(HWND hwnd, HDC hdc) |
| { |
| LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0); |
| LISTVIEW_ITEM *lpItem; |
| HDPA hdpaSubItems; |
| RECT rc; |
| INT i, j; |
| INT nColumnCount; |
| INT nItem = ListView_GetTopIndex(hwnd); |
| |
| if (infoPtr->rcList.right > 0) |
| { |
| /* get number of display columns */ |
| if (infoPtr->rcList.right % infoPtr->nColumnWidth == 0) |
| { |
| nColumnCount = infoPtr->rcList.right / infoPtr->nColumnWidth; |
| } |
| else |
| { |
| nColumnCount = infoPtr->rcList.right / infoPtr->nColumnWidth + 1; |
| } |
| |
| for (i = 0; i < nColumnCount; i++) |
| { |
| j = 0; |
| while ((nItem < GETITEMCOUNT(infoPtr)) && (j < infoPtr->nCountPerColumn)) |
| { |
| hdpaSubItems = (HDPA)DPA_GetPtr(infoPtr->hdpaItems, nItem); |
| if (hdpaSubItems != NULL) |
| { |
| lpItem = (LISTVIEW_ITEM *)DPA_GetPtr(hdpaSubItems, 0); |
| if (lpItem != NULL) |
| { |
| rc.top = j * infoPtr->nItemHeight; |
| rc.left = i * infoPtr->nColumnWidth; |
| rc.bottom = rc.top + infoPtr->nItemHeight; |
| rc.right = rc.left + infoPtr->nColumnWidth; |
| |
| /* draw state icon + icon + text */ |
| LISTVIEW_DrawItem(hwnd, hdc, lpItem, nItem, &rc); |
| } |
| } |
| |
| nItem++; |
| j++; |
| } |
| } |
| } |
| } |
| |
| /*** |
| * DESCRIPTION: |
| * Draws listview items when in small icon display mode. |
| * |
| * PARAMETER(S): |
| * [I] HWND : window handle |
| * [I] HDC : device context handle |
| * |
| * RETURN: |
| * None |
| */ |
| static VOID LISTVIEW_RefreshSmallIcon(HWND hwnd, HDC hdc) |
| { |
| LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0); |
| LISTVIEW_ITEM *lpItem; |
| HDPA hdpaSubItems; |
| RECT rc; |
| INT i, j; |
| INT nItem = ListView_GetTopIndex(hwnd); |
| |
| for (i = 0; i < infoPtr->nCountPerColumn; i++) |
| { |
| j = 0; |
| while ((nItem < GETITEMCOUNT(infoPtr)) && (j < infoPtr->nCountPerRow)) |
| { |
| hdpaSubItems = (HDPA)DPA_GetPtr(infoPtr->hdpaItems, nItem); |
| if (hdpaSubItems != NULL) |
| { |
| lpItem = (LISTVIEW_ITEM *)DPA_GetPtr(hdpaSubItems, 0); |
| if (lpItem != NULL) |
| { |
| rc.top = i * infoPtr->nItemHeight; |
| rc.left = j * infoPtr->nColumnWidth; |
| rc.bottom = rc.top + infoPtr->nItemHeight; |
| rc.right = rc.left + infoPtr->nColumnWidth; |
| |
| /* draw state icon + icon + text */ |
| LISTVIEW_DrawItem(hwnd, hdc, lpItem, nItem, &rc); |
| } |
| } |
| |
| nItem++; |
| j++; |
| } |
| } |
| } |
| |
| /*** |
| * DESCRIPTION: |
| * Draws listview items when in icon display mode. |
| * |
| * PARAMETER(S): |
| * [I] HWND : window handle |
| * [I] HDC : device context handle |
| * |
| * RETURN: |
| * None |
| */ |
| static VOID LISTVIEW_RefreshIcon(HWND hwnd, HDC hdc) |
| { |
| /* TO DO */ |
| } |
| |
| /*** |
| * DESCRIPTION: |
| * Draws listview items. |
| * |
| * PARAMETER(S): |
| * [I] HWND : window handle |
| * [I] HDC : device context handle |
| * |
| * RETURN: |
| * NoneX |
| */ |
| static VOID LISTVIEW_Refresh(HWND hwnd, HDC hdc) |
| { |
| LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0); |
| LONG lStyle = GetWindowLongA(hwnd, GWL_STYLE); |
| HFONT hOldFont; |
| HPEN hPen, hOldPen; |
| |
| /* select font */ |
| hOldFont = SelectObject(hdc, infoPtr->hFont); |
| |
| /* select the doted pen (for drawing the focus box) */ |
| hPen = CreatePen(PS_DOT, 1, 0); |
| hOldPen = SelectObject(hdc, hPen); |
| |
| /* select transparent brush (for drawing the focus box) */ |
| SelectObject(hdc, GetStockObject(NULL_BRUSH)); |
| |
| switch (LVS_TYPEMASK & lStyle) |
| { |
| case LVS_LIST: |
| LISTVIEW_RefreshList(hwnd, hdc); |
| break; |
| case LVS_REPORT: |
| LISTVIEW_RefreshReport(hwnd, hdc); |
| break; |
| case LVS_SMALLICON: |
| LISTVIEW_RefreshSmallIcon(hwnd, hdc); |
| break; |
| case LVS_ICON: |
| LISTVIEW_RefreshIcon(hwnd, hdc); |
| } |
| |
| /* unselect objects */ |
| SelectObject(hdc, hOldFont); |
| SelectObject(hdc, hOldPen); |
| |
| /* delete pen */ |
| DeleteObject(hPen); |
| } |
| |
| |
| /*** |
| * DESCRIPTION: |
| * Calculates the approximate width and height of a given number of items. |
| * |
| * PARAMETER(S): |
| * [I] HWND : window handle |
| * [I] INT : number of items |
| * [I] INT : width |
| * [I] INT : height |
| * |
| * RETURN: |
| * Returns a DWORD. The width in the low word and the height in high word. |
| */ |
| static LRESULT LISTVIEW_ApproximateViewRect(HWND hwnd, INT nItemCount, |
| WORD wWidth, WORD wHeight) |
| { |
| LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0); |
| LONG lStyle = GetWindowLongA(hwnd, GWL_STYLE); |
| INT nItemCountPerColumn = 1; |
| INT nColumnCount = 0; |
| DWORD dwViewRect = 0; |
| |
| if (nItemCount == -1) |
| nItemCount = GETITEMCOUNT(infoPtr); |
| |
| if (lStyle & LVS_LIST) |
| { |
| if (wHeight == 0xFFFF) |
| { |
| /* use current height */ |
| wHeight = infoPtr->rcList.bottom; |
| } |
| |
| if (wHeight < infoPtr->nItemHeight) |
| { |
| wHeight = infoPtr->nItemHeight; |
| } |
| |
| if (nItemCount > 0) |
| { |
| if (infoPtr->nItemHeight > 0) |
| { |
| nItemCountPerColumn = wHeight / infoPtr->nItemHeight; |
| if (nItemCountPerColumn == 0) |
| nItemCountPerColumn = 1; |
| |
| if (nItemCount % nItemCountPerColumn != 0) |
| nColumnCount = nItemCount / nItemCountPerColumn; |
| else |
| nColumnCount = nItemCount / nItemCountPerColumn + 1; |
| } |
| } |
| |
| /* Microsoft padding magic */ |
| wHeight = nItemCountPerColumn * infoPtr->nItemHeight + 2; |
| wWidth = nColumnCount * infoPtr->nColumnWidth + 2; |
| |
| dwViewRect = MAKELONG(wWidth, wHeight); |
| } |
| else if (lStyle & LVS_REPORT) |
| { |
| /* TO DO */ |
| } |
| else if (lStyle & LVS_SMALLICON) |
| { |
| /* TO DO */ |
| } |
| else if (lStyle & LVS_ICON) |
| { |
| /* TO DO */ |
| } |
| |
| return dwViewRect; |
| } |
| |
| /*** |
| * DESCRIPTION: |
| * Arranges listview items in icon display mode. |
| * |
| * PARAMETER(S): |
| * [I] HWND : window handle |
| * [I] INT : alignment code |
| * |
| * RETURN: |
| * SUCCESS : TRUE |
| * FAILURE : FALSE |
| */ |
| static LRESULT LISTVIEW_Arrange(HWND hwnd, INT nAlignCode) |
| { |
| LONG lStyle = GetWindowLongA(hwnd, GWL_STYLE); |
| BOOL bResult = FALSE; |
| |
| if (((LVS_TYPEMASK & lStyle) == LVS_ICON) || |
| ((LVS_TYPEMASK & lStyle) == LVS_SMALLICON)) |
| { |
| switch (nAlignCode) |
| { |
| case LVA_ALIGNLEFT: |
| /* TO DO */ |
| break; |
| case LVA_ALIGNTOP: |
| /* TO DO */ |
| break; |
| case LVA_DEFAULT: |
| /* TO DO */ |
| break; |
| case LVA_SNAPTOGRID: |
| /* TO DO */ |
| } |
| } |
| |
| return bResult; |
| } |
| |
| /* << LISTVIEW_CreateDragImage >> */ |
| |
| /*** |
| * DESCRIPTION: |
| * Removes all listview items and subitems. |
| * |
| * PARAMETER(S): |
| * [I] HWND : window handle |
| * |
| * RETURN: |
| * SUCCESS : TRUE |
| * FAILURE : FALSE |
| */ |
| static LRESULT LISTVIEW_DeleteAllItems(HWND hwnd) |
| { |
| LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0); |
| LONG lCtrlId = GetWindowLongA(hwnd, GWL_ID); |
| LISTVIEW_ITEM *lpItem; |
| LISTVIEW_SUBITEM *lpSubItem; |
| NMLISTVIEW nmlv; |
| BOOL bSuppress; |
| BOOL bResult = FALSE; |
| INT i; |
| INT j; |
| HDPA hdpaSubItems; |
| |
| if (GETITEMCOUNT(infoPtr) > 0) |
| { |
| /* initialize memory */ |
| ZeroMemory(&nmlv, sizeof(NMLISTVIEW)); |
| |
| /* send LVN_DELETEALLITEMS notification */ |
| nmlv.hdr.hwndFrom = hwnd; |
| nmlv.hdr.idFrom = lCtrlId; |
| nmlv.hdr.code = LVN_DELETEALLITEMS; |
| nmlv.iItem = -1; |
| |
| /* verify if subsequent LVN_DELETEITEM notifications should be |
| suppressed */ |
| bSuppress = ListView_LVNotify(GetParent(hwnd), lCtrlId, &nmlv); |
| |
| for (i = 0; i < GETITEMCOUNT(infoPtr); i++) |
| { |
| hdpaSubItems = (HDPA)DPA_GetPtr(infoPtr->hdpaItems, i); |
| if (hdpaSubItems != NULL) |
| { |
| for (j = 1; j < hdpaSubItems->nItemCount; j++) |
| { |
| lpSubItem = (LISTVIEW_SUBITEM *)DPA_GetPtr(hdpaSubItems, j); |
| if (lpSubItem != NULL) |
| { |
| /* free subitem string */ |
| if ((lpSubItem->pszText != NULL) && |
| (lpSubItem->pszText != LPSTR_TEXTCALLBACKA)) |
| { |
| COMCTL32_Free(lpSubItem->pszText); |
| } |
| |
| /* free subitem */ |
| COMCTL32_Free(lpSubItem); |
| } |
| } |
| |
| lpItem = (LISTVIEW_ITEM *)DPA_GetPtr(hdpaSubItems, 0); |
| if (lpItem != NULL) |
| { |
| if (bSuppress == FALSE) |
| { |
| /* send LVN_DELETEITEM notification */ |
| nmlv.hdr.code = LVN_DELETEITEM; |
| nmlv.iItem = i; |
| nmlv.lParam = lpItem->lParam; |
| ListView_LVNotify(GetParent(hwnd), lCtrlId, &nmlv); |
| } |
| |
| /* free item string */ |
| if ((lpItem->pszText != NULL) && |
| (lpItem->pszText != LPSTR_TEXTCALLBACKA)) |
| { |
| COMCTL32_Free(lpItem->pszText); |
| } |
| |
| /* free item */ |
| COMCTL32_Free(lpItem); |
| } |
| |
| DPA_Destroy(hdpaSubItems); |
| } |
| } |
| |
| /* reinitialize listview memory */ |
| bResult = DPA_DeleteAllPtrs(infoPtr->hdpaItems); |
| |
| /* reset scroll parameters */ |
| LISTVIEW_SetScroll(hwnd); |
| |
| /* invalidate client area (optimization needed) */ |
| InvalidateRect(hwnd, NULL, FALSE); |
| } |
| |
| return bResult; |
| } |
| |
| /*** |
| * DESCRIPTION: |
| * Removes a column from the listview control. |
| * |
| * PARAMETER(S): |
| * [I] HWND : window handle |
| * [I] INT : column index |
| * |
| * RETURN: |
| * SUCCESS : TRUE |
| * FAILURE : FALSE |
| */ |
| static LRESULT LISTVIEW_DeleteColumn(HWND hwnd, INT nColumn) |
| { |
| LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0); |
| BOOL bResult = FALSE; |
| |
| if (Header_DeleteItem(infoPtr->hwndHeader, nColumn) == TRUE) |
| { |
| bResult = LISTVIEW_RemoveColumn(infoPtr->hdpaItems, nColumn); |
| } |
| |
| /* reset scroll parameters */ |
| LISTVIEW_SetScroll(hwnd); |
| |
| /* refresh client area */ |
| InvalidateRect(hwnd, NULL, FALSE); |
| |
| return bResult; |
| } |
| |
| /*** |
| * DESCRIPTION: |
| * Removes an item from the listview control. |
| * |
| * PARAMETER(S): |
| * [I] HWND : window handle |
| * [I] INT : item index |
| * |
| * RETURN: |
| * SUCCESS : TRUE |
| * FAILURE : FALSE |
| */ |
| static LRESULT LISTVIEW_DeleteItem(HWND hwnd, INT nItem) |
| { |
| LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0); |
| LONG lCtrlId = GetWindowLongA(hwnd, GWL_ID); |
| NMLISTVIEW nmlv; |
| BOOL bResult = FALSE; |
| HDPA hdpaSubItems; |
| LISTVIEW_ITEM *lpItem; |
| LISTVIEW_SUBITEM *lpSubItem; |
| INT i; |
| |
| if ((nItem >= 0) && (nItem < GETITEMCOUNT(infoPtr))) |
| { |
| /* initialize memory */ |
| ZeroMemory(&nmlv, sizeof(NMLISTVIEW)); |
| |
| hdpaSubItems = (HDPA)DPA_DeletePtr(infoPtr->hdpaItems, nItem); |
| if (hdpaSubItems != NULL) |
| { |
| for (i = 1; i < hdpaSubItems->nItemCount; i++) |
| { |
| lpSubItem = (LISTVIEW_SUBITEM *)DPA_GetPtr(hdpaSubItems, i); |
| if (lpSubItem != NULL) |
| { |
| /* free item string */ |
| if ((lpSubItem->pszText != NULL) && |
| (lpSubItem->pszText != LPSTR_TEXTCALLBACKA)) |
| { |
| COMCTL32_Free(lpSubItem->pszText); |
| } |
| |
| /* free item */ |
| COMCTL32_Free(lpSubItem); |
| } |
| } |
| |
| lpItem = (LISTVIEW_ITEM *)DPA_GetPtr(hdpaSubItems, 0); |
| if (lpItem != NULL) |
| { |
| /* send LVN_DELETEITEM notification */ |
| nmlv.hdr.hwndFrom = hwnd; |
| nmlv.hdr.idFrom = lCtrlId; |
| nmlv.hdr.code = LVN_DELETEITEM; |
| nmlv.iItem = nItem; |
| nmlv.lParam = lpItem->lParam; |
| SendMessageA(GetParent(hwnd), WM_NOTIFY, (WPARAM)lCtrlId, |
| (LPARAM)&nmlv); |
| |
| /* free item string */ |
| if ((lpItem->pszText != NULL) && |
| (lpItem->pszText != LPSTR_TEXTCALLBACKA)) |
| { |
| COMCTL32_Free(lpItem->pszText); |
| } |
| |
| /* free item */ |
| COMCTL32_Free(lpItem); |
| } |
| |
| bResult = DPA_Destroy(hdpaSubItems); |
| } |
| |
| /* refresh client area */ |
| InvalidateRect(hwnd, NULL, FALSE); |
| } |
| |
| return bResult; |
| } |
| |
| /* << LISTVIEW_EditLabel >> */ |
| |
| /*** |
| * DESCRIPTION: |
| * Ensures the specified item is visible, scrolling into view if necessary. |
| * |
| * PARAMETER(S): |
| * [I] HWND : window handle |
| * [I] INT : item index |
| * [I] BOOL : partially or entirely visible |
| * |
| * RETURN: |
| * SUCCESS : TRUE |
| * FAILURE : FALSE |
| */ |
| static BOOL LISTVIEW_EnsureVisible(HWND hwnd, INT nItem, BOOL bPartial) |
| { |
| LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0); |
| LONG lStyle = GetWindowLongA(hwnd, GWL_STYLE); |
| INT nLast; |
| INT nFirst; |
| INT nScrollPos; |
| BOOL bResult = TRUE; |
| |
| switch (LVS_TYPEMASK & lStyle) |
| { |
| case LVS_LIST: |
| if (lStyle & WS_HSCROLL) |
| { |
| nFirst = ListView_GetTopIndex(hwnd); |
| |
| /* calculate last fully visible item index */ |
| nLast = infoPtr->nCountPerColumn * infoPtr->nCountPerRow + nFirst - 1; |
| |
| if (nItem > nLast) |
| { |
| /* calculate new scroll position based on item index */ |
| if (((nItem - nLast) % infoPtr->nCountPerColumn) == 0) |
| { |
| nScrollPos = (nItem - nLast) / infoPtr->nCountPerColumn; |
| } |
| else |
| { |
| nScrollPos = (nItem - nLast) / infoPtr->nCountPerColumn + 1; |
| } |
| |
| bResult = ListView_Scroll(hwnd, nScrollPos, 0); |
| } |
| else if (nItem < nFirst) |
| { |
| /* calculate new scroll position based on item index */ |
| if (((nItem - nFirst) % infoPtr->nCountPerColumn) == 0) |
| { |
| nScrollPos = (nItem - nFirst) / infoPtr->nCountPerColumn; |
| } |
| else |
| { |
| nScrollPos = (nItem - nFirst) / infoPtr->nCountPerColumn -1; |
| } |
| |
| bResult = ListView_Scroll(hwnd, nScrollPos, 0); |
| } |
| } |
| break; |
| |
| case LVS_REPORT: |
| if (lStyle & WS_VSCROLL) |
| { |
| nFirst = ListView_GetTopIndex(hwnd); |
| |
| /* calculate last fully visible item index */ |
| nLast = infoPtr->nCountPerColumn + nFirst - 1; |
| if (nItem > nLast) |
| { |
| nScrollPos = nItem - nLast; |
| bResult = ListView_Scroll(hwnd, 0, nScrollPos); |
| } |
| else if (nItem < nFirst) |
| { |
| nScrollPos = nItem - nFirst; |
| bResult = ListView_Scroll(hwnd, 0, nScrollPos); |
| } |
| } |
| break; |
| |
| case LVS_SMALLICON: |
| /* TO DO */ |
| break; |
| |
| case LVS_ICON: |
| /* TO DO */ |
| break; |
| } |
| |
| return bResult; |
| } |
| /*** |
| * DESCRIPTION: |
| * Searches for an item with specific characteristics. |
| * |
| * PARAMETER(S): |
| * [I] HWND : window handle |
| * [I] INT : base item index |
| * [I] LPLVFINDINFO : item information to look for |
| * |
| * RETURN: |
| * SUCCESS : index of item |
| * FAILURE : -1 |
| */ |
| static LRESULT LISTVIEW_FindItem(HWND hwnd, INT nStart, |
| LPLVFINDINFO lpFindInfo) |
| { |
| /* LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0); */ |
| /* LISTVIEW_ITEM *lpItem; */ |
| /* INT nItem; */ |
| /* INT nEnd = GETITEMCOUNT(infoPtr); */ |
| /* BOOL bWrap = FALSE; */ |
| /* if (nStart == -1) */ |
| /* nStart = 0; */ |
| /* else */ |
| /* nStart++ ; */ |
| /* if (lpFindInfo->flags & LVFI_PARAM) */ |
| /* { */ |
| /* for (nItem = nStart; nItem < nEnd; nItem++) */ |
| /* { */ |
| /* get item pointer */ |
| /* lpItem = (LISTVIEW_ITEM *)DPA_GetPtr(infoPtr->hdpaItems, nItem); */ |
| /* if (lpItem != NULL) */ |
| /* { */ |
| /* if (lpFindInfo->lParam == lpItem->lParam) */ |
| /* return nItem; */ |
| /* } */ |
| /* } */ |
| /* } */ |
| /* else */ |
| /* { */ |
| /* if (lpFindInfo->flags & LVFI_PARTIAL) */ |
| /* { */ |
| /* for (nItem = nStart; nItem < nEnd; nItem++) */ |
| /* { */ |
| /* get item pointer */ |
| /* lpItem = (LISTVIEW_ITEM *)DPA_GetPtr(infoPtr->hdpaItems, nItem); */ |
| /* if (lpItem) */ |
| /* { */ |
| /* if (strncmp(lpItem->pszText, lpFindInfo->psz, strlen(lpFindInfo->psz)) */ |
| /* == 0) */ |
| /* return nItem; */ |
| /* } */ |
| /* } */ |
| /* } */ |
| |
| /* if (lpFindInfo->flags & LVFI_STRING) */ |
| /* { */ |
| /* for (nItem = nStart; nItem < nEnd; nItem++) */ |
| /* { */ |
| /* get item pointer */ |
| /* lpItem = (LISTVIEW_ITEM *)DPA_GetPtr(infoPtr->hdpaItems, nItem); */ |
| /* if (lpItem != NULL) */ |
| /* { */ |
| /* if (strcmp(lpItem->pszText, lpFindInfo->psz) == 0) */ |
| /* return nItem; */ |
| /* } */ |
| /* } */ |
| /* } */ |
| |
| /* if ((lpFindInfo->flags & LVFI_WRAP) && nStart) */ |
| /* { */ |
| /* nEnd = nStart; */ |
| /* nStart = 0; */ |
| /* bWrap = TRUE; */ |
| /* } */ |
| /* else */ |
| /* bWrap = FALSE; */ |
| |
| return -1; |
| } |
| |
| /*** |
| * DESCRIPTION: |
| * Retrieves the background color of the listview control. |
| * |
| * PARAMETER(S): |
| * [I] HWND : window handle |
| * |
| * RETURN: |
| * COLORREF associated with the background. |
| */ |
| static LRESULT LISTVIEW_GetBkColor(HWND hwnd) |
| { |
| LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0); |
| |
| return infoPtr->clrBk; |
| } |
| |
| /*** |
| * DESCRIPTION: |
| * Retrieves the background image of the listview control. |
| * |
| * PARAMETER(S): |
| * [I] HWND : window handle |
| * [O] LPLVMKBIMAGE : background image attributes |
| * |
| * RETURN: |
| * SUCCESS : TRUE |
| * FAILURE : FALSE` |
| */ |
| /* static LRESULT LISTVIEW_GetBkImage(HWND hwnd, LPLVBKIMAGE lpBkImage) */ |
| /* { */ |
| /* return FALSE; */ |
| /* } */ |
| |
| /*** |
| * DESCRIPTION: |
| * Retrieves the callback mask. |
| * |
| * PARAMETER(S): |
| * [I] HWND : window handle |
| * |
| * RETURN: |
| * Value of mask |
| */ |
| static UINT LISTVIEW_GetCallbackMask(HWND hwnd) |
| { |
| LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0); |
| |
| return infoPtr->uCallbackMask; |
| } |
| |
| /*** |
| * DESCRIPTION: |
| * Retrieves column attributes. |
| * |
| * PARAMETER(S): |
| * [I] HWND : window handle |
| * [I] INT : column index |
| * [IO] LPLVCOLUMNA : column information |
| * |
| * RETURN: |
| * SUCCESS : TRUE |
| * FAILURE : FALSE |
| */ |
| static LRESULT LISTVIEW_GetColumnA(HWND hwnd, INT nItem, |
| LPLVCOLUMNA lpColumn) |
| { |
| LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0); |
| HDITEMA hdi; |
| BOOL bResult = FALSE; |
| |
| if (lpColumn != NULL) |
| { |
| /* initialize memory */ |
| ZeroMemory(&hdi, sizeof(HDITEMA)); |
| |
| if (lpColumn->mask & LVCF_FMT) |
| { |
| hdi.mask |= HDI_FORMAT; |
| } |
| |
| if (lpColumn->mask & LVCF_WIDTH) |
| { |
| hdi.mask |= HDI_WIDTH; |
| } |
| |
| if (lpColumn->mask & LVCF_TEXT) |
| { |
| hdi.mask |= (HDI_TEXT | HDI_FORMAT); |
| } |
| |
| if (lpColumn->mask & LVCF_IMAGE) |
| { |
| hdi.mask |= HDI_IMAGE; |
| } |
| |
| if (lpColumn->mask & LVCF_ORDER) |
| { |
| hdi.mask |= HDI_ORDER; |
| } |
| |
| bResult = Header_GetItemA(infoPtr->hwndHeader, nItem, &hdi); |
| if (bResult == TRUE) |
| { |
| if (lpColumn->mask & LVCF_FMT) |
| { |
| lpColumn->fmt = 0; |
| |
| if (hdi.fmt & HDF_LEFT) |
| { |
| lpColumn->fmt |= LVCFMT_LEFT; |
| } |
| else if (hdi.fmt & HDF_RIGHT) |
| { |
| lpColumn->fmt |= LVCFMT_RIGHT; |
| } |
| else if (hdi.fmt & HDF_CENTER) |
| { |
| lpColumn->fmt |= LVCFMT_CENTER; |
| } |
| |
| if (hdi.fmt & HDF_IMAGE) |
| { |
| lpColumn->fmt |= LVCFMT_COL_HAS_IMAGES; |
| } |
| } |
| |
| if (lpColumn->mask & LVCF_WIDTH) |
| { |
| lpColumn->cx = hdi.cxy; |
| } |
| |
| if ((lpColumn->mask & LVCF_TEXT) && (lpColumn->pszText) && (hdi.pszText)) |
| { |
| lstrcpynA (lpColumn->pszText, hdi.pszText, lpColumn->cchTextMax); |
| } |
| |
| if (lpColumn->mask & LVCF_IMAGE) |
| { |
| lpColumn->iImage = hdi.iImage; |
| } |
| |
| if (lpColumn->mask & LVCF_ORDER) |
| { |
| lpColumn->iOrder = hdi.iOrder; |
| } |
| } |
| } |
| |
| return bResult; |
| } |
| |
| /* << LISTVIEW_GetColumnW >> */ |
| /* << LISTVIEW_GetColumnOrderArray >> */ |
| |
| /*** |
| * DESCRIPTION: |
| * Retrieves the column width. |
| * |
| * PARAMETER(S): |
| * [I] HWND : window handle |
| * [I] int : column index |
| * |
| * RETURN: |
| * SUCCESS : column width |
| * FAILURE : zero |
| */ |
| static LRESULT LISTVIEW_GetColumnWidth(HWND hwnd, INT nColumn) |
| { |
| LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0); |
| LONG lStyle = GetWindowLongA(hwnd, GWL_STYLE); |
| HDITEMA hdi; |
| INT nColumnWidth = 0; |
| |
| if ((LVS_TYPEMASK & lStyle) == LVS_LIST) |
| { |
| nColumnWidth = infoPtr->nColumnWidth; |
| } |
| else if ((LVS_TYPEMASK & lStyle) == LVS_REPORT) |
| { |
| /* get column width from header */ |
| ZeroMemory(&hdi, sizeof(HDITEMA)); |
| hdi.mask = HDI_WIDTH; |
| if (Header_GetItemA(infoPtr->hwndHeader, nColumn, &hdi) == TRUE) |
| { |
| nColumnWidth = hdi.cxy; |
| } |
| } |
| |
| return nColumnWidth; |
| } |
| |
| /*** |
| * DESCRIPTION: |
| * In list or report display mode, retrieves the number of items that can fit |
| * vertically in the visible area. In icon or small icon display mode, |
| * retrieves the total number of visible items. |
| * |
| * PARAMETER(S): |
| * [I] HWND : window handle |
| * |
| * RETURN: |
| * Number of fully visible items. |
| */ |
| static LRESULT LISTVIEW_GetCountPerPage(HWND hwnd) |
| { |
| LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0); |
| LONG lStyle = GetWindowLongA(hwnd, GWL_STYLE); |
| INT nItemCount = 0; |
| |
| switch (LVS_TYPEMASK & lStyle) |
| { |
| case LVS_LIST: |
| if (infoPtr->rcList.right / infoPtr->nColumnWidth) |
| { |
| nItemCount = infoPtr->nCountPerRow * infoPtr->nCountPerColumn; |
| } |
| break; |
| |
| case LVS_REPORT: |
| nItemCount = infoPtr->nCountPerColumn; |
| break; |
| |
| default: |
| nItemCount = GETITEMCOUNT(infoPtr); |
| } |
| |
| return nItemCount; |
| } |
| |
| /* << LISTVIEW_GetEditControl >> */ |
| /* << LISTVIEW_GetExtendedListViewStyle >> */ |
| |
| /*** |
| * DESCRIPTION: |
| * Retrieves a header handle. |
| * |
| * PARAMETER(S): |
| * [I] HWND : window handle |
| * |
| * RETURN: |
| * Header handle. |
| */ |
| static LRESULT LISTVIEW_GetHeader(HWND hwnd) |
| { |
| LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0); |
| |
| return infoPtr->hwndHeader; |
| } |
| |
| /* << LISTVIEW_GetHotCursor >> */ |
| /* << LISTVIEW_GetHotItem >> */ |
| /* << LISTVIEW_GetHoverTime >> */ |
| |
| /*** |
| * DESCRIPTION: |
| * Retrieves an image list handle. |
| * |
| * PARAMETER(S): |
| * [I] HWND : window handle |
| * [I] INT : image list identifier |
| * |
| * RETURN: |
| * SUCCESS : image list handle |
| * FAILURE : NULL |
| */ |
| static LRESULT LISTVIEW_GetImageList(HWND hwnd, INT nImageList) |
| { |
| LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0); |
| HIMAGELIST himl = NULL; |
| |
| switch (nImageList) |
| { |
| case LVSIL_NORMAL: |
| himl = infoPtr->himlNormal; |
| break; |
| case LVSIL_SMALL: |
| himl = infoPtr->himlSmall; |
| break; |
| case LVSIL_STATE: |
| himl = infoPtr->himlState; |
| break; |
| } |
| |
| return (LRESULT)himl; |
| } |
| |
| /* << LISTVIEW_GetISearchString >> */ |
| |
| /*** |
| * DESCRIPTION: |
| * Retrieves item attributes. |
| * |
| * PARAMETER(S): |
| * [I] HWND : window handle |
| * [IO] LPLVITEMA : item info |
| * |
| * RETURN: |
| * SUCCESS : TRUE |
| * FAILURE : FALSE |
| */ |
| static LRESULT LISTVIEW_GetItemA(HWND hwnd, LPLVITEMA lpLVItem) |
| { |
| LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0); |
| LISTVIEW_ITEM *lpItem; |
| LISTVIEW_SUBITEM *lpSubItem; |
| HDPA hdpaSubItems; |
| BOOL bResult = FALSE; |
| |
| if (lpLVItem != NULL) |
| { |
| if ((lpLVItem->iItem >= 0) && (lpLVItem->iItem < GETITEMCOUNT(infoPtr))) |
| { |
| hdpaSubItems = (HDPA)DPA_GetPtr(infoPtr->hdpaItems, lpLVItem->iItem); |
| if (hdpaSubItems != NULL) |
| { |
| if (lpLVItem->iSubItem == 0) |
| { |
| lpItem = (LISTVIEW_ITEM *)DPA_GetPtr(hdpaSubItems, 0); |
| if (lpItem != NULL) |
| { |
| bResult = TRUE; |
| |
| /* retrieve valid data */ |
| if (lpLVItem->mask & LVIF_STATE) |
| { |
| lpLVItem->state = lpItem->state & lpLVItem->stateMask; |
| } |
| |
| if (lpLVItem->mask & LVIF_TEXT) |
| { |
| if (lpItem->pszText == LPSTR_TEXTCALLBACKA) |
| { |
| lpLVItem->pszText = LPSTR_TEXTCALLBACKA; |
| } |
| else |
| { |
| bResult = Str_GetPtrA(lpItem->pszText, lpLVItem->pszText, |
| lpLVItem->cchTextMax); |
| } |
| } |
| |
| if (lpLVItem->mask & LVIF_IMAGE) |
| { |
| lpLVItem->iImage = lpItem->iImage; |
| } |
| |
| if (lpLVItem->mask & LVIF_PARAM) |
| { |
| lpLVItem->lParam = lpItem->lParam; |
| } |
| |
| if (lpLVItem->mask & LVIF_INDENT) |
| { |
| lpLVItem->iIndent = lpItem->iIndent; |
| } |
| } |
| } |
| else |
| { |
| lpSubItem = (LISTVIEW_SUBITEM *)DPA_GetPtr(hdpaSubItems, |
| lpLVItem->iSubItem); |
| if (lpSubItem != NULL) |
| { |
| bResult = TRUE; |
| |
| if (lpLVItem->mask & LVIF_TEXT) |
| { |
| if (lpSubItem->pszText == LPSTR_TEXTCALLBACKA) |
| { |
| lpLVItem->pszText = LPSTR_TEXTCALLBACKA; |
| } |
| else |
| { |
| bResult = Str_GetPtrA(lpSubItem->pszText, lpLVItem->pszText, |
| lpLVItem->cchTextMax); |
| } |
| } |
| |
| if (lpLVItem->mask & LVIF_IMAGE) |
| { |
| lpLVItem->iImage = lpSubItem->iImage; |
| } |
| } |
| } |
| } |
| } |
| } |
| |
| return bResult; |
| } |
| |
| /* << LISTVIEW_GetItemW >> */ |
| /* << LISTVIEW_GetHotCursor >> */ |
| /* << LISTVIEW_GetHotItem >> */ |
| /* << LISTVIEW_GetHoverTime >> */ |
| |
| /*** |
| * DESCRIPTION: |
| * Retrieves the number of items in the listview control. |
| * |
| * PARAMETER(S): |
| * [I] HWND : window handle |
| * |
| * RETURN: |
| * Number of items. |
| */ |
| static LRESULT LISTVIEW_GetItemCount(HWND hwnd) |
| { |
| LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0); |
| |
| return GETITEMCOUNT(infoPtr); |
| } |
| |
| /*** |
| * DESCRIPTION: |
| * Retrieves the position (upper-left) of the listview control item. |
| * |
| * PARAMETER(S): |
| * [I] HWND : window handle |
| * [I] INT : item index |
| * [O] LPPOINT : coordinate information |
| * |
| * RETURN: |
| * SUCCESS : TRUE |
| * FAILURE : FALSE |
| */ |
| static LRESULT LISTVIEW_GetItemPosition(HWND hwnd, INT nItem, |
| LPPOINT lppt) |
| { |
| LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0); |
| LONG lStyle = GetWindowLongA(hwnd, GWL_STYLE); |
| INT nColumn; |
| INT nRow; |
| BOOL bResult = FALSE; |
| INT nFirst; |
| INT nLast; |
| |
| if ((nItem >= 0) && (nItem < GETITEMCOUNT(infoPtr)) && (lppt != NULL)) |
| { |
| switch (LVS_TYPEMASK & lStyle) |
| { |
| case LVS_LIST: |
| nFirst = ListView_GetTopIndex(hwnd); |
| nLast = infoPtr->nCountPerColumn * infoPtr->nCountPerRow + nFirst - 1; |
| |
| if ((nItem >= nFirst) || (nItem <= nLast)) |
| { |
| nItem -= nFirst; |
| |
| /* get column */ |
| nColumn = nItem / infoPtr->nCountPerColumn; |
| |
| /* get row */ |
| nRow = nItem % infoPtr->nCountPerColumn; |
| |
| /* X coordinate of the column */ |
| lppt->x = nColumn * infoPtr->nColumnWidth + infoPtr->rcList.left; |
| |
| /* Y coordinate of the item */ |
| lppt->y = nRow * infoPtr->nItemHeight + infoPtr->rcList.top; |
| |
| bResult = TRUE; |
| } |
| break; |
| |
| case LVS_REPORT: |
| nFirst = ListView_GetTopIndex(hwnd); |
| nLast = infoPtr->nCountPerColumn * infoPtr->nCountPerRow + nFirst - 1; |
| |
| /* get column */ |
| nColumn = nItem / infoPtr->nCountPerColumn; |
| |
| /* get row */ |
| nRow = nItem % infoPtr->nCountPerColumn; |
| |
| if ((nItem >= nFirst) || (nItem <= nLast)) |
| { |
| nItem -= nFirst; |
| |
| /* get column */ |
| nColumn = nItem / infoPtr->nCountPerColumn; |
| |
| /* get row */ |
| nRow = nItem % infoPtr->nCountPerColumn; |
| |
| /* X coordinate of the column */ |
| lppt->x = infoPtr->rcList.left; |
| |
| /* Y coordinate of the item */ |
| lppt->y = nRow * infoPtr->nItemHeight + infoPtr->rcList.top; |
| |
| bResult = TRUE; |
| } |
| |
| default: |
| /* TO DO */ |
| } |
| } |
| |
| return bResult; |
| } |
| |
| /*** |
| * DESCRIPTION: |
| * Retrieves the bounding rectangle for a listview control item. |
| * |
| * PARAMETER(S): |
| * [I] HWND : window handle |
| * [I] INT : item index |
| * [IO] LPRECT : bounding rectangle coordinates |
| * |
| * RETURN: |
| * SUCCESS : TRUE |
| * FAILURE : FALSE |
| */ |
| static LRESULT LISTVIEW_GetItemRect(HWND hwnd, INT nItem, LPRECT lprc) |
| { |
| LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0); |
| LONG lStyle = GetWindowLongA(hwnd, GWL_STYLE); |
| LISTVIEW_ITEM *lpItem; |
| HDPA hdpaSubItems; |
| INT nLabelWidth = 0; |
| INT nStateWidth = 0; |
| INT nIconWidth = 0; |
| BOOL bResult = FALSE; |
| CHAR szDispText[DISP_TEXT_SIZE]; |
| LPSTR pszDispText; |
| POINT pt; |
| |
| /*init pointer */ |
| pszDispText = szDispText; |
| |
| if ((nItem >= 0) && (nItem < GETITEMCOUNT(infoPtr)) && (lprc != NULL)) |
| { |
| hdpaSubItems = (HDPA)DPA_GetPtr(infoPtr->hdpaItems, nItem); |
| if (hdpaSubItems != NULL) |
| { |
| lpItem = (LISTVIEW_ITEM *)DPA_GetPtr(hdpaSubItems, 0); |
| if (lpItem != NULL) |
| { |
| if ((LVS_TYPEMASK & lStyle) == LVS_ICON) |
| { |
| |
| } |
| else |
| { |
| if (ListView_GetItemPosition(hwnd, nItem, &pt) == TRUE) |
| { |
| /* get width of label in pixels */ |
| LISTVIEW_GetItemDispInfo(hwnd, nItem, lpItem, NULL, NULL, |
| &pszDispText, DISP_TEXT_SIZE); |
| nLabelWidth = ListView_GetStringWidthA(hwnd, pszDispText); |
| } |
| |
| if (infoPtr->himlState != NULL) |
| { |
| nStateWidth = infoPtr->iconSize.cx; |
| } |
| |
| if (infoPtr->himlSmall == NULL) |
| { |
| nIconWidth = infoPtr->iconSize.cx; |
| } |
| |
| switch(lprc->left) |
| { |
| case LVIR_BOUNDS: |
| lprc->left = pt.x; |
| lprc->top = pt.y; |
| lprc->right = lprc->left + nStateWidth + nIconWidth + nLabelWidth; |
| lprc->bottom = lprc->top + infoPtr->nItemHeight; |
| bResult = TRUE; |
| break; |
| case LVIR_ICON: |
| lprc->left = pt.x + nStateWidth; |
| lprc->top = pt.y; |
| lprc->right = lprc->left + nIconWidth; |
| lprc->bottom = lprc->top + infoPtr->nItemHeight; |
| bResult = TRUE; |
| break; |
| case LVIR_LABEL: |
| lprc->left = pt.x + nIconWidth + nStateWidth; |
| lprc->top = pt.y; |
| lprc->right = lprc->left + nLabelWidth; |
| lprc->bottom = infoPtr->nItemHeight; |
| bResult = TRUE; |
| break; |
| case LVIR_SELECTBOUNDS: |
| lprc->left = pt.x + nStateWidth; |
| lprc->top = pt.y; |
| lprc->right = lprc->left + nIconWidth + nLabelWidth; |
| lprc->bottom = lprc->top + infoPtr->nItemHeight; |
| bResult = TRUE; |
| } |
| } |
| } |
| } |
| } |
| |
| return bResult; |
| } |
| |
| /*** |
| * DESCRIPTION: |
| * Retrieves the spacing between listview control items. |
| * |
| * PARAMETER(S): |
| * [I] HWND : window handle |
| * [I] BOOL : flag for small or large icon |
| * |
| * RETURN: |
| * Horizontal + vertical spacing |
| */ |
| static LRESULT LISTVIEW_GetItemSpacing(HWND hwnd, BOOL bSmall) |
| { |
| LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0); |
| LONG lResult; |
| |
| if (bSmall == TRUE) |
| { |
| lResult = MAKELONG(infoPtr->largeIconSpacing.cx, |
| infoPtr->largeIconSpacing.cy); |
| } |
| else |
| { |
| lResult = MAKELONG(infoPtr->smallIconSpacing.cx, |
| infoPtr->smallIconSpacing.cy); |
| } |
| |
| return lResult; |
| } |
| |
| /*** |
| * DESCRIPTION: |
| * Retrieves the state of a listview control item. |
| * |
| * PARAMETER(S): |
| * [I] HWND : window handle |
| * [I] INT : item index |
| * [I] UINT : state mask |
| * |
| * RETURN: |
| * State specified by the mask. |
| */ |
| static LRESULT LISTVIEW_GetItemState(HWND hwnd, INT nItem, UINT uMask) |
| { |
| LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0); |
| LVITEMA lvItem; |
| UINT uState = 0; |
| |
| if ((nItem >= 0) && (nItem < GETITEMCOUNT(infoPtr))) |
| { |
| ZeroMemory(&lvItem, sizeof(LVITEMA)); |
| lvItem.iItem = nItem; |
| lvItem.stateMask = uMask; |
| lvItem.mask = LVIF_STATE; |
| if (ListView_GetItemA(hwnd, &lvItem) == TRUE) |
| { |
| uState = lvItem.state; |
| } |
| } |
| |
| return uState; |
| } |
| |
| /*** |
| * DESCRIPTION: |
| * Retrieves the text of a listview control item or subitem. |
| * |
| * PARAMETER(S): |
| * [I] HWND : window handle |
| * [I] INT : item index |
| * [IO] LPLVITEMA : item information |
| * |
| * RETURN: |
| * None |
| */ |
| static LRESULT LISTVIEW_GetItemTextA(HWND hwnd, INT nItem, |
| LPLVITEMA lpLVItem) |
| { |
| LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0); |
| LISTVIEW_ITEM *lpItem; |
| LISTVIEW_SUBITEM *lpSubItem; |
| HDPA hdpaSubItems; |
| INT nLength = 0; |
| |
| if (lpLVItem != NULL) |
| { |
| if ((nItem >= 0) && (nItem < GETITEMCOUNT(infoPtr))) |
| { |
| hdpaSubItems = (HDPA)DPA_GetPtr(infoPtr->hdpaItems, lpLVItem->iItem); |
| if (hdpaSubItems != NULL) |
| { |
| if (lpLVItem->iSubItem == 0) |
| { |
| lpItem = (LISTVIEW_ITEM *)DPA_GetPtr(hdpaSubItems, 0); |
| if (lpItem != NULL) |
| { |
| if (lpLVItem->mask & LVIF_TEXT) |
| { |
| if (lpItem->pszText == LPSTR_TEXTCALLBACKA) |
| { |
| lpLVItem->pszText = LPSTR_TEXTCALLBACKA; |
| } |
| else |
| { |
| nLength = Str_GetPtrA(lpItem->pszText, lpLVItem->pszText, |
| lpLVItem->cchTextMax); |
| } |
| } |
| } |
| } |
| else |
| { |
| lpSubItem = (LISTVIEW_SUBITEM *)DPA_GetPtr(hdpaSubItems, |
| lpLVItem->iSubItem); |
| if (lpSubItem != NULL) |
| { |
| if (lpLVItem->mask & LVIF_TEXT) |
| { |
| if (lpSubItem->pszText == LPSTR_TEXTCALLBACKA) |
| { |
| lpLVItem->pszText = LPSTR_TEXTCALLBACKA; |
| } |
| else |
| { |
| nLength = Str_GetPtrA(lpSubItem->pszText, lpLVItem->pszText, |
| lpLVItem->cchTextMax); |
| } |
| } |
| } |
| } |
| } |
| } |
| } |
| |
| return nLength; |
| } |
| |
| /*** |
| * DESCRIPTION: |
| * Searches for an item based on properties + relationships. |
| * |
| * PARAMETER(S): |
| * [I] HWND : window handle |
| * [I] INT : item index |
| * [I] UINT : relationship flag |
| * |
| * RETURN: |
| * SUCCESS : item index |
| * FAILURE : -1 |
| */ |
| static LRESULT LISTVIEW_GetNextItem(HWND hwnd, INT nItem, UINT uFlags) |
| { |
| LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0); |
| INT nResult = -1; |
| |
| if (nItem == -1) |
| { |
| /* start at begin */ |
| nItem = 0; |
| } |
| else |
| { |
| /* exclude specified item */ |
| nItem++; |
| } |
| |
| if ((nItem >= 0) && (nItem < GETITEMCOUNT(infoPtr))) |
| { |
| /* TO DO */ |
| } |
| |
| return nResult; |
| } |
| |
| /* << LISTVIEW_GetNumberOfWorkAreas >> */ |
| |
| /*** |
| * DESCRIPTION: |
| * Retrieves the current origin when in icon or small icon display mode. |
| * |
| * PARAMETER(S): |
| * [I] HWND : window handle |
| * [O] LPPOINT : coordinate information |
| * |
| * RETURN: |
| * SUCCESS : TRUE |
| * FAILURE : FALSE |
| */ |
| static LRESULT LISTVIEW_GetOrigin(HWND hwnd, LPPOINT lpOrigin) |
| { |
| LONG lStyle = GetWindowLongA(hwnd, GWL_ID); |
| BOOL bResult = FALSE; |
| |
| if ((lStyle & LVS_TYPEMASK) == LVS_SMALLICON) |
| { |
| /* TO DO */ |
| lpOrigin->x = 0; |
| lpOrigin->y = 0; |
| } |
| else if ((lStyle & LVS_TYPEMASK) == LVS_ICON) |
| { |
| /* TO DO */ |
| lpOrigin->x = 0; |
| lpOrigin->y = 0; |
| } |
| |
| return bResult; |
| } |
| |
| /*** |
| * DESCRIPTION: |
| * Retrieves the number of items that are marked as selected. |
| * |
| * PARAMETER(S): |
| * [I] HWND : window handle |
| * |
| * RETURN: |
| * Number of items selected. |
| */ |
| static LRESULT LISTVIEW_GetSelectedCount(HWND hwnd) |
| { |
| LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0); |
| INT nSelectedCount = 0; |
| INT i; |
| |
| for (i = 0; i < GETITEMCOUNT(infoPtr); i++) |
| { |
| if (ListView_GetItemState(hwnd, i, LVIS_SELECTED) & LVIS_SELECTED) |
| { |
| nSelectedCount++; |
| } |
| } |
| |
| return nSelectedCount; |
| } |
| |
| /*** |
| * DESCRIPTION: |
| * Retrieves item index that marks the start of a multiple selection. |
| * |
| * PARAMETER(S): |
| * [I] HWND : window handle |
| * |
| * RETURN: |
| * Index number or -1 if there is no selection mark. |
| */ |
| static LRESULT LISTVIEW_GetSelectionMark(HWND hwnd) |
| { |
| LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0); |
| |
| return infoPtr->nSelectionMark; |
| } |
| |
| /*** |
| * DESCRIPTION: |
| * Retrieves the width of a string. |
| * |
| * PARAMETER(S): |
| * [I] HWND : window handle |
| * |
| * RETURN: |
| * SUCCESS : string width (in pixels) |
| * FAILURE : zero |
| */ |
| static LRESULT LISTVIEW_GetStringWidthA(HWND hwnd, LPCSTR lpsz) |
| { |
| LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0); |
| HFONT hFont, hOldFont; |
| HDC hdc; |
| SIZE textSize; |
| |
| /* initialize */ |
| ZeroMemory(&textSize, sizeof(SIZE)); |
| if (lpsz != NULL) |
| { |
| hFont = infoPtr->hFont ? infoPtr->hFont : infoPtr->hDefaultFont; |
| hdc = GetDC(hwnd); |
| hOldFont = SelectObject(hdc, hFont); |
| GetTextExtentPointA(hdc, lpsz, lstrlenA(lpsz), &textSize); |
| SelectObject(hdc, hOldFont); |
| ReleaseDC(hwnd, hdc); |
| } |
| |
| return textSize.cx; |
| } |
| |
| /*** |
| * DESCRIPTION: |
| * Retrieves the text backgound color. |
| * |
| * PARAMETER(S): |
| * [I] HWND : window handle |
| * |
| * RETURN: |
| * COLORREF associated with the the background. |
| */ |
| static LRESULT LISTVIEW_GetTextBkColor(HWND hwnd) |
| { |
| LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO*)GetWindowLongA(hwnd, 0); |
| |
| return infoPtr->clrTextBk; |
| } |
| |
| /*** |
| * DESCRIPTION: |
| * Retrieves the text color. |
| * |
| * PARAMETER(S): |
| * [I] HWND : window handle |
| * |
| * RETURN: |
| * COLORREF associated with the text. |
| */ |
| static LRESULT LISTVIEW_GetTextColor(HWND hwnd) |
| { |
| LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO*)GetWindowLongA(hwnd, 0); |
| |
| return infoPtr->clrText; |
| } |
| |
| /*** |
| * DESCRIPTION: |
| * Retrieves the bounding rectangle of all the items. |
| * |
| * PARAMETER(S): |
| * [I] HWND : window handle |
| * [O] LPRECT : bounding rectangle |
| * |
| * RETURN: |
| * SUCCESS : TRUE |
| * FAILURE : FALSE |
| */ |
| static LRESULT LISTVIEW_GetViewRect(HWND hwnd, LPRECT lprc) |
| { |
| /* LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0); */ |
| LONG lStyle = GetWindowLongA(hwnd, GWL_STYLE); |
| BOOL bResult = FALSE; |
| |
| if (lprc != NULL) |
| { |
| if (((lStyle & LVS_TYPEMASK) == LVS_ICON) || |
| ((lStyle & LVS_TYPEMASK) == LVS_SMALLICON)) |
| { |
| /* TO DO */ |
| } |
| } |
| |
| return bResult; |
| } |
| |
| /*** |
| * DESCRIPTION: |
| * Determines which section of the item was selected (if any). |
| * |
| * PARAMETER(S): |
| * [I] HWND : window handle |
| * [I] INT : item index |
| * [IO] LPLVHITTESTINFO : hit test information |
| * |
| * RETURN: |
| * SUCCESS : item index |
| * FAILURE : -1 |
| */ |
| static INT LISTVIEW_HitTestItem(HWND hwnd, INT nItem, |
| LPLVHITTESTINFO lpHitTestInfo) |
| { |
| LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0); |
| LONG lStyle = GetWindowLongA(hwnd, GWL_STYLE); |
| HDPA hdpaSubItems; |
| LISTVIEW_ITEM *lpItem; |
| INT nOffset; |
| INT nLabelWidth; |
| INT nPosX = 0; |
| CHAR szDispText[DISP_TEXT_SIZE]; |
| LPSTR pszDispText; |
| |
| /*init pointer */ |
| pszDispText = szDispText; |
| |
| if ((LVS_TYPEMASK & lStyle) == LVS_LIST) |
| { |
| /* calculate offset from start of item (in pixels) */ |
| nOffset = lpHitTestInfo->pt.x % infoPtr->nColumnWidth; |
| } |
| else |
| { |
| nOffset = lpHitTestInfo->pt.x; |
| } |
| |
| /* verify existance of item */ |
| if (nItem < GETITEMCOUNT(infoPtr)) |
| { |
| /* get item */ |
| hdpaSubItems = (HDPA)DPA_GetPtr(infoPtr->hdpaItems, nItem); |
| if (hdpaSubItems != NULL) |
| { |
| lpItem = (LISTVIEW_ITEM *)DPA_GetPtr(hdpaSubItems, 0); |
| if (lpItem != NULL) |
| { |
| if (infoPtr->himlState != NULL) |
| { |
| nPosX += infoPtr->iconSize.cx; |
| if (nOffset <= nPosX) |
| { |
| lpHitTestInfo->flags = LVHT_ONITEMSTATEICON | LVHT_ONITEM; |
| lpHitTestInfo->iItem = nItem; |
| lpHitTestInfo->iSubItem = 0; |
| return nItem; |
| } |
| } |
| |
| if (infoPtr->himlSmall != NULL) |
| { |
| nPosX += infoPtr->iconSize.cx; |
| if (nOffset <= nPosX) |
| { |
| lpHitTestInfo->flags = LVHT_ONITEMICON | LVHT_ONITEM; |
| lpHitTestInfo->iItem = nItem; |
| lpHitTestInfo->iSubItem = 0; |
| return nItem; |
| } |
| } |
| |
| /* get width of label in pixels */ |
| LISTVIEW_GetItemDispInfo(hwnd, nItem, lpItem, NULL, NULL, |
| &pszDispText, DISP_TEXT_SIZE); |
| nLabelWidth = ListView_GetStringWidthA(hwnd, pszDispText); |
| nLabelWidth += nPosX; |
| |
| if (nOffset <= nLabelWidth) |
| { |
| lpHitTestInfo->flags = LVHT_ONITEMLABEL | LVHT_ONITEM; |
| lpHitTestInfo->iItem = nItem; |
| lpHitTestInfo->iSubItem = 0; |
| return nItem; |
| } |
| } |
| } |
| } |
| |
| /* hit is not on item */ |
| lpHitTestInfo->flags = LVHT_NOWHERE; |
| |
| return -1; |
| } |
| |
| /*** |
| * DESCRIPTION: |
| * Determines wich listview item is located at the specified position. |
| * |
| * PARAMETER(S): |
| * [I] HWND : window handle |
| * [IO} LPLVHITTESTINFO : hit test information |
| * |
| * RETURN: |
| * SUCCESS : item index |
| * FAILURE : -1 |
| */ |
| static LRESULT LISTVIEW_HitTest(HWND hwnd, LPLVHITTESTINFO lpHitTestInfo) |
| { |
| LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0); |
| LONG lStyle = GetWindowLongA(hwnd, GWL_STYLE); |
| INT nColumn; |
| INT nRow; |
| INT nTopIndex; |
| INT nItem = -1; |
| |
| lpHitTestInfo->flags = 0; |
| if (infoPtr->rcList.left > lpHitTestInfo->pt.x) |
| { |
| lpHitTestInfo->flags = LVHT_TOLEFT; |
| } |
| else if (infoPtr->rcList.right < lpHitTestInfo->pt.x) |
| { |
| lpHitTestInfo->flags = LVHT_TORIGHT; |
| } |
| |
| if (infoPtr->rcList.top > lpHitTestInfo->pt.y) |
| { |
| lpHitTestInfo->flags |= LVHT_ABOVE; |
| } |
| else if (infoPtr->rcList.bottom < lpHitTestInfo->pt.y) |
| { |
| lpHitTestInfo->flags |= LVHT_BELOW; |
| } |
| |
| if (lpHitTestInfo->flags == 0) |
| { |
| switch (LVS_TYPEMASK & lStyle) |
| { |
| case LVS_LIST: |
| /* get current column */ |
| nColumn = lpHitTestInfo->pt.x / infoPtr->nColumnWidth; |
| |
| /* get current row */ |
| nRow = lpHitTestInfo->pt.y / infoPtr->nItemHeight; |
| |
| /* get the index of the first visible item */ |
| nTopIndex = ListView_GetTopIndex(hwnd); |
| |
| nItem = nColumn * infoPtr->nCountPerColumn + nTopIndex + nRow; |
| nItem = LISTVIEW_HitTestItem(hwnd, nItem, lpHitTestInfo); |
| break; |
| |
| case LVS_REPORT: |
| /* get current row */ |
| nRow = ((lpHitTestInfo->pt.y - infoPtr->rcList.top) / |
| infoPtr->nItemHeight); |
| |
| /* get the index of the first visible item */ |
| nTopIndex = ListView_GetTopIndex(hwnd); |
| |
| nItem = nTopIndex + nRow; |
| nItem = LISTVIEW_HitTestItem(hwnd, nItem, lpHitTestInfo); |
| break; |
| |
| default: |
| /* nItem = LISTVIEW_HitTestItem(hwnd, nItem, lpHitTestInfo); */ |
| } |
| } |
| |
| return nItem; |
| } |
| |
| /*** |
| * DESCRIPTION: |
| * Inserts a new column. |
| * |
| * PARAMETER(S): |
| * [I] HWND : window handle |
| * [I] INT : column index |
| * [I] LPLVCOLUMNA : column information |
| * |
| * RETURN: |
| * SUCCESS : new column index |
| * FAILURE : -1 |
| */ |
| static LRESULT LISTVIEW_InsertColumnA(HWND hwnd, INT nColumn, |
| LPLVCOLUMNA lpColumn) |
| { |
| LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0); |
| HDITEMA hdi; |
| INT nNewColumn = -1; |
| |
| if (lpColumn != NULL) |
| { |
| /* initialize memory */ |
| ZeroMemory(&hdi, sizeof(HDITEMA)); |
| |
| if (lpColumn->mask & LVCF_FMT) |
| { |
| /* format member is valid */ |
| hdi.mask |= HDI_FORMAT; |
| |
| /* set text alignment (leftmost column must be left-aligned) */ |
| if (nColumn == 0) |
| { |
| hdi.fmt |= HDF_LEFT; |
| } |
| else |
| { |
| if (lpColumn->fmt & LVCFMT_LEFT) |
| { |
| hdi.fmt |= HDF_LEFT; |
| } |
| else if (lpColumn->fmt & LVCFMT_RIGHT) |
| { |
| hdi.fmt |= HDF_RIGHT; |
| } |
| else if (lpColumn->fmt & LVCFMT_CENTER) |
| { |
| hdi.fmt |= HDF_CENTER; |
| } |
| } |
| |
| if (lpColumn->fmt & LVCFMT_BITMAP_ON_RIGHT) |
| { |
| hdi.fmt |= HDF_BITMAP_ON_RIGHT; |
| /* ??? */ |
| } |
| |
| if (lpColumn->fmt & LVCFMT_COL_HAS_IMAGES) |
| { |
| /* ??? */ |
| } |
| |
| if (lpColumn->fmt & LVCFMT_IMAGE) |
| { |
| hdi.fmt |= HDF_IMAGE; |
| hdi.iImage = I_IMAGECALLBACK; |
| } |
| } |
| |
| if (lpColumn->mask & LVCF_WIDTH) |
| { |
| hdi.mask |= HDI_WIDTH; |
| hdi.cxy = lpColumn->cx; |
| } |
| |
| if (lpColumn->mask & LVCF_TEXT) |
| { |
| hdi.mask |= HDI_TEXT | HDI_FORMAT; |
| hdi.pszText = lpColumn->pszText; |
| hdi.cchTextMax = lstrlenA(lpColumn->pszText); |
| hdi.fmt |= HDF_STRING; |
| } |
| |
| if (lpColumn->mask & LVCF_IMAGE) |
| { |
| hdi.mask |= HDI_IMAGE; |
| hdi.iImage = lpColumn->iImage; |
| } |
| |
| if (lpColumn->mask & LVCF_ORDER) |
| { |
| hdi.mask |= HDI_ORDER; |
| hdi.iOrder = lpColumn->iOrder; |
| } |
| |
| /* insert item in header control */ |
| nNewColumn = SendMessageA(infoPtr->hwndHeader, HDM_INSERTITEMA, |
| (WPARAM)nColumn, (LPARAM)&hdi); |
| |
| LISTVIEW_SetScroll(hwnd); |
| InvalidateRect(hwnd, NULL, FALSE); |
| } |
| |
| return nNewColumn; |
| } |
| |
| /* << LISTVIEW_InsertColumnW >> */ |
| |
| /*** |
| * DESCRIPTION: |
| * Inserts a new item in the listview control. |
| * |
| * PARAMETER(S): |
| * [I] HWND : window handle |
| * [I] LPLVITEMA : item information |
| * |
| * RETURN: |
| * SUCCESS : new item index |
| * FAILURE : -1 |
| */ |
| static LRESULT LISTVIEW_InsertItemA(HWND hwnd, LPLVITEMA lpLVItem) |
| { |
| LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0); |
| LONG lCtrlId = GetWindowLongA(hwnd, GWL_ID); |
| NMLISTVIEW nmlv; |
| INT nItem = -1; |
| HDPA hdpaSubItems; |
| LISTVIEW_ITEM *lpItem = NULL; |
| |
| if (lpLVItem != NULL) |
| { |
| /* make sure it's not a subitem; cannot insert a subitem */ |
| if (lpLVItem->iSubItem == 0) |
| { |
| lpItem = (LISTVIEW_ITEM *)COMCTL32_Alloc(sizeof(LISTVIEW_ITEM)); |
| if (lpItem != NULL) |
| { |
| ZeroMemory(lpItem, sizeof(LISTVIEW_ITEM)); |
| if (LISTVIEW_InitItem(hwnd, lpItem, lpLVItem) == TRUE) |
| { |
| /* insert item in listview control data structure */ |
| hdpaSubItems = DPA_Create(8); |
| if (hdpaSubItems != NULL) |
| { |
| nItem = DPA_InsertPtr(hdpaSubItems, 0, lpItem); |
| if (nItem != -1) |
| { |
| nItem = DPA_InsertPtr(infoPtr->hdpaItems, lpLVItem->iItem, |
| hdpaSubItems); |
| if (nItem != -1) |
| { |
| /* manage item focus */ |
| if (lpLVItem->mask & LVIF_STATE) |
| { |
| if (lpLVItem->stateMask & LVIS_FOCUSED) |
| { |
| LISTVIEW_SetItemFocus(hwnd, nItem); |
| } |
| } |
| |
| /* send LVN_INSERTITEM notification */ |
| ZeroMemory(&nmlv, sizeof(NMLISTVIEW)); |
| nmlv.hdr.hwndFrom = hwnd; |
| nmlv.hdr.idFrom = lCtrlId; |
| nmlv.hdr.code = LVN_INSERTITEM; |
| nmlv.iItem = nItem; |
| nmlv.lParam = lpItem->lParam;; |
| ListView_LVNotify(GetParent(hwnd), lCtrlId, &nmlv); |
| |
| /* set scrolling parameters */ |
| LISTVIEW_SetScroll(hwnd); |
| |
| /* refresh client area */ |
| InvalidateRect(hwnd, NULL, FALSE); |
| } |
| } |
| } |
| } |
| } |
| } |
| } |
| |
| /* free memory if unsuccessful */ |
| if ((nItem == -1) && (lpItem != NULL)) |
| { |
| COMCTL32_Free(lpItem); |
| } |
| |
| return nItem; |
| } |
| |
| /* << LISTVIEW_InsertItemW >> */ |
| |
| /*** |
| * DESCRIPTION: |
| * Redraws a range of items. |
| * |
| * PARAMETER(S): |
| * [I] HWND : window handle |
| * [I] INT : first item |
| * [I] INT : last item |
| * |
| * RETURN: |
| * SUCCESS : TRUE |
| * FAILURE : FALSE |
| */ |
| static LRESULT LISTVIEW_RedrawItems(HWND hwnd, INT nFirst, INT nLast) |
| { |
| LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0); |
| BOOL bResult = FALSE; |
| RECT rc; |
| |
| if (nFirst <= nLast) |
| { |
| if ((nFirst >= 0) && (nFirst < GETITEMCOUNT(infoPtr))) |
| { |
| if ((nLast >= 0) && (nLast < GETITEMCOUNT(infoPtr))) |
| { |
| /* bResult = */ |
| InvalidateRect(hwnd, &rc, FALSE); |
| } |
| } |
| } |
| |
| return bResult; |
| } |
| |
| /*** |
| * DESCRIPTION: |
| * Scrolls the content of a listview. |
| * |
| * PARAMETER(S): |
| * [I] HWND : window handle |
| * [I] INT : amount of horizontal scrolling |
| * [I] INT : amount of vertical scrolling |
| * |
| * RETURN: |
| * SUCCESS : TRUE |
| * FAILURE : FALSE |
| */ |
| static LRESULT LISTVIEW_Scroll(HWND hwnd, INT nHScroll, INT nVScroll) |
| { |
| LONG lStyle = GetWindowLongA(hwnd, GWL_STYLE); |
| INT nScrollPos = 0; |
| BOOL bResult = FALSE; |
| INT nMinRange; |
| INT nMaxRange; |
| |
| if (lStyle & WS_HSCROLL) |
| { |
| nScrollPos = GetScrollPos(hwnd, SB_HORZ); |
| GetScrollRange(hwnd, SB_HORZ, &nMinRange, &nMaxRange); |
| nScrollPos += nHScroll; |
| |
| if ((LVS_TYPEMASK & lStyle) == LVS_LIST) |
| { |
| nScrollPos = GetScrollPos(hwnd, SB_HORZ); |
| GetScrollRange(hwnd, SB_HORZ, &nMinRange, &nMaxRange); |
| nScrollPos += nHScroll; |
| if ((nMinRange <= nScrollPos) && (nScrollPos <= nMaxRange)) |
| { |
| bResult = TRUE; |
| SetScrollPos(hwnd, SB_HORZ, nScrollPos, TRUE); |
| } |
| } |
| else |
| { |
| /* TO DO */ |
| } |
| } |
| |
| if (lStyle & WS_VSCROLL) |
| { |
| if ((LVS_TYPEMASK & lStyle) == LVS_REPORT) |
| { |
| nScrollPos = GetScrollPos(hwnd, SB_VERT); |
| GetScrollRange(hwnd, SB_VERT, &nMinRange, &nMaxRange); |
| nScrollPos += nVScroll; |
| if ((nMinRange <= nScrollPos) && (nScrollPos <= nMaxRange)) |
| { |
| bResult = TRUE; |
| SetScrollPos(hwnd, SB_VERT, nScrollPos, TRUE); |
| } |
| } |
| else |
| { |
| /* TO DO */ |
| } |
| } |
| |
| if (bResult == TRUE) |
| { |
| /* refresh client area */ |
| InvalidateRect(hwnd, NULL, TRUE); |
| } |
| |
| return bResult; |
| } |
| |
| /*** |
| * DESCRIPTION: |
| * Sets the background color. |
| * |
| * PARAMETER(S): |
| * [I] HWND : window handle |
| * [I] COLORREF : background color |
| * |
| * RETURN: |
| * SUCCESS : TRUE |
| * FAILURE : FALSE |
| */ |
| static LRESULT LISTVIEW_SetBkColor(HWND hwnd, COLORREF clrBk) |
| { |
| LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0); |
| |
| infoPtr->clrBk = clrBk; |
| InvalidateRect(hwnd, NULL, TRUE); |
| |
| return TRUE; |
| } |
| |
| /*** |
| * DESCRIPTION: |
| * Sets the callback mask. This mask will be used when the parent |
| * window stores the state information (some or all). |
| * |
| * PARAMETER(S): |
| * [I] HWND : window handle |
| * [I] UINT : state mask |
| * |
| * RETURN: |
| * SUCCESS : TRUE |
| * FAILURE : FALSE |
| */ |
| static BOOL LISTVIEW_SetCallbackMask(HWND hwnd, UINT uMask) |
| { |
| LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0); |
| |
| infoPtr->uCallbackMask = uMask; |
| |
| return TRUE; |
| } |
| |
| /*** |
| * DESCRIPTION: |
| * Sets column attributes. |
| * |
| * PARAMETER(S): |
| * [I] HWND : window handle |
| * [I] INT : column index |
| * [I] LPLVCOLUMNA : column attributes |
| * |
| * RETURN: |
| * SUCCESS : TRUE |
| * FAILURE : FALSE |
| */ |
| static LRESULT LISTVIEW_SetColumnA(HWND hwnd, INT nColumn, |
| LPLVCOLUMNA lpColumn) |
| { |
| LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0); |
| HDITEMA hdi; |
| BOOL bResult = FALSE; |
| |
| if ((lpColumn != NULL) && (nColumn >= 0) && |
| (nColumn < Header_GetItemCount(infoPtr->hwndHeader))) |
| { |
| /* initialize memory */ |
| ZeroMemory(&hdi, sizeof(HDITEMA)); |
| |
| if (lpColumn->mask & LVCF_FMT) |
| { |
| /* format member is valid */ |
| hdi.mask |= HDI_FORMAT; |
| |
| /* set text alignment (leftmost column must be left-aligned) */ |
| if (nColumn == 0) |
| { |
| hdi.fmt |= HDF_LEFT; |
| } |
| else |
| { |
| if (lpColumn->fmt & LVCFMT_LEFT) |
| { |
| hdi.fmt |= HDF_LEFT; |
| } |
| else if (lpColumn->fmt & LVCFMT_RIGHT) |
| { |
| hdi.fmt |= HDF_RIGHT; |
| } |
| else if (lpColumn->fmt & LVCFMT_CENTER) |
| { |
| hdi.fmt |= HDF_CENTER; |
| } |
| } |
| |
| if (lpColumn->fmt & LVCFMT_BITMAP_ON_RIGHT) |
| { |
| hdi.fmt |= HDF_BITMAP_ON_RIGHT; |
| } |
| |
| if (lpColumn->fmt & LVCFMT_COL_HAS_IMAGES) |
| { |
| hdi.fmt |= HDF_IMAGE; |
| } |
| |
| if (lpColumn->fmt & LVCFMT_IMAGE) |
| { |
| hdi.fmt |= HDF_IMAGE; |
| hdi.iImage = I_IMAGECALLBACK; |
| } |
| } |
| |
| if (lpColumn->mask & LVCF_WIDTH) |
| { |
| hdi.mask |= HDI_WIDTH; |
| hdi.cxy = lpColumn->cx; |
| } |
| |
| if (lpColumn->mask & LVCF_TEXT) |
| { |
| hdi.mask |= HDI_TEXT | HDI_FORMAT; |
| hdi.pszText = lpColumn->pszText; |
| hdi.cchTextMax = lstrlenA(lpColumn->pszText); |
| hdi.fmt |= HDF_STRING; |
| } |
| |
| if (lpColumn->mask & LVCF_IMAGE) |
| { |
| hdi.mask |= HDI_IMAGE; |
| hdi.iImage = lpColumn->iImage; |
| } |
| |
| if (lpColumn->mask & LVCF_ORDER) |
| { |
| hdi.mask |= HDI_ORDER; |
| hdi.iOrder = lpColumn->iOrder; |
| } |
| |
| /* set header item attributes */ |
| bResult = Header_SetItemA(infoPtr->hwndHeader, nColumn, &hdi); |
| } |
| |
| return bResult; |
| } |
| |
| /*** |
| * DESCRIPTION: |
| * Sets image list. |
| * |
| * PARAMETER(S): |
| * [I] HWND : window handle |
| * [I] INT : image list type |
| * [I] HIMAGELIST : image list handle |
| * |
| * RETURN: |
| * SUCCESS : old image list |
| * FAILURE : NULL |
| */ |
| static LRESULT LISTVIEW_SetImageList(HWND hwnd, INT nType, HIMAGELIST himl) |
| { |
| LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0); |
| HIMAGELIST himlTemp = 0; |
| |
| switch (nType) |
| { |
| case LVSIL_NORMAL: |
| himlTemp = infoPtr->himlNormal; |
| infoPtr->himlNormal = himl; |
| return (LRESULT)himlTemp; |
| |
| case LVSIL_SMALL: |
| himlTemp = infoPtr->himlSmall; |
| infoPtr->himlSmall = himl; |
| return (LRESULT)himlTemp; |
| |
| case LVSIL_STATE: |
| himlTemp = infoPtr->himlState; |
| infoPtr->himlState = himl; |
| return (LRESULT)himlTemp; |
| } |
| |
| return (LRESULT)NULL; |
| } |
| |
| |
| /*** |
| * DESCRIPTION: |
| * Sets item attributes. |
| * |
| * PARAMETER(S): |
| * [I] HWND : window handle |
| * [I] LPLVITEM : item information |
| * |
| * RETURN: |
| * SUCCESS : TRUE |
| * FAILURE : FALSE |
| */ |
| static LRESULT LISTVIEW_SetItemA(HWND hwnd, LPLVITEMA lpLVItem) |
| { |
| LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0); |
| BOOL bResult = FALSE; |
| |
| if (lpLVItem != NULL) |
| { |
| if ((lpLVItem->iItem >= 0) && (lpLVItem->iItem < GETITEMCOUNT(infoPtr))) |
| { |
| if (lpLVItem->iSubItem == 0) |
| { |
| bResult = LISTVIEW_SetItem(hwnd, lpLVItem); |
| } |
| else |
| { |
| bResult = LISTVIEW_SetSubItem(hwnd, lpLVItem); |
| } |
| } |
| } |
| |
| |
| return bResult; |
| } |
| |
| /* << LISTVIEW_SetItemW >> */ |
| |
| /*** |
| * DESCRIPTION: |
| * Preallocates memory. |
| * |
| * PARAMETER(S): |
| * [I] HWND : window handle |
| * [I] INT : item count (prjected number of items) |
| * |
| * RETURN: |
| * None |
| */ |
| static VOID LISTVIEW_SetItemCount(HWND hwnd, INT nItemCount) |
| { |
| /* TO DO */ |
| } |
| |
| /*** |
| * DESCRIPTION: |
| * Sets item position. |
| * |
| * PARAMETER(S): |
| * [I] HWND : window handle |
| * [I] INT : item index |
| * [I] INT : x coordinate |
| * [I] INT : y coordinate |
| * |
| * RETURN: |
| * SUCCESS : TRUE |
| * FAILURE : FALSE |
| */ |
| static LRESULT LISTVIEW_SetItemPosition(HWND hwnd, INT nItem, |
| INT nPosX, INT nPosY) |
| { |
| LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO*)GetWindowLongA(hwnd, 0); |
| LONG lStyle = GetWindowLongA(hwnd, GWL_STYLE); |
| BOOL bResult = FALSE; |
| |
| if ((nItem >= 0) || (nItem < GETITEMCOUNT(infoPtr))) |
| { |
| if (((lStyle & LVS_TYPEMASK) == LVS_ICON) || |
| ((lStyle & LVS_TYPEMASK) == LVS_SMALLICON)) |
| { |
| /* TO DO */ |
| } |
| } |
| |
| return bResult; |
| } |
| |
| /*** |
| * DESCRIPTION: |
| * Sets the state of one or many items. |
| * |
| * PARAMETER(S): |
| * [I] HWND : window handle |
| * [I]INT : item index |
| * [I] LPLVITEM : item or subitem info |
| * |
| * RETURN: |
| * SUCCESS : TRUE |
| * FAILURE : FALSE |
| */ |
| static LRESULT LISTVIEW_SetItemState(HWND hwnd, INT nItem, |
| LPLVITEMA lpLVItem) |
| { |
| LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0); |
| BOOL bResult = FALSE; |
| LVITEMA lvItem; |
| INT i; |
| |
| if (nItem == -1) |
| { |
| bResult = TRUE; |
| ZeroMemory(&lvItem, sizeof(LVITEMA)); |
| lvItem.mask = LVIF_STATE; |
| lvItem.state = lpLVItem->state; |
| lvItem.stateMask = lpLVItem->stateMask; |
| |
| /* apply to all items */ |
| for (i = 0; i< GETITEMCOUNT(infoPtr); i++) |
| { |
| lvItem.iItem = i; |
| if (ListView_SetItemA(hwnd, &lvItem) == FALSE) |
| { |
| bResult = FALSE; |
| } |
| } |
| } |
| else |
| { |
| ZeroMemory(&lvItem, sizeof(LVITEMA)); |
| lvItem.mask = LVIF_STATE; |
| lvItem.state = lpLVItem->state; |
| lvItem.stateMask = lpLVItem->stateMask; |
| lvItem.iItem = nItem; |
| bResult = ListView_SetItemA(hwnd, &lvItem); |
| } |
| |
| return bResult; |
| } |
| |
| /*** |
| * DESCRIPTION: |
| * Sets the text of an item or subitem. |
| * |
| * PARAMETER(S): |
| * [I] HWND : window handle |
| * [I] INT : item index |
| * [I] LPLVITEMA : item or subitem info |
| * |
| * RETURN: |
| * SUCCESS : TRUE |
| * FAILURE : FALSE |
| */ |
| static BOOL LISTVIEW_SetItemTextA(HWND hwnd, INT nItem, |
| LPLVITEMA lpLVItem) |
| { |
| LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0); |
| BOOL bResult = FALSE; |
| LVITEMA lvItem; |
| |
| if ((nItem >= 0) && (nItem < GETITEMCOUNT(infoPtr))) |
| { |
| ZeroMemory(&lvItem, sizeof(LVITEMA)); |
| lvItem.mask = LVIF_TEXT; |
| lvItem.pszText = lpLVItem->pszText; |
| lvItem.iItem = nItem; |
| lvItem.iSubItem = lpLVItem->iSubItem; |
| bResult = ListView_SetItemA(hwnd, &lvItem); |
| } |
| |
| return bResult; |
| } |
| |
| /*** |
| * DESCRIPTION: |
| * Sets the text background color. |
| * |
| * PARAMETER(S): |
| * [I] HWND : window handle |
| * [I] COLORREF : text background color |
| * |
| * RETURN: |
| * SUCCESS : TRUE |
| * FAILURE : FALSE |
| */ |
| static LRESULT LISTVIEW_SetTextBkColor(HWND hwnd, COLORREF clrTextBk) |
| { |
| LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0); |
| |
| infoPtr->clrTextBk = clrTextBk; |
| |
| return TRUE; |
| } |
| |
| /*** |
| * DESCRIPTION: |
| * Sets the text background color. |
| * |
| * PARAMETER(S): |
| * [I] HWND : window handle |
| * [I] COLORREF : text color |
| * |
| * RETURN: |
| * SUCCESS : TRUE |
| * FAILURE : FALSE |
| */ |
| static LRESULT LISTVIEW_SetTextColor (HWND hwnd, COLORREF clrText) |
| { |
| LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0); |
| |
| infoPtr->clrText = clrText; |
| |
| return TRUE; |
| } |
| |
| /*** |
| * DESCRIPTION: |
| * Sort items. |
| * |
| * PARAMETER(S): |
| * [I] HWND : window handle |
| * |
| * RETURN: |
| * SUCCESS : TRUE |
| * FAILURE : FALSE |
| */ |
| static LRESULT LISTVIEW_SortItems(HWND hwnd, WPARAM wParam, LPARAM lParam) |
| { |
| FIXME (listview, "empty stub!\n"); |
| |
| return TRUE; |
| } |
| |
| /*** |
| * DESCRIPTION: |
| * Updates an items or rearranges the listview control. |
| * |
| * PARAMETER(S): |
| * [I] HWND : window handle |
| * [I] INT : item index |
| * |
| * RETURN: |
| * SUCCESS : TRUE |
| * FAILURE : FALSE |
| */ |
| static LRESULT LISTVIEW_Update(HWND hwnd, INT nItem) |
| { |
| LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0); |
| LONG lStyle = GetWindowLongA(hwnd, GWL_STYLE); |
| BOOL bResult = FALSE; |
| RECT rc; |
| |
| if ((nItem >= 0) && (nItem < GETITEMCOUNT(infoPtr))) |
| { |
| bResult = TRUE; |
| |
| /* rearrange with default alignment style */ |
| if ((lStyle & LVS_AUTOARRANGE) && (((lStyle & LVS_TYPEMASK) == LVS_ICON) || |
| ((lStyle & LVS_TYPEMASK) == LVS_SMALLICON))) |
| { |
| ListView_Arrange(hwnd, 0); |
| } |
| else |
| { |
| /* get item bounding rectangle */ |
| rc.left = LVIR_BOUNDS; |
| ListView_GetItemRect(hwnd, nItem, &rc); |
| InvalidateRect(hwnd, &rc, FALSE); |
| } |
| } |
| |
| return bResult; |
| } |
| |
| /*** |
| * DESCRIPTION: |
| * Creates a listview control. |
| * |
| * PARAMETER(S): |
| * [I] HWND : window handle |
| * |
| * RETURN: |
| * Zero |
| */ |
| static LRESULT LISTVIEW_Create(HWND hwnd, WPARAM wParam, LPARAM lParam) |
| { |
| LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0); |
| LPCREATESTRUCTA lpcs = (LPCREATESTRUCTA)lParam; |
| LOGFONTA logFont; |
| HDLAYOUT hl; |
| WINDOWPOS wp; |
| |
| /* determine the type of structures to use */ |
| infoPtr->notifyFormat = SendMessageA(GetParent(hwnd), WM_NOTIFYFORMAT, |
| (WPARAM)hwnd, (LPARAM)NF_QUERY); |
| if (infoPtr->notifyFormat != NFR_ANSI) |
| { |
| FIXME (listview, "ANSI notify format is NOT used\n"); |
| } |
| |
| /* initialize color information */ |
| infoPtr->clrBk = GetSysColor(COLOR_WINDOW); |
| infoPtr->clrText = GetSysColor(COLOR_WINDOWTEXT); |
| infoPtr->clrTextBk = GetSysColor(COLOR_WINDOW); |
| |
| /* set default values */ |
| infoPtr->uCallbackMask = 0; |
| infoPtr->nFocusedItem = -1; |
| infoPtr->nSelectionMark = -1; |
| infoPtr->iconSize.cx = GetSystemMetrics(SM_CXSMICON); |
| infoPtr->iconSize.cy = GetSystemMetrics(SM_CYSMICON); |
| ZeroMemory(&infoPtr->rcList, sizeof(RECT)); |
| |
| /* get default font (icon title) */ |
| SystemParametersInfoA(SPI_GETICONTITLELOGFONT, 0, &logFont, 0); |
| infoPtr->hDefaultFont = CreateFontIndirectA(&logFont); |
| infoPtr->hFont = infoPtr->hDefaultFont; |
| |
| /* create header */ |
| infoPtr->hwndHeader = CreateWindowA(WC_HEADERA, (LPCSTR)NULL, |
| WS_CHILD | HDS_HORZ | HDS_BUTTONS , |
| 0, 0, 0, 0, hwnd, (HMENU)0, |
| lpcs->hInstance, NULL); |
| |
| /* set header font */ |
| SendMessageA(infoPtr->hwndHeader, WM_SETFONT, (WPARAM)infoPtr->hFont, |
| (LPARAM)TRUE); |
| |
| switch (lpcs->style & LVS_TYPEMASK) |
| { |
| case LVS_REPORT: |
| /* reset header */ |
| hl.prc = &infoPtr->rcList; |
| hl.pwpos = ℘ |
| Header_Layout(infoPtr->hwndHeader, &hl); |
| SetWindowPos(infoPtr->hwndHeader, hwnd, wp.x, wp.y, wp.cx, wp.cy, |
| wp.flags); |
| |
| /* set new top coord */ |
| infoPtr->rcList.top = wp.cy; |
| |
| /* display header */ |
| ShowWindow(infoPtr->hwndHeader, SW_SHOWNORMAL); |
| break; |
| |
| case LVS_LIST: |
| break; |
| |
| default: |
| /* temporary (until there is support) */ |
| SetWindowLongA(hwnd, GWL_STYLE, |
| (lpcs->style & ~LVS_TYPEMASK) | LVS_LIST); |
| } |
| |
| /* TEMPORARY */ |
| LISTVIEW_UnsupportedStyles(lpcs->style); |
| |
| /* allocate memory */ |
| infoPtr->hdpaItems = DPA_Create(10); |
| |
| /* set view dependent information */ |
| LISTVIEW_SetViewInfo(hwnd); |
| |
| return 0; |
| } |
| |
| |
| /*** |
| * DESCRIPTION: |
| * Destroys the window |
| * |
| * PARAMETER(S): |
| * [I] HWND : window handle |
| * |
| * RETURN: |
| * Zero |
| */ |
| static LRESULT LISTVIEW_Destroy(HWND hwnd) |
| { |
| LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO*)GetWindowLongA(hwnd, 0); |
| |
| /* delete all items */ |
| LISTVIEW_DeleteAllItems(hwnd); |
| |
| /* destroy dpa */ |
| DPA_Destroy(infoPtr->hdpaItems); |
| |
| /* destroy header */ |
| if (infoPtr->hwndHeader) |
| { |
| DestroyWindow(infoPtr->hwndHeader); |
| } |
| |
| /* destroy font */ |
| infoPtr->hFont = (HFONT)0; |
| if (infoPtr->hDefaultFont) |
| { |
| DeleteObject(infoPtr->hDefaultFont); |
| } |
| |
| return 0; |
| } |
| |
| /*** |
| * DESCRIPTION: |
| * Erases the background of the listview control |
| * |
| * PARAMETER(S): |
| * [I] HWND : window handle |
| * [I] WPARAM : device context handle |
| * [I] LPARAM : not used |
| * |
| * RETURN: |
| * SUCCESS : TRUE |
| * FAILURE : FALSE |
| */ |
| static LRESULT LISTVIEW_EraseBackground(HWND hwnd, WPARAM wParam, |
| LPARAM lParam) |
| { |
| LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0); |
| BOOL bResult; |
| |
| if (infoPtr->clrBk == CLR_NONE) |
| { |
| bResult = SendMessageA(GetParent(hwnd), WM_ERASEBKGND, wParam, lParam); |
| } |
| else |
| { |
| HBRUSH hBrush = CreateSolidBrush(infoPtr->clrBk); |
| FillRect((HDC)wParam, &infoPtr->rcList, hBrush); |
| DeleteObject(hBrush); |
| bResult = TRUE; |
| } |
| |
| return bResult; |
| } |
| |
| /*** |
| * DESCRIPTION: |
| * Gets the listview control font. |
| * |
| * PARAMETER(S): |
| * [I] HWND : window handle |
| * |
| * RETURN: |
| * Font handle. |
| */ |
| static LRESULT LISTVIEW_GetFont(HWND hwnd) |
| { |
| LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0); |
| |
| return infoPtr->hFont; |
| } |
| |
| /*** |
| * DESCRIPTION: |
| * Performs horizontal scrolling. |
| * |
| * PARAMETER(S): |
| * [I] HWND : window handle |
| * [I] INT : scroll code |
| * [I] INT : scroll position |
| * [I] HWND : scrollbar control window handle |
| * |
| * RETURN: |
| * Zero |
| */ |
| static LRESULT LISTVIEW_VScroll(HWND hwnd, INT nScrollCode, |
| INT nScroll, HWND hScrollWnd) |
| { |
| LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0); |
| LONG lStyle = GetWindowLongA(hwnd, GWL_STYLE); |
| INT nScrollPos, nOldScrollPos; |
| INT nMinRange; |
| INT nMaxRange; |
| |
| GetScrollRange(hwnd, SB_VERT, &nMinRange, &nMaxRange); |
| nOldScrollPos = nScrollPos = GetScrollPos(hwnd, SB_VERT); |
| |
| switch (LVS_TYPEMASK & lStyle) |
| { |
| case LVS_REPORT: |
| switch (nScrollCode) |
| { |
| case SB_LINEUP: |
| if (nScrollPos > nMinRange) |
| { |
| nScrollPos--; |
| } |
| break; |
| case SB_LINEDOWN: |
| if (nScrollPos < nMaxRange) |
| { |
| nScrollPos++; |
| } |
| break; |
| case SB_PAGEUP: |
| if (nScrollPos > nMinRange + infoPtr->nCountPerColumn) |
| { |
| nScrollPos -= infoPtr->nCountPerColumn; |
| } |
| else |
| { |
| nScrollPos = nMinRange; |
| } |
| break; |
| case SB_PAGEDOWN: |
| if (nScrollPos < nMaxRange - infoPtr->nCountPerColumn) |
| { |
| nScrollPos += infoPtr->nCountPerColumn; |
| } |
| else |
| { |
| nScrollPos = nMaxRange; |
| } |
| break; |
| case SB_THUMBPOSITION: |
| nScrollPos = nScroll; |
| break; |
| } |
| break; |
| |
| default: |
| /* TO DO */ |
| } |
| |
| /* set new scroll position */ |
| if (nScrollPos != nOldScrollPos) |
| { |
| SetScrollPos(hwnd, SB_VERT, nScrollPos, TRUE); |
| |
| /* refresh client area */ |
| InvalidateRect(hwnd, NULL, TRUE); |
| } |
| |
| return 0; |
| } |
| |
| |
| /*** |
| * DESCRIPTION: |
| * Performs horizontal scrolling. |
| * |
| * PARAMETER(S): |
| * [I] HWND : window handle |
| * [I] INT : scroll code |
| * [I] INT : scroll position |
| * [I] HWND : scrollbar control window handle |
| * |
| * RETURN: |
| * Zero |
| */ |
| static LRESULT LISTVIEW_HScroll(HWND hwnd, INT nScrollCode, |
| INT nScroll, HWND hScrollWnd) |
| { |
| LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0); |
| LONG lStyle = GetWindowLongA(hwnd, GWL_STYLE); |
| INT nScrollPos, nOldScrollPos; |
| INT nMinRange; |
| INT nMaxRange; |
| |
| GetScrollRange(hwnd, SB_HORZ, &nMinRange, &nMaxRange); |
| nOldScrollPos = nScrollPos = GetScrollPos(hwnd, SB_HORZ); |
| |
| switch (LVS_TYPEMASK & lStyle) |
| { |
| case LVS_LIST: |
| |
| /* list display mode horizontal scrolling */ |
| switch (nScrollCode) |
| { |
| case SB_LINELEFT: |
| if (nScrollPos > nMinRange) |
| { |
| nScrollPos--; |
| } |
| break; |
| case SB_LINERIGHT: |
| if (nScrollPos < nMaxRange) |
| { |
| nScrollPos++; |
| } |
| break; |
| case SB_PAGELEFT: |
| if (nScrollPos > nMinRange) |
| { |
| nScrollPos = max(nMinRange, nScrollPos - infoPtr->nCountPerRow); |
| } |
| else |
| { |
| nScrollPos = nMinRange; |
| } |
| break; |
| case SB_PAGERIGHT: |
| if (nScrollPos < nMaxRange - 1) |
| { |
| nScrollPos = min(nMaxRange, nScrollPos + infoPtr->nCountPerRow); |
| } |
| else |
| { |
| nScrollPos = nMaxRange; |
| } |
| break; |
| case SB_THUMBPOSITION: |
| nScrollPos = nScroll; |
| break; |
| } |
| break; |
| |
| case LVS_REPORT: |
| |
| /* report/details display mode horizontal scrolling */ |
| switch (nScrollCode) |
| { |
| case SB_LINELEFT: |
| if (nScrollPos > nMinRange) |
| { |
| nScrollPos--; |
| } |
| break; |
| case SB_LINERIGHT: |
| if (nScrollPos < nMaxRange) |
| { |
| nScrollPos++; |
| } |
| break; |
| case SB_PAGELEFT: |
| if (nScrollPos > nMinRange) |
| { |
| nScrollPos = max(nMinRange, nScrollPos - infoPtr->rcList.right); |
| } |
| else |
| { |
| nScrollPos = nMinRange; |
| } |
| break; |
| case SB_PAGERIGHT: |
| if (nScrollPos < nMaxRange) |
| { |
| nScrollPos = min(nMaxRange, nScrollPos + infoPtr->rcList.right); |
| } |
| else |
| { |
| nScrollPos = nMaxRange; |
| } |
| break; |
| case SB_THUMBPOSITION: |
| nScrollPos = nScroll; |
| break; |
| } |
| break; |
| |
| default: |
| /* TO DO */ |
| } |
| |
| /* set new scroll position */ |
| if (nScrollPos != nOldScrollPos) |
| { |
| SetScrollPos(hwnd, SB_HORZ, nScrollPos, TRUE); |
| |
| /* refresh client area */ |
| InvalidateRect(hwnd, NULL, TRUE); |
| } |
| |
| return 0; |
| } |
| |
| /*** |
| * DESCRIPTION: |
| * ??? |
| * |
| * PARAMETER(S): |
| * [I] HWND : window handle |
| * [I] INT : virtual key |
| * [I] LONG : key data |
| * |
| * RETURN: |
| * Zero |
| */ |
| static LRESULT LISTVIEW_KeyDown(HWND hwnd, INT nVirtualKey, LONG lKeyData) |
| { |
| LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0); |
| LONG lStyle = GetWindowLongA(hwnd, GWL_STYLE); |
| INT nCtrlId = GetWindowLongA(hwnd, GWL_ID); |
| HWND hwndParent = GetParent(hwnd); |
| NMLVKEYDOWN nmKeyDown; |
| NMHDR nmh; |
| |
| /* send LVN_KEYDOWN notification */ |
| ZeroMemory(&nmKeyDown, sizeof(NMLVKEYDOWN)); |
| nmKeyDown.hdr.hwndFrom = hwnd; |
| nmKeyDown.hdr.idFrom = nCtrlId; |
| nmKeyDown.hdr.code = LVN_KEYDOWN; |
| nmKeyDown.wVKey = nVirtualKey; |
| nmKeyDown.flags = 0; |
| SendMessageA(hwndParent, WM_NOTIFY, (WPARAM)nCtrlId, (LPARAM)&nmKeyDown); |
| |
| /* initialize */ |
| nmh.hwndFrom = hwnd; |
| nmh.idFrom = nCtrlId; |
| |
| switch (nVirtualKey) |
| { |
| case VK_RETURN: |
| if ((GETITEMCOUNT(infoPtr) > 0) && (infoPtr->nFocusedItem != -1)) |
| { |
| /* send NM_RETURN notification */ |
| nmh.code = NM_RETURN; |
| ListView_Notify(hwndParent, nCtrlId, &nmh); |
| |
| /* send LVN_ITEMACTIVATE notification */ |
| nmh.code = LVN_ITEMACTIVATE; |
| ListView_Notify(hwndParent, nCtrlId, &nmh); |
| } |
| break; |
| |
| case VK_HOME: |
| if (GETITEMCOUNT(infoPtr) > 0) |
| { |
| LISTVIEW_KeySelection(hwnd, 0); |
| } |
| break; |
| |
| case VK_END: |
| if (GETITEMCOUNT(infoPtr) > 0) |
| { |
| LISTVIEW_KeySelection(hwnd, GETITEMCOUNT(infoPtr) - 1); |
| } |
| break; |
| |
| case VK_LEFT: |
| switch (LVS_TYPEMASK & lStyle) |
| { |
| case LVS_LIST: |
| if (infoPtr->nFocusedItem >= infoPtr->nCountPerColumn) |
| { |
| LISTVIEW_KeySelection(hwnd, infoPtr->nFocusedItem - infoPtr->nCountPerColumn); |
| } |
| break; |
| case LVS_REPORT: |
| break; |
| |
| default: |
| if (infoPtr->nFocusedItem % infoPtr->nCountPerRow != 0) |
| { |
| LISTVIEW_SetSelection(hwnd, infoPtr->nFocusedItem - 1); |
| } |
| } |
| break; |
| |
| case VK_UP: |
| switch (LVS_TYPEMASK & lStyle) |
| { |
| case LVS_LIST: |
| case LVS_REPORT: |
| if (infoPtr->nFocusedItem > 0) |
| { |
| LISTVIEW_KeySelection(hwnd, infoPtr->nFocusedItem - 1); |
| } |
| break; |
| |
| default: |
| if (infoPtr->nFocusedItem >= infoPtr->nCountPerRow) |
| { |
| LISTVIEW_SetSelection(hwnd, infoPtr->nFocusedItem - |
| infoPtr->nCountPerRow); |
| } |
| } |
| break; |
| |
| case VK_RIGHT: |
| switch (LVS_TYPEMASK & lStyle) |
| { |
| case LVS_LIST: |
| if (infoPtr->nFocusedItem < |
| (GETITEMCOUNT(infoPtr) - infoPtr->nCountPerColumn)) |
| { |
| LISTVIEW_KeySelection(hwnd, infoPtr->nFocusedItem + |
| infoPtr->nCountPerColumn); |
| } |
| case LVS_REPORT: |
| break; |
| |
| default: |
| if (infoPtr->nCountPerRow > 0) |
| { |
| } |
| } |
| break; |
| |
| case VK_DOWN: |
| switch (LVS_TYPEMASK & lStyle) |
| { |
| case LVS_LIST: |
| case LVS_REPORT: |
| if (infoPtr->nFocusedItem < GETITEMCOUNT(infoPtr) - 1) |
| { |
| LISTVIEW_KeySelection(hwnd, infoPtr->nFocusedItem + 1); |
| } |
| default: |
| if (infoPtr->nCountPerRow > 0) |
| { |
| } |
| } |
| break; |
| |
| case VK_PRIOR: |
| break; |
| |
| case VK_NEXT: |
| break; |
| } |
| |
| /* refresh client area */ |
| InvalidateRect(hwnd, NULL, TRUE); |
| |
| return 0; |
| } |
| |
| /*** |
| * DESCRIPTION: |
| * Kills the focus. |
| * |
| * PARAMETER(S): |
| * [I] HWND : window handle |
| * |
| * RETURN: |
| * Zero |
| */ |
| static LRESULT LISTVIEW_KillFocus(HWND hwnd) |
| { |
| LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO*)GetWindowLongA(hwnd, 0); |
| INT nCtrlId = GetWindowLongA(hwnd, GWL_ID); |
| NMHDR nmh; |
| |
| /* send NM_KILLFOCUS notification */ |
| nmh.hwndFrom = hwnd; |
| nmh.idFrom = nCtrlId; |
| nmh.code = NM_KILLFOCUS; |
| ListView_Notify(GetParent(hwnd), nCtrlId, &nmh); |
| |
| /* set window focus flag */ |
| infoPtr->bFocus = FALSE; |
| |
| return 0; |
| } |
| |
| /*** |
| * DESCRIPTION: |
| * Left mouse button double click. |
| * |
| * PARAMETER(S): |
| * [I] HWND : window handle |
| * [I] WORD : key flag |
| * [I] WORD : x coordinate |
| * [I] WORD : y coordinate |
| * |
| * RETURN: |
| * Zero |
| */ |
| static LRESULT LISTVIEW_LButtonDblClk(HWND hwnd, WORD wKey, WORD wPosX, |
| WORD wPosY) |
| { |
| LONG nCtrlId = GetWindowLongA(hwnd, GWL_ID); |
| NMHDR nmh; |
| |
| /* send NM_DBLCLK notification */ |
| nmh.hwndFrom = hwnd; |
| nmh.idFrom = nCtrlId; |
| nmh.code = NM_DBLCLK; |
| ListView_Notify(GetParent(hwnd), nCtrlId, &nmh); |
| |
| /* send LVN_ITEMACTIVATE notification */ |
| nmh.code = LVN_ITEMACTIVATE; |
| ListView_Notify(GetParent(hwnd), nCtrlId, &nmh); |
| |
| return 0; |
| } |
| |
| /*** |
| * DESCRIPTION: |
| * Left mouse button down. |
| * |
| * PARAMETER(S): |
| * [I] HWND : window handle |
| * [I] WORD : key flag |
| * [I] WORD : x coordinate |
| * [I] WORD : y coordinate |
| * |
| * RETURN: |
| * Zero |
| */ |
| static LRESULT LISTVIEW_LButtonDown(HWND hwnd, WORD wKey, WORD wPosX, |
| WORD wPosY) |
| { |
| LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0); |
| INT nCtrlId = GetWindowLongA(hwnd, GWL_ID); |
| LVHITTESTINFO hitTestInfo; |
| NMHDR nmh; |
| INT nItem; |
| static BOOL bGroupSelect = TRUE; |
| |
| /* send NM_RELEASEDCAPTURE notification */ |
| nmh.hwndFrom = hwnd; |
| nmh.idFrom = nCtrlId; |
| nmh.code = NM_RELEASEDCAPTURE; |
| ListView_Notify(GetParent(hwnd), nCtrlId, &nmh); |
| |
| if (infoPtr->bFocus == FALSE) |
| { |
| SetFocus(hwnd); |
| } |
| |
| /* set left button down flag */ |
| infoPtr->bLButtonDown = TRUE; |
| |
| /* set left button hit coordinates */ |
| hitTestInfo.pt.x = wPosX; |
| hitTestInfo.pt.y = wPosY; |
| |
| /* perform hit test */ |
| nItem = ListView_HitTest(hwnd, &hitTestInfo); |
| if ((nItem >= 0) && (nItem < GETITEMCOUNT(infoPtr))) |
| { |
| if ((wKey & MK_CONTROL) && (wKey & MK_SHIFT)) |
| { |
| if (bGroupSelect == TRUE) |
| { |
| LISTVIEW_AddGroupSelection(hwnd, nItem); |
| } |
| else |
| { |
| LISTVIEW_AddSelection(hwnd, nItem); |
| } |
| } |
| else if (wKey & MK_CONTROL) |
| { |
| bGroupSelect = LISTVIEW_ToggleSelection(hwnd, nItem); |
| } |
| else if (wKey & MK_SHIFT) |
| { |
| LISTVIEW_SetGroupSelection(hwnd, nItem); |
| } |
| else |
| { |
| LISTVIEW_SetSelection(hwnd, nItem); |
| } |
| } |
| else |
| { |
| /* remove all selections */ |
| LISTVIEW_RemoveSelections(hwnd, 0, GETITEMCOUNT(infoPtr)); |
| } |
| |
| InvalidateRect(hwnd, NULL, TRUE); |
| |
| return 0; |
| } |
| |
| /*** |
| * DESCRIPTION: |
| * Left mouse button up. |
| * |
| * PARAMETER(S): |
| * [I] HWND : window handle |
| * [I] WORD : key flag |
| * [I] WORD : x coordinate |
| * [I] WORD : y coordinate |
| * |
| * RETURN: |
| * Zero |
| */ |
| static LRESULT LISTVIEW_LButtonUp(HWND hwnd, WORD wKey, WORD wPosX, |
| WORD wPosY) |
| { |
| LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0); |
| INT nCtrlId = GetWindowLongA(hwnd, GWL_ID); |
| NMHDR nmh; |
| |
| if (infoPtr->bLButtonDown == TRUE) |
| { |
| /* send NM_CLICK notification */ |
| nmh.hwndFrom = hwnd; |
| nmh.idFrom = nCtrlId; |
| nmh.code = NM_CLICK; |
| ListView_Notify(GetParent(hwnd), nCtrlId, &nmh); |
| |
| /* set left button flag */ |
| infoPtr->bLButtonDown = FALSE; |
| } |
| |
| return 0; |
| } |
| |
| /*** |
| * DESCRIPTION: |
| * Creates the listview control (called before WM_CREATE). |
| * |
| * PARAMETER(S): |
| * [I] HWND : window handle |
| * [I] WPARAM : unhandled |
| * [I] LPARAM : widow creation info |
| * |
| * RETURN: |
| * Zero |
| */ |
| static LRESULT LISTVIEW_NCCreate(HWND hwnd, WPARAM wParam, LPARAM lParam) |
| { |
| LISTVIEW_INFO *infoPtr; |
| |
| /* allocate memory for info structure */ |
| infoPtr = (LISTVIEW_INFO *)COMCTL32_Alloc(sizeof(LISTVIEW_INFO)); |
| SetWindowLongA(hwnd, 0, (LONG)infoPtr); |
| if (infoPtr == NULL) |
| { |
| ERR(listview, "could not allocate info memory!\n"); |
| return 0; |
| } |
| |
| if ((LISTVIEW_INFO *)GetWindowLongA(hwnd, 0) != infoPtr) |
| { |
| ERR(listview, "pointer assignment error!\n"); |
| return 0; |
| } |
| |
| return DefWindowProcA(hwnd, WM_NCCREATE, wParam, lParam); |
| } |
| |
| /*** |
| * DESCRIPTION: |
| * Destroys the listview control (called after WM_DESTROY). |
| * |
| * PARAMETER(S): |
| * [I] HWND : window handle |
| * |
| * RETURN: |
| * Zero |
| */ |
| static LRESULT LISTVIEW_NCDestroy(HWND hwnd) |
| { |
| LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0); |
| |
| /* free listview info */ |
| COMCTL32_Free(infoPtr); |
| |
| return 0; |
| } |
| |
| /*** |
| * DESCRIPTION: |
| * Handles notification from children. |
| * |
| * PARAMETER(S): |
| * [I] HWND : window handle |
| * [I] INT : control identifier |
| * [I] LPNMHDR : notification information |
| * |
| * RETURN: |
| * Zero |
| */ |
| static LRESULT LISTVIEW_Notify(HWND hwnd, INT nCtrlId, LPNMHDR lpnmh) |
| { |
| LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0); |
| |
| if (lpnmh->hwndFrom == infoPtr->hwndHeader) |
| { |
| /* handle notification from header control */ |
| if (lpnmh->code == HDN_ENDTRACKA) |
| { |
| InvalidateRect(hwnd, NULL, TRUE); |
| } |
| } |
| |
| return 0; |
| } |
| |
| static LRESULT LISTVIEW_NotifyFormat(HWND hwndFrom, HWND hwnd, INT nCommand) |
| { |
| LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0); |
| |
| if (nCommand == NF_REQUERY) |
| { |
| /* determine the type of structures to use */ |
| infoPtr->notifyFormat = SendMessageA(hwndFrom, WM_NOTIFYFORMAT, |
| (WPARAM)hwnd, (LPARAM)NF_QUERY); |
| if (infoPtr->notifyFormat == NFR_UNICODE) |
| { |
| FIXME (listview, "NO support for unicode structures"); |
| } |
| } |
| |
| return 0; |
| } |
| |
| /*** |
| * DESCRIPTION: |
| * Draws the listview control. |
| * |
| * PARAMETER(S): |
| * [I] HWND : window handle |
| * [I] HDC : device context handle |
| * |
| * RETURN: |
| * Zero |
| */ |
| static LRESULT LISTVIEW_Paint(HWND hwnd, HDC hdc) |
| { |
| PAINTSTRUCT ps; |
| |
| if (hdc == 0) |
| { |
| hdc = BeginPaint(hwnd, &ps); |
| LISTVIEW_Refresh(hwnd, hdc); |
| EndPaint(hwnd, &ps); |
| } |
| else |
| { |
| LISTVIEW_Refresh(hwnd, hdc); |
| } |
| |
| return 0; |
| } |
| |
| /*** |
| * DESCRIPTION: |
| * Right mouse button double click. |
| * |
| * PARAMETER(S): |
| * [I] HWND : window handle |
| * [I] WORD : key flag |
| * [I] WORD : x coordinate |
| * [I] WORD : y coordinate |
| * |
| * RETURN: |
| * Zero |
| */ |
| static LRESULT LISTVIEW_RButtonDblClk(HWND hwnd, WORD wKey, WORD wPosX, |
| WORD wPosY) |
| { |
| INT nCtrlId = GetWindowLongA(hwnd, GWL_ID); |
| NMHDR nmh; |
| |
| /* send NM_RELEASEDCAPTURE notification */ |
| nmh.hwndFrom = hwnd; |
| nmh.idFrom = nCtrlId; |
| nmh.code = NM_RELEASEDCAPTURE; |
| ListView_Notify(GetParent(hwnd), nCtrlId, &nmh); |
| |
| /* send NM_RDBLCLK notification */ |
| nmh.code = NM_RDBLCLK; |
| ListView_Notify(GetParent(hwnd), nCtrlId, &nmh); |
| |
| return 0; |
| } |
| |
| /*** |
| * DESCRIPTION: |
| * Right mouse button input. |
| * |
| * PARAMETER(S): |
| * [I] HWND : window handle |
| * [I] WORD : key flag |
| * [I] WORD : x coordinate |
| * [I] WORD : y coordinate |
| * |
| * RETURN: |
| * Zero |
| */ |
| static LRESULT LISTVIEW_RButtonDown(HWND hwnd, WORD wKey, WORD wPosX, |
| WORD wPosY) |
| { |
| LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0); |
| INT nCtrlId = GetWindowLongA(hwnd, GWL_ID); |
| LVHITTESTINFO hitTestInfo; |
| NMHDR nmh; |
| INT nItem; |
| |
| /* send NM_RELEASEDCAPTURE notification */ |
| nmh.hwndFrom = hwnd; |
| nmh.idFrom = nCtrlId; |
| nmh.code = NM_RELEASEDCAPTURE; |
| ListView_Notify(GetParent(hwnd), nCtrlId, &nmh); |
| |
| /* make sure the listview control window has the focus */ |
| if (infoPtr->bFocus == FALSE) |
| { |
| SetFocus(hwnd); |
| } |
| |
| /* set right button down flag */ |
| infoPtr->bRButtonDown = TRUE; |
| |
| /* set hit coordinates */ |
| hitTestInfo.pt.x = wPosX; |
| hitTestInfo.pt.y = wPosY; |
| |
| /* perform hit test */ |
| nItem = ListView_HitTest(hwnd, &hitTestInfo); |
| if ((nItem >= 0) && (nItem < GETITEMCOUNT(infoPtr))) |
| { |
| if (!((wKey & MK_SHIFT) || (wKey & MK_CONTROL))) |
| { |
| LISTVIEW_SetSelection(hwnd, nItem); |
| } |
| } |
| else |
| { |
| LISTVIEW_RemoveSelections(hwnd, 0, GETITEMCOUNT(infoPtr)); |
| } |
| |
| return 0; |
| } |
| |
| /*** |
| * DESCRIPTION: |
| * Right mouse button up. |
| * |
| * PARAMETER(S): |
| * [I] HWND : window handle |
| * [I] WORD : key flag |
| * [I] WORD : x coordinate |
| * [I] WORD : y coordinate |
| * |
| * RETURN: |
| * Zero |
| */ |
| static LRESULT LISTVIEW_RButtonUp(HWND hwnd, WORD wKey, WORD wPosX, |
| WORD wPosY) |
| { |
| LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0); |
| INT nCtrlId = GetWindowLongA(hwnd, GWL_ID); |
| NMHDR nmh; |
| |
| if (infoPtr->bRButtonDown == TRUE) |
| { |
| /* send NM_RClICK notification */ |
| ZeroMemory(&nmh, sizeof(NMHDR)); |
| nmh.hwndFrom = hwnd; |
| nmh.idFrom = nCtrlId; |
| nmh.code = NM_RCLICK; |
| ListView_Notify(GetParent(hwnd), nCtrlId, &nmh); |
| |
| /* set button flag */ |
| infoPtr->bRButtonDown = FALSE; |
| } |
| |
| return 0; |
| } |
| |
| /*** |
| * DESCRIPTION: |
| * Sets the focus. |
| * |
| * PARAMETER(S): |
| * [I] HWND : window handle |
| * [I] HWND : window handle of previously focused window |
| * |
| * RETURN: |
| * Zero |
| */ |
| static LRESULT LISTVIEW_SetFocus(HWND hwnd, HWND hwndLoseFocus) |
| { |
| LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0); |
| INT nCtrlId = GetWindowLongA(hwnd, GWL_ID); |
| NMHDR nmh; |
| |
| /* send NM_SETFOCUS notification */ |
| nmh.hwndFrom = hwnd; |
| nmh.idFrom = nCtrlId; |
| nmh.code = NM_SETFOCUS; |
| ListView_Notify(GetParent(hwnd), nCtrlId, &nmh); |
| |
| /* set window focus flag */ |
| infoPtr->bFocus = TRUE; |
| |
| return 0; |
| } |
| |
| /*** |
| * DESCRIPTION: |
| * Sets the font. |
| * |
| * PARAMETER(S): |
| * [I] HWND : window handle |
| * [I] HFONT : font handle |
| * [I] WORD : redraw flag |
| * |
| * RETURN: |
| * Zero |
| */ |
| static LRESULT LISTVIEW_SetFont(HWND hwnd, HFONT hFont, WORD fRedraw) |
| { |
| LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0); |
| LONG lStyle = GetWindowLongA(hwnd, GWL_STYLE); |
| |
| if (hFont == 0) |
| { |
| infoPtr->hFont = infoPtr->hDefaultFont; |
| } |
| else |
| { |
| infoPtr->hFont = hFont; |
| } |
| |
| if ((LVS_TYPEMASK & lStyle ) == LVS_REPORT) |
| { |
| /* set header font */ |
| SendMessageA(infoPtr->hwndHeader, WM_SETFONT, (WPARAM)hFont, |
| MAKELPARAM(fRedraw, 0)); |
| } |
| |
| /* invalidate listview control client area */ |
| InvalidateRect(hwnd, NULL, FALSE); |
| |
| if (fRedraw == TRUE) |
| { |
| UpdateWindow(hwnd); |
| } |
| |
| return 0; |
| } |
| |
| /*** |
| * DESCRIPTION: |
| * Resizes the listview control. |
| * |
| * PARAMETER(S): |
| * [I] HWND : window handle |
| * [I] WORD : new width |
| * [I] WORD : new height |
| * |
| * RETURN: |
| * Zero |
| */ |
| static LRESULT LISTVIEW_Size(HWND hwnd, WORD wWidth, WORD wHeight) |
| { |
| LISTVIEW_SetSize(hwnd, GetWindowLongA(hwnd, GWL_STYLE), wWidth, wHeight); |
| LISTVIEW_SetViewInfo(hwnd); |
| LISTVIEW_SetScroll(hwnd); |
| |
| /* invalidate + erase background */ |
| InvalidateRect(hwnd, NULL, TRUE); |
| |
| return 0; |
| } |
| |
| /*** |
| * DESCRIPTION: |
| * Sets the size information for a given style. |
| * |
| * PARAMETER(S): |
| * [I] HWND : window handle |
| * [I] LONG : window style |
| * [I] WORD : new width |
| * [I] WORD : new height |
| * |
| * RETURN: |
| * Zero |
| */ |
| static VOID LISTVIEW_SetSize(HWND hwnd, LONG lStyle, LONG lWidth, LONG lHeight) |
| { |
| LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0); |
| HDLAYOUT hl; |
| WINDOWPOS wp; |
| INT lTop = 0; |
| RECT rc; |
| |
| switch (lStyle & LVS_TYPEMASK) |
| { |
| case LVS_LIST: |
| if ((lStyle & LVS_TYPEMASK) == LVS_LIST) |
| { |
| if (!(lStyle & WS_HSCROLL)) |
| { |
| INT nHScrollHeight; |
| |
| nHScrollHeight = GetSystemMetrics(SM_CYHSCROLL); |
| if (lHeight > nHScrollHeight) |
| { |
| lHeight -= nHScrollHeight; |
| } |
| } |
| } |
| break; |
| |
| case LVS_REPORT: |
| rc.left = 0; |
| rc.top = 0; |
| rc.right = lWidth; |
| rc.bottom = lHeight; |
| hl.prc = &rc; |
| hl.pwpos = ℘ |
| Header_Layout(infoPtr->hwndHeader, &hl); |
| lTop = wp.cy; |
| break; |
| } |
| |
| infoPtr->rcList.top = lTop; |
| infoPtr->rcList.left = 0; |
| infoPtr->rcList.bottom = lHeight; |
| infoPtr->rcList.right = lWidth; |
| } |
| |
| /*** |
| * DESCRIPTION: |
| * Notification sent when the window style is modified. |
| * |
| * PARAMETER(S): |
| * [I] HWND : window handle |
| * [I] WPARAM : window style type (normal or extended) |
| * [I] LPSTYLESTRUCT : window style information |
| * |
| * RETURN: |
| * Zero |
| */ |
| static INT LISTVIEW_StyleChanged(HWND hwnd, WPARAM wStyleType, |
| LPSTYLESTRUCT lpss) |
| { |
| LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0); |
| HDLAYOUT hl; |
| WINDOWPOS wp; |
| HDC hdc; |
| RECT rc; |
| HBRUSH hBrush; |
| |
| if (wStyleType == GWL_STYLE) |
| { |
| /* remove vertical scrollbar */ |
| if (lpss->styleOld & WS_VSCROLL) |
| { |
| ShowScrollBar(hwnd, SB_VERT, FALSE); |
| } |
| |
| /* remove horizontal scrollbar */ |
| if (lpss->styleOld & WS_HSCROLL) |
| { |
| ShowScrollBar(hwnd, SB_HORZ, FALSE); |
| } |
| |
| if ((LVS_TYPEMASK & lpss->styleOld) == LVS_REPORT) |
| { |
| /* hide header */ |
| ShowWindow(infoPtr->hwndHeader, SW_HIDE); |
| } |
| |
| /* erase everything */ |
| GetClientRect(hwnd, &rc); |
| hdc = GetDC(hwnd); |
| hBrush = CreateSolidBrush(infoPtr->clrBk); |
| FillRect(hdc, &rc, hBrush); |
| DeleteObject(hBrush); |
| ReleaseDC(hwnd, hdc); |
| |
| if ((lpss->styleNew & LVS_TYPEMASK) == LVS_REPORT) |
| { |
| hl.prc = &rc; |
| hl.pwpos = ℘ |
| Header_Layout(infoPtr->hwndHeader, &hl); |
| SetWindowPos(infoPtr->hwndHeader, hwnd, wp.x, wp.y, wp.cx, wp.cy, |
| wp.flags); |
| ShowWindow(infoPtr->hwndHeader, SW_SHOWNORMAL); |
| } |
| else if (((lpss->styleNew & LVS_TYPEMASK) == LVS_ICON) || |
| ((lpss->styleNew & LVS_TYPEMASK) == LVS_SMALLICON)) |
| { |
| /* for NOW (it's only temporary) */ |
| SetWindowLongA(hwnd, GWL_STYLE, (lpss->styleNew&~LVS_TYPEMASK)|LVS_LIST); |
| } |
| |
| /* TEMPORARY */ |
| LISTVIEW_UnsupportedStyles(lpss->styleNew); |
| |
| /* set new size */ |
| LISTVIEW_SetSize(hwnd, lpss->styleNew, rc.right, rc.bottom); |
| |
| /* recalculate attributes */ |
| LISTVIEW_SetViewInfo(hwnd); |
| |
| /* set scrollbars, if needed */ |
| LISTVIEW_SetScroll(hwnd); |
| |
| /* invalidate + erase background */ |
| InvalidateRect(hwnd, NULL, TRUE); |
| } |
| |
| return 0; |
| } |
| |
| /*** |
| * DESCRIPTION: |
| * Window procedure of the listview control. |
| * |
| * PARAMETER(S): |
| * [I] HWND : |
| * [I] UINT : |
| * [I] WPARAM : |
| * [I] LPARAM : |
| * |
| * RETURN: |
| * |
| */ |
| LRESULT WINAPI LISTVIEW_WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, |
| LPARAM lParam) |
| { |
| switch (uMsg) |
| { |
| case LVM_APPROXIMATEVIEWRECT: |
| return LISTVIEW_ApproximateViewRect(hwnd, (INT)wParam, |
| LOWORD(lParam), HIWORD(lParam)); |
| case LVM_ARRANGE: |
| return LISTVIEW_Arrange(hwnd, (INT)wParam); |
| |
| /* case LVM_CREATEDRAGIMAGE: */ |
| |
| case LVM_DELETEALLITEMS: |
| return LISTVIEW_DeleteAllItems(hwnd); |
| |
| case LVM_DELETECOLUMN: |
| return LISTVIEW_DeleteColumn(hwnd, (INT)wParam); |
| |
| case LVM_DELETEITEM: |
| return LISTVIEW_DeleteItem(hwnd, (INT)wParam); |
| |
| /* case LVM_EDITLABEL: */ |
| |
| case LVM_ENSUREVISIBLE: |
| return LISTVIEW_EnsureVisible(hwnd, (INT)wParam, (BOOL)lParam); |
| |
| case LVM_FINDITEMA: |
| return LISTVIEW_FindItem(hwnd, (INT)wParam, (LPLVFINDINFO)lParam); |
| |
| case LVM_GETBKCOLOR: |
| return LISTVIEW_GetBkColor(hwnd); |
| |
| /* case LVM_GETBKIMAGE: */ |
| |
| case LVM_GETCALLBACKMASK: |
| return LISTVIEW_GetCallbackMask(hwnd); |
| |
| case LVM_GETCOLUMNA: |
| return LISTVIEW_GetColumnA(hwnd, (INT)wParam, (LPLVCOLUMNA)lParam); |
| |
| /* case LVM_GETCOLUMNW: */ |
| /* case LVM_GETCOLUMNORDERARRAY: */ |
| |
| case LVM_GETCOLUMNWIDTH: |
| return LISTVIEW_GetColumnWidth(hwnd, (INT)wParam); |
| |
| case LVM_GETCOUNTPERPAGE: |
| return LISTVIEW_GetCountPerPage(hwnd); |
| |
| /* case LVM_GETEDITCONTROL: */ |
| /* case LVM_GETEXTENDEDLISTVIEWSTYLE: */ |
| |
| case LVM_GETHEADER: |
| return LISTVIEW_GetHeader(hwnd); |
| |
| /* case LVM_GETHOTCURSOR: */ |
| /* case LVM_GETHOTITEM: */ |
| /* case LVM_GETHOVERTIME: */ |
| |
| case LVM_GETIMAGELIST: |
| return LISTVIEW_GetImageList(hwnd, (INT)wParam); |
| |
| /* case LVM_GETISEARCHSTRING: */ |
| |
| case LVM_GETITEMA: |
| return LISTVIEW_GetItemA(hwnd, (LPLVITEMA)lParam); |
| |
| /* case LVM_GETITEMW: */ |
| |
| case LVM_GETITEMCOUNT: |
| return LISTVIEW_GetItemCount(hwnd); |
| |
| case LVM_GETITEMPOSITION: |
| return LISTVIEW_GetItemPosition(hwnd, (INT)wParam, (LPPOINT)lParam); |
| |
| case LVM_GETITEMRECT: |
| return LISTVIEW_GetItemRect(hwnd, (INT)wParam, (LPRECT)lParam); |
| |
| case LVM_GETITEMSPACING: |
| return LISTVIEW_GetItemSpacing(hwnd, (BOOL)wParam); |
| |
| case LVM_GETITEMSTATE: |
| return LISTVIEW_GetItemState(hwnd, (INT)wParam, (UINT)lParam); |
| |
| case LVM_GETITEMTEXTA: |
| LISTVIEW_GetItemTextA(hwnd, (INT)wParam, (LPLVITEMA)lParam); |
| break; |
| |
| /* case LVM_GETITEMTEXTW: */ |
| |
| case LVM_GETNEXTITEM: |
| return LISTVIEW_GetNextItem(hwnd, (INT)wParam, LOWORD(lParam)); |
| |
| /* case LVM_GETNUMBEROFWORKAREAS: */ |
| case LVM_GETORIGIN: |
| return LISTVIEW_GetOrigin(hwnd, (LPPOINT)lParam); |
| |
| case LVM_GETSELECTEDCOUNT: |
| return LISTVIEW_GetSelectedCount(hwnd); |
| |
| case LVM_GETSELECTIONMARK: |
| return LISTVIEW_GetSelectionMark(hwnd); |
| |
| case LVM_GETSTRINGWIDTHA: |
| return LISTVIEW_GetStringWidthA (hwnd, (LPCSTR)lParam); |
| |
| /* case LVM_GETSTRINGWIDTHW: */ |
| /* case LVM_GETSUBITEMRECT: */ |
| |
| case LVM_GETTEXTBKCOLOR: |
| return LISTVIEW_GetTextBkColor(hwnd); |
| |
| case LVM_GETTEXTCOLOR: |
| return LISTVIEW_GetTextColor(hwnd); |
| |
| /* case LVM_GETTOOLTIPS: */ |
| |
| case LVM_GETTOPINDEX: |
| return LISTVIEW_GetTopIndex(hwnd); |
| |
| /* case LVM_GETUNICODEFORMAT: */ |
| |
| case LVM_GETVIEWRECT: |
| return LISTVIEW_GetViewRect(hwnd, (LPRECT)lParam); |
| |
| /* case LVM_GETWORKAREAS: */ |
| |
| case LVM_HITTEST: |
| return LISTVIEW_HitTest(hwnd, (LPLVHITTESTINFO)lParam); |
| |
| case LVM_INSERTCOLUMNA: |
| return LISTVIEW_InsertColumnA(hwnd, (INT)wParam, |
| (LPLVCOLUMNA)lParam); |
| |
| /* case LVM_INSERTCOLUMNW: */ |
| |
| case LVM_INSERTITEMA: |
| return LISTVIEW_InsertItemA(hwnd, (LPLVITEMA)lParam); |
| |
| /* case LVM_INSERTITEMW: */ |
| |
| case LVM_REDRAWITEMS: |
| return LISTVIEW_RedrawItems(hwnd, (INT)wParam, (INT)lParam); |
| |
| case LVM_SCROLL: |
| return LISTVIEW_Scroll(hwnd, (INT)wParam, (INT)lParam); |
| |
| case LVM_SETBKCOLOR: |
| return LISTVIEW_SetBkColor(hwnd, (COLORREF)lParam); |
| |
| /* case LVM_SETBKIMAGE: */ |
| |
| case LVM_SETCALLBACKMASK: |
| return LISTVIEW_SetCallbackMask(hwnd, (UINT)wParam); |
| |
| case LVM_SETCOLUMNA: |
| return LISTVIEW_SetColumnA(hwnd, (INT)wParam, (LPLVCOLUMNA)lParam); |
| |
| /* case LVM_SETCOLUMNW: */ |
| /* case LVM_SETCOLUMNORDERARRAY: */ |
| /* case LVM_SETCOLUMNWIDTH: */ |
| /* case LVM_SETEXTENDEDLISTVIEWSTYLE: */ |
| /* case LVM_SETHOTCURSOR: */ |
| /* case LVM_SETHOTITEM: */ |
| /* case LVM_SETHOVERTIME: */ |
| /* case LVM_SETICONSPACING: */ |
| |
| case LVM_SETIMAGELIST: |
| return LISTVIEW_SetImageList(hwnd, (INT)wParam, (HIMAGELIST)lParam); |
| |
| case LVM_SETITEMA: |
| return LISTVIEW_SetItemA(hwnd, (LPLVITEMA)lParam); |
| |
| /* case LVM_SETITEMW: */ |
| |
| case LVM_SETITEMCOUNT: |
| LISTVIEW_SetItemCount(hwnd, (INT)wParam); |
| break; |
| |
| case LVM_SETITEMPOSITION: |
| return LISTVIEW_SetItemPosition(hwnd, (INT)wParam, (INT)LOWORD(lParam), |
| (INT)HIWORD(lParam)); |
| |
| /* case LVM_SETITEMPOSITION: */ |
| |
| case LVM_SETITEMSTATE: |
| return LISTVIEW_SetItemState(hwnd, (INT)wParam, (LPLVITEMA)lParam); |
| |
| case LVM_SETITEMTEXTA: |
| return LISTVIEW_SetItemTextA(hwnd, (INT)wParam, (LPLVITEMA)lParam); |
| |
| /* case LVM_SETSELECTIONMARK: */ |
| |
| case LVM_SETTEXTBKCOLOR: |
| return LISTVIEW_SetTextBkColor(hwnd, (COLORREF)lParam); |
| |
| case LVM_SETTEXTCOLOR: |
| return LISTVIEW_SetTextColor(hwnd, (COLORREF)lParam); |
| |
| /* case LVM_SETTOOLTIPS: */ |
| /* case LVM_SETUNICODEFORMAT: */ |
| /* case LVM_SETWORKAREAS: */ |
| |
| case LVM_SORTITEMS: |
| return LISTVIEW_SortItems(hwnd, wParam, lParam); |
| |
| /* case LVM_SUBITEMHITTEST: */ |
| |
| case LVM_UPDATE: |
| return LISTVIEW_Update(hwnd, (INT)wParam); |
| |
| /* case WM_CHAR: */ |
| /* case WM_COMMAND: */ |
| |
| case WM_CREATE: |
| return LISTVIEW_Create(hwnd, wParam, lParam); |
| |
| case WM_DESTROY: |
| return LISTVIEW_Destroy(hwnd); |
| |
| case WM_ERASEBKGND: |
| return LISTVIEW_EraseBackground(hwnd, wParam, lParam); |
| |
| case WM_GETDLGCODE: |
| return DLGC_WANTTAB | DLGC_WANTARROWS; |
| |
| case WM_GETFONT: |
| return LISTVIEW_GetFont(hwnd); |
| |
| case WM_HSCROLL: |
| return LISTVIEW_HScroll(hwnd, (INT)LOWORD(wParam), |
| (INT)HIWORD(wParam), (HWND)lParam); |
| |
| case WM_KEYDOWN: |
| return LISTVIEW_KeyDown(hwnd, (INT)wParam, (LONG)lParam); |
| |
| case WM_KILLFOCUS: |
| return LISTVIEW_KillFocus(hwnd); |
| |
| case WM_LBUTTONDBLCLK: |
| return LISTVIEW_LButtonDblClk(hwnd, (WORD)wParam, LOWORD(lParam), |
| HIWORD(lParam)); |
| |
| case WM_LBUTTONDOWN: |
| return LISTVIEW_LButtonDown(hwnd, (WORD)wParam, LOWORD(lParam), |
| HIWORD(lParam)); |
| case WM_LBUTTONUP: |
| return LISTVIEW_LButtonUp(hwnd, (WORD)wParam, LOWORD(lParam), |
| HIWORD(lParam)); |
| |
| /* case WM_MOUSEMOVE: */ |
| /* return LISTVIEW_MouseMove (hwnd, wParam, lParam); */ |
| |
| case WM_NCCREATE: |
| return LISTVIEW_NCCreate(hwnd, wParam, lParam); |
| |
| case WM_NCDESTROY: |
| return LISTVIEW_NCDestroy(hwnd); |
| |
| case WM_NOTIFY: |
| return LISTVIEW_Notify(hwnd, (INT)wParam, (LPNMHDR)lParam); |
| |
| case WM_NOTIFYFORMAT: |
| return LISTVIEW_NotifyFormat(hwnd, (HWND)wParam, (INT)lParam); |
| |
| case WM_PAINT: |
| return LISTVIEW_Paint(hwnd, (HDC)wParam); |
| |
| case WM_RBUTTONDBLCLK: |
| return LISTVIEW_RButtonDblClk(hwnd, (WORD)wParam, LOWORD(lParam), |
| HIWORD(lParam)); |
| |
| case WM_RBUTTONDOWN: |
| return LISTVIEW_RButtonDown(hwnd, (WORD)wParam, LOWORD(lParam), |
| HIWORD(lParam)); |
| |
| case WM_RBUTTONUP: |
| return LISTVIEW_RButtonUp(hwnd, (WORD)wParam, LOWORD(lParam), |
| HIWORD(lParam)); |
| |
| case WM_SETFOCUS: |
| return LISTVIEW_SetFocus(hwnd, (HWND)wParam); |
| |
| case WM_SETFONT: |
| return LISTVIEW_SetFont(hwnd, (HFONT)wParam, (WORD)lParam); |
| |
| /* case WM_SETREDRAW: */ |
| |
| case WM_SIZE: |
| return LISTVIEW_Size(hwnd, LOWORD(lParam), HIWORD(lParam)); |
| |
| case WM_STYLECHANGED: |
| return LISTVIEW_StyleChanged(hwnd, wParam, (LPSTYLESTRUCT)lParam); |
| |
| /* case WM_TIMER: */ |
| |
| case WM_VSCROLL: |
| return LISTVIEW_VScroll(hwnd, (INT)LOWORD(wParam), |
| (INT)HIWORD(wParam), (HWND)lParam); |
| |
| /* case WM_WINDOWPOSCHANGED: */ |
| /* case WM_WININICHANGE: */ |
| |
| default: |
| if (uMsg >= WM_USER) |
| { |
| ERR(listview, "unknown msg %04x wp=%08x lp=%08lx\n", |
| uMsg, wParam, lParam); |
| } |
| |
| /* call default window procedure */ |
| return DefWindowProcA(hwnd, uMsg, wParam, lParam); |
| } |
| |
| return 0; |
| } |
| |
| /*** |
| * DESCRIPTION:` |
| * Registers the window class. |
| * |
| * PARAMETER(S): |
| * None |
| * |
| * RETURN: |
| * None |
| */ |
| VOID LISTVIEW_Register(VOID) |
| { |
| WNDCLASSA wndClass; |
| |
| if (!GlobalFindAtomA(WC_LISTVIEWA)) |
| { |
| ZeroMemory(&wndClass, sizeof(WNDCLASSA)); |
| wndClass.style = CS_GLOBALCLASS | CS_DBLCLKS; |
| wndClass.lpfnWndProc = (WNDPROC)LISTVIEW_WindowProc; |
| wndClass.cbClsExtra = 0; |
| wndClass.cbWndExtra = sizeof(LISTVIEW_INFO *); |
| wndClass.hCursor = LoadCursorA(0, IDC_ARROWA); |
| wndClass.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1); |
| wndClass.lpszClassName = WC_LISTVIEWA; |
| RegisterClassA (&wndClass); |
| } |
| } |
| |
| /*** |
| * DESCRIPTION: |
| * Unregisters the window class. |
| * |
| * PARAMETER(S): |
| * None |
| * |
| * RETURN: |
| * None |
| */ |
| VOID LISTVIEW_Unregister(VOID) |
| { |
| if (GlobalFindAtomA(WC_LISTVIEWA)) |
| UnregisterClassA(WC_LISTVIEWA, (HINSTANCE)NULL); |
| } |
| |