4 * Copyright 2010,2011 David Hedberg
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
33 #include "filedlgbrowser.h"
35 #include "wine/debug.h"
36 #include "wine/list.h"
38 #define IDC_NAV_TOOLBAR 200
39 #define IDC_NAVBACK 201
40 #define IDC_NAVFORWARD 202
44 /* This seems to be another version of IID_IFileDialogCustomize. If
45 * there is any difference I have yet to find it. */
46 DEFINE_GUID(IID_IFileDialogCustomizeAlt
, 0x8016B7B3, 0x3D49, 0x4504, 0xA0,0xAA, 0x2A,0x37,0x49,0x4E,0x60,0x6F);
48 WINE_DEFAULT_DEBUG_CHANNEL(commdlg
);
55 enum ITEMDLG_CCTRL_TYPE
{
57 IDLG_CCTRL_PUSHBUTTON
,
59 IDLG_CCTRL_RADIOBUTTONLIST
,
60 IDLG_CCTRL_CHECKBUTTON
,
64 IDLG_CCTRL_OPENDROPDOWN
,
65 IDLG_CCTRL_VISUALGROUP
68 typedef struct cctrl_item
{
71 CDCONTROLSTATEF cdcstate
;
77 HWND hwnd
, wrapper_hwnd
;
79 enum ITEMDLG_CCTRL_TYPE type
;
80 CDCONTROLSTATEF cdcstate
;
83 struct list sub_cctrls
;
84 struct list sub_cctrls_entry
;
85 struct list sub_items
;
90 IFileDialogEvents
*pfde
;
94 typedef struct FileDialogImpl
{
95 IFileDialog2 IFileDialog2_iface
;
97 IFileOpenDialog IFileOpenDialog_iface
;
98 IFileSaveDialog IFileSaveDialog_iface
;
100 enum ITEMDLG_TYPE dlg_type
;
101 IExplorerBrowserEvents IExplorerBrowserEvents_iface
;
102 IServiceProvider IServiceProvider_iface
;
103 ICommDlgBrowser3 ICommDlgBrowser3_iface
;
104 IOleWindow IOleWindow_iface
;
105 IFileDialogCustomize IFileDialogCustomize_iface
;
108 FILEOPENDIALOGOPTIONS options
;
109 COMDLG_FILTERSPEC
*filterspecs
;
110 UINT filterspec_count
;
113 struct list events_clients
;
114 DWORD events_next_cookie
;
116 IShellItemArray
*psia_selection
;
117 IShellItemArray
*psia_results
;
118 IShellItem
*psi_defaultfolder
;
119 IShellItem
*psi_setfolder
;
120 IShellItem
*psi_folder
;
123 IExplorerBrowser
*peb
;
124 DWORD ebevents_cookie
;
129 LPWSTR custom_okbutton
;
130 LPWSTR custom_cancelbutton
;
131 LPWSTR custom_filenamelabel
;
133 UINT cctrl_width
, cctrl_def_height
, cctrls_cols
;
134 UINT cctrl_indent
, dpi_x
, dpi_y
;
137 UINT_PTR cctrl_next_dlgid
;
138 customctrl
*cctrl_active_vg
;
140 HMENU hmenu_opendropdown
;
141 customctrl cctrl_opendropdown
;
142 HFONT hfont_opendropdown
;
143 BOOL opendropdown_has_selection
;
144 DWORD opendropdown_selection
;
151 /**************************************************************************
154 static HRESULT
events_OnFileOk(FileDialogImpl
*This
)
156 ULONG_PTR ctx_cookie
= 0;
157 events_client
*cursor
;
161 if (This
->user_actctx
!= INVALID_HANDLE_VALUE
)
162 ActivateActCtx(This
->user_actctx
, &ctx_cookie
);
164 LIST_FOR_EACH_ENTRY(cursor
, &This
->events_clients
, events_client
, entry
)
166 TRACE("Notifying %p\n", cursor
);
167 hr
= IFileDialogEvents_OnFileOk(cursor
->pfde
, (IFileDialog
*)&This
->IFileDialog2_iface
);
168 if(FAILED(hr
) && hr
!= E_NOTIMPL
)
172 if (This
->user_actctx
!= INVALID_HANDLE_VALUE
)
173 DeactivateActCtx(0, ctx_cookie
);
181 static HRESULT
events_OnFolderChanging(FileDialogImpl
*This
, IShellItem
*folder
)
183 ULONG_PTR ctx_cookie
= 0;
184 events_client
*cursor
;
186 TRACE("%p (%p)\n", This
, folder
);
188 if (This
->user_actctx
!= INVALID_HANDLE_VALUE
)
189 ActivateActCtx(This
->user_actctx
, &ctx_cookie
);
191 LIST_FOR_EACH_ENTRY(cursor
, &This
->events_clients
, events_client
, entry
)
193 TRACE("Notifying %p\n", cursor
);
194 hr
= IFileDialogEvents_OnFolderChanging(cursor
->pfde
, (IFileDialog
*)&This
->IFileDialog2_iface
, folder
);
195 if(FAILED(hr
) && hr
!= E_NOTIMPL
)
199 if (This
->user_actctx
!= INVALID_HANDLE_VALUE
)
200 DeactivateActCtx(0, ctx_cookie
);
208 static void events_OnFolderChange(FileDialogImpl
*This
)
210 ULONG_PTR ctx_cookie
= 0;
211 events_client
*cursor
;
214 if (This
->user_actctx
!= INVALID_HANDLE_VALUE
)
215 ActivateActCtx(This
->user_actctx
, &ctx_cookie
);
217 LIST_FOR_EACH_ENTRY(cursor
, &This
->events_clients
, events_client
, entry
)
219 TRACE("Notifying %p\n", cursor
);
220 IFileDialogEvents_OnFolderChange(cursor
->pfde
, (IFileDialog
*)&This
->IFileDialog2_iface
);
223 if (This
->user_actctx
!= INVALID_HANDLE_VALUE
)
224 DeactivateActCtx(0, ctx_cookie
);
227 static void events_OnSelectionChange(FileDialogImpl
*This
)
229 ULONG_PTR ctx_cookie
= 0;
230 events_client
*cursor
;
233 if (This
->user_actctx
!= INVALID_HANDLE_VALUE
)
234 ActivateActCtx(This
->user_actctx
, &ctx_cookie
);
236 LIST_FOR_EACH_ENTRY(cursor
, &This
->events_clients
, events_client
, entry
)
238 TRACE("Notifying %p\n", cursor
);
239 IFileDialogEvents_OnSelectionChange(cursor
->pfde
, (IFileDialog
*)&This
->IFileDialog2_iface
);
242 if (This
->user_actctx
!= INVALID_HANDLE_VALUE
)
243 DeactivateActCtx(0, ctx_cookie
);
246 static void events_OnTypeChange(FileDialogImpl
*This
)
248 ULONG_PTR ctx_cookie
= 0;
249 events_client
*cursor
;
252 if (This
->user_actctx
!= INVALID_HANDLE_VALUE
)
253 ActivateActCtx(This
->user_actctx
, &ctx_cookie
);
255 LIST_FOR_EACH_ENTRY(cursor
, &This
->events_clients
, events_client
, entry
)
257 TRACE("Notifying %p\n", cursor
);
258 IFileDialogEvents_OnTypeChange(cursor
->pfde
, (IFileDialog
*)&This
->IFileDialog2_iface
);
261 if (This
->user_actctx
!= INVALID_HANDLE_VALUE
)
262 DeactivateActCtx(0, ctx_cookie
);
265 static HRESULT
events_OnOverwrite(FileDialogImpl
*This
, IShellItem
*shellitem
)
267 ULONG_PTR ctx_cookie
= 0;
268 events_client
*cursor
;
270 FDE_OVERWRITE_RESPONSE response
= FDEOR_DEFAULT
;
271 TRACE("%p %p\n", This
, shellitem
);
273 if (This
->user_actctx
!= INVALID_HANDLE_VALUE
)
274 ActivateActCtx(This
->user_actctx
, &ctx_cookie
);
276 LIST_FOR_EACH_ENTRY(cursor
, &This
->events_clients
, events_client
, entry
)
278 TRACE("Notifying %p\n", cursor
);
279 hr
= IFileDialogEvents_OnOverwrite(cursor
->pfde
, (IFileDialog
*)&This
->IFileDialog2_iface
, shellitem
, &response
);
280 TRACE("<-- hr=%lx response=%u\n", hr
, response
);
281 if(FAILED(hr
) && hr
!= E_NOTIMPL
)
285 if (This
->user_actctx
!= INVALID_HANDLE_VALUE
)
286 DeactivateActCtx(0, ctx_cookie
);
293 if (response
== FDEOR_DEFAULT
)
298 LoadStringW(COMDLG32_hInstance
, IDS_OVERWRITEFILE
, buf
, 100);
299 answer
= MessageBoxW(This
->dlg_hwnd
, buf
, This
->custom_title
,
300 MB_YESNO
| MB_ICONEXCLAMATION
);
301 if (answer
== IDNO
|| answer
== IDCANCEL
)
306 else if (response
== FDEOR_REFUSE
)
313 static inline HRESULT
get_cctrl_event(IFileDialogEvents
*pfde
, IFileDialogControlEvents
**pfdce
)
315 return IFileDialogEvents_QueryInterface(pfde
, &IID_IFileDialogControlEvents
, (void**)pfdce
);
318 static HRESULT
cctrl_event_OnButtonClicked(FileDialogImpl
*This
, DWORD ctl_id
)
320 ULONG_PTR ctx_cookie
= 0;
321 events_client
*cursor
;
324 if (This
->user_actctx
!= INVALID_HANDLE_VALUE
)
325 ActivateActCtx(This
->user_actctx
, &ctx_cookie
);
327 LIST_FOR_EACH_ENTRY(cursor
, &This
->events_clients
, events_client
, entry
)
329 IFileDialogControlEvents
*pfdce
;
330 if(SUCCEEDED(get_cctrl_event(cursor
->pfde
, &pfdce
)))
332 TRACE("Notifying %p\n", cursor
);
333 IFileDialogControlEvents_OnButtonClicked(pfdce
, &This
->IFileDialogCustomize_iface
, ctl_id
);
334 IFileDialogControlEvents_Release(pfdce
);
338 if (This
->user_actctx
!= INVALID_HANDLE_VALUE
)
339 DeactivateActCtx(0, ctx_cookie
);
344 static HRESULT
cctrl_event_OnItemSelected(FileDialogImpl
*This
, DWORD ctl_id
, DWORD item_id
)
346 ULONG_PTR ctx_cookie
= 0;
347 events_client
*cursor
;
348 TRACE("%p %li %li\n", This
, ctl_id
, item_id
);
350 if (This
->user_actctx
!= INVALID_HANDLE_VALUE
)
351 ActivateActCtx(This
->user_actctx
, &ctx_cookie
);
353 LIST_FOR_EACH_ENTRY(cursor
, &This
->events_clients
, events_client
, entry
)
355 IFileDialogControlEvents
*pfdce
;
356 if(SUCCEEDED(get_cctrl_event(cursor
->pfde
, &pfdce
)))
358 TRACE("Notifying %p\n", cursor
);
359 IFileDialogControlEvents_OnItemSelected(pfdce
, &This
->IFileDialogCustomize_iface
, ctl_id
, item_id
);
360 IFileDialogControlEvents_Release(pfdce
);
364 if (This
->user_actctx
!= INVALID_HANDLE_VALUE
)
365 DeactivateActCtx(0, ctx_cookie
);
370 static HRESULT
cctrl_event_OnCheckButtonToggled(FileDialogImpl
*This
, DWORD ctl_id
, BOOL checked
)
372 ULONG_PTR ctx_cookie
= 0;
373 events_client
*cursor
;
376 if (This
->user_actctx
!= INVALID_HANDLE_VALUE
)
377 ActivateActCtx(This
->user_actctx
, &ctx_cookie
);
379 LIST_FOR_EACH_ENTRY(cursor
, &This
->events_clients
, events_client
, entry
)
381 IFileDialogControlEvents
*pfdce
;
382 if(SUCCEEDED(get_cctrl_event(cursor
->pfde
, &pfdce
)))
384 TRACE("Notifying %p\n", cursor
);
385 IFileDialogControlEvents_OnCheckButtonToggled(pfdce
, &This
->IFileDialogCustomize_iface
, ctl_id
, checked
);
386 IFileDialogControlEvents_Release(pfdce
);
390 if (This
->user_actctx
!= INVALID_HANDLE_VALUE
)
391 DeactivateActCtx(0, ctx_cookie
);
396 static HRESULT
cctrl_event_OnControlActivating(FileDialogImpl
*This
,
399 ULONG_PTR ctx_cookie
= 0;
400 events_client
*cursor
;
403 if (This
->user_actctx
!= INVALID_HANDLE_VALUE
)
404 ActivateActCtx(This
->user_actctx
, &ctx_cookie
);
406 LIST_FOR_EACH_ENTRY(cursor
, &This
->events_clients
, events_client
, entry
)
408 IFileDialogControlEvents
*pfdce
;
409 if(SUCCEEDED(get_cctrl_event(cursor
->pfde
, &pfdce
)))
411 TRACE("Notifying %p\n", cursor
);
412 IFileDialogControlEvents_OnControlActivating(pfdce
, &This
->IFileDialogCustomize_iface
, ctl_id
);
413 IFileDialogControlEvents_Release(pfdce
);
417 if (This
->user_actctx
!= INVALID_HANDLE_VALUE
)
418 DeactivateActCtx(0, ctx_cookie
);
423 /**************************************************************************
426 static UINT
get_file_name(FileDialogImpl
*This
, LPWSTR
*str
)
428 HWND hwnd_edit
= GetDlgItem(This
->dlg_hwnd
, IDC_FILENAME
);
433 if(This
->set_filename
)
435 len
= lstrlenW(This
->set_filename
);
436 *str
= CoTaskMemAlloc(sizeof(WCHAR
)*(len
+1));
437 lstrcpyW(*str
, This
->set_filename
);
443 len
= SendMessageW(hwnd_edit
, WM_GETTEXTLENGTH
, 0, 0);
444 *str
= CoTaskMemAlloc(sizeof(WCHAR
)*(len
+1));
448 SendMessageW(hwnd_edit
, WM_GETTEXT
, len
+1, (LPARAM
)*str
);
452 static BOOL
set_file_name(FileDialogImpl
*This
, LPCWSTR str
)
454 if(This
->set_filename
)
455 LocalFree(This
->set_filename
);
457 This
->set_filename
= str
? StrDupW(str
) : NULL
;
459 return SetDlgItemTextW(This
->dlg_hwnd
, IDC_FILENAME
, This
->set_filename
);
462 static void fill_filename_from_selection(FileDialogImpl
*This
)
471 if(!This
->psia_selection
)
474 hr
= IShellItemArray_GetCount(This
->psia_selection
, &item_count
);
475 if(FAILED(hr
) || !item_count
)
478 names
= HeapAlloc(GetProcessHeap(), 0, item_count
*sizeof(LPWSTR
));
480 /* Get names of the selected items */
481 valid_count
= 0; len_total
= 0;
482 for(i
= 0; i
< item_count
; i
++)
484 hr
= IShellItemArray_GetItemAt(This
->psia_selection
, i
, &psi
);
489 hr
= IShellItem_GetAttributes(psi
, SFGAO_FOLDER
, &attr
);
491 (( (This
->options
& FOS_PICKFOLDERS
) && !(attr
& SFGAO_FOLDER
)) ||
492 (!(This
->options
& FOS_PICKFOLDERS
) && (attr
& SFGAO_FOLDER
))))
495 hr
= IShellItem_GetDisplayName(psi
, (This
->options
& FOS_PICKFOLDERS
) ? SIGDN_FILESYSPATH
: SIGDN_PARENTRELATIVEPARSING
, &names
[valid_count
]);
498 len_total
+= lstrlenW(names
[valid_count
]) + 3;
501 IShellItem_Release(psi
);
507 set_file_name(This
, names
[0]);
508 CoTaskMemFree(names
[0]);
510 else if(valid_count
> 1)
512 LPWSTR string
= HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR
)*len_total
);
513 LPWSTR cur_point
= string
;
515 for(i
= 0; i
< valid_count
; i
++)
517 LPWSTR file
= names
[i
];
519 lstrcpyW(cur_point
, file
);
520 cur_point
+= lstrlenW(file
);
525 *(cur_point
-1) = '\0';
527 set_file_name(This
, string
);
528 HeapFree(GetProcessHeap(), 0, string
);
531 HeapFree(GetProcessHeap(), 0, names
);
535 static LPWSTR
get_first_ext_from_spec(LPWSTR buf
, LPCWSTR spec
)
540 if( (endpos
= StrChrW(buf
, ';')) )
543 ext
= PathFindExtensionW(buf
);
544 if(StrChrW(ext
, '*'))
550 static BOOL
shell_item_exists(IShellItem
* shellitem
)
556 hr
= IShellItem_GetDisplayName(shellitem
, SIGDN_FILESYSPATH
, &filename
);
559 /* FIXME: Implement SFGAO_VALIDATE in Wine and use it instead. */
560 result
= (GetFileAttributesW(filename
) != INVALID_FILE_ATTRIBUTES
);
561 CoTaskMemFree(filename
);
566 result
= SUCCEEDED(IShellItem_GetAttributes(shellitem
, SFGAO_VALIDATE
, &attributes
));
572 static HRESULT
on_default_action(FileDialogImpl
*This
)
574 IShellFolder
*psf_parent
, *psf_desktop
;
576 LPITEMIDLIST current_folder
;
577 LPWSTR fn_iter
, files
= NULL
, tmp_files
;
578 UINT file_count
= 0, len
, i
;
580 HRESULT hr
, ret
= E_FAIL
;
582 len
= get_file_name(This
, &tmp_files
);
586 file_count
= COMDLG32_SplitFileNames(tmp_files
, len
, &files
, &size_used
);
587 CoTaskMemFree(tmp_files
);
589 if(!file_count
) return E_FAIL
;
591 hr
= SHGetIDListFromObject((IUnknown
*)This
->psi_folder
, ¤t_folder
);
594 ERR("Failed to get pidl for current directory.\n");
595 HeapFree(GetProcessHeap(), 0, files
);
599 TRACE("Acting on %d file(s).\n", file_count
);
601 pidla
= HeapAlloc(GetProcessHeap(), 0, sizeof(LPITEMIDLIST
) * file_count
);
602 open_action
= ONOPEN_OPEN
;
605 for(i
= 0; i
< file_count
&& open_action
== ONOPEN_OPEN
; i
++)
607 WCHAR canon_filename
[MAX_PATH
];
610 COMDLG32_GetCanonicalPath(current_folder
, fn_iter
, canon_filename
);
612 if( (This
->options
& FOS_NOVALIDATE
) &&
613 !(This
->options
& FOS_FILEMUSTEXIST
) )
614 open_action
= ONOPEN_OPEN
;
616 open_action
= ONOPEN_BROWSE
;
618 open_action
= FILEDLG95_ValidatePathAction(canon_filename
, &psf_parent
, This
->dlg_hwnd
,
619 This
->options
& ~FOS_FILEMUSTEXIST
,
620 (This
->dlg_type
== ITEMDLG_TYPE_SAVE
),
623 /* Add the proper extension */
624 if(open_action
== ONOPEN_OPEN
)
626 if(This
->dlg_type
== ITEMDLG_TYPE_SAVE
)
628 WCHAR extbuf
[MAX_PATH
], *newext
= NULL
;
630 if(This
->filterspec_count
)
632 newext
= get_first_ext_from_spec(extbuf
, This
->filterspecs
[This
->filetypeindex
].pszSpec
);
634 else if(This
->default_ext
)
636 lstrcpyW(extbuf
, L
".");
637 lstrcatW(extbuf
, This
->default_ext
);
643 WCHAR
*ext
= PathFindExtensionW(canon_filename
);
644 if(lstrcmpW(ext
, newext
))
645 lstrcatW(canon_filename
, newext
);
650 if( !(This
->options
& FOS_NOVALIDATE
) && (This
->options
& FOS_FILEMUSTEXIST
) &&
651 !PathFileExistsW(canon_filename
))
653 if(This
->default_ext
)
655 lstrcatW(canon_filename
, L
".");
656 lstrcatW(canon_filename
, This
->default_ext
);
658 if(!PathFileExistsW(canon_filename
))
660 FILEDLG95_OnOpenMessage(This
->dlg_hwnd
, 0, IDS_FILENOTEXISTING
);
661 open_action
= ONOPEN_BROWSE
;
666 FILEDLG95_OnOpenMessage(This
->dlg_hwnd
, 0, IDS_FILENOTEXISTING
);
667 open_action
= ONOPEN_BROWSE
;
673 pidla
[i
] = SHSimpleIDListFromPath(canon_filename
);
675 if(psf_parent
&& !(open_action
== ONOPEN_BROWSE
))
676 IShellFolder_Release(psf_parent
);
678 fn_iter
+= (WCHAR
)lstrlenW(fn_iter
) + 1;
681 HeapFree(GetProcessHeap(), 0, files
);
682 ILFree(current_folder
);
684 if((This
->options
& FOS_PICKFOLDERS
) && open_action
== ONOPEN_BROWSE
)
685 open_action
= ONOPEN_OPEN
; /* FIXME: Multiple folders? */
690 FIXME("Filtering not implemented.\n");
694 hr
= IExplorerBrowser_BrowseToObject(This
->peb
, (IUnknown
*)psf_parent
, SBSP_DEFBROWSER
);
696 ERR("Failed to browse to directory: %08lx\n", hr
);
698 IShellFolder_Release(psf_parent
);
702 hr
= SHGetDesktopFolder(&psf_desktop
);
705 if(This
->psia_results
)
707 IShellItemArray_Release(This
->psia_results
);
708 This
->psia_results
= NULL
;
711 hr
= SHCreateShellItemArray(NULL
, psf_desktop
, file_count
, (PCUITEMID_CHILD_ARRAY
)pidla
,
712 &This
->psia_results
);
714 IShellFolder_Release(psf_desktop
);
719 if(This
->options
& FOS_PICKFOLDERS
)
722 hr
= IShellItemArray_GetAttributes(This
->psia_results
, SIATTRIBFLAGS_AND
, SFGAO_FOLDER
, &attributes
);
726 LoadStringW(COMDLG32_hInstance
, IDS_INVALID_FOLDERNAME
, buf
, ARRAY_SIZE(buf
));
728 MessageBoxW(This
->dlg_hwnd
, buf
, This
->custom_title
, MB_OK
| MB_ICONEXCLAMATION
);
730 IShellItemArray_Release(This
->psia_results
);
731 This
->psia_results
= NULL
;
736 if((This
->options
& FOS_OVERWRITEPROMPT
) && This
->dlg_type
== ITEMDLG_TYPE_SAVE
)
738 IShellItem
*shellitem
;
740 for (i
=0; SUCCEEDED(hr
) && i
<file_count
; i
++)
742 hr
= IShellItemArray_GetItemAt(This
->psia_results
, i
, &shellitem
);
745 if (shell_item_exists(shellitem
))
746 hr
= events_OnOverwrite(This
, shellitem
);
748 IShellItem_Release(shellitem
);
756 if(events_OnFileOk(This
) == S_OK
)
767 for(i
= 0; i
< file_count
; i
++)
769 HeapFree(GetProcessHeap(), 0, pidla
);
771 /* Success closes the dialog */
775 static void show_opendropdown(FileDialogImpl
*This
)
781 open_hwnd
= GetDlgItem(This
->dlg_hwnd
, IDOK
);
783 GetWindowRect(open_hwnd
, &open_rc
);
785 if (TrackPopupMenu(This
->hmenu_opendropdown
, 0, open_rc
.left
, open_rc
.bottom
, 0, This
->dlg_hwnd
, NULL
) &&
786 PeekMessageW(&msg
, This
->dlg_hwnd
, WM_MENUCOMMAND
, WM_MENUCOMMAND
, PM_REMOVE
))
790 This
->opendropdown_has_selection
= TRUE
;
792 mii
.cbSize
= sizeof(mii
);
794 GetMenuItemInfoW((HMENU
)msg
.lParam
, msg
.wParam
, TRUE
, &mii
);
795 This
->opendropdown_selection
= mii
.wID
;
797 if(SUCCEEDED(on_default_action(This
)))
798 EndDialog(This
->dlg_hwnd
, S_OK
);
800 This
->opendropdown_has_selection
= FALSE
;
804 /**************************************************************************
805 * Control item functions.
808 static void item_free(cctrl_item
*item
)
810 DestroyWindow(item
->hwnd
);
811 HeapFree(GetProcessHeap(), 0, item
->label
);
812 HeapFree(GetProcessHeap(), 0, item
);
815 static cctrl_item
* get_item(customctrl
* parent
, DWORD itemid
, CDCONTROLSTATEF visible_flags
, DWORD
* position
)
820 if (!position
) position
= &dummy
;
824 LIST_FOR_EACH_ENTRY(item
, &parent
->sub_items
, cctrl_item
, entry
)
826 if (item
->id
== itemid
)
829 if ((item
->cdcstate
& visible_flags
) == visible_flags
)
836 static cctrl_item
* get_first_item(customctrl
* parent
)
840 LIST_FOR_EACH_ENTRY(item
, &parent
->sub_items
, cctrl_item
, entry
)
842 if ((item
->cdcstate
& (CDCS_VISIBLE
|CDCS_ENABLED
)) == (CDCS_VISIBLE
|CDCS_ENABLED
))
849 static HRESULT
add_item(customctrl
* parent
, DWORD itemid
, LPCWSTR label
, cctrl_item
** result
)
854 if (get_item(parent
, itemid
, 0, NULL
))
857 item
= HeapAlloc(GetProcessHeap(), 0, sizeof(*item
));
858 label_copy
= HeapAlloc(GetProcessHeap(), 0, (lstrlenW(label
)+1)*sizeof(WCHAR
));
860 if (!item
|| !label_copy
)
862 HeapFree(GetProcessHeap(), 0, item
);
863 HeapFree(GetProcessHeap(), 0, label_copy
);
864 return E_OUTOFMEMORY
;
868 item
->parent_id
= parent
->id
;
869 lstrcpyW(label_copy
, label
);
870 item
->label
= label_copy
;
871 item
->cdcstate
= CDCS_VISIBLE
|CDCS_ENABLED
;
873 list_add_tail(&parent
->sub_items
, &item
->entry
);
880 /**************************************************************************
883 static inline customctrl
*get_cctrl_from_dlgid(FileDialogImpl
*This
, DWORD dlgid
)
885 customctrl
*ctrl
, *sub_ctrl
;
887 LIST_FOR_EACH_ENTRY(ctrl
, &This
->cctrls
, customctrl
, entry
)
889 if(ctrl
->dlgid
== dlgid
)
892 LIST_FOR_EACH_ENTRY(sub_ctrl
, &ctrl
->sub_cctrls
, customctrl
, sub_cctrls_entry
)
893 if(sub_ctrl
->dlgid
== dlgid
)
897 ERR("Failed to find control with dialog id %ld\n", dlgid
);
901 static inline customctrl
*get_cctrl(FileDialogImpl
*This
, DWORD ctlid
)
903 customctrl
*ctrl
, *sub_ctrl
;
905 LIST_FOR_EACH_ENTRY(ctrl
, &This
->cctrls
, customctrl
, entry
)
907 if(ctrl
->id
== ctlid
)
910 LIST_FOR_EACH_ENTRY(sub_ctrl
, &ctrl
->sub_cctrls
, customctrl
, sub_cctrls_entry
)
911 if(sub_ctrl
->id
== ctlid
)
915 if (This
->hmenu_opendropdown
&& This
->cctrl_opendropdown
.id
== ctlid
)
916 return &This
->cctrl_opendropdown
;
918 TRACE("No existing control with control id %ld\n", ctlid
);
922 static void ctrl_resize(HWND hctrl
, UINT min_width
, UINT max_width
, BOOL multiline
)
925 UINT len
, final_width
;
926 UINT lines
, final_height
;
935 len
= SendMessageW(hctrl
, WM_GETTEXTLENGTH
, 0, 0);
936 text
= HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR
)*(len
+1));
938 SendMessageW(hctrl
, WM_GETTEXT
, len
+1, (LPARAM
)text
);
941 font
= (HFONT
)SendMessageW(hctrl
, WM_GETFONT
, 0, 0);
942 font
= SelectObject(hdc
, font
);
943 GetTextExtentPoint32W(hdc
, text
, lstrlenW(text
), &size
);
944 SelectObject(hdc
, font
);
945 ReleaseDC(hctrl
, hdc
);
949 /* FIXME: line-wrap */
950 for(lines
= 1, c
= text
; *c
!= '\0'; c
++)
951 if(*c
== '\n') lines
++;
953 final_height
= size
.cy
*lines
+ 2*4;
957 GetWindowRect(hctrl
, &rc
);
958 final_height
= rc
.bottom
- rc
.top
;
961 final_width
= min(max(size
.cx
, min_width
) + 4, max_width
);
962 SetWindowPos(hctrl
, NULL
, 0, 0, final_width
, final_height
,
963 SWP_NOZORDER
| SWP_NOMOVE
| SWP_NOACTIVATE
);
965 HeapFree(GetProcessHeap(), 0, text
);
968 static UINT
ctrl_get_height(customctrl
*ctrl
) {
970 GetWindowRect(ctrl
->wrapper_hwnd
, &rc
);
971 return rc
.bottom
- rc
.top
;
974 static void ctrl_free(customctrl
*ctrl
)
976 customctrl
*sub_cur1
, *sub_cur2
;
977 cctrl_item
*item_cur1
, *item_cur2
;
979 TRACE("Freeing control %p\n", ctrl
);
980 if(ctrl
->type
== IDLG_CCTRL_MENU
)
983 SendMessageW(ctrl
->hwnd
, TB_GETBUTTON
, 0, (LPARAM
)&tbb
);
984 DestroyMenu((HMENU
)tbb
.dwData
);
987 LIST_FOR_EACH_ENTRY_SAFE(sub_cur1
, sub_cur2
, &ctrl
->sub_cctrls
, customctrl
, sub_cctrls_entry
)
989 list_remove(&sub_cur1
->sub_cctrls_entry
);
993 LIST_FOR_EACH_ENTRY_SAFE(item_cur1
, item_cur2
, &ctrl
->sub_items
, cctrl_item
, entry
)
995 list_remove(&item_cur1
->entry
);
996 item_free(item_cur1
);
999 DestroyWindow(ctrl
->hwnd
);
1000 HeapFree(GetProcessHeap(), 0, ctrl
);
1003 static void customctrl_resize(FileDialogImpl
*This
, customctrl
*ctrl
)
1007 UINT max_width
, size
;
1008 customctrl
*sub_ctrl
;
1012 case IDLG_CCTRL_PUSHBUTTON
:
1013 case IDLG_CCTRL_COMBOBOX
:
1014 case IDLG_CCTRL_CHECKBUTTON
:
1015 case IDLG_CCTRL_TEXT
:
1016 size
= MulDiv(160, This
->dpi_x
, USER_DEFAULT_SCREEN_DPI
);
1017 ctrl_resize(ctrl
->hwnd
, size
, size
, TRUE
);
1018 GetWindowRect(ctrl
->hwnd
, &rc
);
1019 SetWindowPos(ctrl
->wrapper_hwnd
, NULL
, 0, 0, rc
.right
-rc
.left
, rc
.bottom
-rc
.top
,
1020 SWP_NOZORDER
|SWP_NOMOVE
);
1022 case IDLG_CCTRL_VISUALGROUP
:
1024 ctrl_resize(ctrl
->hwnd
, 0, This
->cctrl_indent
, TRUE
);
1026 LIST_FOR_EACH_ENTRY(sub_ctrl
, &ctrl
->sub_cctrls
, customctrl
, sub_cctrls_entry
)
1028 customctrl_resize(This
, sub_ctrl
);
1029 SetWindowPos(sub_ctrl
->wrapper_hwnd
, NULL
, This
->cctrl_indent
, total_height
, 0, 0,
1030 SWP_NOZORDER
|SWP_NOSIZE
);
1032 total_height
+= ctrl_get_height(sub_ctrl
);
1035 /* The label should be right adjusted */
1039 GetWindowRect(ctrl
->hwnd
, &rc
);
1040 width
= rc
.right
- rc
.left
;
1041 height
= rc
.bottom
- rc
.top
;
1043 SetWindowPos(ctrl
->hwnd
, NULL
, This
->cctrl_indent
- width
, 0, width
, height
, SWP_NOZORDER
);
1046 /* Resize the wrapper window to fit all the sub controls */
1047 SetWindowPos(ctrl
->wrapper_hwnd
, NULL
, 0, 0, This
->cctrl_width
+ This
->cctrl_indent
, total_height
,
1048 SWP_NOZORDER
|SWP_NOMOVE
);
1050 case IDLG_CCTRL_RADIOBUTTONLIST
:
1057 LIST_FOR_EACH_ENTRY(item
, &ctrl
->sub_items
, cctrl_item
, entry
)
1059 size
= MulDiv(160, This
->dpi_x
, USER_DEFAULT_SCREEN_DPI
);
1060 ctrl_resize(item
->hwnd
, size
, size
, TRUE
);
1061 SetWindowPos(item
->hwnd
, NULL
, 0, total_height
, 0, 0,
1062 SWP_NOZORDER
|SWP_NOSIZE
);
1064 GetWindowRect(item
->hwnd
, &rc
);
1066 total_height
+= rc
.bottom
- rc
.top
;
1067 max_width
= max(rc
.right
- rc
.left
, max_width
);
1070 SetWindowPos(ctrl
->hwnd
, NULL
, 0, 0, max_width
, total_height
,
1071 SWP_NOZORDER
|SWP_NOMOVE
);
1073 SetWindowPos(ctrl
->wrapper_hwnd
, NULL
, 0, 0, max_width
, total_height
,
1074 SWP_NOZORDER
|SWP_NOMOVE
);
1078 case IDLG_CCTRL_EDITBOX
:
1079 case IDLG_CCTRL_SEPARATOR
:
1080 case IDLG_CCTRL_MENU
:
1081 case IDLG_CCTRL_OPENDROPDOWN
:
1087 static LRESULT
notifysink_on_create(HWND hwnd
, CREATESTRUCTW
*crs
)
1089 FileDialogImpl
*This
= crs
->lpCreateParams
;
1090 TRACE("%p\n", This
);
1092 SetWindowLongPtrW(hwnd
, GWLP_USERDATA
, (LPARAM
)This
);
1096 static LRESULT
notifysink_on_bn_clicked(FileDialogImpl
*This
, HWND hwnd
, WPARAM wparam
)
1098 customctrl
*ctrl
= get_cctrl_from_dlgid(This
, LOWORD(wparam
));
1100 TRACE("%p, %Ix\n", This
, wparam
);
1104 if(ctrl
->type
== IDLG_CCTRL_CHECKBUTTON
)
1106 BOOL checked
= (SendMessageW(ctrl
->hwnd
, BM_GETCHECK
, 0, 0) == BST_CHECKED
);
1107 cctrl_event_OnCheckButtonToggled(This
, ctrl
->id
, checked
);
1110 cctrl_event_OnButtonClicked(This
, ctrl
->id
);
1116 static LRESULT
notifysink_on_cbn_selchange(FileDialogImpl
*This
, HWND hwnd
, WPARAM wparam
)
1118 customctrl
*ctrl
= get_cctrl_from_dlgid(This
, LOWORD(wparam
));
1119 TRACE("%p, %p (%Ix)\n", This
, ctrl
, wparam
);
1123 UINT index
= SendMessageW(ctrl
->hwnd
, CB_GETCURSEL
, 0, 0);
1124 UINT selid
= SendMessageW(ctrl
->hwnd
, CB_GETITEMDATA
, index
, 0);
1126 cctrl_event_OnItemSelected(This
, ctrl
->id
, selid
);
1131 static LRESULT
notifysink_on_tvn_dropdown(FileDialogImpl
*This
, LPARAM lparam
)
1133 NMTOOLBARW
*nmtb
= (NMTOOLBARW
*)lparam
;
1134 customctrl
*ctrl
= get_cctrl_from_dlgid(This
, GetDlgCtrlID(nmtb
->hdr
.hwndFrom
));
1135 POINT pt
= { 0, nmtb
->rcButton
.bottom
};
1139 TRACE("%p, %p (%Ix)\n", This
, ctrl
, lparam
);
1143 cctrl_event_OnControlActivating(This
,ctrl
->id
);
1145 SendMessageW(ctrl
->hwnd
, TB_GETBUTTON
, 0, (LPARAM
)&tbb
);
1146 ClientToScreen(ctrl
->hwnd
, &pt
);
1147 idcmd
= TrackPopupMenu((HMENU
)tbb
.dwData
, TPM_RETURNCMD
, pt
.x
, pt
.y
, 0, This
->dlg_hwnd
, NULL
);
1149 cctrl_event_OnItemSelected(This
, ctrl
->id
, idcmd
);
1152 return TBDDRET_DEFAULT
;
1155 static LRESULT
notifysink_on_wm_command(FileDialogImpl
*This
, HWND hwnd
, WPARAM wparam
, LPARAM lparam
)
1157 switch(HIWORD(wparam
))
1159 case BN_CLICKED
: return notifysink_on_bn_clicked(This
, hwnd
, wparam
);
1160 case CBN_SELCHANGE
: return notifysink_on_cbn_selchange(This
, hwnd
, wparam
);
1166 static LRESULT
notifysink_on_wm_notify(FileDialogImpl
*This
, HWND hwnd
, WPARAM wparam
, LPARAM lparam
)
1168 NMHDR
*nmhdr
= (NMHDR
*)lparam
;
1172 case TBN_DROPDOWN
: return notifysink_on_tvn_dropdown(This
, lparam
);
1178 static LRESULT CALLBACK
notifysink_proc(HWND hwnd
, UINT message
, WPARAM wparam
, LPARAM lparam
)
1180 FileDialogImpl
*This
= (FileDialogImpl
*)GetWindowLongPtrW(hwnd
, GWLP_USERDATA
);
1187 case WM_NCCREATE
: return notifysink_on_create(hwnd
, (CREATESTRUCTW
*)lparam
);
1188 case WM_COMMAND
: return notifysink_on_wm_command(This
, hwnd
, wparam
, lparam
);
1189 case WM_NOTIFY
: return notifysink_on_wm_notify(This
, hwnd
, wparam
, lparam
);
1191 hwnd_child
= GetPropW(hwnd
, L
"nfs_child");
1192 ctrl
= (customctrl
*)GetWindowLongPtrW(hwnd_child
, GWLP_USERDATA
);
1193 if(ctrl
&& ctrl
->type
!= IDLG_CCTRL_VISUALGROUP
)
1195 GetClientRect(hwnd
, &rc
);
1196 SetWindowPos(hwnd_child
, NULL
, 0, 0, rc
.right
, rc
.bottom
, SWP_NOMOVE
|SWP_NOACTIVATE
|SWP_NOZORDER
);
1201 return DefWindowProcW(hwnd
, message
, wparam
, lparam
);
1204 static HRESULT
cctrl_create_new(FileDialogImpl
*This
, DWORD id
,
1205 LPCWSTR text
, LPCWSTR wndclass
, DWORD ctrl_wsflags
,
1206 DWORD ctrl_exflags
, UINT height
, customctrl
**ppctrl
)
1208 HWND ns_hwnd
, control_hwnd
, parent_hwnd
;
1209 DWORD wsflags
= WS_CHILD
| WS_VISIBLE
| WS_CLIPSIBLINGS
;
1212 if(get_cctrl(This
, id
))
1213 return E_UNEXPECTED
; /* Duplicate id */
1215 if(This
->cctrl_active_vg
)
1216 parent_hwnd
= This
->cctrl_active_vg
->wrapper_hwnd
;
1218 parent_hwnd
= This
->cctrls_hwnd
;
1220 ns_hwnd
= CreateWindowExW(0, L
"FloatNotifySink", NULL
, wsflags
,
1221 0, 0, This
->cctrl_width
, height
, parent_hwnd
,
1222 (HMENU
)This
->cctrl_next_dlgid
, COMDLG32_hInstance
, This
);
1223 control_hwnd
= CreateWindowExW(ctrl_exflags
, wndclass
, text
, wsflags
| ctrl_wsflags
,
1224 0, 0, This
->cctrl_width
, height
, ns_hwnd
,
1225 (HMENU
)This
->cctrl_next_dlgid
, COMDLG32_hInstance
, 0);
1227 if(!ns_hwnd
|| !control_hwnd
)
1229 ERR("Failed to create wrapper (%p) or control (%p)\n", ns_hwnd
, control_hwnd
);
1230 DestroyWindow(ns_hwnd
);
1231 DestroyWindow(control_hwnd
);
1236 SetPropW(ns_hwnd
, L
"nfs_child", control_hwnd
);
1238 ctrl
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(customctrl
));
1240 return E_OUTOFMEMORY
;
1242 ctrl
->hwnd
= control_hwnd
;
1243 ctrl
->wrapper_hwnd
= ns_hwnd
;
1245 ctrl
->dlgid
= This
->cctrl_next_dlgid
;
1246 ctrl
->cdcstate
= CDCS_ENABLED
| CDCS_VISIBLE
;
1247 list_init(&ctrl
->sub_cctrls
);
1248 list_init(&ctrl
->sub_items
);
1250 if(This
->cctrl_active_vg
)
1251 list_add_tail(&This
->cctrl_active_vg
->sub_cctrls
, &ctrl
->sub_cctrls_entry
);
1253 list_add_tail(&This
->cctrls
, &ctrl
->entry
);
1255 SetWindowLongPtrW(ctrl
->hwnd
, GWLP_USERDATA
, (LPARAM
)ctrl
);
1257 if(ppctrl
) *ppctrl
= ctrl
;
1259 This
->cctrl_next_dlgid
++;
1263 /**************************************************************************
1264 * Container functions.
1266 static UINT
ctrl_container_resize(FileDialogImpl
*This
, UINT container_width
)
1268 UINT container_height
;
1271 UINT max_control_height
, total_height
= 0;
1272 UINT cur_col_pos
, cur_row_pos
;
1275 UINT cspacing
= MulDiv(90, This
->dpi_x
, USER_DEFAULT_SCREEN_DPI
); /* Columns are spaced with 90px */
1276 UINT rspacing
= MulDiv(4, This
->dpi_y
, USER_DEFAULT_SCREEN_DPI
); /* Rows are spaced with 4 px. */
1278 /* Given the new width of the container, this function determines the
1279 * needed height of the container and places the controls according to
1280 * the new layout. Returns the new height.
1283 TRACE("%p\n", This
);
1285 column_width
= This
->cctrl_width
+ cspacing
;
1286 nr_of_cols
= (container_width
- This
->cctrl_indent
+ cspacing
) / column_width
;
1288 /* We don't need to do anything unless the number of visible columns has changed. */
1289 if(nr_of_cols
== This
->cctrls_cols
)
1292 GetWindowRect(This
->cctrls_hwnd
, &rc
);
1293 return rc
.bottom
- rc
.top
;
1296 This
->cctrls_cols
= nr_of_cols
;
1298 /* Get the size of the tallest control, and the total size of
1299 * all the controls to figure out the number of slots we need.
1301 max_control_height
= 0;
1302 LIST_FOR_EACH_ENTRY(ctrl
, &This
->cctrls
, customctrl
, entry
)
1304 if(ctrl
->cdcstate
& CDCS_VISIBLE
)
1306 UINT control_height
= ctrl_get_height(ctrl
);
1307 max_control_height
= max(max_control_height
, control_height
);
1309 total_height
+= control_height
+ rspacing
;
1316 container_height
= max(total_height
/ nr_of_cols
, max_control_height
+ rspacing
);
1317 TRACE("Guess: container_height: %d\n",container_height
);
1319 /* Incrementally increase container_height until all the controls
1323 UINT columns_needed
= 1;
1327 LIST_FOR_EACH_ENTRY(ctrl
, &This
->cctrls
, customctrl
, entry
)
1329 if(ctrl
->cdcstate
& CDCS_VISIBLE
)
1331 UINT control_height
= ctrl_get_height(ctrl
);
1333 if(cur_row_pos
+ control_height
> container_height
)
1335 if(++columns_needed
> nr_of_cols
)
1337 container_height
+= 1;
1338 fits_height
= FALSE
;
1344 cur_row_pos
+= control_height
+ rspacing
;
1347 } while(!fits_height
);
1349 TRACE("Final container height: %d\n", container_height
);
1351 /* Move the controls to their final destination
1353 cur_col_pos
= 0; cur_row_pos
= 0;
1354 LIST_FOR_EACH_ENTRY(ctrl
, &This
->cctrls
, customctrl
, entry
)
1356 if(ctrl
->cdcstate
& CDCS_VISIBLE
)
1359 UINT control_height
, control_indent
;
1360 GetWindowRect(ctrl
->wrapper_hwnd
, &rc
);
1361 control_height
= rc
.bottom
- rc
.top
;
1363 if(cur_row_pos
+ control_height
> container_height
)
1366 cur_col_pos
+= This
->cctrl_width
+ cspacing
;
1370 if(ctrl
->type
== IDLG_CCTRL_VISUALGROUP
)
1373 control_indent
= This
->cctrl_indent
;
1375 SetWindowPos(ctrl
->wrapper_hwnd
, NULL
, cur_col_pos
+ control_indent
, cur_row_pos
, 0, 0,
1376 SWP_NOACTIVATE
| SWP_NOSIZE
| SWP_NOZORDER
);
1378 cur_row_pos
+= control_height
+ rspacing
;
1383 if(cur_row_pos
+ This
->cctrl_width
> container_width
)
1384 ERR("-- Failed to place controls properly.\n");
1386 return container_height
;
1389 static void ctrl_set_font(customctrl
*ctrl
, HFONT font
)
1391 customctrl
*sub_ctrl
;
1394 SendMessageW(ctrl
->hwnd
, WM_SETFONT
, (WPARAM
)font
, TRUE
);
1396 LIST_FOR_EACH_ENTRY(sub_ctrl
, &ctrl
->sub_cctrls
, customctrl
, sub_cctrls_entry
)
1398 ctrl_set_font(sub_ctrl
, font
);
1401 if (ctrl
->type
== IDLG_CCTRL_RADIOBUTTONLIST
)
1403 LIST_FOR_EACH_ENTRY(item
, &ctrl
->sub_items
, cctrl_item
, entry
)
1405 SendMessageW(item
->hwnd
, WM_SETFONT
, (WPARAM
)font
, TRUE
);
1410 static void ctrl_container_reparent(FileDialogImpl
*This
, HWND parent
)
1419 wndstyle
= GetWindowLongW(This
->cctrls_hwnd
, GWL_STYLE
);
1420 wndstyle
&= ~(WS_POPUP
);
1421 wndstyle
|= WS_CHILD
;
1422 SetWindowLongW(This
->cctrls_hwnd
, GWL_STYLE
, wndstyle
);
1424 SetParent(This
->cctrls_hwnd
, parent
);
1425 ShowWindow(This
->cctrls_hwnd
, TRUE
);
1427 /* Set the fonts to match the dialog font. */
1428 font
= (HFONT
)SendMessageW(parent
, WM_GETFONT
, 0, 0);
1430 ERR("Failed to get font handle from dialog.\n");
1432 LIST_FOR_EACH_ENTRY(ctrl
, &This
->cctrls
, customctrl
, entry
)
1434 if(font
) ctrl_set_font(ctrl
, font
);
1435 customctrl_resize(This
, ctrl
);
1440 ShowWindow(This
->cctrls_hwnd
, FALSE
);
1442 wndstyle
= GetWindowLongW(This
->cctrls_hwnd
, GWL_STYLE
);
1443 wndstyle
&= ~(WS_CHILD
);
1444 wndstyle
|= WS_POPUP
;
1445 SetWindowLongW(This
->cctrls_hwnd
, GWL_STYLE
, wndstyle
);
1447 SetParent(This
->cctrls_hwnd
, NULL
);
1451 static LRESULT
ctrl_container_on_create(HWND hwnd
, CREATESTRUCTW
*crs
)
1453 FileDialogImpl
*This
= crs
->lpCreateParams
;
1454 TRACE("%p\n", This
);
1456 SetWindowLongPtrW(hwnd
, GWLP_USERDATA
, (LPARAM
)This
);
1460 static LRESULT
ctrl_container_on_wm_destroy(FileDialogImpl
*This
)
1462 customctrl
*cur1
, *cur2
;
1463 TRACE("%p\n", This
);
1465 LIST_FOR_EACH_ENTRY_SAFE(cur1
, cur2
, &This
->cctrls
, customctrl
, entry
)
1467 list_remove(&cur1
->entry
);
1474 static LRESULT CALLBACK
ctrl_container_wndproc(HWND hwnd
, UINT umessage
, WPARAM wparam
, LPARAM lparam
)
1476 FileDialogImpl
*This
= (FileDialogImpl
*)GetWindowLongPtrW(hwnd
, GWLP_USERDATA
);
1480 case WM_NCCREATE
: return ctrl_container_on_create(hwnd
, (CREATESTRUCTW
*)lparam
);
1481 case WM_DESTROY
: return ctrl_container_on_wm_destroy(This
);
1482 default: return DefWindowProcW(hwnd
, umessage
, wparam
, lparam
);
1488 static void radiobuttonlist_set_selected_item(FileDialogImpl
*This
, customctrl
*ctrl
, cctrl_item
*item
)
1492 LIST_FOR_EACH_ENTRY(cursor
, &ctrl
->sub_items
, cctrl_item
, entry
)
1494 SendMessageW(cursor
->hwnd
, BM_SETCHECK
, (cursor
== item
) ? BST_CHECKED
: BST_UNCHECKED
, 0);
1498 static LRESULT
radiobuttonlist_on_bn_clicked(FileDialogImpl
*This
, HWND hwnd
, HWND child
)
1500 DWORD ctrl_id
= (DWORD
)GetWindowLongPtrW(hwnd
, GWLP_ID
);
1503 BOOL found_item
=FALSE
;
1505 ctrl
= get_cctrl_from_dlgid(This
, ctrl_id
);
1509 ERR("Can't find this control\n");
1513 LIST_FOR_EACH_ENTRY(item
, &ctrl
->sub_items
, cctrl_item
, entry
)
1515 if (item
->hwnd
== child
)
1524 ERR("Can't find control item\n");
1528 radiobuttonlist_set_selected_item(This
, ctrl
, item
);
1530 cctrl_event_OnItemSelected(This
, ctrl
->id
, item
->id
);
1535 static LRESULT
radiobuttonlist_on_wm_command(FileDialogImpl
*This
, HWND hwnd
, WPARAM wparam
, LPARAM lparam
)
1537 switch(HIWORD(wparam
))
1539 case BN_CLICKED
: return radiobuttonlist_on_bn_clicked(This
, hwnd
, (HWND
)lparam
);
1545 static LRESULT CALLBACK
radiobuttonlist_proc(HWND hwnd
, UINT message
, WPARAM wparam
, LPARAM lparam
)
1547 FileDialogImpl
*This
= (FileDialogImpl
*)GetWindowLongPtrW(hwnd
, GWLP_USERDATA
);
1551 case WM_COMMAND
: return radiobuttonlist_on_wm_command(This
, hwnd
, wparam
, lparam
);
1554 return DefWindowProcW(hwnd
, message
, wparam
, lparam
);
1557 static HRESULT
init_custom_controls(FileDialogImpl
*This
)
1561 static const WCHAR ctrl_container_classname
[] = L
"idlg_container_pane";
1563 InitCommonControlsEx(NULL
);
1565 if( !GetClassInfoW(COMDLG32_hInstance
, ctrl_container_classname
, &wc
) )
1567 wc
.style
= CS_HREDRAW
| CS_VREDRAW
;
1568 wc
.lpfnWndProc
= ctrl_container_wndproc
;
1571 wc
.hInstance
= COMDLG32_hInstance
;
1573 wc
.hCursor
= LoadCursorW(0, (LPWSTR
)IDC_ARROW
);
1574 wc
.hbrBackground
= (HBRUSH
)(COLOR_BTNFACE
+ 1);
1575 wc
.lpszMenuName
= NULL
;
1576 wc
.lpszClassName
= ctrl_container_classname
;
1578 if(!RegisterClassW(&wc
)) return E_FAIL
;
1581 This
->cctrls_hwnd
= CreateWindowExW(0, ctrl_container_classname
, NULL
,
1582 WS_CLIPSIBLINGS
| WS_CLIPCHILDREN
,
1583 0, 0, 0, 0, NULL
, 0,
1584 COMDLG32_hInstance
, This
);
1585 if(!This
->cctrls_hwnd
)
1588 hdc
= GetDC(This
->cctrls_hwnd
);
1589 This
->dpi_x
= GetDeviceCaps(hdc
, LOGPIXELSX
);
1590 This
->dpi_y
= GetDeviceCaps(hdc
, LOGPIXELSY
);
1591 ReleaseDC(This
->cctrls_hwnd
, hdc
);
1593 This
->cctrl_width
= MulDiv(160, This
->dpi_x
, USER_DEFAULT_SCREEN_DPI
); /* Controls have a fixed width */
1594 This
->cctrl_indent
= MulDiv(100, This
->dpi_x
, USER_DEFAULT_SCREEN_DPI
);
1595 This
->cctrl_def_height
= MulDiv(23, This
->dpi_y
, USER_DEFAULT_SCREEN_DPI
);
1596 This
->cctrls_cols
= 0;
1598 This
->cctrl_next_dlgid
= 0x2000;
1599 list_init(&This
->cctrls
);
1600 This
->cctrl_active_vg
= NULL
;
1602 SetWindowLongW(This
->cctrls_hwnd
, GWL_STYLE
, WS_TABSTOP
);
1604 /* Register class for */
1605 if (!GetClassInfoW(COMDLG32_hInstance
, L
"FloatNotifySink", &wc
) ||
1606 wc
.hInstance
!= COMDLG32_hInstance
)
1608 wc
.style
= CS_HREDRAW
| CS_VREDRAW
;
1609 wc
.lpfnWndProc
= notifysink_proc
;
1612 wc
.hInstance
= COMDLG32_hInstance
;
1614 wc
.hCursor
= LoadCursorW(0, (LPWSTR
)IDC_ARROW
);
1615 wc
.hbrBackground
= (HBRUSH
)(COLOR_BTNFACE
+ 1);
1616 wc
.lpszMenuName
= NULL
;
1617 wc
.lpszClassName
= L
"FloatNotifySink";
1619 if (!RegisterClassW(&wc
))
1620 ERR("Failed to register FloatNotifySink window class.\n");
1623 if (!GetClassInfoW(COMDLG32_hInstance
, L
"RadioButtonList", &wc
) ||
1624 wc
.hInstance
!= COMDLG32_hInstance
)
1626 wc
.style
= CS_HREDRAW
| CS_VREDRAW
;
1627 wc
.lpfnWndProc
= radiobuttonlist_proc
;
1630 wc
.hInstance
= COMDLG32_hInstance
;
1632 wc
.hCursor
= LoadCursorW(0, (LPWSTR
)IDC_ARROW
);
1633 wc
.hbrBackground
= (HBRUSH
)(COLOR_BTNFACE
+ 1);
1634 wc
.lpszMenuName
= NULL
;
1635 wc
.lpszClassName
= L
"RadioButtonList";
1637 if (!RegisterClassW(&wc
))
1638 ERR("Failed to register RadioButtonList window class.\n");
1644 /**************************************************************************
1645 * Window related functions.
1647 static BOOL
update_open_dropdown(FileDialogImpl
*This
)
1649 /* Show or hide the open dropdown button as appropriate */
1650 BOOL show
=FALSE
, showing
;
1651 HWND open_hwnd
, dropdown_hwnd
;
1653 if (This
->hmenu_opendropdown
)
1655 INT num_visible_items
=0;
1658 LIST_FOR_EACH_ENTRY(item
, &This
->cctrl_opendropdown
.sub_items
, cctrl_item
, entry
)
1660 if (item
->cdcstate
& CDCS_VISIBLE
)
1662 num_visible_items
++;
1663 if (num_visible_items
>= 2)
1672 open_hwnd
= GetDlgItem(This
->dlg_hwnd
, IDOK
);
1673 dropdown_hwnd
= GetDlgItem(This
->dlg_hwnd
, psh1
);
1675 showing
= (GetWindowLongPtrW(dropdown_hwnd
, GWL_STYLE
) & WS_VISIBLE
) != 0;
1677 if (showing
!= show
)
1679 RECT open_rc
, dropdown_rc
;
1681 GetWindowRect(open_hwnd
, &open_rc
);
1682 GetWindowRect(dropdown_hwnd
, &dropdown_rc
);
1686 ShowWindow(dropdown_hwnd
, SW_SHOW
);
1688 SetWindowPos(open_hwnd
, NULL
, 0, 0,
1689 (open_rc
.right
- open_rc
.left
) - (dropdown_rc
.right
- dropdown_rc
.left
),
1690 open_rc
.bottom
- open_rc
.top
, SWP_NOZORDER
| SWP_NOMOVE
| SWP_NOACTIVATE
);
1694 ShowWindow(dropdown_hwnd
, SW_HIDE
);
1696 SetWindowPos(open_hwnd
, NULL
, 0, 0,
1697 (open_rc
.right
- open_rc
.left
) + (dropdown_rc
.right
- dropdown_rc
.left
),
1698 open_rc
.bottom
- open_rc
.top
, SWP_NOZORDER
| SWP_NOMOVE
| SWP_NOACTIVATE
);
1705 static void update_layout(FileDialogImpl
*This
)
1710 RECT cancel_rc
, dropdown_rc
, open_rc
;
1711 RECT filetype_rc
, filename_rc
, filenamelabel_rc
;
1712 RECT toolbar_rc
, ebrowser_rc
, customctrls_rc
;
1713 static const UINT vspacing
= 4, hspacing
= 4;
1714 static const UINT min_width
= 320, min_height
= 200;
1717 if (!GetClientRect(This
->dlg_hwnd
, &dialog_rc
))
1719 TRACE("Invalid dialog window, not updating layout\n");
1723 if(dialog_rc
.right
< min_width
|| dialog_rc
.bottom
< min_height
)
1725 TRACE("Dialog size (%ld, %ld) too small, not updating layout\n", dialog_rc
.right
, dialog_rc
.bottom
);
1730 * Calculate the size of the dialog and all the parts.
1734 hwnd
= GetDlgItem(This
->dlg_hwnd
, IDCANCEL
);
1737 int cancel_width
, cancel_height
;
1738 GetWindowRect(hwnd
, &cancel_rc
);
1739 cancel_width
= cancel_rc
.right
- cancel_rc
.left
;
1740 cancel_height
= cancel_rc
.bottom
- cancel_rc
.top
;
1742 cancel_rc
.left
= dialog_rc
.right
- cancel_width
- hspacing
;
1743 cancel_rc
.top
= dialog_rc
.bottom
- cancel_height
- vspacing
;
1744 cancel_rc
.right
= cancel_rc
.left
+ cancel_width
;
1745 cancel_rc
.bottom
= cancel_rc
.top
+ cancel_height
;
1748 /* Open/Save dropdown */
1749 show_dropdown
= update_open_dropdown(This
);
1753 int dropdown_width
, dropdown_height
;
1754 hwnd
= GetDlgItem(This
->dlg_hwnd
, psh1
);
1756 GetWindowRect(hwnd
, &dropdown_rc
);
1757 dropdown_width
= dropdown_rc
.right
- dropdown_rc
.left
;
1758 dropdown_height
= dropdown_rc
.bottom
- dropdown_rc
.top
;
1760 dropdown_rc
.left
= cancel_rc
.left
- dropdown_width
- hspacing
;
1761 dropdown_rc
.top
= cancel_rc
.top
;
1762 dropdown_rc
.right
= dropdown_rc
.left
+ dropdown_width
;
1763 dropdown_rc
.bottom
= dropdown_rc
.top
+ dropdown_height
;
1767 dropdown_rc
.left
= dropdown_rc
.right
= cancel_rc
.left
- hspacing
;
1768 dropdown_rc
.top
= cancel_rc
.top
;
1769 dropdown_rc
.bottom
= cancel_rc
.bottom
;
1772 /* Open/Save button */
1773 hwnd
= GetDlgItem(This
->dlg_hwnd
, IDOK
);
1776 int open_width
, open_height
;
1777 GetWindowRect(hwnd
, &open_rc
);
1778 open_width
= open_rc
.right
- open_rc
.left
;
1779 open_height
= open_rc
.bottom
- open_rc
.top
;
1781 open_rc
.left
= dropdown_rc
.left
- open_width
;
1782 open_rc
.top
= dropdown_rc
.top
;
1783 open_rc
.right
= open_rc
.left
+ open_width
;
1784 open_rc
.bottom
= open_rc
.top
+ open_height
;
1787 /* The filetype combobox. */
1788 hwnd
= GetDlgItem(This
->dlg_hwnd
, IDC_FILETYPE
);
1791 int filetype_width
, filetype_height
;
1792 GetWindowRect(hwnd
, &filetype_rc
);
1794 filetype_width
= filetype_rc
.right
- filetype_rc
.left
;
1795 filetype_height
= filetype_rc
.bottom
- filetype_rc
.top
;
1797 filetype_rc
.right
= cancel_rc
.right
;
1799 filetype_rc
.left
= filetype_rc
.right
- filetype_width
;
1800 filetype_rc
.top
= cancel_rc
.top
- filetype_height
- vspacing
;
1801 filetype_rc
.bottom
= filetype_rc
.top
+ filetype_height
;
1803 if(!This
->filterspec_count
)
1804 filetype_rc
.left
= filetype_rc
.right
;
1807 /* Filename label. */
1808 hwnd
= GetDlgItem(This
->dlg_hwnd
, IDC_FILENAMESTATIC
);
1811 int filetypelabel_width
, filetypelabel_height
;
1812 GetWindowRect(hwnd
, &filenamelabel_rc
);
1814 filetypelabel_width
= filenamelabel_rc
.right
- filenamelabel_rc
.left
;
1815 filetypelabel_height
= filenamelabel_rc
.bottom
- filenamelabel_rc
.top
;
1817 filenamelabel_rc
.left
= 160; /* FIXME */
1818 filenamelabel_rc
.top
= filetype_rc
.top
;
1819 filenamelabel_rc
.right
= filenamelabel_rc
.left
+ filetypelabel_width
;
1820 filenamelabel_rc
.bottom
= filenamelabel_rc
.top
+ filetypelabel_height
;
1823 /* Filename edit box. */
1824 hwnd
= GetDlgItem(This
->dlg_hwnd
, IDC_FILENAME
);
1827 int filename_width
, filename_height
;
1828 GetWindowRect(hwnd
, &filename_rc
);
1830 filename_width
= filetype_rc
.left
- filenamelabel_rc
.right
- hspacing
*2;
1831 filename_height
= filename_rc
.bottom
- filename_rc
.top
;
1833 filename_rc
.left
= filenamelabel_rc
.right
+ hspacing
;
1834 filename_rc
.top
= filetype_rc
.top
;
1835 filename_rc
.right
= filename_rc
.left
+ filename_width
;
1836 filename_rc
.bottom
= filename_rc
.top
+ filename_height
;
1839 hwnd
= GetDlgItem(This
->dlg_hwnd
, IDC_NAV_TOOLBAR
);
1842 GetWindowRect(hwnd
, &toolbar_rc
);
1843 MapWindowPoints(NULL
, This
->dlg_hwnd
, (POINT
*)&toolbar_rc
, 2);
1846 /* The custom controls */
1847 customctrls_rc
.left
= dialog_rc
.left
+ hspacing
;
1848 customctrls_rc
.right
= dialog_rc
.right
- hspacing
;
1849 customctrls_rc
.bottom
= filename_rc
.top
- vspacing
;
1850 customctrls_rc
.top
= customctrls_rc
.bottom
-
1851 ctrl_container_resize(This
, customctrls_rc
.right
- customctrls_rc
.left
);
1853 /* The ExplorerBrowser control. */
1854 ebrowser_rc
.left
= dialog_rc
.left
+ hspacing
;
1855 ebrowser_rc
.top
= toolbar_rc
.bottom
+ vspacing
;
1856 ebrowser_rc
.right
= dialog_rc
.right
- hspacing
;
1857 ebrowser_rc
.bottom
= customctrls_rc
.top
- vspacing
;
1860 * Move everything to the right place.
1863 /* FIXME: The Save Dialog uses a slightly different layout. */
1864 hdwp
= BeginDeferWindowPos(7);
1866 if(hdwp
&& This
->peb
)
1867 IExplorerBrowser_SetRect(This
->peb
, &hdwp
, ebrowser_rc
);
1869 if(hdwp
&& This
->cctrls_hwnd
)
1870 DeferWindowPos(hdwp
, This
->cctrls_hwnd
, NULL
,
1871 customctrls_rc
.left
, customctrls_rc
.top
,
1872 customctrls_rc
.right
- customctrls_rc
.left
, customctrls_rc
.bottom
- customctrls_rc
.top
,
1873 SWP_NOZORDER
| SWP_NOACTIVATE
);
1875 /* The default controls */
1876 if(hdwp
&& (hwnd
= GetDlgItem(This
->dlg_hwnd
, IDC_FILETYPE
)) )
1877 DeferWindowPos(hdwp
, hwnd
, NULL
, filetype_rc
.left
, filetype_rc
.top
, 0, 0,
1878 SWP_NOZORDER
| SWP_NOSIZE
| SWP_NOACTIVATE
);
1880 if(hdwp
&& (hwnd
= GetDlgItem(This
->dlg_hwnd
, IDC_FILENAME
)) )
1881 DeferWindowPos(hdwp
, hwnd
, NULL
, filename_rc
.left
, filename_rc
.top
,
1882 filename_rc
.right
- filename_rc
.left
, filename_rc
.bottom
- filename_rc
.top
,
1883 SWP_NOZORDER
| SWP_NOACTIVATE
);
1885 if(hdwp
&& (hwnd
= GetDlgItem(This
->dlg_hwnd
, IDC_FILENAMESTATIC
)) )
1886 DeferWindowPos(hdwp
, hwnd
, NULL
, filenamelabel_rc
.left
, filenamelabel_rc
.top
, 0, 0,
1887 SWP_NOZORDER
| SWP_NOSIZE
| SWP_NOACTIVATE
);
1889 if(hdwp
&& (hwnd
= GetDlgItem(This
->dlg_hwnd
, IDOK
)) )
1890 DeferWindowPos(hdwp
, hwnd
, NULL
, open_rc
.left
, open_rc
.top
, 0, 0,
1891 SWP_NOZORDER
| SWP_NOSIZE
| SWP_NOACTIVATE
);
1893 if(hdwp
&& This
->hmenu_opendropdown
&& (hwnd
= GetDlgItem(This
->dlg_hwnd
, psh1
)))
1894 DeferWindowPos(hdwp
, hwnd
, NULL
, dropdown_rc
.left
, dropdown_rc
.top
, 0, 0,
1895 SWP_NOZORDER
| SWP_NOSIZE
| SWP_NOACTIVATE
);
1897 if(hdwp
&& (hwnd
= GetDlgItem(This
->dlg_hwnd
, IDCANCEL
)) )
1898 DeferWindowPos(hdwp
, hwnd
, NULL
, cancel_rc
.left
, cancel_rc
.top
, 0, 0,
1899 SWP_NOZORDER
| SWP_NOSIZE
| SWP_NOACTIVATE
);
1902 EndDeferWindowPos(hdwp
);
1904 ERR("Failed to position dialog controls.\n");
1909 static HRESULT
init_explorerbrowser(FileDialogImpl
*This
)
1911 IShellItem
*psi_folder
;
1912 IObjectWithSite
*client
;
1917 /* Create ExplorerBrowser instance */
1918 OleInitialize(NULL
);
1920 hr
= CoCreateInstance(&CLSID_ExplorerBrowser
, NULL
, CLSCTX_INPROC_SERVER
,
1921 &IID_IExplorerBrowser
, (void**)&This
->peb
);
1924 ERR("Failed to instantiate ExplorerBrowser control.\n");
1928 IExplorerBrowser_SetOptions(This
->peb
, EBO_SHOWFRAMES
| EBO_NOBORDER
);
1930 hr
= IExplorerBrowser_Initialize(This
->peb
, This
->dlg_hwnd
, &rc
, NULL
);
1933 ERR("Failed to initialize the ExplorerBrowser control.\n");
1934 IExplorerBrowser_Release(This
->peb
);
1938 hr
= IExplorerBrowser_Advise(This
->peb
, &This
->IExplorerBrowserEvents_iface
, &This
->ebevents_cookie
);
1940 ERR("Advise (ExplorerBrowser) failed.\n");
1942 /* Get previous options? */
1943 fos
.ViewMode
= fos
.fFlags
= 0;
1944 if(!(This
->options
& FOS_ALLOWMULTISELECT
))
1945 fos
.fFlags
|= FWF_SINGLESEL
;
1947 IExplorerBrowser_SetFolderSettings(This
->peb
, &fos
);
1949 hr
= IExplorerBrowser_QueryInterface(This
->peb
, &IID_IObjectWithSite
, (void**)&client
);
1952 hr
= IObjectWithSite_SetSite(client
, (IUnknown
*)&This
->IFileDialog2_iface
);
1953 IObjectWithSite_Release(client
);
1955 ERR("SetSite failed, 0x%08lx\n", hr
);
1958 /* Browse somewhere */
1959 psi_folder
= This
->psi_setfolder
? This
->psi_setfolder
: This
->psi_defaultfolder
;
1960 IExplorerBrowser_BrowseToObject(This
->peb
, (IUnknown
*)psi_folder
, SBSP_DEFBROWSER
);
1965 static void init_toolbar(FileDialogImpl
*This
, HWND hwnd
)
1973 htoolbar
= CreateWindowExW(0, TOOLBARCLASSNAMEW
, NULL
, TBSTYLE_FLAT
| WS_CHILD
| WS_VISIBLE
,
1975 hwnd
, (HMENU
)IDC_NAV_TOOLBAR
, NULL
, NULL
);
1977 tbab
.hInst
= HINST_COMMCTRL
;
1978 tbab
.nID
= IDB_HIST_LARGE_COLOR
;
1979 SendMessageW(htoolbar
, TB_ADDBITMAP
, 0, (LPARAM
)&tbab
);
1980 tbab
.nID
= IDB_VIEW_LARGE_COLOR
;
1981 navUpImgIndex
= SendMessageW(htoolbar
, TB_ADDBITMAP
, 0, (LPARAM
)&tbab
);
1982 navUpImgIndex
+= VIEW_PARENTFOLDER
;
1984 button
[0].iBitmap
= HIST_BACK
;
1985 button
[0].idCommand
= IDC_NAVBACK
;
1986 button
[0].fsState
= TBSTATE_ENABLED
;
1987 button
[0].fsStyle
= BTNS_BUTTON
;
1988 button
[0].dwData
= 0;
1989 button
[0].iString
= 0;
1991 button
[1].iBitmap
= HIST_FORWARD
;
1992 button
[1].idCommand
= IDC_NAVFORWARD
;
1993 button
[1].fsState
= TBSTATE_ENABLED
;
1994 button
[1].fsStyle
= BTNS_BUTTON
;
1995 button
[1].dwData
= 0;
1996 button
[1].iString
= 0;
1998 button
[2].iBitmap
= navUpImgIndex
;
1999 button
[2].idCommand
= IDC_NAVUP
;
2000 button
[2].fsState
= TBSTATE_ENABLED
;
2001 button
[2].fsStyle
= BTNS_BUTTON
;
2002 button
[2].dwData
= 0;
2003 button
[2].iString
= 0;
2005 SendMessageW(htoolbar
, TB_ADDBUTTONSW
, 3, (LPARAM
)button
);
2006 height
= MulDiv(24, This
->dpi_y
, USER_DEFAULT_SCREEN_DPI
);
2007 SendMessageW(htoolbar
, TB_SETBUTTONSIZE
, 0, MAKELPARAM(height
, height
));
2008 SendMessageW(htoolbar
, TB_AUTOSIZE
, 0, 0);
2011 static void update_control_text(FileDialogImpl
*This
)
2014 LPCWSTR custom_okbutton
;
2016 UINT min_width
= MulDiv(50, This
->dpi_x
, USER_DEFAULT_SCREEN_DPI
);
2017 UINT max_width
= MulDiv(250, This
->dpi_x
, USER_DEFAULT_SCREEN_DPI
);
2019 if(This
->custom_title
)
2020 SetWindowTextW(This
->dlg_hwnd
, This
->custom_title
);
2022 if(This
->hmenu_opendropdown
&& (item
= get_first_item(&This
->cctrl_opendropdown
)))
2023 custom_okbutton
= item
->label
;
2025 custom_okbutton
= This
->custom_okbutton
;
2027 if(custom_okbutton
&&
2028 (hitem
= GetDlgItem(This
->dlg_hwnd
, IDOK
)))
2030 SetWindowTextW(hitem
, custom_okbutton
);
2031 ctrl_resize(hitem
, min_width
, max_width
, FALSE
);
2034 if(This
->custom_cancelbutton
&&
2035 (hitem
= GetDlgItem(This
->dlg_hwnd
, IDCANCEL
)))
2037 SetWindowTextW(hitem
, This
->custom_cancelbutton
);
2038 ctrl_resize(hitem
, min_width
, max_width
, FALSE
);
2041 if(This
->custom_filenamelabel
&&
2042 (hitem
= GetDlgItem(This
->dlg_hwnd
, IDC_FILENAMESTATIC
)))
2044 SetWindowTextW(hitem
, This
->custom_filenamelabel
);
2045 ctrl_resize(hitem
, min_width
, max_width
, FALSE
);
2049 static LRESULT CALLBACK
dropdown_subclass_proc(HWND hwnd
, UINT umessage
, WPARAM wparam
, LPARAM lparam
)
2051 if (umessage
== WM_LBUTTONDOWN
)
2053 FileDialogImpl
*This
= GetPropW(hwnd
, L
"itemdlg_This");
2055 SendMessageW(hwnd
, BM_SETCHECK
, BST_CHECKED
, 0);
2056 show_opendropdown(This
);
2057 SendMessageW(hwnd
, BM_SETCHECK
, BST_UNCHECKED
, 0);
2062 return CallWindowProcW((WNDPROC
)GetPropW(hwnd
, L
"itemdlg_oldwndproc"), hwnd
, umessage
, wparam
, lparam
);
2065 static LRESULT
on_wm_initdialog(HWND hwnd
, LPARAM lParam
)
2067 FileDialogImpl
*This
= (FileDialogImpl
*)lParam
;
2070 TRACE("(%p, %p)\n", This
, hwnd
);
2072 SetWindowLongPtrW(hwnd
, GWLP_USERDATA
, (LPARAM
)This
);
2073 This
->dlg_hwnd
= hwnd
;
2075 hitem
= GetDlgItem(This
->dlg_hwnd
, pshHelp
);
2076 if(hitem
) ShowWindow(hitem
, SW_HIDE
);
2078 hitem
= GetDlgItem(This
->dlg_hwnd
, IDC_FILETYPESTATIC
);
2079 if(hitem
) ShowWindow(hitem
, SW_HIDE
);
2081 /* Fill filetypes combobox, or hide it. */
2082 hitem
= GetDlgItem(This
->dlg_hwnd
, IDC_FILETYPE
);
2083 if(This
->filterspec_count
)
2088 UINT i
, maxwidth
= 0;
2091 font
= (HFONT
)SendMessageW(hitem
, WM_GETFONT
, 0, 0);
2092 SelectObject(hdc
, font
);
2094 for(i
= 0; i
< This
->filterspec_count
; i
++)
2096 SendMessageW(hitem
, CB_ADDSTRING
, 0, (LPARAM
)This
->filterspecs
[i
].pszName
);
2098 if(GetTextExtentPoint32W(hdc
, This
->filterspecs
[i
].pszName
, lstrlenW(This
->filterspecs
[i
].pszName
), &size
))
2099 maxwidth
= max(maxwidth
, size
.cx
);
2101 ReleaseDC(hitem
, hdc
);
2105 maxwidth
+= GetSystemMetrics(SM_CXVSCROLL
) + 4;
2106 SendMessageW(hitem
, CB_SETDROPPEDWIDTH
, (WPARAM
)maxwidth
, 0);
2109 ERR("Failed to calculate width of filetype dropdown\n");
2111 SendMessageW(hitem
, CB_SETCURSEL
, This
->filetypeindex
, 0);
2114 ShowWindow(hitem
, SW_HIDE
);
2116 if(This
->set_filename
&&
2117 (hitem
= GetDlgItem(This
->dlg_hwnd
, IDC_FILENAME
)) )
2118 SendMessageW(hitem
, WM_SETTEXT
, 0, (LPARAM
)This
->set_filename
);
2120 if(This
->hmenu_opendropdown
)
2123 LOGFONTW lfw
, lfw_marlett
;
2126 dropdown_hwnd
= GetDlgItem(This
->dlg_hwnd
, psh1
);
2128 /* Change dropdown button font to Marlett */
2129 dialog_font
= (HFONT
)SendMessageW(dropdown_hwnd
, WM_GETFONT
, 0, 0);
2131 GetObjectW(dialog_font
, sizeof(lfw
), &lfw
);
2133 memset(&lfw_marlett
, 0, sizeof(lfw_marlett
));
2134 lstrcpyW(lfw_marlett
.lfFaceName
, L
"Marlett");
2135 lfw_marlett
.lfHeight
= lfw
.lfHeight
;
2136 lfw_marlett
.lfCharSet
= SYMBOL_CHARSET
;
2138 This
->hfont_opendropdown
= CreateFontIndirectW(&lfw_marlett
);
2140 SendMessageW(dropdown_hwnd
, WM_SETFONT
, (LPARAM
)This
->hfont_opendropdown
, 0);
2142 /* Subclass button so we can handle LBUTTONDOWN */
2143 SetPropW(dropdown_hwnd
, L
"itemdlg_This", This
);
2144 SetPropW(dropdown_hwnd
, L
"itemdlg_oldwndproc",
2145 (HANDLE
)SetWindowLongPtrW(dropdown_hwnd
, GWLP_WNDPROC
, (LONG_PTR
)dropdown_subclass_proc
));
2148 ctrl_container_reparent(This
, This
->dlg_hwnd
);
2149 init_explorerbrowser(This
);
2150 init_toolbar(This
, hwnd
);
2151 update_control_text(This
);
2152 update_layout(This
);
2154 if(This
->filterspec_count
)
2155 events_OnTypeChange(This
);
2157 if ((hitem
= GetDlgItem(This
->dlg_hwnd
, IDC_FILENAME
)))
2163 static LRESULT
on_wm_size(FileDialogImpl
*This
)
2165 update_layout(This
);
2169 static LRESULT
on_wm_getminmaxinfo(FileDialogImpl
*This
, LPARAM lparam
)
2171 MINMAXINFO
*mmi
= (MINMAXINFO
*)lparam
;
2172 TRACE("%p (%p)\n", This
, mmi
);
2175 mmi
->ptMinTrackSize
.x
= 640;
2176 mmi
->ptMinTrackSize
.y
= 480;
2181 static LRESULT
on_wm_destroy(FileDialogImpl
*This
)
2183 TRACE("%p\n", This
);
2187 IExplorerBrowser_Destroy(This
->peb
);
2188 IExplorerBrowser_Release(This
->peb
);
2192 ctrl_container_reparent(This
, NULL
);
2193 This
->dlg_hwnd
= NULL
;
2195 DeleteObject(This
->hfont_opendropdown
);
2196 This
->hfont_opendropdown
= NULL
;
2201 static LRESULT
on_idok(FileDialogImpl
*This
)
2203 TRACE("%p\n", This
);
2205 if(SUCCEEDED(on_default_action(This
)))
2206 EndDialog(This
->dlg_hwnd
, S_OK
);
2211 static LRESULT
on_idcancel(FileDialogImpl
*This
)
2213 TRACE("%p\n", This
);
2215 EndDialog(This
->dlg_hwnd
, HRESULT_FROM_WIN32(ERROR_CANCELLED
));
2220 static LRESULT
on_command_opendropdown(FileDialogImpl
*This
, WPARAM wparam
, LPARAM lparam
)
2222 if(HIWORD(wparam
) == BN_CLICKED
)
2224 HWND hwnd
= (HWND
)lparam
;
2225 SendMessageW(hwnd
, BM_SETCHECK
, BST_CHECKED
, 0);
2226 show_opendropdown(This
);
2227 SendMessageW(hwnd
, BM_SETCHECK
, BST_UNCHECKED
, 0);
2233 static LRESULT
on_browse_back(FileDialogImpl
*This
)
2235 TRACE("%p\n", This
);
2236 IExplorerBrowser_BrowseToIDList(This
->peb
, NULL
, SBSP_NAVIGATEBACK
);
2240 static LRESULT
on_browse_forward(FileDialogImpl
*This
)
2242 TRACE("%p\n", This
);
2243 IExplorerBrowser_BrowseToIDList(This
->peb
, NULL
, SBSP_NAVIGATEFORWARD
);
2247 static LRESULT
on_command_filetype(FileDialogImpl
*This
, WPARAM wparam
, LPARAM lparam
)
2249 if(HIWORD(wparam
) == CBN_SELCHANGE
)
2254 UINT prev_index
= This
->filetypeindex
;
2256 This
->filetypeindex
= SendMessageW((HWND
)lparam
, CB_GETCURSEL
, 0, 0);
2257 TRACE("File type selection changed to %d.\n", This
->filetypeindex
);
2259 if(prev_index
== This
->filetypeindex
)
2262 hr
= IExplorerBrowser_GetCurrentView(This
->peb
, &IID_IShellView
, (void**)&psv
);
2265 IShellView_Refresh(psv
);
2266 IShellView_Release(psv
);
2269 if(This
->dlg_type
== ITEMDLG_TYPE_SAVE
&& get_file_name(This
, &filename
))
2271 WCHAR buf
[MAX_PATH
], extbuf
[MAX_PATH
], *ext
;
2273 ext
= get_first_ext_from_spec(extbuf
, This
->filterspecs
[This
->filetypeindex
].pszSpec
);
2276 lstrcpyW(buf
, filename
);
2278 if(PathMatchSpecW(buf
, This
->filterspecs
[prev_index
].pszSpec
))
2279 PathRemoveExtensionW(buf
);
2282 set_file_name(This
, buf
);
2284 CoTaskMemFree(filename
);
2287 /* The documentation claims that OnTypeChange is called only
2288 * when the dialog is opened, but this is obviously not the
2290 events_OnTypeChange(This
);
2296 static LRESULT
on_browse_up(FileDialogImpl
*This
)
2298 TRACE("%p\n", This
);
2299 IExplorerBrowser_BrowseToIDList(This
->peb
, NULL
, SBSP_PARENT
);
2303 static LRESULT
on_wm_command(FileDialogImpl
*This
, WPARAM wparam
, LPARAM lparam
)
2305 switch(LOWORD(wparam
))
2307 case IDOK
: return on_idok(This
);
2308 case IDCANCEL
: return on_idcancel(This
);
2309 case psh1
: return on_command_opendropdown(This
, wparam
, lparam
);
2310 case IDC_NAVBACK
: return on_browse_back(This
);
2311 case IDC_NAVFORWARD
: return on_browse_forward(This
);
2312 case IDC_FILETYPE
: return on_command_filetype(This
, wparam
, lparam
);
2313 case IDC_NAVUP
: return on_browse_up(This
);
2314 default: TRACE("Unknown command.\n");
2319 static INT_PTR CALLBACK
itemdlg_dlgproc(HWND hwnd
, UINT umessage
, WPARAM wparam
, LPARAM lparam
)
2321 FileDialogImpl
*This
= (FileDialogImpl
*)GetWindowLongPtrW(hwnd
, GWLP_USERDATA
);
2325 case WM_INITDIALOG
: return on_wm_initdialog(hwnd
, lparam
);
2326 case WM_COMMAND
: return on_wm_command(This
, wparam
, lparam
);
2327 case WM_SIZE
: return on_wm_size(This
);
2328 case WM_GETMINMAXINFO
: return on_wm_getminmaxinfo(This
, lparam
);
2329 case WM_DESTROY
: return on_wm_destroy(This
);
2335 static HRESULT
create_dialog(FileDialogImpl
*This
, HWND parent
)
2337 ULONG_PTR ctx_cookie
= 0;
2341 return E_UNEXPECTED
;
2343 if (!GetCurrentActCtx(&This
->user_actctx
))
2344 This
->user_actctx
= INVALID_HANDLE_VALUE
;
2346 if (COMDLG32_hActCtx
!= INVALID_HANDLE_VALUE
)
2347 ActivateActCtx(COMDLG32_hActCtx
, &ctx_cookie
);
2350 res
= DialogBoxParamW(COMDLG32_hInstance
,
2351 MAKEINTRESOURCEW(NEWFILEOPENV3ORD
),
2352 parent
, itemdlg_dlgproc
, (LPARAM
)This
);
2353 This
->dlg_hwnd
= NULL
;
2355 if (COMDLG32_hActCtx
!= INVALID_HANDLE_VALUE
)
2356 DeactivateActCtx(0, ctx_cookie
);
2358 if (This
->user_actctx
!= INVALID_HANDLE_VALUE
)
2360 ReleaseActCtx(This
->user_actctx
);
2361 This
->user_actctx
= INVALID_HANDLE_VALUE
;
2366 ERR("Failed to show dialog (LastError: %ld)\n", GetLastError());
2370 TRACE("Returning 0x%08lx\n", (HRESULT
)res
);
2371 return (HRESULT
)res
;
2374 /**************************************************************************
2375 * IFileDialog implementation
2377 static inline FileDialogImpl
*impl_from_IFileDialog2(IFileDialog2
*iface
)
2379 return CONTAINING_RECORD(iface
, FileDialogImpl
, IFileDialog2_iface
);
2382 static HRESULT WINAPI
IFileDialog2_fnQueryInterface(IFileDialog2
*iface
,
2386 FileDialogImpl
*This
= impl_from_IFileDialog2(iface
);
2387 TRACE("%p (%s, %p)\n", This
, debugstr_guid(riid
), ppvObject
);
2390 if(IsEqualGUID(riid
, &IID_IUnknown
) ||
2391 IsEqualGUID(riid
, &IID_IFileDialog
) ||
2392 IsEqualGUID(riid
, &IID_IFileDialog2
))
2396 else if(IsEqualGUID(riid
, &IID_IFileOpenDialog
) && This
->dlg_type
== ITEMDLG_TYPE_OPEN
)
2398 *ppvObject
= &This
->u
.IFileOpenDialog_iface
;
2400 else if(IsEqualGUID(riid
, &IID_IFileSaveDialog
) && This
->dlg_type
== ITEMDLG_TYPE_SAVE
)
2402 *ppvObject
= &This
->u
.IFileSaveDialog_iface
;
2404 else if(IsEqualGUID(riid
, &IID_IExplorerBrowserEvents
))
2406 *ppvObject
= &This
->IExplorerBrowserEvents_iface
;
2408 else if(IsEqualGUID(riid
, &IID_IServiceProvider
))
2410 *ppvObject
= &This
->IServiceProvider_iface
;
2412 else if(IsEqualGUID(&IID_ICommDlgBrowser3
, riid
) ||
2413 IsEqualGUID(&IID_ICommDlgBrowser2
, riid
) ||
2414 IsEqualGUID(&IID_ICommDlgBrowser
, riid
))
2416 *ppvObject
= &This
->ICommDlgBrowser3_iface
;
2418 else if(IsEqualGUID(&IID_IOleWindow
, riid
))
2420 *ppvObject
= &This
->IOleWindow_iface
;
2422 else if(IsEqualGUID(riid
, &IID_IFileDialogCustomize
) ||
2423 IsEqualGUID(riid
, &IID_IFileDialogCustomizeAlt
))
2425 *ppvObject
= &This
->IFileDialogCustomize_iface
;
2428 FIXME("Unknown interface requested: %s.\n", debugstr_guid(riid
));
2432 IUnknown_AddRef((IUnknown
*)*ppvObject
);
2436 return E_NOINTERFACE
;
2439 static ULONG WINAPI
IFileDialog2_fnAddRef(IFileDialog2
*iface
)
2441 FileDialogImpl
*This
= impl_from_IFileDialog2(iface
);
2442 LONG ref
= InterlockedIncrement(&This
->ref
);
2443 TRACE("%p - ref %ld\n", This
, ref
);
2448 static ULONG WINAPI
IFileDialog2_fnRelease(IFileDialog2
*iface
)
2450 FileDialogImpl
*This
= impl_from_IFileDialog2(iface
);
2451 LONG ref
= InterlockedDecrement(&This
->ref
);
2452 TRACE("%p - ref %ld\n", This
, ref
);
2457 for(i
= 0; i
< This
->filterspec_count
; i
++)
2459 LocalFree((void*)This
->filterspecs
[i
].pszName
);
2460 LocalFree((void*)This
->filterspecs
[i
].pszSpec
);
2462 HeapFree(GetProcessHeap(), 0, This
->filterspecs
);
2464 DestroyWindow(This
->cctrls_hwnd
);
2466 if(This
->psi_defaultfolder
) IShellItem_Release(This
->psi_defaultfolder
);
2467 if(This
->psi_setfolder
) IShellItem_Release(This
->psi_setfolder
);
2468 if(This
->psi_folder
) IShellItem_Release(This
->psi_folder
);
2469 if(This
->psia_selection
) IShellItemArray_Release(This
->psia_selection
);
2470 if(This
->psia_results
) IShellItemArray_Release(This
->psia_results
);
2472 LocalFree(This
->set_filename
);
2473 LocalFree(This
->default_ext
);
2474 LocalFree(This
->custom_title
);
2475 LocalFree(This
->custom_okbutton
);
2476 LocalFree(This
->custom_cancelbutton
);
2477 LocalFree(This
->custom_filenamelabel
);
2479 DestroyMenu(This
->hmenu_opendropdown
);
2480 DeleteObject(This
->hfont_opendropdown
);
2482 HeapFree(GetProcessHeap(), 0, This
);
2488 static HRESULT WINAPI
IFileDialog2_fnShow(IFileDialog2
*iface
, HWND hwndOwner
)
2490 FileDialogImpl
*This
= impl_from_IFileDialog2(iface
);
2491 TRACE("%p (%p)\n", iface
, hwndOwner
);
2493 This
->opendropdown_has_selection
= FALSE
;
2495 return create_dialog(This
, hwndOwner
);
2498 static HRESULT WINAPI
IFileDialog2_fnSetFileTypes(IFileDialog2
*iface
, UINT cFileTypes
,
2499 const COMDLG_FILTERSPEC
*rgFilterSpec
)
2501 FileDialogImpl
*This
= impl_from_IFileDialog2(iface
);
2503 TRACE("%p (%d, %p)\n", This
, cFileTypes
, rgFilterSpec
);
2506 return E_INVALIDARG
;
2508 if(This
->filterspecs
)
2509 return E_UNEXPECTED
;
2514 This
->filterspecs
= HeapAlloc(GetProcessHeap(), 0, sizeof(COMDLG_FILTERSPEC
)*cFileTypes
);
2515 for(i
= 0; i
< cFileTypes
; i
++)
2517 This
->filterspecs
[i
].pszName
= StrDupW(rgFilterSpec
[i
].pszName
);
2518 This
->filterspecs
[i
].pszSpec
= StrDupW(rgFilterSpec
[i
].pszSpec
);
2520 This
->filterspec_count
= cFileTypes
;
2525 static HRESULT WINAPI
IFileDialog2_fnSetFileTypeIndex(IFileDialog2
*iface
, UINT iFileType
)
2527 FileDialogImpl
*This
= impl_from_IFileDialog2(iface
);
2528 TRACE("%p (%d)\n", This
, iFileType
);
2530 if(!This
->filterspecs
)
2533 iFileType
= max(iFileType
, 1);
2534 iFileType
= min(iFileType
, This
->filterspec_count
);
2535 This
->filetypeindex
= iFileType
-1;
2540 static HRESULT WINAPI
IFileDialog2_fnGetFileTypeIndex(IFileDialog2
*iface
, UINT
*piFileType
)
2542 FileDialogImpl
*This
= impl_from_IFileDialog2(iface
);
2543 TRACE("%p (%p)\n", This
, piFileType
);
2546 return E_INVALIDARG
;
2548 if(This
->filterspec_count
== 0)
2551 *piFileType
= This
->filetypeindex
+ 1;
2556 static HRESULT WINAPI
IFileDialog2_fnAdvise(IFileDialog2
*iface
, IFileDialogEvents
*pfde
, DWORD
*pdwCookie
)
2558 FileDialogImpl
*This
= impl_from_IFileDialog2(iface
);
2559 events_client
*client
;
2560 TRACE("%p (%p, %p)\n", This
, pfde
, pdwCookie
);
2562 if(!pfde
|| !pdwCookie
)
2563 return E_INVALIDARG
;
2565 client
= HeapAlloc(GetProcessHeap(), 0, sizeof(events_client
));
2566 client
->pfde
= pfde
;
2567 client
->cookie
= ++This
->events_next_cookie
;
2569 IFileDialogEvents_AddRef(pfde
);
2570 *pdwCookie
= client
->cookie
;
2572 list_add_tail(&This
->events_clients
, &client
->entry
);
2577 static HRESULT WINAPI
IFileDialog2_fnUnadvise(IFileDialog2
*iface
, DWORD dwCookie
)
2579 FileDialogImpl
*This
= impl_from_IFileDialog2(iface
);
2580 events_client
*client
, *found
= NULL
;
2581 TRACE("%p (%ld)\n", This
, dwCookie
);
2583 LIST_FOR_EACH_ENTRY(client
, &This
->events_clients
, events_client
, entry
)
2585 if(client
->cookie
== dwCookie
)
2594 list_remove(&found
->entry
);
2595 IFileDialogEvents_Release(found
->pfde
);
2596 HeapFree(GetProcessHeap(), 0, found
);
2600 return E_INVALIDARG
;
2603 static HRESULT WINAPI
IFileDialog2_fnSetOptions(IFileDialog2
*iface
, FILEOPENDIALOGOPTIONS fos
)
2605 FileDialogImpl
*This
= impl_from_IFileDialog2(iface
);
2606 TRACE("%p (0x%lx)\n", This
, fos
);
2608 if (fos
& ~(FOS_OVERWRITEPROMPT
| FOS_STRICTFILETYPES
| FOS_NOCHANGEDIR
| FOS_PICKFOLDERS
| FOS_FORCEFILESYSTEM
2609 | FOS_ALLNONSTORAGEITEMS
| FOS_NOVALIDATE
| FOS_ALLOWMULTISELECT
| FOS_PATHMUSTEXIST
| FOS_FILEMUSTEXIST
2610 | FOS_CREATEPROMPT
| FOS_SHAREAWARE
| FOS_NOREADONLYRETURN
| FOS_NOTESTFILECREATE
| FOS_HIDEMRUPLACES
2611 | FOS_HIDEPINNEDPLACES
| FOS_NODEREFERENCELINKS
| FOS_DONTADDTORECENT
| FOS_FORCESHOWHIDDEN
2612 | FOS_DEFAULTNOMINIMODE
| FOS_FORCEPREVIEWPANEON
| FOS_SUPPORTSTREAMABLEITEMS
))
2614 WARN("Invalid option %#lx\n", fos
);
2615 return E_INVALIDARG
;
2618 if( !(This
->options
& FOS_PICKFOLDERS
) && (fos
& FOS_PICKFOLDERS
) )
2621 LoadStringW(COMDLG32_hInstance
, IDS_SELECT_FOLDER
, buf
, ARRAY_SIZE(buf
));
2622 IFileDialog2_SetTitle(iface
, buf
);
2625 This
->options
= fos
;
2630 static HRESULT WINAPI
IFileDialog2_fnGetOptions(IFileDialog2
*iface
, FILEOPENDIALOGOPTIONS
*pfos
)
2632 FileDialogImpl
*This
= impl_from_IFileDialog2(iface
);
2633 TRACE("%p (%p)\n", This
, pfos
);
2636 return E_INVALIDARG
;
2638 *pfos
= This
->options
;
2643 static HRESULT WINAPI
IFileDialog2_fnSetDefaultFolder(IFileDialog2
*iface
, IShellItem
*psi
)
2645 FileDialogImpl
*This
= impl_from_IFileDialog2(iface
);
2646 TRACE("%p (%p)\n", This
, psi
);
2647 if(This
->psi_defaultfolder
)
2648 IShellItem_Release(This
->psi_defaultfolder
);
2650 This
->psi_defaultfolder
= psi
;
2652 if(This
->psi_defaultfolder
)
2653 IShellItem_AddRef(This
->psi_defaultfolder
);
2658 static HRESULT WINAPI
IFileDialog2_fnSetFolder(IFileDialog2
*iface
, IShellItem
*psi
)
2660 FileDialogImpl
*This
= impl_from_IFileDialog2(iface
);
2661 TRACE("%p (%p)\n", This
, psi
);
2662 if(This
->psi_setfolder
)
2663 IShellItem_Release(This
->psi_setfolder
);
2665 This
->psi_setfolder
= psi
;
2667 if(This
->psi_setfolder
)
2668 IShellItem_AddRef(This
->psi_setfolder
);
2673 static HRESULT WINAPI
IFileDialog2_fnGetFolder(IFileDialog2
*iface
, IShellItem
**ppsi
)
2675 FileDialogImpl
*This
= impl_from_IFileDialog2(iface
);
2676 TRACE("%p (%p)\n", This
, ppsi
);
2678 return E_INVALIDARG
;
2681 If the dialog is shown, return the current(ly selected) folder. */
2684 if(This
->psi_folder
)
2685 *ppsi
= This
->psi_folder
;
2686 else if(This
->psi_setfolder
)
2687 *ppsi
= This
->psi_setfolder
;
2688 else if(This
->psi_defaultfolder
)
2689 *ppsi
= This
->psi_defaultfolder
;
2693 IShellItem_AddRef(*ppsi
);
2700 static HRESULT WINAPI
IFileDialog2_fnGetCurrentSelection(IFileDialog2
*iface
, IShellItem
**ppsi
)
2702 FileDialogImpl
*This
= impl_from_IFileDialog2(iface
);
2704 TRACE("%p (%p)\n", This
, ppsi
);
2707 return E_INVALIDARG
;
2709 if(This
->psia_selection
)
2711 /* FIXME: Check filename edit box */
2712 hr
= IShellItemArray_GetItemAt(This
->psia_selection
, 0, ppsi
);
2719 static HRESULT WINAPI
IFileDialog2_fnSetFileName(IFileDialog2
*iface
, LPCWSTR pszName
)
2721 FileDialogImpl
*This
= impl_from_IFileDialog2(iface
);
2722 TRACE("%p (%s)\n", iface
, debugstr_w(pszName
));
2724 set_file_name(This
, pszName
);
2729 static HRESULT WINAPI
IFileDialog2_fnGetFileName(IFileDialog2
*iface
, LPWSTR
*pszName
)
2731 FileDialogImpl
*This
= impl_from_IFileDialog2(iface
);
2732 TRACE("%p (%p)\n", iface
, pszName
);
2735 return E_INVALIDARG
;
2738 get_file_name(This
, pszName
);
2739 return *pszName
? S_OK
: E_FAIL
;
2742 static HRESULT WINAPI
IFileDialog2_fnSetTitle(IFileDialog2
*iface
, LPCWSTR pszTitle
)
2744 FileDialogImpl
*This
= impl_from_IFileDialog2(iface
);
2745 TRACE("%p (%s)\n", This
, debugstr_w(pszTitle
));
2747 LocalFree(This
->custom_title
);
2748 This
->custom_title
= StrDupW(pszTitle
);
2749 update_control_text(This
);
2754 static HRESULT WINAPI
IFileDialog2_fnSetOkButtonLabel(IFileDialog2
*iface
, LPCWSTR pszText
)
2756 FileDialogImpl
*This
= impl_from_IFileDialog2(iface
);
2757 TRACE("%p (%s)\n", This
, debugstr_w(pszText
));
2759 LocalFree(This
->custom_okbutton
);
2760 This
->custom_okbutton
= StrDupW(pszText
);
2761 update_control_text(This
);
2762 update_layout(This
);
2767 static HRESULT WINAPI
IFileDialog2_fnSetFileNameLabel(IFileDialog2
*iface
, LPCWSTR pszLabel
)
2769 FileDialogImpl
*This
= impl_from_IFileDialog2(iface
);
2770 TRACE("%p (%s)\n", This
, debugstr_w(pszLabel
));
2772 LocalFree(This
->custom_filenamelabel
);
2773 This
->custom_filenamelabel
= StrDupW(pszLabel
);
2774 update_control_text(This
);
2775 update_layout(This
);
2780 static HRESULT WINAPI
IFileDialog2_fnGetResult(IFileDialog2
*iface
, IShellItem
**ppsi
)
2782 FileDialogImpl
*This
= impl_from_IFileDialog2(iface
);
2784 TRACE("%p (%p)\n", This
, ppsi
);
2787 return E_INVALIDARG
;
2789 if(This
->psia_results
)
2792 hr
= IShellItemArray_GetCount(This
->psia_results
, &item_count
);
2798 /* Adds a reference. */
2799 hr
= IShellItemArray_GetItemAt(This
->psia_results
, 0, ppsi
);
2805 return E_UNEXPECTED
;
2808 static HRESULT WINAPI
IFileDialog2_fnAddPlace(IFileDialog2
*iface
, IShellItem
*psi
, FDAP fdap
)
2810 FileDialogImpl
*This
= impl_from_IFileDialog2(iface
);
2811 FIXME("stub - %p (%p, %d)\n", This
, psi
, fdap
);
2815 static HRESULT WINAPI
IFileDialog2_fnSetDefaultExtension(IFileDialog2
*iface
, LPCWSTR pszDefaultExtension
)
2817 FileDialogImpl
*This
= impl_from_IFileDialog2(iface
);
2818 TRACE("%p (%s)\n", This
, debugstr_w(pszDefaultExtension
));
2820 LocalFree(This
->default_ext
);
2821 This
->default_ext
= StrDupW(pszDefaultExtension
);
2826 static HRESULT WINAPI
IFileDialog2_fnClose(IFileDialog2
*iface
, HRESULT hr
)
2828 FileDialogImpl
*This
= impl_from_IFileDialog2(iface
);
2829 TRACE("%p (0x%08lx)\n", This
, hr
);
2832 EndDialog(This
->dlg_hwnd
, hr
);
2837 static HRESULT WINAPI
IFileDialog2_fnSetClientGuid(IFileDialog2
*iface
, REFGUID guid
)
2839 FileDialogImpl
*This
= impl_from_IFileDialog2(iface
);
2840 TRACE("%p (%s)\n", This
, debugstr_guid(guid
));
2841 This
->client_guid
= *guid
;
2845 static HRESULT WINAPI
IFileDialog2_fnClearClientData(IFileDialog2
*iface
)
2847 FileDialogImpl
*This
= impl_from_IFileDialog2(iface
);
2848 FIXME("stub - %p\n", This
);
2852 static HRESULT WINAPI
IFileDialog2_fnSetFilter(IFileDialog2
*iface
, IShellItemFilter
*pFilter
)
2854 FileDialogImpl
*This
= impl_from_IFileDialog2(iface
);
2855 FIXME("stub - %p (%p)\n", This
, pFilter
);
2859 static HRESULT WINAPI
IFileDialog2_fnSetCancelButtonLabel(IFileDialog2
*iface
, LPCWSTR pszLabel
)
2861 FileDialogImpl
*This
= impl_from_IFileDialog2(iface
);
2862 TRACE("%p (%s)\n", This
, debugstr_w(pszLabel
));
2864 LocalFree(This
->custom_cancelbutton
);
2865 This
->custom_cancelbutton
= StrDupW(pszLabel
);
2866 update_control_text(This
);
2867 update_layout(This
);
2872 static HRESULT WINAPI
IFileDialog2_fnSetNavigationRoot(IFileDialog2
*iface
, IShellItem
*psi
)
2874 FileDialogImpl
*This
= impl_from_IFileDialog2(iface
);
2875 FIXME("stub - %p (%p)\n", This
, psi
);
2879 static const IFileDialog2Vtbl vt_IFileDialog2
= {
2880 IFileDialog2_fnQueryInterface
,
2881 IFileDialog2_fnAddRef
,
2882 IFileDialog2_fnRelease
,
2883 IFileDialog2_fnShow
,
2884 IFileDialog2_fnSetFileTypes
,
2885 IFileDialog2_fnSetFileTypeIndex
,
2886 IFileDialog2_fnGetFileTypeIndex
,
2887 IFileDialog2_fnAdvise
,
2888 IFileDialog2_fnUnadvise
,
2889 IFileDialog2_fnSetOptions
,
2890 IFileDialog2_fnGetOptions
,
2891 IFileDialog2_fnSetDefaultFolder
,
2892 IFileDialog2_fnSetFolder
,
2893 IFileDialog2_fnGetFolder
,
2894 IFileDialog2_fnGetCurrentSelection
,
2895 IFileDialog2_fnSetFileName
,
2896 IFileDialog2_fnGetFileName
,
2897 IFileDialog2_fnSetTitle
,
2898 IFileDialog2_fnSetOkButtonLabel
,
2899 IFileDialog2_fnSetFileNameLabel
,
2900 IFileDialog2_fnGetResult
,
2901 IFileDialog2_fnAddPlace
,
2902 IFileDialog2_fnSetDefaultExtension
,
2903 IFileDialog2_fnClose
,
2904 IFileDialog2_fnSetClientGuid
,
2905 IFileDialog2_fnClearClientData
,
2906 IFileDialog2_fnSetFilter
,
2907 IFileDialog2_fnSetCancelButtonLabel
,
2908 IFileDialog2_fnSetNavigationRoot
2911 /**************************************************************************
2914 static inline FileDialogImpl
*impl_from_IFileOpenDialog(IFileOpenDialog
*iface
)
2916 return CONTAINING_RECORD(iface
, FileDialogImpl
, u
.IFileOpenDialog_iface
);
2919 static HRESULT WINAPI
IFileOpenDialog_fnQueryInterface(IFileOpenDialog
*iface
,
2920 REFIID riid
, void **ppvObject
)
2922 FileDialogImpl
*This
= impl_from_IFileOpenDialog(iface
);
2923 return IFileDialog2_QueryInterface(&This
->IFileDialog2_iface
, riid
, ppvObject
);
2926 static ULONG WINAPI
IFileOpenDialog_fnAddRef(IFileOpenDialog
*iface
)
2928 FileDialogImpl
*This
= impl_from_IFileOpenDialog(iface
);
2929 return IFileDialog2_AddRef(&This
->IFileDialog2_iface
);
2932 static ULONG WINAPI
IFileOpenDialog_fnRelease(IFileOpenDialog
*iface
)
2934 FileDialogImpl
*This
= impl_from_IFileOpenDialog(iface
);
2935 return IFileDialog2_Release(&This
->IFileDialog2_iface
);
2938 static HRESULT WINAPI
IFileOpenDialog_fnShow(IFileOpenDialog
*iface
, HWND hwndOwner
)
2940 FileDialogImpl
*This
= impl_from_IFileOpenDialog(iface
);
2941 return IFileDialog2_Show(&This
->IFileDialog2_iface
, hwndOwner
);
2944 static HRESULT WINAPI
IFileOpenDialog_fnSetFileTypes(IFileOpenDialog
*iface
, UINT cFileTypes
,
2945 const COMDLG_FILTERSPEC
*rgFilterSpec
)
2947 FileDialogImpl
*This
= impl_from_IFileOpenDialog(iface
);
2948 return IFileDialog2_SetFileTypes(&This
->IFileDialog2_iface
, cFileTypes
, rgFilterSpec
);
2951 static HRESULT WINAPI
IFileOpenDialog_fnSetFileTypeIndex(IFileOpenDialog
*iface
, UINT iFileType
)
2953 FileDialogImpl
*This
= impl_from_IFileOpenDialog(iface
);
2954 return IFileDialog2_SetFileTypeIndex(&This
->IFileDialog2_iface
, iFileType
);
2957 static HRESULT WINAPI
IFileOpenDialog_fnGetFileTypeIndex(IFileOpenDialog
*iface
, UINT
*piFileType
)
2959 FileDialogImpl
*This
= impl_from_IFileOpenDialog(iface
);
2960 return IFileDialog2_GetFileTypeIndex(&This
->IFileDialog2_iface
, piFileType
);
2963 static HRESULT WINAPI
IFileOpenDialog_fnAdvise(IFileOpenDialog
*iface
, IFileDialogEvents
*pfde
,
2966 FileDialogImpl
*This
= impl_from_IFileOpenDialog(iface
);
2967 return IFileDialog2_Advise(&This
->IFileDialog2_iface
, pfde
, pdwCookie
);
2970 static HRESULT WINAPI
IFileOpenDialog_fnUnadvise(IFileOpenDialog
*iface
, DWORD dwCookie
)
2972 FileDialogImpl
*This
= impl_from_IFileOpenDialog(iface
);
2973 return IFileDialog2_Unadvise(&This
->IFileDialog2_iface
, dwCookie
);
2976 static HRESULT WINAPI
IFileOpenDialog_fnSetOptions(IFileOpenDialog
*iface
, FILEOPENDIALOGOPTIONS fos
)
2978 FileDialogImpl
*This
= impl_from_IFileOpenDialog(iface
);
2979 return IFileDialog2_SetOptions(&This
->IFileDialog2_iface
, fos
);
2982 static HRESULT WINAPI
IFileOpenDialog_fnGetOptions(IFileOpenDialog
*iface
, FILEOPENDIALOGOPTIONS
*pfos
)
2984 FileDialogImpl
*This
= impl_from_IFileOpenDialog(iface
);
2985 return IFileDialog2_GetOptions(&This
->IFileDialog2_iface
, pfos
);
2988 static HRESULT WINAPI
IFileOpenDialog_fnSetDefaultFolder(IFileOpenDialog
*iface
, IShellItem
*psi
)
2990 FileDialogImpl
*This
= impl_from_IFileOpenDialog(iface
);
2991 return IFileDialog2_SetDefaultFolder(&This
->IFileDialog2_iface
, psi
);
2994 static HRESULT WINAPI
IFileOpenDialog_fnSetFolder(IFileOpenDialog
*iface
, IShellItem
*psi
)
2996 FileDialogImpl
*This
= impl_from_IFileOpenDialog(iface
);
2997 return IFileDialog2_SetFolder(&This
->IFileDialog2_iface
, psi
);
3000 static HRESULT WINAPI
IFileOpenDialog_fnGetFolder(IFileOpenDialog
*iface
, IShellItem
**ppsi
)
3002 FileDialogImpl
*This
= impl_from_IFileOpenDialog(iface
);
3003 return IFileDialog2_GetFolder(&This
->IFileDialog2_iface
, ppsi
);
3006 static HRESULT WINAPI
IFileOpenDialog_fnGetCurrentSelection(IFileOpenDialog
*iface
, IShellItem
**ppsi
)
3008 FileDialogImpl
*This
= impl_from_IFileOpenDialog(iface
);
3009 return IFileDialog2_GetCurrentSelection(&This
->IFileDialog2_iface
, ppsi
);
3012 static HRESULT WINAPI
IFileOpenDialog_fnSetFileName(IFileOpenDialog
*iface
, LPCWSTR pszName
)
3014 FileDialogImpl
*This
= impl_from_IFileOpenDialog(iface
);
3015 return IFileDialog2_SetFileName(&This
->IFileDialog2_iface
, pszName
);
3018 static HRESULT WINAPI
IFileOpenDialog_fnGetFileName(IFileOpenDialog
*iface
, LPWSTR
*pszName
)
3020 FileDialogImpl
*This
= impl_from_IFileOpenDialog(iface
);
3021 return IFileDialog2_GetFileName(&This
->IFileDialog2_iface
, pszName
);
3024 static HRESULT WINAPI
IFileOpenDialog_fnSetTitle(IFileOpenDialog
*iface
, LPCWSTR pszTitle
)
3026 FileDialogImpl
*This
= impl_from_IFileOpenDialog(iface
);
3027 return IFileDialog2_SetTitle(&This
->IFileDialog2_iface
, pszTitle
);
3030 static HRESULT WINAPI
IFileOpenDialog_fnSetOkButtonLabel(IFileOpenDialog
*iface
, LPCWSTR pszText
)
3032 FileDialogImpl
*This
= impl_from_IFileOpenDialog(iface
);
3033 return IFileDialog2_SetOkButtonLabel(&This
->IFileDialog2_iface
, pszText
);
3036 static HRESULT WINAPI
IFileOpenDialog_fnSetFileNameLabel(IFileOpenDialog
*iface
, LPCWSTR pszLabel
)
3038 FileDialogImpl
*This
= impl_from_IFileOpenDialog(iface
);
3039 return IFileDialog2_SetFileNameLabel(&This
->IFileDialog2_iface
, pszLabel
);
3042 static HRESULT WINAPI
IFileOpenDialog_fnGetResult(IFileOpenDialog
*iface
, IShellItem
**ppsi
)
3044 FileDialogImpl
*This
= impl_from_IFileOpenDialog(iface
);
3045 return IFileDialog2_GetResult(&This
->IFileDialog2_iface
, ppsi
);
3048 static HRESULT WINAPI
IFileOpenDialog_fnAddPlace(IFileOpenDialog
*iface
, IShellItem
*psi
, FDAP fdap
)
3050 FileDialogImpl
*This
= impl_from_IFileOpenDialog(iface
);
3051 return IFileDialog2_AddPlace(&This
->IFileDialog2_iface
, psi
, fdap
);
3054 static HRESULT WINAPI
IFileOpenDialog_fnSetDefaultExtension(IFileOpenDialog
*iface
,
3055 LPCWSTR pszDefaultExtension
)
3057 FileDialogImpl
*This
= impl_from_IFileOpenDialog(iface
);
3058 return IFileDialog2_SetDefaultExtension(&This
->IFileDialog2_iface
, pszDefaultExtension
);
3061 static HRESULT WINAPI
IFileOpenDialog_fnClose(IFileOpenDialog
*iface
, HRESULT hr
)
3063 FileDialogImpl
*This
= impl_from_IFileOpenDialog(iface
);
3064 return IFileDialog2_Close(&This
->IFileDialog2_iface
, hr
);
3067 static HRESULT WINAPI
IFileOpenDialog_fnSetClientGuid(IFileOpenDialog
*iface
, REFGUID guid
)
3069 FileDialogImpl
*This
= impl_from_IFileOpenDialog(iface
);
3070 return IFileDialog2_SetClientGuid(&This
->IFileDialog2_iface
, guid
);
3073 static HRESULT WINAPI
IFileOpenDialog_fnClearClientData(IFileOpenDialog
*iface
)
3075 FileDialogImpl
*This
= impl_from_IFileOpenDialog(iface
);
3076 return IFileDialog2_ClearClientData(&This
->IFileDialog2_iface
);
3079 static HRESULT WINAPI
IFileOpenDialog_fnSetFilter(IFileOpenDialog
*iface
, IShellItemFilter
*pFilter
)
3081 FileDialogImpl
*This
= impl_from_IFileOpenDialog(iface
);
3082 return IFileDialog2_SetFilter(&This
->IFileDialog2_iface
, pFilter
);
3085 static HRESULT WINAPI
IFileOpenDialog_fnGetResults(IFileOpenDialog
*iface
, IShellItemArray
**ppenum
)
3087 FileDialogImpl
*This
= impl_from_IFileOpenDialog(iface
);
3088 TRACE("%p (%p)\n", This
, ppenum
);
3090 *ppenum
= This
->psia_results
;
3094 IShellItemArray_AddRef(*ppenum
);
3101 static HRESULT WINAPI
IFileOpenDialog_fnGetSelectedItems(IFileOpenDialog
*iface
, IShellItemArray
**ppsai
)
3103 FileDialogImpl
*This
= impl_from_IFileOpenDialog(iface
);
3104 TRACE("%p (%p)\n", This
, ppsai
);
3106 if(This
->psia_selection
)
3108 *ppsai
= This
->psia_selection
;
3109 IShellItemArray_AddRef(*ppsai
);
3116 static const IFileOpenDialogVtbl vt_IFileOpenDialog
= {
3117 IFileOpenDialog_fnQueryInterface
,
3118 IFileOpenDialog_fnAddRef
,
3119 IFileOpenDialog_fnRelease
,
3120 IFileOpenDialog_fnShow
,
3121 IFileOpenDialog_fnSetFileTypes
,
3122 IFileOpenDialog_fnSetFileTypeIndex
,
3123 IFileOpenDialog_fnGetFileTypeIndex
,
3124 IFileOpenDialog_fnAdvise
,
3125 IFileOpenDialog_fnUnadvise
,
3126 IFileOpenDialog_fnSetOptions
,
3127 IFileOpenDialog_fnGetOptions
,
3128 IFileOpenDialog_fnSetDefaultFolder
,
3129 IFileOpenDialog_fnSetFolder
,
3130 IFileOpenDialog_fnGetFolder
,
3131 IFileOpenDialog_fnGetCurrentSelection
,
3132 IFileOpenDialog_fnSetFileName
,
3133 IFileOpenDialog_fnGetFileName
,
3134 IFileOpenDialog_fnSetTitle
,
3135 IFileOpenDialog_fnSetOkButtonLabel
,
3136 IFileOpenDialog_fnSetFileNameLabel
,
3137 IFileOpenDialog_fnGetResult
,
3138 IFileOpenDialog_fnAddPlace
,
3139 IFileOpenDialog_fnSetDefaultExtension
,
3140 IFileOpenDialog_fnClose
,
3141 IFileOpenDialog_fnSetClientGuid
,
3142 IFileOpenDialog_fnClearClientData
,
3143 IFileOpenDialog_fnSetFilter
,
3144 IFileOpenDialog_fnGetResults
,
3145 IFileOpenDialog_fnGetSelectedItems
3148 /**************************************************************************
3151 static inline FileDialogImpl
*impl_from_IFileSaveDialog(IFileSaveDialog
*iface
)
3153 return CONTAINING_RECORD(iface
, FileDialogImpl
, u
.IFileSaveDialog_iface
);
3156 static HRESULT WINAPI
IFileSaveDialog_fnQueryInterface(IFileSaveDialog
*iface
,
3160 FileDialogImpl
*This
= impl_from_IFileSaveDialog(iface
);
3161 return IFileDialog2_QueryInterface(&This
->IFileDialog2_iface
, riid
, ppvObject
);
3164 static ULONG WINAPI
IFileSaveDialog_fnAddRef(IFileSaveDialog
*iface
)
3166 FileDialogImpl
*This
= impl_from_IFileSaveDialog(iface
);
3167 return IFileDialog2_AddRef(&This
->IFileDialog2_iface
);
3170 static ULONG WINAPI
IFileSaveDialog_fnRelease(IFileSaveDialog
*iface
)
3172 FileDialogImpl
*This
= impl_from_IFileSaveDialog(iface
);
3173 return IFileDialog2_Release(&This
->IFileDialog2_iface
);
3176 static HRESULT WINAPI
IFileSaveDialog_fnShow(IFileSaveDialog
*iface
, HWND hwndOwner
)
3178 FileDialogImpl
*This
= impl_from_IFileSaveDialog(iface
);
3179 return IFileDialog2_Show(&This
->IFileDialog2_iface
, hwndOwner
);
3182 static HRESULT WINAPI
IFileSaveDialog_fnSetFileTypes(IFileSaveDialog
*iface
, UINT cFileTypes
,
3183 const COMDLG_FILTERSPEC
*rgFilterSpec
)
3185 FileDialogImpl
*This
= impl_from_IFileSaveDialog(iface
);
3186 return IFileDialog2_SetFileTypes(&This
->IFileDialog2_iface
, cFileTypes
, rgFilterSpec
);
3189 static HRESULT WINAPI
IFileSaveDialog_fnSetFileTypeIndex(IFileSaveDialog
*iface
, UINT iFileType
)
3191 FileDialogImpl
*This
= impl_from_IFileSaveDialog(iface
);
3192 return IFileDialog2_SetFileTypeIndex(&This
->IFileDialog2_iface
, iFileType
);
3195 static HRESULT WINAPI
IFileSaveDialog_fnGetFileTypeIndex(IFileSaveDialog
*iface
, UINT
*piFileType
)
3197 FileDialogImpl
*This
= impl_from_IFileSaveDialog(iface
);
3198 return IFileDialog2_GetFileTypeIndex(&This
->IFileDialog2_iface
, piFileType
);
3201 static HRESULT WINAPI
IFileSaveDialog_fnAdvise(IFileSaveDialog
*iface
, IFileDialogEvents
*pfde
,
3204 FileDialogImpl
*This
= impl_from_IFileSaveDialog(iface
);
3205 return IFileDialog2_Advise(&This
->IFileDialog2_iface
, pfde
, pdwCookie
);
3208 static HRESULT WINAPI
IFileSaveDialog_fnUnadvise(IFileSaveDialog
*iface
, DWORD dwCookie
)
3210 FileDialogImpl
*This
= impl_from_IFileSaveDialog(iface
);
3211 return IFileDialog2_Unadvise(&This
->IFileDialog2_iface
, dwCookie
);
3214 static HRESULT WINAPI
IFileSaveDialog_fnSetOptions(IFileSaveDialog
*iface
, FILEOPENDIALOGOPTIONS fos
)
3216 FileDialogImpl
*This
= impl_from_IFileSaveDialog(iface
);
3217 return IFileDialog2_SetOptions(&This
->IFileDialog2_iface
, fos
);
3220 static HRESULT WINAPI
IFileSaveDialog_fnGetOptions(IFileSaveDialog
*iface
, FILEOPENDIALOGOPTIONS
*pfos
)
3222 FileDialogImpl
*This
= impl_from_IFileSaveDialog(iface
);
3223 return IFileDialog2_GetOptions(&This
->IFileDialog2_iface
, pfos
);
3226 static HRESULT WINAPI
IFileSaveDialog_fnSetDefaultFolder(IFileSaveDialog
*iface
, IShellItem
*psi
)
3228 FileDialogImpl
*This
= impl_from_IFileSaveDialog(iface
);
3229 return IFileDialog2_SetDefaultFolder(&This
->IFileDialog2_iface
, psi
);
3232 static HRESULT WINAPI
IFileSaveDialog_fnSetFolder(IFileSaveDialog
*iface
, IShellItem
*psi
)
3234 FileDialogImpl
*This
= impl_from_IFileSaveDialog(iface
);
3235 return IFileDialog2_SetFolder(&This
->IFileDialog2_iface
, psi
);
3238 static HRESULT WINAPI
IFileSaveDialog_fnGetFolder(IFileSaveDialog
*iface
, IShellItem
**ppsi
)
3240 FileDialogImpl
*This
= impl_from_IFileSaveDialog(iface
);
3241 return IFileDialog2_GetFolder(&This
->IFileDialog2_iface
, ppsi
);
3244 static HRESULT WINAPI
IFileSaveDialog_fnGetCurrentSelection(IFileSaveDialog
*iface
, IShellItem
**ppsi
)
3246 FileDialogImpl
*This
= impl_from_IFileSaveDialog(iface
);
3247 return IFileDialog2_GetCurrentSelection(&This
->IFileDialog2_iface
, ppsi
);
3250 static HRESULT WINAPI
IFileSaveDialog_fnSetFileName(IFileSaveDialog
*iface
, LPCWSTR pszName
)
3252 FileDialogImpl
*This
= impl_from_IFileSaveDialog(iface
);
3253 return IFileDialog2_SetFileName(&This
->IFileDialog2_iface
, pszName
);
3256 static HRESULT WINAPI
IFileSaveDialog_fnGetFileName(IFileSaveDialog
*iface
, LPWSTR
*pszName
)
3258 FileDialogImpl
*This
= impl_from_IFileSaveDialog(iface
);
3259 return IFileDialog2_GetFileName(&This
->IFileDialog2_iface
, pszName
);
3262 static HRESULT WINAPI
IFileSaveDialog_fnSetTitle(IFileSaveDialog
*iface
, LPCWSTR pszTitle
)
3264 FileDialogImpl
*This
= impl_from_IFileSaveDialog(iface
);
3265 return IFileDialog2_SetTitle(&This
->IFileDialog2_iface
, pszTitle
);
3268 static HRESULT WINAPI
IFileSaveDialog_fnSetOkButtonLabel(IFileSaveDialog
*iface
, LPCWSTR pszText
)
3270 FileDialogImpl
*This
= impl_from_IFileSaveDialog(iface
);
3271 return IFileDialog2_SetOkButtonLabel(&This
->IFileDialog2_iface
, pszText
);
3274 static HRESULT WINAPI
IFileSaveDialog_fnSetFileNameLabel(IFileSaveDialog
*iface
, LPCWSTR pszLabel
)
3276 FileDialogImpl
*This
= impl_from_IFileSaveDialog(iface
);
3277 return IFileDialog2_SetFileNameLabel(&This
->IFileDialog2_iface
, pszLabel
);
3280 static HRESULT WINAPI
IFileSaveDialog_fnGetResult(IFileSaveDialog
*iface
, IShellItem
**ppsi
)
3282 FileDialogImpl
*This
= impl_from_IFileSaveDialog(iface
);
3283 return IFileDialog2_GetResult(&This
->IFileDialog2_iface
, ppsi
);
3286 static HRESULT WINAPI
IFileSaveDialog_fnAddPlace(IFileSaveDialog
*iface
, IShellItem
*psi
, FDAP fdap
)
3288 FileDialogImpl
*This
= impl_from_IFileSaveDialog(iface
);
3289 return IFileDialog2_AddPlace(&This
->IFileDialog2_iface
, psi
, fdap
);
3292 static HRESULT WINAPI
IFileSaveDialog_fnSetDefaultExtension(IFileSaveDialog
*iface
,
3293 LPCWSTR pszDefaultExtension
)
3295 FileDialogImpl
*This
= impl_from_IFileSaveDialog(iface
);
3296 return IFileDialog2_SetDefaultExtension(&This
->IFileDialog2_iface
, pszDefaultExtension
);
3299 static HRESULT WINAPI
IFileSaveDialog_fnClose(IFileSaveDialog
*iface
, HRESULT hr
)
3301 FileDialogImpl
*This
= impl_from_IFileSaveDialog(iface
);
3302 return IFileDialog2_Close(&This
->IFileDialog2_iface
, hr
);
3305 static HRESULT WINAPI
IFileSaveDialog_fnSetClientGuid(IFileSaveDialog
*iface
, REFGUID guid
)
3307 FileDialogImpl
*This
= impl_from_IFileSaveDialog(iface
);
3308 return IFileDialog2_SetClientGuid(&This
->IFileDialog2_iface
, guid
);
3311 static HRESULT WINAPI
IFileSaveDialog_fnClearClientData(IFileSaveDialog
*iface
)
3313 FileDialogImpl
*This
= impl_from_IFileSaveDialog(iface
);
3314 return IFileDialog2_ClearClientData(&This
->IFileDialog2_iface
);
3317 static HRESULT WINAPI
IFileSaveDialog_fnSetFilter(IFileSaveDialog
*iface
, IShellItemFilter
*pFilter
)
3319 FileDialogImpl
*This
= impl_from_IFileSaveDialog(iface
);
3320 return IFileDialog2_SetFilter(&This
->IFileDialog2_iface
, pFilter
);
3323 static HRESULT WINAPI
IFileSaveDialog_fnSetSaveAsItem(IFileSaveDialog
* iface
, IShellItem
*psi
)
3325 FileDialogImpl
*This
= impl_from_IFileSaveDialog(iface
);
3326 FIXME("stub - %p (%p)\n", This
, psi
);
3330 static HRESULT WINAPI
IFileSaveDialog_fnSetProperties(IFileSaveDialog
* iface
, IPropertyStore
*pStore
)
3332 FileDialogImpl
*This
= impl_from_IFileSaveDialog(iface
);
3333 FIXME("stub - %p (%p)\n", This
, pStore
);
3337 static HRESULT WINAPI
IFileSaveDialog_fnSetCollectedProperties(IFileSaveDialog
* iface
,
3338 IPropertyDescriptionList
*pList
,
3339 BOOL fAppendDefault
)
3341 FileDialogImpl
*This
= impl_from_IFileSaveDialog(iface
);
3342 FIXME("stub - %p (%p, %d)\n", This
, pList
, fAppendDefault
);
3346 static HRESULT WINAPI
IFileSaveDialog_fnGetProperties(IFileSaveDialog
* iface
, IPropertyStore
**ppStore
)
3348 FileDialogImpl
*This
= impl_from_IFileSaveDialog(iface
);
3349 FIXME("stub - %p (%p)\n", This
, ppStore
);
3353 static HRESULT WINAPI
IFileSaveDialog_fnApplyProperties(IFileSaveDialog
* iface
,
3355 IPropertyStore
*pStore
,
3357 IFileOperationProgressSink
*pSink
)
3359 FileDialogImpl
*This
= impl_from_IFileSaveDialog(iface
);
3360 FIXME("%p (%p, %p, %p, %p)\n", This
, psi
, pStore
, hwnd
, pSink
);
3364 static const IFileSaveDialogVtbl vt_IFileSaveDialog
= {
3365 IFileSaveDialog_fnQueryInterface
,
3366 IFileSaveDialog_fnAddRef
,
3367 IFileSaveDialog_fnRelease
,
3368 IFileSaveDialog_fnShow
,
3369 IFileSaveDialog_fnSetFileTypes
,
3370 IFileSaveDialog_fnSetFileTypeIndex
,
3371 IFileSaveDialog_fnGetFileTypeIndex
,
3372 IFileSaveDialog_fnAdvise
,
3373 IFileSaveDialog_fnUnadvise
,
3374 IFileSaveDialog_fnSetOptions
,
3375 IFileSaveDialog_fnGetOptions
,
3376 IFileSaveDialog_fnSetDefaultFolder
,
3377 IFileSaveDialog_fnSetFolder
,
3378 IFileSaveDialog_fnGetFolder
,
3379 IFileSaveDialog_fnGetCurrentSelection
,
3380 IFileSaveDialog_fnSetFileName
,
3381 IFileSaveDialog_fnGetFileName
,
3382 IFileSaveDialog_fnSetTitle
,
3383 IFileSaveDialog_fnSetOkButtonLabel
,
3384 IFileSaveDialog_fnSetFileNameLabel
,
3385 IFileSaveDialog_fnGetResult
,
3386 IFileSaveDialog_fnAddPlace
,
3387 IFileSaveDialog_fnSetDefaultExtension
,
3388 IFileSaveDialog_fnClose
,
3389 IFileSaveDialog_fnSetClientGuid
,
3390 IFileSaveDialog_fnClearClientData
,
3391 IFileSaveDialog_fnSetFilter
,
3392 IFileSaveDialog_fnSetSaveAsItem
,
3393 IFileSaveDialog_fnSetProperties
,
3394 IFileSaveDialog_fnSetCollectedProperties
,
3395 IFileSaveDialog_fnGetProperties
,
3396 IFileSaveDialog_fnApplyProperties
3399 /**************************************************************************
3400 * IExplorerBrowserEvents implementation
3402 static inline FileDialogImpl
*impl_from_IExplorerBrowserEvents(IExplorerBrowserEvents
*iface
)
3404 return CONTAINING_RECORD(iface
, FileDialogImpl
, IExplorerBrowserEvents_iface
);
3407 static HRESULT WINAPI
IExplorerBrowserEvents_fnQueryInterface(IExplorerBrowserEvents
*iface
,
3408 REFIID riid
, void **ppvObject
)
3410 FileDialogImpl
*This
= impl_from_IExplorerBrowserEvents(iface
);
3411 TRACE("%p (%s, %p)\n", This
, debugstr_guid(riid
), ppvObject
);
3413 return IFileDialog2_QueryInterface(&This
->IFileDialog2_iface
, riid
, ppvObject
);
3416 static ULONG WINAPI
IExplorerBrowserEvents_fnAddRef(IExplorerBrowserEvents
*iface
)
3418 FileDialogImpl
*This
= impl_from_IExplorerBrowserEvents(iface
);
3419 TRACE("%p\n", This
);
3420 return IFileDialog2_AddRef(&This
->IFileDialog2_iface
);
3423 static ULONG WINAPI
IExplorerBrowserEvents_fnRelease(IExplorerBrowserEvents
*iface
)
3425 FileDialogImpl
*This
= impl_from_IExplorerBrowserEvents(iface
);
3426 TRACE("%p\n", This
);
3427 return IFileDialog2_Release(&This
->IFileDialog2_iface
);
3430 static HRESULT WINAPI
IExplorerBrowserEvents_fnOnNavigationPending(IExplorerBrowserEvents
*iface
,
3431 PCIDLIST_ABSOLUTE pidlFolder
)
3433 FileDialogImpl
*This
= impl_from_IExplorerBrowserEvents(iface
);
3436 TRACE("%p (%p)\n", This
, pidlFolder
);
3438 hr
= SHCreateItemFromIDList(pidlFolder
, &IID_IShellItem
, (void**)&psi
);
3441 hr
= events_OnFolderChanging(This
, psi
);
3442 IShellItem_Release(psi
);
3444 /* The ExplorerBrowser treats S_FALSE as S_OK, we don't. */
3451 ERR("Failed to convert pidl (%p) to a shellitem.\n", pidlFolder
);
3456 static HRESULT WINAPI
IExplorerBrowserEvents_fnOnViewCreated(IExplorerBrowserEvents
*iface
,
3459 FileDialogImpl
*This
= impl_from_IExplorerBrowserEvents(iface
);
3460 TRACE("%p (%p)\n", This
, psv
);
3464 static HRESULT WINAPI
IExplorerBrowserEvents_fnOnNavigationComplete(IExplorerBrowserEvents
*iface
,
3465 PCIDLIST_ABSOLUTE pidlFolder
)
3467 FileDialogImpl
*This
= impl_from_IExplorerBrowserEvents(iface
);
3469 TRACE("%p (%p)\n", This
, pidlFolder
);
3471 if(This
->psi_folder
)
3472 IShellItem_Release(This
->psi_folder
);
3474 hr
= SHCreateItemFromIDList(pidlFolder
, &IID_IShellItem
, (void**)&This
->psi_folder
);
3477 ERR("Failed to get the current folder.\n");
3478 This
->psi_folder
= NULL
;
3481 events_OnFolderChange(This
);
3486 static HRESULT WINAPI
IExplorerBrowserEvents_fnOnNavigationFailed(IExplorerBrowserEvents
*iface
,
3487 PCIDLIST_ABSOLUTE pidlFolder
)
3489 FileDialogImpl
*This
= impl_from_IExplorerBrowserEvents(iface
);
3490 TRACE("%p (%p)\n", This
, pidlFolder
);
3494 static const IExplorerBrowserEventsVtbl vt_IExplorerBrowserEvents
= {
3495 IExplorerBrowserEvents_fnQueryInterface
,
3496 IExplorerBrowserEvents_fnAddRef
,
3497 IExplorerBrowserEvents_fnRelease
,
3498 IExplorerBrowserEvents_fnOnNavigationPending
,
3499 IExplorerBrowserEvents_fnOnViewCreated
,
3500 IExplorerBrowserEvents_fnOnNavigationComplete
,
3501 IExplorerBrowserEvents_fnOnNavigationFailed
3504 /**************************************************************************
3505 * IServiceProvider implementation
3507 static inline FileDialogImpl
*impl_from_IServiceProvider(IServiceProvider
*iface
)
3509 return CONTAINING_RECORD(iface
, FileDialogImpl
, IServiceProvider_iface
);
3512 static HRESULT WINAPI
IServiceProvider_fnQueryInterface(IServiceProvider
*iface
,
3513 REFIID riid
, void **ppvObject
)
3515 FileDialogImpl
*This
= impl_from_IServiceProvider(iface
);
3516 TRACE("%p\n", This
);
3517 return IFileDialog2_QueryInterface(&This
->IFileDialog2_iface
, riid
, ppvObject
);
3520 static ULONG WINAPI
IServiceProvider_fnAddRef(IServiceProvider
*iface
)
3522 FileDialogImpl
*This
= impl_from_IServiceProvider(iface
);
3523 TRACE("%p\n", This
);
3524 return IFileDialog2_AddRef(&This
->IFileDialog2_iface
);
3527 static ULONG WINAPI
IServiceProvider_fnRelease(IServiceProvider
*iface
)
3529 FileDialogImpl
*This
= impl_from_IServiceProvider(iface
);
3530 TRACE("%p\n", This
);
3531 return IFileDialog2_Release(&This
->IFileDialog2_iface
);
3534 static HRESULT WINAPI
IServiceProvider_fnQueryService(IServiceProvider
*iface
,
3535 REFGUID guidService
,
3536 REFIID riid
, void **ppv
)
3538 FileDialogImpl
*This
= impl_from_IServiceProvider(iface
);
3539 HRESULT hr
= E_NOTIMPL
;
3540 TRACE("%p (%s, %s, %p)\n", This
, debugstr_guid(guidService
), debugstr_guid(riid
), ppv
);
3543 if(IsEqualGUID(guidService
, &SID_STopLevelBrowser
) && This
->peb
)
3544 hr
= IExplorerBrowser_QueryInterface(This
->peb
, riid
, ppv
);
3545 else if(IsEqualGUID(guidService
, &SID_SExplorerBrowserFrame
))
3546 hr
= IFileDialog2_QueryInterface(&This
->IFileDialog2_iface
, riid
, ppv
);
3548 FIXME("Interface %s requested from unknown service %s\n",
3549 debugstr_guid(riid
), debugstr_guid(guidService
));
3554 static const IServiceProviderVtbl vt_IServiceProvider
= {
3555 IServiceProvider_fnQueryInterface
,
3556 IServiceProvider_fnAddRef
,
3557 IServiceProvider_fnRelease
,
3558 IServiceProvider_fnQueryService
3561 /**************************************************************************
3562 * ICommDlgBrowser3 implementation
3564 static inline FileDialogImpl
*impl_from_ICommDlgBrowser3(ICommDlgBrowser3
*iface
)
3566 return CONTAINING_RECORD(iface
, FileDialogImpl
, ICommDlgBrowser3_iface
);
3569 static HRESULT WINAPI
ICommDlgBrowser3_fnQueryInterface(ICommDlgBrowser3
*iface
,
3570 REFIID riid
, void **ppvObject
)
3572 FileDialogImpl
*This
= impl_from_ICommDlgBrowser3(iface
);
3573 TRACE("%p\n", This
);
3574 return IFileDialog2_QueryInterface(&This
->IFileDialog2_iface
, riid
, ppvObject
);
3577 static ULONG WINAPI
ICommDlgBrowser3_fnAddRef(ICommDlgBrowser3
*iface
)
3579 FileDialogImpl
*This
= impl_from_ICommDlgBrowser3(iface
);
3580 TRACE("%p\n", This
);
3581 return IFileDialog2_AddRef(&This
->IFileDialog2_iface
);
3584 static ULONG WINAPI
ICommDlgBrowser3_fnRelease(ICommDlgBrowser3
*iface
)
3586 FileDialogImpl
*This
= impl_from_ICommDlgBrowser3(iface
);
3587 TRACE("%p\n", This
);
3588 return IFileDialog2_Release(&This
->IFileDialog2_iface
);
3591 static HRESULT WINAPI
ICommDlgBrowser3_fnOnDefaultCommand(ICommDlgBrowser3
*iface
,
3594 FileDialogImpl
*This
= impl_from_ICommDlgBrowser3(iface
);
3596 TRACE("%p (%p)\n", This
, shv
);
3598 hr
= on_default_action(This
);
3601 EndDialog(This
->dlg_hwnd
, S_OK
);
3606 static HRESULT WINAPI
ICommDlgBrowser3_fnOnStateChange(ICommDlgBrowser3
*iface
,
3607 IShellView
*shv
, ULONG uChange
)
3609 FileDialogImpl
*This
= impl_from_ICommDlgBrowser3(iface
);
3610 IDataObject
*new_selection
;
3612 TRACE("%p (%p, %lx)\n", This
, shv
, uChange
);
3616 case CDBOSC_SELCHANGE
:
3617 if(This
->psia_selection
)
3619 IShellItemArray_Release(This
->psia_selection
);
3620 This
->psia_selection
= NULL
;
3623 hr
= IShellView_GetItemObject(shv
, SVGIO_SELECTION
, &IID_IDataObject
, (void**)&new_selection
);
3626 hr
= SHCreateShellItemArrayFromDataObject(new_selection
, &IID_IShellItemArray
,
3627 (void**)&This
->psia_selection
);
3630 fill_filename_from_selection(This
);
3631 events_OnSelectionChange(This
);
3634 IDataObject_Release(new_selection
);
3638 TRACE("Unhandled state change\n");
3643 static HRESULT WINAPI
ICommDlgBrowser3_fnIncludeObject(ICommDlgBrowser3
*iface
,
3644 IShellView
*shv
, LPCITEMIDLIST pidl
)
3646 FileDialogImpl
*This
= impl_from_ICommDlgBrowser3(iface
);
3649 LPITEMIDLIST parent_pidl
;
3652 TRACE("%p (%p, %p)\n", This
, shv
, pidl
);
3654 if(!This
->filterspec_count
&& !(This
->options
& FOS_PICKFOLDERS
))
3657 hr
= SHGetIDListFromObject((IUnknown
*)shv
, &parent_pidl
);
3660 LPITEMIDLIST full_pidl
= ILCombine(parent_pidl
, pidl
);
3661 hr
= SHCreateItemFromIDList(full_pidl
, &IID_IShellItem
, (void**)&psi
);
3662 ILFree(parent_pidl
);
3667 ERR("Failed to get shellitem (%08lx).\n", hr
);
3671 hr
= IShellItem_GetAttributes(psi
, SFGAO_FOLDER
|SFGAO_LINK
, &attr
);
3672 if(FAILED(hr
) || (attr
& (SFGAO_FOLDER
| SFGAO_LINK
)))
3674 IShellItem_Release(psi
);
3678 if((This
->options
& FOS_PICKFOLDERS
) && !(attr
& (SFGAO_FOLDER
| SFGAO_LINK
)))
3680 IShellItem_Release(psi
);
3685 if(SUCCEEDED(IShellItem_GetDisplayName(psi
, SIGDN_PARENTRELATIVEPARSING
, &filename
)))
3687 if(!PathMatchSpecW(filename
, This
->filterspecs
[This
->filetypeindex
].pszSpec
))
3689 CoTaskMemFree(filename
);
3692 IShellItem_Release(psi
);
3696 static HRESULT WINAPI
ICommDlgBrowser3_fnNotify(ICommDlgBrowser3
*iface
,
3697 IShellView
*ppshv
, DWORD dwNotifyType
)
3699 FileDialogImpl
*This
= impl_from_ICommDlgBrowser3(iface
);
3700 FIXME("Stub: %p (%p, 0x%lx)\n", This
, ppshv
, dwNotifyType
);
3704 static HRESULT WINAPI
ICommDlgBrowser3_fnGetDefaultMenuText(ICommDlgBrowser3
*iface
,
3706 LPWSTR pszText
, int cchMax
)
3708 FileDialogImpl
*This
= impl_from_ICommDlgBrowser3(iface
);
3709 FIXME("Stub: %p (%p, %p, %d)\n", This
, pshv
, pszText
, cchMax
);
3713 static HRESULT WINAPI
ICommDlgBrowser3_fnGetViewFlags(ICommDlgBrowser3
*iface
, DWORD
*pdwFlags
)
3715 FileDialogImpl
*This
= impl_from_ICommDlgBrowser3(iface
);
3716 FIXME("Stub: %p (%p)\n", This
, pdwFlags
);
3720 static HRESULT WINAPI
ICommDlgBrowser3_fnOnColumnClicked(ICommDlgBrowser3
*iface
,
3721 IShellView
*pshv
, int iColumn
)
3723 FileDialogImpl
*This
= impl_from_ICommDlgBrowser3(iface
);
3724 FIXME("Stub: %p (%p, %d)\n", This
, pshv
, iColumn
);
3728 static HRESULT WINAPI
ICommDlgBrowser3_fnGetCurrentFilter(ICommDlgBrowser3
*iface
,
3729 LPWSTR pszFileSpec
, int cchFileSpec
)
3731 FileDialogImpl
*This
= impl_from_ICommDlgBrowser3(iface
);
3732 FIXME("Stub: %p (%p, %d)\n", This
, pszFileSpec
, cchFileSpec
);
3736 static HRESULT WINAPI
ICommDlgBrowser3_fnOnPreviewCreated(ICommDlgBrowser3
*iface
,
3739 FileDialogImpl
*This
= impl_from_ICommDlgBrowser3(iface
);
3740 FIXME("Stub: %p (%p)\n", This
, pshv
);
3744 static const ICommDlgBrowser3Vtbl vt_ICommDlgBrowser3
= {
3745 ICommDlgBrowser3_fnQueryInterface
,
3746 ICommDlgBrowser3_fnAddRef
,
3747 ICommDlgBrowser3_fnRelease
,
3748 ICommDlgBrowser3_fnOnDefaultCommand
,
3749 ICommDlgBrowser3_fnOnStateChange
,
3750 ICommDlgBrowser3_fnIncludeObject
,
3751 ICommDlgBrowser3_fnNotify
,
3752 ICommDlgBrowser3_fnGetDefaultMenuText
,
3753 ICommDlgBrowser3_fnGetViewFlags
,
3754 ICommDlgBrowser3_fnOnColumnClicked
,
3755 ICommDlgBrowser3_fnGetCurrentFilter
,
3756 ICommDlgBrowser3_fnOnPreviewCreated
3759 /**************************************************************************
3760 * IOleWindow implementation
3762 static inline FileDialogImpl
*impl_from_IOleWindow(IOleWindow
*iface
)
3764 return CONTAINING_RECORD(iface
, FileDialogImpl
, IOleWindow_iface
);
3767 static HRESULT WINAPI
IOleWindow_fnQueryInterface(IOleWindow
*iface
, REFIID riid
, void **ppvObject
)
3769 FileDialogImpl
*This
= impl_from_IOleWindow(iface
);
3770 return IFileDialog2_QueryInterface(&This
->IFileDialog2_iface
, riid
, ppvObject
);
3773 static ULONG WINAPI
IOleWindow_fnAddRef(IOleWindow
*iface
)
3775 FileDialogImpl
*This
= impl_from_IOleWindow(iface
);
3776 return IFileDialog2_AddRef(&This
->IFileDialog2_iface
);
3779 static ULONG WINAPI
IOleWindow_fnRelease(IOleWindow
*iface
)
3781 FileDialogImpl
*This
= impl_from_IOleWindow(iface
);
3782 return IFileDialog2_Release(&This
->IFileDialog2_iface
);
3785 static HRESULT WINAPI
IOleWindow_fnContextSensitiveHelp(IOleWindow
*iface
, BOOL fEnterMOde
)
3787 FileDialogImpl
*This
= impl_from_IOleWindow(iface
);
3788 FIXME("Stub: %p (%d)\n", This
, fEnterMOde
);
3792 static HRESULT WINAPI
IOleWindow_fnGetWindow(IOleWindow
*iface
, HWND
*phwnd
)
3794 FileDialogImpl
*This
= impl_from_IOleWindow(iface
);
3795 TRACE("%p (%p)\n", This
, phwnd
);
3796 *phwnd
= This
->dlg_hwnd
;
3800 static const IOleWindowVtbl vt_IOleWindow
= {
3801 IOleWindow_fnQueryInterface
,
3802 IOleWindow_fnAddRef
,
3803 IOleWindow_fnRelease
,
3804 IOleWindow_fnGetWindow
,
3805 IOleWindow_fnContextSensitiveHelp
3808 /**************************************************************************
3809 * IFileDialogCustomize implementation
3811 static inline FileDialogImpl
*impl_from_IFileDialogCustomize(IFileDialogCustomize
*iface
)
3813 return CONTAINING_RECORD(iface
, FileDialogImpl
, IFileDialogCustomize_iface
);
3816 static HRESULT WINAPI
IFileDialogCustomize_fnQueryInterface(IFileDialogCustomize
*iface
,
3817 REFIID riid
, void **ppvObject
)
3819 FileDialogImpl
*This
= impl_from_IFileDialogCustomize(iface
);
3820 return IFileDialog2_QueryInterface(&This
->IFileDialog2_iface
, riid
, ppvObject
);
3823 static ULONG WINAPI
IFileDialogCustomize_fnAddRef(IFileDialogCustomize
*iface
)
3825 FileDialogImpl
*This
= impl_from_IFileDialogCustomize(iface
);
3826 return IFileDialog2_AddRef(&This
->IFileDialog2_iface
);
3829 static ULONG WINAPI
IFileDialogCustomize_fnRelease(IFileDialogCustomize
*iface
)
3831 FileDialogImpl
*This
= impl_from_IFileDialogCustomize(iface
);
3832 return IFileDialog2_Release(&This
->IFileDialog2_iface
);
3835 static HRESULT WINAPI
IFileDialogCustomize_fnEnableOpenDropDown(IFileDialogCustomize
*iface
,
3838 FileDialogImpl
*This
= impl_from_IFileDialogCustomize(iface
);
3840 TRACE("%p (%ld)\n", This
, dwIDCtl
);
3842 if (This
->hmenu_opendropdown
|| get_cctrl(This
, dwIDCtl
))
3843 return E_UNEXPECTED
;
3845 This
->hmenu_opendropdown
= CreatePopupMenu();
3847 if (!This
->hmenu_opendropdown
)
3848 return E_OUTOFMEMORY
;
3850 mi
.cbSize
= sizeof(mi
);
3851 mi
.fMask
= MIM_STYLE
;
3852 mi
.dwStyle
= MNS_NOTIFYBYPOS
;
3853 SetMenuInfo(This
->hmenu_opendropdown
, &mi
);
3855 This
->cctrl_opendropdown
.hwnd
= NULL
;
3856 This
->cctrl_opendropdown
.wrapper_hwnd
= NULL
;
3857 This
->cctrl_opendropdown
.id
= dwIDCtl
;
3858 This
->cctrl_opendropdown
.dlgid
= 0;
3859 This
->cctrl_opendropdown
.type
= IDLG_CCTRL_OPENDROPDOWN
;
3860 This
->cctrl_opendropdown
.cdcstate
= CDCS_ENABLED
| CDCS_VISIBLE
;
3861 list_init(&This
->cctrl_opendropdown
.sub_cctrls
);
3862 list_init(&This
->cctrl_opendropdown
.sub_items
);
3867 static HRESULT WINAPI
IFileDialogCustomize_fnAddMenu(IFileDialogCustomize
*iface
,
3871 FileDialogImpl
*This
= impl_from_IFileDialogCustomize(iface
);
3875 TRACE("%p (%ld, %p)\n", This
, dwIDCtl
, pszLabel
);
3877 hr
= cctrl_create_new(This
, dwIDCtl
, NULL
, TOOLBARCLASSNAMEW
,
3878 TBSTYLE_FLAT
| CCS_NODIVIDER
, 0,
3879 This
->cctrl_def_height
, &ctrl
);
3882 SendMessageW(ctrl
->hwnd
, TB_BUTTONSTRUCTSIZE
, sizeof(tbb
), 0);
3883 ctrl
->type
= IDLG_CCTRL_MENU
;
3885 /* Add the actual button with a popup menu. */
3886 tbb
.iBitmap
= I_IMAGENONE
;
3887 tbb
.dwData
= (DWORD_PTR
)CreatePopupMenu();
3888 tbb
.iString
= (DWORD_PTR
)pszLabel
;
3889 tbb
.fsState
= TBSTATE_ENABLED
;
3890 tbb
.fsStyle
= BTNS_WHOLEDROPDOWN
;
3893 SendMessageW(ctrl
->hwnd
, TB_ADDBUTTONSW
, 1, (LPARAM
)&tbb
);
3899 static HRESULT WINAPI
IFileDialogCustomize_fnAddPushButton(IFileDialogCustomize
*iface
,
3903 FileDialogImpl
*This
= impl_from_IFileDialogCustomize(iface
);
3906 TRACE("%p (%ld, %p)\n", This
, dwIDCtl
, pszLabel
);
3908 hr
= cctrl_create_new(This
, dwIDCtl
, pszLabel
, WC_BUTTONW
, BS_MULTILINE
, 0,
3909 This
->cctrl_def_height
, &ctrl
);
3911 ctrl
->type
= IDLG_CCTRL_PUSHBUTTON
;
3916 static HRESULT WINAPI
IFileDialogCustomize_fnAddComboBox(IFileDialogCustomize
*iface
,
3919 FileDialogImpl
*This
= impl_from_IFileDialogCustomize(iface
);
3922 TRACE("%p (%ld)\n", This
, dwIDCtl
);
3924 hr
= cctrl_create_new(This
, dwIDCtl
, NULL
, WC_COMBOBOXW
, CBS_DROPDOWNLIST
, 0,
3925 This
->cctrl_def_height
, &ctrl
);
3927 ctrl
->type
= IDLG_CCTRL_COMBOBOX
;
3932 static HRESULT WINAPI
IFileDialogCustomize_fnAddRadioButtonList(IFileDialogCustomize
*iface
,
3935 FileDialogImpl
*This
= impl_from_IFileDialogCustomize(iface
);
3938 TRACE("%p (%ld)\n", This
, dwIDCtl
);
3940 hr
= cctrl_create_new(This
, dwIDCtl
, NULL
, L
"RadioButtonList", 0, 0, 0, &ctrl
);
3943 ctrl
->type
= IDLG_CCTRL_RADIOBUTTONLIST
;
3944 SetWindowLongPtrW(ctrl
->hwnd
, GWLP_USERDATA
, (LPARAM
)This
);
3950 static HRESULT WINAPI
IFileDialogCustomize_fnAddCheckButton(IFileDialogCustomize
*iface
,
3955 FileDialogImpl
*This
= impl_from_IFileDialogCustomize(iface
);
3958 TRACE("%p (%ld, %p, %d)\n", This
, dwIDCtl
, pszLabel
, bChecked
);
3960 hr
= cctrl_create_new(This
, dwIDCtl
, pszLabel
, WC_BUTTONW
, BS_AUTOCHECKBOX
|BS_MULTILINE
, 0,
3961 This
->cctrl_def_height
, &ctrl
);
3964 ctrl
->type
= IDLG_CCTRL_CHECKBUTTON
;
3965 SendMessageW(ctrl
->hwnd
, BM_SETCHECK
, bChecked
? BST_CHECKED
: BST_UNCHECKED
, 0);
3971 static HRESULT WINAPI
IFileDialogCustomize_fnAddEditBox(IFileDialogCustomize
*iface
,
3975 FileDialogImpl
*This
= impl_from_IFileDialogCustomize(iface
);
3978 TRACE("%p (%ld, %p)\n", This
, dwIDCtl
, pszText
);
3980 hr
= cctrl_create_new(This
, dwIDCtl
, pszText
, WC_EDITW
, ES_AUTOHSCROLL
, WS_EX_CLIENTEDGE
,
3981 This
->cctrl_def_height
, &ctrl
);
3983 ctrl
->type
= IDLG_CCTRL_EDITBOX
;
3988 static HRESULT WINAPI
IFileDialogCustomize_fnAddSeparator(IFileDialogCustomize
*iface
,
3991 FileDialogImpl
*This
= impl_from_IFileDialogCustomize(iface
);
3994 TRACE("%p (%ld)\n", This
, dwIDCtl
);
3996 hr
= cctrl_create_new(This
, dwIDCtl
, NULL
, WC_STATICW
, SS_ETCHEDHORZ
, 0,
3997 GetSystemMetrics(SM_CYEDGE
), &ctrl
);
3999 ctrl
->type
= IDLG_CCTRL_SEPARATOR
;
4004 static HRESULT WINAPI
IFileDialogCustomize_fnAddText(IFileDialogCustomize
*iface
,
4008 FileDialogImpl
*This
= impl_from_IFileDialogCustomize(iface
);
4011 TRACE("%p (%ld, %p)\n", This
, dwIDCtl
, pszText
);
4013 hr
= cctrl_create_new(This
, dwIDCtl
, pszText
, WC_STATICW
, 0, 0,
4014 This
->cctrl_def_height
, &ctrl
);
4016 ctrl
->type
= IDLG_CCTRL_TEXT
;
4021 static HRESULT WINAPI
IFileDialogCustomize_fnSetControlLabel(IFileDialogCustomize
*iface
,
4025 FileDialogImpl
*This
= impl_from_IFileDialogCustomize(iface
);
4026 customctrl
*ctrl
= get_cctrl(This
, dwIDCtl
);
4027 TRACE("%p (%ld, %p)\n", This
, dwIDCtl
, pszLabel
);
4029 if(!ctrl
) return E_INVALIDARG
;
4033 case IDLG_CCTRL_MENU
:
4034 case IDLG_CCTRL_PUSHBUTTON
:
4035 case IDLG_CCTRL_CHECKBUTTON
:
4036 case IDLG_CCTRL_TEXT
:
4037 case IDLG_CCTRL_VISUALGROUP
:
4038 SendMessageW(ctrl
->hwnd
, WM_SETTEXT
, 0, (LPARAM
)pszLabel
);
4040 case IDLG_CCTRL_OPENDROPDOWN
:
4049 static HRESULT WINAPI
IFileDialogCustomize_fnGetControlState(IFileDialogCustomize
*iface
,
4051 CDCONTROLSTATEF
*pdwState
)
4053 FileDialogImpl
*This
= impl_from_IFileDialogCustomize(iface
);
4054 customctrl
*ctrl
= get_cctrl(This
, dwIDCtl
);
4055 TRACE("%p (%ld, %p)\n", This
, dwIDCtl
, pdwState
);
4057 if(!ctrl
|| ctrl
->type
== IDLG_CCTRL_OPENDROPDOWN
) return E_NOTIMPL
;
4059 *pdwState
= ctrl
->cdcstate
;
4063 static HRESULT WINAPI
IFileDialogCustomize_fnSetControlState(IFileDialogCustomize
*iface
,
4065 CDCONTROLSTATEF dwState
)
4067 FileDialogImpl
*This
= impl_from_IFileDialogCustomize(iface
);
4068 customctrl
*ctrl
= get_cctrl(This
,dwIDCtl
);
4069 TRACE("%p (%ld, %x)\n", This
, dwIDCtl
, dwState
);
4071 if(ctrl
&& ctrl
->hwnd
)
4073 LONG wndstyle
= GetWindowLongW(ctrl
->hwnd
, GWL_STYLE
);
4075 if(dwState
& CDCS_ENABLED
)
4076 wndstyle
&= ~(WS_DISABLED
);
4078 wndstyle
|= WS_DISABLED
;
4080 if(dwState
& CDCS_VISIBLE
)
4081 wndstyle
|= WS_VISIBLE
;
4083 wndstyle
&= ~(WS_VISIBLE
);
4085 SetWindowLongW(ctrl
->hwnd
, GWL_STYLE
, wndstyle
);
4087 /* We save the state separately since at least one application
4088 * relies on being able to hide a control. */
4089 ctrl
->cdcstate
= dwState
;
4095 static HRESULT WINAPI
IFileDialogCustomize_fnGetEditBoxText(IFileDialogCustomize
*iface
,
4099 FileDialogImpl
*This
= impl_from_IFileDialogCustomize(iface
);
4100 customctrl
*ctrl
= get_cctrl(This
, dwIDCtl
);
4102 TRACE("%p (%ld, %p)\n", This
, dwIDCtl
, ppszText
);
4104 if(!ctrl
|| !ctrl
->hwnd
|| !(len
= SendMessageW(ctrl
->hwnd
, WM_GETTEXTLENGTH
, 0, 0)))
4107 text
= CoTaskMemAlloc(sizeof(WCHAR
)*(len
+1));
4108 if(!text
) return E_FAIL
;
4110 SendMessageW(ctrl
->hwnd
, WM_GETTEXT
, len
+1, (LPARAM
)text
);
4115 static HRESULT WINAPI
IFileDialogCustomize_fnSetEditBoxText(IFileDialogCustomize
*iface
,
4119 FileDialogImpl
*This
= impl_from_IFileDialogCustomize(iface
);
4120 customctrl
*ctrl
= get_cctrl(This
, dwIDCtl
);
4121 TRACE("%p (%ld, %s)\n", This
, dwIDCtl
, debugstr_w(pszText
));
4123 if(!ctrl
|| ctrl
->type
!= IDLG_CCTRL_EDITBOX
)
4126 SendMessageW(ctrl
->hwnd
, WM_SETTEXT
, 0, (LPARAM
)pszText
);
4130 static HRESULT WINAPI
IFileDialogCustomize_fnGetCheckButtonState(IFileDialogCustomize
*iface
,
4134 FileDialogImpl
*This
= impl_from_IFileDialogCustomize(iface
);
4135 customctrl
*ctrl
= get_cctrl(This
, dwIDCtl
);
4136 TRACE("%p (%ld, %p)\n", This
, dwIDCtl
, pbChecked
);
4138 if(ctrl
&& ctrl
->hwnd
)
4139 *pbChecked
= (SendMessageW(ctrl
->hwnd
, BM_GETCHECK
, 0, 0) == BST_CHECKED
);
4144 static HRESULT WINAPI
IFileDialogCustomize_fnSetCheckButtonState(IFileDialogCustomize
*iface
,
4148 FileDialogImpl
*This
= impl_from_IFileDialogCustomize(iface
);
4149 customctrl
*ctrl
= get_cctrl(This
, dwIDCtl
);
4150 TRACE("%p (%ld, %d)\n", This
, dwIDCtl
, bChecked
);
4152 if(ctrl
&& ctrl
->hwnd
)
4153 SendMessageW(ctrl
->hwnd
, BM_SETCHECK
, bChecked
? BST_CHECKED
:BST_UNCHECKED
, 0);
4158 static UINT
get_combobox_index_from_id(HWND cb_hwnd
, DWORD dwIDItem
)
4160 UINT count
= SendMessageW(cb_hwnd
, CB_GETCOUNT
, 0, 0);
4162 if(!count
|| (count
== CB_ERR
))
4165 for(i
= 0; i
< count
; i
++)
4166 if(SendMessageW(cb_hwnd
, CB_GETITEMDATA
, i
, 0) == dwIDItem
)
4169 TRACE("Item with id %ld not found in combobox %p (item count: %d)\n", dwIDItem
, cb_hwnd
, count
);
4173 static HRESULT WINAPI
IFileDialogCustomize_fnAddControlItem(IFileDialogCustomize
*iface
,
4178 FileDialogImpl
*This
= impl_from_IFileDialogCustomize(iface
);
4179 customctrl
*ctrl
= get_cctrl(This
, dwIDCtl
);
4181 TRACE("%p (%ld, %ld, %s)\n", This
, dwIDCtl
, dwIDItem
, debugstr_w(pszLabel
));
4183 if(!ctrl
) return E_FAIL
;
4187 case IDLG_CCTRL_COMBOBOX
:
4192 hr
= add_item(ctrl
, dwIDItem
, pszLabel
, &item
);
4194 if (FAILED(hr
)) return hr
;
4196 index
= SendMessageW(ctrl
->hwnd
, CB_ADDSTRING
, 0, (LPARAM
)pszLabel
);
4197 SendMessageW(ctrl
->hwnd
, CB_SETITEMDATA
, index
, dwIDItem
);
4201 case IDLG_CCTRL_MENU
:
4202 case IDLG_CCTRL_OPENDROPDOWN
:
4207 hr
= add_item(ctrl
, dwIDItem
, pszLabel
, &item
);
4209 if (FAILED(hr
)) return hr
;
4211 if (ctrl
->type
== IDLG_CCTRL_MENU
)
4214 SendMessageW(ctrl
->hwnd
, TB_GETBUTTON
, 0, (LPARAM
)&tbb
);
4215 hmenu
= (HMENU
)tbb
.dwData
;
4217 else /* ctrl->type == IDLG_CCTRL_OPENDROPDOWN */
4218 hmenu
= This
->hmenu_opendropdown
;
4220 AppendMenuW(hmenu
, MF_STRING
, dwIDItem
, pszLabel
);
4223 case IDLG_CCTRL_RADIOBUTTONLIST
:
4227 hr
= add_item(ctrl
, dwIDItem
, pszLabel
, &item
);
4231 item
->hwnd
= CreateWindowExW(0, WC_BUTTONW
, pszLabel
,
4232 WS_CHILD
|WS_VISIBLE
|WS_CLIPSIBLINGS
|BS_RADIOBUTTON
|BS_MULTILINE
,
4233 0, 0, 0, 0, ctrl
->hwnd
, ULongToHandle(dwIDItem
), COMDLG32_hInstance
, 0);
4237 ERR("Failed to create radio button\n");
4238 list_remove(&item
->entry
);
4250 return E_NOINTERFACE
; /* win7 */
4253 static HRESULT WINAPI
IFileDialogCustomize_fnRemoveControlItem(IFileDialogCustomize
*iface
,
4257 FileDialogImpl
*This
= impl_from_IFileDialogCustomize(iface
);
4258 customctrl
*ctrl
= get_cctrl(This
, dwIDCtl
);
4259 TRACE("%p (%ld, %ld)\n", This
, dwIDCtl
, dwIDItem
);
4261 if(!ctrl
) return E_FAIL
;
4265 case IDLG_CCTRL_COMBOBOX
:
4270 item
= get_item(ctrl
, dwIDItem
, CDCS_VISIBLE
|CDCS_ENABLED
, &position
);
4273 return E_INVALIDARG
;
4275 if ((item
->cdcstate
& (CDCS_VISIBLE
|CDCS_ENABLED
)) == (CDCS_VISIBLE
|CDCS_ENABLED
))
4277 if(SendMessageW(ctrl
->hwnd
, CB_DELETESTRING
, position
, 0) == CB_ERR
)
4281 list_remove(&item
->entry
);
4286 case IDLG_CCTRL_MENU
:
4287 case IDLG_CCTRL_OPENDROPDOWN
:
4292 item
= get_item(ctrl
, dwIDItem
, 0, NULL
);
4295 return E_UNEXPECTED
;
4297 if (item
->cdcstate
& CDCS_VISIBLE
)
4299 if (ctrl
->type
== IDLG_CCTRL_MENU
)
4302 SendMessageW(ctrl
->hwnd
, TB_GETBUTTON
, 0, (LPARAM
)&tbb
);
4303 hmenu
= (HMENU
)tbb
.dwData
;
4305 else /* ctrl->type == IDLG_CCTRL_OPENDROPDOWN */
4306 hmenu
= This
->hmenu_opendropdown
;
4308 if(!hmenu
|| !DeleteMenu(hmenu
, dwIDItem
, MF_BYCOMMAND
))
4309 return E_UNEXPECTED
;
4312 list_remove(&item
->entry
);
4317 case IDLG_CCTRL_RADIOBUTTONLIST
:
4321 item
= get_item(ctrl
, dwIDItem
, 0, NULL
);
4324 return E_UNEXPECTED
;
4326 list_remove(&item
->entry
);
4338 static HRESULT WINAPI
IFileDialogCustomize_fnRemoveAllControlItems(IFileDialogCustomize
*iface
,
4341 FileDialogImpl
*This
= impl_from_IFileDialogCustomize(iface
);
4342 TRACE("%p (%ld)\n", This
, dwIDCtl
);
4344 /* Not implemented by native */
4348 static HRESULT WINAPI
IFileDialogCustomize_fnGetControlItemState(IFileDialogCustomize
*iface
,
4351 CDCONTROLSTATEF
*pdwState
)
4353 FileDialogImpl
*This
= impl_from_IFileDialogCustomize(iface
);
4354 customctrl
*ctrl
= get_cctrl(This
, dwIDCtl
);
4355 TRACE("%p (%ld, %ld, %p)\n", This
, dwIDCtl
, dwIDItem
, pdwState
);
4357 if(!ctrl
) return E_FAIL
;
4361 case IDLG_CCTRL_COMBOBOX
:
4362 case IDLG_CCTRL_MENU
:
4363 case IDLG_CCTRL_OPENDROPDOWN
:
4364 case IDLG_CCTRL_RADIOBUTTONLIST
:
4368 item
= get_item(ctrl
, dwIDItem
, 0, NULL
);
4371 return E_UNEXPECTED
;
4373 *pdwState
= item
->cdcstate
;
4384 static HRESULT WINAPI
IFileDialogCustomize_fnSetControlItemState(IFileDialogCustomize
*iface
,
4387 CDCONTROLSTATEF dwState
)
4389 FileDialogImpl
*This
= impl_from_IFileDialogCustomize(iface
);
4390 customctrl
*ctrl
= get_cctrl(This
, dwIDCtl
);
4391 TRACE("%p (%ld, %ld, %x)\n", This
, dwIDCtl
, dwIDItem
, dwState
);
4393 if(!ctrl
) return E_FAIL
;
4397 case IDLG_CCTRL_COMBOBOX
:
4400 BOOL visible
, was_visible
;
4403 item
= get_item(ctrl
, dwIDItem
, CDCS_VISIBLE
|CDCS_ENABLED
, &position
);
4406 return E_UNEXPECTED
;
4408 visible
= ((dwState
& (CDCS_VISIBLE
|CDCS_ENABLED
)) == (CDCS_VISIBLE
|CDCS_ENABLED
));
4409 was_visible
= ((item
->cdcstate
& (CDCS_VISIBLE
|CDCS_ENABLED
)) == (CDCS_VISIBLE
|CDCS_ENABLED
));
4411 if (visible
&& !was_visible
)
4413 SendMessageW(ctrl
->hwnd
, CB_INSERTSTRING
, position
, (LPARAM
)item
->label
);
4414 SendMessageW(ctrl
->hwnd
, CB_SETITEMDATA
, position
, dwIDItem
);
4416 else if (!visible
&& was_visible
)
4418 SendMessageW(ctrl
->hwnd
, CB_DELETESTRING
, position
, 0);
4421 item
->cdcstate
= dwState
;
4425 case IDLG_CCTRL_MENU
:
4426 case IDLG_CCTRL_OPENDROPDOWN
:
4430 CDCONTROLSTATEF prev_state
;
4433 item
= get_item(ctrl
, dwIDItem
, CDCS_VISIBLE
, &position
);
4436 return E_UNEXPECTED
;
4438 prev_state
= item
->cdcstate
;
4440 if (ctrl
->type
== IDLG_CCTRL_MENU
)
4443 SendMessageW(ctrl
->hwnd
, TB_GETBUTTON
, 0, (LPARAM
)&tbb
);
4444 hmenu
= (HMENU
)tbb
.dwData
;
4446 else /* ctrl->type == IDLG_CCTRL_OPENDROPDOWN */
4447 hmenu
= This
->hmenu_opendropdown
;
4449 if (dwState
& CDCS_VISIBLE
)
4451 if (prev_state
& CDCS_VISIBLE
)
4454 EnableMenuItem(hmenu
, dwIDItem
,
4455 MF_BYCOMMAND
|((dwState
& CDCS_ENABLED
) ? MFS_ENABLED
: MFS_DISABLED
));
4462 mii
.cbSize
= sizeof(mii
);
4463 mii
.fMask
= MIIM_ID
|MIIM_STATE
|MIIM_STRING
;
4464 mii
.fState
= (dwState
& CDCS_ENABLED
) ? MFS_ENABLED
: MFS_DISABLED
;
4466 mii
.dwTypeData
= item
->label
;
4468 InsertMenuItemW(hmenu
, position
, TRUE
, &mii
);
4471 else if (prev_state
& CDCS_VISIBLE
)
4474 DeleteMenu(hmenu
, dwIDItem
, MF_BYCOMMAND
);
4477 item
->cdcstate
= dwState
;
4479 if (ctrl
->type
== IDLG_CCTRL_OPENDROPDOWN
)
4481 update_control_text(This
);
4482 update_layout(This
);
4487 case IDLG_CCTRL_RADIOBUTTONLIST
:
4491 item
= get_item(ctrl
, dwIDItem
, CDCS_VISIBLE
, NULL
);
4494 return E_UNEXPECTED
;
4496 /* Oddly, native allows setting this but doesn't seem to do anything with it. */
4497 item
->cdcstate
= dwState
;
4508 static HRESULT WINAPI
IFileDialogCustomize_fnGetSelectedControlItem(IFileDialogCustomize
*iface
,
4512 FileDialogImpl
*This
= impl_from_IFileDialogCustomize(iface
);
4513 customctrl
*ctrl
= get_cctrl(This
, dwIDCtl
);
4514 TRACE("%p (%ld, %p)\n", This
, dwIDCtl
, pdwIDItem
);
4516 if(!ctrl
) return E_FAIL
;
4520 case IDLG_CCTRL_COMBOBOX
:
4522 UINT index
= SendMessageW(ctrl
->hwnd
, CB_GETCURSEL
, 0, 0);
4526 *pdwIDItem
= SendMessageW(ctrl
->hwnd
, CB_GETITEMDATA
, index
, 0);
4529 case IDLG_CCTRL_OPENDROPDOWN
:
4530 if (This
->opendropdown_has_selection
)
4532 *pdwIDItem
= This
->opendropdown_selection
;
4537 /* Return first enabled item. */
4538 cctrl_item
* item
= get_first_item(ctrl
);
4542 *pdwIDItem
= item
->id
;
4546 WARN("no enabled items in open dropdown\n");
4549 case IDLG_CCTRL_RADIOBUTTONLIST
:
4553 LIST_FOR_EACH_ENTRY(item
, &ctrl
->sub_items
, cctrl_item
, entry
)
4555 if (SendMessageW(item
->hwnd
, BM_GETCHECK
, 0, 0) == BST_CHECKED
)
4557 *pdwIDItem
= item
->id
;
4562 WARN("no checked items in radio button list\n");
4566 FIXME("Unsupported control type %d\n", ctrl
->type
);
4572 static HRESULT WINAPI
IFileDialogCustomize_fnSetSelectedControlItem(IFileDialogCustomize
*iface
,
4576 FileDialogImpl
*This
= impl_from_IFileDialogCustomize(iface
);
4577 customctrl
*ctrl
= get_cctrl(This
, dwIDCtl
);
4578 TRACE("%p (%ld, %ld)\n", This
, dwIDCtl
, dwIDItem
);
4580 if(!ctrl
) return E_INVALIDARG
;
4584 case IDLG_CCTRL_COMBOBOX
:
4586 UINT index
= get_combobox_index_from_id(ctrl
->hwnd
, dwIDItem
);
4589 return E_INVALIDARG
;
4591 if(SendMessageW(ctrl
->hwnd
, CB_SETCURSEL
, index
, 0) == CB_ERR
)
4596 case IDLG_CCTRL_RADIOBUTTONLIST
:
4600 item
= get_item(ctrl
, dwIDItem
, 0, NULL
);
4604 radiobuttonlist_set_selected_item(This
, ctrl
, item
);
4608 return E_INVALIDARG
;
4611 FIXME("Unsupported control type %d\n", ctrl
->type
);
4614 return E_INVALIDARG
;
4617 static HRESULT WINAPI
IFileDialogCustomize_fnStartVisualGroup(IFileDialogCustomize
*iface
,
4621 FileDialogImpl
*This
= impl_from_IFileDialogCustomize(iface
);
4624 TRACE("%p (%ld, %s)\n", This
, dwIDCtl
, debugstr_w(pszLabel
));
4626 if(This
->cctrl_active_vg
)
4627 return E_UNEXPECTED
;
4629 hr
= cctrl_create_new(This
, dwIDCtl
, pszLabel
, WC_STATICW
, 0, 0,
4630 This
->cctrl_def_height
, &vg
);
4633 vg
->type
= IDLG_CCTRL_VISUALGROUP
;
4634 This
->cctrl_active_vg
= vg
;
4640 static HRESULT WINAPI
IFileDialogCustomize_fnEndVisualGroup(IFileDialogCustomize
*iface
)
4642 FileDialogImpl
*This
= impl_from_IFileDialogCustomize(iface
);
4643 TRACE("%p\n", This
);
4645 This
->cctrl_active_vg
= NULL
;
4650 static HRESULT WINAPI
IFileDialogCustomize_fnMakeProminent(IFileDialogCustomize
*iface
,
4653 FileDialogImpl
*This
= impl_from_IFileDialogCustomize(iface
);
4654 FIXME("stub - %p (%ld)\n", This
, dwIDCtl
);
4658 static HRESULT WINAPI
IFileDialogCustomize_fnSetControlItemText(IFileDialogCustomize
*iface
,
4663 FileDialogImpl
*This
= impl_from_IFileDialogCustomize(iface
);
4664 FIXME("stub - %p (%ld, %ld, %s)\n", This
, dwIDCtl
, dwIDItem
, debugstr_w(pszLabel
));
4668 static const IFileDialogCustomizeVtbl vt_IFileDialogCustomize
= {
4669 IFileDialogCustomize_fnQueryInterface
,
4670 IFileDialogCustomize_fnAddRef
,
4671 IFileDialogCustomize_fnRelease
,
4672 IFileDialogCustomize_fnEnableOpenDropDown
,
4673 IFileDialogCustomize_fnAddMenu
,
4674 IFileDialogCustomize_fnAddPushButton
,
4675 IFileDialogCustomize_fnAddComboBox
,
4676 IFileDialogCustomize_fnAddRadioButtonList
,
4677 IFileDialogCustomize_fnAddCheckButton
,
4678 IFileDialogCustomize_fnAddEditBox
,
4679 IFileDialogCustomize_fnAddSeparator
,
4680 IFileDialogCustomize_fnAddText
,
4681 IFileDialogCustomize_fnSetControlLabel
,
4682 IFileDialogCustomize_fnGetControlState
,
4683 IFileDialogCustomize_fnSetControlState
,
4684 IFileDialogCustomize_fnGetEditBoxText
,
4685 IFileDialogCustomize_fnSetEditBoxText
,
4686 IFileDialogCustomize_fnGetCheckButtonState
,
4687 IFileDialogCustomize_fnSetCheckButtonState
,
4688 IFileDialogCustomize_fnAddControlItem
,
4689 IFileDialogCustomize_fnRemoveControlItem
,
4690 IFileDialogCustomize_fnRemoveAllControlItems
,
4691 IFileDialogCustomize_fnGetControlItemState
,
4692 IFileDialogCustomize_fnSetControlItemState
,
4693 IFileDialogCustomize_fnGetSelectedControlItem
,
4694 IFileDialogCustomize_fnSetSelectedControlItem
,
4695 IFileDialogCustomize_fnStartVisualGroup
,
4696 IFileDialogCustomize_fnEndVisualGroup
,
4697 IFileDialogCustomize_fnMakeProminent
,
4698 IFileDialogCustomize_fnSetControlItemText
4701 static HRESULT
FileDialog_constructor(IUnknown
*pUnkOuter
, REFIID riid
, void **ppv
, enum ITEMDLG_TYPE type
)
4703 FileDialogImpl
*fdimpl
;
4706 TRACE("%p, %s, %p\n", pUnkOuter
, debugstr_guid(riid
), ppv
);
4711 return CLASS_E_NOAGGREGATION
;
4713 fdimpl
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(FileDialogImpl
));
4715 return E_OUTOFMEMORY
;
4718 fdimpl
->IFileDialog2_iface
.lpVtbl
= &vt_IFileDialog2
;
4719 fdimpl
->IExplorerBrowserEvents_iface
.lpVtbl
= &vt_IExplorerBrowserEvents
;
4720 fdimpl
->IServiceProvider_iface
.lpVtbl
= &vt_IServiceProvider
;
4721 fdimpl
->ICommDlgBrowser3_iface
.lpVtbl
= &vt_ICommDlgBrowser3
;
4722 fdimpl
->IOleWindow_iface
.lpVtbl
= &vt_IOleWindow
;
4723 fdimpl
->IFileDialogCustomize_iface
.lpVtbl
= &vt_IFileDialogCustomize
;
4725 if(type
== ITEMDLG_TYPE_OPEN
)
4727 fdimpl
->dlg_type
= ITEMDLG_TYPE_OPEN
;
4728 fdimpl
->u
.IFileOpenDialog_iface
.lpVtbl
= &vt_IFileOpenDialog
;
4729 fdimpl
->options
= FOS_PATHMUSTEXIST
| FOS_FILEMUSTEXIST
| FOS_NOCHANGEDIR
;
4730 fdimpl
->custom_title
= fdimpl
->custom_okbutton
= NULL
;
4735 fdimpl
->dlg_type
= ITEMDLG_TYPE_SAVE
;
4736 fdimpl
->u
.IFileSaveDialog_iface
.lpVtbl
= &vt_IFileSaveDialog
;
4737 fdimpl
->options
= FOS_OVERWRITEPROMPT
| FOS_NOREADONLYRETURN
| FOS_PATHMUSTEXIST
| FOS_NOCHANGEDIR
;
4739 LoadStringW(COMDLG32_hInstance
, IDS_SAVE
, buf
, ARRAY_SIZE(buf
));
4740 fdimpl
->custom_title
= StrDupW(buf
);
4741 fdimpl
->custom_okbutton
= StrDupW(buf
);
4744 list_init(&fdimpl
->events_clients
);
4746 /* FIXME: The default folder setting should be restored for the
4747 * application if it was previously set. */
4748 SHGetDesktopFolder(&psf
);
4749 SHGetItemFromObject((IUnknown
*)psf
, &IID_IShellItem
, (void**)&fdimpl
->psi_defaultfolder
);
4750 IShellFolder_Release(psf
);
4752 hr
= init_custom_controls(fdimpl
);
4755 ERR("Failed to initialize custom controls (0x%08lx).\n", hr
);
4756 IFileDialog2_Release(&fdimpl
->IFileDialog2_iface
);
4760 fdimpl
->user_actctx
= INVALID_HANDLE_VALUE
;
4762 hr
= IFileDialog2_QueryInterface(&fdimpl
->IFileDialog2_iface
, riid
, ppv
);
4763 IFileDialog2_Release(&fdimpl
->IFileDialog2_iface
);
4767 HRESULT
FileOpenDialog_Constructor(IUnknown
*pUnkOuter
, REFIID riid
, void **ppv
)
4769 return FileDialog_constructor(pUnkOuter
, riid
, ppv
, ITEMDLG_TYPE_OPEN
);
4772 HRESULT
FileSaveDialog_Constructor(IUnknown
*pUnkOuter
, REFIID riid
, void **ppv
)
4774 return FileDialog_constructor(pUnkOuter
, riid
, ppv
, ITEMDLG_TYPE_SAVE
);