David Hedberg : comdlg32: Add a container for custom controls.

Alexandre Julliard julliard at winehq.org
Fri May 27 11:03:40 CDT 2011


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

Author: David Hedberg <david.hedberg at gmail.com>
Date:   Fri May 27 04:05:50 2011 +0200

comdlg32: Add a container for custom controls.

---

 dlls/comdlg32/itemdlg.c       |  131 ++++++++++++++++++++++++++++++++++++++++-
 dlls/comdlg32/tests/itemdlg.c |   33 ++++++++++
 2 files changed, 161 insertions(+), 3 deletions(-)

diff --git a/dlls/comdlg32/itemdlg.c b/dlls/comdlg32/itemdlg.c
index a1d61e8..920353b 100644
--- a/dlls/comdlg32/itemdlg.c
+++ b/dlls/comdlg32/itemdlg.c
@@ -98,6 +98,8 @@ typedef struct FileDialogImpl {
     LPWSTR custom_okbutton;
     LPWSTR custom_cancelbutton;
     LPWSTR custom_filenamelabel;
+
+    HWND cctrls_hwnd;
 } FileDialogImpl;
 
 /**************************************************************************
@@ -486,6 +488,104 @@ static void ctrl_resize(HWND hctrl, UINT min_width, UINT max_width)
 }
 
 /**************************************************************************
+ * Container functions.
+ */
+static UINT ctrl_container_resize(FileDialogImpl *This, UINT container_width)
+{
+    return 0;
+}
+
+static void ctrl_container_reparent(FileDialogImpl *This, HWND parent)
+{
+    LONG wndstyle;
+
+    if(parent)
+    {
+        wndstyle = GetWindowLongW(This->cctrls_hwnd, GWL_STYLE);
+        wndstyle &= ~(WS_POPUP);
+        wndstyle |= WS_CHILD;
+        SetWindowLongW(This->cctrls_hwnd, GWL_STYLE, wndstyle);
+
+        SetParent(This->cctrls_hwnd, parent);
+        ShowWindow(This->cctrls_hwnd, TRUE);
+    }
+    else
+    {
+        ShowWindow(This->cctrls_hwnd, FALSE);
+
+        wndstyle = GetWindowLongW(This->cctrls_hwnd, GWL_STYLE);
+        wndstyle &= ~(WS_CHILD);
+        wndstyle |= WS_POPUP;
+        SetWindowLongW(This->cctrls_hwnd, GWL_STYLE, wndstyle);
+
+        SetParent(This->cctrls_hwnd, NULL);
+    }
+}
+
+static LRESULT ctrl_container_on_create(HWND hwnd, CREATESTRUCTW *crs)
+{
+    FileDialogImpl *This = crs->lpCreateParams;
+    TRACE("%p\n", This);
+
+    SetWindowLongPtrW(hwnd, GWLP_USERDATA, (LPARAM)This);
+    return TRUE;
+}
+
+static LRESULT ctrl_container_on_wm_destroy(FileDialogImpl *This)
+{
+    TRACE("%p", This);
+    return TRUE;
+}
+
+static LRESULT CALLBACK ctrl_container_wndproc(HWND hwnd, UINT umessage, WPARAM wparam, LPARAM lparam)
+{
+    FileDialogImpl *This = (FileDialogImpl*)GetWindowLongPtrW(hwnd, GWLP_USERDATA);
+
+    switch(umessage)
+    {
+    case WM_NCCREATE:         return ctrl_container_on_create(hwnd, (CREATESTRUCTW*)lparam);
+    case WM_DESTROY:          return ctrl_container_on_wm_destroy(This);
+    default:                  return DefWindowProcW(hwnd, umessage, wparam, lparam);
+    }
+
+    return FALSE;
+}
+
+static HRESULT init_custom_controls(FileDialogImpl *This)
+{
+    WNDCLASSW wc;
+    static const WCHAR ctrl_container_classname[] =
+        {'i','d','l','g','_','c','o','n','t','a','i','n','e','r','_','p','a','n','e',0};
+
+    if( !GetClassInfoW(COMDLG32_hInstance, ctrl_container_classname, &wc) )
+    {
+        wc.style            = CS_HREDRAW | CS_VREDRAW;
+        wc.lpfnWndProc      = ctrl_container_wndproc;
+        wc.cbClsExtra       = 0;
+        wc.cbWndExtra       = 0;
+        wc.hInstance        = COMDLG32_hInstance;
+        wc.hIcon            = 0;
+        wc.hCursor          = LoadCursorW(0, (LPWSTR)IDC_ARROW);
+        wc.hbrBackground    = (HBRUSH)(COLOR_BTNFACE + 1);
+        wc.lpszMenuName     = NULL;
+        wc.lpszClassName    = ctrl_container_classname;
+
+        if(!RegisterClassW(&wc)) return E_FAIL;
+    }
+
+    This->cctrls_hwnd = CreateWindowExW(0, ctrl_container_classname, NULL,
+                                        WS_CLIPSIBLINGS | WS_CLIPCHILDREN,
+                                        0, 0, 0, 0, NULL, 0,
+                                        COMDLG32_hInstance, (void*)This);
+    if(!This->cctrls_hwnd)
+        return E_FAIL;
+
+    SetWindowLongW(This->cctrls_hwnd, GWL_STYLE, WS_TABSTOP);
+
+    return S_OK;
+}
+
+/**************************************************************************
  * Window related functions.
  */
 static SIZE update_layout(FileDialogImpl *This)
@@ -495,7 +595,7 @@ static SIZE update_layout(FileDialogImpl *This)
     RECT dialog_rc;
     RECT cancel_rc, open_rc;
     RECT filetype_rc, filename_rc, filenamelabel_rc;
-    RECT toolbar_rc, ebrowser_rc;
+    RECT toolbar_rc, ebrowser_rc, customctrls_rc;
     int missing_width, missing_height;
     static const UINT vspacing = 4, hspacing = 4;
     SIZE ret;
@@ -606,22 +706,35 @@ static SIZE update_layout(FileDialogImpl *This)
         MapWindowPoints(NULL, This->dlg_hwnd, (POINT*)&toolbar_rc, 2);
     }
 
+    /* The custom controls */
+    customctrls_rc.left = dialog_rc.left + vspacing;
+    customctrls_rc.right = dialog_rc.right - vspacing;
+    customctrls_rc.bottom = filename_rc.top - hspacing;
+    customctrls_rc.top = customctrls_rc.bottom -
+        ctrl_container_resize(This, customctrls_rc.right - customctrls_rc.left);
+
     /* The ExplorerBrowser control. */
     ebrowser_rc.left = dialog_rc.left + vspacing;
     ebrowser_rc.top = toolbar_rc.bottom + vspacing;
     ebrowser_rc.right = dialog_rc.right - hspacing;
-    ebrowser_rc.bottom = filename_rc.top - hspacing;
+    ebrowser_rc.bottom = customctrls_rc.top - hspacing;
 
     /****
      * Move everything to the right place.
      */
 
     /* FIXME: The Save Dialog uses a slightly different layout. */
-    hdwp = BeginDeferWindowPos(6);
+    hdwp = BeginDeferWindowPos(7);
 
     if(hdwp && This->peb)
         IExplorerBrowser_SetRect(This->peb, &hdwp, ebrowser_rc);
 
+    if(hdwp && This->cctrls_hwnd)
+        DeferWindowPos(hdwp, This->cctrls_hwnd, NULL,
+                       customctrls_rc.left, customctrls_rc.top,
+                       customctrls_rc.right - customctrls_rc.left, customctrls_rc.bottom - customctrls_rc.top,
+                       SWP_NOZORDER | SWP_NOACTIVATE);
+
     /* The default controls */
     if(hdwp && (hwnd = GetDlgItem(This->dlg_hwnd, IDC_FILETYPE)) )
         DeferWindowPos(hdwp, hwnd, NULL, filetype_rc.left, filetype_rc.top, 0, 0,
@@ -797,6 +910,7 @@ static LRESULT on_wm_initdialog(HWND hwnd, LPARAM lParam)
        (hitem = GetDlgItem(This->dlg_hwnd, IDC_FILENAME)) )
         SendMessageW(hitem, WM_SETTEXT, 0, (LPARAM)This->set_filename);
 
+    ctrl_container_reparent(This, This->dlg_hwnd);
     init_explorerbrowser(This);
     init_toolbar(This, hwnd);
     update_control_text(This);
@@ -834,6 +948,7 @@ static LRESULT on_wm_destroy(FileDialogImpl *This)
         This->peb = NULL;
     }
 
+    ctrl_container_reparent(This, NULL);
     This->dlg_hwnd = NULL;
 
     return TRUE;
@@ -1055,6 +1170,8 @@ static ULONG WINAPI IFileDialog2_fnRelease(IFileDialog2 *iface)
         }
         HeapFree(GetProcessHeap(), 0, This->filterspecs);
 
+        DestroyWindow(This->cctrls_hwnd);
+
         if(This->psi_defaultfolder) IShellItem_Release(This->psi_defaultfolder);
         if(This->psi_setfolder)     IShellItem_Release(This->psi_setfolder);
         if(This->psi_folder)        IShellItem_Release(This->psi_folder);
@@ -2736,6 +2853,14 @@ static HRESULT FileDialog_constructor(IUnknown *pUnkOuter, REFIID riid, void **p
     SHGetItemFromObject((IUnknown*)psf, &IID_IShellItem, (void**)&fdimpl->psi_defaultfolder);
     IShellFolder_Release(psf);
 
+    hr = init_custom_controls(fdimpl);
+    if(FAILED(hr))
+    {
+        ERR("Failed to initialize custom controls (0x%08x).\n", hr);
+        IUnknown_Release((IUnknown*)fdimpl);
+        return E_FAIL;
+    }
+
     hr = IUnknown_QueryInterface((IUnknown*)fdimpl, riid, ppv);
     IUnknown_Release((IUnknown*)fdimpl);
     return hr;
diff --git a/dlls/comdlg32/tests/itemdlg.c b/dlls/comdlg32/tests/itemdlg.c
index 4c4e1ce..9e4d571 100644
--- a/dlls/comdlg32/tests/itemdlg.c
+++ b/dlls/comdlg32/tests/itemdlg.c
@@ -1200,6 +1200,38 @@ static void test_filename(void)
     DeleteFileW(filename_ext2W);
 }
 
+static void test_customize(void)
+{
+    IFileDialog *pfod;
+    IFileDialogCustomize *pfdc;
+    IOleWindow *pow;
+    LONG ref;
+    HWND dlg_hwnd;
+    HRESULT hr;
+    hr = CoCreateInstance(&CLSID_FileOpenDialog, NULL, CLSCTX_INPROC_SERVER,
+                          &IID_IFileDialog, (void**)&pfod);
+    ok(hr == S_OK, "got 0x%08x.\n", hr);
+
+    hr = IFileOpenDialog_QueryInterface(pfod, &IID_IFileDialogCustomize, (void**)&pfdc);
+    ok(hr == S_OK, "got 0x%08x.\n", hr);
+    if(FAILED(hr))
+    {
+        skip("Skipping IFileDialogCustomize tests.\n");
+        return;
+    }
+
+    hr = IFileDialog_QueryInterface(pfod, &IID_IOleWindow, (void**)&pow);
+    ok(hr == S_OK, "Got 0x%08x\n", hr);
+    hr = IOleWindow_GetWindow(pow, &dlg_hwnd);
+    ok(hr == S_OK, "Got 0x%08x\n", hr);
+    ok(dlg_hwnd == NULL, "NULL\n");
+    IOleWindow_Release(pow);
+
+    IFileDialogCustomize_Release(pfdc);
+    ref = IFileOpenDialog_Release(pfod);
+    ok(!ref, "Refcount not zero (%d).\n", ref);
+}
+
 START_TEST(itemdlg)
 {
     OleInitialize(NULL);
@@ -1210,6 +1242,7 @@ START_TEST(itemdlg)
         test_basics();
         test_advise();
         test_filename();
+        test_customize();
     }
     else
         skip("Skipping all Item Dialog tests.\n");




More information about the wine-cvs mailing list