comctl32/listview: Implement delayed header creation for ListView control

Nikolay Sivov bunglehead at gmail.com
Tue Apr 7 11:59:15 CDT 2009


http://bugs.winehq.org/show_bug.cgi?id=4175

Changelog:
    - Implement delayed header creation for ListView control
    - Some typos in tests corrected

>From 99d191a22bc6b839233ba157080a66a5363c5687 Mon Sep 17 00:00:00 2001
From: Nikolay Sivov <bunglehead at gmail.com>
Date: Tue, 7 Apr 2009 12:15:21 -0400
Subject: Implement delayed header creation for ListView control

---
 dlls/comctl32/listview.c       |   96 ++++++++++++++++++++++++++++++++-------
 dlls/comctl32/tests/listview.c |   20 ++++----
 2 files changed, 88 insertions(+), 28 deletions(-)

diff --git a/dlls/comctl32/listview.c b/dlls/comctl32/listview.c
index 9d1b4ff..f06095b 100644
--- a/dlls/comctl32/listview.c
+++ b/dlls/comctl32/listview.c
@@ -1374,7 +1374,34 @@ static inline COLUMN_INFO * LISTVIEW_GetColumnInfo(const LISTVIEW_INFO *infoPtr,
     assert (nSubItem >= 0 && nSubItem < DPA_GetPtrCount(infoPtr->hdpaColumns));
     return DPA_GetPtr(infoPtr->hdpaColumns, nSubItem);
 }
-	
+
+static INT LISTVIEW_CreateHeader(LISTVIEW_INFO *infoPtr)
+{
+    DWORD dFlags = WS_CHILD | HDS_HORZ | HDS_FULLDRAG | HDS_DRAGDROP;
+    HINSTANCE hInst;
+
+    if (infoPtr->hwndHeader) return 0;
+
+    /* setup creation flags */
+    dFlags |= (LVS_NOSORTHEADER & infoPtr->dwStyle) ? 0 : HDS_BUTTONS;
+    dFlags |= (LVS_NOCOLUMNHEADER & infoPtr->dwStyle) ? HDS_HIDDEN : 0;
+
+    hInst = (HINSTANCE)GetWindowLongPtrW(infoPtr->hwndSelf, GWLP_HINSTANCE);
+
+    /* create header */
+    infoPtr->hwndHeader = CreateWindowW(WC_HEADERW, NULL, dFlags,
+      0, 0, 0, 0, infoPtr->hwndSelf, NULL, hInst, NULL);
+    if (!infoPtr->hwndHeader) return -1;
+
+    /* set header unicode format */
+    SendMessageW(infoPtr->hwndHeader, HDM_SETUNICODEFORMAT, TRUE, 0);
+
+    /* set header font */
+    SendMessageW(infoPtr->hwndHeader, WM_SETFONT, (WPARAM)infoPtr->hFont, (LPARAM)TRUE);
+
+    return 0;
+}
+
 static inline void LISTVIEW_GetHeaderRect(const LISTVIEW_INFO *infoPtr, INT nSubItem, LPRECT lprc)
 {
     *lprc = LISTVIEW_GetColumnInfo(infoPtr, nSubItem)->rcHeader;
@@ -6859,6 +6886,7 @@ static INT LISTVIEW_InsertColumnT(LISTVIEW_INFO *infoPtr, INT nColumn,
     COLUMN_INFO *lpColumnInfo;
     INT nNewColumn;
     HDITEMW hdi;
+    UINT uView = infoPtr->dwStyle & LVS_TYPEMASK;
 
     TRACE("(nColumn=%d, lpColumn=%s, isW=%d)\n", nColumn, debuglvcolumn_t(lpColumn, isW), isW);
 
@@ -6887,6 +6915,14 @@ static INT LISTVIEW_InsertColumnT(LISTVIEW_INFO *infoPtr, INT nColumn,
         hdi.lParam = lpColumn->iSubItem;
     }
 
+    /* create header if not present */
+    LISTVIEW_CreateHeader(infoPtr);
+    if (!(LVS_NOCOLUMNHEADER & infoPtr->dwStyle) &&
+         (LVS_REPORT == uView) && (WS_VISIBLE & infoPtr->dwStyle))
+    {
+        ShowWindow(infoPtr->hwndHeader, SW_SHOWNORMAL);
+    }
+
     /* insert item in header control */
     nNewColumn = SendMessageW(infoPtr->hwndHeader, 
 		              isW ? HDM_INSERTITEMW : HDM_INSERTITEMA,
@@ -8079,7 +8115,6 @@ static LRESULT LISTVIEW_Create(HWND hwnd, const CREATESTRUCTW *lpcs)
 {
   LISTVIEW_INFO *infoPtr = (LISTVIEW_INFO *)GetWindowLongPtrW(hwnd, 0);
   UINT uView = lpcs->style & LVS_TYPEMASK;
-  DWORD dFlags = WS_CHILD | HDS_HORZ | HDS_FULLDRAG | HDS_DRAGDROP;
 
   TRACE("(lpcs=%p)\n", lpcs);
 
@@ -8087,28 +8122,19 @@ static LRESULT LISTVIEW_Create(HWND hwnd, const CREATESTRUCTW *lpcs)
   infoPtr->notifyFormat = SendMessageW(infoPtr->hwndNotify, WM_NOTIFYFORMAT,
                                        (WPARAM)infoPtr->hwndSelf, (LPARAM)NF_QUERY);
 
-  /* setup creation flags */
-  dFlags |= (LVS_NOSORTHEADER & lpcs->style) ? 0 : HDS_BUTTONS;
-  dFlags |= (LVS_NOCOLUMNHEADER & lpcs->style) ? HDS_HIDDEN : 0;
-
-  /* create header */
-  infoPtr->hwndHeader = CreateWindowW(WC_HEADERW, NULL, dFlags,
-    0, 0, 0, 0, hwnd, NULL,
-    lpcs->hInstance, NULL);
-  if (!infoPtr->hwndHeader) return -1;
-
-  /* set header unicode format */
-  SendMessageW(infoPtr->hwndHeader, HDM_SETUNICODEFORMAT, TRUE, 0);
-
-  /* set header font */
-  SendMessageW(infoPtr->hwndHeader, WM_SETFONT, (WPARAM)infoPtr->hFont, (LPARAM)TRUE);
+  if ((uView == LVS_REPORT) && (lpcs->style & WS_VISIBLE))
+  {
+    if (LISTVIEW_CreateHeader(infoPtr) < 0)  return -1;
+  }
+  else
+    infoPtr->hwndHeader = 0;
 
   /* init item size to avoid division by 0 */
   LISTVIEW_UpdateItemSize (infoPtr);
 
   if (uView == LVS_REPORT)
   {
-    if (!(LVS_NOCOLUMNHEADER & lpcs->style))
+    if (!(LVS_NOCOLUMNHEADER & lpcs->style) && (WS_VISIBLE & lpcs->style))
     {
       ShowWindow(infoPtr->hwndHeader, SW_SHOWNORMAL);
     }
@@ -9553,6 +9579,8 @@ static INT LISTVIEW_StyleChanged(LISTVIEW_INFO *infoPtr, WPARAM wStyleType,
             HDLAYOUT hl;
             WINDOWPOS wp;
 
+            LISTVIEW_CreateHeader( infoPtr );
+
             hl.prc = &infoPtr->rcList;
             hl.pwpos = &wp;
             SendMessageW( infoPtr->hwndHeader, HDM_LAYOUT, 0, (LPARAM)&hl );
@@ -9603,6 +9631,34 @@ static INT LISTVIEW_StyleChanged(LISTVIEW_INFO *infoPtr, WPARAM wStyleType,
 
 /***
  * DESCRIPTION:
+ * Processes WM_SHOWWINDOW messages.
+ *
+ * PARAMETER(S):
+ * [I] infoPtr : valid pointer to the listview structure
+ * [I] bShown  : window is being shown (FALSE when hidden)
+ * [I] iStatus : window show status
+ *
+ * RETURN:
+ * Zero
+ */
+static LRESULT LISTVIEW_ShowWindow(LISTVIEW_INFO *infoPtr, BOOL bShown, INT iStatus)
+{
+  UINT uView = infoPtr->dwStyle & LVS_TYPEMASK;
+
+  /* header delayed creation */
+  if ((uView == LVS_REPORT) && bShown)
+  {
+    LISTVIEW_CreateHeader(infoPtr);
+
+    if (!(LVS_NOCOLUMNHEADER & infoPtr->dwStyle))
+      ShowWindow(infoPtr->hwndHeader, SW_SHOWNORMAL);
+  }
+
+  return 0;
+}
+
+/***
+ * DESCRIPTION:
  * Window procedure of the listview control.
  *
  */
@@ -10064,6 +10120,10 @@ LISTVIEW_WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
   case WM_SETREDRAW:
     return LISTVIEW_SetRedraw(infoPtr, (BOOL)wParam);
 
+  case WM_SHOWWINDOW:
+    LISTVIEW_ShowWindow(infoPtr, (BOOL)wParam, (INT)lParam);
+    return DefWindowProcW(hwnd, uMsg, wParam, lParam);
+
   case WM_SIZE:
     return LISTVIEW_Size(infoPtr, (short)LOWORD(lParam), (short)HIWORD(lParam));
 
diff --git a/dlls/comctl32/tests/listview.c b/dlls/comctl32/tests/listview.c
index 84db3d2..6f3524b 100644
--- a/dlls/comctl32/tests/listview.c
+++ b/dlls/comctl32/tests/listview.c
@@ -787,8 +787,8 @@ static void test_create(void)
     hList = CreateWindow("SysListView32", "Test", WS_VISIBLE, 0, 0, 100, 100, NULL, NULL,
                           GetModuleHandle(NULL), 0);
     hHeader = (HWND)SendMessage(hList, LVM_GETHEADER, 0, 0);
-    todo_wine ok(!IsWindow(hHeader), "Header shouldn't be created\n");
-    todo_wine ok(NULL == GetDlgItem(hList, 0), "NULL dialog item expected\n");
+    ok(!IsWindow(hHeader), "Header shouldn't be created\n");
+    ok(NULL == GetDlgItem(hList, 0), "NULL dialog item expected\n");
     /* insert column */
     memset(&col, 0, sizeof(LVCOLUMNA));
     col.mask = LVCF_WIDTH;
@@ -803,8 +803,8 @@ static void test_create(void)
     hList = CreateWindow("SysListView32", "Test", WS_VISIBLE|LVS_LIST, 0, 0, 100, 100, NULL, NULL,
                           GetModuleHandle(NULL), 0);
     hHeader = (HWND)SendMessage(hList, LVM_GETHEADER, 0, 0);
-    todo_wine ok(!IsWindow(hHeader), "Header shouldn't be created\n");
-    todo_wine ok(NULL == GetDlgItem(hList, 0), "NULL dialog item expected\n");
+    ok(!IsWindow(hHeader), "Header shouldn't be created\n");
+    ok(NULL == GetDlgItem(hList, 0), "NULL dialog item expected\n");
     /* insert column */
     memset(&col, 0, sizeof(LVCOLUMNA));
     col.mask = LVCF_WIDTH;
@@ -851,8 +851,8 @@ static void test_create(void)
     hList = CreateWindow("SysListView32", "Test", LVS_REPORT, 0, 0, 100, 100, NULL, NULL,
                           GetModuleHandle(NULL), 0);
     hHeader = (HWND)SendMessage(hList, LVM_GETHEADER, 0, 0);
-    todo_wine ok(!IsWindow(hHeader), "Header shouldn't be created\n");
-    todo_wine ok(NULL == GetDlgItem(hList, 0), "NULL dialog item expected\n");
+    ok(!IsWindow(hHeader), "Header shouldn't be created\n");
+    ok(NULL == GetDlgItem(hList, 0), "NULL dialog item expected\n");
     /* insert column */
     memset(&col, 0, sizeof(LVCOLUMNA));
     col.mask = LVCF_WIDTH;
@@ -868,12 +868,12 @@ static void test_create(void)
     hList = CreateWindow("SysListView32", "Test", LVS_REPORT, 0, 0, 100, 100, NULL, NULL,
                           GetModuleHandle(NULL), 0);
     hHeader = (HWND)SendMessage(hList, LVM_GETHEADER, 0, 0);
-    todo_wine ok(!IsWindow(hHeader), "Header shouldn't be created\n");
-    todo_wine ok(NULL == GetDlgItem(hList, 0), "NULL dialog item expected\n");
+    ok(!IsWindow(hHeader), "Header shouldn't be created\n");
+    ok(NULL == GetDlgItem(hList, 0), "NULL dialog item expected\n");
     ShowWindow(hList, SW_SHOW);
     hHeader = (HWND)SendMessage(hList, LVM_GETHEADER, 0, 0);
-    ok(IsWindow(hHeader), "Header shouldn't be created\n");
-    ok(hHeader == GetDlgItem(hList, 0), "NULL dialog item expected\n");
+    ok(IsWindow(hHeader), "Header should be created\n");
+    ok(hHeader == GetDlgItem(hList, 0), "Expected header as dialog item\n");
     DestroyWindow(hList);
 }
 
-- 
1.5.6.5





More information about the wine-patches mailing list