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
21 #ifndef __REACTOS__ /* Win 7 */
26 #define NONAMELESSUNION
37 #include "filedlgbrowser.h"
39 #include "wine/debug.h"
40 #include "wine/list.h"
42 #define IDC_NAV_TOOLBAR 200
43 #define IDC_NAVBACK 201
44 #define IDC_NAVFORWARD 202
47 /* This seems to be another version of IID_IFileDialogCustomize. If
48 * there is any difference I have yet to find it. */
49 DEFINE_GUID(IID_IFileDialogCustomizeAlt
, 0x8016B7B3, 0x3D49, 0x4504, 0xA0,0xAA, 0x2A,0x37,0x49,0x4E,0x60,0x6F);
51 WINE_DEFAULT_DEBUG_CHANNEL(commdlg
);
53 static const WCHAR notifysink_childW
[] = {'n','f','s','_','c','h','i','l','d',0};
54 static const WCHAR floatnotifysinkW
[] = {'F','l','o','a','t','N','o','t','i','f','y','S','i','n','k',0};
55 static const WCHAR radiobuttonlistW
[] = {'R','a','d','i','o','B','u','t','t','o','n','L','i','s','t',0};
62 enum ITEMDLG_CCTRL_TYPE
{
64 IDLG_CCTRL_PUSHBUTTON
,
66 IDLG_CCTRL_RADIOBUTTONLIST
,
67 IDLG_CCTRL_CHECKBUTTON
,
71 IDLG_CCTRL_OPENDROPDOWN
,
72 IDLG_CCTRL_VISUALGROUP
75 typedef struct cctrl_item
{
78 CDCONTROLSTATEF cdcstate
;
84 HWND hwnd
, wrapper_hwnd
;
86 enum ITEMDLG_CCTRL_TYPE type
;
87 CDCONTROLSTATEF cdcstate
;
90 struct list sub_cctrls
;
91 struct list sub_cctrls_entry
;
92 struct list sub_items
;
97 IFileDialogEvents
*pfde
;
101 typedef struct FileDialogImpl
{
102 IFileDialog2 IFileDialog2_iface
;
104 IFileOpenDialog IFileOpenDialog_iface
;
105 IFileSaveDialog IFileSaveDialog_iface
;
107 enum ITEMDLG_TYPE dlg_type
;
108 IExplorerBrowserEvents IExplorerBrowserEvents_iface
;
109 IServiceProvider IServiceProvider_iface
;
110 ICommDlgBrowser3 ICommDlgBrowser3_iface
;
111 IOleWindow IOleWindow_iface
;
112 IFileDialogCustomize IFileDialogCustomize_iface
;
115 FILEOPENDIALOGOPTIONS options
;
116 COMDLG_FILTERSPEC
*filterspecs
;
117 UINT filterspec_count
;
120 struct list events_clients
;
121 DWORD events_next_cookie
;
123 IShellItemArray
*psia_selection
;
124 IShellItemArray
*psia_results
;
125 IShellItem
*psi_defaultfolder
;
126 IShellItem
*psi_setfolder
;
127 IShellItem
*psi_folder
;
130 IExplorerBrowser
*peb
;
131 DWORD ebevents_cookie
;
136 LPWSTR custom_okbutton
;
137 LPWSTR custom_cancelbutton
;
138 LPWSTR custom_filenamelabel
;
140 UINT cctrl_width
, cctrl_def_height
, cctrls_cols
;
141 UINT cctrl_indent
, dpi_x
, dpi_y
;
144 UINT_PTR cctrl_next_dlgid
;
145 customctrl
*cctrl_active_vg
;
147 HMENU hmenu_opendropdown
;
148 customctrl cctrl_opendropdown
;
149 HFONT hfont_opendropdown
;
150 BOOL opendropdown_has_selection
;
151 DWORD opendropdown_selection
;
156 /**************************************************************************
159 static HRESULT
events_OnFileOk(FileDialogImpl
*This
)
161 events_client
*cursor
;
165 LIST_FOR_EACH_ENTRY(cursor
, &This
->events_clients
, events_client
, entry
)
167 TRACE("Notifying %p\n", cursor
);
168 hr
= IFileDialogEvents_OnFileOk(cursor
->pfde
, (IFileDialog
*)&This
->IFileDialog2_iface
);
169 if(FAILED(hr
) && hr
!= E_NOTIMPL
)
179 static HRESULT
events_OnFolderChanging(FileDialogImpl
*This
, IShellItem
*folder
)
181 events_client
*cursor
;
183 TRACE("%p (%p)\n", This
, folder
);
185 LIST_FOR_EACH_ENTRY(cursor
, &This
->events_clients
, events_client
, entry
)
187 TRACE("Notifying %p\n", cursor
);
188 hr
= IFileDialogEvents_OnFolderChanging(cursor
->pfde
, (IFileDialog
*)&This
->IFileDialog2_iface
, folder
);
189 if(FAILED(hr
) && hr
!= E_NOTIMPL
)
199 static void events_OnFolderChange(FileDialogImpl
*This
)
201 events_client
*cursor
;
204 LIST_FOR_EACH_ENTRY(cursor
, &This
->events_clients
, events_client
, entry
)
206 TRACE("Notifying %p\n", cursor
);
207 IFileDialogEvents_OnFolderChange(cursor
->pfde
, (IFileDialog
*)&This
->IFileDialog2_iface
);
211 static void events_OnSelectionChange(FileDialogImpl
*This
)
213 events_client
*cursor
;
216 LIST_FOR_EACH_ENTRY(cursor
, &This
->events_clients
, events_client
, entry
)
218 TRACE("Notifying %p\n", cursor
);
219 IFileDialogEvents_OnSelectionChange(cursor
->pfde
, (IFileDialog
*)&This
->IFileDialog2_iface
);
223 static void events_OnTypeChange(FileDialogImpl
*This
)
225 events_client
*cursor
;
228 LIST_FOR_EACH_ENTRY(cursor
, &This
->events_clients
, events_client
, entry
)
230 TRACE("Notifying %p\n", cursor
);
231 IFileDialogEvents_OnTypeChange(cursor
->pfde
, (IFileDialog
*)&This
->IFileDialog2_iface
);
235 static HRESULT
events_OnOverwrite(FileDialogImpl
*This
, IShellItem
*shellitem
)
237 events_client
*cursor
;
239 FDE_OVERWRITE_RESPONSE response
= FDEOR_DEFAULT
;
240 TRACE("%p %p\n", This
, shellitem
);
242 LIST_FOR_EACH_ENTRY(cursor
, &This
->events_clients
, events_client
, entry
)
244 TRACE("Notifying %p\n", cursor
);
245 hr
= IFileDialogEvents_OnOverwrite(cursor
->pfde
, (IFileDialog
*)&This
->IFileDialog2_iface
, shellitem
, &response
);
246 TRACE("<-- hr=%x response=%u\n", hr
, response
);
247 if(FAILED(hr
) && hr
!= E_NOTIMPL
)
256 if (response
== FDEOR_DEFAULT
)
261 LoadStringW(COMDLG32_hInstance
, IDS_OVERWRITEFILE
, buf
, 100);
262 answer
= MessageBoxW(This
->dlg_hwnd
, buf
, This
->custom_title
,
263 MB_YESNO
| MB_ICONEXCLAMATION
);
264 if (answer
== IDNO
|| answer
== IDCANCEL
)
269 else if (response
== FDEOR_REFUSE
)
276 static inline HRESULT
get_cctrl_event(IFileDialogEvents
*pfde
, IFileDialogControlEvents
**pfdce
)
278 return IFileDialogEvents_QueryInterface(pfde
, &IID_IFileDialogControlEvents
, (void**)pfdce
);
281 static HRESULT
cctrl_event_OnButtonClicked(FileDialogImpl
*This
, DWORD ctl_id
)
283 events_client
*cursor
;
286 LIST_FOR_EACH_ENTRY(cursor
, &This
->events_clients
, events_client
, entry
)
288 IFileDialogControlEvents
*pfdce
;
289 if(SUCCEEDED(get_cctrl_event(cursor
->pfde
, &pfdce
)))
291 TRACE("Notifying %p\n", cursor
);
292 IFileDialogControlEvents_OnButtonClicked(pfdce
, &This
->IFileDialogCustomize_iface
, ctl_id
);
293 IFileDialogControlEvents_Release(pfdce
);
300 static HRESULT
cctrl_event_OnItemSelected(FileDialogImpl
*This
, DWORD ctl_id
, DWORD item_id
)
302 events_client
*cursor
;
303 TRACE("%p %i %i\n", This
, ctl_id
, item_id
);
305 LIST_FOR_EACH_ENTRY(cursor
, &This
->events_clients
, events_client
, entry
)
307 IFileDialogControlEvents
*pfdce
;
308 if(SUCCEEDED(get_cctrl_event(cursor
->pfde
, &pfdce
)))
310 TRACE("Notifying %p\n", cursor
);
311 IFileDialogControlEvents_OnItemSelected(pfdce
, &This
->IFileDialogCustomize_iface
, ctl_id
, item_id
);
312 IFileDialogControlEvents_Release(pfdce
);
319 static HRESULT
cctrl_event_OnCheckButtonToggled(FileDialogImpl
*This
, DWORD ctl_id
, BOOL checked
)
321 events_client
*cursor
;
324 LIST_FOR_EACH_ENTRY(cursor
, &This
->events_clients
, events_client
, entry
)
326 IFileDialogControlEvents
*pfdce
;
327 if(SUCCEEDED(get_cctrl_event(cursor
->pfde
, &pfdce
)))
329 TRACE("Notifying %p\n", cursor
);
330 IFileDialogControlEvents_OnCheckButtonToggled(pfdce
, &This
->IFileDialogCustomize_iface
, ctl_id
, checked
);
331 IFileDialogControlEvents_Release(pfdce
);
338 static HRESULT
cctrl_event_OnControlActivating(FileDialogImpl
*This
,
341 events_client
*cursor
;
344 LIST_FOR_EACH_ENTRY(cursor
, &This
->events_clients
, events_client
, entry
)
346 IFileDialogControlEvents
*pfdce
;
347 if(SUCCEEDED(get_cctrl_event(cursor
->pfde
, &pfdce
)))
349 TRACE("Notifying %p\n", cursor
);
350 IFileDialogControlEvents_OnControlActivating(pfdce
, &This
->IFileDialogCustomize_iface
, ctl_id
);
351 IFileDialogControlEvents_Release(pfdce
);
358 /**************************************************************************
361 static UINT
get_file_name(FileDialogImpl
*This
, LPWSTR
*str
)
363 HWND hwnd_edit
= GetDlgItem(This
->dlg_hwnd
, IDC_FILENAME
);
368 if(This
->set_filename
)
370 len
= lstrlenW(This
->set_filename
);
371 *str
= CoTaskMemAlloc(sizeof(WCHAR
)*(len
+1));
372 lstrcpyW(*str
, This
->set_filename
);
378 len
= SendMessageW(hwnd_edit
, WM_GETTEXTLENGTH
, 0, 0);
379 *str
= CoTaskMemAlloc(sizeof(WCHAR
)*(len
+1));
383 SendMessageW(hwnd_edit
, WM_GETTEXT
, len
+1, (LPARAM
)*str
);
387 static BOOL
set_file_name(FileDialogImpl
*This
, LPCWSTR str
)
389 if(This
->set_filename
)
390 LocalFree(This
->set_filename
);
392 This
->set_filename
= str
? StrDupW(str
) : NULL
;
394 return SetDlgItemTextW(This
->dlg_hwnd
, IDC_FILENAME
, This
->set_filename
);
397 static void fill_filename_from_selection(FileDialogImpl
*This
)
402 UINT item_count
, valid_count
;
405 if(!This
->psia_selection
)
408 hr
= IShellItemArray_GetCount(This
->psia_selection
, &item_count
);
409 if(FAILED(hr
) || !item_count
)
412 names
= HeapAlloc(GetProcessHeap(), 0, item_count
*sizeof(LPWSTR
));
414 /* Get names of the selected items */
415 valid_count
= 0; len_total
= 0;
416 for(i
= 0; i
< item_count
; i
++)
418 hr
= IShellItemArray_GetItemAt(This
->psia_selection
, i
, &psi
);
423 hr
= IShellItem_GetAttributes(psi
, SFGAO_FOLDER
, &attr
);
425 (( (This
->options
& FOS_PICKFOLDERS
) && !(attr
& SFGAO_FOLDER
)) ||
426 (!(This
->options
& FOS_PICKFOLDERS
) && (attr
& SFGAO_FOLDER
))))
429 hr
= IShellItem_GetDisplayName(psi
, SIGDN_PARENTRELATIVEPARSING
, &names
[valid_count
]);
432 len_total
+= lstrlenW(names
[valid_count
]) + 3;
435 IShellItem_Release(psi
);
441 set_file_name(This
, names
[0]);
442 CoTaskMemFree(names
[0]);
444 else if(valid_count
> 1)
446 LPWSTR string
= HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR
)*len_total
);
447 LPWSTR cur_point
= string
;
449 for(i
= 0; i
< valid_count
; i
++)
451 LPWSTR file
= names
[i
];
453 lstrcpyW(cur_point
, file
);
454 cur_point
+= lstrlenW(file
);
459 *(cur_point
-1) = '\0';
461 set_file_name(This
, string
);
462 HeapFree(GetProcessHeap(), 0, string
);
465 HeapFree(GetProcessHeap(), 0, names
);
469 static LPWSTR
get_first_ext_from_spec(LPWSTR buf
, LPCWSTR spec
)
474 if( (endpos
= StrChrW(buf
, ';')) )
477 ext
= PathFindExtensionW(buf
);
478 if(StrChrW(ext
, '*'))
484 static BOOL
shell_item_exists(IShellItem
* shellitem
)
490 hr
= IShellItem_GetDisplayName(shellitem
, SIGDN_FILESYSPATH
, &filename
);
493 /* FIXME: Implement SFGAO_VALIDATE in Wine and use it instead. */
494 result
= (GetFileAttributesW(filename
) != INVALID_FILE_ATTRIBUTES
);
495 CoTaskMemFree(filename
);
500 result
= SUCCEEDED(IShellItem_GetAttributes(shellitem
, SFGAO_VALIDATE
, &attributes
));
506 static HRESULT
on_default_action(FileDialogImpl
*This
)
508 IShellFolder
*psf_parent
, *psf_desktop
;
510 LPITEMIDLIST current_folder
;
511 LPWSTR fn_iter
, files
= NULL
, tmp_files
;
512 UINT file_count
= 0, len
, i
;
514 HRESULT hr
, ret
= E_FAIL
;
516 len
= get_file_name(This
, &tmp_files
);
520 file_count
= COMDLG32_SplitFileNames(tmp_files
, len
, &files
, &size_used
);
521 CoTaskMemFree(tmp_files
);
523 if(!file_count
) return E_FAIL
;
525 hr
= SHGetIDListFromObject((IUnknown
*)This
->psi_folder
, ¤t_folder
);
528 ERR("Failed to get pidl for current directory.\n");
529 HeapFree(GetProcessHeap(), 0, files
);
533 TRACE("Acting on %d file(s).\n", file_count
);
535 pidla
= HeapAlloc(GetProcessHeap(), 0, sizeof(LPITEMIDLIST
) * file_count
);
536 open_action
= ONOPEN_OPEN
;
539 for(i
= 0; i
< file_count
&& open_action
== ONOPEN_OPEN
; i
++)
541 WCHAR canon_filename
[MAX_PATH
];
544 COMDLG32_GetCanonicalPath(current_folder
, fn_iter
, canon_filename
);
546 if( (This
->options
& FOS_NOVALIDATE
) &&
547 !(This
->options
& FOS_FILEMUSTEXIST
) )
548 open_action
= ONOPEN_OPEN
;
550 open_action
= ONOPEN_BROWSE
;
552 open_action
= FILEDLG95_ValidatePathAction(canon_filename
, &psf_parent
, This
->dlg_hwnd
,
553 This
->options
& ~FOS_FILEMUSTEXIST
,
554 (This
->dlg_type
== ITEMDLG_TYPE_SAVE
),
557 /* Add the proper extension */
558 if(open_action
== ONOPEN_OPEN
)
560 static const WCHAR dotW
[] = {'.',0};
562 if(This
->dlg_type
== ITEMDLG_TYPE_SAVE
)
564 WCHAR extbuf
[MAX_PATH
], *newext
= NULL
;
566 if(This
->filterspec_count
)
568 newext
= get_first_ext_from_spec(extbuf
, This
->filterspecs
[This
->filetypeindex
].pszSpec
);
570 else if(This
->default_ext
)
572 lstrcpyW(extbuf
, dotW
);
573 lstrcatW(extbuf
, This
->default_ext
);
579 WCHAR
*ext
= PathFindExtensionW(canon_filename
);
580 if(lstrcmpW(ext
, newext
))
581 lstrcatW(canon_filename
, newext
);
586 if( !(This
->options
& FOS_NOVALIDATE
) && (This
->options
& FOS_FILEMUSTEXIST
) &&
587 !PathFileExistsW(canon_filename
))
589 if(This
->default_ext
)
591 lstrcatW(canon_filename
, dotW
);
592 lstrcatW(canon_filename
, This
->default_ext
);
594 if(!PathFileExistsW(canon_filename
))
596 FILEDLG95_OnOpenMessage(This
->dlg_hwnd
, 0, IDS_FILENOTEXISTING
);
597 open_action
= ONOPEN_BROWSE
;
602 FILEDLG95_OnOpenMessage(This
->dlg_hwnd
, 0, IDS_FILENOTEXISTING
);
603 open_action
= ONOPEN_BROWSE
;
609 pidla
[i
] = COMDLG32_SHSimpleIDListFromPathAW(canon_filename
);
611 if(psf_parent
&& !(open_action
== ONOPEN_BROWSE
))
612 IShellFolder_Release(psf_parent
);
614 fn_iter
+= (WCHAR
)lstrlenW(fn_iter
) + 1;
617 HeapFree(GetProcessHeap(), 0, files
);
618 ILFree(current_folder
);
620 if((This
->options
& FOS_PICKFOLDERS
) && open_action
== ONOPEN_BROWSE
)
621 open_action
= ONOPEN_OPEN
; /* FIXME: Multiple folders? */
626 FIXME("Filtering not implemented.\n");
630 hr
= IExplorerBrowser_BrowseToObject(This
->peb
, (IUnknown
*)psf_parent
, SBSP_DEFBROWSER
);
632 ERR("Failed to browse to directory: %08x\n", hr
);
634 IShellFolder_Release(psf_parent
);
638 hr
= SHGetDesktopFolder(&psf_desktop
);
641 if(This
->psia_results
)
643 IShellItemArray_Release(This
->psia_results
);
644 This
->psia_results
= NULL
;
647 hr
= SHCreateShellItemArray(NULL
, psf_desktop
, file_count
, (PCUITEMID_CHILD_ARRAY
)pidla
,
648 &This
->psia_results
);
650 IShellFolder_Release(psf_desktop
);
655 if(This
->options
& FOS_PICKFOLDERS
)
658 hr
= IShellItemArray_GetAttributes(This
->psia_results
, SIATTRIBFLAGS_AND
, SFGAO_FOLDER
, &attributes
);
662 LoadStringW(COMDLG32_hInstance
, IDS_INVALID_FOLDERNAME
, buf
, ARRAY_SIZE(buf
));
664 MessageBoxW(This
->dlg_hwnd
, buf
, This
->custom_title
, MB_OK
| MB_ICONEXCLAMATION
);
666 IShellItemArray_Release(This
->psia_results
);
667 This
->psia_results
= NULL
;
672 if((This
->options
& FOS_OVERWRITEPROMPT
) && This
->dlg_type
== ITEMDLG_TYPE_SAVE
)
674 IShellItem
*shellitem
;
676 for (i
=0; SUCCEEDED(hr
) && i
<file_count
; i
++)
678 hr
= IShellItemArray_GetItemAt(This
->psia_results
, i
, &shellitem
);
681 if (shell_item_exists(shellitem
))
682 hr
= events_OnOverwrite(This
, shellitem
);
684 IShellItem_Release(shellitem
);
692 if(events_OnFileOk(This
) == S_OK
)
703 for(i
= 0; i
< file_count
; i
++)
705 HeapFree(GetProcessHeap(), 0, pidla
);
707 /* Success closes the dialog */
711 static void show_opendropdown(FileDialogImpl
*This
)
717 open_hwnd
= GetDlgItem(This
->dlg_hwnd
, IDOK
);
719 GetWindowRect(open_hwnd
, &open_rc
);
721 if (TrackPopupMenu(This
->hmenu_opendropdown
, 0, open_rc
.left
, open_rc
.bottom
, 0, This
->dlg_hwnd
, NULL
) &&
722 PeekMessageW(&msg
, This
->dlg_hwnd
, WM_MENUCOMMAND
, WM_MENUCOMMAND
, PM_REMOVE
))
726 This
->opendropdown_has_selection
= TRUE
;
728 mii
.cbSize
= sizeof(mii
);
730 GetMenuItemInfoW((HMENU
)msg
.lParam
, msg
.wParam
, TRUE
, &mii
);
731 This
->opendropdown_selection
= mii
.wID
;
733 if(SUCCEEDED(on_default_action(This
)))
734 EndDialog(This
->dlg_hwnd
, S_OK
);
736 This
->opendropdown_has_selection
= FALSE
;
740 /**************************************************************************
741 * Control item functions.
744 static void item_free(cctrl_item
*item
)
746 DestroyWindow(item
->hwnd
);
747 HeapFree(GetProcessHeap(), 0, item
->label
);
748 HeapFree(GetProcessHeap(), 0, item
);
751 static cctrl_item
* get_item(customctrl
* parent
, DWORD itemid
, CDCONTROLSTATEF visible_flags
, DWORD
* position
)
756 if (!position
) position
= &dummy
;
760 LIST_FOR_EACH_ENTRY(item
, &parent
->sub_items
, cctrl_item
, entry
)
762 if (item
->id
== itemid
)
765 if ((item
->cdcstate
& visible_flags
) == visible_flags
)
772 static cctrl_item
* get_first_item(customctrl
* parent
)
776 LIST_FOR_EACH_ENTRY(item
, &parent
->sub_items
, cctrl_item
, entry
)
778 if ((item
->cdcstate
& (CDCS_VISIBLE
|CDCS_ENABLED
)) == (CDCS_VISIBLE
|CDCS_ENABLED
))
785 static HRESULT
add_item(customctrl
* parent
, DWORD itemid
, LPCWSTR label
, cctrl_item
** result
)
790 if (get_item(parent
, itemid
, 0, NULL
))
793 item
= HeapAlloc(GetProcessHeap(), 0, sizeof(*item
));
794 label_copy
= HeapAlloc(GetProcessHeap(), 0, (lstrlenW(label
)+1)*sizeof(WCHAR
));
796 if (!item
|| !label_copy
)
798 HeapFree(GetProcessHeap(), 0, item
);
799 HeapFree(GetProcessHeap(), 0, label_copy
);
800 return E_OUTOFMEMORY
;
804 item
->parent_id
= parent
->id
;
805 lstrcpyW(label_copy
, label
);
806 item
->label
= label_copy
;
807 item
->cdcstate
= CDCS_VISIBLE
|CDCS_ENABLED
;
809 list_add_tail(&parent
->sub_items
, &item
->entry
);
816 /**************************************************************************
819 static inline customctrl
*get_cctrl_from_dlgid(FileDialogImpl
*This
, DWORD dlgid
)
821 customctrl
*ctrl
, *sub_ctrl
;
823 LIST_FOR_EACH_ENTRY(ctrl
, &This
->cctrls
, customctrl
, entry
)
825 if(ctrl
->dlgid
== dlgid
)
828 LIST_FOR_EACH_ENTRY(sub_ctrl
, &ctrl
->sub_cctrls
, customctrl
, sub_cctrls_entry
)
829 if(sub_ctrl
->dlgid
== dlgid
)
833 ERR("Failed to find control with dialog id %d\n", dlgid
);
837 static inline customctrl
*get_cctrl(FileDialogImpl
*This
, DWORD ctlid
)
839 customctrl
*ctrl
, *sub_ctrl
;
841 LIST_FOR_EACH_ENTRY(ctrl
, &This
->cctrls
, customctrl
, entry
)
843 if(ctrl
->id
== ctlid
)
846 LIST_FOR_EACH_ENTRY(sub_ctrl
, &ctrl
->sub_cctrls
, customctrl
, sub_cctrls_entry
)
847 if(sub_ctrl
->id
== ctlid
)
851 if (This
->hmenu_opendropdown
&& This
->cctrl_opendropdown
.id
== ctlid
)
852 return &This
->cctrl_opendropdown
;
854 TRACE("No existing control with control id %d\n", ctlid
);
858 static void ctrl_resize(HWND hctrl
, UINT min_width
, UINT max_width
, BOOL multiline
)
861 UINT len
, final_width
;
862 UINT lines
, final_height
;
871 len
= SendMessageW(hctrl
, WM_GETTEXTLENGTH
, 0, 0);
872 text
= HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR
)*(len
+1));
874 SendMessageW(hctrl
, WM_GETTEXT
, len
+1, (LPARAM
)text
);
877 font
= (HFONT
)SendMessageW(hctrl
, WM_GETFONT
, 0, 0);
878 font
= SelectObject(hdc
, font
);
879 GetTextExtentPoint32W(hdc
, text
, lstrlenW(text
), &size
);
880 SelectObject(hdc
, font
);
881 ReleaseDC(hctrl
, hdc
);
885 /* FIXME: line-wrap */
886 for(lines
= 1, c
= text
; *c
!= '\0'; c
++)
887 if(*c
== '\n') lines
++;
889 final_height
= size
.cy
*lines
+ 2*4;
893 GetWindowRect(hctrl
, &rc
);
894 final_height
= rc
.bottom
- rc
.top
;
897 final_width
= min(max(size
.cx
, min_width
) + 4, max_width
);
898 SetWindowPos(hctrl
, NULL
, 0, 0, final_width
, final_height
,
899 SWP_NOZORDER
| SWP_NOMOVE
| SWP_NOACTIVATE
);
901 HeapFree(GetProcessHeap(), 0, text
);
904 static UINT
ctrl_get_height(customctrl
*ctrl
) {
906 GetWindowRect(ctrl
->wrapper_hwnd
, &rc
);
907 return rc
.bottom
- rc
.top
;
910 static void ctrl_free(customctrl
*ctrl
)
912 customctrl
*sub_cur1
, *sub_cur2
;
913 cctrl_item
*item_cur1
, *item_cur2
;
915 TRACE("Freeing control %p\n", ctrl
);
916 if(ctrl
->type
== IDLG_CCTRL_MENU
)
919 SendMessageW(ctrl
->hwnd
, TB_GETBUTTON
, 0, (LPARAM
)&tbb
);
920 DestroyMenu((HMENU
)tbb
.dwData
);
923 LIST_FOR_EACH_ENTRY_SAFE(sub_cur1
, sub_cur2
, &ctrl
->sub_cctrls
, customctrl
, sub_cctrls_entry
)
925 list_remove(&sub_cur1
->sub_cctrls_entry
);
929 LIST_FOR_EACH_ENTRY_SAFE(item_cur1
, item_cur2
, &ctrl
->sub_items
, cctrl_item
, entry
)
931 list_remove(&item_cur1
->entry
);
932 item_free(item_cur1
);
935 DestroyWindow(ctrl
->hwnd
);
936 HeapFree(GetProcessHeap(), 0, ctrl
);
939 static void customctrl_resize(FileDialogImpl
*This
, customctrl
*ctrl
)
943 UINT max_width
, size
;
944 customctrl
*sub_ctrl
;
948 case IDLG_CCTRL_PUSHBUTTON
:
949 case IDLG_CCTRL_COMBOBOX
:
950 case IDLG_CCTRL_CHECKBUTTON
:
951 case IDLG_CCTRL_TEXT
:
952 size
= MulDiv(160, This
->dpi_x
, USER_DEFAULT_SCREEN_DPI
);
953 ctrl_resize(ctrl
->hwnd
, size
, size
, TRUE
);
954 GetWindowRect(ctrl
->hwnd
, &rc
);
955 SetWindowPos(ctrl
->wrapper_hwnd
, NULL
, 0, 0, rc
.right
-rc
.left
, rc
.bottom
-rc
.top
,
956 SWP_NOZORDER
|SWP_NOMOVE
);
958 case IDLG_CCTRL_VISUALGROUP
:
960 ctrl_resize(ctrl
->hwnd
, 0, This
->cctrl_indent
, TRUE
);
962 LIST_FOR_EACH_ENTRY(sub_ctrl
, &ctrl
->sub_cctrls
, customctrl
, sub_cctrls_entry
)
964 customctrl_resize(This
, sub_ctrl
);
965 SetWindowPos(sub_ctrl
->wrapper_hwnd
, NULL
, This
->cctrl_indent
, total_height
, 0, 0,
966 SWP_NOZORDER
|SWP_NOSIZE
);
968 total_height
+= ctrl_get_height(sub_ctrl
);
971 /* The label should be right adjusted */
975 GetWindowRect(ctrl
->hwnd
, &rc
);
976 width
= rc
.right
- rc
.left
;
977 height
= rc
.bottom
- rc
.top
;
979 SetWindowPos(ctrl
->hwnd
, NULL
, This
->cctrl_indent
- width
, 0, width
, height
, SWP_NOZORDER
);
982 /* Resize the wrapper window to fit all the sub controls */
983 SetWindowPos(ctrl
->wrapper_hwnd
, NULL
, 0, 0, This
->cctrl_width
+ This
->cctrl_indent
, total_height
,
984 SWP_NOZORDER
|SWP_NOMOVE
);
986 case IDLG_CCTRL_RADIOBUTTONLIST
:
993 LIST_FOR_EACH_ENTRY(item
, &ctrl
->sub_items
, cctrl_item
, entry
)
995 size
= MulDiv(160, This
->dpi_x
, USER_DEFAULT_SCREEN_DPI
);
996 ctrl_resize(item
->hwnd
, size
, size
, TRUE
);
997 SetWindowPos(item
->hwnd
, NULL
, 0, total_height
, 0, 0,
998 SWP_NOZORDER
|SWP_NOSIZE
);
1000 GetWindowRect(item
->hwnd
, &rc
);
1002 total_height
+= rc
.bottom
- rc
.top
;
1003 max_width
= max(rc
.right
- rc
.left
, max_width
);
1006 SetWindowPos(ctrl
->hwnd
, NULL
, 0, 0, max_width
, total_height
,
1007 SWP_NOZORDER
|SWP_NOMOVE
);
1009 SetWindowPos(ctrl
->wrapper_hwnd
, NULL
, 0, 0, max_width
, total_height
,
1010 SWP_NOZORDER
|SWP_NOMOVE
);
1014 case IDLG_CCTRL_EDITBOX
:
1015 case IDLG_CCTRL_SEPARATOR
:
1016 case IDLG_CCTRL_MENU
:
1017 case IDLG_CCTRL_OPENDROPDOWN
:
1023 static LRESULT
notifysink_on_create(HWND hwnd
, CREATESTRUCTW
*crs
)
1025 FileDialogImpl
*This
= crs
->lpCreateParams
;
1026 TRACE("%p\n", This
);
1028 SetWindowLongPtrW(hwnd
, GWLP_USERDATA
, (LPARAM
)This
);
1032 static LRESULT
notifysink_on_bn_clicked(FileDialogImpl
*This
, HWND hwnd
, WPARAM wparam
)
1034 customctrl
*ctrl
= get_cctrl_from_dlgid(This
, LOWORD(wparam
));
1036 TRACE("%p, %lx\n", This
, wparam
);
1040 if(ctrl
->type
== IDLG_CCTRL_CHECKBUTTON
)
1042 BOOL checked
= (SendMessageW(ctrl
->hwnd
, BM_GETCHECK
, 0, 0) == BST_CHECKED
);
1043 cctrl_event_OnCheckButtonToggled(This
, ctrl
->id
, checked
);
1046 cctrl_event_OnButtonClicked(This
, ctrl
->id
);
1052 static LRESULT
notifysink_on_cbn_selchange(FileDialogImpl
*This
, HWND hwnd
, WPARAM wparam
)
1054 customctrl
*ctrl
= get_cctrl_from_dlgid(This
, LOWORD(wparam
));
1055 TRACE("%p, %p (%lx)\n", This
, ctrl
, wparam
);
1059 UINT index
= SendMessageW(ctrl
->hwnd
, CB_GETCURSEL
, 0, 0);
1060 UINT selid
= SendMessageW(ctrl
->hwnd
, CB_GETITEMDATA
, index
, 0);
1062 cctrl_event_OnItemSelected(This
, ctrl
->id
, selid
);
1067 static LRESULT
notifysink_on_tvn_dropdown(FileDialogImpl
*This
, LPARAM lparam
)
1069 NMTOOLBARW
*nmtb
= (NMTOOLBARW
*)lparam
;
1070 customctrl
*ctrl
= get_cctrl_from_dlgid(This
, GetDlgCtrlID(nmtb
->hdr
.hwndFrom
));
1071 POINT pt
= { 0, nmtb
->rcButton
.bottom
};
1075 TRACE("%p, %p (%lx)\n", This
, ctrl
, lparam
);
1079 cctrl_event_OnControlActivating(This
,ctrl
->id
);
1081 SendMessageW(ctrl
->hwnd
, TB_GETBUTTON
, 0, (LPARAM
)&tbb
);
1082 ClientToScreen(ctrl
->hwnd
, &pt
);
1083 idcmd
= TrackPopupMenu((HMENU
)tbb
.dwData
, TPM_RETURNCMD
, pt
.x
, pt
.y
, 0, This
->dlg_hwnd
, NULL
);
1085 cctrl_event_OnItemSelected(This
, ctrl
->id
, idcmd
);
1088 return TBDDRET_DEFAULT
;
1091 static LRESULT
notifysink_on_wm_command(FileDialogImpl
*This
, HWND hwnd
, WPARAM wparam
, LPARAM lparam
)
1093 switch(HIWORD(wparam
))
1095 case BN_CLICKED
: return notifysink_on_bn_clicked(This
, hwnd
, wparam
);
1096 case CBN_SELCHANGE
: return notifysink_on_cbn_selchange(This
, hwnd
, wparam
);
1102 static LRESULT
notifysink_on_wm_notify(FileDialogImpl
*This
, HWND hwnd
, WPARAM wparam
, LPARAM lparam
)
1104 NMHDR
*nmhdr
= (NMHDR
*)lparam
;
1108 case TBN_DROPDOWN
: return notifysink_on_tvn_dropdown(This
, lparam
);
1114 static LRESULT CALLBACK
notifysink_proc(HWND hwnd
, UINT message
, WPARAM wparam
, LPARAM lparam
)
1116 FileDialogImpl
*This
= (FileDialogImpl
*)GetWindowLongPtrW(hwnd
, GWLP_USERDATA
);
1123 case WM_NCCREATE
: return notifysink_on_create(hwnd
, (CREATESTRUCTW
*)lparam
);
1124 case WM_COMMAND
: return notifysink_on_wm_command(This
, hwnd
, wparam
, lparam
);
1125 case WM_NOTIFY
: return notifysink_on_wm_notify(This
, hwnd
, wparam
, lparam
);
1127 hwnd_child
= GetPropW(hwnd
, notifysink_childW
);
1128 ctrl
= (customctrl
*)GetWindowLongPtrW(hwnd_child
, GWLP_USERDATA
);
1129 if(ctrl
&& ctrl
->type
!= IDLG_CCTRL_VISUALGROUP
)
1131 GetClientRect(hwnd
, &rc
);
1132 SetWindowPos(hwnd_child
, NULL
, 0, 0, rc
.right
, rc
.bottom
, SWP_NOMOVE
|SWP_NOACTIVATE
|SWP_NOZORDER
);
1137 return DefWindowProcW(hwnd
, message
, wparam
, lparam
);
1140 static HRESULT
cctrl_create_new(FileDialogImpl
*This
, DWORD id
,
1141 LPCWSTR text
, LPCWSTR wndclass
, DWORD ctrl_wsflags
,
1142 DWORD ctrl_exflags
, UINT height
, customctrl
**ppctrl
)
1144 HWND ns_hwnd
, control_hwnd
, parent_hwnd
;
1145 DWORD wsflags
= WS_CHILD
| WS_VISIBLE
| WS_CLIPSIBLINGS
;
1148 if(get_cctrl(This
, id
))
1149 return E_UNEXPECTED
; /* Duplicate id */
1151 if(This
->cctrl_active_vg
)
1152 parent_hwnd
= This
->cctrl_active_vg
->wrapper_hwnd
;
1154 parent_hwnd
= This
->cctrls_hwnd
;
1156 ns_hwnd
= CreateWindowExW(0, floatnotifysinkW
, NULL
, wsflags
,
1157 0, 0, This
->cctrl_width
, height
, parent_hwnd
,
1158 (HMENU
)This
->cctrl_next_dlgid
, COMDLG32_hInstance
, This
);
1159 control_hwnd
= CreateWindowExW(ctrl_exflags
, wndclass
, text
, wsflags
| ctrl_wsflags
,
1160 0, 0, This
->cctrl_width
, height
, ns_hwnd
,
1161 (HMENU
)This
->cctrl_next_dlgid
, COMDLG32_hInstance
, 0);
1163 if(!ns_hwnd
|| !control_hwnd
)
1165 ERR("Failed to create wrapper (%p) or control (%p)\n", ns_hwnd
, control_hwnd
);
1166 DestroyWindow(ns_hwnd
);
1167 DestroyWindow(control_hwnd
);
1172 SetPropW(ns_hwnd
, notifysink_childW
, control_hwnd
);
1174 ctrl
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(customctrl
));
1176 return E_OUTOFMEMORY
;
1178 ctrl
->hwnd
= control_hwnd
;
1179 ctrl
->wrapper_hwnd
= ns_hwnd
;
1181 ctrl
->dlgid
= This
->cctrl_next_dlgid
;
1182 ctrl
->cdcstate
= CDCS_ENABLED
| CDCS_VISIBLE
;
1183 list_init(&ctrl
->sub_cctrls
);
1184 list_init(&ctrl
->sub_items
);
1186 if(This
->cctrl_active_vg
)
1187 list_add_tail(&This
->cctrl_active_vg
->sub_cctrls
, &ctrl
->sub_cctrls_entry
);
1189 list_add_tail(&This
->cctrls
, &ctrl
->entry
);
1191 SetWindowLongPtrW(ctrl
->hwnd
, GWLP_USERDATA
, (LPARAM
)ctrl
);
1193 if(ppctrl
) *ppctrl
= ctrl
;
1195 This
->cctrl_next_dlgid
++;
1199 /**************************************************************************
1200 * Container functions.
1202 static UINT
ctrl_container_resize(FileDialogImpl
*This
, UINT container_width
)
1204 UINT container_height
;
1207 UINT max_control_height
, total_height
= 0;
1208 UINT cur_col_pos
, cur_row_pos
;
1211 UINT cspacing
= MulDiv(90, This
->dpi_x
, USER_DEFAULT_SCREEN_DPI
); /* Columns are spaced with 90px */
1212 UINT rspacing
= MulDiv(4, This
->dpi_y
, USER_DEFAULT_SCREEN_DPI
); /* Rows are spaced with 4 px. */
1214 /* Given the new width of the container, this function determines the
1215 * needed height of the container and places the controls according to
1216 * the new layout. Returns the new height.
1219 TRACE("%p\n", This
);
1221 column_width
= This
->cctrl_width
+ cspacing
;
1222 nr_of_cols
= (container_width
- This
->cctrl_indent
+ cspacing
) / column_width
;
1224 /* We don't need to do anything unless the number of visible columns has changed. */
1225 if(nr_of_cols
== This
->cctrls_cols
)
1228 GetWindowRect(This
->cctrls_hwnd
, &rc
);
1229 return rc
.bottom
- rc
.top
;
1232 This
->cctrls_cols
= nr_of_cols
;
1234 /* Get the size of the tallest control, and the total size of
1235 * all the controls to figure out the number of slots we need.
1237 max_control_height
= 0;
1238 LIST_FOR_EACH_ENTRY(ctrl
, &This
->cctrls
, customctrl
, entry
)
1240 if(ctrl
->cdcstate
& CDCS_VISIBLE
)
1242 UINT control_height
= ctrl_get_height(ctrl
);
1243 max_control_height
= max(max_control_height
, control_height
);
1245 total_height
+= control_height
+ rspacing
;
1252 container_height
= max(total_height
/ nr_of_cols
, max_control_height
+ rspacing
);
1253 TRACE("Guess: container_height: %d\n",container_height
);
1255 /* Incrementally increase container_height until all the controls
1259 UINT columns_needed
= 1;
1263 LIST_FOR_EACH_ENTRY(ctrl
, &This
->cctrls
, customctrl
, entry
)
1265 if(ctrl
->cdcstate
& CDCS_VISIBLE
)
1267 UINT control_height
= ctrl_get_height(ctrl
);
1269 if(cur_row_pos
+ control_height
> container_height
)
1271 if(++columns_needed
> nr_of_cols
)
1273 container_height
+= 1;
1274 fits_height
= FALSE
;
1280 cur_row_pos
+= control_height
+ rspacing
;
1283 } while(!fits_height
);
1285 TRACE("Final container height: %d\n", container_height
);
1287 /* Move the controls to their final destination
1289 cur_col_pos
= 0, cur_row_pos
= 0;
1290 LIST_FOR_EACH_ENTRY(ctrl
, &This
->cctrls
, customctrl
, entry
)
1292 if(ctrl
->cdcstate
& CDCS_VISIBLE
)
1295 UINT control_height
, control_indent
;
1296 GetWindowRect(ctrl
->wrapper_hwnd
, &rc
);
1297 control_height
= rc
.bottom
- rc
.top
;
1299 if(cur_row_pos
+ control_height
> container_height
)
1302 cur_col_pos
+= This
->cctrl_width
+ cspacing
;
1306 if(ctrl
->type
== IDLG_CCTRL_VISUALGROUP
)
1309 control_indent
= This
->cctrl_indent
;
1311 SetWindowPos(ctrl
->wrapper_hwnd
, NULL
, cur_col_pos
+ control_indent
, cur_row_pos
, 0, 0,
1312 SWP_NOACTIVATE
| SWP_NOSIZE
| SWP_NOZORDER
);
1314 cur_row_pos
+= control_height
+ rspacing
;
1319 if(cur_row_pos
+ This
->cctrl_width
> container_width
)
1320 ERR("-- Failed to place controls properly.\n");
1322 return container_height
;
1325 static void ctrl_set_font(customctrl
*ctrl
, HFONT font
)
1327 customctrl
*sub_ctrl
;
1330 SendMessageW(ctrl
->hwnd
, WM_SETFONT
, (WPARAM
)font
, TRUE
);
1332 LIST_FOR_EACH_ENTRY(sub_ctrl
, &ctrl
->sub_cctrls
, customctrl
, sub_cctrls_entry
)
1334 ctrl_set_font(sub_ctrl
, font
);
1337 if (ctrl
->type
== IDLG_CCTRL_RADIOBUTTONLIST
)
1339 LIST_FOR_EACH_ENTRY(item
, &ctrl
->sub_items
, cctrl_item
, entry
)
1341 SendMessageW(item
->hwnd
, WM_SETFONT
, (WPARAM
)font
, TRUE
);
1346 static void ctrl_container_reparent(FileDialogImpl
*This
, HWND parent
)
1355 wndstyle
= GetWindowLongW(This
->cctrls_hwnd
, GWL_STYLE
);
1356 wndstyle
&= ~(WS_POPUP
);
1357 wndstyle
|= WS_CHILD
;
1358 SetWindowLongW(This
->cctrls_hwnd
, GWL_STYLE
, wndstyle
);
1360 SetParent(This
->cctrls_hwnd
, parent
);
1361 ShowWindow(This
->cctrls_hwnd
, TRUE
);
1363 /* Set the fonts to match the dialog font. */
1364 font
= (HFONT
)SendMessageW(parent
, WM_GETFONT
, 0, 0);
1366 ERR("Failed to get font handle from dialog.\n");
1368 LIST_FOR_EACH_ENTRY(ctrl
, &This
->cctrls
, customctrl
, entry
)
1370 if(font
) ctrl_set_font(ctrl
, font
);
1371 customctrl_resize(This
, ctrl
);
1376 ShowWindow(This
->cctrls_hwnd
, FALSE
);
1378 wndstyle
= GetWindowLongW(This
->cctrls_hwnd
, GWL_STYLE
);
1379 wndstyle
&= ~(WS_CHILD
);
1380 wndstyle
|= WS_POPUP
;
1381 SetWindowLongW(This
->cctrls_hwnd
, GWL_STYLE
, wndstyle
);
1383 SetParent(This
->cctrls_hwnd
, NULL
);
1387 static LRESULT
ctrl_container_on_create(HWND hwnd
, CREATESTRUCTW
*crs
)
1389 FileDialogImpl
*This
= crs
->lpCreateParams
;
1390 TRACE("%p\n", This
);
1392 SetWindowLongPtrW(hwnd
, GWLP_USERDATA
, (LPARAM
)This
);
1396 static LRESULT
ctrl_container_on_wm_destroy(FileDialogImpl
*This
)
1398 customctrl
*cur1
, *cur2
;
1399 TRACE("%p\n", This
);
1401 LIST_FOR_EACH_ENTRY_SAFE(cur1
, cur2
, &This
->cctrls
, customctrl
, entry
)
1403 list_remove(&cur1
->entry
);
1410 static LRESULT CALLBACK
ctrl_container_wndproc(HWND hwnd
, UINT umessage
, WPARAM wparam
, LPARAM lparam
)
1412 FileDialogImpl
*This
= (FileDialogImpl
*)GetWindowLongPtrW(hwnd
, GWLP_USERDATA
);
1416 case WM_NCCREATE
: return ctrl_container_on_create(hwnd
, (CREATESTRUCTW
*)lparam
);
1417 case WM_DESTROY
: return ctrl_container_on_wm_destroy(This
);
1418 default: return DefWindowProcW(hwnd
, umessage
, wparam
, lparam
);
1424 static void radiobuttonlist_set_selected_item(FileDialogImpl
*This
, customctrl
*ctrl
, cctrl_item
*item
)
1428 LIST_FOR_EACH_ENTRY(cursor
, &ctrl
->sub_items
, cctrl_item
, entry
)
1430 SendMessageW(cursor
->hwnd
, BM_SETCHECK
, (cursor
== item
) ? BST_CHECKED
: BST_UNCHECKED
, 0);
1434 static LRESULT
radiobuttonlist_on_bn_clicked(FileDialogImpl
*This
, HWND hwnd
, HWND child
)
1436 DWORD ctrl_id
= (DWORD
)GetWindowLongPtrW(hwnd
, GWLP_ID
);
1439 BOOL found_item
=FALSE
;
1441 ctrl
= get_cctrl_from_dlgid(This
, ctrl_id
);
1445 ERR("Can't find this control\n");
1449 LIST_FOR_EACH_ENTRY(item
, &ctrl
->sub_items
, cctrl_item
, entry
)
1451 if (item
->hwnd
== child
)
1460 ERR("Can't find control item\n");
1464 radiobuttonlist_set_selected_item(This
, ctrl
, item
);
1466 cctrl_event_OnItemSelected(This
, ctrl
->id
, item
->id
);
1471 static LRESULT
radiobuttonlist_on_wm_command(FileDialogImpl
*This
, HWND hwnd
, WPARAM wparam
, LPARAM lparam
)
1473 switch(HIWORD(wparam
))
1475 case BN_CLICKED
: return radiobuttonlist_on_bn_clicked(This
, hwnd
, (HWND
)lparam
);
1481 static LRESULT CALLBACK
radiobuttonlist_proc(HWND hwnd
, UINT message
, WPARAM wparam
, LPARAM lparam
)
1483 FileDialogImpl
*This
= (FileDialogImpl
*)GetWindowLongPtrW(hwnd
, GWLP_USERDATA
);
1487 case WM_COMMAND
: return radiobuttonlist_on_wm_command(This
, hwnd
, wparam
, lparam
);
1490 return DefWindowProcW(hwnd
, message
, wparam
, lparam
);
1493 static HRESULT
init_custom_controls(FileDialogImpl
*This
)
1497 static const WCHAR ctrl_container_classname
[] =
1498 {'i','d','l','g','_','c','o','n','t','a','i','n','e','r','_','p','a','n','e',0};
1500 InitCommonControlsEx(NULL
);
1502 if( !GetClassInfoW(COMDLG32_hInstance
, ctrl_container_classname
, &wc
) )
1504 wc
.style
= CS_HREDRAW
| CS_VREDRAW
;
1505 wc
.lpfnWndProc
= ctrl_container_wndproc
;
1508 wc
.hInstance
= COMDLG32_hInstance
;
1510 wc
.hCursor
= LoadCursorW(0, (LPWSTR
)IDC_ARROW
);
1511 wc
.hbrBackground
= (HBRUSH
)(COLOR_BTNFACE
+ 1);
1512 wc
.lpszMenuName
= NULL
;
1513 wc
.lpszClassName
= ctrl_container_classname
;
1515 if(!RegisterClassW(&wc
)) return E_FAIL
;
1518 This
->cctrls_hwnd
= CreateWindowExW(0, ctrl_container_classname
, NULL
,
1519 WS_CLIPSIBLINGS
| WS_CLIPCHILDREN
,
1520 0, 0, 0, 0, NULL
, 0,
1521 COMDLG32_hInstance
, This
);
1522 if(!This
->cctrls_hwnd
)
1525 hdc
= GetDC(This
->cctrls_hwnd
);
1526 This
->dpi_x
= GetDeviceCaps(hdc
, LOGPIXELSX
);
1527 This
->dpi_y
= GetDeviceCaps(hdc
, LOGPIXELSY
);
1528 ReleaseDC(This
->cctrls_hwnd
, hdc
);
1530 This
->cctrl_width
= MulDiv(160, This
->dpi_x
, USER_DEFAULT_SCREEN_DPI
); /* Controls have a fixed width */
1531 This
->cctrl_indent
= MulDiv(100, This
->dpi_x
, USER_DEFAULT_SCREEN_DPI
);
1532 This
->cctrl_def_height
= MulDiv(23, This
->dpi_y
, USER_DEFAULT_SCREEN_DPI
);
1533 This
->cctrls_cols
= 0;
1535 This
->cctrl_next_dlgid
= 0x2000;
1536 list_init(&This
->cctrls
);
1537 This
->cctrl_active_vg
= NULL
;
1539 SetWindowLongW(This
->cctrls_hwnd
, GWL_STYLE
, WS_TABSTOP
);
1541 /* Register class for */
1542 if( !GetClassInfoW(COMDLG32_hInstance
, floatnotifysinkW
, &wc
) ||
1543 wc
.hInstance
!= COMDLG32_hInstance
)
1545 wc
.style
= CS_HREDRAW
| CS_VREDRAW
;
1546 wc
.lpfnWndProc
= notifysink_proc
;
1549 wc
.hInstance
= COMDLG32_hInstance
;
1551 wc
.hCursor
= LoadCursorW(0, (LPWSTR
)IDC_ARROW
);
1552 wc
.hbrBackground
= (HBRUSH
)(COLOR_BTNFACE
+ 1);
1553 wc
.lpszMenuName
= NULL
;
1554 wc
.lpszClassName
= floatnotifysinkW
;
1556 if (!RegisterClassW(&wc
))
1557 ERR("Failed to register FloatNotifySink window class.\n");
1560 if( !GetClassInfoW(COMDLG32_hInstance
, radiobuttonlistW
, &wc
) ||
1561 wc
.hInstance
!= COMDLG32_hInstance
)
1563 wc
.style
= CS_HREDRAW
| CS_VREDRAW
;
1564 wc
.lpfnWndProc
= radiobuttonlist_proc
;
1567 wc
.hInstance
= COMDLG32_hInstance
;
1569 wc
.hCursor
= LoadCursorW(0, (LPWSTR
)IDC_ARROW
);
1570 wc
.hbrBackground
= (HBRUSH
)(COLOR_BTNFACE
+ 1);
1571 wc
.lpszMenuName
= NULL
;
1572 wc
.lpszClassName
= radiobuttonlistW
;
1574 if (!RegisterClassW(&wc
))
1575 ERR("Failed to register RadioButtonList window class.\n");
1581 /**************************************************************************
1582 * Window related functions.
1584 static BOOL
update_open_dropdown(FileDialogImpl
*This
)
1586 /* Show or hide the open dropdown button as appropriate */
1587 BOOL show
=FALSE
, showing
;
1588 HWND open_hwnd
, dropdown_hwnd
;
1590 if (This
->hmenu_opendropdown
)
1592 INT num_visible_items
=0;
1595 LIST_FOR_EACH_ENTRY(item
, &This
->cctrl_opendropdown
.sub_items
, cctrl_item
, entry
)
1597 if (item
->cdcstate
& CDCS_VISIBLE
)
1599 num_visible_items
++;
1600 if (num_visible_items
>= 2)
1609 open_hwnd
= GetDlgItem(This
->dlg_hwnd
, IDOK
);
1610 dropdown_hwnd
= GetDlgItem(This
->dlg_hwnd
, psh1
);
1612 showing
= (GetWindowLongPtrW(dropdown_hwnd
, GWL_STYLE
) & WS_VISIBLE
) != 0;
1614 if (showing
!= show
)
1616 RECT open_rc
, dropdown_rc
;
1618 GetWindowRect(open_hwnd
, &open_rc
);
1619 GetWindowRect(dropdown_hwnd
, &dropdown_rc
);
1623 ShowWindow(dropdown_hwnd
, SW_SHOW
);
1625 SetWindowPos(open_hwnd
, NULL
, 0, 0,
1626 (open_rc
.right
- open_rc
.left
) - (dropdown_rc
.right
- dropdown_rc
.left
),
1627 open_rc
.bottom
- open_rc
.top
, SWP_NOZORDER
| SWP_NOMOVE
| SWP_NOACTIVATE
);
1631 ShowWindow(dropdown_hwnd
, SW_HIDE
);
1633 SetWindowPos(open_hwnd
, NULL
, 0, 0,
1634 (open_rc
.right
- open_rc
.left
) + (dropdown_rc
.right
- dropdown_rc
.left
),
1635 open_rc
.bottom
- open_rc
.top
, SWP_NOZORDER
| SWP_NOMOVE
| SWP_NOACTIVATE
);
1642 static void update_layout(FileDialogImpl
*This
)
1647 RECT cancel_rc
, dropdown_rc
, open_rc
;
1648 RECT filetype_rc
, filename_rc
, filenamelabel_rc
;
1649 RECT toolbar_rc
, ebrowser_rc
, customctrls_rc
;
1650 static const UINT vspacing
= 4, hspacing
= 4;
1651 static const UINT min_width
= 320, min_height
= 200;
1654 if (!GetClientRect(This
->dlg_hwnd
, &dialog_rc
))
1656 TRACE("Invalid dialog window, not updating layout\n");
1660 if(dialog_rc
.right
< min_width
|| dialog_rc
.bottom
< min_height
)
1662 TRACE("Dialog size (%d, %d) too small, not updating layout\n", dialog_rc
.right
, dialog_rc
.bottom
);
1667 * Calculate the size of the dialog and all the parts.
1671 hwnd
= GetDlgItem(This
->dlg_hwnd
, IDCANCEL
);
1674 int cancel_width
, cancel_height
;
1675 GetWindowRect(hwnd
, &cancel_rc
);
1676 cancel_width
= cancel_rc
.right
- cancel_rc
.left
;
1677 cancel_height
= cancel_rc
.bottom
- cancel_rc
.top
;
1679 cancel_rc
.left
= dialog_rc
.right
- cancel_width
- hspacing
;
1680 cancel_rc
.top
= dialog_rc
.bottom
- cancel_height
- vspacing
;
1681 cancel_rc
.right
= cancel_rc
.left
+ cancel_width
;
1682 cancel_rc
.bottom
= cancel_rc
.top
+ cancel_height
;
1685 /* Open/Save dropdown */
1686 show_dropdown
= update_open_dropdown(This
);
1690 int dropdown_width
, dropdown_height
;
1691 hwnd
= GetDlgItem(This
->dlg_hwnd
, psh1
);
1693 GetWindowRect(hwnd
, &dropdown_rc
);
1694 dropdown_width
= dropdown_rc
.right
- dropdown_rc
.left
;
1695 dropdown_height
= dropdown_rc
.bottom
- dropdown_rc
.top
;
1697 dropdown_rc
.left
= cancel_rc
.left
- dropdown_width
- hspacing
;
1698 dropdown_rc
.top
= cancel_rc
.top
;
1699 dropdown_rc
.right
= dropdown_rc
.left
+ dropdown_width
;
1700 dropdown_rc
.bottom
= dropdown_rc
.top
+ dropdown_height
;
1704 dropdown_rc
.left
= dropdown_rc
.right
= cancel_rc
.left
- hspacing
;
1705 dropdown_rc
.top
= cancel_rc
.top
;
1706 dropdown_rc
.bottom
= cancel_rc
.bottom
;
1709 /* Open/Save button */
1710 hwnd
= GetDlgItem(This
->dlg_hwnd
, IDOK
);
1713 int open_width
, open_height
;
1714 GetWindowRect(hwnd
, &open_rc
);
1715 open_width
= open_rc
.right
- open_rc
.left
;
1716 open_height
= open_rc
.bottom
- open_rc
.top
;
1718 open_rc
.left
= dropdown_rc
.left
- open_width
;
1719 open_rc
.top
= dropdown_rc
.top
;
1720 open_rc
.right
= open_rc
.left
+ open_width
;
1721 open_rc
.bottom
= open_rc
.top
+ open_height
;
1724 /* The filetype combobox. */
1725 hwnd
= GetDlgItem(This
->dlg_hwnd
, IDC_FILETYPE
);
1728 int filetype_width
, filetype_height
;
1729 GetWindowRect(hwnd
, &filetype_rc
);
1731 filetype_width
= filetype_rc
.right
- filetype_rc
.left
;
1732 filetype_height
= filetype_rc
.bottom
- filetype_rc
.top
;
1734 filetype_rc
.right
= cancel_rc
.right
;
1736 filetype_rc
.left
= filetype_rc
.right
- filetype_width
;
1737 filetype_rc
.top
= cancel_rc
.top
- filetype_height
- vspacing
;
1738 filetype_rc
.bottom
= filetype_rc
.top
+ filetype_height
;
1740 if(!This
->filterspec_count
)
1741 filetype_rc
.left
= filetype_rc
.right
;
1744 /* Filename label. */
1745 hwnd
= GetDlgItem(This
->dlg_hwnd
, IDC_FILENAMESTATIC
);
1748 int filetypelabel_width
, filetypelabel_height
;
1749 GetWindowRect(hwnd
, &filenamelabel_rc
);
1751 filetypelabel_width
= filenamelabel_rc
.right
- filenamelabel_rc
.left
;
1752 filetypelabel_height
= filenamelabel_rc
.bottom
- filenamelabel_rc
.top
;
1754 filenamelabel_rc
.left
= 160; /* FIXME */
1755 filenamelabel_rc
.top
= filetype_rc
.top
;
1756 filenamelabel_rc
.right
= filenamelabel_rc
.left
+ filetypelabel_width
;
1757 filenamelabel_rc
.bottom
= filenamelabel_rc
.top
+ filetypelabel_height
;
1760 /* Filename edit box. */
1761 hwnd
= GetDlgItem(This
->dlg_hwnd
, IDC_FILENAME
);
1764 int filename_width
, filename_height
;
1765 GetWindowRect(hwnd
, &filename_rc
);
1767 filename_width
= filetype_rc
.left
- filenamelabel_rc
.right
- hspacing
*2;
1768 filename_height
= filename_rc
.bottom
- filename_rc
.top
;
1770 filename_rc
.left
= filenamelabel_rc
.right
+ hspacing
;
1771 filename_rc
.top
= filetype_rc
.top
;
1772 filename_rc
.right
= filename_rc
.left
+ filename_width
;
1773 filename_rc
.bottom
= filename_rc
.top
+ filename_height
;
1776 hwnd
= GetDlgItem(This
->dlg_hwnd
, IDC_NAV_TOOLBAR
);
1779 GetWindowRect(hwnd
, &toolbar_rc
);
1780 MapWindowPoints(NULL
, This
->dlg_hwnd
, (POINT
*)&toolbar_rc
, 2);
1783 /* The custom controls */
1784 customctrls_rc
.left
= dialog_rc
.left
+ hspacing
;
1785 customctrls_rc
.right
= dialog_rc
.right
- hspacing
;
1786 customctrls_rc
.bottom
= filename_rc
.top
- vspacing
;
1787 customctrls_rc
.top
= customctrls_rc
.bottom
-
1788 ctrl_container_resize(This
, customctrls_rc
.right
- customctrls_rc
.left
);
1790 /* The ExplorerBrowser control. */
1791 ebrowser_rc
.left
= dialog_rc
.left
+ hspacing
;
1792 ebrowser_rc
.top
= toolbar_rc
.bottom
+ vspacing
;
1793 ebrowser_rc
.right
= dialog_rc
.right
- hspacing
;
1794 ebrowser_rc
.bottom
= customctrls_rc
.top
- vspacing
;
1797 * Move everything to the right place.
1800 /* FIXME: The Save Dialog uses a slightly different layout. */
1801 hdwp
= BeginDeferWindowPos(7);
1803 if(hdwp
&& This
->peb
)
1804 IExplorerBrowser_SetRect(This
->peb
, &hdwp
, ebrowser_rc
);
1806 if(hdwp
&& This
->cctrls_hwnd
)
1807 DeferWindowPos(hdwp
, This
->cctrls_hwnd
, NULL
,
1808 customctrls_rc
.left
, customctrls_rc
.top
,
1809 customctrls_rc
.right
- customctrls_rc
.left
, customctrls_rc
.bottom
- customctrls_rc
.top
,
1810 SWP_NOZORDER
| SWP_NOACTIVATE
);
1812 /* The default controls */
1813 if(hdwp
&& (hwnd
= GetDlgItem(This
->dlg_hwnd
, IDC_FILETYPE
)) )
1814 DeferWindowPos(hdwp
, hwnd
, NULL
, filetype_rc
.left
, filetype_rc
.top
, 0, 0,
1815 SWP_NOZORDER
| SWP_NOSIZE
| SWP_NOACTIVATE
);
1817 if(hdwp
&& (hwnd
= GetDlgItem(This
->dlg_hwnd
, IDC_FILENAME
)) )
1818 DeferWindowPos(hdwp
, hwnd
, NULL
, filename_rc
.left
, filename_rc
.top
,
1819 filename_rc
.right
- filename_rc
.left
, filename_rc
.bottom
- filename_rc
.top
,
1820 SWP_NOZORDER
| SWP_NOACTIVATE
);
1822 if(hdwp
&& (hwnd
= GetDlgItem(This
->dlg_hwnd
, IDC_FILENAMESTATIC
)) )
1823 DeferWindowPos(hdwp
, hwnd
, NULL
, filenamelabel_rc
.left
, filenamelabel_rc
.top
, 0, 0,
1824 SWP_NOZORDER
| SWP_NOSIZE
| SWP_NOACTIVATE
);
1826 if(hdwp
&& (hwnd
= GetDlgItem(This
->dlg_hwnd
, IDOK
)) )
1827 DeferWindowPos(hdwp
, hwnd
, NULL
, open_rc
.left
, open_rc
.top
, 0, 0,
1828 SWP_NOZORDER
| SWP_NOSIZE
| SWP_NOACTIVATE
);
1830 if(hdwp
&& This
->hmenu_opendropdown
&& (hwnd
= GetDlgItem(This
->dlg_hwnd
, psh1
)))
1831 DeferWindowPos(hdwp
, hwnd
, NULL
, dropdown_rc
.left
, dropdown_rc
.top
, 0, 0,
1832 SWP_NOZORDER
| SWP_NOSIZE
| SWP_NOACTIVATE
);
1834 if(hdwp
&& (hwnd
= GetDlgItem(This
->dlg_hwnd
, IDCANCEL
)) )
1835 DeferWindowPos(hdwp
, hwnd
, NULL
, cancel_rc
.left
, cancel_rc
.top
, 0, 0,
1836 SWP_NOZORDER
| SWP_NOSIZE
| SWP_NOACTIVATE
);
1839 EndDeferWindowPos(hdwp
);
1841 ERR("Failed to position dialog controls.\n");
1846 static HRESULT
init_explorerbrowser(FileDialogImpl
*This
)
1848 IShellItem
*psi_folder
;
1849 IObjectWithSite
*client
;
1854 /* Create ExplorerBrowser instance */
1855 OleInitialize(NULL
);
1857 hr
= CoCreateInstance(&CLSID_ExplorerBrowser
, NULL
, CLSCTX_INPROC_SERVER
,
1858 &IID_IExplorerBrowser
, (void**)&This
->peb
);
1861 ERR("Failed to instantiate ExplorerBrowser control.\n");
1865 IExplorerBrowser_SetOptions(This
->peb
, EBO_SHOWFRAMES
| EBO_NOBORDER
);
1867 hr
= IExplorerBrowser_Initialize(This
->peb
, This
->dlg_hwnd
, &rc
, NULL
);
1870 ERR("Failed to initialize the ExplorerBrowser control.\n");
1871 IExplorerBrowser_Release(This
->peb
);
1875 hr
= IExplorerBrowser_Advise(This
->peb
, &This
->IExplorerBrowserEvents_iface
, &This
->ebevents_cookie
);
1877 ERR("Advise (ExplorerBrowser) failed.\n");
1879 /* Get previous options? */
1880 fos
.ViewMode
= fos
.fFlags
= 0;
1881 if(!(This
->options
& FOS_ALLOWMULTISELECT
))
1882 fos
.fFlags
|= FWF_SINGLESEL
;
1884 IExplorerBrowser_SetFolderSettings(This
->peb
, &fos
);
1886 hr
= IExplorerBrowser_QueryInterface(This
->peb
, &IID_IObjectWithSite
, (void**)&client
);
1889 hr
= IObjectWithSite_SetSite(client
, (IUnknown
*)&This
->IFileDialog2_iface
);
1890 IObjectWithSite_Release(client
);
1892 ERR("SetSite failed, 0x%08x\n", hr
);
1895 /* Browse somewhere */
1896 psi_folder
= This
->psi_setfolder
? This
->psi_setfolder
: This
->psi_defaultfolder
;
1897 IExplorerBrowser_BrowseToObject(This
->peb
, (IUnknown
*)psi_folder
, SBSP_DEFBROWSER
);
1902 static void init_toolbar(FileDialogImpl
*This
, HWND hwnd
)
1908 htoolbar
= CreateWindowExW(0, TOOLBARCLASSNAMEW
, NULL
, TBSTYLE_FLAT
| WS_CHILD
| WS_VISIBLE
,
1910 hwnd
, (HMENU
)IDC_NAV_TOOLBAR
, NULL
, NULL
);
1912 tbab
.hInst
= HINST_COMMCTRL
;
1913 tbab
.nID
= IDB_HIST_LARGE_COLOR
;
1914 SendMessageW(htoolbar
, TB_ADDBITMAP
, 0, (LPARAM
)&tbab
);
1916 button
[0].iBitmap
= HIST_BACK
;
1917 button
[0].idCommand
= IDC_NAVBACK
;
1918 button
[0].fsState
= TBSTATE_ENABLED
;
1919 button
[0].fsStyle
= BTNS_BUTTON
;
1920 button
[0].dwData
= 0;
1921 button
[0].iString
= 0;
1923 button
[1].iBitmap
= HIST_FORWARD
;
1924 button
[1].idCommand
= IDC_NAVFORWARD
;
1925 button
[1].fsState
= TBSTATE_ENABLED
;
1926 button
[1].fsStyle
= BTNS_BUTTON
;
1927 button
[1].dwData
= 0;
1928 button
[1].iString
= 0;
1930 SendMessageW(htoolbar
, TB_ADDBUTTONSW
, 2, (LPARAM
)button
);
1931 SendMessageW(htoolbar
, TB_SETBUTTONSIZE
, 0, MAKELPARAM(24,24));
1932 SendMessageW(htoolbar
, TB_AUTOSIZE
, 0, 0);
1935 static void update_control_text(FileDialogImpl
*This
)
1938 LPCWSTR custom_okbutton
;
1940 UINT min_width
= MulDiv(50, This
->dpi_x
, USER_DEFAULT_SCREEN_DPI
);
1941 UINT max_width
= MulDiv(250, This
->dpi_x
, USER_DEFAULT_SCREEN_DPI
);
1943 if(This
->custom_title
)
1944 SetWindowTextW(This
->dlg_hwnd
, This
->custom_title
);
1946 if(This
->hmenu_opendropdown
&& (item
= get_first_item(&This
->cctrl_opendropdown
)))
1947 custom_okbutton
= item
->label
;
1949 custom_okbutton
= This
->custom_okbutton
;
1951 if(custom_okbutton
&&
1952 (hitem
= GetDlgItem(This
->dlg_hwnd
, IDOK
)))
1954 SetWindowTextW(hitem
, custom_okbutton
);
1955 ctrl_resize(hitem
, min_width
, max_width
, FALSE
);
1958 if(This
->custom_cancelbutton
&&
1959 (hitem
= GetDlgItem(This
->dlg_hwnd
, IDCANCEL
)))
1961 SetWindowTextW(hitem
, This
->custom_cancelbutton
);
1962 ctrl_resize(hitem
, min_width
, max_width
, FALSE
);
1965 if(This
->custom_filenamelabel
&&
1966 (hitem
= GetDlgItem(This
->dlg_hwnd
, IDC_FILENAMESTATIC
)))
1968 SetWindowTextW(hitem
, This
->custom_filenamelabel
);
1969 ctrl_resize(hitem
, min_width
, max_width
, FALSE
);
1973 static LRESULT CALLBACK
dropdown_subclass_proc(HWND hwnd
, UINT umessage
, WPARAM wparam
, LPARAM lparam
)
1975 static const WCHAR prop_this
[] = {'i','t','e','m','d','l','g','_','T','h','i','s',0};
1976 static const WCHAR prop_oldwndproc
[] = {'i','t','e','m','d','l','g','_','o','l','d','w','n','d','p','r','o','c',0};
1978 if (umessage
== WM_LBUTTONDOWN
)
1980 FileDialogImpl
*This
= GetPropW(hwnd
, prop_this
);
1982 SendMessageW(hwnd
, BM_SETCHECK
, BST_CHECKED
, 0);
1983 show_opendropdown(This
);
1984 SendMessageW(hwnd
, BM_SETCHECK
, BST_UNCHECKED
, 0);
1989 return CallWindowProcW((WNDPROC
)GetPropW(hwnd
, prop_oldwndproc
), hwnd
, umessage
, wparam
, lparam
);
1992 static LRESULT
on_wm_initdialog(HWND hwnd
, LPARAM lParam
)
1994 FileDialogImpl
*This
= (FileDialogImpl
*)lParam
;
1997 TRACE("(%p, %p)\n", This
, hwnd
);
1999 SetWindowLongPtrW(hwnd
, GWLP_USERDATA
, (LPARAM
)This
);
2000 This
->dlg_hwnd
= hwnd
;
2002 hitem
= GetDlgItem(This
->dlg_hwnd
, pshHelp
);
2003 if(hitem
) ShowWindow(hitem
, SW_HIDE
);
2005 hitem
= GetDlgItem(This
->dlg_hwnd
, IDC_FILETYPESTATIC
);
2006 if(hitem
) ShowWindow(hitem
, SW_HIDE
);
2008 /* Fill filetypes combobox, or hide it. */
2009 hitem
= GetDlgItem(This
->dlg_hwnd
, IDC_FILETYPE
);
2010 if(This
->filterspec_count
)
2015 UINT i
, maxwidth
= 0;
2018 font
= (HFONT
)SendMessageW(hitem
, WM_GETFONT
, 0, 0);
2019 SelectObject(hdc
, font
);
2021 for(i
= 0; i
< This
->filterspec_count
; i
++)
2023 SendMessageW(hitem
, CB_ADDSTRING
, 0, (LPARAM
)This
->filterspecs
[i
].pszName
);
2025 if(GetTextExtentPoint32W(hdc
, This
->filterspecs
[i
].pszName
, lstrlenW(This
->filterspecs
[i
].pszName
), &size
))
2026 maxwidth
= max(maxwidth
, size
.cx
);
2028 ReleaseDC(hitem
, hdc
);
2032 maxwidth
+= GetSystemMetrics(SM_CXVSCROLL
) + 4;
2033 SendMessageW(hitem
, CB_SETDROPPEDWIDTH
, (WPARAM
)maxwidth
, 0);
2036 ERR("Failed to calculate width of filetype dropdown\n");
2038 SendMessageW(hitem
, CB_SETCURSEL
, This
->filetypeindex
, 0);
2041 ShowWindow(hitem
, SW_HIDE
);
2043 if(This
->set_filename
&&
2044 (hitem
= GetDlgItem(This
->dlg_hwnd
, IDC_FILENAME
)) )
2045 SendMessageW(hitem
, WM_SETTEXT
, 0, (LPARAM
)This
->set_filename
);
2047 if(This
->hmenu_opendropdown
)
2050 LOGFONTW lfw
, lfw_marlett
;
2052 static const WCHAR marlett
[] = {'M','a','r','l','e','t','t',0};
2053 static const WCHAR prop_this
[] = {'i','t','e','m','d','l','g','_','T','h','i','s',0};
2054 static const WCHAR prop_oldwndproc
[] = {'i','t','e','m','d','l','g','_','o','l','d','w','n','d','p','r','o','c',0};
2056 dropdown_hwnd
= GetDlgItem(This
->dlg_hwnd
, psh1
);
2058 /* Change dropdown button font to Marlett */
2059 dialog_font
= (HFONT
)SendMessageW(dropdown_hwnd
, WM_GETFONT
, 0, 0);
2061 GetObjectW(dialog_font
, sizeof(lfw
), &lfw
);
2063 memset(&lfw_marlett
, 0, sizeof(lfw_marlett
));
2064 lstrcpyW(lfw_marlett
.lfFaceName
, marlett
);
2065 lfw_marlett
.lfHeight
= lfw
.lfHeight
;
2066 lfw_marlett
.lfCharSet
= SYMBOL_CHARSET
;
2068 This
->hfont_opendropdown
= CreateFontIndirectW(&lfw_marlett
);
2070 SendMessageW(dropdown_hwnd
, WM_SETFONT
, (LPARAM
)This
->hfont_opendropdown
, 0);
2072 /* Subclass button so we can handle LBUTTONDOWN */
2073 SetPropW(dropdown_hwnd
, prop_this
, This
);
2074 SetPropW(dropdown_hwnd
, prop_oldwndproc
,
2075 (HANDLE
)SetWindowLongPtrW(dropdown_hwnd
, GWLP_WNDPROC
, (LONG_PTR
)dropdown_subclass_proc
));
2078 ctrl_container_reparent(This
, This
->dlg_hwnd
);
2079 init_explorerbrowser(This
);
2080 init_toolbar(This
, hwnd
);
2081 update_control_text(This
);
2082 update_layout(This
);
2084 if(This
->filterspec_count
)
2085 events_OnTypeChange(This
);
2087 if ((hitem
= GetDlgItem(This
->dlg_hwnd
, IDC_FILENAME
)))
2093 static LRESULT
on_wm_size(FileDialogImpl
*This
)
2095 update_layout(This
);
2099 static LRESULT
on_wm_getminmaxinfo(FileDialogImpl
*This
, LPARAM lparam
)
2101 MINMAXINFO
*mmi
= (MINMAXINFO
*)lparam
;
2102 TRACE("%p (%p)\n", This
, mmi
);
2105 mmi
->ptMinTrackSize
.x
= 640;
2106 mmi
->ptMinTrackSize
.y
= 480;
2111 static LRESULT
on_wm_destroy(FileDialogImpl
*This
)
2113 TRACE("%p\n", This
);
2117 IExplorerBrowser_Destroy(This
->peb
);
2118 IExplorerBrowser_Release(This
->peb
);
2122 ctrl_container_reparent(This
, NULL
);
2123 This
->dlg_hwnd
= NULL
;
2125 DeleteObject(This
->hfont_opendropdown
);
2126 This
->hfont_opendropdown
= NULL
;
2131 static LRESULT
on_idok(FileDialogImpl
*This
)
2133 TRACE("%p\n", This
);
2135 if(SUCCEEDED(on_default_action(This
)))
2136 EndDialog(This
->dlg_hwnd
, S_OK
);
2141 static LRESULT
on_idcancel(FileDialogImpl
*This
)
2143 TRACE("%p\n", This
);
2145 EndDialog(This
->dlg_hwnd
, HRESULT_FROM_WIN32(ERROR_CANCELLED
));
2150 static LRESULT
on_command_opendropdown(FileDialogImpl
*This
, WPARAM wparam
, LPARAM lparam
)
2152 if(HIWORD(wparam
) == BN_CLICKED
)
2154 HWND hwnd
= (HWND
)lparam
;
2155 SendMessageW(hwnd
, BM_SETCHECK
, BST_CHECKED
, 0);
2156 show_opendropdown(This
);
2157 SendMessageW(hwnd
, BM_SETCHECK
, BST_UNCHECKED
, 0);
2163 static LRESULT
on_browse_back(FileDialogImpl
*This
)
2165 TRACE("%p\n", This
);
2166 IExplorerBrowser_BrowseToIDList(This
->peb
, NULL
, SBSP_NAVIGATEBACK
);
2170 static LRESULT
on_browse_forward(FileDialogImpl
*This
)
2172 TRACE("%p\n", This
);
2173 IExplorerBrowser_BrowseToIDList(This
->peb
, NULL
, SBSP_NAVIGATEFORWARD
);
2177 static LRESULT
on_command_filetype(FileDialogImpl
*This
, WPARAM wparam
, LPARAM lparam
)
2179 if(HIWORD(wparam
) == CBN_SELCHANGE
)
2184 UINT prev_index
= This
->filetypeindex
;
2186 This
->filetypeindex
= SendMessageW((HWND
)lparam
, CB_GETCURSEL
, 0, 0);
2187 TRACE("File type selection changed to %d.\n", This
->filetypeindex
);
2189 if(prev_index
== This
->filetypeindex
)
2192 hr
= IExplorerBrowser_GetCurrentView(This
->peb
, &IID_IShellView
, (void**)&psv
);
2195 IShellView_Refresh(psv
);
2196 IShellView_Release(psv
);
2199 if(This
->dlg_type
== ITEMDLG_TYPE_SAVE
&& get_file_name(This
, &filename
))
2201 WCHAR buf
[MAX_PATH
], extbuf
[MAX_PATH
], *ext
;
2203 ext
= get_first_ext_from_spec(extbuf
, This
->filterspecs
[This
->filetypeindex
].pszSpec
);
2206 lstrcpyW(buf
, filename
);
2208 if(PathMatchSpecW(buf
, This
->filterspecs
[prev_index
].pszSpec
))
2209 PathRemoveExtensionW(buf
);
2212 set_file_name(This
, buf
);
2214 CoTaskMemFree(filename
);
2217 /* The documentation claims that OnTypeChange is called only
2218 * when the dialog is opened, but this is obviously not the
2220 events_OnTypeChange(This
);
2226 static LRESULT
on_wm_command(FileDialogImpl
*This
, WPARAM wparam
, LPARAM lparam
)
2228 switch(LOWORD(wparam
))
2230 case IDOK
: return on_idok(This
);
2231 case IDCANCEL
: return on_idcancel(This
);
2232 case psh1
: return on_command_opendropdown(This
, wparam
, lparam
);
2233 case IDC_NAVBACK
: return on_browse_back(This
);
2234 case IDC_NAVFORWARD
: return on_browse_forward(This
);
2235 case IDC_FILETYPE
: return on_command_filetype(This
, wparam
, lparam
);
2236 default: TRACE("Unknown command.\n");
2241 static LRESULT CALLBACK
itemdlg_dlgproc(HWND hwnd
, UINT umessage
, WPARAM wparam
, LPARAM lparam
)
2243 FileDialogImpl
*This
= (FileDialogImpl
*)GetWindowLongPtrW(hwnd
, GWLP_USERDATA
);
2247 case WM_INITDIALOG
: return on_wm_initdialog(hwnd
, lparam
);
2248 case WM_COMMAND
: return on_wm_command(This
, wparam
, lparam
);
2249 case WM_SIZE
: return on_wm_size(This
);
2250 case WM_GETMINMAXINFO
: return on_wm_getminmaxinfo(This
, lparam
);
2251 case WM_DESTROY
: return on_wm_destroy(This
);
2257 static HRESULT
create_dialog(FileDialogImpl
*This
, HWND parent
)
2262 res
= DialogBoxParamW(COMDLG32_hInstance
,
2263 MAKEINTRESOURCEW(NEWFILEOPENV3ORD
),
2264 parent
, itemdlg_dlgproc
, (LPARAM
)This
);
2265 This
->dlg_hwnd
= NULL
;
2268 ERR("Failed to show dialog (LastError: %d)\n", GetLastError());
2272 TRACE("Returning 0x%08x\n", (HRESULT
)res
);
2273 return (HRESULT
)res
;
2276 /**************************************************************************
2277 * IFileDialog implementation
2279 static inline FileDialogImpl
*impl_from_IFileDialog2(IFileDialog2
*iface
)
2281 return CONTAINING_RECORD(iface
, FileDialogImpl
, IFileDialog2_iface
);
2284 static HRESULT WINAPI
IFileDialog2_fnQueryInterface(IFileDialog2
*iface
,
2288 FileDialogImpl
*This
= impl_from_IFileDialog2(iface
);
2289 TRACE("%p (%s, %p)\n", This
, debugstr_guid(riid
), ppvObject
);
2292 if(IsEqualGUID(riid
, &IID_IUnknown
) ||
2293 IsEqualGUID(riid
, &IID_IFileDialog
) ||
2294 IsEqualGUID(riid
, &IID_IFileDialog2
))
2298 else if(IsEqualGUID(riid
, &IID_IFileOpenDialog
) && This
->dlg_type
== ITEMDLG_TYPE_OPEN
)
2300 *ppvObject
= &This
->u
.IFileOpenDialog_iface
;
2302 else if(IsEqualGUID(riid
, &IID_IFileSaveDialog
) && This
->dlg_type
== ITEMDLG_TYPE_SAVE
)
2304 *ppvObject
= &This
->u
.IFileSaveDialog_iface
;
2306 else if(IsEqualGUID(riid
, &IID_IExplorerBrowserEvents
))
2308 *ppvObject
= &This
->IExplorerBrowserEvents_iface
;
2310 else if(IsEqualGUID(riid
, &IID_IServiceProvider
))
2312 *ppvObject
= &This
->IServiceProvider_iface
;
2314 else if(IsEqualGUID(&IID_ICommDlgBrowser3
, riid
) ||
2315 IsEqualGUID(&IID_ICommDlgBrowser2
, riid
) ||
2316 IsEqualGUID(&IID_ICommDlgBrowser
, riid
))
2318 *ppvObject
= &This
->ICommDlgBrowser3_iface
;
2320 else if(IsEqualGUID(&IID_IOleWindow
, riid
))
2322 *ppvObject
= &This
->IOleWindow_iface
;
2324 else if(IsEqualGUID(riid
, &IID_IFileDialogCustomize
) ||
2325 IsEqualGUID(riid
, &IID_IFileDialogCustomizeAlt
))
2327 *ppvObject
= &This
->IFileDialogCustomize_iface
;
2330 FIXME("Unknown interface requested: %s.\n", debugstr_guid(riid
));
2334 IUnknown_AddRef((IUnknown
*)*ppvObject
);
2338 return E_NOINTERFACE
;
2341 static ULONG WINAPI
IFileDialog2_fnAddRef(IFileDialog2
*iface
)
2343 FileDialogImpl
*This
= impl_from_IFileDialog2(iface
);
2344 LONG ref
= InterlockedIncrement(&This
->ref
);
2345 TRACE("%p - ref %d\n", This
, ref
);
2350 static ULONG WINAPI
IFileDialog2_fnRelease(IFileDialog2
*iface
)
2352 FileDialogImpl
*This
= impl_from_IFileDialog2(iface
);
2353 LONG ref
= InterlockedDecrement(&This
->ref
);
2354 TRACE("%p - ref %d\n", This
, ref
);
2359 for(i
= 0; i
< This
->filterspec_count
; i
++)
2361 LocalFree((void*)This
->filterspecs
[i
].pszName
);
2362 LocalFree((void*)This
->filterspecs
[i
].pszSpec
);
2364 HeapFree(GetProcessHeap(), 0, This
->filterspecs
);
2366 DestroyWindow(This
->cctrls_hwnd
);
2368 if(This
->psi_defaultfolder
) IShellItem_Release(This
->psi_defaultfolder
);
2369 if(This
->psi_setfolder
) IShellItem_Release(This
->psi_setfolder
);
2370 if(This
->psi_folder
) IShellItem_Release(This
->psi_folder
);
2371 if(This
->psia_selection
) IShellItemArray_Release(This
->psia_selection
);
2372 if(This
->psia_results
) IShellItemArray_Release(This
->psia_results
);
2374 LocalFree(This
->set_filename
);
2375 LocalFree(This
->default_ext
);
2376 LocalFree(This
->custom_title
);
2377 LocalFree(This
->custom_okbutton
);
2378 LocalFree(This
->custom_cancelbutton
);
2379 LocalFree(This
->custom_filenamelabel
);
2381 DestroyMenu(This
->hmenu_opendropdown
);
2382 DeleteObject(This
->hfont_opendropdown
);
2384 HeapFree(GetProcessHeap(), 0, This
);
2390 static HRESULT WINAPI
IFileDialog2_fnShow(IFileDialog2
*iface
, HWND hwndOwner
)
2392 FileDialogImpl
*This
= impl_from_IFileDialog2(iface
);
2393 TRACE("%p (%p)\n", iface
, hwndOwner
);
2395 This
->opendropdown_has_selection
= FALSE
;
2397 return create_dialog(This
, hwndOwner
);
2400 static HRESULT WINAPI
IFileDialog2_fnSetFileTypes(IFileDialog2
*iface
, UINT cFileTypes
,
2401 const COMDLG_FILTERSPEC
*rgFilterSpec
)
2403 FileDialogImpl
*This
= impl_from_IFileDialog2(iface
);
2405 TRACE("%p (%d, %p)\n", This
, cFileTypes
, rgFilterSpec
);
2407 if(This
->filterspecs
)
2408 return E_UNEXPECTED
;
2411 return E_INVALIDARG
;
2416 This
->filterspecs
= HeapAlloc(GetProcessHeap(), 0, sizeof(COMDLG_FILTERSPEC
)*cFileTypes
);
2417 for(i
= 0; i
< cFileTypes
; i
++)
2419 This
->filterspecs
[i
].pszName
= StrDupW(rgFilterSpec
[i
].pszName
);
2420 This
->filterspecs
[i
].pszSpec
= StrDupW(rgFilterSpec
[i
].pszSpec
);
2422 This
->filterspec_count
= cFileTypes
;
2427 static HRESULT WINAPI
IFileDialog2_fnSetFileTypeIndex(IFileDialog2
*iface
, UINT iFileType
)
2429 FileDialogImpl
*This
= impl_from_IFileDialog2(iface
);
2430 TRACE("%p (%d)\n", This
, iFileType
);
2432 if(!This
->filterspecs
)
2435 iFileType
= max(iFileType
, 1);
2436 iFileType
= min(iFileType
, This
->filterspec_count
);
2437 This
->filetypeindex
= iFileType
-1;
2442 static HRESULT WINAPI
IFileDialog2_fnGetFileTypeIndex(IFileDialog2
*iface
, UINT
*piFileType
)
2444 FileDialogImpl
*This
= impl_from_IFileDialog2(iface
);
2445 TRACE("%p (%p)\n", This
, piFileType
);
2448 return E_INVALIDARG
;
2450 if(This
->filterspec_count
== 0)
2453 *piFileType
= This
->filetypeindex
+ 1;
2458 static HRESULT WINAPI
IFileDialog2_fnAdvise(IFileDialog2
*iface
, IFileDialogEvents
*pfde
, DWORD
*pdwCookie
)
2460 FileDialogImpl
*This
= impl_from_IFileDialog2(iface
);
2461 events_client
*client
;
2462 TRACE("%p (%p, %p)\n", This
, pfde
, pdwCookie
);
2464 if(!pfde
|| !pdwCookie
)
2465 return E_INVALIDARG
;
2467 client
= HeapAlloc(GetProcessHeap(), 0, sizeof(events_client
));
2468 client
->pfde
= pfde
;
2469 client
->cookie
= ++This
->events_next_cookie
;
2471 IFileDialogEvents_AddRef(pfde
);
2472 *pdwCookie
= client
->cookie
;
2474 list_add_tail(&This
->events_clients
, &client
->entry
);
2479 static HRESULT WINAPI
IFileDialog2_fnUnadvise(IFileDialog2
*iface
, DWORD dwCookie
)
2481 FileDialogImpl
*This
= impl_from_IFileDialog2(iface
);
2482 events_client
*client
, *found
= NULL
;
2483 TRACE("%p (%d)\n", This
, dwCookie
);
2485 LIST_FOR_EACH_ENTRY(client
, &This
->events_clients
, events_client
, entry
)
2487 if(client
->cookie
== dwCookie
)
2496 list_remove(&found
->entry
);
2497 IFileDialogEvents_Release(found
->pfde
);
2498 HeapFree(GetProcessHeap(), 0, found
);
2502 return E_INVALIDARG
;
2505 static HRESULT WINAPI
IFileDialog2_fnSetOptions(IFileDialog2
*iface
, FILEOPENDIALOGOPTIONS fos
)
2507 FileDialogImpl
*This
= impl_from_IFileDialog2(iface
);
2508 TRACE("%p (0x%x)\n", This
, fos
);
2510 if( !(This
->options
& FOS_PICKFOLDERS
) && (fos
& FOS_PICKFOLDERS
) )
2513 LoadStringW(COMDLG32_hInstance
, IDS_SELECT_FOLDER
, buf
, ARRAY_SIZE(buf
));
2514 IFileDialog2_SetTitle(iface
, buf
);
2517 This
->options
= fos
;
2522 static HRESULT WINAPI
IFileDialog2_fnGetOptions(IFileDialog2
*iface
, FILEOPENDIALOGOPTIONS
*pfos
)
2524 FileDialogImpl
*This
= impl_from_IFileDialog2(iface
);
2525 TRACE("%p (%p)\n", This
, pfos
);
2528 return E_INVALIDARG
;
2530 *pfos
= This
->options
;
2535 static HRESULT WINAPI
IFileDialog2_fnSetDefaultFolder(IFileDialog2
*iface
, IShellItem
*psi
)
2537 FileDialogImpl
*This
= impl_from_IFileDialog2(iface
);
2538 TRACE("%p (%p)\n", This
, psi
);
2539 if(This
->psi_defaultfolder
)
2540 IShellItem_Release(This
->psi_defaultfolder
);
2542 This
->psi_defaultfolder
= psi
;
2544 if(This
->psi_defaultfolder
)
2545 IShellItem_AddRef(This
->psi_defaultfolder
);
2550 static HRESULT WINAPI
IFileDialog2_fnSetFolder(IFileDialog2
*iface
, IShellItem
*psi
)
2552 FileDialogImpl
*This
= impl_from_IFileDialog2(iface
);
2553 TRACE("%p (%p)\n", This
, psi
);
2554 if(This
->psi_setfolder
)
2555 IShellItem_Release(This
->psi_setfolder
);
2557 This
->psi_setfolder
= psi
;
2559 if(This
->psi_setfolder
)
2560 IShellItem_AddRef(This
->psi_setfolder
);
2565 static HRESULT WINAPI
IFileDialog2_fnGetFolder(IFileDialog2
*iface
, IShellItem
**ppsi
)
2567 FileDialogImpl
*This
= impl_from_IFileDialog2(iface
);
2568 TRACE("%p (%p)\n", This
, ppsi
);
2570 return E_INVALIDARG
;
2573 If the dialog is shown, return the current(ly selected) folder. */
2576 if(This
->psi_folder
)
2577 *ppsi
= This
->psi_folder
;
2578 else if(This
->psi_setfolder
)
2579 *ppsi
= This
->psi_setfolder
;
2580 else if(This
->psi_defaultfolder
)
2581 *ppsi
= This
->psi_defaultfolder
;
2585 IShellItem_AddRef(*ppsi
);
2592 static HRESULT WINAPI
IFileDialog2_fnGetCurrentSelection(IFileDialog2
*iface
, IShellItem
**ppsi
)
2594 FileDialogImpl
*This
= impl_from_IFileDialog2(iface
);
2596 TRACE("%p (%p)\n", This
, ppsi
);
2599 return E_INVALIDARG
;
2601 if(This
->psia_selection
)
2603 /* FIXME: Check filename edit box */
2604 hr
= IShellItemArray_GetItemAt(This
->psia_selection
, 0, ppsi
);
2611 static HRESULT WINAPI
IFileDialog2_fnSetFileName(IFileDialog2
*iface
, LPCWSTR pszName
)
2613 FileDialogImpl
*This
= impl_from_IFileDialog2(iface
);
2614 TRACE("%p (%s)\n", iface
, debugstr_w(pszName
));
2616 set_file_name(This
, pszName
);
2621 static HRESULT WINAPI
IFileDialog2_fnGetFileName(IFileDialog2
*iface
, LPWSTR
*pszName
)
2623 FileDialogImpl
*This
= impl_from_IFileDialog2(iface
);
2624 TRACE("%p (%p)\n", iface
, pszName
);
2627 return E_INVALIDARG
;
2630 get_file_name(This
, pszName
);
2631 return *pszName
? S_OK
: E_FAIL
;
2634 static HRESULT WINAPI
IFileDialog2_fnSetTitle(IFileDialog2
*iface
, LPCWSTR pszTitle
)
2636 FileDialogImpl
*This
= impl_from_IFileDialog2(iface
);
2637 TRACE("%p (%s)\n", This
, debugstr_w(pszTitle
));
2639 LocalFree(This
->custom_title
);
2640 This
->custom_title
= StrDupW(pszTitle
);
2641 update_control_text(This
);
2646 static HRESULT WINAPI
IFileDialog2_fnSetOkButtonLabel(IFileDialog2
*iface
, LPCWSTR pszText
)
2648 FileDialogImpl
*This
= impl_from_IFileDialog2(iface
);
2649 TRACE("%p (%s)\n", This
, debugstr_w(pszText
));
2651 LocalFree(This
->custom_okbutton
);
2652 This
->custom_okbutton
= StrDupW(pszText
);
2653 update_control_text(This
);
2654 update_layout(This
);
2659 static HRESULT WINAPI
IFileDialog2_fnSetFileNameLabel(IFileDialog2
*iface
, LPCWSTR pszLabel
)
2661 FileDialogImpl
*This
= impl_from_IFileDialog2(iface
);
2662 TRACE("%p (%s)\n", This
, debugstr_w(pszLabel
));
2664 LocalFree(This
->custom_filenamelabel
);
2665 This
->custom_filenamelabel
= StrDupW(pszLabel
);
2666 update_control_text(This
);
2667 update_layout(This
);
2672 static HRESULT WINAPI
IFileDialog2_fnGetResult(IFileDialog2
*iface
, IShellItem
**ppsi
)
2674 FileDialogImpl
*This
= impl_from_IFileDialog2(iface
);
2676 TRACE("%p (%p)\n", This
, ppsi
);
2679 return E_INVALIDARG
;
2681 if(This
->psia_results
)
2684 hr
= IShellItemArray_GetCount(This
->psia_results
, &item_count
);
2690 /* Adds a reference. */
2691 hr
= IShellItemArray_GetItemAt(This
->psia_results
, 0, ppsi
);
2697 return E_UNEXPECTED
;
2700 static HRESULT WINAPI
IFileDialog2_fnAddPlace(IFileDialog2
*iface
, IShellItem
*psi
, FDAP fdap
)
2702 FileDialogImpl
*This
= impl_from_IFileDialog2(iface
);
2703 FIXME("stub - %p (%p, %d)\n", This
, psi
, fdap
);
2707 static HRESULT WINAPI
IFileDialog2_fnSetDefaultExtension(IFileDialog2
*iface
, LPCWSTR pszDefaultExtension
)
2709 FileDialogImpl
*This
= impl_from_IFileDialog2(iface
);
2710 TRACE("%p (%s)\n", This
, debugstr_w(pszDefaultExtension
));
2712 LocalFree(This
->default_ext
);
2713 This
->default_ext
= StrDupW(pszDefaultExtension
);
2718 static HRESULT WINAPI
IFileDialog2_fnClose(IFileDialog2
*iface
, HRESULT hr
)
2720 FileDialogImpl
*This
= impl_from_IFileDialog2(iface
);
2721 TRACE("%p (0x%08x)\n", This
, hr
);
2724 EndDialog(This
->dlg_hwnd
, hr
);
2729 static HRESULT WINAPI
IFileDialog2_fnSetClientGuid(IFileDialog2
*iface
, REFGUID guid
)
2731 FileDialogImpl
*This
= impl_from_IFileDialog2(iface
);
2732 TRACE("%p (%s)\n", This
, debugstr_guid(guid
));
2733 This
->client_guid
= *guid
;
2737 static HRESULT WINAPI
IFileDialog2_fnClearClientData(IFileDialog2
*iface
)
2739 FileDialogImpl
*This
= impl_from_IFileDialog2(iface
);
2740 FIXME("stub - %p\n", This
);
2744 static HRESULT WINAPI
IFileDialog2_fnSetFilter(IFileDialog2
*iface
, IShellItemFilter
*pFilter
)
2746 FileDialogImpl
*This
= impl_from_IFileDialog2(iface
);
2747 FIXME("stub - %p (%p)\n", This
, pFilter
);
2751 static HRESULT WINAPI
IFileDialog2_fnSetCancelButtonLabel(IFileDialog2
*iface
, LPCWSTR pszLabel
)
2753 FileDialogImpl
*This
= impl_from_IFileDialog2(iface
);
2754 TRACE("%p (%s)\n", This
, debugstr_w(pszLabel
));
2756 LocalFree(This
->custom_cancelbutton
);
2757 This
->custom_cancelbutton
= StrDupW(pszLabel
);
2758 update_control_text(This
);
2759 update_layout(This
);
2764 static HRESULT WINAPI
IFileDialog2_fnSetNavigationRoot(IFileDialog2
*iface
, IShellItem
*psi
)
2766 FileDialogImpl
*This
= impl_from_IFileDialog2(iface
);
2767 FIXME("stub - %p (%p)\n", This
, psi
);
2771 static const IFileDialog2Vtbl vt_IFileDialog2
= {
2772 IFileDialog2_fnQueryInterface
,
2773 IFileDialog2_fnAddRef
,
2774 IFileDialog2_fnRelease
,
2775 IFileDialog2_fnShow
,
2776 IFileDialog2_fnSetFileTypes
,
2777 IFileDialog2_fnSetFileTypeIndex
,
2778 IFileDialog2_fnGetFileTypeIndex
,
2779 IFileDialog2_fnAdvise
,
2780 IFileDialog2_fnUnadvise
,
2781 IFileDialog2_fnSetOptions
,
2782 IFileDialog2_fnGetOptions
,
2783 IFileDialog2_fnSetDefaultFolder
,
2784 IFileDialog2_fnSetFolder
,
2785 IFileDialog2_fnGetFolder
,
2786 IFileDialog2_fnGetCurrentSelection
,
2787 IFileDialog2_fnSetFileName
,
2788 IFileDialog2_fnGetFileName
,
2789 IFileDialog2_fnSetTitle
,
2790 IFileDialog2_fnSetOkButtonLabel
,
2791 IFileDialog2_fnSetFileNameLabel
,
2792 IFileDialog2_fnGetResult
,
2793 IFileDialog2_fnAddPlace
,
2794 IFileDialog2_fnSetDefaultExtension
,
2795 IFileDialog2_fnClose
,
2796 IFileDialog2_fnSetClientGuid
,
2797 IFileDialog2_fnClearClientData
,
2798 IFileDialog2_fnSetFilter
,
2799 IFileDialog2_fnSetCancelButtonLabel
,
2800 IFileDialog2_fnSetNavigationRoot
2803 /**************************************************************************
2806 static inline FileDialogImpl
*impl_from_IFileOpenDialog(IFileOpenDialog
*iface
)
2808 return CONTAINING_RECORD(iface
, FileDialogImpl
, u
.IFileOpenDialog_iface
);
2811 static HRESULT WINAPI
IFileOpenDialog_fnQueryInterface(IFileOpenDialog
*iface
,
2812 REFIID riid
, void **ppvObject
)
2814 FileDialogImpl
*This
= impl_from_IFileOpenDialog(iface
);
2815 return IFileDialog2_QueryInterface(&This
->IFileDialog2_iface
, riid
, ppvObject
);
2818 static ULONG WINAPI
IFileOpenDialog_fnAddRef(IFileOpenDialog
*iface
)
2820 FileDialogImpl
*This
= impl_from_IFileOpenDialog(iface
);
2821 return IFileDialog2_AddRef(&This
->IFileDialog2_iface
);
2824 static ULONG WINAPI
IFileOpenDialog_fnRelease(IFileOpenDialog
*iface
)
2826 FileDialogImpl
*This
= impl_from_IFileOpenDialog(iface
);
2827 return IFileDialog2_Release(&This
->IFileDialog2_iface
);
2830 static HRESULT WINAPI
IFileOpenDialog_fnShow(IFileOpenDialog
*iface
, HWND hwndOwner
)
2832 FileDialogImpl
*This
= impl_from_IFileOpenDialog(iface
);
2833 return IFileDialog2_Show(&This
->IFileDialog2_iface
, hwndOwner
);
2836 static HRESULT WINAPI
IFileOpenDialog_fnSetFileTypes(IFileOpenDialog
*iface
, UINT cFileTypes
,
2837 const COMDLG_FILTERSPEC
*rgFilterSpec
)
2839 FileDialogImpl
*This
= impl_from_IFileOpenDialog(iface
);
2840 return IFileDialog2_SetFileTypes(&This
->IFileDialog2_iface
, cFileTypes
, rgFilterSpec
);
2843 static HRESULT WINAPI
IFileOpenDialog_fnSetFileTypeIndex(IFileOpenDialog
*iface
, UINT iFileType
)
2845 FileDialogImpl
*This
= impl_from_IFileOpenDialog(iface
);
2846 return IFileDialog2_SetFileTypeIndex(&This
->IFileDialog2_iface
, iFileType
);
2849 static HRESULT WINAPI
IFileOpenDialog_fnGetFileTypeIndex(IFileOpenDialog
*iface
, UINT
*piFileType
)
2851 FileDialogImpl
*This
= impl_from_IFileOpenDialog(iface
);
2852 return IFileDialog2_GetFileTypeIndex(&This
->IFileDialog2_iface
, piFileType
);
2855 static HRESULT WINAPI
IFileOpenDialog_fnAdvise(IFileOpenDialog
*iface
, IFileDialogEvents
*pfde
,
2858 FileDialogImpl
*This
= impl_from_IFileOpenDialog(iface
);
2859 return IFileDialog2_Advise(&This
->IFileDialog2_iface
, pfde
, pdwCookie
);
2862 static HRESULT WINAPI
IFileOpenDialog_fnUnadvise(IFileOpenDialog
*iface
, DWORD dwCookie
)
2864 FileDialogImpl
*This
= impl_from_IFileOpenDialog(iface
);
2865 return IFileDialog2_Unadvise(&This
->IFileDialog2_iface
, dwCookie
);
2868 static HRESULT WINAPI
IFileOpenDialog_fnSetOptions(IFileOpenDialog
*iface
, FILEOPENDIALOGOPTIONS fos
)
2870 FileDialogImpl
*This
= impl_from_IFileOpenDialog(iface
);
2871 return IFileDialog2_SetOptions(&This
->IFileDialog2_iface
, fos
);
2874 static HRESULT WINAPI
IFileOpenDialog_fnGetOptions(IFileOpenDialog
*iface
, FILEOPENDIALOGOPTIONS
*pfos
)
2876 FileDialogImpl
*This
= impl_from_IFileOpenDialog(iface
);
2877 return IFileDialog2_GetOptions(&This
->IFileDialog2_iface
, pfos
);
2880 static HRESULT WINAPI
IFileOpenDialog_fnSetDefaultFolder(IFileOpenDialog
*iface
, IShellItem
*psi
)
2882 FileDialogImpl
*This
= impl_from_IFileOpenDialog(iface
);
2883 return IFileDialog2_SetDefaultFolder(&This
->IFileDialog2_iface
, psi
);
2886 static HRESULT WINAPI
IFileOpenDialog_fnSetFolder(IFileOpenDialog
*iface
, IShellItem
*psi
)
2888 FileDialogImpl
*This
= impl_from_IFileOpenDialog(iface
);
2889 return IFileDialog2_SetFolder(&This
->IFileDialog2_iface
, psi
);
2892 static HRESULT WINAPI
IFileOpenDialog_fnGetFolder(IFileOpenDialog
*iface
, IShellItem
**ppsi
)
2894 FileDialogImpl
*This
= impl_from_IFileOpenDialog(iface
);
2895 return IFileDialog2_GetFolder(&This
->IFileDialog2_iface
, ppsi
);
2898 static HRESULT WINAPI
IFileOpenDialog_fnGetCurrentSelection(IFileOpenDialog
*iface
, IShellItem
**ppsi
)
2900 FileDialogImpl
*This
= impl_from_IFileOpenDialog(iface
);
2901 return IFileDialog2_GetCurrentSelection(&This
->IFileDialog2_iface
, ppsi
);
2904 static HRESULT WINAPI
IFileOpenDialog_fnSetFileName(IFileOpenDialog
*iface
, LPCWSTR pszName
)
2906 FileDialogImpl
*This
= impl_from_IFileOpenDialog(iface
);
2907 return IFileDialog2_SetFileName(&This
->IFileDialog2_iface
, pszName
);
2910 static HRESULT WINAPI
IFileOpenDialog_fnGetFileName(IFileOpenDialog
*iface
, LPWSTR
*pszName
)
2912 FileDialogImpl
*This
= impl_from_IFileOpenDialog(iface
);
2913 return IFileDialog2_GetFileName(&This
->IFileDialog2_iface
, pszName
);
2916 static HRESULT WINAPI
IFileOpenDialog_fnSetTitle(IFileOpenDialog
*iface
, LPCWSTR pszTitle
)
2918 FileDialogImpl
*This
= impl_from_IFileOpenDialog(iface
);
2919 return IFileDialog2_SetTitle(&This
->IFileDialog2_iface
, pszTitle
);
2922 static HRESULT WINAPI
IFileOpenDialog_fnSetOkButtonLabel(IFileOpenDialog
*iface
, LPCWSTR pszText
)
2924 FileDialogImpl
*This
= impl_from_IFileOpenDialog(iface
);
2925 return IFileDialog2_SetOkButtonLabel(&This
->IFileDialog2_iface
, pszText
);
2928 static HRESULT WINAPI
IFileOpenDialog_fnSetFileNameLabel(IFileOpenDialog
*iface
, LPCWSTR pszLabel
)
2930 FileDialogImpl
*This
= impl_from_IFileOpenDialog(iface
);
2931 return IFileDialog2_SetFileNameLabel(&This
->IFileDialog2_iface
, pszLabel
);
2934 static HRESULT WINAPI
IFileOpenDialog_fnGetResult(IFileOpenDialog
*iface
, IShellItem
**ppsi
)
2936 FileDialogImpl
*This
= impl_from_IFileOpenDialog(iface
);
2937 return IFileDialog2_GetResult(&This
->IFileDialog2_iface
, ppsi
);
2940 static HRESULT WINAPI
IFileOpenDialog_fnAddPlace(IFileOpenDialog
*iface
, IShellItem
*psi
, FDAP fdap
)
2942 FileDialogImpl
*This
= impl_from_IFileOpenDialog(iface
);
2943 return IFileDialog2_AddPlace(&This
->IFileDialog2_iface
, psi
, fdap
);
2946 static HRESULT WINAPI
IFileOpenDialog_fnSetDefaultExtension(IFileOpenDialog
*iface
,
2947 LPCWSTR pszDefaultExtension
)
2949 FileDialogImpl
*This
= impl_from_IFileOpenDialog(iface
);
2950 return IFileDialog2_SetDefaultExtension(&This
->IFileDialog2_iface
, pszDefaultExtension
);
2953 static HRESULT WINAPI
IFileOpenDialog_fnClose(IFileOpenDialog
*iface
, HRESULT hr
)
2955 FileDialogImpl
*This
= impl_from_IFileOpenDialog(iface
);
2956 return IFileDialog2_Close(&This
->IFileDialog2_iface
, hr
);
2959 static HRESULT WINAPI
IFileOpenDialog_fnSetClientGuid(IFileOpenDialog
*iface
, REFGUID guid
)
2961 FileDialogImpl
*This
= impl_from_IFileOpenDialog(iface
);
2962 return IFileDialog2_SetClientGuid(&This
->IFileDialog2_iface
, guid
);
2965 static HRESULT WINAPI
IFileOpenDialog_fnClearClientData(IFileOpenDialog
*iface
)
2967 FileDialogImpl
*This
= impl_from_IFileOpenDialog(iface
);
2968 return IFileDialog2_ClearClientData(&This
->IFileDialog2_iface
);
2971 static HRESULT WINAPI
IFileOpenDialog_fnSetFilter(IFileOpenDialog
*iface
, IShellItemFilter
*pFilter
)
2973 FileDialogImpl
*This
= impl_from_IFileOpenDialog(iface
);
2974 return IFileDialog2_SetFilter(&This
->IFileDialog2_iface
, pFilter
);
2977 static HRESULT WINAPI
IFileOpenDialog_fnGetResults(IFileOpenDialog
*iface
, IShellItemArray
**ppenum
)
2979 FileDialogImpl
*This
= impl_from_IFileOpenDialog(iface
);
2980 TRACE("%p (%p)\n", This
, ppenum
);
2982 *ppenum
= This
->psia_results
;
2986 IShellItemArray_AddRef(*ppenum
);
2993 static HRESULT WINAPI
IFileOpenDialog_fnGetSelectedItems(IFileOpenDialog
*iface
, IShellItemArray
**ppsai
)
2995 FileDialogImpl
*This
= impl_from_IFileOpenDialog(iface
);
2996 TRACE("%p (%p)\n", This
, ppsai
);
2998 if(This
->psia_selection
)
3000 *ppsai
= This
->psia_selection
;
3001 IShellItemArray_AddRef(*ppsai
);
3008 static const IFileOpenDialogVtbl vt_IFileOpenDialog
= {
3009 IFileOpenDialog_fnQueryInterface
,
3010 IFileOpenDialog_fnAddRef
,
3011 IFileOpenDialog_fnRelease
,
3012 IFileOpenDialog_fnShow
,
3013 IFileOpenDialog_fnSetFileTypes
,
3014 IFileOpenDialog_fnSetFileTypeIndex
,
3015 IFileOpenDialog_fnGetFileTypeIndex
,
3016 IFileOpenDialog_fnAdvise
,
3017 IFileOpenDialog_fnUnadvise
,
3018 IFileOpenDialog_fnSetOptions
,
3019 IFileOpenDialog_fnGetOptions
,
3020 IFileOpenDialog_fnSetDefaultFolder
,
3021 IFileOpenDialog_fnSetFolder
,
3022 IFileOpenDialog_fnGetFolder
,
3023 IFileOpenDialog_fnGetCurrentSelection
,
3024 IFileOpenDialog_fnSetFileName
,
3025 IFileOpenDialog_fnGetFileName
,
3026 IFileOpenDialog_fnSetTitle
,
3027 IFileOpenDialog_fnSetOkButtonLabel
,
3028 IFileOpenDialog_fnSetFileNameLabel
,
3029 IFileOpenDialog_fnGetResult
,
3030 IFileOpenDialog_fnAddPlace
,
3031 IFileOpenDialog_fnSetDefaultExtension
,
3032 IFileOpenDialog_fnClose
,
3033 IFileOpenDialog_fnSetClientGuid
,
3034 IFileOpenDialog_fnClearClientData
,
3035 IFileOpenDialog_fnSetFilter
,
3036 IFileOpenDialog_fnGetResults
,
3037 IFileOpenDialog_fnGetSelectedItems
3040 /**************************************************************************
3043 static inline FileDialogImpl
*impl_from_IFileSaveDialog(IFileSaveDialog
*iface
)
3045 return CONTAINING_RECORD(iface
, FileDialogImpl
, u
.IFileSaveDialog_iface
);
3048 static HRESULT WINAPI
IFileSaveDialog_fnQueryInterface(IFileSaveDialog
*iface
,
3052 FileDialogImpl
*This
= impl_from_IFileSaveDialog(iface
);
3053 return IFileDialog2_QueryInterface(&This
->IFileDialog2_iface
, riid
, ppvObject
);
3056 static ULONG WINAPI
IFileSaveDialog_fnAddRef(IFileSaveDialog
*iface
)
3058 FileDialogImpl
*This
= impl_from_IFileSaveDialog(iface
);
3059 return IFileDialog2_AddRef(&This
->IFileDialog2_iface
);
3062 static ULONG WINAPI
IFileSaveDialog_fnRelease(IFileSaveDialog
*iface
)
3064 FileDialogImpl
*This
= impl_from_IFileSaveDialog(iface
);
3065 return IFileDialog2_Release(&This
->IFileDialog2_iface
);
3068 static HRESULT WINAPI
IFileSaveDialog_fnShow(IFileSaveDialog
*iface
, HWND hwndOwner
)
3070 FileDialogImpl
*This
= impl_from_IFileSaveDialog(iface
);
3071 return IFileDialog2_Show(&This
->IFileDialog2_iface
, hwndOwner
);
3074 static HRESULT WINAPI
IFileSaveDialog_fnSetFileTypes(IFileSaveDialog
*iface
, UINT cFileTypes
,
3075 const COMDLG_FILTERSPEC
*rgFilterSpec
)
3077 FileDialogImpl
*This
= impl_from_IFileSaveDialog(iface
);
3078 return IFileDialog2_SetFileTypes(&This
->IFileDialog2_iface
, cFileTypes
, rgFilterSpec
);
3081 static HRESULT WINAPI
IFileSaveDialog_fnSetFileTypeIndex(IFileSaveDialog
*iface
, UINT iFileType
)
3083 FileDialogImpl
*This
= impl_from_IFileSaveDialog(iface
);
3084 return IFileDialog2_SetFileTypeIndex(&This
->IFileDialog2_iface
, iFileType
);
3087 static HRESULT WINAPI
IFileSaveDialog_fnGetFileTypeIndex(IFileSaveDialog
*iface
, UINT
*piFileType
)
3089 FileDialogImpl
*This
= impl_from_IFileSaveDialog(iface
);
3090 return IFileDialog2_GetFileTypeIndex(&This
->IFileDialog2_iface
, piFileType
);
3093 static HRESULT WINAPI
IFileSaveDialog_fnAdvise(IFileSaveDialog
*iface
, IFileDialogEvents
*pfde
,
3096 FileDialogImpl
*This
= impl_from_IFileSaveDialog(iface
);
3097 return IFileDialog2_Advise(&This
->IFileDialog2_iface
, pfde
, pdwCookie
);
3100 static HRESULT WINAPI
IFileSaveDialog_fnUnadvise(IFileSaveDialog
*iface
, DWORD dwCookie
)
3102 FileDialogImpl
*This
= impl_from_IFileSaveDialog(iface
);
3103 return IFileDialog2_Unadvise(&This
->IFileDialog2_iface
, dwCookie
);
3106 static HRESULT WINAPI
IFileSaveDialog_fnSetOptions(IFileSaveDialog
*iface
, FILEOPENDIALOGOPTIONS fos
)
3108 FileDialogImpl
*This
= impl_from_IFileSaveDialog(iface
);
3109 return IFileDialog2_SetOptions(&This
->IFileDialog2_iface
, fos
);
3112 static HRESULT WINAPI
IFileSaveDialog_fnGetOptions(IFileSaveDialog
*iface
, FILEOPENDIALOGOPTIONS
*pfos
)
3114 FileDialogImpl
*This
= impl_from_IFileSaveDialog(iface
);
3115 return IFileDialog2_GetOptions(&This
->IFileDialog2_iface
, pfos
);
3118 static HRESULT WINAPI
IFileSaveDialog_fnSetDefaultFolder(IFileSaveDialog
*iface
, IShellItem
*psi
)
3120 FileDialogImpl
*This
= impl_from_IFileSaveDialog(iface
);
3121 return IFileDialog2_SetDefaultFolder(&This
->IFileDialog2_iface
, psi
);
3124 static HRESULT WINAPI
IFileSaveDialog_fnSetFolder(IFileSaveDialog
*iface
, IShellItem
*psi
)
3126 FileDialogImpl
*This
= impl_from_IFileSaveDialog(iface
);
3127 return IFileDialog2_SetFolder(&This
->IFileDialog2_iface
, psi
);
3130 static HRESULT WINAPI
IFileSaveDialog_fnGetFolder(IFileSaveDialog
*iface
, IShellItem
**ppsi
)
3132 FileDialogImpl
*This
= impl_from_IFileSaveDialog(iface
);
3133 return IFileDialog2_GetFolder(&This
->IFileDialog2_iface
, ppsi
);
3136 static HRESULT WINAPI
IFileSaveDialog_fnGetCurrentSelection(IFileSaveDialog
*iface
, IShellItem
**ppsi
)
3138 FileDialogImpl
*This
= impl_from_IFileSaveDialog(iface
);
3139 return IFileDialog2_GetCurrentSelection(&This
->IFileDialog2_iface
, ppsi
);
3142 static HRESULT WINAPI
IFileSaveDialog_fnSetFileName(IFileSaveDialog
*iface
, LPCWSTR pszName
)
3144 FileDialogImpl
*This
= impl_from_IFileSaveDialog(iface
);
3145 return IFileDialog2_SetFileName(&This
->IFileDialog2_iface
, pszName
);
3148 static HRESULT WINAPI
IFileSaveDialog_fnGetFileName(IFileSaveDialog
*iface
, LPWSTR
*pszName
)
3150 FileDialogImpl
*This
= impl_from_IFileSaveDialog(iface
);
3151 return IFileDialog2_GetFileName(&This
->IFileDialog2_iface
, pszName
);
3154 static HRESULT WINAPI
IFileSaveDialog_fnSetTitle(IFileSaveDialog
*iface
, LPCWSTR pszTitle
)
3156 FileDialogImpl
*This
= impl_from_IFileSaveDialog(iface
);
3157 return IFileDialog2_SetTitle(&This
->IFileDialog2_iface
, pszTitle
);
3160 static HRESULT WINAPI
IFileSaveDialog_fnSetOkButtonLabel(IFileSaveDialog
*iface
, LPCWSTR pszText
)
3162 FileDialogImpl
*This
= impl_from_IFileSaveDialog(iface
);
3163 return IFileDialog2_SetOkButtonLabel(&This
->IFileDialog2_iface
, pszText
);
3166 static HRESULT WINAPI
IFileSaveDialog_fnSetFileNameLabel(IFileSaveDialog
*iface
, LPCWSTR pszLabel
)
3168 FileDialogImpl
*This
= impl_from_IFileSaveDialog(iface
);
3169 return IFileDialog2_SetFileNameLabel(&This
->IFileDialog2_iface
, pszLabel
);
3172 static HRESULT WINAPI
IFileSaveDialog_fnGetResult(IFileSaveDialog
*iface
, IShellItem
**ppsi
)
3174 FileDialogImpl
*This
= impl_from_IFileSaveDialog(iface
);
3175 return IFileDialog2_GetResult(&This
->IFileDialog2_iface
, ppsi
);
3178 static HRESULT WINAPI
IFileSaveDialog_fnAddPlace(IFileSaveDialog
*iface
, IShellItem
*psi
, FDAP fdap
)
3180 FileDialogImpl
*This
= impl_from_IFileSaveDialog(iface
);
3181 return IFileDialog2_AddPlace(&This
->IFileDialog2_iface
, psi
, fdap
);
3184 static HRESULT WINAPI
IFileSaveDialog_fnSetDefaultExtension(IFileSaveDialog
*iface
,
3185 LPCWSTR pszDefaultExtension
)
3187 FileDialogImpl
*This
= impl_from_IFileSaveDialog(iface
);
3188 return IFileDialog2_SetDefaultExtension(&This
->IFileDialog2_iface
, pszDefaultExtension
);
3191 static HRESULT WINAPI
IFileSaveDialog_fnClose(IFileSaveDialog
*iface
, HRESULT hr
)
3193 FileDialogImpl
*This
= impl_from_IFileSaveDialog(iface
);
3194 return IFileDialog2_Close(&This
->IFileDialog2_iface
, hr
);
3197 static HRESULT WINAPI
IFileSaveDialog_fnSetClientGuid(IFileSaveDialog
*iface
, REFGUID guid
)
3199 FileDialogImpl
*This
= impl_from_IFileSaveDialog(iface
);
3200 return IFileDialog2_SetClientGuid(&This
->IFileDialog2_iface
, guid
);
3203 static HRESULT WINAPI
IFileSaveDialog_fnClearClientData(IFileSaveDialog
*iface
)
3205 FileDialogImpl
*This
= impl_from_IFileSaveDialog(iface
);
3206 return IFileDialog2_ClearClientData(&This
->IFileDialog2_iface
);
3209 static HRESULT WINAPI
IFileSaveDialog_fnSetFilter(IFileSaveDialog
*iface
, IShellItemFilter
*pFilter
)
3211 FileDialogImpl
*This
= impl_from_IFileSaveDialog(iface
);
3212 return IFileDialog2_SetFilter(&This
->IFileDialog2_iface
, pFilter
);
3215 static HRESULT WINAPI
IFileSaveDialog_fnSetSaveAsItem(IFileSaveDialog
* iface
, IShellItem
*psi
)
3217 FileDialogImpl
*This
= impl_from_IFileSaveDialog(iface
);
3218 FIXME("stub - %p (%p)\n", This
, psi
);
3222 static HRESULT WINAPI
IFileSaveDialog_fnSetProperties(IFileSaveDialog
* iface
, IPropertyStore
*pStore
)
3224 FileDialogImpl
*This
= impl_from_IFileSaveDialog(iface
);
3225 FIXME("stub - %p (%p)\n", This
, pStore
);
3229 static HRESULT WINAPI
IFileSaveDialog_fnSetCollectedProperties(IFileSaveDialog
* iface
,
3230 IPropertyDescriptionList
*pList
,
3231 BOOL fAppendDefault
)
3233 FileDialogImpl
*This
= impl_from_IFileSaveDialog(iface
);
3234 FIXME("stub - %p (%p, %d)\n", This
, pList
, fAppendDefault
);
3238 static HRESULT WINAPI
IFileSaveDialog_fnGetProperties(IFileSaveDialog
* iface
, IPropertyStore
**ppStore
)
3240 FileDialogImpl
*This
= impl_from_IFileSaveDialog(iface
);
3241 FIXME("stub - %p (%p)\n", This
, ppStore
);
3245 static HRESULT WINAPI
IFileSaveDialog_fnApplyProperties(IFileSaveDialog
* iface
,
3247 IPropertyStore
*pStore
,
3249 IFileOperationProgressSink
*pSink
)
3251 FileDialogImpl
*This
= impl_from_IFileSaveDialog(iface
);
3252 FIXME("%p (%p, %p, %p, %p)\n", This
, psi
, pStore
, hwnd
, pSink
);
3256 static const IFileSaveDialogVtbl vt_IFileSaveDialog
= {
3257 IFileSaveDialog_fnQueryInterface
,
3258 IFileSaveDialog_fnAddRef
,
3259 IFileSaveDialog_fnRelease
,
3260 IFileSaveDialog_fnShow
,
3261 IFileSaveDialog_fnSetFileTypes
,
3262 IFileSaveDialog_fnSetFileTypeIndex
,
3263 IFileSaveDialog_fnGetFileTypeIndex
,
3264 IFileSaveDialog_fnAdvise
,
3265 IFileSaveDialog_fnUnadvise
,
3266 IFileSaveDialog_fnSetOptions
,
3267 IFileSaveDialog_fnGetOptions
,
3268 IFileSaveDialog_fnSetDefaultFolder
,
3269 IFileSaveDialog_fnSetFolder
,
3270 IFileSaveDialog_fnGetFolder
,
3271 IFileSaveDialog_fnGetCurrentSelection
,
3272 IFileSaveDialog_fnSetFileName
,
3273 IFileSaveDialog_fnGetFileName
,
3274 IFileSaveDialog_fnSetTitle
,
3275 IFileSaveDialog_fnSetOkButtonLabel
,
3276 IFileSaveDialog_fnSetFileNameLabel
,
3277 IFileSaveDialog_fnGetResult
,
3278 IFileSaveDialog_fnAddPlace
,
3279 IFileSaveDialog_fnSetDefaultExtension
,
3280 IFileSaveDialog_fnClose
,
3281 IFileSaveDialog_fnSetClientGuid
,
3282 IFileSaveDialog_fnClearClientData
,
3283 IFileSaveDialog_fnSetFilter
,
3284 IFileSaveDialog_fnSetSaveAsItem
,
3285 IFileSaveDialog_fnSetProperties
,
3286 IFileSaveDialog_fnSetCollectedProperties
,
3287 IFileSaveDialog_fnGetProperties
,
3288 IFileSaveDialog_fnApplyProperties
3291 /**************************************************************************
3292 * IExplorerBrowserEvents implementation
3294 static inline FileDialogImpl
*impl_from_IExplorerBrowserEvents(IExplorerBrowserEvents
*iface
)
3296 return CONTAINING_RECORD(iface
, FileDialogImpl
, IExplorerBrowserEvents_iface
);
3299 static HRESULT WINAPI
IExplorerBrowserEvents_fnQueryInterface(IExplorerBrowserEvents
*iface
,
3300 REFIID riid
, void **ppvObject
)
3302 FileDialogImpl
*This
= impl_from_IExplorerBrowserEvents(iface
);
3303 TRACE("%p (%s, %p)\n", This
, debugstr_guid(riid
), ppvObject
);
3305 return IFileDialog2_QueryInterface(&This
->IFileDialog2_iface
, riid
, ppvObject
);
3308 static ULONG WINAPI
IExplorerBrowserEvents_fnAddRef(IExplorerBrowserEvents
*iface
)
3310 FileDialogImpl
*This
= impl_from_IExplorerBrowserEvents(iface
);
3311 TRACE("%p\n", This
);
3312 return IFileDialog2_AddRef(&This
->IFileDialog2_iface
);
3315 static ULONG WINAPI
IExplorerBrowserEvents_fnRelease(IExplorerBrowserEvents
*iface
)
3317 FileDialogImpl
*This
= impl_from_IExplorerBrowserEvents(iface
);
3318 TRACE("%p\n", This
);
3319 return IFileDialog2_Release(&This
->IFileDialog2_iface
);
3322 static HRESULT WINAPI
IExplorerBrowserEvents_fnOnNavigationPending(IExplorerBrowserEvents
*iface
,
3323 PCIDLIST_ABSOLUTE pidlFolder
)
3325 FileDialogImpl
*This
= impl_from_IExplorerBrowserEvents(iface
);
3328 TRACE("%p (%p)\n", This
, pidlFolder
);
3330 hr
= SHCreateItemFromIDList(pidlFolder
, &IID_IShellItem
, (void**)&psi
);
3333 hr
= events_OnFolderChanging(This
, psi
);
3334 IShellItem_Release(psi
);
3336 /* The ExplorerBrowser treats S_FALSE as S_OK, we don't. */
3343 ERR("Failed to convert pidl (%p) to a shellitem.\n", pidlFolder
);
3348 static HRESULT WINAPI
IExplorerBrowserEvents_fnOnViewCreated(IExplorerBrowserEvents
*iface
,
3351 FileDialogImpl
*This
= impl_from_IExplorerBrowserEvents(iface
);
3352 TRACE("%p (%p)\n", This
, psv
);
3356 static HRESULT WINAPI
IExplorerBrowserEvents_fnOnNavigationComplete(IExplorerBrowserEvents
*iface
,
3357 PCIDLIST_ABSOLUTE pidlFolder
)
3359 FileDialogImpl
*This
= impl_from_IExplorerBrowserEvents(iface
);
3361 TRACE("%p (%p)\n", This
, pidlFolder
);
3363 if(This
->psi_folder
)
3364 IShellItem_Release(This
->psi_folder
);
3366 hr
= SHCreateItemFromIDList(pidlFolder
, &IID_IShellItem
, (void**)&This
->psi_folder
);
3369 ERR("Failed to get the current folder.\n");
3370 This
->psi_folder
= NULL
;
3373 events_OnFolderChange(This
);
3378 static HRESULT WINAPI
IExplorerBrowserEvents_fnOnNavigationFailed(IExplorerBrowserEvents
*iface
,
3379 PCIDLIST_ABSOLUTE pidlFolder
)
3381 FileDialogImpl
*This
= impl_from_IExplorerBrowserEvents(iface
);
3382 TRACE("%p (%p)\n", This
, pidlFolder
);
3386 static const IExplorerBrowserEventsVtbl vt_IExplorerBrowserEvents
= {
3387 IExplorerBrowserEvents_fnQueryInterface
,
3388 IExplorerBrowserEvents_fnAddRef
,
3389 IExplorerBrowserEvents_fnRelease
,
3390 IExplorerBrowserEvents_fnOnNavigationPending
,
3391 IExplorerBrowserEvents_fnOnViewCreated
,
3392 IExplorerBrowserEvents_fnOnNavigationComplete
,
3393 IExplorerBrowserEvents_fnOnNavigationFailed
3396 /**************************************************************************
3397 * IServiceProvider implementation
3399 static inline FileDialogImpl
*impl_from_IServiceProvider(IServiceProvider
*iface
)
3401 return CONTAINING_RECORD(iface
, FileDialogImpl
, IServiceProvider_iface
);
3404 static HRESULT WINAPI
IServiceProvider_fnQueryInterface(IServiceProvider
*iface
,
3405 REFIID riid
, void **ppvObject
)
3407 FileDialogImpl
*This
= impl_from_IServiceProvider(iface
);
3408 TRACE("%p\n", This
);
3409 return IFileDialog2_QueryInterface(&This
->IFileDialog2_iface
, riid
, ppvObject
);
3412 static ULONG WINAPI
IServiceProvider_fnAddRef(IServiceProvider
*iface
)
3414 FileDialogImpl
*This
= impl_from_IServiceProvider(iface
);
3415 TRACE("%p\n", This
);
3416 return IFileDialog2_AddRef(&This
->IFileDialog2_iface
);
3419 static ULONG WINAPI
IServiceProvider_fnRelease(IServiceProvider
*iface
)
3421 FileDialogImpl
*This
= impl_from_IServiceProvider(iface
);
3422 TRACE("%p\n", This
);
3423 return IFileDialog2_Release(&This
->IFileDialog2_iface
);
3426 static HRESULT WINAPI
IServiceProvider_fnQueryService(IServiceProvider
*iface
,
3427 REFGUID guidService
,
3428 REFIID riid
, void **ppv
)
3430 FileDialogImpl
*This
= impl_from_IServiceProvider(iface
);
3431 HRESULT hr
= E_NOTIMPL
;
3432 TRACE("%p (%s, %s, %p)\n", This
, debugstr_guid(guidService
), debugstr_guid(riid
), ppv
);
3435 if(IsEqualGUID(guidService
, &SID_STopLevelBrowser
) && This
->peb
)
3436 hr
= IExplorerBrowser_QueryInterface(This
->peb
, riid
, ppv
);
3437 else if(IsEqualGUID(guidService
, &SID_SExplorerBrowserFrame
))
3438 hr
= IFileDialog2_QueryInterface(&This
->IFileDialog2_iface
, riid
, ppv
);
3440 FIXME("Interface %s requested from unknown service %s\n",
3441 debugstr_guid(riid
), debugstr_guid(guidService
));
3446 static const IServiceProviderVtbl vt_IServiceProvider
= {
3447 IServiceProvider_fnQueryInterface
,
3448 IServiceProvider_fnAddRef
,
3449 IServiceProvider_fnRelease
,
3450 IServiceProvider_fnQueryService
3453 /**************************************************************************
3454 * ICommDlgBrowser3 implementation
3456 static inline FileDialogImpl
*impl_from_ICommDlgBrowser3(ICommDlgBrowser3
*iface
)
3458 return CONTAINING_RECORD(iface
, FileDialogImpl
, ICommDlgBrowser3_iface
);
3461 static HRESULT WINAPI
ICommDlgBrowser3_fnQueryInterface(ICommDlgBrowser3
*iface
,
3462 REFIID riid
, void **ppvObject
)
3464 FileDialogImpl
*This
= impl_from_ICommDlgBrowser3(iface
);
3465 TRACE("%p\n", This
);
3466 return IFileDialog2_QueryInterface(&This
->IFileDialog2_iface
, riid
, ppvObject
);
3469 static ULONG WINAPI
ICommDlgBrowser3_fnAddRef(ICommDlgBrowser3
*iface
)
3471 FileDialogImpl
*This
= impl_from_ICommDlgBrowser3(iface
);
3472 TRACE("%p\n", This
);
3473 return IFileDialog2_AddRef(&This
->IFileDialog2_iface
);
3476 static ULONG WINAPI
ICommDlgBrowser3_fnRelease(ICommDlgBrowser3
*iface
)
3478 FileDialogImpl
*This
= impl_from_ICommDlgBrowser3(iface
);
3479 TRACE("%p\n", This
);
3480 return IFileDialog2_Release(&This
->IFileDialog2_iface
);
3483 static HRESULT WINAPI
ICommDlgBrowser3_fnOnDefaultCommand(ICommDlgBrowser3
*iface
,
3486 FileDialogImpl
*This
= impl_from_ICommDlgBrowser3(iface
);
3488 TRACE("%p (%p)\n", This
, shv
);
3490 hr
= on_default_action(This
);
3493 EndDialog(This
->dlg_hwnd
, S_OK
);
3498 static HRESULT WINAPI
ICommDlgBrowser3_fnOnStateChange(ICommDlgBrowser3
*iface
,
3499 IShellView
*shv
, ULONG uChange
)
3501 FileDialogImpl
*This
= impl_from_ICommDlgBrowser3(iface
);
3502 IDataObject
*new_selection
;
3504 TRACE("%p (%p, %x)\n", This
, shv
, uChange
);
3508 case CDBOSC_SELCHANGE
:
3509 if(This
->psia_selection
)
3511 IShellItemArray_Release(This
->psia_selection
);
3512 This
->psia_selection
= NULL
;
3515 hr
= IShellView_GetItemObject(shv
, SVGIO_SELECTION
, &IID_IDataObject
, (void**)&new_selection
);
3518 hr
= SHCreateShellItemArrayFromDataObject(new_selection
, &IID_IShellItemArray
,
3519 (void**)&This
->psia_selection
);
3522 fill_filename_from_selection(This
);
3523 events_OnSelectionChange(This
);
3526 IDataObject_Release(new_selection
);
3530 TRACE("Unhandled state change\n");
3535 static HRESULT WINAPI
ICommDlgBrowser3_fnIncludeObject(ICommDlgBrowser3
*iface
,
3536 IShellView
*shv
, LPCITEMIDLIST pidl
)
3538 FileDialogImpl
*This
= impl_from_ICommDlgBrowser3(iface
);
3541 LPITEMIDLIST parent_pidl
;
3544 TRACE("%p (%p, %p)\n", This
, shv
, pidl
);
3546 if(!This
->filterspec_count
&& !(This
->options
& FOS_PICKFOLDERS
))
3549 hr
= SHGetIDListFromObject((IUnknown
*)shv
, &parent_pidl
);
3552 LPITEMIDLIST full_pidl
= ILCombine(parent_pidl
, pidl
);
3553 hr
= SHCreateItemFromIDList(full_pidl
, &IID_IShellItem
, (void**)&psi
);
3554 ILFree(parent_pidl
);
3559 ERR("Failed to get shellitem (%08x).\n", hr
);
3563 hr
= IShellItem_GetAttributes(psi
, SFGAO_FOLDER
|SFGAO_LINK
, &attr
);
3564 if(FAILED(hr
) || (attr
& (SFGAO_FOLDER
| SFGAO_LINK
)))
3566 IShellItem_Release(psi
);
3570 if((This
->options
& FOS_PICKFOLDERS
) && !(attr
& (SFGAO_FOLDER
| SFGAO_LINK
)))
3572 IShellItem_Release(psi
);
3577 if(SUCCEEDED(IShellItem_GetDisplayName(psi
, SIGDN_PARENTRELATIVEPARSING
, &filename
)))
3579 if(!PathMatchSpecW(filename
, This
->filterspecs
[This
->filetypeindex
].pszSpec
))
3581 CoTaskMemFree(filename
);
3584 IShellItem_Release(psi
);
3588 static HRESULT WINAPI
ICommDlgBrowser3_fnNotify(ICommDlgBrowser3
*iface
,
3589 IShellView
*ppshv
, DWORD dwNotifyType
)
3591 FileDialogImpl
*This
= impl_from_ICommDlgBrowser3(iface
);
3592 FIXME("Stub: %p (%p, 0x%x)\n", This
, ppshv
, dwNotifyType
);
3596 static HRESULT WINAPI
ICommDlgBrowser3_fnGetDefaultMenuText(ICommDlgBrowser3
*iface
,
3598 LPWSTR pszText
, int cchMax
)
3600 FileDialogImpl
*This
= impl_from_ICommDlgBrowser3(iface
);
3601 FIXME("Stub: %p (%p, %p, %d)\n", This
, pshv
, pszText
, cchMax
);
3605 static HRESULT WINAPI
ICommDlgBrowser3_fnGetViewFlags(ICommDlgBrowser3
*iface
, DWORD
*pdwFlags
)
3607 FileDialogImpl
*This
= impl_from_ICommDlgBrowser3(iface
);
3608 FIXME("Stub: %p (%p)\n", This
, pdwFlags
);
3612 static HRESULT WINAPI
ICommDlgBrowser3_fnOnColumnClicked(ICommDlgBrowser3
*iface
,
3613 IShellView
*pshv
, int iColumn
)
3615 FileDialogImpl
*This
= impl_from_ICommDlgBrowser3(iface
);
3616 FIXME("Stub: %p (%p, %d)\n", This
, pshv
, iColumn
);
3620 static HRESULT WINAPI
ICommDlgBrowser3_fnGetCurrentFilter(ICommDlgBrowser3
*iface
,
3621 LPWSTR pszFileSpec
, int cchFileSpec
)
3623 FileDialogImpl
*This
= impl_from_ICommDlgBrowser3(iface
);
3624 FIXME("Stub: %p (%p, %d)\n", This
, pszFileSpec
, cchFileSpec
);
3628 static HRESULT WINAPI
ICommDlgBrowser3_fnOnPreviewCreated(ICommDlgBrowser3
*iface
,
3631 FileDialogImpl
*This
= impl_from_ICommDlgBrowser3(iface
);
3632 FIXME("Stub: %p (%p)\n", This
, pshv
);
3636 static const ICommDlgBrowser3Vtbl vt_ICommDlgBrowser3
= {
3637 ICommDlgBrowser3_fnQueryInterface
,
3638 ICommDlgBrowser3_fnAddRef
,
3639 ICommDlgBrowser3_fnRelease
,
3640 ICommDlgBrowser3_fnOnDefaultCommand
,
3641 ICommDlgBrowser3_fnOnStateChange
,
3642 ICommDlgBrowser3_fnIncludeObject
,
3643 ICommDlgBrowser3_fnNotify
,
3644 ICommDlgBrowser3_fnGetDefaultMenuText
,
3645 ICommDlgBrowser3_fnGetViewFlags
,
3646 ICommDlgBrowser3_fnOnColumnClicked
,
3647 ICommDlgBrowser3_fnGetCurrentFilter
,
3648 ICommDlgBrowser3_fnOnPreviewCreated
3651 /**************************************************************************
3652 * IOleWindow implementation
3654 static inline FileDialogImpl
*impl_from_IOleWindow(IOleWindow
*iface
)
3656 return CONTAINING_RECORD(iface
, FileDialogImpl
, IOleWindow_iface
);
3659 static HRESULT WINAPI
IOleWindow_fnQueryInterface(IOleWindow
*iface
, REFIID riid
, void **ppvObject
)
3661 FileDialogImpl
*This
= impl_from_IOleWindow(iface
);
3662 return IFileDialog2_QueryInterface(&This
->IFileDialog2_iface
, riid
, ppvObject
);
3665 static ULONG WINAPI
IOleWindow_fnAddRef(IOleWindow
*iface
)
3667 FileDialogImpl
*This
= impl_from_IOleWindow(iface
);
3668 return IFileDialog2_AddRef(&This
->IFileDialog2_iface
);
3671 static ULONG WINAPI
IOleWindow_fnRelease(IOleWindow
*iface
)
3673 FileDialogImpl
*This
= impl_from_IOleWindow(iface
);
3674 return IFileDialog2_Release(&This
->IFileDialog2_iface
);
3677 static HRESULT WINAPI
IOleWindow_fnContextSensitiveHelp(IOleWindow
*iface
, BOOL fEnterMOde
)
3679 FileDialogImpl
*This
= impl_from_IOleWindow(iface
);
3680 FIXME("Stub: %p (%d)\n", This
, fEnterMOde
);
3684 static HRESULT WINAPI
IOleWindow_fnGetWindow(IOleWindow
*iface
, HWND
*phwnd
)
3686 FileDialogImpl
*This
= impl_from_IOleWindow(iface
);
3687 TRACE("%p (%p)\n", This
, phwnd
);
3688 *phwnd
= This
->dlg_hwnd
;
3692 static const IOleWindowVtbl vt_IOleWindow
= {
3693 IOleWindow_fnQueryInterface
,
3694 IOleWindow_fnAddRef
,
3695 IOleWindow_fnRelease
,
3696 IOleWindow_fnGetWindow
,
3697 IOleWindow_fnContextSensitiveHelp
3700 /**************************************************************************
3701 * IFileDialogCustomize implementation
3703 static inline FileDialogImpl
*impl_from_IFileDialogCustomize(IFileDialogCustomize
*iface
)
3705 return CONTAINING_RECORD(iface
, FileDialogImpl
, IFileDialogCustomize_iface
);
3708 static HRESULT WINAPI
IFileDialogCustomize_fnQueryInterface(IFileDialogCustomize
*iface
,
3709 REFIID riid
, void **ppvObject
)
3711 FileDialogImpl
*This
= impl_from_IFileDialogCustomize(iface
);
3712 return IFileDialog2_QueryInterface(&This
->IFileDialog2_iface
, riid
, ppvObject
);
3715 static ULONG WINAPI
IFileDialogCustomize_fnAddRef(IFileDialogCustomize
*iface
)
3717 FileDialogImpl
*This
= impl_from_IFileDialogCustomize(iface
);
3718 return IFileDialog2_AddRef(&This
->IFileDialog2_iface
);
3721 static ULONG WINAPI
IFileDialogCustomize_fnRelease(IFileDialogCustomize
*iface
)
3723 FileDialogImpl
*This
= impl_from_IFileDialogCustomize(iface
);
3724 return IFileDialog2_Release(&This
->IFileDialog2_iface
);
3727 static HRESULT WINAPI
IFileDialogCustomize_fnEnableOpenDropDown(IFileDialogCustomize
*iface
,
3730 FileDialogImpl
*This
= impl_from_IFileDialogCustomize(iface
);
3732 TRACE("%p (%d)\n", This
, dwIDCtl
);
3734 if (This
->hmenu_opendropdown
|| get_cctrl(This
, dwIDCtl
))
3735 return E_UNEXPECTED
;
3737 This
->hmenu_opendropdown
= CreatePopupMenu();
3739 if (!This
->hmenu_opendropdown
)
3740 return E_OUTOFMEMORY
;
3742 mi
.cbSize
= sizeof(mi
);
3743 mi
.fMask
= MIM_STYLE
;
3744 mi
.dwStyle
= MNS_NOTIFYBYPOS
;
3745 SetMenuInfo(This
->hmenu_opendropdown
, &mi
);
3747 This
->cctrl_opendropdown
.hwnd
= NULL
;
3748 This
->cctrl_opendropdown
.wrapper_hwnd
= NULL
;
3749 This
->cctrl_opendropdown
.id
= dwIDCtl
;
3750 This
->cctrl_opendropdown
.dlgid
= 0;
3751 This
->cctrl_opendropdown
.type
= IDLG_CCTRL_OPENDROPDOWN
;
3752 This
->cctrl_opendropdown
.cdcstate
= CDCS_ENABLED
| CDCS_VISIBLE
;
3753 list_init(&This
->cctrl_opendropdown
.sub_cctrls
);
3754 list_init(&This
->cctrl_opendropdown
.sub_items
);
3759 static HRESULT WINAPI
IFileDialogCustomize_fnAddMenu(IFileDialogCustomize
*iface
,
3763 FileDialogImpl
*This
= impl_from_IFileDialogCustomize(iface
);
3767 TRACE("%p (%d, %p)\n", This
, dwIDCtl
, pszLabel
);
3769 hr
= cctrl_create_new(This
, dwIDCtl
, NULL
, TOOLBARCLASSNAMEW
,
3770 TBSTYLE_FLAT
| CCS_NODIVIDER
, 0,
3771 This
->cctrl_def_height
, &ctrl
);
3774 SendMessageW(ctrl
->hwnd
, TB_BUTTONSTRUCTSIZE
, sizeof(tbb
), 0);
3775 ctrl
->type
= IDLG_CCTRL_MENU
;
3777 /* Add the actual button with a popup menu. */
3778 tbb
.iBitmap
= I_IMAGENONE
;
3779 tbb
.dwData
= (DWORD_PTR
)CreatePopupMenu();
3780 tbb
.iString
= (DWORD_PTR
)pszLabel
;
3781 tbb
.fsState
= TBSTATE_ENABLED
;
3782 tbb
.fsStyle
= BTNS_WHOLEDROPDOWN
;
3785 SendMessageW(ctrl
->hwnd
, TB_ADDBUTTONSW
, 1, (LPARAM
)&tbb
);
3791 static HRESULT WINAPI
IFileDialogCustomize_fnAddPushButton(IFileDialogCustomize
*iface
,
3795 FileDialogImpl
*This
= impl_from_IFileDialogCustomize(iface
);
3798 TRACE("%p (%d, %p)\n", This
, dwIDCtl
, pszLabel
);
3800 hr
= cctrl_create_new(This
, dwIDCtl
, pszLabel
, WC_BUTTONW
, BS_MULTILINE
, 0,
3801 This
->cctrl_def_height
, &ctrl
);
3803 ctrl
->type
= IDLG_CCTRL_PUSHBUTTON
;
3808 static HRESULT WINAPI
IFileDialogCustomize_fnAddComboBox(IFileDialogCustomize
*iface
,
3811 FileDialogImpl
*This
= impl_from_IFileDialogCustomize(iface
);
3814 TRACE("%p (%d)\n", This
, dwIDCtl
);
3816 hr
= cctrl_create_new(This
, dwIDCtl
, NULL
, WC_COMBOBOXW
, CBS_DROPDOWNLIST
, 0,
3817 This
->cctrl_def_height
, &ctrl
);
3819 ctrl
->type
= IDLG_CCTRL_COMBOBOX
;
3824 static HRESULT WINAPI
IFileDialogCustomize_fnAddRadioButtonList(IFileDialogCustomize
*iface
,
3827 FileDialogImpl
*This
= impl_from_IFileDialogCustomize(iface
);
3830 TRACE("%p (%d)\n", This
, dwIDCtl
);
3832 hr
= cctrl_create_new(This
, dwIDCtl
, NULL
, radiobuttonlistW
, 0, 0, 0, &ctrl
);
3835 ctrl
->type
= IDLG_CCTRL_RADIOBUTTONLIST
;
3836 SetWindowLongPtrW(ctrl
->hwnd
, GWLP_USERDATA
, (LPARAM
)This
);
3842 static HRESULT WINAPI
IFileDialogCustomize_fnAddCheckButton(IFileDialogCustomize
*iface
,
3847 FileDialogImpl
*This
= impl_from_IFileDialogCustomize(iface
);
3850 TRACE("%p (%d, %p, %d)\n", This
, dwIDCtl
, pszLabel
, bChecked
);
3852 hr
= cctrl_create_new(This
, dwIDCtl
, pszLabel
, WC_BUTTONW
, BS_AUTOCHECKBOX
|BS_MULTILINE
, 0,
3853 This
->cctrl_def_height
, &ctrl
);
3856 ctrl
->type
= IDLG_CCTRL_CHECKBUTTON
;
3857 SendMessageW(ctrl
->hwnd
, BM_SETCHECK
, bChecked
? BST_CHECKED
: BST_UNCHECKED
, 0);
3863 static HRESULT WINAPI
IFileDialogCustomize_fnAddEditBox(IFileDialogCustomize
*iface
,
3867 FileDialogImpl
*This
= impl_from_IFileDialogCustomize(iface
);
3870 TRACE("%p (%d, %p)\n", This
, dwIDCtl
, pszText
);
3872 hr
= cctrl_create_new(This
, dwIDCtl
, pszText
, WC_EDITW
, ES_AUTOHSCROLL
, WS_EX_CLIENTEDGE
,
3873 This
->cctrl_def_height
, &ctrl
);
3875 ctrl
->type
= IDLG_CCTRL_EDITBOX
;
3880 static HRESULT WINAPI
IFileDialogCustomize_fnAddSeparator(IFileDialogCustomize
*iface
,
3883 FileDialogImpl
*This
= impl_from_IFileDialogCustomize(iface
);
3886 TRACE("%p (%d)\n", This
, dwIDCtl
);
3888 hr
= cctrl_create_new(This
, dwIDCtl
, NULL
, WC_STATICW
, SS_ETCHEDHORZ
, 0,
3889 GetSystemMetrics(SM_CYEDGE
), &ctrl
);
3891 ctrl
->type
= IDLG_CCTRL_SEPARATOR
;
3896 static HRESULT WINAPI
IFileDialogCustomize_fnAddText(IFileDialogCustomize
*iface
,
3900 FileDialogImpl
*This
= impl_from_IFileDialogCustomize(iface
);
3903 TRACE("%p (%d, %p)\n", This
, dwIDCtl
, pszText
);
3905 hr
= cctrl_create_new(This
, dwIDCtl
, pszText
, WC_STATICW
, 0, 0,
3906 This
->cctrl_def_height
, &ctrl
);
3908 ctrl
->type
= IDLG_CCTRL_TEXT
;
3913 static HRESULT WINAPI
IFileDialogCustomize_fnSetControlLabel(IFileDialogCustomize
*iface
,
3917 FileDialogImpl
*This
= impl_from_IFileDialogCustomize(iface
);
3918 customctrl
*ctrl
= get_cctrl(This
, dwIDCtl
);
3919 TRACE("%p (%d, %p)\n", This
, dwIDCtl
, pszLabel
);
3921 if(!ctrl
) return E_INVALIDARG
;
3925 case IDLG_CCTRL_MENU
:
3926 case IDLG_CCTRL_PUSHBUTTON
:
3927 case IDLG_CCTRL_CHECKBUTTON
:
3928 case IDLG_CCTRL_TEXT
:
3929 case IDLG_CCTRL_VISUALGROUP
:
3930 SendMessageW(ctrl
->hwnd
, WM_SETTEXT
, 0, (LPARAM
)pszLabel
);
3932 case IDLG_CCTRL_OPENDROPDOWN
:
3941 static HRESULT WINAPI
IFileDialogCustomize_fnGetControlState(IFileDialogCustomize
*iface
,
3943 CDCONTROLSTATEF
*pdwState
)
3945 FileDialogImpl
*This
= impl_from_IFileDialogCustomize(iface
);
3946 customctrl
*ctrl
= get_cctrl(This
, dwIDCtl
);
3947 TRACE("%p (%d, %p)\n", This
, dwIDCtl
, pdwState
);
3949 if(!ctrl
|| ctrl
->type
== IDLG_CCTRL_OPENDROPDOWN
) return E_NOTIMPL
;
3951 *pdwState
= ctrl
->cdcstate
;
3955 static HRESULT WINAPI
IFileDialogCustomize_fnSetControlState(IFileDialogCustomize
*iface
,
3957 CDCONTROLSTATEF dwState
)
3959 FileDialogImpl
*This
= impl_from_IFileDialogCustomize(iface
);
3960 customctrl
*ctrl
= get_cctrl(This
,dwIDCtl
);
3961 TRACE("%p (%d, %x)\n", This
, dwIDCtl
, dwState
);
3963 if(ctrl
&& ctrl
->hwnd
)
3965 LONG wndstyle
= GetWindowLongW(ctrl
->hwnd
, GWL_STYLE
);
3967 if(dwState
& CDCS_ENABLED
)
3968 wndstyle
&= ~(WS_DISABLED
);
3970 wndstyle
|= WS_DISABLED
;
3972 if(dwState
& CDCS_VISIBLE
)
3973 wndstyle
|= WS_VISIBLE
;
3975 wndstyle
&= ~(WS_VISIBLE
);
3977 SetWindowLongW(ctrl
->hwnd
, GWL_STYLE
, wndstyle
);
3979 /* We save the state separately since at least one application
3980 * relies on being able to hide a control. */
3981 ctrl
->cdcstate
= dwState
;
3987 static HRESULT WINAPI
IFileDialogCustomize_fnGetEditBoxText(IFileDialogCustomize
*iface
,
3991 FileDialogImpl
*This
= impl_from_IFileDialogCustomize(iface
);
3992 customctrl
*ctrl
= get_cctrl(This
, dwIDCtl
);
3994 TRACE("%p (%d, %p)\n", This
, dwIDCtl
, ppszText
);
3996 if(!ctrl
|| !ctrl
->hwnd
|| !(len
= SendMessageW(ctrl
->hwnd
, WM_GETTEXTLENGTH
, 0, 0)))
3999 text
= CoTaskMemAlloc(sizeof(WCHAR
)*(len
+1));
4000 if(!text
) return E_FAIL
;
4002 SendMessageW(ctrl
->hwnd
, WM_GETTEXT
, len
+1, (LPARAM
)text
);
4007 static HRESULT WINAPI
IFileDialogCustomize_fnSetEditBoxText(IFileDialogCustomize
*iface
,
4011 FileDialogImpl
*This
= impl_from_IFileDialogCustomize(iface
);
4012 customctrl
*ctrl
= get_cctrl(This
, dwIDCtl
);
4013 TRACE("%p (%d, %s)\n", This
, dwIDCtl
, debugstr_w(pszText
));
4015 if(!ctrl
|| ctrl
->type
!= IDLG_CCTRL_EDITBOX
)
4018 SendMessageW(ctrl
->hwnd
, WM_SETTEXT
, 0, (LPARAM
)pszText
);
4022 static HRESULT WINAPI
IFileDialogCustomize_fnGetCheckButtonState(IFileDialogCustomize
*iface
,
4026 FileDialogImpl
*This
= impl_from_IFileDialogCustomize(iface
);
4027 customctrl
*ctrl
= get_cctrl(This
, dwIDCtl
);
4028 TRACE("%p (%d, %p)\n", This
, dwIDCtl
, pbChecked
);
4030 if(ctrl
&& ctrl
->hwnd
)
4031 *pbChecked
= (SendMessageW(ctrl
->hwnd
, BM_GETCHECK
, 0, 0) == BST_CHECKED
);
4036 static HRESULT WINAPI
IFileDialogCustomize_fnSetCheckButtonState(IFileDialogCustomize
*iface
,
4040 FileDialogImpl
*This
= impl_from_IFileDialogCustomize(iface
);
4041 customctrl
*ctrl
= get_cctrl(This
, dwIDCtl
);
4042 TRACE("%p (%d, %d)\n", This
, dwIDCtl
, bChecked
);
4044 if(ctrl
&& ctrl
->hwnd
)
4045 SendMessageW(ctrl
->hwnd
, BM_SETCHECK
, bChecked
? BST_CHECKED
:BST_UNCHECKED
, 0);
4050 static UINT
get_combobox_index_from_id(HWND cb_hwnd
, DWORD dwIDItem
)
4052 UINT count
= SendMessageW(cb_hwnd
, CB_GETCOUNT
, 0, 0);
4054 if(!count
|| (count
== CB_ERR
))
4057 for(i
= 0; i
< count
; i
++)
4058 if(SendMessageW(cb_hwnd
, CB_GETITEMDATA
, i
, 0) == dwIDItem
)
4061 TRACE("Item with id %d not found in combobox %p (item count: %d)\n", dwIDItem
, cb_hwnd
, count
);
4065 static HRESULT WINAPI
IFileDialogCustomize_fnAddControlItem(IFileDialogCustomize
*iface
,
4070 FileDialogImpl
*This
= impl_from_IFileDialogCustomize(iface
);
4071 customctrl
*ctrl
= get_cctrl(This
, dwIDCtl
);
4073 TRACE("%p (%d, %d, %s)\n", This
, dwIDCtl
, dwIDItem
, debugstr_w(pszLabel
));
4075 if(!ctrl
) return E_FAIL
;
4079 case IDLG_CCTRL_COMBOBOX
:
4084 hr
= add_item(ctrl
, dwIDItem
, pszLabel
, &item
);
4086 if (FAILED(hr
)) return hr
;
4088 index
= SendMessageW(ctrl
->hwnd
, CB_ADDSTRING
, 0, (LPARAM
)pszLabel
);
4089 SendMessageW(ctrl
->hwnd
, CB_SETITEMDATA
, index
, dwIDItem
);
4093 case IDLG_CCTRL_MENU
:
4094 case IDLG_CCTRL_OPENDROPDOWN
:
4099 hr
= add_item(ctrl
, dwIDItem
, pszLabel
, &item
);
4101 if (FAILED(hr
)) return hr
;
4103 if (ctrl
->type
== IDLG_CCTRL_MENU
)
4106 SendMessageW(ctrl
->hwnd
, TB_GETBUTTON
, 0, (LPARAM
)&tbb
);
4107 hmenu
= (HMENU
)tbb
.dwData
;
4109 else /* ctrl->type == IDLG_CCTRL_OPENDROPDOWN */
4110 hmenu
= This
->hmenu_opendropdown
;
4112 AppendMenuW(hmenu
, MF_STRING
, dwIDItem
, pszLabel
);
4115 case IDLG_CCTRL_RADIOBUTTONLIST
:
4119 hr
= add_item(ctrl
, dwIDItem
, pszLabel
, &item
);
4123 item
->hwnd
= CreateWindowExW(0, WC_BUTTONW
, pszLabel
,
4124 WS_CHILD
|WS_VISIBLE
|WS_CLIPSIBLINGS
|BS_RADIOBUTTON
|BS_MULTILINE
,
4125 0, 0, 0, 0, ctrl
->hwnd
, ULongToHandle(dwIDItem
), COMDLG32_hInstance
, 0);
4129 ERR("Failed to create radio button\n");
4130 list_remove(&item
->entry
);
4142 return E_NOINTERFACE
; /* win7 */
4145 static HRESULT WINAPI
IFileDialogCustomize_fnRemoveControlItem(IFileDialogCustomize
*iface
,
4149 FileDialogImpl
*This
= impl_from_IFileDialogCustomize(iface
);
4150 customctrl
*ctrl
= get_cctrl(This
, dwIDCtl
);
4151 TRACE("%p (%d, %d)\n", This
, dwIDCtl
, dwIDItem
);
4153 if(!ctrl
) return E_FAIL
;
4157 case IDLG_CCTRL_COMBOBOX
:
4162 item
= get_item(ctrl
, dwIDItem
, CDCS_VISIBLE
|CDCS_ENABLED
, &position
);
4164 if ((item
->cdcstate
& (CDCS_VISIBLE
|CDCS_ENABLED
)) == (CDCS_VISIBLE
|CDCS_ENABLED
))
4166 if(SendMessageW(ctrl
->hwnd
, CB_DELETESTRING
, position
, 0) == CB_ERR
)
4170 list_remove(&item
->entry
);
4175 case IDLG_CCTRL_MENU
:
4176 case IDLG_CCTRL_OPENDROPDOWN
:
4181 item
= get_item(ctrl
, dwIDItem
, 0, NULL
);
4184 return E_UNEXPECTED
;
4186 if (item
->cdcstate
& CDCS_VISIBLE
)
4188 if (ctrl
->type
== IDLG_CCTRL_MENU
)
4191 SendMessageW(ctrl
->hwnd
, TB_GETBUTTON
, 0, (LPARAM
)&tbb
);
4192 hmenu
= (HMENU
)tbb
.dwData
;
4194 else /* ctrl->type == IDLG_CCTRL_OPENDROPDOWN */
4195 hmenu
= This
->hmenu_opendropdown
;
4197 if(!hmenu
|| !DeleteMenu(hmenu
, dwIDItem
, MF_BYCOMMAND
))
4198 return E_UNEXPECTED
;
4201 list_remove(&item
->entry
);
4206 case IDLG_CCTRL_RADIOBUTTONLIST
:
4210 item
= get_item(ctrl
, dwIDItem
, 0, NULL
);
4213 return E_UNEXPECTED
;
4215 list_remove(&item
->entry
);
4227 static HRESULT WINAPI
IFileDialogCustomize_fnRemoveAllControlItems(IFileDialogCustomize
*iface
,
4230 FileDialogImpl
*This
= impl_from_IFileDialogCustomize(iface
);
4231 TRACE("%p (%d)\n", This
, dwIDCtl
);
4233 /* Not implemented by native */
4237 static HRESULT WINAPI
IFileDialogCustomize_fnGetControlItemState(IFileDialogCustomize
*iface
,
4240 CDCONTROLSTATEF
*pdwState
)
4242 FileDialogImpl
*This
= impl_from_IFileDialogCustomize(iface
);
4243 customctrl
*ctrl
= get_cctrl(This
, dwIDCtl
);
4244 TRACE("%p (%d, %d, %p)\n", This
, dwIDCtl
, dwIDItem
, pdwState
);
4246 if(!ctrl
) return E_FAIL
;
4250 case IDLG_CCTRL_COMBOBOX
:
4251 case IDLG_CCTRL_MENU
:
4252 case IDLG_CCTRL_OPENDROPDOWN
:
4253 case IDLG_CCTRL_RADIOBUTTONLIST
:
4257 item
= get_item(ctrl
, dwIDItem
, 0, NULL
);
4260 return E_UNEXPECTED
;
4262 *pdwState
= item
->cdcstate
;
4273 static HRESULT WINAPI
IFileDialogCustomize_fnSetControlItemState(IFileDialogCustomize
*iface
,
4276 CDCONTROLSTATEF dwState
)
4278 FileDialogImpl
*This
= impl_from_IFileDialogCustomize(iface
);
4279 customctrl
*ctrl
= get_cctrl(This
, dwIDCtl
);
4280 TRACE("%p (%d, %d, %x)\n", This
, dwIDCtl
, dwIDItem
, dwState
);
4282 if(!ctrl
) return E_FAIL
;
4286 case IDLG_CCTRL_COMBOBOX
:
4289 BOOL visible
, was_visible
;
4292 item
= get_item(ctrl
, dwIDItem
, CDCS_VISIBLE
|CDCS_ENABLED
, &position
);
4295 return E_UNEXPECTED
;
4297 visible
= ((dwState
& (CDCS_VISIBLE
|CDCS_ENABLED
)) == (CDCS_VISIBLE
|CDCS_ENABLED
));
4298 was_visible
= ((item
->cdcstate
& (CDCS_VISIBLE
|CDCS_ENABLED
)) == (CDCS_VISIBLE
|CDCS_ENABLED
));
4300 if (visible
&& !was_visible
)
4302 SendMessageW(ctrl
->hwnd
, CB_INSERTSTRING
, position
, (LPARAM
)item
->label
);
4303 SendMessageW(ctrl
->hwnd
, CB_SETITEMDATA
, position
, dwIDItem
);
4305 else if (!visible
&& was_visible
)
4307 SendMessageW(ctrl
->hwnd
, CB_DELETESTRING
, position
, 0);
4310 item
->cdcstate
= dwState
;
4314 case IDLG_CCTRL_MENU
:
4315 case IDLG_CCTRL_OPENDROPDOWN
:
4319 CDCONTROLSTATEF prev_state
;
4322 item
= get_item(ctrl
, dwIDItem
, CDCS_VISIBLE
, &position
);
4325 return E_UNEXPECTED
;
4327 prev_state
= item
->cdcstate
;
4329 if (ctrl
->type
== IDLG_CCTRL_MENU
)
4332 SendMessageW(ctrl
->hwnd
, TB_GETBUTTON
, 0, (LPARAM
)&tbb
);
4333 hmenu
= (HMENU
)tbb
.dwData
;
4335 else /* ctrl->type == IDLG_CCTRL_OPENDROPDOWN */
4336 hmenu
= This
->hmenu_opendropdown
;
4338 if (dwState
& CDCS_VISIBLE
)
4340 if (prev_state
& CDCS_VISIBLE
)
4343 EnableMenuItem(hmenu
, dwIDItem
,
4344 MF_BYCOMMAND
|((dwState
& CDCS_ENABLED
) ? MFS_ENABLED
: MFS_DISABLED
));
4351 mii
.cbSize
= sizeof(mii
);
4352 mii
.fMask
= MIIM_ID
|MIIM_STATE
|MIIM_STRING
;
4353 mii
.fState
= (dwState
& CDCS_ENABLED
) ? MFS_ENABLED
: MFS_DISABLED
;
4355 mii
.dwTypeData
= item
->label
;
4357 InsertMenuItemW(hmenu
, position
, TRUE
, &mii
);
4360 else if (prev_state
& CDCS_VISIBLE
)
4363 DeleteMenu(hmenu
, dwIDItem
, MF_BYCOMMAND
);
4366 item
->cdcstate
= dwState
;
4368 if (ctrl
->type
== IDLG_CCTRL_OPENDROPDOWN
)
4370 update_control_text(This
);
4371 update_layout(This
);
4376 case IDLG_CCTRL_RADIOBUTTONLIST
:
4380 item
= get_item(ctrl
, dwIDItem
, CDCS_VISIBLE
, NULL
);
4383 return E_UNEXPECTED
;
4385 /* Oddly, native allows setting this but doesn't seem to do anything with it. */
4386 item
->cdcstate
= dwState
;
4397 static HRESULT WINAPI
IFileDialogCustomize_fnGetSelectedControlItem(IFileDialogCustomize
*iface
,
4401 FileDialogImpl
*This
= impl_from_IFileDialogCustomize(iface
);
4402 customctrl
*ctrl
= get_cctrl(This
, dwIDCtl
);
4403 TRACE("%p (%d, %p)\n", This
, dwIDCtl
, pdwIDItem
);
4405 if(!ctrl
) return E_FAIL
;
4409 case IDLG_CCTRL_COMBOBOX
:
4411 UINT index
= SendMessageW(ctrl
->hwnd
, CB_GETCURSEL
, 0, 0);
4415 *pdwIDItem
= SendMessageW(ctrl
->hwnd
, CB_GETITEMDATA
, index
, 0);
4418 case IDLG_CCTRL_OPENDROPDOWN
:
4419 if (This
->opendropdown_has_selection
)
4421 *pdwIDItem
= This
->opendropdown_selection
;
4426 /* Return first enabled item. */
4427 cctrl_item
* item
= get_first_item(ctrl
);
4431 *pdwIDItem
= item
->id
;
4435 WARN("no enabled items in open dropdown\n");
4438 case IDLG_CCTRL_RADIOBUTTONLIST
:
4442 LIST_FOR_EACH_ENTRY(item
, &ctrl
->sub_items
, cctrl_item
, entry
)
4444 if (SendMessageW(item
->hwnd
, BM_GETCHECK
, 0, 0) == BST_CHECKED
)
4446 *pdwIDItem
= item
->id
;
4451 WARN("no checked items in radio button list\n");
4455 FIXME("Unsupported control type %d\n", ctrl
->type
);
4461 static HRESULT WINAPI
IFileDialogCustomize_fnSetSelectedControlItem(IFileDialogCustomize
*iface
,
4465 FileDialogImpl
*This
= impl_from_IFileDialogCustomize(iface
);
4466 customctrl
*ctrl
= get_cctrl(This
, dwIDCtl
);
4467 TRACE("%p (%d, %d)\n", This
, dwIDCtl
, dwIDItem
);
4469 if(!ctrl
) return E_INVALIDARG
;
4473 case IDLG_CCTRL_COMBOBOX
:
4475 UINT index
= get_combobox_index_from_id(ctrl
->hwnd
, dwIDItem
);
4478 return E_INVALIDARG
;
4480 if(SendMessageW(ctrl
->hwnd
, CB_SETCURSEL
, index
, 0) == CB_ERR
)
4485 case IDLG_CCTRL_RADIOBUTTONLIST
:
4489 item
= get_item(ctrl
, dwIDItem
, 0, NULL
);
4493 radiobuttonlist_set_selected_item(This
, ctrl
, item
);
4497 return E_INVALIDARG
;
4500 FIXME("Unsupported control type %d\n", ctrl
->type
);
4503 return E_INVALIDARG
;
4506 static HRESULT WINAPI
IFileDialogCustomize_fnStartVisualGroup(IFileDialogCustomize
*iface
,
4510 FileDialogImpl
*This
= impl_from_IFileDialogCustomize(iface
);
4513 TRACE("%p (%d, %s)\n", This
, dwIDCtl
, debugstr_w(pszLabel
));
4515 if(This
->cctrl_active_vg
)
4516 return E_UNEXPECTED
;
4518 hr
= cctrl_create_new(This
, dwIDCtl
, pszLabel
, WC_STATICW
, 0, 0,
4519 This
->cctrl_def_height
, &vg
);
4522 vg
->type
= IDLG_CCTRL_VISUALGROUP
;
4523 This
->cctrl_active_vg
= vg
;
4529 static HRESULT WINAPI
IFileDialogCustomize_fnEndVisualGroup(IFileDialogCustomize
*iface
)
4531 FileDialogImpl
*This
= impl_from_IFileDialogCustomize(iface
);
4532 TRACE("%p\n", This
);
4534 This
->cctrl_active_vg
= NULL
;
4539 static HRESULT WINAPI
IFileDialogCustomize_fnMakeProminent(IFileDialogCustomize
*iface
,
4542 FileDialogImpl
*This
= impl_from_IFileDialogCustomize(iface
);
4543 FIXME("stub - %p (%d)\n", This
, dwIDCtl
);
4547 static HRESULT WINAPI
IFileDialogCustomize_fnSetControlItemText(IFileDialogCustomize
*iface
,
4552 FileDialogImpl
*This
= impl_from_IFileDialogCustomize(iface
);
4553 FIXME("stub - %p (%d, %d, %s)\n", This
, dwIDCtl
, dwIDItem
, debugstr_w(pszLabel
));
4557 static const IFileDialogCustomizeVtbl vt_IFileDialogCustomize
= {
4558 IFileDialogCustomize_fnQueryInterface
,
4559 IFileDialogCustomize_fnAddRef
,
4560 IFileDialogCustomize_fnRelease
,
4561 IFileDialogCustomize_fnEnableOpenDropDown
,
4562 IFileDialogCustomize_fnAddMenu
,
4563 IFileDialogCustomize_fnAddPushButton
,
4564 IFileDialogCustomize_fnAddComboBox
,
4565 IFileDialogCustomize_fnAddRadioButtonList
,
4566 IFileDialogCustomize_fnAddCheckButton
,
4567 IFileDialogCustomize_fnAddEditBox
,
4568 IFileDialogCustomize_fnAddSeparator
,
4569 IFileDialogCustomize_fnAddText
,
4570 IFileDialogCustomize_fnSetControlLabel
,
4571 IFileDialogCustomize_fnGetControlState
,
4572 IFileDialogCustomize_fnSetControlState
,
4573 IFileDialogCustomize_fnGetEditBoxText
,
4574 IFileDialogCustomize_fnSetEditBoxText
,
4575 IFileDialogCustomize_fnGetCheckButtonState
,
4576 IFileDialogCustomize_fnSetCheckButtonState
,
4577 IFileDialogCustomize_fnAddControlItem
,
4578 IFileDialogCustomize_fnRemoveControlItem
,
4579 IFileDialogCustomize_fnRemoveAllControlItems
,
4580 IFileDialogCustomize_fnGetControlItemState
,
4581 IFileDialogCustomize_fnSetControlItemState
,
4582 IFileDialogCustomize_fnGetSelectedControlItem
,
4583 IFileDialogCustomize_fnSetSelectedControlItem
,
4584 IFileDialogCustomize_fnStartVisualGroup
,
4585 IFileDialogCustomize_fnEndVisualGroup
,
4586 IFileDialogCustomize_fnMakeProminent
,
4587 IFileDialogCustomize_fnSetControlItemText
4590 static HRESULT
FileDialog_constructor(IUnknown
*pUnkOuter
, REFIID riid
, void **ppv
, enum ITEMDLG_TYPE type
)
4592 FileDialogImpl
*fdimpl
;
4595 TRACE("%p, %s, %p\n", pUnkOuter
, debugstr_guid(riid
), ppv
);
4600 return CLASS_E_NOAGGREGATION
;
4602 fdimpl
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(FileDialogImpl
));
4604 return E_OUTOFMEMORY
;
4607 fdimpl
->IFileDialog2_iface
.lpVtbl
= &vt_IFileDialog2
;
4608 fdimpl
->IExplorerBrowserEvents_iface
.lpVtbl
= &vt_IExplorerBrowserEvents
;
4609 fdimpl
->IServiceProvider_iface
.lpVtbl
= &vt_IServiceProvider
;
4610 fdimpl
->ICommDlgBrowser3_iface
.lpVtbl
= &vt_ICommDlgBrowser3
;
4611 fdimpl
->IOleWindow_iface
.lpVtbl
= &vt_IOleWindow
;
4612 fdimpl
->IFileDialogCustomize_iface
.lpVtbl
= &vt_IFileDialogCustomize
;
4614 if(type
== ITEMDLG_TYPE_OPEN
)
4616 fdimpl
->dlg_type
= ITEMDLG_TYPE_OPEN
;
4617 fdimpl
->u
.IFileOpenDialog_iface
.lpVtbl
= &vt_IFileOpenDialog
;
4618 fdimpl
->options
= FOS_PATHMUSTEXIST
| FOS_FILEMUSTEXIST
| FOS_NOCHANGEDIR
;
4619 fdimpl
->custom_title
= fdimpl
->custom_okbutton
= NULL
;
4624 fdimpl
->dlg_type
= ITEMDLG_TYPE_SAVE
;
4625 fdimpl
->u
.IFileSaveDialog_iface
.lpVtbl
= &vt_IFileSaveDialog
;
4626 fdimpl
->options
= FOS_OVERWRITEPROMPT
| FOS_NOREADONLYRETURN
| FOS_PATHMUSTEXIST
| FOS_NOCHANGEDIR
;
4628 LoadStringW(COMDLG32_hInstance
, IDS_SAVE
, buf
, ARRAY_SIZE(buf
));
4629 fdimpl
->custom_title
= StrDupW(buf
);
4630 fdimpl
->custom_okbutton
= StrDupW(buf
);
4633 list_init(&fdimpl
->events_clients
);
4635 /* FIXME: The default folder setting should be restored for the
4636 * application if it was previously set. */
4637 SHGetDesktopFolder(&psf
);
4638 SHGetItemFromObject((IUnknown
*)psf
, &IID_IShellItem
, (void**)&fdimpl
->psi_defaultfolder
);
4639 IShellFolder_Release(psf
);
4641 hr
= init_custom_controls(fdimpl
);
4644 ERR("Failed to initialize custom controls (0x%08x).\n", hr
);
4645 IFileDialog2_Release(&fdimpl
->IFileDialog2_iface
);
4649 hr
= IFileDialog2_QueryInterface(&fdimpl
->IFileDialog2_iface
, riid
, ppv
);
4650 IFileDialog2_Release(&fdimpl
->IFileDialog2_iface
);
4654 HRESULT
FileOpenDialog_Constructor(IUnknown
*pUnkOuter
, REFIID riid
, void **ppv
)
4656 return FileDialog_constructor(pUnkOuter
, riid
, ppv
, ITEMDLG_TYPE_OPEN
);
4659 HRESULT
FileSaveDialog_Constructor(IUnknown
*pUnkOuter
, REFIID riid
, void **ppv
)
4661 return FileDialog_constructor(pUnkOuter
, riid
, ppv
, ITEMDLG_TYPE_SAVE
);