[PATCH 08/16] Implement LVS_EX_HEADERINALLVIEWS
Nikolay Sivov
bunglehead at gmail.com
Fri Nov 27 06:38:05 CST 2009
---
dlls/comctl32/listview.c | 96 ++++++++++++++++++++++++++++-----------
dlls/comctl32/tests/listview.c | 65 +++++++++++++++++++++++++++
2 files changed, 134 insertions(+), 27 deletions(-)
diff --git a/dlls/comctl32/listview.c b/dlls/comctl32/listview.c
index c95ba67..df48272 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 1b6fcab..bccddc2 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);
--
1.5.6.5
--=-CsVwlKjGuis0pU79WqBl--
More information about the wine-patches
mailing list