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