Nikolay Sivov : comctl32/listview: Implement LVS_EX_HEADERINALLVIEWS.

Alexandre Julliard julliard at winehq.org
Mon Nov 30 10:42:49 CST 2009


Module: wine
Branch: master
Commit: 999810566b5459be83fe3f8fc28540f60097a1f6
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=999810566b5459be83fe3f8fc28540f60097a1f6

Author: Nikolay Sivov <bunglehead at gmail.com>
Date:   Fri Nov 27 15:38:05 2009 +0300

comctl32/listview: Implement LVS_EX_HEADERINALLVIEWS.

---

 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 = &wp;
+	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 = &wp;
-	    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..651b941 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);
 




More information about the wine-cvs mailing list