[5/5] comdlg32: Implement radio button lists in item dialog.
Vincent Povirk
madewokherd at gmail.com
Fri Sep 11 13:40:04 CDT 2015
-------------- next part --------------
From 6071b341a2906200d30593ce356296868cd21383 Mon Sep 17 00:00:00 2001
From: Vincent Povirk <vincent at codeweavers.com>
Date: Thu, 10 Sep 2015 10:22:11 -0500
Subject: [PATCH 5/5] comdlg32: Implement radio button lists in item dialog.
---
dlls/comdlg32/itemdlg.c | 223 +++++++++++++++++++++++++++++++++++++++++-
dlls/comdlg32/tests/itemdlg.c | 24 +++--
2 files changed, 232 insertions(+), 15 deletions(-)
diff --git a/dlls/comdlg32/itemdlg.c b/dlls/comdlg32/itemdlg.c
index aa42bf3..ee60412 100644
--- a/dlls/comdlg32/itemdlg.c
+++ b/dlls/comdlg32/itemdlg.c
@@ -50,6 +50,7 @@ WINE_DEFAULT_DEBUG_CHANNEL(commdlg);
static const WCHAR notifysink_childW[] = {'n','f','s','_','c','h','i','l','d',0};
static const WCHAR floatnotifysinkW[] = {'F','l','o','a','t','N','o','t','i','f','y','S','i','n','k',0};
+static const WCHAR radiobuttonlistW[] = {'R','a','d','i','o','B','u','t','t','o','n','L','i','s','t',0};
enum ITEMDLG_TYPE {
ITEMDLG_TYPE_OPEN,
@@ -73,6 +74,7 @@ typedef struct cctrl_item {
DWORD id, parent_id;
LPWSTR label;
CDCONTROLSTATEF cdcstate;
+ HWND hwnd;
struct list entry;
} cctrl_item;
@@ -741,6 +743,7 @@ static void show_opendropdown(FileDialogImpl *This)
static void item_free(cctrl_item *item)
{
+ DestroyWindow(item->hwnd);
HeapFree(GetProcessHeap(), 0, item->label);
HeapFree(GetProcessHeap(), 0, item);
}
@@ -802,6 +805,7 @@ static HRESULT add_item(customctrl* parent, DWORD itemid, LPCWSTR label, cctrl_i
lstrcpyW(label_copy, label);
item->label = label_copy;
item->cdcstate = CDCS_VISIBLE|CDCS_ENABLED;
+ item->hwnd = NULL;
list_add_tail(&parent->sub_items, &item->entry);
*result = item;
@@ -932,6 +936,7 @@ static void customctrl_resize(FileDialogImpl *This, customctrl *ctrl)
{
RECT rc;
UINT total_height;
+ UINT max_width;
customctrl *sub_ctrl;
switch(ctrl->type)
@@ -974,6 +979,32 @@ static void customctrl_resize(FileDialogImpl *This, customctrl *ctrl)
SWP_NOZORDER|SWP_NOMOVE);
break;
case IDLG_CCTRL_RADIOBUTTONLIST:
+ {
+ cctrl_item* item;
+
+ total_height = 0;
+ max_width = 0;
+
+ LIST_FOR_EACH_ENTRY(item, &ctrl->sub_items, cctrl_item, entry)
+ {
+ ctrl_resize(item->hwnd, 160, 160, TRUE);
+ SetWindowPos(item->hwnd, NULL, 0, total_height, 0, 0,
+ SWP_NOZORDER|SWP_NOSIZE);
+
+ GetWindowRect(item->hwnd, &rc);
+
+ total_height += rc.bottom - rc.top;
+ max_width = max(rc.right - rc.left, max_width);
+ }
+
+ SetWindowPos(ctrl->hwnd, NULL, 0, 0, max_width, total_height,
+ SWP_NOZORDER|SWP_NOMOVE);
+
+ SetWindowPos(ctrl->wrapper_hwnd, NULL, 0, 0, max_width, total_height,
+ SWP_NOZORDER|SWP_NOMOVE);
+
+ break;
+ }
case IDLG_CCTRL_EDITBOX:
case IDLG_CCTRL_SEPARATOR:
case IDLG_CCTRL_MENU:
@@ -1317,6 +1348,15 @@ static void ctrl_container_reparent(FileDialogImpl *This, HWND parent)
if(font) SendMessageW(sub_ctrl->hwnd, WM_SETFONT, (WPARAM)font, TRUE);
}
+ if (ctrl->type == IDLG_CCTRL_RADIOBUTTONLIST)
+ {
+ cctrl_item* item;
+ LIST_FOR_EACH_ENTRY(item, &ctrl->sub_items, cctrl_item, entry)
+ {
+ if (font) SendMessageW(item->hwnd, WM_SETFONT, (WPARAM)font, TRUE);
+ }
+ }
+
customctrl_resize(This, ctrl);
}
}
@@ -1370,6 +1410,75 @@ static LRESULT CALLBACK ctrl_container_wndproc(HWND hwnd, UINT umessage, WPARAM
return FALSE;
}
+static void radiobuttonlist_set_selected_item(FileDialogImpl *This, customctrl *ctrl, cctrl_item *item)
+{
+ cctrl_item *cursor;
+
+ LIST_FOR_EACH_ENTRY(cursor, &ctrl->sub_items, cctrl_item, entry)
+ {
+ SendMessageW(cursor->hwnd, BM_SETCHECK, (cursor == item) ? BST_CHECKED : BST_UNCHECKED, 0);
+ }
+}
+
+static LRESULT radiobuttonlist_on_bn_clicked(FileDialogImpl *This, HWND hwnd, HWND child)
+{
+ DWORD ctrl_id = (DWORD)GetWindowLongPtrW(hwnd, GWLP_ID);
+ customctrl *ctrl;
+ cctrl_item *item;
+ BOOL found_item=FALSE;
+
+ ctrl = get_cctrl_from_dlgid(This, ctrl_id);
+
+ if (!ctrl)
+ {
+ ERR("Can't find this control\n");
+ return 0;
+ }
+
+ LIST_FOR_EACH_ENTRY(item, &ctrl->sub_items, cctrl_item, entry)
+ {
+ if (item->hwnd == child)
+ {
+ found_item = TRUE;
+ break;
+ }
+ }
+
+ if (!found_item)
+ {
+ ERR("Can't find control item\n");
+ return 0;
+ }
+
+ radiobuttonlist_set_selected_item(This, ctrl, item);
+
+ cctrl_event_OnItemSelected(This, ctrl->id, item->id);
+
+ return 0;
+}
+
+static LRESULT radiobuttonlist_on_wm_command(FileDialogImpl *This, HWND hwnd, WPARAM wparam, LPARAM lparam)
+{
+ switch(HIWORD(wparam))
+ {
+ case BN_CLICKED: return radiobuttonlist_on_bn_clicked(This, hwnd, (HWND)lparam);
+ }
+
+ return FALSE;
+}
+
+static LRESULT CALLBACK radiobuttonlist_proc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam)
+{
+ FileDialogImpl *This = (FileDialogImpl*)GetWindowLongPtrW(hwnd, GWLP_USERDATA);
+
+ switch(message)
+ {
+ case WM_COMMAND: return radiobuttonlist_on_wm_command(This, hwnd, wparam, lparam);
+ }
+
+ return DefWindowProcW(hwnd, message, wparam, lparam);
+}
+
static HRESULT init_custom_controls(FileDialogImpl *This)
{
WNDCLASSW wc;
@@ -1431,6 +1540,24 @@ static HRESULT init_custom_controls(FileDialogImpl *This)
ERR("Failed to register FloatNotifySink window class.\n");
}
+ if( !GetClassInfoW(COMDLG32_hInstance, radiobuttonlistW, &wc) ||
+ wc.hInstance != COMDLG32_hInstance)
+ {
+ wc.style = CS_HREDRAW | CS_VREDRAW;
+ wc.lpfnWndProc = radiobuttonlist_proc;
+ 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 = radiobuttonlistW;
+
+ if (!RegisterClassW(&wc))
+ ERR("Failed to register RadioButtonList window class.\n");
+ }
+
return S_OK;
}
@@ -3678,8 +3805,18 @@ static HRESULT WINAPI IFileDialogCustomize_fnAddRadioButtonList(IFileDialogCusto
DWORD dwIDCtl)
{
FileDialogImpl *This = impl_from_IFileDialogCustomize(iface);
- FIXME("stub - %p (%d)\n", This, dwIDCtl);
- return E_NOTIMPL;
+ customctrl *ctrl;
+ HRESULT hr;
+ TRACE("%p (%d)\n", This, dwIDCtl);
+
+ hr = cctrl_create_new(This, dwIDCtl, NULL, radiobuttonlistW, 0, 0, 0, &ctrl);
+ if(SUCCEEDED(hr))
+ {
+ ctrl->type = IDLG_CCTRL_RADIOBUTTONLIST;
+ SetWindowLongPtrW(ctrl->hwnd, GWLP_USERDATA, (LPARAM)This);
+ }
+
+ return hr;
}
static HRESULT WINAPI IFileDialogCustomize_fnAddCheckButton(IFileDialogCustomize *iface,
@@ -3955,6 +4092,29 @@ static HRESULT WINAPI IFileDialogCustomize_fnAddControlItem(IFileDialogCustomize
AppendMenuW(hmenu, MF_STRING, dwIDItem, pszLabel);
return S_OK;
}
+ case IDLG_CCTRL_RADIOBUTTONLIST:
+ {
+ cctrl_item* item;
+
+ hr = add_item(ctrl, dwIDItem, pszLabel, &item);
+
+ if (SUCCEEDED(hr))
+ {
+ item->hwnd = CreateWindowExW(0, WC_BUTTONW, pszLabel,
+ WS_CHILD|WS_VISIBLE|WS_CLIPSIBLINGS|BS_RADIOBUTTON|BS_MULTILINE,
+ 0, 0, 0, 0, ctrl->hwnd, (HMENU)dwIDItem, COMDLG32_hInstance, 0);
+
+ if (!item->hwnd)
+ {
+ ERR("Failed to create radio button\n");
+ list_remove(&item->entry);
+ item_free(item);
+ return E_FAIL;
+ }
+ }
+
+ return hr;
+ }
default:
break;
}
@@ -4023,6 +4183,20 @@ static HRESULT WINAPI IFileDialogCustomize_fnRemoveControlItem(IFileDialogCustom
return S_OK;
}
+ case IDLG_CCTRL_RADIOBUTTONLIST:
+ {
+ cctrl_item* item;
+
+ item = get_item(ctrl, dwIDItem, 0, NULL);
+
+ if (!item)
+ return E_UNEXPECTED;
+
+ list_remove(&item->entry);
+ item_free(item);
+
+ return S_OK;
+ }
default:
break;
}
@@ -4056,6 +4230,7 @@ static HRESULT WINAPI IFileDialogCustomize_fnGetControlItemState(IFileDialogCust
case IDLG_CCTRL_COMBOBOX:
case IDLG_CCTRL_MENU:
case IDLG_CCTRL_OPENDROPDOWN:
+ case IDLG_CCTRL_RADIOBUTTONLIST:
{
cctrl_item* item;
@@ -4178,6 +4353,20 @@ static HRESULT WINAPI IFileDialogCustomize_fnSetControlItemState(IFileDialogCust
return S_OK;
}
+ case IDLG_CCTRL_RADIOBUTTONLIST:
+ {
+ cctrl_item* item;
+
+ item = get_item(ctrl, dwIDItem, CDCS_VISIBLE, NULL);
+
+ if (!item)
+ return E_UNEXPECTED;
+
+ /* Oddly, native allows setting this but doesn't seem to do anything with it. */
+ item->cdcstate = dwState;
+
+ return S_OK;
+ }
default:
break;
}
@@ -4226,6 +4415,22 @@ static HRESULT WINAPI IFileDialogCustomize_fnGetSelectedControlItem(IFileDialogC
WARN("no enabled items in open dropdown\n");
return E_FAIL;
}
+ case IDLG_CCTRL_RADIOBUTTONLIST:
+ {
+ cctrl_item* item;
+
+ LIST_FOR_EACH_ENTRY(item, &ctrl->sub_items, cctrl_item, entry)
+ {
+ if (SendMessageW(item->hwnd, BM_GETCHECK, 0, 0) == BST_CHECKED)
+ {
+ *pdwIDItem = item->id;
+ return S_OK;
+ }
+ }
+
+ WARN("no checked items in radio button list\n");
+ return E_FAIL;
+ }
default:
FIXME("Unsupported control type %d\n", ctrl->type);
}
@@ -4257,6 +4462,20 @@ static HRESULT WINAPI IFileDialogCustomize_fnSetSelectedControlItem(IFileDialogC
return S_OK;
}
+ case IDLG_CCTRL_RADIOBUTTONLIST:
+ {
+ cctrl_item* item;
+
+ item = get_item(ctrl, dwIDItem, 0, NULL);
+
+ if (item)
+ {
+ radiobuttonlist_set_selected_item(This, ctrl, item);
+ return S_OK;
+ }
+
+ return E_INVALIDARG;
+ }
default:
FIXME("Unsupported control type %d\n", ctrl->type);
}
diff --git a/dlls/comdlg32/tests/itemdlg.c b/dlls/comdlg32/tests/itemdlg.c
index 4649620..b4fb480 100644
--- a/dlls/comdlg32/tests/itemdlg.c
+++ b/dlls/comdlg32/tests/itemdlg.c
@@ -1549,10 +1549,10 @@ static void test_customize_onfolderchange(IFileDialog *pfd)
GetClassNameW(item_parent, buf, 1024);
ok(!lstrcmpW(buf, floatnotifysinkW), "Got %s\n", wine_dbgstr_w(buf));
item = find_window(dlg_hwnd, NULL, radiobutton1W);
- todo_wine ok(item != NULL, "Failed to find item.\n");
+ ok(item != NULL, "Failed to find item.\n");
item_parent = GetParent(item);
GetClassNameW(item_parent, buf, 1024);
- todo_wine ok(!lstrcmpW(buf, RadioButtonListW), "Got %s\n", wine_dbgstr_w(buf));
+ ok(!lstrcmpW(buf, RadioButtonListW), "Got %s\n", wine_dbgstr_w(buf));
item_parent = GetParent(item_parent);
GetClassNameW(item_parent, buf, 1024);
ok(!lstrcmpW(buf, floatnotifysinkW), "Got %s\n", wine_dbgstr_w(buf));
@@ -1731,25 +1731,25 @@ static void test_customize(void)
ok(hr == S_OK, "got 0x%08x (control: %d).\n", hr, i);
hr = IFileDialogCustomize_AddRadioButtonList(pfdc, i);
- todo_wine ok(hr == E_UNEXPECTED, "got 0x%08x.\n", hr);
+ ok(hr == E_UNEXPECTED, "got 0x%08x.\n", hr);
hr = IFileDialogCustomize_AddRadioButtonList(pfdc, ++i);
- todo_wine ok(hr == S_OK, "got 0x%08x.\n", hr);
+ ok(hr == S_OK, "got 0x%08x.\n", hr);
cdstate = 0xdeadbeef;
hr = IFileDialogCustomize_GetControlState(pfdc, i, &cdstate);
- todo_wine ok(hr == S_OK, "got 0x%08x.\n", hr);
- todo_wine ok(cdstate == CDCS_ENABLEDVISIBLE, "got 0x%08x.\n", cdstate);
+ ok(hr == S_OK, "got 0x%08x.\n", hr);
+ ok(cdstate == CDCS_ENABLEDVISIBLE, "got 0x%08x.\n", cdstate);
hr = IFileDialogCustomize_AddControlItem(pfdc, i, 0, radiobutton1W);
- todo_wine ok(hr == S_OK, "got 0x%08x.\n", hr);
+ ok(hr == S_OK, "got 0x%08x.\n", hr);
hr = IFileDialogCustomize_AddControlItem(pfdc, i, 0, radiobutton1W);
- todo_wine ok(hr == E_INVALIDARG, "got 0x%08x.\n", hr);
+ ok(hr == E_INVALIDARG, "got 0x%08x.\n", hr);
hr = IFileDialogCustomize_SetControlLabel(pfdc, i, radiobutton2W);
- todo_wine ok(hr == S_OK, "got 0x%08x (control: %d).\n", hr, i);
+ ok(hr == S_OK, "got 0x%08x (control: %d).\n", hr, i);
hr = IFileDialogCustomize_AddCheckButton(pfdc, i, label, TRUE);
- todo_wine ok(hr == E_UNEXPECTED, "got 0x%08x.\n", hr);
+ ok(hr == E_UNEXPECTED, "got 0x%08x.\n", hr);
hr = IFileDialogCustomize_AddCheckButton(pfdc, ++i, checkbutton1W, TRUE);
ok(hr == S_OK, "got 0x%08x.\n", hr);
@@ -2012,7 +2012,7 @@ static void test_customize(void)
}
hr = IFileDialogCustomize_AddRadioButtonList(pfdc, ++i);
- todo_wine ok(hr == S_OK, "got 0x%08x.\n", hr);
+ ok(hr == S_OK, "got 0x%08x.\n", hr);
if(SUCCEEDED(hr))
{
DWORD selected = -1;
@@ -2028,7 +2028,6 @@ static void test_customize(void)
ok(hr == E_FAIL, "got 0x%08x.\n", hr);
ok(selected == -1, "got %d.\n", selected);
- todo_wine {
cdstate = 0xdeadbeef;
hr = IFileDialogCustomize_GetControlItemState(pfdc, i, 0, &cdstate);
ok(hr == S_OK, "got 0x%08x.\n", hr);
@@ -2045,7 +2044,6 @@ static void test_customize(void)
hr = IFileDialogCustomize_GetControlItemState(pfdc, i, 0, &cdstate);
ok(hr == S_OK, "got 0x%08x.\n", hr);
ok(cdstate == CDCS_ENABLEDVISIBLE, "got 0x%08x.\n", cdstate);
- }
for(j = 0; j < 10; j++)
{
--
2.1.4
More information about the wine-patches
mailing list