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
24 #define NONAMELESSUNION
35 #include "filedlgbrowser.h"
37 #include "wine/debug.h"
38 #include "wine/list.h"
40 #define IDC_NAV_TOOLBAR 200
41 #define IDC_NAVBACK 201
42 #define IDC_NAVFORWARD 202
45 /* This seems to be another version of IID_IFileDialogCustomize. If
46 * there is any difference I have yet to find it. */
47 DEFINE_GUID(IID_IFileDialogCustomizeAlt
, 0x8016B7B3, 0x3D49, 0x4504, 0xA0,0xAA, 0x2A,0x37,0x49,0x4E,0x60,0x6F);
49 WINE_DEFAULT_DEBUG_CHANNEL(commdlg
);
51 static const WCHAR notifysink_childW
[] = {'n','f','s','_','c','h','i','l','d',0};
52 static const WCHAR floatnotifysinkW
[] = {'F','l','o','a','t','N','o','t','i','f','y','S','i','n','k',0};
53 static const WCHAR radiobuttonlistW
[] = {'R','a','d','i','o','B','u','t','t','o','n','L','i','s','t',0};
60 enum ITEMDLG_CCTRL_TYPE
{
62 IDLG_CCTRL_PUSHBUTTON
,
64 IDLG_CCTRL_RADIOBUTTONLIST
,
65 IDLG_CCTRL_CHECKBUTTON
,
69 IDLG_CCTRL_OPENDROPDOWN
,
70 IDLG_CCTRL_VISUALGROUP
73 typedef struct cctrl_item
{
76 CDCONTROLSTATEF cdcstate
;
82 HWND hwnd
, wrapper_hwnd
;
84 enum ITEMDLG_CCTRL_TYPE type
;
85 CDCONTROLSTATEF cdcstate
;
88 struct list sub_cctrls
;
89 struct list sub_cctrls_entry
;
90 struct list sub_items
;
95 IFileDialogEvents
*pfde
;
99 typedef struct FileDialogImpl
{
100 IFileDialog2 IFileDialog2_iface
;
102 IFileOpenDialog IFileOpenDialog_iface
;
103 IFileSaveDialog IFileSaveDialog_iface
;
105 enum ITEMDLG_TYPE dlg_type
;
106 IExplorerBrowserEvents IExplorerBrowserEvents_iface
;
107 IServiceProvider IServiceProvider_iface
;
108 ICommDlgBrowser3 ICommDlgBrowser3_iface
;
109 IOleWindow IOleWindow_iface
;
110 IFileDialogCustomize IFileDialogCustomize_iface
;
113 FILEOPENDIALOGOPTIONS options
;
114 COMDLG_FILTERSPEC
*filterspecs
;
115 UINT filterspec_count
;
118 struct list events_clients
;
119 DWORD events_next_cookie
;
121 IShellItemArray
*psia_selection
;
122 IShellItemArray
*psia_results
;
123 IShellItem
*psi_defaultfolder
;
124 IShellItem
*psi_setfolder
;
125 IShellItem
*psi_folder
;
128 IExplorerBrowser
*peb
;
129 DWORD ebevents_cookie
;
134 LPWSTR custom_okbutton
;
135 LPWSTR custom_cancelbutton
;
136 LPWSTR custom_filenamelabel
;
138 UINT cctrl_width
, cctrl_def_height
, cctrls_cols
;
139 UINT cctrl_indent
, dpi_x
, dpi_y
;
142 UINT_PTR cctrl_next_dlgid
;
143 customctrl
*cctrl_active_vg
;
145 HMENU hmenu_opendropdown
;
146 customctrl cctrl_opendropdown
;
147 HFONT hfont_opendropdown
;
148 BOOL opendropdown_has_selection
;
149 DWORD opendropdown_selection
;
154 /**************************************************************************
157 static HRESULT
events_OnFileOk(FileDialogImpl
*This
)
159 events_client
*cursor
;
163 LIST_FOR_EACH_ENTRY(cursor
, &This
->events_clients
, events_client
, entry
)
165 TRACE("Notifying %p\n", cursor
);
166 hr
= IFileDialogEvents_OnFileOk(cursor
->pfde
, (IFileDialog
*)&This
->IFileDialog2_iface
);
167 if(FAILED(hr
) && hr
!= E_NOTIMPL
)
177 static HRESULT
events_OnFolderChanging(FileDialogImpl
*This
, IShellItem
*folder
)
179 events_client
*cursor
;
181 TRACE("%p (%p)\n", This
, folder
);
183 LIST_FOR_EACH_ENTRY(cursor
, &This
->events_clients
, events_client
, entry
)
185 TRACE("Notifying %p\n", cursor
);
186 hr
= IFileDialogEvents_OnFolderChanging(cursor
->pfde
, (IFileDialog
*)&This
->IFileDialog2_iface
, folder
);
187 if(FAILED(hr
) && hr
!= E_NOTIMPL
)
197 static void events_OnFolderChange(FileDialogImpl
*This
)
199 events_client
*cursor
;
202 LIST_FOR_EACH_ENTRY(cursor
, &This
->events_clients
, events_client
, entry
)
204 TRACE("Notifying %p\n", cursor
);
205 IFileDialogEvents_OnFolderChange(cursor
->pfde
, (IFileDialog
*)&This
->IFileDialog2_iface
);
209 static void events_OnSelectionChange(FileDialogImpl
*This
)
211 events_client
*cursor
;
214 LIST_FOR_EACH_ENTRY(cursor
, &This
->events_clients
, events_client
, entry
)
216 TRACE("Notifying %p\n", cursor
);
217 IFileDialogEvents_OnSelectionChange(cursor
->pfde
, (IFileDialog
*)&This
->IFileDialog2_iface
);
221 static void events_OnTypeChange(FileDialogImpl
*This
)
223 events_client
*cursor
;
226 LIST_FOR_EACH_ENTRY(cursor
, &This
->events_clients
, events_client
, entry
)
228 TRACE("Notifying %p\n", cursor
);
229 IFileDialogEvents_OnTypeChange(cursor
->pfde
, (IFileDialog
*)&This
->IFileDialog2_iface
);
233 static HRESULT
events_OnOverwrite(FileDialogImpl
*This
, IShellItem
*shellitem
)
235 events_client
*cursor
;
237 FDE_OVERWRITE_RESPONSE response
= FDEOR_DEFAULT
;
238 TRACE("%p %p\n", This
, shellitem
);
240 LIST_FOR_EACH_ENTRY(cursor
, &This
->events_clients
, events_client
, entry
)
242 TRACE("Notifying %p\n", cursor
);
243 hr
= IFileDialogEvents_OnOverwrite(cursor
->pfde
, (IFileDialog
*)&This
->IFileDialog2_iface
, shellitem
, &response
);
244 TRACE("<-- hr=%x response=%u\n", hr
, response
);
245 if(FAILED(hr
) && hr
!= E_NOTIMPL
)
254 if (response
== FDEOR_DEFAULT
)
259 LoadStringW(COMDLG32_hInstance
, IDS_OVERWRITEFILE
, buf
, 100);
260 answer
= MessageBoxW(This
->dlg_hwnd
, buf
, This
->custom_title
,
261 MB_YESNO
| MB_ICONEXCLAMATION
);
262 if (answer
== IDNO
|| answer
== IDCANCEL
)
267 else if (response
== FDEOR_REFUSE
)
274 static inline HRESULT
get_cctrl_event(IFileDialogEvents
*pfde
, IFileDialogControlEvents
**pfdce
)
276 return IFileDialogEvents_QueryInterface(pfde
, &IID_IFileDialogControlEvents
, (void**)pfdce
);
279 static HRESULT
cctrl_event_OnButtonClicked(FileDialogImpl
*This
, DWORD ctl_id
)
281 events_client
*cursor
;
284 LIST_FOR_EACH_ENTRY(cursor
, &This
->events_clients
, events_client
, entry
)
286 IFileDialogControlEvents
*pfdce
;
287 if(SUCCEEDED(get_cctrl_event(cursor
->pfde
, &pfdce
)))
289 TRACE("Notifying %p\n", cursor
);
290 IFileDialogControlEvents_OnButtonClicked(pfdce
, &This
->IFileDialogCustomize_iface
, ctl_id
);
291 IFileDialogControlEvents_Release(pfdce
);
298 static HRESULT
cctrl_event_OnItemSelected(FileDialogImpl
*This
, DWORD ctl_id
, DWORD item_id
)
300 events_client
*cursor
;
301 TRACE("%p %i %i\n", This
, ctl_id
, item_id
);
303 LIST_FOR_EACH_ENTRY(cursor
, &This
->events_clients
, events_client
, entry
)
305 IFileDialogControlEvents
*pfdce
;
306 if(SUCCEEDED(get_cctrl_event(cursor
->pfde
, &pfdce
)))
308 TRACE("Notifying %p\n", cursor
);
309 IFileDialogControlEvents_OnItemSelected(pfdce
, &This
->IFileDialogCustomize_iface
, ctl_id
, item_id
);
310 IFileDialogControlEvents_Release(pfdce
);
317 static HRESULT
cctrl_event_OnCheckButtonToggled(FileDialogImpl
*This
, DWORD ctl_id
, BOOL checked
)
319 events_client
*cursor
;
322 LIST_FOR_EACH_ENTRY(cursor
, &This
->events_clients
, events_client
, entry
)
324 IFileDialogControlEvents
*pfdce
;
325 if(SUCCEEDED(get_cctrl_event(cursor
->pfde
, &pfdce
)))
327 TRACE("Notifying %p\n", cursor
);
328 IFileDialogControlEvents_OnCheckButtonToggled(pfdce
, &This
->IFileDialogCustomize_iface
, ctl_id
, checked
);
329 IFileDialogControlEvents_Release(pfdce
);
336 static HRESULT
cctrl_event_OnControlActivating(FileDialogImpl
*This
,
339 events_client
*cursor
;
342 LIST_FOR_EACH_ENTRY(cursor
, &This
->events_clients
, events_client
, entry
)
344 IFileDialogControlEvents
*pfdce
;
345 if(SUCCEEDED(get_cctrl_event(cursor
->pfde
, &pfdce
)))
347 TRACE("Notifying %p\n", cursor
);
348 IFileDialogControlEvents_OnControlActivating(pfdce
, &This
->IFileDialogCustomize_iface
, ctl_id
);
349 IFileDialogControlEvents_Release(pfdce
);
356 /**************************************************************************
359 static UINT
get_file_name(FileDialogImpl
*This
, LPWSTR
*str
)
361 HWND hwnd_edit
= GetDlgItem(This
->dlg_hwnd
, IDC_FILENAME
);
366 if(This
->set_filename
)
368 len
= lstrlenW(This
->set_filename
);
369 *str
= CoTaskMemAlloc(sizeof(WCHAR
)*(len
+1));
370 lstrcpyW(*str
, This
->set_filename
);
376 len
= SendMessageW(hwnd_edit
, WM_GETTEXTLENGTH
, 0, 0);
377 *str
= CoTaskMemAlloc(sizeof(WCHAR
)*(len
+1));
381 SendMessageW(hwnd_edit
, WM_GETTEXT
, len
+1, (LPARAM
)*str
);
385 static BOOL
set_file_name(FileDialogImpl
*This
, LPCWSTR str
)
387 if(This
->set_filename
)
388 LocalFree(This
->set_filename
);
390 This
->set_filename
= str
? StrDupW(str
) : NULL
;
392 return SetDlgItemTextW(This
->dlg_hwnd
, IDC_FILENAME
, This
->set_filename
);
395 static void fill_filename_from_selection(FileDialogImpl
*This
)
400 UINT item_count
, valid_count
;
403 if(!This
->psia_selection
)
406 hr
= IShellItemArray_GetCount(This
->psia_selection
, &item_count
);
407 if(FAILED(hr
) || !item_count
)
410 names
= HeapAlloc(GetProcessHeap(), 0, item_count
*sizeof(LPWSTR
));
412 /* Get names of the selected items */
413 valid_count
= 0; len_total
= 0;
414 for(i
= 0; i
< item_count
; i
++)
416 hr
= IShellItemArray_GetItemAt(This
->psia_selection
, i
, &psi
);
421 hr
= IShellItem_GetAttributes(psi
, SFGAO_FOLDER
, &attr
);
423 (( (This
->options
& FOS_PICKFOLDERS
) && !(attr
& SFGAO_FOLDER
)) ||
424 (!(This
->options
& FOS_PICKFOLDERS
) && (attr
& SFGAO_FOLDER
))))
427 hr
= IShellItem_GetDisplayName(psi
, (This
->options
& FOS_PICKFOLDERS
) ? SIGDN_FILESYSPATH
: SIGDN_PARENTRELATIVEPARSING
, &names
[valid_count
]);
430 len_total
+= lstrlenW(names
[valid_count
]) + 3;
433 IShellItem_Release(psi
);
439 set_file_name(This
, names
[0]);
440 CoTaskMemFree(names
[0]);
442 else if(valid_count
> 1)
444 LPWSTR string
= HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR
)*len_total
);
445 LPWSTR cur_point
= string
;
447 for(i
= 0; i
< valid_count
; i
++)
449 LPWSTR file
= names
[i
];
451 lstrcpyW(cur_point
, file
);
452 cur_point
+= lstrlenW(file
);
457 *(cur_point
-1) = '\0';
459 set_file_name(This
, string
);
460 HeapFree(GetProcessHeap(), 0, string
);
463 HeapFree(GetProcessHeap(), 0, names
);
467 static LPWSTR
get_first_ext_from_spec(LPWSTR buf
, LPCWSTR spec
)
472 if( (endpos
= StrChrW(buf
, ';')) )
475 ext
= PathFindExtensionW(buf
);
476 if(StrChrW(ext
, '*'))
482 static BOOL
shell_item_exists(IShellItem
* shellitem
)
488 hr
= IShellItem_GetDisplayName(shellitem
, SIGDN_FILESYSPATH
, &filename
);
491 /* FIXME: Implement SFGAO_VALIDATE in Wine and use it instead. */
492 result
= (GetFileAttributesW(filename
) != INVALID_FILE_ATTRIBUTES
);
493 CoTaskMemFree(filename
);
498 result
= SUCCEEDED(IShellItem_GetAttributes(shellitem
, SFGAO_VALIDATE
, &attributes
));
504 static HRESULT
on_default_action(FileDialogImpl
*This
)
506 IShellFolder
*psf_parent
, *psf_desktop
;
508 LPITEMIDLIST current_folder
;
509 LPWSTR fn_iter
, files
= NULL
, tmp_files
;
510 UINT file_count
= 0, len
, i
;
512 HRESULT hr
, ret
= E_FAIL
;
514 len
= get_file_name(This
, &tmp_files
);
518 file_count
= COMDLG32_SplitFileNames(tmp_files
, len
, &files
, &size_used
);
519 CoTaskMemFree(tmp_files
);
521 if(!file_count
) return E_FAIL
;
523 hr
= SHGetIDListFromObject((IUnknown
*)This
->psi_folder
, ¤t_folder
);
526 ERR("Failed to get pidl for current directory.\n");
527 HeapFree(GetProcessHeap(), 0, files
);
531 TRACE("Acting on %d file(s).\n", file_count
);
533 pidla
= HeapAlloc(GetProcessHeap(), 0, sizeof(LPITEMIDLIST
) * file_count
);
534 open_action
= ONOPEN_OPEN
;
537 for(i
= 0; i
< file_count
&& open_action
== ONOPEN_OPEN
; i
++)
539 WCHAR canon_filename
[MAX_PATH
];
542 COMDLG32_GetCanonicalPath(current_folder
, fn_iter
, canon_filename
);
544 if( (This
->options
& FOS_NOVALIDATE
) &&
545 !(This
->options
& FOS_FILEMUSTEXIST
) )
546 open_action
= ONOPEN_OPEN
;
548 open_action
= ONOPEN_BROWSE
;
550 open_action
= FILEDLG95_ValidatePathAction(canon_filename
, &psf_parent
, This
->dlg_hwnd
,
551 This
->options
& ~FOS_FILEMUSTEXIST
,
552 (This
->dlg_type
== ITEMDLG_TYPE_SAVE
),
555 /* Add the proper extension */
556 if(open_action
== ONOPEN_OPEN
)
558 static const WCHAR dotW
[] = {'.',0};
560 if(This
->dlg_type
== ITEMDLG_TYPE_SAVE
)
562 WCHAR extbuf
[MAX_PATH
], *newext
= NULL
;
564 if(This
->filterspec_count
)
566 newext
= get_first_ext_from_spec(extbuf
, This
->filterspecs
[This
->filetypeindex
].pszSpec
);
568 else if(This
->default_ext
)
570 lstrcpyW(extbuf
, dotW
);
571 lstrcatW(extbuf
, This
->default_ext
);
577 WCHAR
*ext
= PathFindExtensionW(canon_filename
);
578 if(lstrcmpW(ext
, newext
))
579 lstrcatW(canon_filename
, newext
);
584 if( !(This
->options
& FOS_NOVALIDATE
) && (This
->options
& FOS_FILEMUSTEXIST
) &&
585 !PathFileExistsW(canon_filename
))
587 if(This
->default_ext
)
589 lstrcatW(canon_filename
, dotW
);
590 lstrcatW(canon_filename
, This
->default_ext
);
592 if(!PathFileExistsW(canon_filename
))
594 FILEDLG95_OnOpenMessage(This
->dlg_hwnd
, 0, IDS_FILENOTEXISTING
);
595 open_action
= ONOPEN_BROWSE
;
600 FILEDLG95_OnOpenMessage(This
->dlg_hwnd
, 0, IDS_FILENOTEXISTING
);
601 open_action
= ONOPEN_BROWSE
;
607 pidla
[i
] = COMDLG32_SHSimpleIDListFromPathAW(canon_filename
);
609 if(psf_parent
&& !(open_action
== ONOPEN_BROWSE
))
610 IShellFolder_Release(psf_parent
);
612 fn_iter
+= (WCHAR
)lstrlenW(fn_iter
) + 1;
615 HeapFree(GetProcessHeap(), 0, files
);
616 ILFree(current_folder
);
618 if((This
->options
& FOS_PICKFOLDERS
) && open_action
== ONOPEN_BROWSE
)
619 open_action
= ONOPEN_OPEN
; /* FIXME: Multiple folders? */
624 FIXME("Filtering not implemented.\n");
628 hr
= IExplorerBrowser_BrowseToObject(This
->peb
, (IUnknown
*)psf_parent
, SBSP_DEFBROWSER
);
630 ERR("Failed to browse to directory: %08x\n", hr
);
632 IShellFolder_Release(psf_parent
);
636 hr
= SHGetDesktopFolder(&psf_desktop
);
639 if(This
->psia_results
)
641 IShellItemArray_Release(This
->psia_results
);
642 This
->psia_results
= NULL
;
645 hr
= SHCreateShellItemArray(NULL
, psf_desktop
, file_count
, (PCUITEMID_CHILD_ARRAY
)pidla
,
646 &This
->psia_results
);
648 IShellFolder_Release(psf_desktop
);
653 if(This
->options
& FOS_PICKFOLDERS
)
656 hr
= IShellItemArray_GetAttributes(This
->psia_results
, SIATTRIBFLAGS_AND
, SFGAO_FOLDER
, &attributes
);
660 LoadStringW(COMDLG32_hInstance
, IDS_INVALID_FOLDERNAME
, buf
, ARRAY_SIZE(buf
));
662 MessageBoxW(This
->dlg_hwnd
, buf
, This
->custom_title
, MB_OK
| MB_ICONEXCLAMATION
);
664 IShellItemArray_Release(This
->psia_results
);
665 This
->psia_results
= NULL
;
670 if((This
->options
& FOS_OVERWRITEPROMPT
) && This
->dlg_type
== ITEMDLG_TYPE_SAVE
)
672 IShellItem
*shellitem
;
674 for (i
=0; SUCCEEDED(hr
) && i
<file_count
; i
++)
676 hr
= IShellItemArray_GetItemAt(This
->psia_results
, i
, &shellitem
);
679 if (shell_item_exists(shellitem
))
680 hr
= events_OnOverwrite(This
, shellitem
);
682 IShellItem_Release(shellitem
);
690 if(events_OnFileOk(This
) == S_OK
)
701 for(i
= 0; i
< file_count
; i
++)
703 HeapFree(GetProcessHeap(), 0, pidla
);
705 /* Success closes the dialog */
709 static void show_opendropdown(FileDialogImpl
*This
)
715 open_hwnd
= GetDlgItem(This
->dlg_hwnd
, IDOK
);
717 GetWindowRect(open_hwnd
, &open_rc
);
719 if (TrackPopupMenu(This
->hmenu_opendropdown
, 0, open_rc
.left
, open_rc
.bottom
, 0, This
->dlg_hwnd
, NULL
) &&
720 PeekMessageW(&msg
, This
->dlg_hwnd
, WM_MENUCOMMAND
, WM_MENUCOMMAND
, PM_REMOVE
))
724 This
->opendropdown_has_selection
= TRUE
;
726 mii
.cbSize
= sizeof(mii
);
728 GetMenuItemInfoW((HMENU
)msg
.lParam
, msg
.wParam
, TRUE
, &mii
);
729 This
->opendropdown_selection
= mii
.wID
;
731 if(SUCCEEDED(on_default_action(This
)))
732 EndDialog(This
->dlg_hwnd
, S_OK
);
734 This
->opendropdown_has_selection
= FALSE
;
738 /**************************************************************************
739 * Control item functions.
742 static void item_free(cctrl_item
*item
)
744 DestroyWindow(item
->hwnd
);
745 HeapFree(GetProcessHeap(), 0, item
->label
);
746 HeapFree(GetProcessHeap(), 0, item
);
749 static cctrl_item
* get_item(customctrl
* parent
, DWORD itemid
, CDCONTROLSTATEF visible_flags
, DWORD
* position
)
754 if (!position
) position
= &dummy
;
758 LIST_FOR_EACH_ENTRY(item
, &parent
->sub_items
, cctrl_item
, entry
)
760 if (item
->id
== itemid
)
763 if ((item
->cdcstate
& visible_flags
) == visible_flags
)
770 static cctrl_item
* get_first_item(customctrl
* parent
)
774 LIST_FOR_EACH_ENTRY(item
, &parent
->sub_items
, cctrl_item
, entry
)
776 if ((item
->cdcstate
& (CDCS_VISIBLE
|CDCS_ENABLED
)) == (CDCS_VISIBLE
|CDCS_ENABLED
))
783 static HRESULT
add_item(customctrl
* parent
, DWORD itemid
, LPCWSTR label
, cctrl_item
** result
)
788 if (get_item(parent
, itemid
, 0, NULL
))
791 item
= HeapAlloc(GetProcessHeap(), 0, sizeof(*item
));
792 label_copy
= HeapAlloc(GetProcessHeap(), 0, (lstrlenW(label
)+1)*sizeof(WCHAR
));
794 if (!item
|| !label_copy
)
796 HeapFree(GetProcessHeap(), 0, item
);
797 HeapFree(GetProcessHeap(), 0, label_copy
);
798 return E_OUTOFMEMORY
;
802 item
->parent_id
= parent
->id
;
803 lstrcpyW(label_copy
, label
);
804 item
->label
= label_copy
;
805 item
->cdcstate
= CDCS_VISIBLE
|CDCS_ENABLED
;
807 list_add_tail(&parent
->sub_items
, &item
->entry
);
814 /**************************************************************************
817 static inline customctrl
*get_cctrl_from_dlgid(FileDialogImpl
*This
, DWORD dlgid
)
819 customctrl
*ctrl
, *sub_ctrl
;
821 LIST_FOR_EACH_ENTRY(ctrl
, &This
->cctrls
, customctrl
, entry
)
823 if(ctrl
->dlgid
== dlgid
)
826 LIST_FOR_EACH_ENTRY(sub_ctrl
, &ctrl
->sub_cctrls
, customctrl
, sub_cctrls_entry
)
827 if(sub_ctrl
->dlgid
== dlgid
)
831 ERR("Failed to find control with dialog id %d\n", dlgid
);
835 static inline customctrl
*get_cctrl(FileDialogImpl
*This
, DWORD ctlid
)
837 customctrl
*ctrl
, *sub_ctrl
;
839 LIST_FOR_EACH_ENTRY(ctrl
, &This
->cctrls
, customctrl
, entry
)
841 if(ctrl
->id
== ctlid
)
844 LIST_FOR_EACH_ENTRY(sub_ctrl
, &ctrl
->sub_cctrls
, customctrl
, sub_cctrls_entry
)
845 if(sub_ctrl
->id
== ctlid
)
849 if (This
->hmenu_opendropdown
&& This
->cctrl_opendropdown
.id
== ctlid
)
850 return &This
->cctrl_opendropdown
;
852 TRACE("No existing control with control id %d\n", ctlid
);
856 static void ctrl_resize(HWND hctrl
, UINT min_width
, UINT max_width
, BOOL multiline
)
859 UINT len
, final_width
;
860 UINT lines
, final_height
;
869 len
= SendMessageW(hctrl
, WM_GETTEXTLENGTH
, 0, 0);
870 text
= HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR
)*(len
+1));
872 SendMessageW(hctrl
, WM_GETTEXT
, len
+1, (LPARAM
)text
);
875 font
= (HFONT
)SendMessageW(hctrl
, WM_GETFONT
, 0, 0);
876 font
= SelectObject(hdc
, font
);
877 GetTextExtentPoint32W(hdc
, text
, lstrlenW(text
), &size
);
878 SelectObject(hdc
, font
);
879 ReleaseDC(hctrl
, hdc
);
883 /* FIXME: line-wrap */
884 for(lines
= 1, c
= text
; *c
!= '\0'; c
++)
885 if(*c
== '\n') lines
++;
887 final_height
= size
.cy
*lines
+ 2*4;
891 GetWindowRect(hctrl
, &rc
);
892 final_height
= rc
.bottom
- rc
.top
;
895 final_width
= min(max(size
.cx
, min_width
) + 4, max_width
);
896 SetWindowPos(hctrl
, NULL
, 0, 0, final_width
, final_height
,
897 SWP_NOZORDER
| SWP_NOMOVE
| SWP_NOACTIVATE
);
899 HeapFree(GetProcessHeap(), 0, text
);
902 static UINT
ctrl_get_height(customctrl
*ctrl
) {
904 GetWindowRect(ctrl
->wrapper_hwnd
, &rc
);
905 return rc
.bottom
- rc
.top
;
908 static void ctrl_free(customctrl
*ctrl
)
910 customctrl
*sub_cur1
, *sub_cur2
;
911 cctrl_item
*item_cur1
, *item_cur2
;
913 TRACE("Freeing control %p\n", ctrl
);
914 if(ctrl
->type
== IDLG_CCTRL_MENU
)
917 SendMessageW(ctrl
->hwnd
, TB_GETBUTTON
, 0, (LPARAM
)&tbb
);
918 DestroyMenu((HMENU
)tbb
.dwData
);
921 LIST_FOR_EACH_ENTRY_SAFE(sub_cur1
, sub_cur2
, &ctrl
->sub_cctrls
, customctrl
, sub_cctrls_entry
)
923 list_remove(&sub_cur1
->sub_cctrls_entry
);
927 LIST_FOR_EACH_ENTRY_SAFE(item_cur1
, item_cur2
, &ctrl
->sub_items
, cctrl_item
, entry
)
929 list_remove(&item_cur1
->entry
);
930 item_free(item_cur1
);
933 DestroyWindow(ctrl
->hwnd
);
934 HeapFree(GetProcessHeap(), 0, ctrl
);
937 static void customctrl_resize(FileDialogImpl
*This
, customctrl
*ctrl
)
941 UINT max_width
, size
;
942 customctrl
*sub_ctrl
;
946 case IDLG_CCTRL_PUSHBUTTON
:
947 case IDLG_CCTRL_COMBOBOX
:
948 case IDLG_CCTRL_CHECKBUTTON
:
949 case IDLG_CCTRL_TEXT
:
950 size
= MulDiv(160, This
->dpi_x
, USER_DEFAULT_SCREEN_DPI
);
951 ctrl_resize(ctrl
->hwnd
, size
, size
, TRUE
);
952 GetWindowRect(ctrl
->hwnd
, &rc
);
953 SetWindowPos(ctrl
->wrapper_hwnd
, NULL
, 0, 0, rc
.right
-rc
.left
, rc
.bottom
-rc
.top
,
954 SWP_NOZORDER
|SWP_NOMOVE
);
956 case IDLG_CCTRL_VISUALGROUP
:
958 ctrl_resize(ctrl
->hwnd
, 0, This
->cctrl_indent
, TRUE
);
960 LIST_FOR_EACH_ENTRY(sub_ctrl
, &ctrl
->sub_cctrls
, customctrl
, sub_cctrls_entry
)
962 customctrl_resize(This
, sub_ctrl
);
963 SetWindowPos(sub_ctrl
->wrapper_hwnd
, NULL
, This
->cctrl_indent
, total_height
, 0, 0,
964 SWP_NOZORDER
|SWP_NOSIZE
);
966 total_height
+= ctrl_get_height(sub_ctrl
);
969 /* The label should be right adjusted */
973 GetWindowRect(ctrl
->hwnd
, &rc
);
974 width
= rc
.right
- rc
.left
;
975 height
= rc
.bottom
- rc
.top
;
977 SetWindowPos(ctrl
->hwnd
, NULL
, This
->cctrl_indent
- width
, 0, width
, height
, SWP_NOZORDER
);
980 /* Resize the wrapper window to fit all the sub controls */
981 SetWindowPos(ctrl
->wrapper_hwnd
, NULL
, 0, 0, This
->cctrl_width
+ This
->cctrl_indent
, total_height
,
982 SWP_NOZORDER
|SWP_NOMOVE
);
984 case IDLG_CCTRL_RADIOBUTTONLIST
:
991 LIST_FOR_EACH_ENTRY(item
, &ctrl
->sub_items
, cctrl_item
, entry
)
993 size
= MulDiv(160, This
->dpi_x
, USER_DEFAULT_SCREEN_DPI
);
994 ctrl_resize(item
->hwnd
, size
, size
, TRUE
);
995 SetWindowPos(item
->hwnd
, NULL
, 0, total_height
, 0, 0,
996 SWP_NOZORDER
|SWP_NOSIZE
);
998 GetWindowRect(item
->hwnd
, &rc
);
1000 total_height
+= rc
.bottom
- rc
.top
;
1001 max_width
= max(rc
.right
- rc
.left
, max_width
);
1004 SetWindowPos(ctrl
->hwnd
, NULL
, 0, 0, max_width
, total_height
,
1005 SWP_NOZORDER
|SWP_NOMOVE
);
1007 SetWindowPos(ctrl
->wrapper_hwnd
, NULL
, 0, 0, max_width
, total_height
,
1008 SWP_NOZORDER
|SWP_NOMOVE
);
1012 case IDLG_CCTRL_EDITBOX
:
1013 case IDLG_CCTRL_SEPARATOR
:
1014 case IDLG_CCTRL_MENU
:
1015 case IDLG_CCTRL_OPENDROPDOWN
:
1021 static LRESULT
notifysink_on_create(HWND hwnd
, CREATESTRUCTW
*crs
)
1023 FileDialogImpl
*This
= crs
->lpCreateParams
;
1024 TRACE("%p\n", This
);
1026 SetWindowLongPtrW(hwnd
, GWLP_USERDATA
, (LPARAM
)This
);
1030 static LRESULT
notifysink_on_bn_clicked(FileDialogImpl
*This
, HWND hwnd
, WPARAM wparam
)
1032 customctrl
*ctrl
= get_cctrl_from_dlgid(This
, LOWORD(wparam
));
1034 TRACE("%p, %lx\n", This
, wparam
);
1038 if(ctrl
->type
== IDLG_CCTRL_CHECKBUTTON
)
1040 BOOL checked
= (SendMessageW(ctrl
->hwnd
, BM_GETCHECK
, 0, 0) == BST_CHECKED
);
1041 cctrl_event_OnCheckButtonToggled(This
, ctrl
->id
, checked
);
1044 cctrl_event_OnButtonClicked(This
, ctrl
->id
);
1050 static LRESULT
notifysink_on_cbn_selchange(FileDialogImpl
*This
, HWND hwnd
, WPARAM wparam
)
1052 customctrl
*ctrl
= get_cctrl_from_dlgid(This
, LOWORD(wparam
));
1053 TRACE("%p, %p (%lx)\n", This
, ctrl
, wparam
);
1057 UINT index
= SendMessageW(ctrl
->hwnd
, CB_GETCURSEL
, 0, 0);
1058 UINT selid
= SendMessageW(ctrl
->hwnd
, CB_GETITEMDATA
, index
, 0);
1060 cctrl_event_OnItemSelected(This
, ctrl
->id
, selid
);
1065 static LRESULT
notifysink_on_tvn_dropdown(FileDialogImpl
*This
, LPARAM lparam
)
1067 NMTOOLBARW
*nmtb
= (NMTOOLBARW
*)lparam
;
1068 customctrl
*ctrl
= get_cctrl_from_dlgid(This
, GetDlgCtrlID(nmtb
->hdr
.hwndFrom
));
1069 POINT pt
= { 0, nmtb
->rcButton
.bottom
};
1073 TRACE("%p, %p (%lx)\n", This
, ctrl
, lparam
);
1077 cctrl_event_OnControlActivating(This
,ctrl
->id
);
1079 SendMessageW(ctrl
->hwnd
, TB_GETBUTTON
, 0, (LPARAM
)&tbb
);
1080 ClientToScreen(ctrl
->hwnd
, &pt
);
1081 idcmd
= TrackPopupMenu((HMENU
)tbb
.dwData
, TPM_RETURNCMD
, pt
.x
, pt
.y
, 0, This
->dlg_hwnd
, NULL
);
1083 cctrl_event_OnItemSelected(This
, ctrl
->id
, idcmd
);
1086 return TBDDRET_DEFAULT
;
1089 static LRESULT
notifysink_on_wm_command(FileDialogImpl
*This
, HWND hwnd
, WPARAM wparam
, LPARAM lparam
)
1091 switch(HIWORD(wparam
))
1093 case BN_CLICKED
: return notifysink_on_bn_clicked(This
, hwnd
, wparam
);
1094 case CBN_SELCHANGE
: return notifysink_on_cbn_selchange(This
, hwnd
, wparam
);
1100 static LRESULT
notifysink_on_wm_notify(FileDialogImpl
*This
, HWND hwnd
, WPARAM wparam
, LPARAM lparam
)
1102 NMHDR
*nmhdr
= (NMHDR
*)lparam
;
1106 case TBN_DROPDOWN
: return notifysink_on_tvn_dropdown(This
, lparam
);
1112 static LRESULT CALLBACK
notifysink_proc(HWND hwnd
, UINT message
, WPARAM wparam
, LPARAM lparam
)
1114 FileDialogImpl
*This
= (FileDialogImpl
*)GetWindowLongPtrW(hwnd
, GWLP_USERDATA
);
1121 case WM_NCCREATE
: return notifysink_on_create(hwnd
, (CREATESTRUCTW
*)lparam
);
1122 case WM_COMMAND
: return notifysink_on_wm_command(This
, hwnd
, wparam
, lparam
);
1123 case WM_NOTIFY
: return notifysink_on_wm_notify(This
, hwnd
, wparam
, lparam
);
1125 hwnd_child
= GetPropW(hwnd
, notifysink_childW
);
1126 ctrl
= (customctrl
*)GetWindowLongPtrW(hwnd_child
, GWLP_USERDATA
);
1127 if(ctrl
&& ctrl
->type
!= IDLG_CCTRL_VISUALGROUP
)
1129 GetClientRect(hwnd
, &rc
);
1130 SetWindowPos(hwnd_child
, NULL
, 0, 0, rc
.right
, rc
.bottom
, SWP_NOMOVE
|SWP_NOACTIVATE
|SWP_NOZORDER
);
1135 return DefWindowProcW(hwnd
, message
, wparam
, lparam
);
1138 static HRESULT
cctrl_create_new(FileDialogImpl
*This
, DWORD id
,
1139 LPCWSTR text
, LPCWSTR wndclass
, DWORD ctrl_wsflags
,
1140 DWORD ctrl_exflags
, UINT height
, customctrl
**ppctrl
)
1142 HWND ns_hwnd
, control_hwnd
, parent_hwnd
;
1143 DWORD wsflags
= WS_CHILD
| WS_VISIBLE
| WS_CLIPSIBLINGS
;
1146 if(get_cctrl(This
, id
))
1147 return E_UNEXPECTED
; /* Duplicate id */
1149 if(This
->cctrl_active_vg
)
1150 parent_hwnd
= This
->cctrl_active_vg
->wrapper_hwnd
;
1152 parent_hwnd
= This
->cctrls_hwnd
;
1154 ns_hwnd
= CreateWindowExW(0, floatnotifysinkW
, NULL
, wsflags
,
1155 0, 0, This
->cctrl_width
, height
, parent_hwnd
,
1156 (HMENU
)This
->cctrl_next_dlgid
, COMDLG32_hInstance
, This
);
1157 control_hwnd
= CreateWindowExW(ctrl_exflags
, wndclass
, text
, wsflags
| ctrl_wsflags
,
1158 0, 0, This
->cctrl_width
, height
, ns_hwnd
,
1159 (HMENU
)This
->cctrl_next_dlgid
, COMDLG32_hInstance
, 0);
1161 if(!ns_hwnd
|| !control_hwnd
)
1163 ERR("Failed to create wrapper (%p) or control (%p)\n", ns_hwnd
, control_hwnd
);
1164 DestroyWindow(ns_hwnd
);
1165 DestroyWindow(control_hwnd
);
1170 SetPropW(ns_hwnd
, notifysink_childW
, control_hwnd
);
1172 ctrl
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(customctrl
));
1174 return E_OUTOFMEMORY
;
1176 ctrl
->hwnd
= control_hwnd
;
1177 ctrl
->wrapper_hwnd
= ns_hwnd
;
1179 ctrl
->dlgid
= This
->cctrl_next_dlgid
;
1180 ctrl
->cdcstate
= CDCS_ENABLED
| CDCS_VISIBLE
;
1181 list_init(&ctrl
->sub_cctrls
);
1182 list_init(&ctrl
->sub_items
);
1184 if(This
->cctrl_active_vg
)
1185 list_add_tail(&This
->cctrl_active_vg
->sub_cctrls
, &ctrl
->sub_cctrls_entry
);
1187 list_add_tail(&This
->cctrls
, &ctrl
->entry
);
1189 SetWindowLongPtrW(ctrl
->hwnd
, GWLP_USERDATA
, (LPARAM
)ctrl
);
1191 if(ppctrl
) *ppctrl
= ctrl
;
1193 This
->cctrl_next_dlgid
++;
1197 /**************************************************************************
1198 * Container functions.
1200 static UINT
ctrl_container_resize(FileDialogImpl
*This
, UINT container_width
)
1202 UINT container_height
;
1205 UINT max_control_height
, total_height
= 0;
1206 UINT cur_col_pos
, cur_row_pos
;
1209 UINT cspacing
= MulDiv(90, This
->dpi_x
, USER_DEFAULT_SCREEN_DPI
); /* Columns are spaced with 90px */
1210 UINT rspacing
= MulDiv(4, This
->dpi_y
, USER_DEFAULT_SCREEN_DPI
); /* Rows are spaced with 4 px. */
1212 /* Given the new width of the container, this function determines the
1213 * needed height of the container and places the controls according to
1214 * the new layout. Returns the new height.
1217 TRACE("%p\n", This
);
1219 column_width
= This
->cctrl_width
+ cspacing
;
1220 nr_of_cols
= (container_width
- This
->cctrl_indent
+ cspacing
) / column_width
;
1222 /* We don't need to do anything unless the number of visible columns has changed. */
1223 if(nr_of_cols
== This
->cctrls_cols
)
1226 GetWindowRect(This
->cctrls_hwnd
, &rc
);
1227 return rc
.bottom
- rc
.top
;
1230 This
->cctrls_cols
= nr_of_cols
;
1232 /* Get the size of the tallest control, and the total size of
1233 * all the controls to figure out the number of slots we need.
1235 max_control_height
= 0;
1236 LIST_FOR_EACH_ENTRY(ctrl
, &This
->cctrls
, customctrl
, entry
)
1238 if(ctrl
->cdcstate
& CDCS_VISIBLE
)
1240 UINT control_height
= ctrl_get_height(ctrl
);
1241 max_control_height
= max(max_control_height
, control_height
);
1243 total_height
+= control_height
+ rspacing
;
1250 container_height
= max(total_height
/ nr_of_cols
, max_control_height
+ rspacing
);
1251 TRACE("Guess: container_height: %d\n",container_height
);
1253 /* Incrementally increase container_height until all the controls
1257 UINT columns_needed
= 1;
1261 LIST_FOR_EACH_ENTRY(ctrl
, &This
->cctrls
, customctrl
, entry
)
1263 if(ctrl
->cdcstate
& CDCS_VISIBLE
)
1265 UINT control_height
= ctrl_get_height(ctrl
);
1267 if(cur_row_pos
+ control_height
> container_height
)
1269 if(++columns_needed
> nr_of_cols
)
1271 container_height
+= 1;
1272 fits_height
= FALSE
;
1278 cur_row_pos
+= control_height
+ rspacing
;
1281 } while(!fits_height
);
1283 TRACE("Final container height: %d\n", container_height
);
1285 /* Move the controls to their final destination
1287 cur_col_pos
= 0; cur_row_pos
= 0;
1288 LIST_FOR_EACH_ENTRY(ctrl
, &This
->cctrls
, customctrl
, entry
)
1290 if(ctrl
->cdcstate
& CDCS_VISIBLE
)
1293 UINT control_height
, control_indent
;
1294 GetWindowRect(ctrl
->wrapper_hwnd
, &rc
);
1295 control_height
= rc
.bottom
- rc
.top
;
1297 if(cur_row_pos
+ control_height
> container_height
)
1300 cur_col_pos
+= This
->cctrl_width
+ cspacing
;
1304 if(ctrl
->type
== IDLG_CCTRL_VISUALGROUP
)
1307 control_indent
= This
->cctrl_indent
;
1309 SetWindowPos(ctrl
->wrapper_hwnd
, NULL
, cur_col_pos
+ control_indent
, cur_row_pos
, 0, 0,
1310 SWP_NOACTIVATE
| SWP_NOSIZE
| SWP_NOZORDER
);
1312 cur_row_pos
+= control_height
+ rspacing
;
1317 if(cur_row_pos
+ This
->cctrl_width
> container_width
)
1318 ERR("-- Failed to place controls properly.\n");
1320 return container_height
;
1323 static void ctrl_set_font(customctrl
*ctrl
, HFONT font
)
1325 customctrl
*sub_ctrl
;
1328 SendMessageW(ctrl
->hwnd
, WM_SETFONT
, (WPARAM
)font
, TRUE
);
1330 LIST_FOR_EACH_ENTRY(sub_ctrl
, &ctrl
->sub_cctrls
, customctrl
, sub_cctrls_entry
)
1332 ctrl_set_font(sub_ctrl
, font
);
1335 if (ctrl
->type
== IDLG_CCTRL_RADIOBUTTONLIST
)
1337 LIST_FOR_EACH_ENTRY(item
, &ctrl
->sub_items
, cctrl_item
, entry
)
1339 SendMessageW(item
->hwnd
, WM_SETFONT
, (WPARAM
)font
, TRUE
);
1344 static void ctrl_container_reparent(FileDialogImpl
*This
, HWND parent
)
1353 wndstyle
= GetWindowLongW(This
->cctrls_hwnd
, GWL_STYLE
);
1354 wndstyle
&= ~(WS_POPUP
);
1355 wndstyle
|= WS_CHILD
;
1356 SetWindowLongW(This
->cctrls_hwnd
, GWL_STYLE
, wndstyle
);
1358 SetParent(This
->cctrls_hwnd
, parent
);
1359 ShowWindow(This
->cctrls_hwnd
, TRUE
);
1361 /* Set the fonts to match the dialog font. */
1362 font
= (HFONT
)SendMessageW(parent
, WM_GETFONT
, 0, 0);
1364 ERR("Failed to get font handle from dialog.\n");
1366 LIST_FOR_EACH_ENTRY(ctrl
, &This
->cctrls
, customctrl
, entry
)
1368 if(font
) ctrl_set_font(ctrl
, font
);
1369 customctrl_resize(This
, ctrl
);
1374 ShowWindow(This
->cctrls_hwnd
, FALSE
);
1376 wndstyle
= GetWindowLongW(This
->cctrls_hwnd
, GWL_STYLE
);
1377 wndstyle
&= ~(WS_CHILD
);
1378 wndstyle
|= WS_POPUP
;
1379 SetWindowLongW(This
->cctrls_hwnd
, GWL_STYLE
, wndstyle
);
1381 SetParent(This
->cctrls_hwnd
, NULL
);
1385 static LRESULT
ctrl_container_on_create(HWND hwnd
, CREATESTRUCTW
*crs
)
1387 FileDialogImpl
*This
= crs
->lpCreateParams
;
1388 TRACE("%p\n", This
);
1390 SetWindowLongPtrW(hwnd
, GWLP_USERDATA
, (LPARAM
)This
);
1394 static LRESULT
ctrl_container_on_wm_destroy(FileDialogImpl
*This
)
1396 customctrl
*cur1
, *cur2
;
1397 TRACE("%p\n", This
);
1399 LIST_FOR_EACH_ENTRY_SAFE(cur1
, cur2
, &This
->cctrls
, customctrl
, entry
)
1401 list_remove(&cur1
->entry
);
1408 static LRESULT CALLBACK
ctrl_container_wndproc(HWND hwnd
, UINT umessage
, WPARAM wparam
, LPARAM lparam
)
1410 FileDialogImpl
*This
= (FileDialogImpl
*)GetWindowLongPtrW(hwnd
, GWLP_USERDATA
);
1414 case WM_NCCREATE
: return ctrl_container_on_create(hwnd
, (CREATESTRUCTW
*)lparam
);
1415 case WM_DESTROY
: return ctrl_container_on_wm_destroy(This
);
1416 default: return DefWindowProcW(hwnd
, umessage
, wparam
, lparam
);
1422 static void radiobuttonlist_set_selected_item(FileDialogImpl
*This
, customctrl
*ctrl
, cctrl_item
*item
)
1426 LIST_FOR_EACH_ENTRY(cursor
, &ctrl
->sub_items
, cctrl_item
, entry
)
1428 SendMessageW(cursor
->hwnd
, BM_SETCHECK
, (cursor
== item
) ? BST_CHECKED
: BST_UNCHECKED
, 0);
1432 static LRESULT
radiobuttonlist_on_bn_clicked(FileDialogImpl
*This
, HWND hwnd
, HWND child
)
1434 DWORD ctrl_id
= (DWORD
)GetWindowLongPtrW(hwnd
, GWLP_ID
);
1437 BOOL found_item
=FALSE
;
1439 ctrl
= get_cctrl_from_dlgid(This
, ctrl_id
);
1443 ERR("Can't find this control\n");
1447 LIST_FOR_EACH_ENTRY(item
, &ctrl
->sub_items
, cctrl_item
, entry
)
1449 if (item
->hwnd
== child
)
1458 ERR("Can't find control item\n");
1462 radiobuttonlist_set_selected_item(This
, ctrl
, item
);
1464 cctrl_event_OnItemSelected(This
, ctrl
->id
, item
->id
);
1469 static LRESULT
radiobuttonlist_on_wm_command(FileDialogImpl
*This
, HWND hwnd
, WPARAM wparam
, LPARAM lparam
)
1471 switch(HIWORD(wparam
))
1473 case BN_CLICKED
: return radiobuttonlist_on_bn_clicked(This
, hwnd
, (HWND
)lparam
);
1479 static LRESULT CALLBACK
radiobuttonlist_proc(HWND hwnd
, UINT message
, WPARAM wparam
, LPARAM lparam
)
1481 FileDialogImpl
*This
= (FileDialogImpl
*)GetWindowLongPtrW(hwnd
, GWLP_USERDATA
);
1485 case WM_COMMAND
: return radiobuttonlist_on_wm_command(This
, hwnd
, wparam
, lparam
);
1488 return DefWindowProcW(hwnd
, message
, wparam
, lparam
);
1491 static HRESULT
init_custom_controls(FileDialogImpl
*This
)
1495 static const WCHAR ctrl_container_classname
[] =
1496 {'i','d','l','g','_','c','o','n','t','a','i','n','e','r','_','p','a','n','e',0};
1498 InitCommonControlsEx(NULL
);
1500 if( !GetClassInfoW(COMDLG32_hInstance
, ctrl_container_classname
, &wc
) )
1502 wc
.style
= CS_HREDRAW
| CS_VREDRAW
;
1503 wc
.lpfnWndProc
= ctrl_container_wndproc
;
1506 wc
.hInstance
= COMDLG32_hInstance
;
1508 wc
.hCursor
= LoadCursorW(0, (LPWSTR
)IDC_ARROW
);
1509 wc
.hbrBackground
= (HBRUSH
)(COLOR_BTNFACE
+ 1);
1510 wc
.lpszMenuName
= NULL
;
1511 wc
.lpszClassName
= ctrl_container_classname
;
1513 if(!RegisterClassW(&wc
)) return E_FAIL
;
1516 This
->cctrls_hwnd
= CreateWindowExW(0, ctrl_container_classname
, NULL
,
1517 WS_CLIPSIBLINGS
| WS_CLIPCHILDREN
,
1518 0, 0, 0, 0, NULL
, 0,
1519 COMDLG32_hInstance
, This
);
1520 if(!This
->cctrls_hwnd
)
1523 hdc
= GetDC(This
->cctrls_hwnd
);
1524 This
->dpi_x
= GetDeviceCaps(hdc
, LOGPIXELSX
);
1525 This
->dpi_y
= GetDeviceCaps(hdc
, LOGPIXELSY
);
1526 ReleaseDC(This
->cctrls_hwnd
, hdc
);
1528 This
->cctrl_width
= MulDiv(160, This
->dpi_x
, USER_DEFAULT_SCREEN_DPI
); /* Controls have a fixed width */
1529 This
->cctrl_indent
= MulDiv(100, This
->dpi_x
, USER_DEFAULT_SCREEN_DPI
);
1530 This
->cctrl_def_height
= MulDiv(23, This
->dpi_y
, USER_DEFAULT_SCREEN_DPI
);
1531 This
->cctrls_cols
= 0;
1533 This
->cctrl_next_dlgid
= 0x2000;
1534 list_init(&This
->cctrls
);
1535 This
->cctrl_active_vg
= NULL
;
1537 SetWindowLongW(This
->cctrls_hwnd
, GWL_STYLE
, WS_TABSTOP
);
1539 /* Register class for */
1540 if( !GetClassInfoW(COMDLG32_hInstance
, floatnotifysinkW
, &wc
) ||
1541 wc
.hInstance
!= COMDLG32_hInstance
)
1543 wc
.style
= CS_HREDRAW
| CS_VREDRAW
;
1544 wc
.lpfnWndProc
= notifysink_proc
;
1547 wc
.hInstance
= COMDLG32_hInstance
;
1549 wc
.hCursor
= LoadCursorW(0, (LPWSTR
)IDC_ARROW
);
1550 wc
.hbrBackground
= (HBRUSH
)(COLOR_BTNFACE
+ 1);
1551 wc
.lpszMenuName
= NULL
;
1552 wc
.lpszClassName
= floatnotifysinkW
;
1554 if (!RegisterClassW(&wc
))
1555 ERR("Failed to register FloatNotifySink window class.\n");
1558 if( !GetClassInfoW(COMDLG32_hInstance
, radiobuttonlistW
, &wc
) ||
1559 wc
.hInstance
!= COMDLG32_hInstance
)
1561 wc
.style
= CS_HREDRAW
| CS_VREDRAW
;
1562 wc
.lpfnWndProc
= radiobuttonlist_proc
;
1565 wc
.hInstance
= COMDLG32_hInstance
;
1567 wc
.hCursor
= LoadCursorW(0, (LPWSTR
)IDC_ARROW
);
1568 wc
.hbrBackground
= (HBRUSH
)(COLOR_BTNFACE
+ 1);
1569 wc
.lpszMenuName
= NULL
;
1570 wc
.lpszClassName
= radiobuttonlistW
;
1572 if (!RegisterClassW(&wc
))
1573 ERR("Failed to register RadioButtonList window class.\n");
1579 /**************************************************************************
1580 * Window related functions.
1582 static BOOL
update_open_dropdown(FileDialogImpl
*This
)
1584 /* Show or hide the open dropdown button as appropriate */
1585 BOOL show
=FALSE
, showing
;
1586 HWND open_hwnd
, dropdown_hwnd
;
1588 if (This
->hmenu_opendropdown
)
1590 INT num_visible_items
=0;
1593 LIST_FOR_EACH_ENTRY(item
, &This
->cctrl_opendropdown
.sub_items
, cctrl_item
, entry
)
1595 if (item
->cdcstate
& CDCS_VISIBLE
)
1597 num_visible_items
++;
1598 if (num_visible_items
>= 2)
1607 open_hwnd
= GetDlgItem(This
->dlg_hwnd
, IDOK
);
1608 dropdown_hwnd
= GetDlgItem(This
->dlg_hwnd
, psh1
);
1610 showing
= (GetWindowLongPtrW(dropdown_hwnd
, GWL_STYLE
) & WS_VISIBLE
) != 0;
1612 if (showing
!= show
)
1614 RECT open_rc
, dropdown_rc
;
1616 GetWindowRect(open_hwnd
, &open_rc
);
1617 GetWindowRect(dropdown_hwnd
, &dropdown_rc
);
1621 ShowWindow(dropdown_hwnd
, SW_SHOW
);
1623 SetWindowPos(open_hwnd
, NULL
, 0, 0,
1624 (open_rc
.right
- open_rc
.left
) - (dropdown_rc
.right
- dropdown_rc
.left
),
1625 open_rc
.bottom
- open_rc
.top
, SWP_NOZORDER
| SWP_NOMOVE
| SWP_NOACTIVATE
);
1629 ShowWindow(dropdown_hwnd
, SW_HIDE
);
1631 SetWindowPos(open_hwnd
, NULL
, 0, 0,
1632 (open_rc
.right
- open_rc
.left
) + (dropdown_rc
.right
- dropdown_rc
.left
),
1633 open_rc
.bottom
- open_rc
.top
, SWP_NOZORDER
| SWP_NOMOVE
| SWP_NOACTIVATE
);
1640 static void update_layout(FileDialogImpl
*This
)
1645 RECT cancel_rc
, dropdown_rc
, open_rc
;
1646 RECT filetype_rc
, filename_rc
, filenamelabel_rc
;
1647 RECT toolbar_rc
, ebrowser_rc
, customctrls_rc
;
1648 static const UINT vspacing
= 4, hspacing
= 4;
1649 static const UINT min_width
= 320, min_height
= 200;
1652 if (!GetClientRect(This
->dlg_hwnd
, &dialog_rc
))
1654 TRACE("Invalid dialog window, not updating layout\n");
1658 if(dialog_rc
.right
< min_width
|| dialog_rc
.bottom
< min_height
)
1660 TRACE("Dialog size (%d, %d) too small, not updating layout\n", dialog_rc
.right
, dialog_rc
.bottom
);
1665 * Calculate the size of the dialog and all the parts.
1669 hwnd
= GetDlgItem(This
->dlg_hwnd
, IDCANCEL
);
1672 int cancel_width
, cancel_height
;
1673 GetWindowRect(hwnd
, &cancel_rc
);
1674 cancel_width
= cancel_rc
.right
- cancel_rc
.left
;
1675 cancel_height
= cancel_rc
.bottom
- cancel_rc
.top
;
1677 cancel_rc
.left
= dialog_rc
.right
- cancel_width
- hspacing
;
1678 cancel_rc
.top
= dialog_rc
.bottom
- cancel_height
- vspacing
;
1679 cancel_rc
.right
= cancel_rc
.left
+ cancel_width
;
1680 cancel_rc
.bottom
= cancel_rc
.top
+ cancel_height
;
1683 /* Open/Save dropdown */
1684 show_dropdown
= update_open_dropdown(This
);
1688 int dropdown_width
, dropdown_height
;
1689 hwnd
= GetDlgItem(This
->dlg_hwnd
, psh1
);
1691 GetWindowRect(hwnd
, &dropdown_rc
);
1692 dropdown_width
= dropdown_rc
.right
- dropdown_rc
.left
;
1693 dropdown_height
= dropdown_rc
.bottom
- dropdown_rc
.top
;
1695 dropdown_rc
.left
= cancel_rc
.left
- dropdown_width
- hspacing
;
1696 dropdown_rc
.top
= cancel_rc
.top
;
1697 dropdown_rc
.right
= dropdown_rc
.left
+ dropdown_width
;
1698 dropdown_rc
.bottom
= dropdown_rc
.top
+ dropdown_height
;
1702 dropdown_rc
.left
= dropdown_rc
.right
= cancel_rc
.left
- hspacing
;
1703 dropdown_rc
.top
= cancel_rc
.top
;
1704 dropdown_rc
.bottom
= cancel_rc
.bottom
;
1707 /* Open/Save button */
1708 hwnd
= GetDlgItem(This
->dlg_hwnd
, IDOK
);
1711 int open_width
, open_height
;
1712 GetWindowRect(hwnd
, &open_rc
);
1713 open_width
= open_rc
.right
- open_rc
.left
;
1714 open_height
= open_rc
.bottom
- open_rc
.top
;
1716 open_rc
.left
= dropdown_rc
.left
- open_width
;
1717 open_rc
.top
= dropdown_rc
.top
;
1718 open_rc
.right
= open_rc
.left
+ open_width
;
1719 open_rc
.bottom
= open_rc
.top
+ open_height
;
1722 /* The filetype combobox. */
1723 hwnd
= GetDlgItem(This
->dlg_hwnd
, IDC_FILETYPE
);
1726 int filetype_width
, filetype_height
;
1727 GetWindowRect(hwnd
, &filetype_rc
);
1729 filetype_width
= filetype_rc
.right
- filetype_rc
.left
;
1730 filetype_height
= filetype_rc
.bottom
- filetype_rc
.top
;
1732 filetype_rc
.right
= cancel_rc
.right
;
1734 filetype_rc
.left
= filetype_rc
.right
- filetype_width
;
1735 filetype_rc
.top
= cancel_rc
.top
- filetype_height
- vspacing
;
1736 filetype_rc
.bottom
= filetype_rc
.top
+ filetype_height
;
1738 if(!This
->filterspec_count
)
1739 filetype_rc
.left
= filetype_rc
.right
;
1742 /* Filename label. */
1743 hwnd
= GetDlgItem(This
->dlg_hwnd
, IDC_FILENAMESTATIC
);
1746 int filetypelabel_width
, filetypelabel_height
;
1747 GetWindowRect(hwnd
, &filenamelabel_rc
);
1749 filetypelabel_width
= filenamelabel_rc
.right
- filenamelabel_rc
.left
;
1750 filetypelabel_height
= filenamelabel_rc
.bottom
- filenamelabel_rc
.top
;
1752 filenamelabel_rc
.left
= 160; /* FIXME */
1753 filenamelabel_rc
.top
= filetype_rc
.top
;
1754 filenamelabel_rc
.right
= filenamelabel_rc
.left
+ filetypelabel_width
;
1755 filenamelabel_rc
.bottom
= filenamelabel_rc
.top
+ filetypelabel_height
;
1758 /* Filename edit box. */
1759 hwnd
= GetDlgItem(This
->dlg_hwnd
, IDC_FILENAME
);
1762 int filename_width
, filename_height
;
1763 GetWindowRect(hwnd
, &filename_rc
);
1765 filename_width
= filetype_rc
.left
- filenamelabel_rc
.right
- hspacing
*2;
1766 filename_height
= filename_rc
.bottom
- filename_rc
.top
;
1768 filename_rc
.left
= filenamelabel_rc
.right
+ hspacing
;
1769 filename_rc
.top
= filetype_rc
.top
;
1770 filename_rc
.right
= filename_rc
.left
+ filename_width
;
1771 filename_rc
.bottom
= filename_rc
.top
+ filename_height
;
1774 hwnd
= GetDlgItem(This
->dlg_hwnd
, IDC_NAV_TOOLBAR
);
1777 GetWindowRect(hwnd
, &toolbar_rc
);
1778 MapWindowPoints(NULL
, This
->dlg_hwnd
, (POINT
*)&toolbar_rc
, 2);
1781 /* The custom controls */
1782 customctrls_rc
.left
= dialog_rc
.left
+ hspacing
;
1783 customctrls_rc
.right
= dialog_rc
.right
- hspacing
;
1784 customctrls_rc
.bottom
= filename_rc
.top
- vspacing
;
1785 customctrls_rc
.top
= customctrls_rc
.bottom
-
1786 ctrl_container_resize(This
, customctrls_rc
.right
- customctrls_rc
.left
);
1788 /* The ExplorerBrowser control. */
1789 ebrowser_rc
.left
= dialog_rc
.left
+ hspacing
;
1790 ebrowser_rc
.top
= toolbar_rc
.bottom
+ vspacing
;
1791 ebrowser_rc
.right
= dialog_rc
.right
- hspacing
;
1792 ebrowser_rc
.bottom
= customctrls_rc
.top
- vspacing
;
1795 * Move everything to the right place.
1798 /* FIXME: The Save Dialog uses a slightly different layout. */
1799 hdwp
= BeginDeferWindowPos(7);
1801 if(hdwp
&& This
->peb
)
1802 IExplorerBrowser_SetRect(This
->peb
, &hdwp
, ebrowser_rc
);
1804 if(hdwp
&& This
->cctrls_hwnd
)
1805 DeferWindowPos(hdwp
, This
->cctrls_hwnd
, NULL
,
1806 customctrls_rc
.left
, customctrls_rc
.top
,
1807 customctrls_rc
.right
- customctrls_rc
.left
, customctrls_rc
.bottom
- customctrls_rc
.top
,
1808 SWP_NOZORDER
| SWP_NOACTIVATE
);
1810 /* The default controls */
1811 if(hdwp
&& (hwnd
= GetDlgItem(This
->dlg_hwnd
, IDC_FILETYPE
)) )
1812 DeferWindowPos(hdwp
, hwnd
, NULL
, filetype_rc
.left
, filetype_rc
.top
, 0, 0,
1813 SWP_NOZORDER
| SWP_NOSIZE
| SWP_NOACTIVATE
);
1815 if(hdwp
&& (hwnd
= GetDlgItem(This
->dlg_hwnd
, IDC_FILENAME
)) )
1816 DeferWindowPos(hdwp
, hwnd
, NULL
, filename_rc
.left
, filename_rc
.top
,
1817 filename_rc
.right
- filename_rc
.left
, filename_rc
.bottom
- filename_rc
.top
,
1818 SWP_NOZORDER
| SWP_NOACTIVATE
);
1820 if(hdwp
&& (hwnd
= GetDlgItem(This
->dlg_hwnd
, IDC_FILENAMESTATIC
)) )
1821 DeferWindowPos(hdwp
, hwnd
, NULL
, filenamelabel_rc
.left
, filenamelabel_rc
.top
, 0, 0,
1822 SWP_NOZORDER
| SWP_NOSIZE
| SWP_NOACTIVATE
);
1824 if(hdwp
&& (hwnd
= GetDlgItem(This
->dlg_hwnd
, IDOK
)) )
1825 DeferWindowPos(hdwp
, hwnd
, NULL
, open_rc
.left
, open_rc
.top
, 0, 0,
1826 SWP_NOZORDER
| SWP_NOSIZE
| SWP_NOACTIVATE
);
1828 if(hdwp
&& This
->hmenu_opendropdown
&& (hwnd
= GetDlgItem(This
->dlg_hwnd
, psh1
)))
1829 DeferWindowPos(hdwp
, hwnd
, NULL
, dropdown_rc
.left
, dropdown_rc
.top
, 0, 0,
1830 SWP_NOZORDER
| SWP_NOSIZE
| SWP_NOACTIVATE
);
1832 if(hdwp
&& (hwnd
= GetDlgItem(This
->dlg_hwnd
, IDCANCEL
)) )
1833 DeferWindowPos(hdwp
, hwnd
, NULL
, cancel_rc
.left
, cancel_rc
.top
, 0, 0,
1834 SWP_NOZORDER
| SWP_NOSIZE
| SWP_NOACTIVATE
);
1837 EndDeferWindowPos(hdwp
);
1839 ERR("Failed to position dialog controls.\n");
1844 static HRESULT
init_explorerbrowser(FileDialogImpl
*This
)
1846 IShellItem
*psi_folder
;
1847 IObjectWithSite
*client
;
1852 /* Create ExplorerBrowser instance */
1853 OleInitialize(NULL
);
1855 hr
= CoCreateInstance(&CLSID_ExplorerBrowser
, NULL
, CLSCTX_INPROC_SERVER
,
1856 &IID_IExplorerBrowser
, (void**)&This
->peb
);
1859 ERR("Failed to instantiate ExplorerBrowser control.\n");
1863 IExplorerBrowser_SetOptions(This
->peb
, EBO_SHOWFRAMES
| EBO_NOBORDER
);
1865 hr
= IExplorerBrowser_Initialize(This
->peb
, This
->dlg_hwnd
, &rc
, NULL
);
1868 ERR("Failed to initialize the ExplorerBrowser control.\n");
1869 IExplorerBrowser_Release(This
->peb
);
1873 hr
= IExplorerBrowser_Advise(This
->peb
, &This
->IExplorerBrowserEvents_iface
, &This
->ebevents_cookie
);
1875 ERR("Advise (ExplorerBrowser) failed.\n");
1877 /* Get previous options? */
1878 fos
.ViewMode
= fos
.fFlags
= 0;
1879 if(!(This
->options
& FOS_ALLOWMULTISELECT
))
1880 fos
.fFlags
|= FWF_SINGLESEL
;
1882 IExplorerBrowser_SetFolderSettings(This
->peb
, &fos
);
1884 hr
= IExplorerBrowser_QueryInterface(This
->peb
, &IID_IObjectWithSite
, (void**)&client
);
1887 hr
= IObjectWithSite_SetSite(client
, (IUnknown
*)&This
->IFileDialog2_iface
);
1888 IObjectWithSite_Release(client
);
1890 ERR("SetSite failed, 0x%08x\n", hr
);
1893 /* Browse somewhere */
1894 psi_folder
= This
->psi_setfolder
? This
->psi_setfolder
: This
->psi_defaultfolder
;
1895 IExplorerBrowser_BrowseToObject(This
->peb
, (IUnknown
*)psi_folder
, SBSP_DEFBROWSER
);
1900 static void init_toolbar(FileDialogImpl
*This
, HWND hwnd
)
1906 htoolbar
= CreateWindowExW(0, TOOLBARCLASSNAMEW
, NULL
, TBSTYLE_FLAT
| WS_CHILD
| WS_VISIBLE
,
1908 hwnd
, (HMENU
)IDC_NAV_TOOLBAR
, NULL
, NULL
);
1910 tbab
.hInst
= HINST_COMMCTRL
;
1911 tbab
.nID
= IDB_HIST_LARGE_COLOR
;
1912 SendMessageW(htoolbar
, TB_ADDBITMAP
, 0, (LPARAM
)&tbab
);
1914 button
[0].iBitmap
= HIST_BACK
;
1915 button
[0].idCommand
= IDC_NAVBACK
;
1916 button
[0].fsState
= TBSTATE_ENABLED
;
1917 button
[0].fsStyle
= BTNS_BUTTON
;
1918 button
[0].dwData
= 0;
1919 button
[0].iString
= 0;
1921 button
[1].iBitmap
= HIST_FORWARD
;
1922 button
[1].idCommand
= IDC_NAVFORWARD
;
1923 button
[1].fsState
= TBSTATE_ENABLED
;
1924 button
[1].fsStyle
= BTNS_BUTTON
;
1925 button
[1].dwData
= 0;
1926 button
[1].iString
= 0;
1928 SendMessageW(htoolbar
, TB_ADDBUTTONSW
, 2, (LPARAM
)button
);
1929 SendMessageW(htoolbar
, TB_SETBUTTONSIZE
, 0, MAKELPARAM(24,24));
1930 SendMessageW(htoolbar
, TB_AUTOSIZE
, 0, 0);
1933 static void update_control_text(FileDialogImpl
*This
)
1936 LPCWSTR custom_okbutton
;
1938 UINT min_width
= MulDiv(50, This
->dpi_x
, USER_DEFAULT_SCREEN_DPI
);
1939 UINT max_width
= MulDiv(250, This
->dpi_x
, USER_DEFAULT_SCREEN_DPI
);
1941 if(This
->custom_title
)
1942 SetWindowTextW(This
->dlg_hwnd
, This
->custom_title
);
1944 if(This
->hmenu_opendropdown
&& (item
= get_first_item(&This
->cctrl_opendropdown
)))
1945 custom_okbutton
= item
->label
;
1947 custom_okbutton
= This
->custom_okbutton
;
1949 if(custom_okbutton
&&
1950 (hitem
= GetDlgItem(This
->dlg_hwnd
, IDOK
)))
1952 SetWindowTextW(hitem
, custom_okbutton
);
1953 ctrl_resize(hitem
, min_width
, max_width
, FALSE
);
1956 if(This
->custom_cancelbutton
&&
1957 (hitem
= GetDlgItem(This
->dlg_hwnd
, IDCANCEL
)))
1959 SetWindowTextW(hitem
, This
->custom_cancelbutton
);
1960 ctrl_resize(hitem
, min_width
, max_width
, FALSE
);
1963 if(This
->custom_filenamelabel
&&
1964 (hitem
= GetDlgItem(This
->dlg_hwnd
, IDC_FILENAMESTATIC
)))
1966 SetWindowTextW(hitem
, This
->custom_filenamelabel
);
1967 ctrl_resize(hitem
, min_width
, max_width
, FALSE
);
1971 static LRESULT CALLBACK
dropdown_subclass_proc(HWND hwnd
, UINT umessage
, WPARAM wparam
, LPARAM lparam
)
1973 static const WCHAR prop_this
[] = {'i','t','e','m','d','l','g','_','T','h','i','s',0};
1974 static const WCHAR prop_oldwndproc
[] = {'i','t','e','m','d','l','g','_','o','l','d','w','n','d','p','r','o','c',0};
1976 if (umessage
== WM_LBUTTONDOWN
)
1978 FileDialogImpl
*This
= GetPropW(hwnd
, prop_this
);
1980 SendMessageW(hwnd
, BM_SETCHECK
, BST_CHECKED
, 0);
1981 show_opendropdown(This
);
1982 SendMessageW(hwnd
, BM_SETCHECK
, BST_UNCHECKED
, 0);
1987 return CallWindowProcW((WNDPROC
)GetPropW(hwnd
, prop_oldwndproc
), hwnd
, umessage
, wparam
, lparam
);
1990 static LRESULT
on_wm_initdialog(HWND hwnd
, LPARAM lParam
)
1992 FileDialogImpl
*This
= (FileDialogImpl
*)lParam
;
1995 TRACE("(%p, %p)\n", This
, hwnd
);
1997 SetWindowLongPtrW(hwnd
, GWLP_USERDATA
, (LPARAM
)This
);
1998 This
->dlg_hwnd
= hwnd
;
2000 hitem
= GetDlgItem(This
->dlg_hwnd
, pshHelp
);
2001 if(hitem
) ShowWindow(hitem
, SW_HIDE
);
2003 hitem
= GetDlgItem(This
->dlg_hwnd
, IDC_FILETYPESTATIC
);
2004 if(hitem
) ShowWindow(hitem
, SW_HIDE
);
2006 /* Fill filetypes combobox, or hide it. */
2007 hitem
= GetDlgItem(This
->dlg_hwnd
, IDC_FILETYPE
);
2008 if(This
->filterspec_count
)
2013 UINT i
, maxwidth
= 0;
2016 font
= (HFONT
)SendMessageW(hitem
, WM_GETFONT
, 0, 0);
2017 SelectObject(hdc
, font
);
2019 for(i
= 0; i
< This
->filterspec_count
; i
++)
2021 SendMessageW(hitem
, CB_ADDSTRING
, 0, (LPARAM
)This
->filterspecs
[i
].pszName
);
2023 if(GetTextExtentPoint32W(hdc
, This
->filterspecs
[i
].pszName
, lstrlenW(This
->filterspecs
[i
].pszName
), &size
))
2024 maxwidth
= max(maxwidth
, size
.cx
);
2026 ReleaseDC(hitem
, hdc
);
2030 maxwidth
+= GetSystemMetrics(SM_CXVSCROLL
) + 4;
2031 SendMessageW(hitem
, CB_SETDROPPEDWIDTH
, (WPARAM
)maxwidth
, 0);
2034 ERR("Failed to calculate width of filetype dropdown\n");
2036 SendMessageW(hitem
, CB_SETCURSEL
, This
->filetypeindex
, 0);
2039 ShowWindow(hitem
, SW_HIDE
);
2041 if(This
->set_filename
&&
2042 (hitem
= GetDlgItem(This
->dlg_hwnd
, IDC_FILENAME
)) )
2043 SendMessageW(hitem
, WM_SETTEXT
, 0, (LPARAM
)This
->set_filename
);
2045 if(This
->hmenu_opendropdown
)
2048 LOGFONTW lfw
, lfw_marlett
;
2050 static const WCHAR marlett
[] = {'M','a','r','l','e','t','t',0};
2051 static const WCHAR prop_this
[] = {'i','t','e','m','d','l','g','_','T','h','i','s',0};
2052 static const WCHAR prop_oldwndproc
[] = {'i','t','e','m','d','l','g','_','o','l','d','w','n','d','p','r','o','c',0};
2054 dropdown_hwnd
= GetDlgItem(This
->dlg_hwnd
, psh1
);
2056 /* Change dropdown button font to Marlett */
2057 dialog_font
= (HFONT
)SendMessageW(dropdown_hwnd
, WM_GETFONT
, 0, 0);
2059 GetObjectW(dialog_font
, sizeof(lfw
), &lfw
);
2061 memset(&lfw_marlett
, 0, sizeof(lfw_marlett
));
2062 lstrcpyW(lfw_marlett
.lfFaceName
, marlett
);
2063 lfw_marlett
.lfHeight
= lfw
.lfHeight
;
2064 lfw_marlett
.lfCharSet
= SYMBOL_CHARSET
;
2066 This
->hfont_opendropdown
= CreateFontIndirectW(&lfw_marlett
);
2068 SendMessageW(dropdown_hwnd
, WM_SETFONT
, (LPARAM
)This
->hfont_opendropdown
, 0);
2070 /* Subclass button so we can handle LBUTTONDOWN */
2071 SetPropW(dropdown_hwnd
, prop_this
, This
);
2072 SetPropW(dropdown_hwnd
, prop_oldwndproc
,
2073 (HANDLE
)SetWindowLongPtrW(dropdown_hwnd
, GWLP_WNDPROC
, (LONG_PTR
)dropdown_subclass_proc
));
2076 ctrl_container_reparent(This
, This
->dlg_hwnd
);
2077 init_explorerbrowser(This
);
2078 init_toolbar(This
, hwnd
);
2079 update_control_text(This
);
2080 update_layout(This
);
2082 if(This
->filterspec_count
)
2083 events_OnTypeChange(This
);
2085 if ((hitem
= GetDlgItem(This
->dlg_hwnd
, IDC_FILENAME
)))
2091 static LRESULT
on_wm_size(FileDialogImpl
*This
)
2093 update_layout(This
);
2097 static LRESULT
on_wm_getminmaxinfo(FileDialogImpl
*This
, LPARAM lparam
)
2099 MINMAXINFO
*mmi
= (MINMAXINFO
*)lparam
;
2100 TRACE("%p (%p)\n", This
, mmi
);
2103 mmi
->ptMinTrackSize
.x
= 640;
2104 mmi
->ptMinTrackSize
.y
= 480;
2109 static LRESULT
on_wm_destroy(FileDialogImpl
*This
)
2111 TRACE("%p\n", This
);
2115 IExplorerBrowser_Destroy(This
->peb
);
2116 IExplorerBrowser_Release(This
->peb
);
2120 ctrl_container_reparent(This
, NULL
);
2121 This
->dlg_hwnd
= NULL
;
2123 DeleteObject(This
->hfont_opendropdown
);
2124 This
->hfont_opendropdown
= NULL
;
2129 static LRESULT
on_idok(FileDialogImpl
*This
)
2131 TRACE("%p\n", This
);
2133 if(SUCCEEDED(on_default_action(This
)))
2134 EndDialog(This
->dlg_hwnd
, S_OK
);
2139 static LRESULT
on_idcancel(FileDialogImpl
*This
)
2141 TRACE("%p\n", This
);
2143 EndDialog(This
->dlg_hwnd
, HRESULT_FROM_WIN32(ERROR_CANCELLED
));
2148 static LRESULT
on_command_opendropdown(FileDialogImpl
*This
, WPARAM wparam
, LPARAM lparam
)
2150 if(HIWORD(wparam
) == BN_CLICKED
)
2152 HWND hwnd
= (HWND
)lparam
;
2153 SendMessageW(hwnd
, BM_SETCHECK
, BST_CHECKED
, 0);
2154 show_opendropdown(This
);
2155 SendMessageW(hwnd
, BM_SETCHECK
, BST_UNCHECKED
, 0);
2161 static LRESULT
on_browse_back(FileDialogImpl
*This
)
2163 TRACE("%p\n", This
);
2164 IExplorerBrowser_BrowseToIDList(This
->peb
, NULL
, SBSP_NAVIGATEBACK
);
2168 static LRESULT
on_browse_forward(FileDialogImpl
*This
)
2170 TRACE("%p\n", This
);
2171 IExplorerBrowser_BrowseToIDList(This
->peb
, NULL
, SBSP_NAVIGATEFORWARD
);
2175 static LRESULT
on_command_filetype(FileDialogImpl
*This
, WPARAM wparam
, LPARAM lparam
)
2177 if(HIWORD(wparam
) == CBN_SELCHANGE
)
2182 UINT prev_index
= This
->filetypeindex
;
2184 This
->filetypeindex
= SendMessageW((HWND
)lparam
, CB_GETCURSEL
, 0, 0);
2185 TRACE("File type selection changed to %d.\n", This
->filetypeindex
);
2187 if(prev_index
== This
->filetypeindex
)
2190 hr
= IExplorerBrowser_GetCurrentView(This
->peb
, &IID_IShellView
, (void**)&psv
);
2193 IShellView_Refresh(psv
);
2194 IShellView_Release(psv
);
2197 if(This
->dlg_type
== ITEMDLG_TYPE_SAVE
&& get_file_name(This
, &filename
))
2199 WCHAR buf
[MAX_PATH
], extbuf
[MAX_PATH
], *ext
;
2201 ext
= get_first_ext_from_spec(extbuf
, This
->filterspecs
[This
->filetypeindex
].pszSpec
);
2204 lstrcpyW(buf
, filename
);
2206 if(PathMatchSpecW(buf
, This
->filterspecs
[prev_index
].pszSpec
))
2207 PathRemoveExtensionW(buf
);
2210 set_file_name(This
, buf
);
2212 CoTaskMemFree(filename
);
2215 /* The documentation claims that OnTypeChange is called only
2216 * when the dialog is opened, but this is obviously not the
2218 events_OnTypeChange(This
);
2224 static LRESULT
on_wm_command(FileDialogImpl
*This
, WPARAM wparam
, LPARAM lparam
)
2226 switch(LOWORD(wparam
))
2228 case IDOK
: return on_idok(This
);
2229 case IDCANCEL
: return on_idcancel(This
);
2230 case psh1
: return on_command_opendropdown(This
, wparam
, lparam
);
2231 case IDC_NAVBACK
: return on_browse_back(This
);
2232 case IDC_NAVFORWARD
: return on_browse_forward(This
);
2233 case IDC_FILETYPE
: return on_command_filetype(This
, wparam
, lparam
);
2234 default: TRACE("Unknown command.\n");
2239 static LRESULT CALLBACK
itemdlg_dlgproc(HWND hwnd
, UINT umessage
, WPARAM wparam
, LPARAM lparam
)
2241 FileDialogImpl
*This
= (FileDialogImpl
*)GetWindowLongPtrW(hwnd
, GWLP_USERDATA
);
2245 case WM_INITDIALOG
: return on_wm_initdialog(hwnd
, lparam
);
2246 case WM_COMMAND
: return on_wm_command(This
, wparam
, lparam
);
2247 case WM_SIZE
: return on_wm_size(This
);
2248 case WM_GETMINMAXINFO
: return on_wm_getminmaxinfo(This
, lparam
);
2249 case WM_DESTROY
: return on_wm_destroy(This
);
2255 static HRESULT
create_dialog(FileDialogImpl
*This
, HWND parent
)
2260 res
= DialogBoxParamW(COMDLG32_hInstance
,
2261 MAKEINTRESOURCEW(NEWFILEOPENV3ORD
),
2262 parent
, itemdlg_dlgproc
, (LPARAM
)This
);
2263 This
->dlg_hwnd
= NULL
;
2266 ERR("Failed to show dialog (LastError: %d)\n", GetLastError());
2270 TRACE("Returning 0x%08x\n", (HRESULT
)res
);
2271 return (HRESULT
)res
;
2274 /**************************************************************************
2275 * IFileDialog implementation
2277 static inline FileDialogImpl
*impl_from_IFileDialog2(IFileDialog2
*iface
)
2279 return CONTAINING_RECORD(iface
, FileDialogImpl
, IFileDialog2_iface
);
2282 static HRESULT WINAPI
IFileDialog2_fnQueryInterface(IFileDialog2
*iface
,
2286 FileDialogImpl
*This
= impl_from_IFileDialog2(iface
);
2287 TRACE("%p (%s, %p)\n", This
, debugstr_guid(riid
), ppvObject
);
2290 if(IsEqualGUID(riid
, &IID_IUnknown
) ||
2291 IsEqualGUID(riid
, &IID_IFileDialog
) ||
2292 IsEqualGUID(riid
, &IID_IFileDialog2
))
2296 else if(IsEqualGUID(riid
, &IID_IFileOpenDialog
) && This
->dlg_type
== ITEMDLG_TYPE_OPEN
)
2298 *ppvObject
= &This
->u
.IFileOpenDialog_iface
;
2300 else if(IsEqualGUID(riid
, &IID_IFileSaveDialog
) && This
->dlg_type
== ITEMDLG_TYPE_SAVE
)
2302 *ppvObject
= &This
->u
.IFileSaveDialog_iface
;
2304 else if(IsEqualGUID(riid
, &IID_IExplorerBrowserEvents
))
2306 *ppvObject
= &This
->IExplorerBrowserEvents_iface
;
2308 else if(IsEqualGUID(riid
, &IID_IServiceProvider
))
2310 *ppvObject
= &This
->IServiceProvider_iface
;
2312 else if(IsEqualGUID(&IID_ICommDlgBrowser3
, riid
) ||
2313 IsEqualGUID(&IID_ICommDlgBrowser2
, riid
) ||
2314 IsEqualGUID(&IID_ICommDlgBrowser
, riid
))
2316 *ppvObject
= &This
->ICommDlgBrowser3_iface
;
2318 else if(IsEqualGUID(&IID_IOleWindow
, riid
))
2320 *ppvObject
= &This
->IOleWindow_iface
;
2322 else if(IsEqualGUID(riid
, &IID_IFileDialogCustomize
) ||
2323 IsEqualGUID(riid
, &IID_IFileDialogCustomizeAlt
))
2325 *ppvObject
= &This
->IFileDialogCustomize_iface
;
2328 FIXME("Unknown interface requested: %s.\n", debugstr_guid(riid
));
2332 IUnknown_AddRef((IUnknown
*)*ppvObject
);
2336 return E_NOINTERFACE
;
2339 static ULONG WINAPI
IFileDialog2_fnAddRef(IFileDialog2
*iface
)
2341 FileDialogImpl
*This
= impl_from_IFileDialog2(iface
);
2342 LONG ref
= InterlockedIncrement(&This
->ref
);
2343 TRACE("%p - ref %d\n", This
, ref
);
2348 static ULONG WINAPI
IFileDialog2_fnRelease(IFileDialog2
*iface
)
2350 FileDialogImpl
*This
= impl_from_IFileDialog2(iface
);
2351 LONG ref
= InterlockedDecrement(&This
->ref
);
2352 TRACE("%p - ref %d\n", This
, ref
);
2357 for(i
= 0; i
< This
->filterspec_count
; i
++)
2359 LocalFree((void*)This
->filterspecs
[i
].pszName
);
2360 LocalFree((void*)This
->filterspecs
[i
].pszSpec
);
2362 HeapFree(GetProcessHeap(), 0, This
->filterspecs
);
2364 DestroyWindow(This
->cctrls_hwnd
);
2366 if(This
->psi_defaultfolder
) IShellItem_Release(This
->psi_defaultfolder
);
2367 if(This
->psi_setfolder
) IShellItem_Release(This
->psi_setfolder
);
2368 if(This
->psi_folder
) IShellItem_Release(This
->psi_folder
);
2369 if(This
->psia_selection
) IShellItemArray_Release(This
->psia_selection
);
2370 if(This
->psia_results
) IShellItemArray_Release(This
->psia_results
);
2372 LocalFree(This
->set_filename
);
2373 LocalFree(This
->default_ext
);
2374 LocalFree(This
->custom_title
);
2375 LocalFree(This
->custom_okbutton
);
2376 LocalFree(This
->custom_cancelbutton
);
2377 LocalFree(This
->custom_filenamelabel
);
2379 DestroyMenu(This
->hmenu_opendropdown
);
2380 DeleteObject(This
->hfont_opendropdown
);
2382 HeapFree(GetProcessHeap(), 0, This
);
2388 static HRESULT WINAPI
IFileDialog2_fnShow(IFileDialog2
*iface
, HWND hwndOwner
)
2390 FileDialogImpl
*This
= impl_from_IFileDialog2(iface
);
2391 TRACE("%p (%p)\n", iface
, hwndOwner
);
2393 This
->opendropdown_has_selection
= FALSE
;
2395 return create_dialog(This
, hwndOwner
);
2398 static HRESULT WINAPI
IFileDialog2_fnSetFileTypes(IFileDialog2
*iface
, UINT cFileTypes
,
2399 const COMDLG_FILTERSPEC
*rgFilterSpec
)
2401 FileDialogImpl
*This
= impl_from_IFileDialog2(iface
);
2403 TRACE("%p (%d, %p)\n", This
, cFileTypes
, rgFilterSpec
);
2405 if(This
->filterspecs
)
2406 return E_UNEXPECTED
;
2409 return E_INVALIDARG
;
2414 This
->filterspecs
= HeapAlloc(GetProcessHeap(), 0, sizeof(COMDLG_FILTERSPEC
)*cFileTypes
);
2415 for(i
= 0; i
< cFileTypes
; i
++)
2417 This
->filterspecs
[i
].pszName
= StrDupW(rgFilterSpec
[i
].pszName
);
2418 This
->filterspecs
[i
].pszSpec
= StrDupW(rgFilterSpec
[i
].pszSpec
);
2420 This
->filterspec_count
= cFileTypes
;
2425 static HRESULT WINAPI
IFileDialog2_fnSetFileTypeIndex(IFileDialog2
*iface
, UINT iFileType
)
2427 FileDialogImpl
*This
= impl_from_IFileDialog2(iface
);
2428 TRACE("%p (%d)\n", This
, iFileType
);
2430 if(!This
->filterspecs
)
2433 iFileType
= max(iFileType
, 1);
2434 iFileType
= min(iFileType
, This
->filterspec_count
);
2435 This
->filetypeindex
= iFileType
-1;
2440 static HRESULT WINAPI
IFileDialog2_fnGetFileTypeIndex(IFileDialog2
*iface
, UINT
*piFileType
)
2442 FileDialogImpl
*This
= impl_from_IFileDialog2(iface
);
2443 TRACE("%p (%p)\n", This
, piFileType
);
2446 return E_INVALIDARG
;
2448 if(This
->filterspec_count
== 0)
2451 *piFileType
= This
->filetypeindex
+ 1;
2456 static HRESULT WINAPI
IFileDialog2_fnAdvise(IFileDialog2
*iface
, IFileDialogEvents
*pfde
, DWORD
*pdwCookie
)
2458 FileDialogImpl
*This
= impl_from_IFileDialog2(iface
);
2459 events_client
*client
;
2460 TRACE("%p (%p, %p)\n", This
, pfde
, pdwCookie
);
2462 if(!pfde
|| !pdwCookie
)
2463 return E_INVALIDARG
;
2465 client
= HeapAlloc(GetProcessHeap(), 0, sizeof(events_client
));
2466 client
->pfde
= pfde
;
2467 client
->cookie
= ++This
->events_next_cookie
;
2469 IFileDialogEvents_AddRef(pfde
);
2470 *pdwCookie
= client
->cookie
;
2472 list_add_tail(&This
->events_clients
, &client
->entry
);
2477 static HRESULT WINAPI
IFileDialog2_fnUnadvise(IFileDialog2
*iface
, DWORD dwCookie
)
2479 FileDialogImpl
*This
= impl_from_IFileDialog2(iface
);
2480 events_client
*client
, *found
= NULL
;
2481 TRACE("%p (%d)\n", This
, dwCookie
);
2483 LIST_FOR_EACH_ENTRY(client
, &This
->events_clients
, events_client
, entry
)
2485 if(client
->cookie
== dwCookie
)
2494 list_remove(&found
->entry
);
2495 IFileDialogEvents_Release(found
->pfde
);
2496 HeapFree(GetProcessHeap(), 0, found
);
2500 return E_INVALIDARG
;
2503 static HRESULT WINAPI
IFileDialog2_fnSetOptions(IFileDialog2
*iface
, FILEOPENDIALOGOPTIONS fos
)
2505 FileDialogImpl
*This
= impl_from_IFileDialog2(iface
);
2506 TRACE("%p (0x%x)\n", This
, fos
);
2508 if (fos
& ~(FOS_OVERWRITEPROMPT
| FOS_STRICTFILETYPES
| FOS_NOCHANGEDIR
| FOS_PICKFOLDERS
| FOS_FORCEFILESYSTEM
2509 | FOS_ALLNONSTORAGEITEMS
| FOS_NOVALIDATE
| FOS_ALLOWMULTISELECT
| FOS_PATHMUSTEXIST
| FOS_FILEMUSTEXIST
2510 | FOS_CREATEPROMPT
| FOS_SHAREAWARE
| FOS_NOREADONLYRETURN
| FOS_NOTESTFILECREATE
| FOS_HIDEMRUPLACES
2511 | FOS_HIDEPINNEDPLACES
| FOS_NODEREFERENCELINKS
| FOS_DONTADDTORECENT
| FOS_FORCESHOWHIDDEN
2512 | FOS_DEFAULTNOMINIMODE
| FOS_FORCEPREVIEWPANEON
| FOS_SUPPORTSTREAMABLEITEMS
))
2514 WARN("Invalid option %#x\n", fos
);
2515 return E_INVALIDARG
;
2518 if( !(This
->options
& FOS_PICKFOLDERS
) && (fos
& FOS_PICKFOLDERS
) )
2521 LoadStringW(COMDLG32_hInstance
, IDS_SELECT_FOLDER
, buf
, ARRAY_SIZE(buf
));
2522 IFileDialog2_SetTitle(iface
, buf
);
2525 This
->options
= fos
;
2530 static HRESULT WINAPI
IFileDialog2_fnGetOptions(IFileDialog2
*iface
, FILEOPENDIALOGOPTIONS
*pfos
)
2532 FileDialogImpl
*This
= impl_from_IFileDialog2(iface
);
2533 TRACE("%p (%p)\n", This
, pfos
);
2536 return E_INVALIDARG
;
2538 *pfos
= This
->options
;
2543 static HRESULT WINAPI
IFileDialog2_fnSetDefaultFolder(IFileDialog2
*iface
, IShellItem
*psi
)
2545 FileDialogImpl
*This
= impl_from_IFileDialog2(iface
);
2546 TRACE("%p (%p)\n", This
, psi
);
2547 if(This
->psi_defaultfolder
)
2548 IShellItem_Release(This
->psi_defaultfolder
);
2550 This
->psi_defaultfolder
= psi
;
2552 if(This
->psi_defaultfolder
)
2553 IShellItem_AddRef(This
->psi_defaultfolder
);
2558 static HRESULT WINAPI
IFileDialog2_fnSetFolder(IFileDialog2
*iface
, IShellItem
*psi
)
2560 FileDialogImpl
*This
= impl_from_IFileDialog2(iface
);
2561 TRACE("%p (%p)\n", This
, psi
);
2562 if(This
->psi_setfolder
)
2563 IShellItem_Release(This
->psi_setfolder
);
2565 This
->psi_setfolder
= psi
;
2567 if(This
->psi_setfolder
)
2568 IShellItem_AddRef(This
->psi_setfolder
);
2573 static HRESULT WINAPI
IFileDialog2_fnGetFolder(IFileDialog2
*iface
, IShellItem
**ppsi
)
2575 FileDialogImpl
*This
= impl_from_IFileDialog2(iface
);
2576 TRACE("%p (%p)\n", This
, ppsi
);
2578 return E_INVALIDARG
;
2581 If the dialog is shown, return the current(ly selected) folder. */
2584 if(This
->psi_folder
)
2585 *ppsi
= This
->psi_folder
;
2586 else if(This
->psi_setfolder
)
2587 *ppsi
= This
->psi_setfolder
;
2588 else if(This
->psi_defaultfolder
)
2589 *ppsi
= This
->psi_defaultfolder
;
2593 IShellItem_AddRef(*ppsi
);
2600 static HRESULT WINAPI
IFileDialog2_fnGetCurrentSelection(IFileDialog2
*iface
, IShellItem
**ppsi
)
2602 FileDialogImpl
*This
= impl_from_IFileDialog2(iface
);
2604 TRACE("%p (%p)\n", This
, ppsi
);
2607 return E_INVALIDARG
;
2609 if(This
->psia_selection
)
2611 /* FIXME: Check filename edit box */
2612 hr
= IShellItemArray_GetItemAt(This
->psia_selection
, 0, ppsi
);
2619 static HRESULT WINAPI
IFileDialog2_fnSetFileName(IFileDialog2
*iface
, LPCWSTR pszName
)
2621 FileDialogImpl
*This
= impl_from_IFileDialog2(iface
);
2622 TRACE("%p (%s)\n", iface
, debugstr_w(pszName
));
2624 set_file_name(This
, pszName
);
2629 static HRESULT WINAPI
IFileDialog2_fnGetFileName(IFileDialog2
*iface
, LPWSTR
*pszName
)
2631 FileDialogImpl
*This
= impl_from_IFileDialog2(iface
);
2632 TRACE("%p (%p)\n", iface
, pszName
);
2635 return E_INVALIDARG
;
2638 get_file_name(This
, pszName
);
2639 return *pszName
? S_OK
: E_FAIL
;
2642 static HRESULT WINAPI
IFileDialog2_fnSetTitle(IFileDialog2
*iface
, LPCWSTR pszTitle
)
2644 FileDialogImpl
*This
= impl_from_IFileDialog2(iface
);
2645 TRACE("%p (%s)\n", This
, debugstr_w(pszTitle
));
2647 LocalFree(This
->custom_title
);
2648 This
->custom_title
= StrDupW(pszTitle
);
2649 update_control_text(This
);
2654 static HRESULT WINAPI
IFileDialog2_fnSetOkButtonLabel(IFileDialog2
*iface
, LPCWSTR pszText
)
2656 FileDialogImpl
*This
= impl_from_IFileDialog2(iface
);
2657 TRACE("%p (%s)\n", This
, debugstr_w(pszText
));
2659 LocalFree(This
->custom_okbutton
);
2660 This
->custom_okbutton
= StrDupW(pszText
);
2661 update_control_text(This
);
2662 update_layout(This
);
2667 static HRESULT WINAPI
IFileDialog2_fnSetFileNameLabel(IFileDialog2
*iface
, LPCWSTR pszLabel
)
2669 FileDialogImpl
*This
= impl_from_IFileDialog2(iface
);
2670 TRACE("%p (%s)\n", This
, debugstr_w(pszLabel
));
2672 LocalFree(This
->custom_filenamelabel
);
2673 This
->custom_filenamelabel
= StrDupW(pszLabel
);
2674 update_control_text(This
);
2675 update_layout(This
);
2680 static HRESULT WINAPI
IFileDialog2_fnGetResult(IFileDialog2
*iface
, IShellItem
**ppsi
)
2682 FileDialogImpl
*This
= impl_from_IFileDialog2(iface
);
2684 TRACE("%p (%p)\n", This
, ppsi
);
2687 return E_INVALIDARG
;
2689 if(This
->psia_results
)
2692 hr
= IShellItemArray_GetCount(This
->psia_results
, &item_count
);
2698 /* Adds a reference. */
2699 hr
= IShellItemArray_GetItemAt(This
->psia_results
, 0, ppsi
);
2705 return E_UNEXPECTED
;
2708 static HRESULT WINAPI
IFileDialog2_fnAddPlace(IFileDialog2
*iface
, IShellItem
*psi
, FDAP fdap
)
2710 FileDialogImpl
*This
= impl_from_IFileDialog2(iface
);
2711 FIXME("stub - %p (%p, %d)\n", This
, psi
, fdap
);
2715 static HRESULT WINAPI
IFileDialog2_fnSetDefaultExtension(IFileDialog2
*iface
, LPCWSTR pszDefaultExtension
)
2717 FileDialogImpl
*This
= impl_from_IFileDialog2(iface
);
2718 TRACE("%p (%s)\n", This
, debugstr_w(pszDefaultExtension
));
2720 LocalFree(This
->default_ext
);
2721 This
->default_ext
= StrDupW(pszDefaultExtension
);
2726 static HRESULT WINAPI
IFileDialog2_fnClose(IFileDialog2
*iface
, HRESULT hr
)
2728 FileDialogImpl
*This
= impl_from_IFileDialog2(iface
);
2729 TRACE("%p (0x%08x)\n", This
, hr
);
2732 EndDialog(This
->dlg_hwnd
, hr
);
2737 static HRESULT WINAPI
IFileDialog2_fnSetClientGuid(IFileDialog2
*iface
, REFGUID guid
)
2739 FileDialogImpl
*This
= impl_from_IFileDialog2(iface
);
2740 TRACE("%p (%s)\n", This
, debugstr_guid(guid
));
2741 This
->client_guid
= *guid
;
2745 static HRESULT WINAPI
IFileDialog2_fnClearClientData(IFileDialog2
*iface
)
2747 FileDialogImpl
*This
= impl_from_IFileDialog2(iface
);
2748 FIXME("stub - %p\n", This
);
2752 static HRESULT WINAPI
IFileDialog2_fnSetFilter(IFileDialog2
*iface
, IShellItemFilter
*pFilter
)
2754 FileDialogImpl
*This
= impl_from_IFileDialog2(iface
);
2755 FIXME("stub - %p (%p)\n", This
, pFilter
);
2759 static HRESULT WINAPI
IFileDialog2_fnSetCancelButtonLabel(IFileDialog2
*iface
, LPCWSTR pszLabel
)
2761 FileDialogImpl
*This
= impl_from_IFileDialog2(iface
);
2762 TRACE("%p (%s)\n", This
, debugstr_w(pszLabel
));
2764 LocalFree(This
->custom_cancelbutton
);
2765 This
->custom_cancelbutton
= StrDupW(pszLabel
);
2766 update_control_text(This
);
2767 update_layout(This
);
2772 static HRESULT WINAPI
IFileDialog2_fnSetNavigationRoot(IFileDialog2
*iface
, IShellItem
*psi
)
2774 FileDialogImpl
*This
= impl_from_IFileDialog2(iface
);
2775 FIXME("stub - %p (%p)\n", This
, psi
);
2779 static const IFileDialog2Vtbl vt_IFileDialog2
= {
2780 IFileDialog2_fnQueryInterface
,
2781 IFileDialog2_fnAddRef
,
2782 IFileDialog2_fnRelease
,
2783 IFileDialog2_fnShow
,
2784 IFileDialog2_fnSetFileTypes
,
2785 IFileDialog2_fnSetFileTypeIndex
,
2786 IFileDialog2_fnGetFileTypeIndex
,
2787 IFileDialog2_fnAdvise
,
2788 IFileDialog2_fnUnadvise
,
2789 IFileDialog2_fnSetOptions
,
2790 IFileDialog2_fnGetOptions
,
2791 IFileDialog2_fnSetDefaultFolder
,
2792 IFileDialog2_fnSetFolder
,
2793 IFileDialog2_fnGetFolder
,
2794 IFileDialog2_fnGetCurrentSelection
,
2795 IFileDialog2_fnSetFileName
,
2796 IFileDialog2_fnGetFileName
,
2797 IFileDialog2_fnSetTitle
,
2798 IFileDialog2_fnSetOkButtonLabel
,
2799 IFileDialog2_fnSetFileNameLabel
,
2800 IFileDialog2_fnGetResult
,
2801 IFileDialog2_fnAddPlace
,
2802 IFileDialog2_fnSetDefaultExtension
,
2803 IFileDialog2_fnClose
,
2804 IFileDialog2_fnSetClientGuid
,
2805 IFileDialog2_fnClearClientData
,
2806 IFileDialog2_fnSetFilter
,
2807 IFileDialog2_fnSetCancelButtonLabel
,
2808 IFileDialog2_fnSetNavigationRoot
2811 /**************************************************************************
2814 static inline FileDialogImpl
*impl_from_IFileOpenDialog(IFileOpenDialog
*iface
)
2816 return CONTAINING_RECORD(iface
, FileDialogImpl
, u
.IFileOpenDialog_iface
);
2819 static HRESULT WINAPI
IFileOpenDialog_fnQueryInterface(IFileOpenDialog
*iface
,
2820 REFIID riid
, void **ppvObject
)
2822 FileDialogImpl
*This
= impl_from_IFileOpenDialog(iface
);
2823 return IFileDialog2_QueryInterface(&This
->IFileDialog2_iface
, riid
, ppvObject
);
2826 static ULONG WINAPI
IFileOpenDialog_fnAddRef(IFileOpenDialog
*iface
)
2828 FileDialogImpl
*This
= impl_from_IFileOpenDialog(iface
);
2829 return IFileDialog2_AddRef(&This
->IFileDialog2_iface
);
2832 static ULONG WINAPI
IFileOpenDialog_fnRelease(IFileOpenDialog
*iface
)
2834 FileDialogImpl
*This
= impl_from_IFileOpenDialog(iface
);
2835 return IFileDialog2_Release(&This
->IFileDialog2_iface
);
2838 static HRESULT WINAPI
IFileOpenDialog_fnShow(IFileOpenDialog
*iface
, HWND hwndOwner
)
2840 FileDialogImpl
*This
= impl_from_IFileOpenDialog(iface
);
2841 return IFileDialog2_Show(&This
->IFileDialog2_iface
, hwndOwner
);
2844 static HRESULT WINAPI
IFileOpenDialog_fnSetFileTypes(IFileOpenDialog
*iface
, UINT cFileTypes
,
2845 const COMDLG_FILTERSPEC
*rgFilterSpec
)
2847 FileDialogImpl
*This
= impl_from_IFileOpenDialog(iface
);
2848 return IFileDialog2_SetFileTypes(&This
->IFileDialog2_iface
, cFileTypes
, rgFilterSpec
);
2851 static HRESULT WINAPI
IFileOpenDialog_fnSetFileTypeIndex(IFileOpenDialog
*iface
, UINT iFileType
)
2853 FileDialogImpl
*This
= impl_from_IFileOpenDialog(iface
);
2854 return IFileDialog2_SetFileTypeIndex(&This
->IFileDialog2_iface
, iFileType
);
2857 static HRESULT WINAPI
IFileOpenDialog_fnGetFileTypeIndex(IFileOpenDialog
*iface
, UINT
*piFileType
)
2859 FileDialogImpl
*This
= impl_from_IFileOpenDialog(iface
);
2860 return IFileDialog2_GetFileTypeIndex(&This
->IFileDialog2_iface
, piFileType
);
2863 static HRESULT WINAPI
IFileOpenDialog_fnAdvise(IFileOpenDialog
*iface
, IFileDialogEvents
*pfde
,
2866 FileDialogImpl
*This
= impl_from_IFileOpenDialog(iface
);
2867 return IFileDialog2_Advise(&This
->IFileDialog2_iface
, pfde
, pdwCookie
);
2870 static HRESULT WINAPI
IFileOpenDialog_fnUnadvise(IFileOpenDialog
*iface
, DWORD dwCookie
)
2872 FileDialogImpl
*This
= impl_from_IFileOpenDialog(iface
);
2873 return IFileDialog2_Unadvise(&This
->IFileDialog2_iface
, dwCookie
);
2876 static HRESULT WINAPI
IFileOpenDialog_fnSetOptions(IFileOpenDialog
*iface
, FILEOPENDIALOGOPTIONS fos
)
2878 FileDialogImpl
*This
= impl_from_IFileOpenDialog(iface
);
2879 return IFileDialog2_SetOptions(&This
->IFileDialog2_iface
, fos
);
2882 static HRESULT WINAPI
IFileOpenDialog_fnGetOptions(IFileOpenDialog
*iface
, FILEOPENDIALOGOPTIONS
*pfos
)
2884 FileDialogImpl
*This
= impl_from_IFileOpenDialog(iface
);
2885 return IFileDialog2_GetOptions(&This
->IFileDialog2_iface
, pfos
);
2888 static HRESULT WINAPI
IFileOpenDialog_fnSetDefaultFolder(IFileOpenDialog
*iface
, IShellItem
*psi
)
2890 FileDialogImpl
*This
= impl_from_IFileOpenDialog(iface
);
2891 return IFileDialog2_SetDefaultFolder(&This
->IFileDialog2_iface
, psi
);
2894 static HRESULT WINAPI
IFileOpenDialog_fnSetFolder(IFileOpenDialog
*iface
, IShellItem
*psi
)
2896 FileDialogImpl
*This
= impl_from_IFileOpenDialog(iface
);
2897 return IFileDialog2_SetFolder(&This
->IFileDialog2_iface
, psi
);
2900 static HRESULT WINAPI
IFileOpenDialog_fnGetFolder(IFileOpenDialog
*iface
, IShellItem
**ppsi
)
2902 FileDialogImpl
*This
= impl_from_IFileOpenDialog(iface
);
2903 return IFileDialog2_GetFolder(&This
->IFileDialog2_iface
, ppsi
);
2906 static HRESULT WINAPI
IFileOpenDialog_fnGetCurrentSelection(IFileOpenDialog
*iface
, IShellItem
**ppsi
)
2908 FileDialogImpl
*This
= impl_from_IFileOpenDialog(iface
);
2909 return IFileDialog2_GetCurrentSelection(&This
->IFileDialog2_iface
, ppsi
);
2912 static HRESULT WINAPI
IFileOpenDialog_fnSetFileName(IFileOpenDialog
*iface
, LPCWSTR pszName
)
2914 FileDialogImpl
*This
= impl_from_IFileOpenDialog(iface
);
2915 return IFileDialog2_SetFileName(&This
->IFileDialog2_iface
, pszName
);
2918 static HRESULT WINAPI
IFileOpenDialog_fnGetFileName(IFileOpenDialog
*iface
, LPWSTR
*pszName
)
2920 FileDialogImpl
*This
= impl_from_IFileOpenDialog(iface
);
2921 return IFileDialog2_GetFileName(&This
->IFileDialog2_iface
, pszName
);
2924 static HRESULT WINAPI
IFileOpenDialog_fnSetTitle(IFileOpenDialog
*iface
, LPCWSTR pszTitle
)
2926 FileDialogImpl
*This
= impl_from_IFileOpenDialog(iface
);
2927 return IFileDialog2_SetTitle(&This
->IFileDialog2_iface
, pszTitle
);
2930 static HRESULT WINAPI
IFileOpenDialog_fnSetOkButtonLabel(IFileOpenDialog
*iface
, LPCWSTR pszText
)
2932 FileDialogImpl
*This
= impl_from_IFileOpenDialog(iface
);
2933 return IFileDialog2_SetOkButtonLabel(&This
->IFileDialog2_iface
, pszText
);
2936 static HRESULT WINAPI
IFileOpenDialog_fnSetFileNameLabel(IFileOpenDialog
*iface
, LPCWSTR pszLabel
)
2938 FileDialogImpl
*This
= impl_from_IFileOpenDialog(iface
);
2939 return IFileDialog2_SetFileNameLabel(&This
->IFileDialog2_iface
, pszLabel
);
2942 static HRESULT WINAPI
IFileOpenDialog_fnGetResult(IFileOpenDialog
*iface
, IShellItem
**ppsi
)
2944 FileDialogImpl
*This
= impl_from_IFileOpenDialog(iface
);
2945 return IFileDialog2_GetResult(&This
->IFileDialog2_iface
, ppsi
);
2948 static HRESULT WINAPI
IFileOpenDialog_fnAddPlace(IFileOpenDialog
*iface
, IShellItem
*psi
, FDAP fdap
)
2950 FileDialogImpl
*This
= impl_from_IFileOpenDialog(iface
);
2951 return IFileDialog2_AddPlace(&This
->IFileDialog2_iface
, psi
, fdap
);
2954 static HRESULT WINAPI
IFileOpenDialog_fnSetDefaultExtension(IFileOpenDialog
*iface
,
2955 LPCWSTR pszDefaultExtension
)
2957 FileDialogImpl
*This
= impl_from_IFileOpenDialog(iface
);
2958 return IFileDialog2_SetDefaultExtension(&This
->IFileDialog2_iface
, pszDefaultExtension
);
2961 static HRESULT WINAPI
IFileOpenDialog_fnClose(IFileOpenDialog
*iface
, HRESULT hr
)
2963 FileDialogImpl
*This
= impl_from_IFileOpenDialog(iface
);
2964 return IFileDialog2_Close(&This
->IFileDialog2_iface
, hr
);
2967 static HRESULT WINAPI
IFileOpenDialog_fnSetClientGuid(IFileOpenDialog
*iface
, REFGUID guid
)
2969 FileDialogImpl
*This
= impl_from_IFileOpenDialog(iface
);
2970 return IFileDialog2_SetClientGuid(&This
->IFileDialog2_iface
, guid
);
2973 static HRESULT WINAPI
IFileOpenDialog_fnClearClientData(IFileOpenDialog
*iface
)
2975 FileDialogImpl
*This
= impl_from_IFileOpenDialog(iface
);
2976 return IFileDialog2_ClearClientData(&This
->IFileDialog2_iface
);
2979 static HRESULT WINAPI
IFileOpenDialog_fnSetFilter(IFileOpenDialog
*iface
, IShellItemFilter
*pFilter
)
2981 FileDialogImpl
*This
= impl_from_IFileOpenDialog(iface
);
2982 return IFileDialog2_SetFilter(&This
->IFileDialog2_iface
, pFilter
);
2985 static HRESULT WINAPI
IFileOpenDialog_fnGetResults(IFileOpenDialog
*iface
, IShellItemArray
**ppenum
)
2987 FileDialogImpl
*This
= impl_from_IFileOpenDialog(iface
);
2988 TRACE("%p (%p)\n", This
, ppenum
);
2990 *ppenum
= This
->psia_results
;
2994 IShellItemArray_AddRef(*ppenum
);
3001 static HRESULT WINAPI
IFileOpenDialog_fnGetSelectedItems(IFileOpenDialog
*iface
, IShellItemArray
**ppsai
)
3003 FileDialogImpl
*This
= impl_from_IFileOpenDialog(iface
);
3004 TRACE("%p (%p)\n", This
, ppsai
);
3006 if(This
->psia_selection
)
3008 *ppsai
= This
->psia_selection
;
3009 IShellItemArray_AddRef(*ppsai
);
3016 static const IFileOpenDialogVtbl vt_IFileOpenDialog
= {
3017 IFileOpenDialog_fnQueryInterface
,
3018 IFileOpenDialog_fnAddRef
,
3019 IFileOpenDialog_fnRelease
,
3020 IFileOpenDialog_fnShow
,
3021 IFileOpenDialog_fnSetFileTypes
,
3022 IFileOpenDialog_fnSetFileTypeIndex
,
3023 IFileOpenDialog_fnGetFileTypeIndex
,
3024 IFileOpenDialog_fnAdvise
,
3025 IFileOpenDialog_fnUnadvise
,
3026 IFileOpenDialog_fnSetOptions
,
3027 IFileOpenDialog_fnGetOptions
,
3028 IFileOpenDialog_fnSetDefaultFolder
,
3029 IFileOpenDialog_fnSetFolder
,
3030 IFileOpenDialog_fnGetFolder
,
3031 IFileOpenDialog_fnGetCurrentSelection
,
3032 IFileOpenDialog_fnSetFileName
,
3033 IFileOpenDialog_fnGetFileName
,
3034 IFileOpenDialog_fnSetTitle
,
3035 IFileOpenDialog_fnSetOkButtonLabel
,
3036 IFileOpenDialog_fnSetFileNameLabel
,
3037 IFileOpenDialog_fnGetResult
,
3038 IFileOpenDialog_fnAddPlace
,
3039 IFileOpenDialog_fnSetDefaultExtension
,
3040 IFileOpenDialog_fnClose
,
3041 IFileOpenDialog_fnSetClientGuid
,
3042 IFileOpenDialog_fnClearClientData
,
3043 IFileOpenDialog_fnSetFilter
,
3044 IFileOpenDialog_fnGetResults
,
3045 IFileOpenDialog_fnGetSelectedItems
3048 /**************************************************************************
3051 static inline FileDialogImpl
*impl_from_IFileSaveDialog(IFileSaveDialog
*iface
)
3053 return CONTAINING_RECORD(iface
, FileDialogImpl
, u
.IFileSaveDialog_iface
);
3056 static HRESULT WINAPI
IFileSaveDialog_fnQueryInterface(IFileSaveDialog
*iface
,
3060 FileDialogImpl
*This
= impl_from_IFileSaveDialog(iface
);
3061 return IFileDialog2_QueryInterface(&This
->IFileDialog2_iface
, riid
, ppvObject
);
3064 static ULONG WINAPI
IFileSaveDialog_fnAddRef(IFileSaveDialog
*iface
)
3066 FileDialogImpl
*This
= impl_from_IFileSaveDialog(iface
);
3067 return IFileDialog2_AddRef(&This
->IFileDialog2_iface
);
3070 static ULONG WINAPI
IFileSaveDialog_fnRelease(IFileSaveDialog
*iface
)
3072 FileDialogImpl
*This
= impl_from_IFileSaveDialog(iface
);
3073 return IFileDialog2_Release(&This
->IFileDialog2_iface
);
3076 static HRESULT WINAPI
IFileSaveDialog_fnShow(IFileSaveDialog
*iface
, HWND hwndOwner
)
3078 FileDialogImpl
*This
= impl_from_IFileSaveDialog(iface
);
3079 return IFileDialog2_Show(&This
->IFileDialog2_iface
, hwndOwner
);
3082 static HRESULT WINAPI
IFileSaveDialog_fnSetFileTypes(IFileSaveDialog
*iface
, UINT cFileTypes
,
3083 const COMDLG_FILTERSPEC
*rgFilterSpec
)
3085 FileDialogImpl
*This
= impl_from_IFileSaveDialog(iface
);
3086 return IFileDialog2_SetFileTypes(&This
->IFileDialog2_iface
, cFileTypes
, rgFilterSpec
);
3089 static HRESULT WINAPI
IFileSaveDialog_fnSetFileTypeIndex(IFileSaveDialog
*iface
, UINT iFileType
)
3091 FileDialogImpl
*This
= impl_from_IFileSaveDialog(iface
);
3092 return IFileDialog2_SetFileTypeIndex(&This
->IFileDialog2_iface
, iFileType
);
3095 static HRESULT WINAPI
IFileSaveDialog_fnGetFileTypeIndex(IFileSaveDialog
*iface
, UINT
*piFileType
)
3097 FileDialogImpl
*This
= impl_from_IFileSaveDialog(iface
);
3098 return IFileDialog2_GetFileTypeIndex(&This
->IFileDialog2_iface
, piFileType
);
3101 static HRESULT WINAPI
IFileSaveDialog_fnAdvise(IFileSaveDialog
*iface
, IFileDialogEvents
*pfde
,
3104 FileDialogImpl
*This
= impl_from_IFileSaveDialog(iface
);
3105 return IFileDialog2_Advise(&This
->IFileDialog2_iface
, pfde
, pdwCookie
);
3108 static HRESULT WINAPI
IFileSaveDialog_fnUnadvise(IFileSaveDialog
*iface
, DWORD dwCookie
)
3110 FileDialogImpl
*This
= impl_from_IFileSaveDialog(iface
);
3111 return IFileDialog2_Unadvise(&This
->IFileDialog2_iface
, dwCookie
);
3114 static HRESULT WINAPI
IFileSaveDialog_fnSetOptions(IFileSaveDialog
*iface
, FILEOPENDIALOGOPTIONS fos
)
3116 FileDialogImpl
*This
= impl_from_IFileSaveDialog(iface
);
3117 return IFileDialog2_SetOptions(&This
->IFileDialog2_iface
, fos
);
3120 static HRESULT WINAPI
IFileSaveDialog_fnGetOptions(IFileSaveDialog
*iface
, FILEOPENDIALOGOPTIONS
*pfos
)
3122 FileDialogImpl
*This
= impl_from_IFileSaveDialog(iface
);
3123 return IFileDialog2_GetOptions(&This
->IFileDialog2_iface
, pfos
);
3126 static HRESULT WINAPI
IFileSaveDialog_fnSetDefaultFolder(IFileSaveDialog
*iface
, IShellItem
*psi
)
3128 FileDialogImpl
*This
= impl_from_IFileSaveDialog(iface
);
3129 return IFileDialog2_SetDefaultFolder(&This
->IFileDialog2_iface
, psi
);
3132 static HRESULT WINAPI
IFileSaveDialog_fnSetFolder(IFileSaveDialog
*iface
, IShellItem
*psi
)
3134 FileDialogImpl
*This
= impl_from_IFileSaveDialog(iface
);
3135 return IFileDialog2_SetFolder(&This
->IFileDialog2_iface
, psi
);
3138 static HRESULT WINAPI
IFileSaveDialog_fnGetFolder(IFileSaveDialog
*iface
, IShellItem
**ppsi
)
3140 FileDialogImpl
*This
= impl_from_IFileSaveDialog(iface
);
3141 return IFileDialog2_GetFolder(&This
->IFileDialog2_iface
, ppsi
);
3144 static HRESULT WINAPI
IFileSaveDialog_fnGetCurrentSelection(IFileSaveDialog
*iface
, IShellItem
**ppsi
)
3146 FileDialogImpl
*This
= impl_from_IFileSaveDialog(iface
);
3147 return IFileDialog2_GetCurrentSelection(&This
->IFileDialog2_iface
, ppsi
);
3150 static HRESULT WINAPI
IFileSaveDialog_fnSetFileName(IFileSaveDialog
*iface
, LPCWSTR pszName
)
3152 FileDialogImpl
*This
= impl_from_IFileSaveDialog(iface
);
3153 return IFileDialog2_SetFileName(&This
->IFileDialog2_iface
, pszName
);
3156 static HRESULT WINAPI
IFileSaveDialog_fnGetFileName(IFileSaveDialog
*iface
, LPWSTR
*pszName
)
3158 FileDialogImpl
*This
= impl_from_IFileSaveDialog(iface
);
3159 return IFileDialog2_GetFileName(&This
->IFileDialog2_iface
, pszName
);
3162 static HRESULT WINAPI
IFileSaveDialog_fnSetTitle(IFileSaveDialog
*iface
, LPCWSTR pszTitle
)
3164 FileDialogImpl
*This
= impl_from_IFileSaveDialog(iface
);
3165 return IFileDialog2_SetTitle(&This
->IFileDialog2_iface
, pszTitle
);
3168 static HRESULT WINAPI
IFileSaveDialog_fnSetOkButtonLabel(IFileSaveDialog
*iface
, LPCWSTR pszText
)
3170 FileDialogImpl
*This
= impl_from_IFileSaveDialog(iface
);
3171 return IFileDialog2_SetOkButtonLabel(&This
->IFileDialog2_iface
, pszText
);
3174 static HRESULT WINAPI
IFileSaveDialog_fnSetFileNameLabel(IFileSaveDialog
*iface
, LPCWSTR pszLabel
)
3176 FileDialogImpl
*This
= impl_from_IFileSaveDialog(iface
);
3177 return IFileDialog2_SetFileNameLabel(&This
->IFileDialog2_iface
, pszLabel
);
3180 static HRESULT WINAPI
IFileSaveDialog_fnGetResult(IFileSaveDialog
*iface
, IShellItem
**ppsi
)
3182 FileDialogImpl
*This
= impl_from_IFileSaveDialog(iface
);
3183 return IFileDialog2_GetResult(&This
->IFileDialog2_iface
, ppsi
);
3186 static HRESULT WINAPI
IFileSaveDialog_fnAddPlace(IFileSaveDialog
*iface
, IShellItem
*psi
, FDAP fdap
)
3188 FileDialogImpl
*This
= impl_from_IFileSaveDialog(iface
);
3189 return IFileDialog2_AddPlace(&This
->IFileDialog2_iface
, psi
, fdap
);
3192 static HRESULT WINAPI
IFileSaveDialog_fnSetDefaultExtension(IFileSaveDialog
*iface
,
3193 LPCWSTR pszDefaultExtension
)
3195 FileDialogImpl
*This
= impl_from_IFileSaveDialog(iface
);
3196 return IFileDialog2_SetDefaultExtension(&This
->IFileDialog2_iface
, pszDefaultExtension
);
3199 static HRESULT WINAPI
IFileSaveDialog_fnClose(IFileSaveDialog
*iface
, HRESULT hr
)
3201 FileDialogImpl
*This
= impl_from_IFileSaveDialog(iface
);
3202 return IFileDialog2_Close(&This
->IFileDialog2_iface
, hr
);
3205 static HRESULT WINAPI
IFileSaveDialog_fnSetClientGuid(IFileSaveDialog
*iface
, REFGUID guid
)
3207 FileDialogImpl
*This
= impl_from_IFileSaveDialog(iface
);
3208 return IFileDialog2_SetClientGuid(&This
->IFileDialog2_iface
, guid
);
3211 static HRESULT WINAPI
IFileSaveDialog_fnClearClientData(IFileSaveDialog
*iface
)
3213 FileDialogImpl
*This
= impl_from_IFileSaveDialog(iface
);
3214 return IFileDialog2_ClearClientData(&This
->IFileDialog2_iface
);
3217 static HRESULT WINAPI
IFileSaveDialog_fnSetFilter(IFileSaveDialog
*iface
, IShellItemFilter
*pFilter
)
3219 FileDialogImpl
*This
= impl_from_IFileSaveDialog(iface
);
3220 return IFileDialog2_SetFilter(&This
->IFileDialog2_iface
, pFilter
);
3223 static HRESULT WINAPI
IFileSaveDialog_fnSetSaveAsItem(IFileSaveDialog
* iface
, IShellItem
*psi
)
3225 FileDialogImpl
*This
= impl_from_IFileSaveDialog(iface
);
3226 FIXME("stub - %p (%p)\n", This
, psi
);
3230 static HRESULT WINAPI
IFileSaveDialog_fnSetProperties(IFileSaveDialog
* iface
, IPropertyStore
*pStore
)
3232 FileDialogImpl
*This
= impl_from_IFileSaveDialog(iface
);
3233 FIXME("stub - %p (%p)\n", This
, pStore
);
3237 static HRESULT WINAPI
IFileSaveDialog_fnSetCollectedProperties(IFileSaveDialog
* iface
,
3238 IPropertyDescriptionList
*pList
,
3239 BOOL fAppendDefault
)
3241 FileDialogImpl
*This
= impl_from_IFileSaveDialog(iface
);
3242 FIXME("stub - %p (%p, %d)\n", This
, pList
, fAppendDefault
);
3246 static HRESULT WINAPI
IFileSaveDialog_fnGetProperties(IFileSaveDialog
* iface
, IPropertyStore
**ppStore
)
3248 FileDialogImpl
*This
= impl_from_IFileSaveDialog(iface
);
3249 FIXME("stub - %p (%p)\n", This
, ppStore
);
3253 static HRESULT WINAPI
IFileSaveDialog_fnApplyProperties(IFileSaveDialog
* iface
,
3255 IPropertyStore
*pStore
,
3257 IFileOperationProgressSink
*pSink
)
3259 FileDialogImpl
*This
= impl_from_IFileSaveDialog(iface
);
3260 FIXME("%p (%p, %p, %p, %p)\n", This
, psi
, pStore
, hwnd
, pSink
);
3264 static const IFileSaveDialogVtbl vt_IFileSaveDialog
= {
3265 IFileSaveDialog_fnQueryInterface
,
3266 IFileSaveDialog_fnAddRef
,
3267 IFileSaveDialog_fnRelease
,
3268 IFileSaveDialog_fnShow
,
3269 IFileSaveDialog_fnSetFileTypes
,
3270 IFileSaveDialog_fnSetFileTypeIndex
,
3271 IFileSaveDialog_fnGetFileTypeIndex
,
3272 IFileSaveDialog_fnAdvise
,
3273 IFileSaveDialog_fnUnadvise
,
3274 IFileSaveDialog_fnSetOptions
,
3275 IFileSaveDialog_fnGetOptions
,
3276 IFileSaveDialog_fnSetDefaultFolder
,
3277 IFileSaveDialog_fnSetFolder
,
3278 IFileSaveDialog_fnGetFolder
,
3279 IFileSaveDialog_fnGetCurrentSelection
,
3280 IFileSaveDialog_fnSetFileName
,
3281 IFileSaveDialog_fnGetFileName
,
3282 IFileSaveDialog_fnSetTitle
,
3283 IFileSaveDialog_fnSetOkButtonLabel
,
3284 IFileSaveDialog_fnSetFileNameLabel
,
3285 IFileSaveDialog_fnGetResult
,
3286 IFileSaveDialog_fnAddPlace
,
3287 IFileSaveDialog_fnSetDefaultExtension
,
3288 IFileSaveDialog_fnClose
,
3289 IFileSaveDialog_fnSetClientGuid
,
3290 IFileSaveDialog_fnClearClientData
,
3291 IFileSaveDialog_fnSetFilter
,
3292 IFileSaveDialog_fnSetSaveAsItem
,
3293 IFileSaveDialog_fnSetProperties
,
3294 IFileSaveDialog_fnSetCollectedProperties
,
3295 IFileSaveDialog_fnGetProperties
,
3296 IFileSaveDialog_fnApplyProperties
3299 /**************************************************************************
3300 * IExplorerBrowserEvents implementation
3302 static inline FileDialogImpl
*impl_from_IExplorerBrowserEvents(IExplorerBrowserEvents
*iface
)
3304 return CONTAINING_RECORD(iface
, FileDialogImpl
, IExplorerBrowserEvents_iface
);
3307 static HRESULT WINAPI
IExplorerBrowserEvents_fnQueryInterface(IExplorerBrowserEvents
*iface
,
3308 REFIID riid
, void **ppvObject
)
3310 FileDialogImpl
*This
= impl_from_IExplorerBrowserEvents(iface
);
3311 TRACE("%p (%s, %p)\n", This
, debugstr_guid(riid
), ppvObject
);
3313 return IFileDialog2_QueryInterface(&This
->IFileDialog2_iface
, riid
, ppvObject
);
3316 static ULONG WINAPI
IExplorerBrowserEvents_fnAddRef(IExplorerBrowserEvents
*iface
)
3318 FileDialogImpl
*This
= impl_from_IExplorerBrowserEvents(iface
);
3319 TRACE("%p\n", This
);
3320 return IFileDialog2_AddRef(&This
->IFileDialog2_iface
);
3323 static ULONG WINAPI
IExplorerBrowserEvents_fnRelease(IExplorerBrowserEvents
*iface
)
3325 FileDialogImpl
*This
= impl_from_IExplorerBrowserEvents(iface
);
3326 TRACE("%p\n", This
);
3327 return IFileDialog2_Release(&This
->IFileDialog2_iface
);
3330 static HRESULT WINAPI
IExplorerBrowserEvents_fnOnNavigationPending(IExplorerBrowserEvents
*iface
,
3331 PCIDLIST_ABSOLUTE pidlFolder
)
3333 FileDialogImpl
*This
= impl_from_IExplorerBrowserEvents(iface
);
3336 TRACE("%p (%p)\n", This
, pidlFolder
);
3338 hr
= SHCreateItemFromIDList(pidlFolder
, &IID_IShellItem
, (void**)&psi
);
3341 hr
= events_OnFolderChanging(This
, psi
);
3342 IShellItem_Release(psi
);
3344 /* The ExplorerBrowser treats S_FALSE as S_OK, we don't. */
3351 ERR("Failed to convert pidl (%p) to a shellitem.\n", pidlFolder
);
3356 static HRESULT WINAPI
IExplorerBrowserEvents_fnOnViewCreated(IExplorerBrowserEvents
*iface
,
3359 FileDialogImpl
*This
= impl_from_IExplorerBrowserEvents(iface
);
3360 TRACE("%p (%p)\n", This
, psv
);
3364 static HRESULT WINAPI
IExplorerBrowserEvents_fnOnNavigationComplete(IExplorerBrowserEvents
*iface
,
3365 PCIDLIST_ABSOLUTE pidlFolder
)
3367 FileDialogImpl
*This
= impl_from_IExplorerBrowserEvents(iface
);
3369 TRACE("%p (%p)\n", This
, pidlFolder
);
3371 if(This
->psi_folder
)
3372 IShellItem_Release(This
->psi_folder
);
3374 hr
= SHCreateItemFromIDList(pidlFolder
, &IID_IShellItem
, (void**)&This
->psi_folder
);
3377 ERR("Failed to get the current folder.\n");
3378 This
->psi_folder
= NULL
;
3381 events_OnFolderChange(This
);
3386 static HRESULT WINAPI
IExplorerBrowserEvents_fnOnNavigationFailed(IExplorerBrowserEvents
*iface
,
3387 PCIDLIST_ABSOLUTE pidlFolder
)
3389 FileDialogImpl
*This
= impl_from_IExplorerBrowserEvents(iface
);
3390 TRACE("%p (%p)\n", This
, pidlFolder
);
3394 static const IExplorerBrowserEventsVtbl vt_IExplorerBrowserEvents
= {
3395 IExplorerBrowserEvents_fnQueryInterface
,
3396 IExplorerBrowserEvents_fnAddRef
,
3397 IExplorerBrowserEvents_fnRelease
,
3398 IExplorerBrowserEvents_fnOnNavigationPending
,
3399 IExplorerBrowserEvents_fnOnViewCreated
,
3400 IExplorerBrowserEvents_fnOnNavigationComplete
,
3401 IExplorerBrowserEvents_fnOnNavigationFailed
3404 /**************************************************************************
3405 * IServiceProvider implementation
3407 static inline FileDialogImpl
*impl_from_IServiceProvider(IServiceProvider
*iface
)
3409 return CONTAINING_RECORD(iface
, FileDialogImpl
, IServiceProvider_iface
);
3412 static HRESULT WINAPI
IServiceProvider_fnQueryInterface(IServiceProvider
*iface
,
3413 REFIID riid
, void **ppvObject
)
3415 FileDialogImpl
*This
= impl_from_IServiceProvider(iface
);
3416 TRACE("%p\n", This
);
3417 return IFileDialog2_QueryInterface(&This
->IFileDialog2_iface
, riid
, ppvObject
);
3420 static ULONG WINAPI
IServiceProvider_fnAddRef(IServiceProvider
*iface
)
3422 FileDialogImpl
*This
= impl_from_IServiceProvider(iface
);
3423 TRACE("%p\n", This
);
3424 return IFileDialog2_AddRef(&This
->IFileDialog2_iface
);
3427 static ULONG WINAPI
IServiceProvider_fnRelease(IServiceProvider
*iface
)
3429 FileDialogImpl
*This
= impl_from_IServiceProvider(iface
);
3430 TRACE("%p\n", This
);
3431 return IFileDialog2_Release(&This
->IFileDialog2_iface
);
3434 static HRESULT WINAPI
IServiceProvider_fnQueryService(IServiceProvider
*iface
,
3435 REFGUID guidService
,
3436 REFIID riid
, void **ppv
)
3438 FileDialogImpl
*This
= impl_from_IServiceProvider(iface
);
3439 HRESULT hr
= E_NOTIMPL
;
3440 TRACE("%p (%s, %s, %p)\n", This
, debugstr_guid(guidService
), debugstr_guid(riid
), ppv
);
3443 if(IsEqualGUID(guidService
, &SID_STopLevelBrowser
) && This
->peb
)
3444 hr
= IExplorerBrowser_QueryInterface(This
->peb
, riid
, ppv
);
3445 else if(IsEqualGUID(guidService
, &SID_SExplorerBrowserFrame
))
3446 hr
= IFileDialog2_QueryInterface(&This
->IFileDialog2_iface
, riid
, ppv
);
3448 FIXME("Interface %s requested from unknown service %s\n",
3449 debugstr_guid(riid
), debugstr_guid(guidService
));
3454 static const IServiceProviderVtbl vt_IServiceProvider
= {
3455 IServiceProvider_fnQueryInterface
,
3456 IServiceProvider_fnAddRef
,
3457 IServiceProvider_fnRelease
,
3458 IServiceProvider_fnQueryService
3461 /**************************************************************************
3462 * ICommDlgBrowser3 implementation
3464 static inline FileDialogImpl
*impl_from_ICommDlgBrowser3(ICommDlgBrowser3
*iface
)
3466 return CONTAINING_RECORD(iface
, FileDialogImpl
, ICommDlgBrowser3_iface
);
3469 static HRESULT WINAPI
ICommDlgBrowser3_fnQueryInterface(ICommDlgBrowser3
*iface
,
3470 REFIID riid
, void **ppvObject
)
3472 FileDialogImpl
*This
= impl_from_ICommDlgBrowser3(iface
);
3473 TRACE("%p\n", This
);
3474 return IFileDialog2_QueryInterface(&This
->IFileDialog2_iface
, riid
, ppvObject
);
3477 static ULONG WINAPI
ICommDlgBrowser3_fnAddRef(ICommDlgBrowser3
*iface
)
3479 FileDialogImpl
*This
= impl_from_ICommDlgBrowser3(iface
);
3480 TRACE("%p\n", This
);
3481 return IFileDialog2_AddRef(&This
->IFileDialog2_iface
);
3484 static ULONG WINAPI
ICommDlgBrowser3_fnRelease(ICommDlgBrowser3
*iface
)
3486 FileDialogImpl
*This
= impl_from_ICommDlgBrowser3(iface
);
3487 TRACE("%p\n", This
);
3488 return IFileDialog2_Release(&This
->IFileDialog2_iface
);
3491 static HRESULT WINAPI
ICommDlgBrowser3_fnOnDefaultCommand(ICommDlgBrowser3
*iface
,
3494 FileDialogImpl
*This
= impl_from_ICommDlgBrowser3(iface
);
3496 TRACE("%p (%p)\n", This
, shv
);
3498 hr
= on_default_action(This
);
3501 EndDialog(This
->dlg_hwnd
, S_OK
);
3506 static HRESULT WINAPI
ICommDlgBrowser3_fnOnStateChange(ICommDlgBrowser3
*iface
,
3507 IShellView
*shv
, ULONG uChange
)
3509 FileDialogImpl
*This
= impl_from_ICommDlgBrowser3(iface
);
3510 IDataObject
*new_selection
;
3512 TRACE("%p (%p, %x)\n", This
, shv
, uChange
);
3516 case CDBOSC_SELCHANGE
:
3517 if(This
->psia_selection
)
3519 IShellItemArray_Release(This
->psia_selection
);
3520 This
->psia_selection
= NULL
;
3523 hr
= IShellView_GetItemObject(shv
, SVGIO_SELECTION
, &IID_IDataObject
, (void**)&new_selection
);
3526 hr
= SHCreateShellItemArrayFromDataObject(new_selection
, &IID_IShellItemArray
,
3527 (void**)&This
->psia_selection
);
3530 fill_filename_from_selection(This
);
3531 events_OnSelectionChange(This
);
3534 IDataObject_Release(new_selection
);
3538 TRACE("Unhandled state change\n");
3543 static HRESULT WINAPI
ICommDlgBrowser3_fnIncludeObject(ICommDlgBrowser3
*iface
,
3544 IShellView
*shv
, LPCITEMIDLIST pidl
)
3546 FileDialogImpl
*This
= impl_from_ICommDlgBrowser3(iface
);
3549 LPITEMIDLIST parent_pidl
;
3552 TRACE("%p (%p, %p)\n", This
, shv
, pidl
);
3554 if(!This
->filterspec_count
&& !(This
->options
& FOS_PICKFOLDERS
))
3557 hr
= SHGetIDListFromObject((IUnknown
*)shv
, &parent_pidl
);
3560 LPITEMIDLIST full_pidl
= ILCombine(parent_pidl
, pidl
);
3561 hr
= SHCreateItemFromIDList(full_pidl
, &IID_IShellItem
, (void**)&psi
);
3562 ILFree(parent_pidl
);
3567 ERR("Failed to get shellitem (%08x).\n", hr
);
3571 hr
= IShellItem_GetAttributes(psi
, SFGAO_FOLDER
|SFGAO_LINK
, &attr
);
3572 if(FAILED(hr
) || (attr
& (SFGAO_FOLDER
| SFGAO_LINK
)))
3574 IShellItem_Release(psi
);
3578 if((This
->options
& FOS_PICKFOLDERS
) && !(attr
& (SFGAO_FOLDER
| SFGAO_LINK
)))
3580 IShellItem_Release(psi
);
3585 if(SUCCEEDED(IShellItem_GetDisplayName(psi
, SIGDN_PARENTRELATIVEPARSING
, &filename
)))
3587 if(!PathMatchSpecW(filename
, This
->filterspecs
[This
->filetypeindex
].pszSpec
))
3589 CoTaskMemFree(filename
);
3592 IShellItem_Release(psi
);
3596 static HRESULT WINAPI
ICommDlgBrowser3_fnNotify(ICommDlgBrowser3
*iface
,
3597 IShellView
*ppshv
, DWORD dwNotifyType
)
3599 FileDialogImpl
*This
= impl_from_ICommDlgBrowser3(iface
);
3600 FIXME("Stub: %p (%p, 0x%x)\n", This
, ppshv
, dwNotifyType
);
3604 static HRESULT WINAPI
ICommDlgBrowser3_fnGetDefaultMenuText(ICommDlgBrowser3
*iface
,
3606 LPWSTR pszText
, int cchMax
)
3608 FileDialogImpl
*This
= impl_from_ICommDlgBrowser3(iface
);
3609 FIXME("Stub: %p (%p, %p, %d)\n", This
, pshv
, pszText
, cchMax
);
3613 static HRESULT WINAPI
ICommDlgBrowser3_fnGetViewFlags(ICommDlgBrowser3
*iface
, DWORD
*pdwFlags
)
3615 FileDialogImpl
*This
= impl_from_ICommDlgBrowser3(iface
);
3616 FIXME("Stub: %p (%p)\n", This
, pdwFlags
);
3620 static HRESULT WINAPI
ICommDlgBrowser3_fnOnColumnClicked(ICommDlgBrowser3
*iface
,
3621 IShellView
*pshv
, int iColumn
)
3623 FileDialogImpl
*This
= impl_from_ICommDlgBrowser3(iface
);
3624 FIXME("Stub: %p (%p, %d)\n", This
, pshv
, iColumn
);
3628 static HRESULT WINAPI
ICommDlgBrowser3_fnGetCurrentFilter(ICommDlgBrowser3
*iface
,
3629 LPWSTR pszFileSpec
, int cchFileSpec
)
3631 FileDialogImpl
*This
= impl_from_ICommDlgBrowser3(iface
);
3632 FIXME("Stub: %p (%p, %d)\n", This
, pszFileSpec
, cchFileSpec
);
3636 static HRESULT WINAPI
ICommDlgBrowser3_fnOnPreviewCreated(ICommDlgBrowser3
*iface
,
3639 FileDialogImpl
*This
= impl_from_ICommDlgBrowser3(iface
);
3640 FIXME("Stub: %p (%p)\n", This
, pshv
);
3644 static const ICommDlgBrowser3Vtbl vt_ICommDlgBrowser3
= {
3645 ICommDlgBrowser3_fnQueryInterface
,
3646 ICommDlgBrowser3_fnAddRef
,
3647 ICommDlgBrowser3_fnRelease
,
3648 ICommDlgBrowser3_fnOnDefaultCommand
,
3649 ICommDlgBrowser3_fnOnStateChange
,
3650 ICommDlgBrowser3_fnIncludeObject
,
3651 ICommDlgBrowser3_fnNotify
,
3652 ICommDlgBrowser3_fnGetDefaultMenuText
,
3653 ICommDlgBrowser3_fnGetViewFlags
,
3654 ICommDlgBrowser3_fnOnColumnClicked
,
3655 ICommDlgBrowser3_fnGetCurrentFilter
,
3656 ICommDlgBrowser3_fnOnPreviewCreated
3659 /**************************************************************************
3660 * IOleWindow implementation
3662 static inline FileDialogImpl
*impl_from_IOleWindow(IOleWindow
*iface
)
3664 return CONTAINING_RECORD(iface
, FileDialogImpl
, IOleWindow_iface
);
3667 static HRESULT WINAPI
IOleWindow_fnQueryInterface(IOleWindow
*iface
, REFIID riid
, void **ppvObject
)
3669 FileDialogImpl
*This
= impl_from_IOleWindow(iface
);
3670 return IFileDialog2_QueryInterface(&This
->IFileDialog2_iface
, riid
, ppvObject
);
3673 static ULONG WINAPI
IOleWindow_fnAddRef(IOleWindow
*iface
)
3675 FileDialogImpl
*This
= impl_from_IOleWindow(iface
);
3676 return IFileDialog2_AddRef(&This
->IFileDialog2_iface
);
3679 static ULONG WINAPI
IOleWindow_fnRelease(IOleWindow
*iface
)
3681 FileDialogImpl
*This
= impl_from_IOleWindow(iface
);
3682 return IFileDialog2_Release(&This
->IFileDialog2_iface
);
3685 static HRESULT WINAPI
IOleWindow_fnContextSensitiveHelp(IOleWindow
*iface
, BOOL fEnterMOde
)
3687 FileDialogImpl
*This
= impl_from_IOleWindow(iface
);
3688 FIXME("Stub: %p (%d)\n", This
, fEnterMOde
);
3692 static HRESULT WINAPI
IOleWindow_fnGetWindow(IOleWindow
*iface
, HWND
*phwnd
)
3694 FileDialogImpl
*This
= impl_from_IOleWindow(iface
);
3695 TRACE("%p (%p)\n", This
, phwnd
);
3696 *phwnd
= This
->dlg_hwnd
;
3700 static const IOleWindowVtbl vt_IOleWindow
= {
3701 IOleWindow_fnQueryInterface
,
3702 IOleWindow_fnAddRef
,
3703 IOleWindow_fnRelease
,
3704 IOleWindow_fnGetWindow
,
3705 IOleWindow_fnContextSensitiveHelp
3708 /**************************************************************************
3709 * IFileDialogCustomize implementation
3711 static inline FileDialogImpl
*impl_from_IFileDialogCustomize(IFileDialogCustomize
*iface
)
3713 return CONTAINING_RECORD(iface
, FileDialogImpl
, IFileDialogCustomize_iface
);
3716 static HRESULT WINAPI
IFileDialogCustomize_fnQueryInterface(IFileDialogCustomize
*iface
,
3717 REFIID riid
, void **ppvObject
)
3719 FileDialogImpl
*This
= impl_from_IFileDialogCustomize(iface
);
3720 return IFileDialog2_QueryInterface(&This
->IFileDialog2_iface
, riid
, ppvObject
);
3723 static ULONG WINAPI
IFileDialogCustomize_fnAddRef(IFileDialogCustomize
*iface
)
3725 FileDialogImpl
*This
= impl_from_IFileDialogCustomize(iface
);
3726 return IFileDialog2_AddRef(&This
->IFileDialog2_iface
);
3729 static ULONG WINAPI
IFileDialogCustomize_fnRelease(IFileDialogCustomize
*iface
)
3731 FileDialogImpl
*This
= impl_from_IFileDialogCustomize(iface
);
3732 return IFileDialog2_Release(&This
->IFileDialog2_iface
);
3735 static HRESULT WINAPI
IFileDialogCustomize_fnEnableOpenDropDown(IFileDialogCustomize
*iface
,
3738 FileDialogImpl
*This
= impl_from_IFileDialogCustomize(iface
);
3740 TRACE("%p (%d)\n", This
, dwIDCtl
);
3742 if (This
->hmenu_opendropdown
|| get_cctrl(This
, dwIDCtl
))
3743 return E_UNEXPECTED
;
3745 This
->hmenu_opendropdown
= CreatePopupMenu();
3747 if (!This
->hmenu_opendropdown
)
3748 return E_OUTOFMEMORY
;
3750 mi
.cbSize
= sizeof(mi
);
3751 mi
.fMask
= MIM_STYLE
;
3752 mi
.dwStyle
= MNS_NOTIFYBYPOS
;
3753 SetMenuInfo(This
->hmenu_opendropdown
, &mi
);
3755 This
->cctrl_opendropdown
.hwnd
= NULL
;
3756 This
->cctrl_opendropdown
.wrapper_hwnd
= NULL
;
3757 This
->cctrl_opendropdown
.id
= dwIDCtl
;
3758 This
->cctrl_opendropdown
.dlgid
= 0;
3759 This
->cctrl_opendropdown
.type
= IDLG_CCTRL_OPENDROPDOWN
;
3760 This
->cctrl_opendropdown
.cdcstate
= CDCS_ENABLED
| CDCS_VISIBLE
;
3761 list_init(&This
->cctrl_opendropdown
.sub_cctrls
);
3762 list_init(&This
->cctrl_opendropdown
.sub_items
);
3767 static HRESULT WINAPI
IFileDialogCustomize_fnAddMenu(IFileDialogCustomize
*iface
,
3771 FileDialogImpl
*This
= impl_from_IFileDialogCustomize(iface
);
3775 TRACE("%p (%d, %p)\n", This
, dwIDCtl
, pszLabel
);
3777 hr
= cctrl_create_new(This
, dwIDCtl
, NULL
, TOOLBARCLASSNAMEW
,
3778 TBSTYLE_FLAT
| CCS_NODIVIDER
, 0,
3779 This
->cctrl_def_height
, &ctrl
);
3782 SendMessageW(ctrl
->hwnd
, TB_BUTTONSTRUCTSIZE
, sizeof(tbb
), 0);
3783 ctrl
->type
= IDLG_CCTRL_MENU
;
3785 /* Add the actual button with a popup menu. */
3786 tbb
.iBitmap
= I_IMAGENONE
;
3787 tbb
.dwData
= (DWORD_PTR
)CreatePopupMenu();
3788 tbb
.iString
= (DWORD_PTR
)pszLabel
;
3789 tbb
.fsState
= TBSTATE_ENABLED
;
3790 tbb
.fsStyle
= BTNS_WHOLEDROPDOWN
;
3793 SendMessageW(ctrl
->hwnd
, TB_ADDBUTTONSW
, 1, (LPARAM
)&tbb
);
3799 static HRESULT WINAPI
IFileDialogCustomize_fnAddPushButton(IFileDialogCustomize
*iface
,
3803 FileDialogImpl
*This
= impl_from_IFileDialogCustomize(iface
);
3806 TRACE("%p (%d, %p)\n", This
, dwIDCtl
, pszLabel
);
3808 hr
= cctrl_create_new(This
, dwIDCtl
, pszLabel
, WC_BUTTONW
, BS_MULTILINE
, 0,
3809 This
->cctrl_def_height
, &ctrl
);
3811 ctrl
->type
= IDLG_CCTRL_PUSHBUTTON
;
3816 static HRESULT WINAPI
IFileDialogCustomize_fnAddComboBox(IFileDialogCustomize
*iface
,
3819 FileDialogImpl
*This
= impl_from_IFileDialogCustomize(iface
);
3822 TRACE("%p (%d)\n", This
, dwIDCtl
);
3824 hr
= cctrl_create_new(This
, dwIDCtl
, NULL
, WC_COMBOBOXW
, CBS_DROPDOWNLIST
, 0,
3825 This
->cctrl_def_height
, &ctrl
);
3827 ctrl
->type
= IDLG_CCTRL_COMBOBOX
;
3832 static HRESULT WINAPI
IFileDialogCustomize_fnAddRadioButtonList(IFileDialogCustomize
*iface
,
3835 FileDialogImpl
*This
= impl_from_IFileDialogCustomize(iface
);
3838 TRACE("%p (%d)\n", This
, dwIDCtl
);
3840 hr
= cctrl_create_new(This
, dwIDCtl
, NULL
, radiobuttonlistW
, 0, 0, 0, &ctrl
);
3843 ctrl
->type
= IDLG_CCTRL_RADIOBUTTONLIST
;
3844 SetWindowLongPtrW(ctrl
->hwnd
, GWLP_USERDATA
, (LPARAM
)This
);
3850 static HRESULT WINAPI
IFileDialogCustomize_fnAddCheckButton(IFileDialogCustomize
*iface
,
3855 FileDialogImpl
*This
= impl_from_IFileDialogCustomize(iface
);
3858 TRACE("%p (%d, %p, %d)\n", This
, dwIDCtl
, pszLabel
, bChecked
);
3860 hr
= cctrl_create_new(This
, dwIDCtl
, pszLabel
, WC_BUTTONW
, BS_AUTOCHECKBOX
|BS_MULTILINE
, 0,
3861 This
->cctrl_def_height
, &ctrl
);
3864 ctrl
->type
= IDLG_CCTRL_CHECKBUTTON
;
3865 SendMessageW(ctrl
->hwnd
, BM_SETCHECK
, bChecked
? BST_CHECKED
: BST_UNCHECKED
, 0);
3871 static HRESULT WINAPI
IFileDialogCustomize_fnAddEditBox(IFileDialogCustomize
*iface
,
3875 FileDialogImpl
*This
= impl_from_IFileDialogCustomize(iface
);
3878 TRACE("%p (%d, %p)\n", This
, dwIDCtl
, pszText
);
3880 hr
= cctrl_create_new(This
, dwIDCtl
, pszText
, WC_EDITW
, ES_AUTOHSCROLL
, WS_EX_CLIENTEDGE
,
3881 This
->cctrl_def_height
, &ctrl
);
3883 ctrl
->type
= IDLG_CCTRL_EDITBOX
;
3888 static HRESULT WINAPI
IFileDialogCustomize_fnAddSeparator(IFileDialogCustomize
*iface
,
3891 FileDialogImpl
*This
= impl_from_IFileDialogCustomize(iface
);
3894 TRACE("%p (%d)\n", This
, dwIDCtl
);
3896 hr
= cctrl_create_new(This
, dwIDCtl
, NULL
, WC_STATICW
, SS_ETCHEDHORZ
, 0,
3897 GetSystemMetrics(SM_CYEDGE
), &ctrl
);
3899 ctrl
->type
= IDLG_CCTRL_SEPARATOR
;
3904 static HRESULT WINAPI
IFileDialogCustomize_fnAddText(IFileDialogCustomize
*iface
,
3908 FileDialogImpl
*This
= impl_from_IFileDialogCustomize(iface
);
3911 TRACE("%p (%d, %p)\n", This
, dwIDCtl
, pszText
);
3913 hr
= cctrl_create_new(This
, dwIDCtl
, pszText
, WC_STATICW
, 0, 0,
3914 This
->cctrl_def_height
, &ctrl
);
3916 ctrl
->type
= IDLG_CCTRL_TEXT
;
3921 static HRESULT WINAPI
IFileDialogCustomize_fnSetControlLabel(IFileDialogCustomize
*iface
,
3925 FileDialogImpl
*This
= impl_from_IFileDialogCustomize(iface
);
3926 customctrl
*ctrl
= get_cctrl(This
, dwIDCtl
);
3927 TRACE("%p (%d, %p)\n", This
, dwIDCtl
, pszLabel
);
3929 if(!ctrl
) return E_INVALIDARG
;
3933 case IDLG_CCTRL_MENU
:
3934 case IDLG_CCTRL_PUSHBUTTON
:
3935 case IDLG_CCTRL_CHECKBUTTON
:
3936 case IDLG_CCTRL_TEXT
:
3937 case IDLG_CCTRL_VISUALGROUP
:
3938 SendMessageW(ctrl
->hwnd
, WM_SETTEXT
, 0, (LPARAM
)pszLabel
);
3940 case IDLG_CCTRL_OPENDROPDOWN
:
3949 static HRESULT WINAPI
IFileDialogCustomize_fnGetControlState(IFileDialogCustomize
*iface
,
3951 CDCONTROLSTATEF
*pdwState
)
3953 FileDialogImpl
*This
= impl_from_IFileDialogCustomize(iface
);
3954 customctrl
*ctrl
= get_cctrl(This
, dwIDCtl
);
3955 TRACE("%p (%d, %p)\n", This
, dwIDCtl
, pdwState
);
3957 if(!ctrl
|| ctrl
->type
== IDLG_CCTRL_OPENDROPDOWN
) return E_NOTIMPL
;
3959 *pdwState
= ctrl
->cdcstate
;
3963 static HRESULT WINAPI
IFileDialogCustomize_fnSetControlState(IFileDialogCustomize
*iface
,
3965 CDCONTROLSTATEF dwState
)
3967 FileDialogImpl
*This
= impl_from_IFileDialogCustomize(iface
);
3968 customctrl
*ctrl
= get_cctrl(This
,dwIDCtl
);
3969 TRACE("%p (%d, %x)\n", This
, dwIDCtl
, dwState
);
3971 if(ctrl
&& ctrl
->hwnd
)
3973 LONG wndstyle
= GetWindowLongW(ctrl
->hwnd
, GWL_STYLE
);
3975 if(dwState
& CDCS_ENABLED
)
3976 wndstyle
&= ~(WS_DISABLED
);
3978 wndstyle
|= WS_DISABLED
;
3980 if(dwState
& CDCS_VISIBLE
)
3981 wndstyle
|= WS_VISIBLE
;
3983 wndstyle
&= ~(WS_VISIBLE
);
3985 SetWindowLongW(ctrl
->hwnd
, GWL_STYLE
, wndstyle
);
3987 /* We save the state separately since at least one application
3988 * relies on being able to hide a control. */
3989 ctrl
->cdcstate
= dwState
;
3995 static HRESULT WINAPI
IFileDialogCustomize_fnGetEditBoxText(IFileDialogCustomize
*iface
,
3999 FileDialogImpl
*This
= impl_from_IFileDialogCustomize(iface
);
4000 customctrl
*ctrl
= get_cctrl(This
, dwIDCtl
);
4002 TRACE("%p (%d, %p)\n", This
, dwIDCtl
, ppszText
);
4004 if(!ctrl
|| !ctrl
->hwnd
|| !(len
= SendMessageW(ctrl
->hwnd
, WM_GETTEXTLENGTH
, 0, 0)))
4007 text
= CoTaskMemAlloc(sizeof(WCHAR
)*(len
+1));
4008 if(!text
) return E_FAIL
;
4010 SendMessageW(ctrl
->hwnd
, WM_GETTEXT
, len
+1, (LPARAM
)text
);
4015 static HRESULT WINAPI
IFileDialogCustomize_fnSetEditBoxText(IFileDialogCustomize
*iface
,
4019 FileDialogImpl
*This
= impl_from_IFileDialogCustomize(iface
);
4020 customctrl
*ctrl
= get_cctrl(This
, dwIDCtl
);
4021 TRACE("%p (%d, %s)\n", This
, dwIDCtl
, debugstr_w(pszText
));
4023 if(!ctrl
|| ctrl
->type
!= IDLG_CCTRL_EDITBOX
)
4026 SendMessageW(ctrl
->hwnd
, WM_SETTEXT
, 0, (LPARAM
)pszText
);
4030 static HRESULT WINAPI
IFileDialogCustomize_fnGetCheckButtonState(IFileDialogCustomize
*iface
,
4034 FileDialogImpl
*This
= impl_from_IFileDialogCustomize(iface
);
4035 customctrl
*ctrl
= get_cctrl(This
, dwIDCtl
);
4036 TRACE("%p (%d, %p)\n", This
, dwIDCtl
, pbChecked
);
4038 if(ctrl
&& ctrl
->hwnd
)
4039 *pbChecked
= (SendMessageW(ctrl
->hwnd
, BM_GETCHECK
, 0, 0) == BST_CHECKED
);
4044 static HRESULT WINAPI
IFileDialogCustomize_fnSetCheckButtonState(IFileDialogCustomize
*iface
,
4048 FileDialogImpl
*This
= impl_from_IFileDialogCustomize(iface
);
4049 customctrl
*ctrl
= get_cctrl(This
, dwIDCtl
);
4050 TRACE("%p (%d, %d)\n", This
, dwIDCtl
, bChecked
);
4052 if(ctrl
&& ctrl
->hwnd
)
4053 SendMessageW(ctrl
->hwnd
, BM_SETCHECK
, bChecked
? BST_CHECKED
:BST_UNCHECKED
, 0);
4058 static UINT
get_combobox_index_from_id(HWND cb_hwnd
, DWORD dwIDItem
)
4060 UINT count
= SendMessageW(cb_hwnd
, CB_GETCOUNT
, 0, 0);
4062 if(!count
|| (count
== CB_ERR
))
4065 for(i
= 0; i
< count
; i
++)
4066 if(SendMessageW(cb_hwnd
, CB_GETITEMDATA
, i
, 0) == dwIDItem
)
4069 TRACE("Item with id %d not found in combobox %p (item count: %d)\n", dwIDItem
, cb_hwnd
, count
);
4073 static HRESULT WINAPI
IFileDialogCustomize_fnAddControlItem(IFileDialogCustomize
*iface
,
4078 FileDialogImpl
*This
= impl_from_IFileDialogCustomize(iface
);
4079 customctrl
*ctrl
= get_cctrl(This
, dwIDCtl
);
4081 TRACE("%p (%d, %d, %s)\n", This
, dwIDCtl
, dwIDItem
, debugstr_w(pszLabel
));
4083 if(!ctrl
) return E_FAIL
;
4087 case IDLG_CCTRL_COMBOBOX
:
4092 hr
= add_item(ctrl
, dwIDItem
, pszLabel
, &item
);
4094 if (FAILED(hr
)) return hr
;
4096 index
= SendMessageW(ctrl
->hwnd
, CB_ADDSTRING
, 0, (LPARAM
)pszLabel
);
4097 SendMessageW(ctrl
->hwnd
, CB_SETITEMDATA
, index
, dwIDItem
);
4101 case IDLG_CCTRL_MENU
:
4102 case IDLG_CCTRL_OPENDROPDOWN
:
4107 hr
= add_item(ctrl
, dwIDItem
, pszLabel
, &item
);
4109 if (FAILED(hr
)) return hr
;
4111 if (ctrl
->type
== IDLG_CCTRL_MENU
)
4114 SendMessageW(ctrl
->hwnd
, TB_GETBUTTON
, 0, (LPARAM
)&tbb
);
4115 hmenu
= (HMENU
)tbb
.dwData
;
4117 else /* ctrl->type == IDLG_CCTRL_OPENDROPDOWN */
4118 hmenu
= This
->hmenu_opendropdown
;
4120 AppendMenuW(hmenu
, MF_STRING
, dwIDItem
, pszLabel
);
4123 case IDLG_CCTRL_RADIOBUTTONLIST
:
4127 hr
= add_item(ctrl
, dwIDItem
, pszLabel
, &item
);
4131 item
->hwnd
= CreateWindowExW(0, WC_BUTTONW
, pszLabel
,
4132 WS_CHILD
|WS_VISIBLE
|WS_CLIPSIBLINGS
|BS_RADIOBUTTON
|BS_MULTILINE
,
4133 0, 0, 0, 0, ctrl
->hwnd
, ULongToHandle(dwIDItem
), COMDLG32_hInstance
, 0);
4137 ERR("Failed to create radio button\n");
4138 list_remove(&item
->entry
);
4150 return E_NOINTERFACE
; /* win7 */
4153 static HRESULT WINAPI
IFileDialogCustomize_fnRemoveControlItem(IFileDialogCustomize
*iface
,
4157 FileDialogImpl
*This
= impl_from_IFileDialogCustomize(iface
);
4158 customctrl
*ctrl
= get_cctrl(This
, dwIDCtl
);
4159 TRACE("%p (%d, %d)\n", This
, dwIDCtl
, dwIDItem
);
4161 if(!ctrl
) return E_FAIL
;
4165 case IDLG_CCTRL_COMBOBOX
:
4170 item
= get_item(ctrl
, dwIDItem
, CDCS_VISIBLE
|CDCS_ENABLED
, &position
);
4172 if ((item
->cdcstate
& (CDCS_VISIBLE
|CDCS_ENABLED
)) == (CDCS_VISIBLE
|CDCS_ENABLED
))
4174 if(SendMessageW(ctrl
->hwnd
, CB_DELETESTRING
, position
, 0) == CB_ERR
)
4178 list_remove(&item
->entry
);
4183 case IDLG_CCTRL_MENU
:
4184 case IDLG_CCTRL_OPENDROPDOWN
:
4189 item
= get_item(ctrl
, dwIDItem
, 0, NULL
);
4192 return E_UNEXPECTED
;
4194 if (item
->cdcstate
& CDCS_VISIBLE
)
4196 if (ctrl
->type
== IDLG_CCTRL_MENU
)
4199 SendMessageW(ctrl
->hwnd
, TB_GETBUTTON
, 0, (LPARAM
)&tbb
);
4200 hmenu
= (HMENU
)tbb
.dwData
;
4202 else /* ctrl->type == IDLG_CCTRL_OPENDROPDOWN */
4203 hmenu
= This
->hmenu_opendropdown
;
4205 if(!hmenu
|| !DeleteMenu(hmenu
, dwIDItem
, MF_BYCOMMAND
))
4206 return E_UNEXPECTED
;
4209 list_remove(&item
->entry
);
4214 case IDLG_CCTRL_RADIOBUTTONLIST
:
4218 item
= get_item(ctrl
, dwIDItem
, 0, NULL
);
4221 return E_UNEXPECTED
;
4223 list_remove(&item
->entry
);
4235 static HRESULT WINAPI
IFileDialogCustomize_fnRemoveAllControlItems(IFileDialogCustomize
*iface
,
4238 FileDialogImpl
*This
= impl_from_IFileDialogCustomize(iface
);
4239 TRACE("%p (%d)\n", This
, dwIDCtl
);
4241 /* Not implemented by native */
4245 static HRESULT WINAPI
IFileDialogCustomize_fnGetControlItemState(IFileDialogCustomize
*iface
,
4248 CDCONTROLSTATEF
*pdwState
)
4250 FileDialogImpl
*This
= impl_from_IFileDialogCustomize(iface
);
4251 customctrl
*ctrl
= get_cctrl(This
, dwIDCtl
);
4252 TRACE("%p (%d, %d, %p)\n", This
, dwIDCtl
, dwIDItem
, pdwState
);
4254 if(!ctrl
) return E_FAIL
;
4258 case IDLG_CCTRL_COMBOBOX
:
4259 case IDLG_CCTRL_MENU
:
4260 case IDLG_CCTRL_OPENDROPDOWN
:
4261 case IDLG_CCTRL_RADIOBUTTONLIST
:
4265 item
= get_item(ctrl
, dwIDItem
, 0, NULL
);
4268 return E_UNEXPECTED
;
4270 *pdwState
= item
->cdcstate
;
4281 static HRESULT WINAPI
IFileDialogCustomize_fnSetControlItemState(IFileDialogCustomize
*iface
,
4284 CDCONTROLSTATEF dwState
)
4286 FileDialogImpl
*This
= impl_from_IFileDialogCustomize(iface
);
4287 customctrl
*ctrl
= get_cctrl(This
, dwIDCtl
);
4288 TRACE("%p (%d, %d, %x)\n", This
, dwIDCtl
, dwIDItem
, dwState
);
4290 if(!ctrl
) return E_FAIL
;
4294 case IDLG_CCTRL_COMBOBOX
:
4297 BOOL visible
, was_visible
;
4300 item
= get_item(ctrl
, dwIDItem
, CDCS_VISIBLE
|CDCS_ENABLED
, &position
);
4303 return E_UNEXPECTED
;
4305 visible
= ((dwState
& (CDCS_VISIBLE
|CDCS_ENABLED
)) == (CDCS_VISIBLE
|CDCS_ENABLED
));
4306 was_visible
= ((item
->cdcstate
& (CDCS_VISIBLE
|CDCS_ENABLED
)) == (CDCS_VISIBLE
|CDCS_ENABLED
));
4308 if (visible
&& !was_visible
)
4310 SendMessageW(ctrl
->hwnd
, CB_INSERTSTRING
, position
, (LPARAM
)item
->label
);
4311 SendMessageW(ctrl
->hwnd
, CB_SETITEMDATA
, position
, dwIDItem
);
4313 else if (!visible
&& was_visible
)
4315 SendMessageW(ctrl
->hwnd
, CB_DELETESTRING
, position
, 0);
4318 item
->cdcstate
= dwState
;
4322 case IDLG_CCTRL_MENU
:
4323 case IDLG_CCTRL_OPENDROPDOWN
:
4327 CDCONTROLSTATEF prev_state
;
4330 item
= get_item(ctrl
, dwIDItem
, CDCS_VISIBLE
, &position
);
4333 return E_UNEXPECTED
;
4335 prev_state
= item
->cdcstate
;
4337 if (ctrl
->type
== IDLG_CCTRL_MENU
)
4340 SendMessageW(ctrl
->hwnd
, TB_GETBUTTON
, 0, (LPARAM
)&tbb
);
4341 hmenu
= (HMENU
)tbb
.dwData
;
4343 else /* ctrl->type == IDLG_CCTRL_OPENDROPDOWN */
4344 hmenu
= This
->hmenu_opendropdown
;
4346 if (dwState
& CDCS_VISIBLE
)
4348 if (prev_state
& CDCS_VISIBLE
)
4351 EnableMenuItem(hmenu
, dwIDItem
,
4352 MF_BYCOMMAND
|((dwState
& CDCS_ENABLED
) ? MFS_ENABLED
: MFS_DISABLED
));
4359 mii
.cbSize
= sizeof(mii
);
4360 mii
.fMask
= MIIM_ID
|MIIM_STATE
|MIIM_STRING
;
4361 mii
.fState
= (dwState
& CDCS_ENABLED
) ? MFS_ENABLED
: MFS_DISABLED
;
4363 mii
.dwTypeData
= item
->label
;
4365 InsertMenuItemW(hmenu
, position
, TRUE
, &mii
);
4368 else if (prev_state
& CDCS_VISIBLE
)
4371 DeleteMenu(hmenu
, dwIDItem
, MF_BYCOMMAND
);
4374 item
->cdcstate
= dwState
;
4376 if (ctrl
->type
== IDLG_CCTRL_OPENDROPDOWN
)
4378 update_control_text(This
);
4379 update_layout(This
);
4384 case IDLG_CCTRL_RADIOBUTTONLIST
:
4388 item
= get_item(ctrl
, dwIDItem
, CDCS_VISIBLE
, NULL
);
4391 return E_UNEXPECTED
;
4393 /* Oddly, native allows setting this but doesn't seem to do anything with it. */
4394 item
->cdcstate
= dwState
;
4405 static HRESULT WINAPI
IFileDialogCustomize_fnGetSelectedControlItem(IFileDialogCustomize
*iface
,
4409 FileDialogImpl
*This
= impl_from_IFileDialogCustomize(iface
);
4410 customctrl
*ctrl
= get_cctrl(This
, dwIDCtl
);
4411 TRACE("%p (%d, %p)\n", This
, dwIDCtl
, pdwIDItem
);
4413 if(!ctrl
) return E_FAIL
;
4417 case IDLG_CCTRL_COMBOBOX
:
4419 UINT index
= SendMessageW(ctrl
->hwnd
, CB_GETCURSEL
, 0, 0);
4423 *pdwIDItem
= SendMessageW(ctrl
->hwnd
, CB_GETITEMDATA
, index
, 0);
4426 case IDLG_CCTRL_OPENDROPDOWN
:
4427 if (This
->opendropdown_has_selection
)
4429 *pdwIDItem
= This
->opendropdown_selection
;
4434 /* Return first enabled item. */
4435 cctrl_item
* item
= get_first_item(ctrl
);
4439 *pdwIDItem
= item
->id
;
4443 WARN("no enabled items in open dropdown\n");
4446 case IDLG_CCTRL_RADIOBUTTONLIST
:
4450 LIST_FOR_EACH_ENTRY(item
, &ctrl
->sub_items
, cctrl_item
, entry
)
4452 if (SendMessageW(item
->hwnd
, BM_GETCHECK
, 0, 0) == BST_CHECKED
)
4454 *pdwIDItem
= item
->id
;
4459 WARN("no checked items in radio button list\n");
4463 FIXME("Unsupported control type %d\n", ctrl
->type
);
4469 static HRESULT WINAPI
IFileDialogCustomize_fnSetSelectedControlItem(IFileDialogCustomize
*iface
,
4473 FileDialogImpl
*This
= impl_from_IFileDialogCustomize(iface
);
4474 customctrl
*ctrl
= get_cctrl(This
, dwIDCtl
);
4475 TRACE("%p (%d, %d)\n", This
, dwIDCtl
, dwIDItem
);
4477 if(!ctrl
) return E_INVALIDARG
;
4481 case IDLG_CCTRL_COMBOBOX
:
4483 UINT index
= get_combobox_index_from_id(ctrl
->hwnd
, dwIDItem
);
4486 return E_INVALIDARG
;
4488 if(SendMessageW(ctrl
->hwnd
, CB_SETCURSEL
, index
, 0) == CB_ERR
)
4493 case IDLG_CCTRL_RADIOBUTTONLIST
:
4497 item
= get_item(ctrl
, dwIDItem
, 0, NULL
);
4501 radiobuttonlist_set_selected_item(This
, ctrl
, item
);
4505 return E_INVALIDARG
;
4508 FIXME("Unsupported control type %d\n", ctrl
->type
);
4511 return E_INVALIDARG
;
4514 static HRESULT WINAPI
IFileDialogCustomize_fnStartVisualGroup(IFileDialogCustomize
*iface
,
4518 FileDialogImpl
*This
= impl_from_IFileDialogCustomize(iface
);
4521 TRACE("%p (%d, %s)\n", This
, dwIDCtl
, debugstr_w(pszLabel
));
4523 if(This
->cctrl_active_vg
)
4524 return E_UNEXPECTED
;
4526 hr
= cctrl_create_new(This
, dwIDCtl
, pszLabel
, WC_STATICW
, 0, 0,
4527 This
->cctrl_def_height
, &vg
);
4530 vg
->type
= IDLG_CCTRL_VISUALGROUP
;
4531 This
->cctrl_active_vg
= vg
;
4537 static HRESULT WINAPI
IFileDialogCustomize_fnEndVisualGroup(IFileDialogCustomize
*iface
)
4539 FileDialogImpl
*This
= impl_from_IFileDialogCustomize(iface
);
4540 TRACE("%p\n", This
);
4542 This
->cctrl_active_vg
= NULL
;
4547 static HRESULT WINAPI
IFileDialogCustomize_fnMakeProminent(IFileDialogCustomize
*iface
,
4550 FileDialogImpl
*This
= impl_from_IFileDialogCustomize(iface
);
4551 FIXME("stub - %p (%d)\n", This
, dwIDCtl
);
4555 static HRESULT WINAPI
IFileDialogCustomize_fnSetControlItemText(IFileDialogCustomize
*iface
,
4560 FileDialogImpl
*This
= impl_from_IFileDialogCustomize(iface
);
4561 FIXME("stub - %p (%d, %d, %s)\n", This
, dwIDCtl
, dwIDItem
, debugstr_w(pszLabel
));
4565 static const IFileDialogCustomizeVtbl vt_IFileDialogCustomize
= {
4566 IFileDialogCustomize_fnQueryInterface
,
4567 IFileDialogCustomize_fnAddRef
,
4568 IFileDialogCustomize_fnRelease
,
4569 IFileDialogCustomize_fnEnableOpenDropDown
,
4570 IFileDialogCustomize_fnAddMenu
,
4571 IFileDialogCustomize_fnAddPushButton
,
4572 IFileDialogCustomize_fnAddComboBox
,
4573 IFileDialogCustomize_fnAddRadioButtonList
,
4574 IFileDialogCustomize_fnAddCheckButton
,
4575 IFileDialogCustomize_fnAddEditBox
,
4576 IFileDialogCustomize_fnAddSeparator
,
4577 IFileDialogCustomize_fnAddText
,
4578 IFileDialogCustomize_fnSetControlLabel
,
4579 IFileDialogCustomize_fnGetControlState
,
4580 IFileDialogCustomize_fnSetControlState
,
4581 IFileDialogCustomize_fnGetEditBoxText
,
4582 IFileDialogCustomize_fnSetEditBoxText
,
4583 IFileDialogCustomize_fnGetCheckButtonState
,
4584 IFileDialogCustomize_fnSetCheckButtonState
,
4585 IFileDialogCustomize_fnAddControlItem
,
4586 IFileDialogCustomize_fnRemoveControlItem
,
4587 IFileDialogCustomize_fnRemoveAllControlItems
,
4588 IFileDialogCustomize_fnGetControlItemState
,
4589 IFileDialogCustomize_fnSetControlItemState
,
4590 IFileDialogCustomize_fnGetSelectedControlItem
,
4591 IFileDialogCustomize_fnSetSelectedControlItem
,
4592 IFileDialogCustomize_fnStartVisualGroup
,
4593 IFileDialogCustomize_fnEndVisualGroup
,
4594 IFileDialogCustomize_fnMakeProminent
,
4595 IFileDialogCustomize_fnSetControlItemText
4598 static HRESULT
FileDialog_constructor(IUnknown
*pUnkOuter
, REFIID riid
, void **ppv
, enum ITEMDLG_TYPE type
)
4600 FileDialogImpl
*fdimpl
;
4603 TRACE("%p, %s, %p\n", pUnkOuter
, debugstr_guid(riid
), ppv
);
4608 return CLASS_E_NOAGGREGATION
;
4610 fdimpl
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(FileDialogImpl
));
4612 return E_OUTOFMEMORY
;
4615 fdimpl
->IFileDialog2_iface
.lpVtbl
= &vt_IFileDialog2
;
4616 fdimpl
->IExplorerBrowserEvents_iface
.lpVtbl
= &vt_IExplorerBrowserEvents
;
4617 fdimpl
->IServiceProvider_iface
.lpVtbl
= &vt_IServiceProvider
;
4618 fdimpl
->ICommDlgBrowser3_iface
.lpVtbl
= &vt_ICommDlgBrowser3
;
4619 fdimpl
->IOleWindow_iface
.lpVtbl
= &vt_IOleWindow
;
4620 fdimpl
->IFileDialogCustomize_iface
.lpVtbl
= &vt_IFileDialogCustomize
;
4622 if(type
== ITEMDLG_TYPE_OPEN
)
4624 fdimpl
->dlg_type
= ITEMDLG_TYPE_OPEN
;
4625 fdimpl
->u
.IFileOpenDialog_iface
.lpVtbl
= &vt_IFileOpenDialog
;
4626 fdimpl
->options
= FOS_PATHMUSTEXIST
| FOS_FILEMUSTEXIST
| FOS_NOCHANGEDIR
;
4627 fdimpl
->custom_title
= fdimpl
->custom_okbutton
= NULL
;
4632 fdimpl
->dlg_type
= ITEMDLG_TYPE_SAVE
;
4633 fdimpl
->u
.IFileSaveDialog_iface
.lpVtbl
= &vt_IFileSaveDialog
;
4634 fdimpl
->options
= FOS_OVERWRITEPROMPT
| FOS_NOREADONLYRETURN
| FOS_PATHMUSTEXIST
| FOS_NOCHANGEDIR
;
4636 LoadStringW(COMDLG32_hInstance
, IDS_SAVE
, buf
, ARRAY_SIZE(buf
));
4637 fdimpl
->custom_title
= StrDupW(buf
);
4638 fdimpl
->custom_okbutton
= StrDupW(buf
);
4641 list_init(&fdimpl
->events_clients
);
4643 /* FIXME: The default folder setting should be restored for the
4644 * application if it was previously set. */
4645 SHGetDesktopFolder(&psf
);
4646 SHGetItemFromObject((IUnknown
*)psf
, &IID_IShellItem
, (void**)&fdimpl
->psi_defaultfolder
);
4647 IShellFolder_Release(psf
);
4649 hr
= init_custom_controls(fdimpl
);
4652 ERR("Failed to initialize custom controls (0x%08x).\n", hr
);
4653 IFileDialog2_Release(&fdimpl
->IFileDialog2_iface
);
4657 hr
= IFileDialog2_QueryInterface(&fdimpl
->IFileDialog2_iface
, riid
, ppv
);
4658 IFileDialog2_Release(&fdimpl
->IFileDialog2_iface
);
4662 HRESULT
FileOpenDialog_Constructor(IUnknown
*pUnkOuter
, REFIID riid
, void **ppv
)
4664 return FileDialog_constructor(pUnkOuter
, riid
, ppv
, ITEMDLG_TYPE_OPEN
);
4667 HRESULT
FileSaveDialog_Constructor(IUnknown
*pUnkOuter
, REFIID riid
, void **ppv
)
4669 return FileDialog_constructor(pUnkOuter
, riid
, ppv
, ITEMDLG_TYPE_SAVE
);