diff --git a/dlls/comctl32/listview.c b/dlls/comctl32/listview.c index c95ba67debe..df482725190 100644 --- a/dlls/comctl32/listview.c +++ b/dlls/comctl32/listview.c @@ -1588,6 +1588,13 @@ static inline void LISTVIEW_GetHeaderRect(const LISTVIEW_INFO *infoPtr, INT nSub { *lprc = LISTVIEW_GetColumnInfo(infoPtr, nSubItem)->rcHeader; } + +static inline BOOL LISTVIEW_IsHeaderEnabled(const LISTVIEW_INFO *infoPtr) +{ + return (infoPtr->uView == LV_VIEW_DETAILS || + infoPtr->dwLvExStyle & LVS_EX_HEADERINALLVIEWS) && + !(infoPtr->dwStyle & LVS_NOCOLUMNHEADER); +} static inline BOOL LISTVIEW_GetItemW(const LISTVIEW_INFO *infoPtr, LPLVITEMW lpLVItem) { @@ -1926,7 +1933,23 @@ static void LISTVIEW_UpdateScroll(const LISTVIEW_INFO *infoPtr) if (LISTVIEW_GetViewRect(infoPtr, &rcView)) horzInfo.nMax = rcView.right - rcView.left; } - + + if (LISTVIEW_IsHeaderEnabled(infoPtr)) + { + if (DPA_GetPtrCount(infoPtr->hdpaColumns)) + { + RECT rcHeader; + INT index; + + index = SendMessageW(infoPtr->hwndHeader, HDM_ORDERTOINDEX, + DPA_GetPtrCount(infoPtr->hdpaColumns) - 1, 0); + + LISTVIEW_GetHeaderRect(infoPtr, index, &rcHeader); + horzInfo.nMax = rcHeader.right; + TRACE("horzInfo.nMax=%d\n", horzInfo.nMax); + } + } + horzInfo.fMask = SIF_RANGE | SIF_PAGE; horzInfo.nMax = max(horzInfo.nMax - 1, 0); dx = GetScrollPos(infoPtr->hwndSelf, SB_HORZ); @@ -1976,7 +1999,7 @@ static void LISTVIEW_UpdateScroll(const LISTVIEW_INFO *infoPtr) } /* Update the Header Control */ - if (infoPtr->uView == LV_VIEW_DETAILS) + if (infoPtr->hwndHeader) { horzInfo.fMask = SIF_POS; GetScrollInfo(infoPtr->hwndSelf, SB_HORZ, &horzInfo); @@ -8171,6 +8194,16 @@ static DWORD LISTVIEW_SetExtendedListViewStyle(LISTVIEW_INFO *infoPtr, DWORD dwM LISTVIEW_SetBkColor(infoPtr, CLR_NONE); } + if((infoPtr->dwLvExStyle ^ dwOldExStyle) & LVS_EX_HEADERINALLVIEWS) + { + if (infoPtr->dwLvExStyle & LVS_EX_HEADERINALLVIEWS) + LISTVIEW_CreateHeader(infoPtr); + else + ShowWindow(infoPtr->hwndHeader, SW_HIDE); + LISTVIEW_UpdateSize(infoPtr); + LISTVIEW_UpdateScroll(infoPtr); + } + LISTVIEW_InvalidateList(infoPtr); return dwOldExStyle; } @@ -9412,21 +9445,20 @@ static LRESULT LISTVIEW_HScroll(LISTVIEW_INFO *infoPtr, INT nScrollCode, scrollInfo.fMask = SIF_POS; scrollInfo.nPos = nNewScrollPos; nNewScrollPos = SetScrollInfo(infoPtr->hwndSelf, SB_HORZ, &scrollInfo, TRUE); - + /* carry on only if it really changed */ if (nNewScrollPos == nOldScrollPos) return 0; - - if (infoPtr->uView == LV_VIEW_DETAILS) - LISTVIEW_UpdateHeaderSize(infoPtr, nNewScrollPos); - + + if (infoPtr->hwndHeader) LISTVIEW_UpdateHeaderSize(infoPtr, nNewScrollPos); + /* now adjust to client coordinates */ nScrollDiff = nOldScrollPos - nNewScrollPos; if (infoPtr->uView == LV_VIEW_LIST) nScrollDiff *= infoPtr->nItemWidth; - + /* and scroll the window */ scroll_list(infoPtr, nScrollDiff, 0); - return 0; + return 0; } static LRESULT LISTVIEW_MouseWheel(LISTVIEW_INFO *infoPtr, INT wheelDelta) @@ -10077,6 +10109,9 @@ static LRESULT LISTVIEW_HeaderNotification(LISTVIEW_INFO *infoPtr, const NMHEADE case HDN_DIVIDERDBLCLICKW: case HDN_DIVIDERDBLCLICKA: + /* FIXME: for LVS_EX_HEADERINALLVIEWS and not LV_VIEW_DETAILS + we should use LVSCW_AUTOSIZE_USEHEADER, helper rework or + split needed for that */ LISTVIEW_SetColumnWidth(infoPtr, lpnmh->iItem, LVSCW_AUTOSIZE); notify_forward_header(infoPtr, lpnmh); break; @@ -10568,27 +10603,34 @@ static void LISTVIEW_UpdateSize(LISTVIEW_INFO *infoPtr) infoPtr->rcList.bottom -= GetSystemMetrics(SM_CYHSCROLL); infoPtr->rcList.bottom = max (infoPtr->rcList.bottom - 2, 0); } - else if (infoPtr->uView == LV_VIEW_DETAILS) + + /* if control created invisible header isn't created */ + if (infoPtr->hwndHeader) { - /* if control created invisible header isn't created */ - if (infoPtr->hwndHeader) + HDLAYOUT hl; + WINDOWPOS wp; + + hl.prc = &infoPtr->rcList; + hl.pwpos = ℘ + SendMessageW( infoPtr->hwndHeader, HDM_LAYOUT, 0, (LPARAM)&hl ); + TRACE(" wp.flags=0x%08x, wp=%d,%d (%dx%d)\n", wp.flags, wp.x, wp.y, wp.cx, wp.cy); + + if (LISTVIEW_IsHeaderEnabled(infoPtr)) + wp.flags |= SWP_SHOWWINDOW; + else { - HDLAYOUT hl; - WINDOWPOS wp; - - hl.prc = &infoPtr->rcList; - hl.pwpos = ℘ - SendMessageW( infoPtr->hwndHeader, HDM_LAYOUT, 0, (LPARAM)&hl ); - TRACE(" wp.flags=0x%08x, wp=%d,%d (%dx%d)\n", wp.flags, wp.x, wp.y, wp.cx, wp.cy); - SetWindowPos(wp.hwnd, wp.hwndInsertAfter, wp.x, wp.y, wp.cx, wp.cy, - wp.flags | ((infoPtr->dwStyle & LVS_NOCOLUMNHEADER) - ? SWP_HIDEWINDOW : SWP_SHOWWINDOW)); - TRACE(" after SWP wp=%d,%d (%dx%d)\n", wp.x, wp.y, wp.cx, wp.cy); - - infoPtr->rcList.top = max(wp.cy, 0); + wp.flags |= SWP_HIDEWINDOW; + wp.cy = 0; } - infoPtr->rcList.top += (infoPtr->dwLvExStyle & LVS_EX_GRIDLINES) ? 2 : 0; + + SetWindowPos(wp.hwnd, wp.hwndInsertAfter, wp.x, wp.y, wp.cx, wp.cy, wp.flags); + TRACE(" after SWP wp=%d,%d (%dx%d)\n", wp.x, wp.y, wp.cx, wp.cy); + + infoPtr->rcList.top = max(wp.cy, 0); } + /* extra padding for grid */ + if (infoPtr->uView == LV_VIEW_DETAILS && infoPtr->dwLvExStyle & LVS_EX_GRIDLINES) + infoPtr->rcList.top += 2; TRACE(" rcList=%s\n", wine_dbgstr_rect(&infoPtr->rcList)); } @@ -10669,7 +10711,7 @@ static INT LISTVIEW_StyleChanged(LISTVIEW_INFO *infoPtr, WPARAM wStyleType, LISTVIEW_UpdateItemSize(infoPtr); } - if (uNewView == LVS_REPORT) + if (uNewView == LVS_REPORT || infoPtr->dwLvExStyle & LVS_EX_HEADERINALLVIEWS) { if ((lpss->styleOld ^ lpss->styleNew) & LVS_NOCOLUMNHEADER) { diff --git a/dlls/comctl32/tests/listview.c b/dlls/comctl32/tests/listview.c index 1b6fcab1c7f..651b941a1c1 100644 --- a/dlls/comctl32/tests/listview.c +++ b/dlls/comctl32/tests/listview.c @@ -1253,6 +1253,8 @@ static void test_create(void) LVCOLUMNA col; RECT rect; WNDCLASSEX cls; + DWORD style; + cls.cbSize = sizeof(WNDCLASSEX); ok(GetClassInfoEx(GetModuleHandle(NULL), "SysListView32", &cls), "GetClassInfoEx failed\n"); listviewWndProc = cls.lpfnWndProc; @@ -1292,6 +1294,8 @@ static void test_create(void) hHeader = (HWND)SendMessage(hList, LVM_GETHEADER, 0, 0); ok(IsWindow(hHeader), "Header should be created\n"); ok(hHeader == GetDlgItem(hList, 0), "Expected header as dialog item\n"); + style = GetWindowLong(hHeader, GWL_STYLE); + ok(!(style & HDS_HIDDEN), "Not expected HDS_HIDDEN\n"); DestroyWindow(hList); hList = CreateWindow("SysListView32", "Test", WS_VISIBLE|LVS_LIST, 0, 0, 100, 100, NULL, NULL, @@ -4183,6 +4187,66 @@ static void test_finditem(void) DestroyWindow(hwnd); } +static void test_LVS_EX_HEADERINALLVIEWS(void) +{ + HWND hwnd, header; + DWORD style; + + hwnd = create_custom_listview_control(LVS_ICON); + + SendMessage(hwnd, LVM_SETEXTENDEDLISTVIEWSTYLE, LVS_EX_HEADERINALLVIEWS, + LVS_EX_HEADERINALLVIEWS); + + header = (HWND)SendMessage(hwnd, LVM_GETHEADER, 0, 0); + if (!IsWindow(header)) + { + win_skip("LVS_EX_HEADERINALLVIEWS unsupported\n"); + DestroyWindow(hwnd); + return; + } + + /* LVS_NOCOLUMNHEADER works as before */ + style = GetWindowLongA(hwnd, GWL_STYLE); + SetWindowLongW(hwnd, GWL_STYLE, style | LVS_NOCOLUMNHEADER); + style = GetWindowLongA(header, GWL_STYLE); + ok(style & HDS_HIDDEN, "Expected HDS_HIDDEN\n"); + style = GetWindowLongA(hwnd, GWL_STYLE); + SetWindowLongW(hwnd, GWL_STYLE, style & ~LVS_NOCOLUMNHEADER); + style = GetWindowLongA(header, GWL_STYLE); + ok(!(style & HDS_HIDDEN), "Expected HDS_HIDDEN to be unset\n"); + + /* try to remove style */ + SendMessage(hwnd, LVM_SETEXTENDEDLISTVIEWSTYLE, LVS_EX_HEADERINALLVIEWS, 0); + header = (HWND)SendMessage(hwnd, LVM_GETHEADER, 0, 0); + ok(IsWindow(header), "Expected header to be created\n"); + style = GetWindowLongA(header, GWL_STYLE); + ok(!(style & HDS_HIDDEN), "HDS_HIDDEN not expected\n"); + + DestroyWindow(hwnd); + + /* check other styles */ + hwnd = create_custom_listview_control(LVS_LIST); + SendMessage(hwnd, LVM_SETEXTENDEDLISTVIEWSTYLE, LVS_EX_HEADERINALLVIEWS, + LVS_EX_HEADERINALLVIEWS); + header = (HWND)SendMessage(hwnd, LVM_GETHEADER, 0, 0); + ok(IsWindow(header), "Expected header to be created\n"); + DestroyWindow(hwnd); + + hwnd = create_custom_listview_control(LVS_SMALLICON); + SendMessage(hwnd, LVM_SETEXTENDEDLISTVIEWSTYLE, LVS_EX_HEADERINALLVIEWS, + LVS_EX_HEADERINALLVIEWS); + header = (HWND)SendMessage(hwnd, LVM_GETHEADER, 0, 0); + ok(IsWindow(header), "Expected header to be created\n"); + DestroyWindow(hwnd); + + hwnd = create_custom_listview_control(LVS_REPORT); + SendMessage(hwnd, LVM_SETEXTENDEDLISTVIEWSTYLE, LVS_EX_HEADERINALLVIEWS, + LVS_EX_HEADERINALLVIEWS); + header = (HWND)SendMessage(hwnd, LVM_GETHEADER, 0, 0); + ok(IsWindow(header), "Expected header to be created\n"); + DestroyWindow(hwnd); +} + START_TEST(listview) { HMODULE hComctl32; @@ -4270,6 +4334,7 @@ START_TEST(listview) test_mapidindex(); test_scrollnotify(); test_LVS_EX_TRANSPARENTBKGND(); + test_LVS_EX_HEADERINALLVIEWS(); unload_v6_module(ctx_cookie, hCtx);