4 * Copyright 2010,2011 David Hedberg
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
24 #define NONAMELESSUNION
35 #include "filedlgbrowser.h"
37 #include "wine/debug.h"
38 #include "wine/list.h"
40 #define IDC_NAV_TOOLBAR 200
41 #define IDC_NAVBACK 201
42 #define IDC_NAVFORWARD 202
45 /* This seems to be another version of IID_IFileDialogCustomize. If
46 * there is any difference I have yet to find it. */
47 DEFINE_GUID(IID_IFileDialogCustomizeAlt
, 0x8016B7B3, 0x3D49, 0x4504, 0xA0,0xAA, 0x2A,0x37,0x49,0x4E,0x60,0x6F);
49 WINE_DEFAULT_DEBUG_CHANNEL(commdlg
);
56 enum ITEMDLG_CCTRL_TYPE
{
58 IDLG_CCTRL_PUSHBUTTON
,
60 IDLG_CCTRL_RADIOBUTTONLIST
,
61 IDLG_CCTRL_CHECKBUTTON
,
65 IDLG_CCTRL_OPENDROPDOWN
,
66 IDLG_CCTRL_VISUALGROUP
69 typedef struct cctrl_item
{
72 CDCONTROLSTATEF cdcstate
;
78 HWND hwnd
, wrapper_hwnd
;
80 enum ITEMDLG_CCTRL_TYPE type
;
81 CDCONTROLSTATEF cdcstate
;
84 struct list sub_cctrls
;
85 struct list sub_cctrls_entry
;
86 struct list sub_items
;
91 IFileDialogEvents
*pfde
;
95 typedef struct FileDialogImpl
{
96 IFileDialog2 IFileDialog2_iface
;
98 IFileOpenDialog IFileOpenDialog_iface
;
99 IFileSaveDialog IFileSaveDialog_iface
;
101 enum ITEMDLG_TYPE dlg_type
;
102 IExplorerBrowserEvents IExplorerBrowserEvents_iface
;
103 IServiceProvider IServiceProvider_iface
;
104 ICommDlgBrowser3 ICommDlgBrowser3_iface
;
105 IOleWindow IOleWindow_iface
;
106 IFileDialogCustomize IFileDialogCustomize_iface
;
109 FILEOPENDIALOGOPTIONS options
;
110 COMDLG_FILTERSPEC
*filterspecs
;
111 UINT filterspec_count
;
114 struct list events_clients
;
115 DWORD events_next_cookie
;
117 IShellItemArray
*psia_selection
;
118 IShellItemArray
*psia_results
;
119 IShellItem
*psi_defaultfolder
;
120 IShellItem
*psi_setfolder
;
121 IShellItem
*psi_folder
;
124 IExplorerBrowser
*peb
;
125 DWORD ebevents_cookie
;
130 LPWSTR custom_okbutton
;
131 LPWSTR custom_cancelbutton
;
132 LPWSTR custom_filenamelabel
;
134 UINT cctrl_width
, cctrl_def_height
, cctrls_cols
;
135 UINT cctrl_indent
, dpi_x
, dpi_y
;
138 UINT_PTR cctrl_next_dlgid
;
139 customctrl
*cctrl_active_vg
;
141 HMENU hmenu_opendropdown
;
142 customctrl cctrl_opendropdown
;
143 HFONT hfont_opendropdown
;
144 BOOL opendropdown_has_selection
;
145 DWORD opendropdown_selection
;
150 /**************************************************************************
153 static HRESULT
events_OnFileOk(FileDialogImpl
*This
)
155 events_client
*cursor
;
159 LIST_FOR_EACH_ENTRY(cursor
, &This
->events_clients
, events_client
, entry
)
161 TRACE("Notifying %p\n", cursor
);
162 hr
= IFileDialogEvents_OnFileOk(cursor
->pfde
, (IFileDialog
*)&This
->IFileDialog2_iface
);
163 if(FAILED(hr
) && hr
!= E_NOTIMPL
)
173 static HRESULT
events_OnFolderChanging(FileDialogImpl
*This
, IShellItem
*folder
)
175 events_client
*cursor
;
177 TRACE("%p (%p)\n", This
, folder
);
179 LIST_FOR_EACH_ENTRY(cursor
, &This
->events_clients
, events_client
, entry
)
181 TRACE("Notifying %p\n", cursor
);
182 hr
= IFileDialogEvents_OnFolderChanging(cursor
->pfde
, (IFileDialog
*)&This
->IFileDialog2_iface
, folder
);
183 if(FAILED(hr
) && hr
!= E_NOTIMPL
)
193 static void events_OnFolderChange(FileDialogImpl
*This
)
195 events_client
*cursor
;
198 LIST_FOR_EACH_ENTRY(cursor
, &This
->events_clients
, events_client
, entry
)
200 TRACE("Notifying %p\n", cursor
);
201 IFileDialogEvents_OnFolderChange(cursor
->pfde
, (IFileDialog
*)&This
->IFileDialog2_iface
);
205 static void events_OnSelectionChange(FileDialogImpl
*This
)
207 events_client
*cursor
;
210 LIST_FOR_EACH_ENTRY(cursor
, &This
->events_clients
, events_client
, entry
)
212 TRACE("Notifying %p\n", cursor
);
213 IFileDialogEvents_OnSelectionChange(cursor
->pfde
, (IFileDialog
*)&This
->IFileDialog2_iface
);
217 static void events_OnTypeChange(FileDialogImpl
*This
)
219 events_client
*cursor
;
222 LIST_FOR_EACH_ENTRY(cursor
, &This
->events_clients
, events_client
, entry
)
224 TRACE("Notifying %p\n", cursor
);
225 IFileDialogEvents_OnTypeChange(cursor
->pfde
, (IFileDialog
*)&This
->IFileDialog2_iface
);
229 static HRESULT
events_OnOverwrite(FileDialogImpl
*This
, IShellItem
*shellitem
)
231 events_client
*cursor
;
233 FDE_OVERWRITE_RESPONSE response
= FDEOR_DEFAULT
;
234 TRACE("%p %p\n", This
, shellitem
);
236 LIST_FOR_EACH_ENTRY(cursor
, &This
->events_clients
, events_client
, entry
)
238 TRACE("Notifying %p\n", cursor
);
239 hr
= IFileDialogEvents_OnOverwrite(cursor
->pfde
, (IFileDialog
*)&This
->IFileDialog2_iface
, shellitem
, &response
);
240 TRACE("<-- hr=%lx response=%u\n", hr
, response
);
241 if(FAILED(hr
) && hr
!= E_NOTIMPL
)
250 if (response
== FDEOR_DEFAULT
)
255 LoadStringW(COMDLG32_hInstance
, IDS_OVERWRITEFILE
, buf
, 100);
256 answer
= MessageBoxW(This
->dlg_hwnd
, buf
, This
->custom_title
,
257 MB_YESNO
| MB_ICONEXCLAMATION
);
258 if (answer
== IDNO
|| answer
== IDCANCEL
)
263 else if (response
== FDEOR_REFUSE
)
270 static inline HRESULT
get_cctrl_event(IFileDialogEvents
*pfde
, IFileDialogControlEvents
**pfdce
)
272 return IFileDialogEvents_QueryInterface(pfde
, &IID_IFileDialogControlEvents
, (void**)pfdce
);
275 static HRESULT
cctrl_event_OnButtonClicked(FileDialogImpl
*This
, DWORD ctl_id
)
277 events_client
*cursor
;
280 LIST_FOR_EACH_ENTRY(cursor
, &This
->events_clients
, events_client
, entry
)
282 IFileDialogControlEvents
*pfdce
;
283 if(SUCCEEDED(get_cctrl_event(cursor
->pfde
, &pfdce
)))
285 TRACE("Notifying %p\n", cursor
);
286 IFileDialogControlEvents_OnButtonClicked(pfdce
, &This
->IFileDialogCustomize_iface
, ctl_id
);
287 IFileDialogControlEvents_Release(pfdce
);
294 static HRESULT
cctrl_event_OnItemSelected(FileDialogImpl
*This
, DWORD ctl_id
, DWORD item_id
)
296 events_client
*cursor
;
297 TRACE("%p %li %li\n", This
, ctl_id
, item_id
);
299 LIST_FOR_EACH_ENTRY(cursor
, &This
->events_clients
, events_client
, entry
)
301 IFileDialogControlEvents
*pfdce
;
302 if(SUCCEEDED(get_cctrl_event(cursor
->pfde
, &pfdce
)))
304 TRACE("Notifying %p\n", cursor
);
305 IFileDialogControlEvents_OnItemSelected(pfdce
, &This
->IFileDialogCustomize_iface
, ctl_id
, item_id
);
306 IFileDialogControlEvents_Release(pfdce
);
313 static HRESULT
cctrl_event_OnCheckButtonToggled(FileDialogImpl
*This
, DWORD ctl_id
, BOOL checked
)
315 events_client
*cursor
;
318 LIST_FOR_EACH_ENTRY(cursor
, &This
->events_clients
, events_client
, entry
)
320 IFileDialogControlEvents
*pfdce
;
321 if(SUCCEEDED(get_cctrl_event(cursor
->pfde
, &pfdce
)))
323 TRACE("Notifying %p\n", cursor
);
324 IFileDialogControlEvents_OnCheckButtonToggled(pfdce
, &This
->IFileDialogCustomize_iface
, ctl_id
, checked
);
325 IFileDialogControlEvents_Release(pfdce
);
332 static HRESULT
cctrl_event_OnControlActivating(FileDialogImpl
*This
,
335 events_client
*cursor
;
338 LIST_FOR_EACH_ENTRY(cursor
, &This
->events_clients
, events_client
, entry
)
340 IFileDialogControlEvents
*pfdce
;
341 if(SUCCEEDED(get_cctrl_event(cursor
->pfde
, &pfdce
)))
343 TRACE("Notifying %p\n", cursor
);
344 IFileDialogControlEvents_OnControlActivating(pfdce
, &This
->IFileDialogCustomize_iface
, ctl_id
);
345 IFileDialogControlEvents_Release(pfdce
);
352 /**************************************************************************
355 static UINT
get_file_name(FileDialogImpl
*This
, LPWSTR
*str
)
357 HWND hwnd_edit
= GetDlgItem(This
->dlg_hwnd
, IDC_FILENAME
);
362 if(This
->set_filename
)
364 len
= lstrlenW(This
->set_filename
);
365 *str
= CoTaskMemAlloc(sizeof(WCHAR
)*(len
+1));
366 lstrcpyW(*str
, This
->set_filename
);
372 len
= SendMessageW(hwnd_edit
, WM_GETTEXTLENGTH
, 0, 0);
373 *str
= CoTaskMemAlloc(sizeof(WCHAR
)*(len
+1));
377 SendMessageW(hwnd_edit
, WM_GETTEXT
, len
+1, (LPARAM
)*str
);
381 static BOOL
set_file_name(FileDialogImpl
*This
, LPCWSTR str
)
383 if(This
->set_filename
)
384 LocalFree(This
->set_filename
);
386 This
->set_filename
= str
? StrDupW(str
) : NULL
;
388 return SetDlgItemTextW(This
->dlg_hwnd
, IDC_FILENAME
, This
->set_filename
);
391 static void fill_filename_from_selection(FileDialogImpl
*This
)
400 if(!This
->psia_selection
)
403 hr
= IShellItemArray_GetCount(This
->psia_selection
, &item_count
);
404 if(FAILED(hr
) || !item_count
)
407 names
= HeapAlloc(GetProcessHeap(), 0, item_count
*sizeof(LPWSTR
));
409 /* Get names of the selected items */
410 valid_count
= 0; len_total
= 0;
411 for(i
= 0; i
< item_count
; i
++)
413 hr
= IShellItemArray_GetItemAt(This
->psia_selection
, i
, &psi
);
418 hr
= IShellItem_GetAttributes(psi
, SFGAO_FOLDER
, &attr
);
420 (( (This
->options
& FOS_PICKFOLDERS
) && !(attr
& SFGAO_FOLDER
)) ||
421 (!(This
->options
& FOS_PICKFOLDERS
) && (attr
& SFGAO_FOLDER
))))
424 hr
= IShellItem_GetDisplayName(psi
, (This
->options
& FOS_PICKFOLDERS
) ? SIGDN_FILESYSPATH
: SIGDN_PARENTRELATIVEPARSING
, &names
[valid_count
]);
427 len_total
+= lstrlenW(names
[valid_count
]) + 3;
430 IShellItem_Release(psi
);
436 set_file_name(This
, names
[0]);
437 CoTaskMemFree(names
[0]);
439 else if(valid_count
> 1)
441 LPWSTR string
= HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR
)*len_total
);
442 LPWSTR cur_point
= string
;
444 for(i
= 0; i
< valid_count
; i
++)
446 LPWSTR file
= names
[i
];
448 lstrcpyW(cur_point
, file
);
449 cur_point
+= lstrlenW(file
);
454 *(cur_point
-1) = '\0';
456 set_file_name(This
, string
);
457 HeapFree(GetProcessHeap(), 0, string
);
460 HeapFree(GetProcessHeap(), 0, names
);
464 static LPWSTR
get_first_ext_from_spec(LPWSTR buf
, LPCWSTR spec
)
469 if( (endpos
= StrChrW(buf
, ';')) )
472 ext
= PathFindExtensionW(buf
);
473 if(StrChrW(ext
, '*'))
479 static BOOL
shell_item_exists(IShellItem
* shellitem
)
485 hr
= IShellItem_GetDisplayName(shellitem
, SIGDN_FILESYSPATH
, &filename
);
488 /* FIXME: Implement SFGAO_VALIDATE in Wine and use it instead. */
489 result
= (GetFileAttributesW(filename
) != INVALID_FILE_ATTRIBUTES
);
490 CoTaskMemFree(filename
);
495 result
= SUCCEEDED(IShellItem_GetAttributes(shellitem
, SFGAO_VALIDATE
, &attributes
));
501 static HRESULT
on_default_action(FileDialogImpl
*This
)
503 IShellFolder
*psf_parent
, *psf_desktop
;
505 LPITEMIDLIST current_folder
;
506 LPWSTR fn_iter
, files
= NULL
, tmp_files
;
507 UINT file_count
= 0, len
, i
;
509 HRESULT hr
, ret
= E_FAIL
;
511 len
= get_file_name(This
, &tmp_files
);
515 file_count
= COMDLG32_SplitFileNames(tmp_files
, len
, &files
, &size_used
);
516 CoTaskMemFree(tmp_files
);
518 if(!file_count
) return E_FAIL
;
520 hr
= SHGetIDListFromObject((IUnknown
*)This
->psi_folder
, ¤t_folder
);
523 ERR("Failed to get pidl for current directory.\n");
524 HeapFree(GetProcessHeap(), 0, files
);
528 TRACE("Acting on %d file(s).\n", file_count
);
530 pidla
= HeapAlloc(GetProcessHeap(), 0, sizeof(LPITEMIDLIST
) * file_count
);
531 open_action
= ONOPEN_OPEN
;
534 for(i
= 0; i
< file_count
&& open_action
== ONOPEN_OPEN
; i
++)
536 WCHAR canon_filename
[MAX_PATH
];
539 COMDLG32_GetCanonicalPath(current_folder
, fn_iter
, canon_filename
);
541 if( (This
->options
& FOS_NOVALIDATE
) &&
542 !(This
->options
& FOS_FILEMUSTEXIST
) )
543 open_action
= ONOPEN_OPEN
;
545 open_action
= ONOPEN_BROWSE
;
547 open_action
= FILEDLG95_ValidatePathAction(canon_filename
, &psf_parent
, This
->dlg_hwnd
,
548 This
->options
& ~FOS_FILEMUSTEXIST
,
549 (This
->dlg_type
== ITEMDLG_TYPE_SAVE
),
552 /* Add the proper extension */
553 if(open_action
== ONOPEN_OPEN
)
555 if(This
->dlg_type
== ITEMDLG_TYPE_SAVE
)
557 WCHAR extbuf
[MAX_PATH
], *newext
= NULL
;
559 if(This
->filterspec_count
)
561 newext
= get_first_ext_from_spec(extbuf
, This
->filterspecs
[This
->filetypeindex
].pszSpec
);
563 else if(This
->default_ext
)
565 lstrcpyW(extbuf
, L
".");
566 lstrcatW(extbuf
, This
->default_ext
);
572 WCHAR
*ext
= PathFindExtensionW(canon_filename
);
573 if(lstrcmpW(ext
, newext
))
574 lstrcatW(canon_filename
, newext
);
579 if( !(This
->options
& FOS_NOVALIDATE
) && (This
->options
& FOS_FILEMUSTEXIST
) &&
580 !PathFileExistsW(canon_filename
))
582 if(This
->default_ext
)
584 lstrcatW(canon_filename
, L
".");
585 lstrcatW(canon_filename
, This
->default_ext
);
587 if(!PathFileExistsW(canon_filename
))
589 FILEDLG95_OnOpenMessage(This
->dlg_hwnd
, 0, IDS_FILENOTEXISTING
);
590 open_action
= ONOPEN_BROWSE
;
595 FILEDLG95_OnOpenMessage(This
->dlg_hwnd
, 0, IDS_FILENOTEXISTING
);
596 open_action
= ONOPEN_BROWSE
;
602 pidla
[i
] = COMDLG32_SHSimpleIDListFromPathAW(canon_filename
);
604 if(psf_parent
&& !(open_action
== ONOPEN_BROWSE
))
605 IShellFolder_Release(psf_parent
);
607 fn_iter
+= (WCHAR
)lstrlenW(fn_iter
) + 1;
610 HeapFree(GetProcessHeap(), 0, files
);
611 ILFree(current_folder
);
613 if((This
->options
& FOS_PICKFOLDERS
) && open_action
== ONOPEN_BROWSE
)
614 open_action
= ONOPEN_OPEN
; /* FIXME: Multiple folders? */
619 FIXME("Filtering not implemented.\n");
623 hr
= IExplorerBrowser_BrowseToObject(This
->peb
, (IUnknown
*)psf_parent
, SBSP_DEFBROWSER
);
625 ERR("Failed to browse to directory: %08lx\n", hr
);
627 IShellFolder_Release(psf_parent
);
631 hr
= SHGetDesktopFolder(&psf_desktop
);
634 if(This
->psia_results
)
636 IShellItemArray_Release(This
->psia_results
);
637 This
->psia_results
= NULL
;
640 hr
= SHCreateShellItemArray(NULL
, psf_desktop
, file_count
, (PCUITEMID_CHILD_ARRAY
)pidla
,
641 &This
->psia_results
);
643 IShellFolder_Release(psf_desktop
);
648 if(This
->options
& FOS_PICKFOLDERS
)
651 hr
= IShellItemArray_GetAttributes(This
->psia_results
, SIATTRIBFLAGS_AND
, SFGAO_FOLDER
, &attributes
);
655 LoadStringW(COMDLG32_hInstance
, IDS_INVALID_FOLDERNAME
, buf
, ARRAY_SIZE(buf
));
657 MessageBoxW(This
->dlg_hwnd
, buf
, This
->custom_title
, MB_OK
| MB_ICONEXCLAMATION
);
659 IShellItemArray_Release(This
->psia_results
);
660 This
->psia_results
= NULL
;
665 if((This
->options
& FOS_OVERWRITEPROMPT
) && This
->dlg_type
== ITEMDLG_TYPE_SAVE
)
667 IShellItem
*shellitem
;
669 for (i
=0; SUCCEEDED(hr
) && i
<file_count
; i
++)
671 hr
= IShellItemArray_GetItemAt(This
->psia_results
, i
, &shellitem
);
674 if (shell_item_exists(shellitem
))
675 hr
= events_OnOverwrite(This
, shellitem
);
677 IShellItem_Release(shellitem
);
685 if(events_OnFileOk(This
) == S_OK
)
696 for(i
= 0; i
< file_count
; i
++)
698 HeapFree(GetProcessHeap(), 0, pidla
);
700 /* Success closes the dialog */
704 static void show_opendropdown(FileDialogImpl
*This
)
710 open_hwnd
= GetDlgItem(This
->dlg_hwnd
, IDOK
);
712 GetWindowRect(open_hwnd
, &open_rc
);
714 if (TrackPopupMenu(This
->hmenu_opendropdown
, 0, open_rc
.left
, open_rc
.bottom
, 0, This
->dlg_hwnd
, NULL
) &&
715 PeekMessageW(&msg
, This
->dlg_hwnd
, WM_MENUCOMMAND
, WM_MENUCOMMAND
, PM_REMOVE
))
719 This
->opendropdown_has_selection
= TRUE
;
721 mii
.cbSize
= sizeof(mii
);
723 GetMenuItemInfoW((HMENU
)msg
.lParam
, msg
.wParam
, TRUE
, &mii
);
724 This
->opendropdown_selection
= mii
.wID
;
726 if(SUCCEEDED(on_default_action(This
)))
727 EndDialog(This
->dlg_hwnd
, S_OK
);
729 This
->opendropdown_has_selection
= FALSE
;
733 /**************************************************************************
734 * Control item functions.
737 static void item_free(cctrl_item
*item
)
739 DestroyWindow(item
->hwnd
);
740 HeapFree(GetProcessHeap(), 0, item
->label
);
741 HeapFree(GetProcessHeap(), 0, item
);
744 static cctrl_item
* get_item(customctrl
* parent
, DWORD itemid
, CDCONTROLSTATEF visible_flags
, DWORD
* position
)
749 if (!position
) position
= &dummy
;
753 LIST_FOR_EACH_ENTRY(item
, &parent
->sub_items
, cctrl_item
, entry
)
755 if (item
->id
== itemid
)
758 if ((item
->cdcstate
& visible_flags
) == visible_flags
)
765 static cctrl_item
* get_first_item(customctrl
* parent
)
769 LIST_FOR_EACH_ENTRY(item
, &parent
->sub_items
, cctrl_item
, entry
)
771 if ((item
->cdcstate
& (CDCS_VISIBLE
|CDCS_ENABLED
)) == (CDCS_VISIBLE
|CDCS_ENABLED
))
778 static HRESULT
add_item(customctrl
* parent
, DWORD itemid
, LPCWSTR label
, cctrl_item
** result
)
783 if (get_item(parent
, itemid
, 0, NULL
))
786 item
= HeapAlloc(GetProcessHeap(), 0, sizeof(*item
));
787 label_copy
= HeapAlloc(GetProcessHeap(), 0, (lstrlenW(label
)+1)*sizeof(WCHAR
));
789 if (!item
|| !label_copy
)
791 HeapFree(GetProcessHeap(), 0, item
);
792 HeapFree(GetProcessHeap(), 0, label_copy
);
793 return E_OUTOFMEMORY
;
797 item
->parent_id
= parent
->id
;
798 lstrcpyW(label_copy
, label
);
799 item
->label
= label_copy
;
800 item
->cdcstate
= CDCS_VISIBLE
|CDCS_ENABLED
;
802 list_add_tail(&parent
->sub_items
, &item
->entry
);
809 /**************************************************************************
812 static inline customctrl
*get_cctrl_from_dlgid(FileDialogImpl
*This
, DWORD dlgid
)
814 customctrl
*ctrl
, *sub_ctrl
;
816 LIST_FOR_EACH_ENTRY(ctrl
, &This
->cctrls
, customctrl
, entry
)
818 if(ctrl
->dlgid
== dlgid
)
821 LIST_FOR_EACH_ENTRY(sub_ctrl
, &ctrl
->sub_cctrls
, customctrl
, sub_cctrls_entry
)
822 if(sub_ctrl
->dlgid
== dlgid
)
826 ERR("Failed to find control with dialog id %ld\n", dlgid
);
830 static inline customctrl
*get_cctrl(FileDialogImpl
*This
, DWORD ctlid
)
832 customctrl
*ctrl
, *sub_ctrl
;
834 LIST_FOR_EACH_ENTRY(ctrl
, &This
->cctrls
, customctrl
, entry
)
836 if(ctrl
->id
== ctlid
)
839 LIST_FOR_EACH_ENTRY(sub_ctrl
, &ctrl
->sub_cctrls
, customctrl
, sub_cctrls_entry
)
840 if(sub_ctrl
->id
== ctlid
)
844 if (This
->hmenu_opendropdown
&& This
->cctrl_opendropdown
.id
== ctlid
)
845 return &This
->cctrl_opendropdown
;
847 TRACE("No existing control with control id %ld\n", ctlid
);
851 static void ctrl_resize(HWND hctrl
, UINT min_width
, UINT max_width
, BOOL multiline
)
854 UINT len
, final_width
;
855 UINT lines
, final_height
;
864 len
= SendMessageW(hctrl
, WM_GETTEXTLENGTH
, 0, 0);
865 text
= HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR
)*(len
+1));
867 SendMessageW(hctrl
, WM_GETTEXT
, len
+1, (LPARAM
)text
);
870 font
= (HFONT
)SendMessageW(hctrl
, WM_GETFONT
, 0, 0);
871 font
= SelectObject(hdc
, font
);
872 GetTextExtentPoint32W(hdc
, text
, lstrlenW(text
), &size
);
873 SelectObject(hdc
, font
);
874 ReleaseDC(hctrl
, hdc
);
878 /* FIXME: line-wrap */
879 for(lines
= 1, c
= text
; *c
!= '\0'; c
++)
880 if(*c
== '\n') lines
++;
882 final_height
= size
.cy
*lines
+ 2*4;
886 GetWindowRect(hctrl
, &rc
);
887 final_height
= rc
.bottom
- rc
.top
;
890 final_width
= min(max(size
.cx
, min_width
) + 4, max_width
);
891 SetWindowPos(hctrl
, NULL
, 0, 0, final_width
, final_height
,
892 SWP_NOZORDER
| SWP_NOMOVE
| SWP_NOACTIVATE
);
894 HeapFree(GetProcessHeap(), 0, text
);
897 static UINT
ctrl_get_height(customctrl
*ctrl
) {
899 GetWindowRect(ctrl
->wrapper_hwnd
, &rc
);
900 return rc
.bottom
- rc
.top
;
903 static void ctrl_free(customctrl
*ctrl
)
905 customctrl
*sub_cur1
, *sub_cur2
;
906 cctrl_item
*item_cur1
, *item_cur2
;
908 TRACE("Freeing control %p\n", ctrl
);
909 if(ctrl
->type
== IDLG_CCTRL_MENU
)
912 SendMessageW(ctrl
->hwnd
, TB_GETBUTTON
, 0, (LPARAM
)&tbb
);
913 DestroyMenu((HMENU
)tbb
.dwData
);
916 LIST_FOR_EACH_ENTRY_SAFE(sub_cur1
, sub_cur2
, &ctrl
->sub_cctrls
, customctrl
, sub_cctrls_entry
)
918 list_remove(&sub_cur1
->sub_cctrls_entry
);
922 LIST_FOR_EACH_ENTRY_SAFE(item_cur1
, item_cur2
, &ctrl
->sub_items
, cctrl_item
, entry
)
924 list_remove(&item_cur1
->entry
);
925 item_free(item_cur1
);
928 DestroyWindow(ctrl
->hwnd
);
929 HeapFree(GetProcessHeap(), 0, ctrl
);
932 static void customctrl_resize(FileDialogImpl
*This
, customctrl
*ctrl
)
936 UINT max_width
, size
;
937 customctrl
*sub_ctrl
;
941 case IDLG_CCTRL_PUSHBUTTON
:
942 case IDLG_CCTRL_COMBOBOX
:
943 case IDLG_CCTRL_CHECKBUTTON
:
944 case IDLG_CCTRL_TEXT
:
945 size
= MulDiv(160, This
->dpi_x
, USER_DEFAULT_SCREEN_DPI
);
946 ctrl_resize(ctrl
->hwnd
, size
, size
, TRUE
);
947 GetWindowRect(ctrl
->hwnd
, &rc
);
948 SetWindowPos(ctrl
->wrapper_hwnd
, NULL
, 0, 0, rc
.right
-rc
.left
, rc
.bottom
-rc
.top
,
949 SWP_NOZORDER
|SWP_NOMOVE
);
951 case IDLG_CCTRL_VISUALGROUP
:
953 ctrl_resize(ctrl
->hwnd
, 0, This
->cctrl_indent
, TRUE
);
955 LIST_FOR_EACH_ENTRY(sub_ctrl
, &ctrl
->sub_cctrls
, customctrl
, sub_cctrls_entry
)
957 customctrl_resize(This
, sub_ctrl
);
958 SetWindowPos(sub_ctrl
->wrapper_hwnd
, NULL
, This
->cctrl_indent
, total_height
, 0, 0,
959 SWP_NOZORDER
|SWP_NOSIZE
);
961 total_height
+= ctrl_get_height(sub_ctrl
);
964 /* The label should be right adjusted */
968 GetWindowRect(ctrl
->hwnd
, &rc
);
969 width
= rc
.right
- rc
.left
;
970 height
= rc
.bottom
- rc
.top
;
972 SetWindowPos(ctrl
->hwnd
, NULL
, This
->cctrl_indent
- width
, 0, width
, height
, SWP_NOZORDER
);
975 /* Resize the wrapper window to fit all the sub controls */
976 SetWindowPos(ctrl
->wrapper_hwnd
, NULL
, 0, 0, This
->cctrl_width
+ This
->cctrl_indent
, total_height
,
977 SWP_NOZORDER
|SWP_NOMOVE
);
979 case IDLG_CCTRL_RADIOBUTTONLIST
:
986 LIST_FOR_EACH_ENTRY(item
, &ctrl
->sub_items
, cctrl_item
, entry
)
988 size
= MulDiv(160, This
->dpi_x
, USER_DEFAULT_SCREEN_DPI
);
989 ctrl_resize(item
->hwnd
, size
, size
, TRUE
);
990 SetWindowPos(item
->hwnd
, NULL
, 0, total_height
, 0, 0,
991 SWP_NOZORDER
|SWP_NOSIZE
);
993 GetWindowRect(item
->hwnd
, &rc
);
995 total_height
+= rc
.bottom
- rc
.top
;
996 max_width
= max(rc
.right
- rc
.left
, max_width
);
999 SetWindowPos(ctrl
->hwnd
, NULL
, 0, 0, max_width
, total_height
,
1000 SWP_NOZORDER
|SWP_NOMOVE
);
1002 SetWindowPos(ctrl
->wrapper_hwnd
, NULL
, 0, 0, max_width
, total_height
,
1003 SWP_NOZORDER
|SWP_NOMOVE
);
1007 case IDLG_CCTRL_EDITBOX
:
1008 case IDLG_CCTRL_SEPARATOR
:
1009 case IDLG_CCTRL_MENU
:
1010 case IDLG_CCTRL_OPENDROPDOWN
:
1016 static LRESULT
notifysink_on_create(HWND hwnd
, CREATESTRUCTW
*crs
)
1018 FileDialogImpl
*This
= crs
->lpCreateParams
;
1019 TRACE("%p\n", This
);
1021 SetWindowLongPtrW(hwnd
, GWLP_USERDATA
, (LPARAM
)This
);
1025 static LRESULT
notifysink_on_bn_clicked(FileDialogImpl
*This
, HWND hwnd
, WPARAM wparam
)
1027 customctrl
*ctrl
= get_cctrl_from_dlgid(This
, LOWORD(wparam
));
1029 TRACE("%p, %Ix\n", This
, wparam
);
1033 if(ctrl
->type
== IDLG_CCTRL_CHECKBUTTON
)
1035 BOOL checked
= (SendMessageW(ctrl
->hwnd
, BM_GETCHECK
, 0, 0) == BST_CHECKED
);
1036 cctrl_event_OnCheckButtonToggled(This
, ctrl
->id
, checked
);
1039 cctrl_event_OnButtonClicked(This
, ctrl
->id
);
1045 static LRESULT
notifysink_on_cbn_selchange(FileDialogImpl
*This
, HWND hwnd
, WPARAM wparam
)
1047 customctrl
*ctrl
= get_cctrl_from_dlgid(This
, LOWORD(wparam
));
1048 TRACE("%p, %p (%Ix)\n", This
, ctrl
, wparam
);
1052 UINT index
= SendMessageW(ctrl
->hwnd
, CB_GETCURSEL
, 0, 0);
1053 UINT selid
= SendMessageW(ctrl
->hwnd
, CB_GETITEMDATA
, index
, 0);
1055 cctrl_event_OnItemSelected(This
, ctrl
->id
, selid
);
1060 static LRESULT
notifysink_on_tvn_dropdown(FileDialogImpl
*This
, LPARAM lparam
)
1062 NMTOOLBARW
*nmtb
= (NMTOOLBARW
*)lparam
;
1063 customctrl
*ctrl
= get_cctrl_from_dlgid(This
, GetDlgCtrlID(nmtb
->hdr
.hwndFrom
));
1064 POINT pt
= { 0, nmtb
->rcButton
.bottom
};
1068 TRACE("%p, %p (%Ix)\n", This
, ctrl
, lparam
);
1072 cctrl_event_OnControlActivating(This
,ctrl
->id
);
1074 SendMessageW(ctrl
->hwnd
, TB_GETBUTTON
, 0, (LPARAM
)&tbb
);
1075 ClientToScreen(ctrl
->hwnd
, &pt
);
1076 idcmd
= TrackPopupMenu((HMENU
)tbb
.dwData
, TPM_RETURNCMD
, pt
.x
, pt
.y
, 0, This
->dlg_hwnd
, NULL
);
1078 cctrl_event_OnItemSelected(This
, ctrl
->id
, idcmd
);
1081 return TBDDRET_DEFAULT
;
1084 static LRESULT
notifysink_on_wm_command(FileDialogImpl
*This
, HWND hwnd
, WPARAM wparam
, LPARAM lparam
)
1086 switch(HIWORD(wparam
))
1088 case BN_CLICKED
: return notifysink_on_bn_clicked(This
, hwnd
, wparam
);
1089 case CBN_SELCHANGE
: return notifysink_on_cbn_selchange(This
, hwnd
, wparam
);
1095 static LRESULT
notifysink_on_wm_notify(FileDialogImpl
*This
, HWND hwnd
, WPARAM wparam
, LPARAM lparam
)
1097 NMHDR
*nmhdr
= (NMHDR
*)lparam
;
1101 case TBN_DROPDOWN
: return notifysink_on_tvn_dropdown(This
, lparam
);
1107 static LRESULT CALLBACK
notifysink_proc(HWND hwnd
, UINT message
, WPARAM wparam
, LPARAM lparam
)
1109 FileDialogImpl
*This
= (FileDialogImpl
*)GetWindowLongPtrW(hwnd
, GWLP_USERDATA
);
1116 case WM_NCCREATE
: return notifysink_on_create(hwnd
, (CREATESTRUCTW
*)lparam
);
1117 case WM_COMMAND
: return notifysink_on_wm_command(This
, hwnd
, wparam
, lparam
);
1118 case WM_NOTIFY
: return notifysink_on_wm_notify(This
, hwnd
, wparam
, lparam
);
1120 hwnd_child
= GetPropW(hwnd
, L
"nfs_child");
1121 ctrl
= (customctrl
*)GetWindowLongPtrW(hwnd_child
, GWLP_USERDATA
);
1122 if(ctrl
&& ctrl
->type
!= IDLG_CCTRL_VISUALGROUP
)
1124 GetClientRect(hwnd
, &rc
);
1125 SetWindowPos(hwnd_child
, NULL
, 0, 0, rc
.right
, rc
.bottom
, SWP_NOMOVE
|SWP_NOACTIVATE
|SWP_NOZORDER
);
1130 return DefWindowProcW(hwnd
, message
, wparam
, lparam
);
1133 static HRESULT
cctrl_create_new(FileDialogImpl
*This
, DWORD id
,
1134 LPCWSTR text
, LPCWSTR wndclass
, DWORD ctrl_wsflags
,
1135 DWORD ctrl_exflags
, UINT height
, customctrl
**ppctrl
)
1137 HWND ns_hwnd
, control_hwnd
, parent_hwnd
;
1138 DWORD wsflags
= WS_CHILD
| WS_VISIBLE
| WS_CLIPSIBLINGS
;
1141 if(get_cctrl(This
, id
))
1142 return E_UNEXPECTED
; /* Duplicate id */
1144 if(This
->cctrl_active_vg
)
1145 parent_hwnd
= This
->cctrl_active_vg
->wrapper_hwnd
;
1147 parent_hwnd
= This
->cctrls_hwnd
;
1149 ns_hwnd
= CreateWindowExW(0, L
"FloatNotifySink", NULL
, wsflags
,
1150 0, 0, This
->cctrl_width
, height
, parent_hwnd
,
1151 (HMENU
)This
->cctrl_next_dlgid
, COMDLG32_hInstance
, This
);
1152 control_hwnd
= CreateWindowExW(ctrl_exflags
, wndclass
, text
, wsflags
| ctrl_wsflags
,
1153 0, 0, This
->cctrl_width
, height
, ns_hwnd
,
1154 (HMENU
)This
->cctrl_next_dlgid
, COMDLG32_hInstance
, 0);
1156 if(!ns_hwnd
|| !control_hwnd
)
1158 ERR("Failed to create wrapper (%p) or control (%p)\n", ns_hwnd
, control_hwnd
);
1159 DestroyWindow(ns_hwnd
);
1160 DestroyWindow(control_hwnd
);
1165 SetPropW(ns_hwnd
, L
"nfs_child", control_hwnd
);
1167 ctrl
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(customctrl
));
1169 return E_OUTOFMEMORY
;
1171 ctrl
->hwnd
= control_hwnd
;
1172 ctrl
->wrapper_hwnd
= ns_hwnd
;
1174 ctrl
->dlgid
= This
->cctrl_next_dlgid
;
1175 ctrl
->cdcstate
= CDCS_ENABLED
| CDCS_VISIBLE
;
1176 list_init(&ctrl
->sub_cctrls
);
1177 list_init(&ctrl
->sub_items
);
1179 if(This
->cctrl_active_vg
)
1180 list_add_tail(&This
->cctrl_active_vg
->sub_cctrls
, &ctrl
->sub_cctrls_entry
);
1182 list_add_tail(&This
->cctrls
, &ctrl
->entry
);
1184 SetWindowLongPtrW(ctrl
->hwnd
, GWLP_USERDATA
, (LPARAM
)ctrl
);
1186 if(ppctrl
) *ppctrl
= ctrl
;
1188 This
->cctrl_next_dlgid
++;
1192 /**************************************************************************
1193 * Container functions.
1195 static UINT
ctrl_container_resize(FileDialogImpl
*This
, UINT container_width
)
1197 UINT container_height
;
1200 UINT max_control_height
, total_height
= 0;
1201 UINT cur_col_pos
, cur_row_pos
;
1204 UINT cspacing
= MulDiv(90, This
->dpi_x
, USER_DEFAULT_SCREEN_DPI
); /* Columns are spaced with 90px */
1205 UINT rspacing
= MulDiv(4, This
->dpi_y
, USER_DEFAULT_SCREEN_DPI
); /* Rows are spaced with 4 px. */
1207 /* Given the new width of the container, this function determines the
1208 * needed height of the container and places the controls according to
1209 * the new layout. Returns the new height.
1212 TRACE("%p\n", This
);
1214 column_width
= This
->cctrl_width
+ cspacing
;
1215 nr_of_cols
= (container_width
- This
->cctrl_indent
+ cspacing
) / column_width
;
1217 /* We don't need to do anything unless the number of visible columns has changed. */
1218 if(nr_of_cols
== This
->cctrls_cols
)
1221 GetWindowRect(This
->cctrls_hwnd
, &rc
);
1222 return rc
.bottom
- rc
.top
;
1225 This
->cctrls_cols
= nr_of_cols
;
1227 /* Get the size of the tallest control, and the total size of
1228 * all the controls to figure out the number of slots we need.
1230 max_control_height
= 0;
1231 LIST_FOR_EACH_ENTRY(ctrl
, &This
->cctrls
, customctrl
, entry
)
1233 if(ctrl
->cdcstate
& CDCS_VISIBLE
)
1235 UINT control_height
= ctrl_get_height(ctrl
);
1236 max_control_height
= max(max_control_height
, control_height
);
1238 total_height
+= control_height
+ rspacing
;
1245 container_height
= max(total_height
/ nr_of_cols
, max_control_height
+ rspacing
);
1246 TRACE("Guess: container_height: %d\n",container_height
);
1248 /* Incrementally increase container_height until all the controls
1252 UINT columns_needed
= 1;
1256 LIST_FOR_EACH_ENTRY(ctrl
, &This
->cctrls
, customctrl
, entry
)
1258 if(ctrl
->cdcstate
& CDCS_VISIBLE
)
1260 UINT control_height
= ctrl_get_height(ctrl
);
1262 if(cur_row_pos
+ control_height
> container_height
)
1264 if(++columns_needed
> nr_of_cols
)
1266 container_height
+= 1;
1267 fits_height
= FALSE
;
1273 cur_row_pos
+= control_height
+ rspacing
;
1276 } while(!fits_height
);
1278 TRACE("Final container height: %d\n", container_height
);
1280 /* Move the controls to their final destination
1282 cur_col_pos
= 0; cur_row_pos
= 0;
1283 LIST_FOR_EACH_ENTRY(ctrl
, &This
->cctrls
, customctrl
, entry
)
1285 if(ctrl
->cdcstate
& CDCS_VISIBLE
)
1288 UINT control_height
, control_indent
;
1289 GetWindowRect(ctrl
->wrapper_hwnd
, &rc
);
1290 control_height
= rc
.bottom
- rc
.top
;
1292 if(cur_row_pos
+ control_height
> container_height
)
1295 cur_col_pos
+= This
->cctrl_width
+ cspacing
;
1299 if(ctrl
->type
== IDLG_CCTRL_VISUALGROUP
)
1302 control_indent
= This
->cctrl_indent
;
1304 SetWindowPos(ctrl
->wrapper_hwnd
, NULL
, cur_col_pos
+ control_indent
, cur_row_pos
, 0, 0,
1305 SWP_NOACTIVATE
| SWP_NOSIZE
| SWP_NOZORDER
);
1307 cur_row_pos
+= control_height
+ rspacing
;
1312 if(cur_row_pos
+ This
->cctrl_width
> container_width
)
1313 ERR("-- Failed to place controls properly.\n");
1315 return container_height
;
1318 static void ctrl_set_font(customctrl
*ctrl
, HFONT font
)
1320 customctrl
*sub_ctrl
;
1323 SendMessageW(ctrl
->hwnd
, WM_SETFONT
, (WPARAM
)font
, TRUE
);
1325 LIST_FOR_EACH_ENTRY(sub_ctrl
, &ctrl
->sub_cctrls
, customctrl
, sub_cctrls_entry
)
1327 ctrl_set_font(sub_ctrl
, font
);
1330 if (ctrl
->type
== IDLG_CCTRL_RADIOBUTTONLIST
)
1332 LIST_FOR_EACH_ENTRY(item
, &ctrl
->sub_items
, cctrl_item
, entry
)
1334 SendMessageW(item
->hwnd
, WM_SETFONT
, (WPARAM
)font
, TRUE
);
1339 static void ctrl_container_reparent(FileDialogImpl
*This
, HWND parent
)
1348 wndstyle
= GetWindowLongW(This
->cctrls_hwnd
, GWL_STYLE
);
1349 wndstyle
&= ~(WS_POPUP
);
1350 wndstyle
|= WS_CHILD
;
1351 SetWindowLongW(This
->cctrls_hwnd
, GWL_STYLE
, wndstyle
);
1353 SetParent(This
->cctrls_hwnd
, parent
);
1354 ShowWindow(This
->cctrls_hwnd
, TRUE
);
1356 /* Set the fonts to match the dialog font. */
1357 font
= (HFONT
)SendMessageW(parent
, WM_GETFONT
, 0, 0);
1359 ERR("Failed to get font handle from dialog.\n");
1361 LIST_FOR_EACH_ENTRY(ctrl
, &This
->cctrls
, customctrl
, entry
)
1363 if(font
) ctrl_set_font(ctrl
, font
);
1364 customctrl_resize(This
, ctrl
);
1369 ShowWindow(This
->cctrls_hwnd
, FALSE
);
1371 wndstyle
= GetWindowLongW(This
->cctrls_hwnd
, GWL_STYLE
);
1372 wndstyle
&= ~(WS_CHILD
);
1373 wndstyle
|= WS_POPUP
;
1374 SetWindowLongW(This
->cctrls_hwnd
, GWL_STYLE
, wndstyle
);
1376 SetParent(This
->cctrls_hwnd
, NULL
);
1380 static LRESULT
ctrl_container_on_create(HWND hwnd
, CREATESTRUCTW
*crs
)
1382 FileDialogImpl
*This
= crs
->lpCreateParams
;
1383 TRACE("%p\n", This
);
1385 SetWindowLongPtrW(hwnd
, GWLP_USERDATA
, (LPARAM
)This
);
1389 static LRESULT
ctrl_container_on_wm_destroy(FileDialogImpl
*This
)
1391 customctrl
*cur1
, *cur2
;
1392 TRACE("%p\n", This
);
1394 LIST_FOR_EACH_ENTRY_SAFE(cur1
, cur2
, &This
->cctrls
, customctrl
, entry
)
1396 list_remove(&cur1
->entry
);
1403 static LRESULT CALLBACK
ctrl_container_wndproc(HWND hwnd
, UINT umessage
, WPARAM wparam
, LPARAM lparam
)
1405 FileDialogImpl
*This
= (FileDialogImpl
*)GetWindowLongPtrW(hwnd
, GWLP_USERDATA
);
1409 case WM_NCCREATE
: return ctrl_container_on_create(hwnd
, (CREATESTRUCTW
*)lparam
);
1410 case WM_DESTROY
: return ctrl_container_on_wm_destroy(This
);
1411 default: return DefWindowProcW(hwnd
, umessage
, wparam
, lparam
);
1417 static void radiobuttonlist_set_selected_item(FileDialogImpl
*This
, customctrl
*ctrl
, cctrl_item
*item
)
1421 LIST_FOR_EACH_ENTRY(cursor
, &ctrl
->sub_items
, cctrl_item
, entry
)
1423 SendMessageW(cursor
->hwnd
, BM_SETCHECK
, (cursor
== item
) ? BST_CHECKED
: BST_UNCHECKED
, 0);
1427 static LRESULT
radiobuttonlist_on_bn_clicked(FileDialogImpl
*This
, HWND hwnd
, HWND child
)
1429 DWORD ctrl_id
= (DWORD
)GetWindowLongPtrW(hwnd
, GWLP_ID
);
1432 BOOL found_item
=FALSE
;
1434 ctrl
= get_cctrl_from_dlgid(This
, ctrl_id
);
1438 ERR("Can't find this control\n");
1442 LIST_FOR_EACH_ENTRY(item
, &ctrl
->sub_items
, cctrl_item
, entry
)
1444 if (item
->hwnd
== child
)
1453 ERR("Can't find control item\n");
1457 radiobuttonlist_set_selected_item(This
, ctrl
, item
);
1459 cctrl_event_OnItemSelected(This
, ctrl
->id
, item
->id
);
1464 static LRESULT
radiobuttonlist_on_wm_command(FileDialogImpl
*This
, HWND hwnd
, WPARAM wparam
, LPARAM lparam
)
1466 switch(HIWORD(wparam
))
1468 case BN_CLICKED
: return radiobuttonlist_on_bn_clicked(This
, hwnd
, (HWND
)lparam
);
1474 static LRESULT CALLBACK
radiobuttonlist_proc(HWND hwnd
, UINT message
, WPARAM wparam
, LPARAM lparam
)
1476 FileDialogImpl
*This
= (FileDialogImpl
*)GetWindowLongPtrW(hwnd
, GWLP_USERDATA
);
1480 case WM_COMMAND
: return radiobuttonlist_on_wm_command(This
, hwnd
, wparam
, lparam
);
1483 return DefWindowProcW(hwnd
, message
, wparam
, lparam
);
1486 static HRESULT
init_custom_controls(FileDialogImpl
*This
)
1490 static const WCHAR ctrl_container_classname
[] = L
"idlg_container_pane";
1492 InitCommonControlsEx(NULL
);
1494 if( !GetClassInfoW(COMDLG32_hInstance
, ctrl_container_classname
, &wc
) )
1496 wc
.style
= CS_HREDRAW
| CS_VREDRAW
;
1497 wc
.lpfnWndProc
= ctrl_container_wndproc
;
1500 wc
.hInstance
= COMDLG32_hInstance
;
1502 wc
.hCursor
= LoadCursorW(0, (LPWSTR
)IDC_ARROW
);
1503 wc
.hbrBackground
= (HBRUSH
)(COLOR_BTNFACE
+ 1);
1504 wc
.lpszMenuName
= NULL
;
1505 wc
.lpszClassName
= ctrl_container_classname
;
1507 if(!RegisterClassW(&wc
)) return E_FAIL
;
1510 This
->cctrls_hwnd
= CreateWindowExW(0, ctrl_container_classname
, NULL
,
1511 WS_CLIPSIBLINGS
| WS_CLIPCHILDREN
,
1512 0, 0, 0, 0, NULL
, 0,
1513 COMDLG32_hInstance
, This
);
1514 if(!This
->cctrls_hwnd
)
1517 hdc
= GetDC(This
->cctrls_hwnd
);
1518 This
->dpi_x
= GetDeviceCaps(hdc
, LOGPIXELSX
);
1519 This
->dpi_y
= GetDeviceCaps(hdc
, LOGPIXELSY
);
1520 ReleaseDC(This
->cctrls_hwnd
, hdc
);
1522 This
->cctrl_width
= MulDiv(160, This
->dpi_x
, USER_DEFAULT_SCREEN_DPI
); /* Controls have a fixed width */
1523 This
->cctrl_indent
= MulDiv(100, This
->dpi_x
, USER_DEFAULT_SCREEN_DPI
);
1524 This
->cctrl_def_height
= MulDiv(23, This
->dpi_y
, USER_DEFAULT_SCREEN_DPI
);
1525 This
->cctrls_cols
= 0;
1527 This
->cctrl_next_dlgid
= 0x2000;
1528 list_init(&This
->cctrls
);
1529 This
->cctrl_active_vg
= NULL
;
1531 SetWindowLongW(This
->cctrls_hwnd
, GWL_STYLE
, WS_TABSTOP
);
1533 /* Register class for */
1534 if (!GetClassInfoW(COMDLG32_hInstance
, L
"FloatNotifySink", &wc
) ||
1535 wc
.hInstance
!= COMDLG32_hInstance
)
1537 wc
.style
= CS_HREDRAW
| CS_VREDRAW
;
1538 wc
.lpfnWndProc
= notifysink_proc
;
1541 wc
.hInstance
= COMDLG32_hInstance
;
1543 wc
.hCursor
= LoadCursorW(0, (LPWSTR
)IDC_ARROW
);
1544 wc
.hbrBackground
= (HBRUSH
)(COLOR_BTNFACE
+ 1);
1545 wc
.lpszMenuName
= NULL
;
1546 wc
.lpszClassName
= L
"FloatNotifySink";
1548 if (!RegisterClassW(&wc
))
1549 ERR("Failed to register FloatNotifySink window class.\n");
1552 if (!GetClassInfoW(COMDLG32_hInstance
, L
"RadioButtonList", &wc
) ||
1553 wc
.hInstance
!= COMDLG32_hInstance
)
1555 wc
.style
= CS_HREDRAW
| CS_VREDRAW
;
1556 wc
.lpfnWndProc
= radiobuttonlist_proc
;
1559 wc
.hInstance
= COMDLG32_hInstance
;
1561 wc
.hCursor
= LoadCursorW(0, (LPWSTR
)IDC_ARROW
);
1562 wc
.hbrBackground
= (HBRUSH
)(COLOR_BTNFACE
+ 1);
1563 wc
.lpszMenuName
= NULL
;
1564 wc
.lpszClassName
= L
"RadioButtonList";
1566 if (!RegisterClassW(&wc
))
1567 ERR("Failed to register RadioButtonList window class.\n");
1573 /**************************************************************************
1574 * Window related functions.
1576 static BOOL
update_open_dropdown(FileDialogImpl
*This
)
1578 /* Show or hide the open dropdown button as appropriate */
1579 BOOL show
=FALSE
, showing
;
1580 HWND open_hwnd
, dropdown_hwnd
;
1582 if (This
->hmenu_opendropdown
)
1584 INT num_visible_items
=0;
1587 LIST_FOR_EACH_ENTRY(item
, &This
->cctrl_opendropdown
.sub_items
, cctrl_item
, entry
)
1589 if (item
->cdcstate
& CDCS_VISIBLE
)
1591 num_visible_items
++;
1592 if (num_visible_items
>= 2)
1601 open_hwnd
= GetDlgItem(This
->dlg_hwnd
, IDOK
);
1602 dropdown_hwnd
= GetDlgItem(This
->dlg_hwnd
, psh1
);
1604 showing
= (GetWindowLongPtrW(dropdown_hwnd
, GWL_STYLE
) & WS_VISIBLE
) != 0;
1606 if (showing
!= show
)
1608 RECT open_rc
, dropdown_rc
;
1610 GetWindowRect(open_hwnd
, &open_rc
);
1611 GetWindowRect(dropdown_hwnd
, &dropdown_rc
);
1615 ShowWindow(dropdown_hwnd
, SW_SHOW
);
1617 SetWindowPos(open_hwnd
, NULL
, 0, 0,
1618 (open_rc
.right
- open_rc
.left
) - (dropdown_rc
.right
- dropdown_rc
.left
),
1619 open_rc
.bottom
- open_rc
.top
, SWP_NOZORDER
| SWP_NOMOVE
| SWP_NOACTIVATE
);
1623 ShowWindow(dropdown_hwnd
, SW_HIDE
);
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
);
1634 static void update_layout(FileDialogImpl
*This
)
1639 RECT cancel_rc
, dropdown_rc
, open_rc
;
1640 RECT filetype_rc
, filename_rc
, filenamelabel_rc
;
1641 RECT toolbar_rc
, ebrowser_rc
, customctrls_rc
;
1642 static const UINT vspacing
= 4, hspacing
= 4;
1643 static const UINT min_width
= 320, min_height
= 200;
1646 if (!GetClientRect(This
->dlg_hwnd
, &dialog_rc
))
1648 TRACE("Invalid dialog window, not updating layout\n");
1652 if(dialog_rc
.right
< min_width
|| dialog_rc
.bottom
< min_height
)
1654 TRACE("Dialog size (%ld, %ld) too small, not updating layout\n", dialog_rc
.right
, dialog_rc
.bottom
);
1659 * Calculate the size of the dialog and all the parts.
1663 hwnd
= GetDlgItem(This
->dlg_hwnd
, IDCANCEL
);
1666 int cancel_width
, cancel_height
;
1667 GetWindowRect(hwnd
, &cancel_rc
);
1668 cancel_width
= cancel_rc
.right
- cancel_rc
.left
;
1669 cancel_height
= cancel_rc
.bottom
- cancel_rc
.top
;
1671 cancel_rc
.left
= dialog_rc
.right
- cancel_width
- hspacing
;
1672 cancel_rc
.top
= dialog_rc
.bottom
- cancel_height
- vspacing
;
1673 cancel_rc
.right
= cancel_rc
.left
+ cancel_width
;
1674 cancel_rc
.bottom
= cancel_rc
.top
+ cancel_height
;
1677 /* Open/Save dropdown */
1678 show_dropdown
= update_open_dropdown(This
);
1682 int dropdown_width
, dropdown_height
;
1683 hwnd
= GetDlgItem(This
->dlg_hwnd
, psh1
);
1685 GetWindowRect(hwnd
, &dropdown_rc
);
1686 dropdown_width
= dropdown_rc
.right
- dropdown_rc
.left
;
1687 dropdown_height
= dropdown_rc
.bottom
- dropdown_rc
.top
;
1689 dropdown_rc
.left
= cancel_rc
.left
- dropdown_width
- hspacing
;
1690 dropdown_rc
.top
= cancel_rc
.top
;
1691 dropdown_rc
.right
= dropdown_rc
.left
+ dropdown_width
;
1692 dropdown_rc
.bottom
= dropdown_rc
.top
+ dropdown_height
;
1696 dropdown_rc
.left
= dropdown_rc
.right
= cancel_rc
.left
- hspacing
;
1697 dropdown_rc
.top
= cancel_rc
.top
;
1698 dropdown_rc
.bottom
= cancel_rc
.bottom
;
1701 /* Open/Save button */
1702 hwnd
= GetDlgItem(This
->dlg_hwnd
, IDOK
);
1705 int open_width
, open_height
;
1706 GetWindowRect(hwnd
, &open_rc
);
1707 open_width
= open_rc
.right
- open_rc
.left
;
1708 open_height
= open_rc
.bottom
- open_rc
.top
;
1710 open_rc
.left
= dropdown_rc
.left
- open_width
;
1711 open_rc
.top
= dropdown_rc
.top
;
1712 open_rc
.right
= open_rc
.left
+ open_width
;
1713 open_rc
.bottom
= open_rc
.top
+ open_height
;
1716 /* The filetype combobox. */
1717 hwnd
= GetDlgItem(This
->dlg_hwnd
, IDC_FILETYPE
);
1720 int filetype_width
, filetype_height
;
1721 GetWindowRect(hwnd
, &filetype_rc
);
1723 filetype_width
= filetype_rc
.right
- filetype_rc
.left
;
1724 filetype_height
= filetype_rc
.bottom
- filetype_rc
.top
;
1726 filetype_rc
.right
= cancel_rc
.right
;
1728 filetype_rc
.left
= filetype_rc
.right
- filetype_width
;
1729 filetype_rc
.top
= cancel_rc
.top
- filetype_height
- vspacing
;
1730 filetype_rc
.bottom
= filetype_rc
.top
+ filetype_height
;
1732 if(!This
->filterspec_count
)
1733 filetype_rc
.left
= filetype_rc
.right
;
1736 /* Filename label. */
1737 hwnd
= GetDlgItem(This
->dlg_hwnd
, IDC_FILENAMESTATIC
);
1740 int filetypelabel_width
, filetypelabel_height
;
1741 GetWindowRect(hwnd
, &filenamelabel_rc
);
1743 filetypelabel_width
= filenamelabel_rc
.right
- filenamelabel_rc
.left
;
1744 filetypelabel_height
= filenamelabel_rc
.bottom
- filenamelabel_rc
.top
;
1746 filenamelabel_rc
.left
= 160; /* FIXME */
1747 filenamelabel_rc
.top
= filetype_rc
.top
;
1748 filenamelabel_rc
.right
= filenamelabel_rc
.left
+ filetypelabel_width
;
1749 filenamelabel_rc
.bottom
= filenamelabel_rc
.top
+ filetypelabel_height
;
1752 /* Filename edit box. */
1753 hwnd
= GetDlgItem(This
->dlg_hwnd
, IDC_FILENAME
);
1756 int filename_width
, filename_height
;
1757 GetWindowRect(hwnd
, &filename_rc
);
1759 filename_width
= filetype_rc
.left
- filenamelabel_rc
.right
- hspacing
*2;
1760 filename_height
= filename_rc
.bottom
- filename_rc
.top
;
1762 filename_rc
.left
= filenamelabel_rc
.right
+ hspacing
;
1763 filename_rc
.top
= filetype_rc
.top
;
1764 filename_rc
.right
= filename_rc
.left
+ filename_width
;
1765 filename_rc
.bottom
= filename_rc
.top
+ filename_height
;
1768 hwnd
= GetDlgItem(This
->dlg_hwnd
, IDC_NAV_TOOLBAR
);
1771 GetWindowRect(hwnd
, &toolbar_rc
);
1772 MapWindowPoints(NULL
, This
->dlg_hwnd
, (POINT
*)&toolbar_rc
, 2);
1775 /* The custom controls */
1776 customctrls_rc
.left
= dialog_rc
.left
+ hspacing
;
1777 customctrls_rc
.right
= dialog_rc
.right
- hspacing
;
1778 customctrls_rc
.bottom
= filename_rc
.top
- vspacing
;
1779 customctrls_rc
.top
= customctrls_rc
.bottom
-
1780 ctrl_container_resize(This
, customctrls_rc
.right
- customctrls_rc
.left
);
1782 /* The ExplorerBrowser control. */
1783 ebrowser_rc
.left
= dialog_rc
.left
+ hspacing
;
1784 ebrowser_rc
.top
= toolbar_rc
.bottom
+ vspacing
;
1785 ebrowser_rc
.right
= dialog_rc
.right
- hspacing
;
1786 ebrowser_rc
.bottom
= customctrls_rc
.top
- vspacing
;
1789 * Move everything to the right place.
1792 /* FIXME: The Save Dialog uses a slightly different layout. */
1793 hdwp
= BeginDeferWindowPos(7);
1795 if(hdwp
&& This
->peb
)
1796 IExplorerBrowser_SetRect(This
->peb
, &hdwp
, ebrowser_rc
);
1798 if(hdwp
&& This
->cctrls_hwnd
)
1799 DeferWindowPos(hdwp
, This
->cctrls_hwnd
, NULL
,
1800 customctrls_rc
.left
, customctrls_rc
.top
,
1801 customctrls_rc
.right
- customctrls_rc
.left
, customctrls_rc
.bottom
- customctrls_rc
.top
,
1802 SWP_NOZORDER
| SWP_NOACTIVATE
);
1804 /* The default controls */
1805 if(hdwp
&& (hwnd
= GetDlgItem(This
->dlg_hwnd
, IDC_FILETYPE
)) )
1806 DeferWindowPos(hdwp
, hwnd
, NULL
, filetype_rc
.left
, filetype_rc
.top
, 0, 0,
1807 SWP_NOZORDER
| SWP_NOSIZE
| SWP_NOACTIVATE
);
1809 if(hdwp
&& (hwnd
= GetDlgItem(This
->dlg_hwnd
, IDC_FILENAME
)) )
1810 DeferWindowPos(hdwp
, hwnd
, NULL
, filename_rc
.left
, filename_rc
.top
,
1811 filename_rc
.right
- filename_rc
.left
, filename_rc
.bottom
- filename_rc
.top
,
1812 SWP_NOZORDER
| SWP_NOACTIVATE
);
1814 if(hdwp
&& (hwnd
= GetDlgItem(This
->dlg_hwnd
, IDC_FILENAMESTATIC
)) )
1815 DeferWindowPos(hdwp
, hwnd
, NULL
, filenamelabel_rc
.left
, filenamelabel_rc
.top
, 0, 0,
1816 SWP_NOZORDER
| SWP_NOSIZE
| SWP_NOACTIVATE
);
1818 if(hdwp
&& (hwnd
= GetDlgItem(This
->dlg_hwnd
, IDOK
)) )
1819 DeferWindowPos(hdwp
, hwnd
, NULL
, open_rc
.left
, open_rc
.top
, 0, 0,
1820 SWP_NOZORDER
| SWP_NOSIZE
| SWP_NOACTIVATE
);
1822 if(hdwp
&& This
->hmenu_opendropdown
&& (hwnd
= GetDlgItem(This
->dlg_hwnd
, psh1
)))
1823 DeferWindowPos(hdwp
, hwnd
, NULL
, dropdown_rc
.left
, dropdown_rc
.top
, 0, 0,
1824 SWP_NOZORDER
| SWP_NOSIZE
| SWP_NOACTIVATE
);
1826 if(hdwp
&& (hwnd
= GetDlgItem(This
->dlg_hwnd
, IDCANCEL
)) )
1827 DeferWindowPos(hdwp
, hwnd
, NULL
, cancel_rc
.left
, cancel_rc
.top
, 0, 0,
1828 SWP_NOZORDER
| SWP_NOSIZE
| SWP_NOACTIVATE
);
1831 EndDeferWindowPos(hdwp
);
1833 ERR("Failed to position dialog controls.\n");
1838 static HRESULT
init_explorerbrowser(FileDialogImpl
*This
)
1840 IShellItem
*psi_folder
;
1841 IObjectWithSite
*client
;
1846 /* Create ExplorerBrowser instance */
1847 OleInitialize(NULL
);
1849 hr
= CoCreateInstance(&CLSID_ExplorerBrowser
, NULL
, CLSCTX_INPROC_SERVER
,
1850 &IID_IExplorerBrowser
, (void**)&This
->peb
);
1853 ERR("Failed to instantiate ExplorerBrowser control.\n");
1857 IExplorerBrowser_SetOptions(This
->peb
, EBO_SHOWFRAMES
| EBO_NOBORDER
);
1859 hr
= IExplorerBrowser_Initialize(This
->peb
, This
->dlg_hwnd
, &rc
, NULL
);
1862 ERR("Failed to initialize the ExplorerBrowser control.\n");
1863 IExplorerBrowser_Release(This
->peb
);
1867 hr
= IExplorerBrowser_Advise(This
->peb
, &This
->IExplorerBrowserEvents_iface
, &This
->ebevents_cookie
);
1869 ERR("Advise (ExplorerBrowser) failed.\n");
1871 /* Get previous options? */
1872 fos
.ViewMode
= fos
.fFlags
= 0;
1873 if(!(This
->options
& FOS_ALLOWMULTISELECT
))
1874 fos
.fFlags
|= FWF_SINGLESEL
;
1876 IExplorerBrowser_SetFolderSettings(This
->peb
, &fos
);
1878 hr
= IExplorerBrowser_QueryInterface(This
->peb
, &IID_IObjectWithSite
, (void**)&client
);
1881 hr
= IObjectWithSite_SetSite(client
, (IUnknown
*)&This
->IFileDialog2_iface
);
1882 IObjectWithSite_Release(client
);
1884 ERR("SetSite failed, 0x%08lx\n", hr
);
1887 /* Browse somewhere */
1888 psi_folder
= This
->psi_setfolder
? This
->psi_setfolder
: This
->psi_defaultfolder
;
1889 IExplorerBrowser_BrowseToObject(This
->peb
, (IUnknown
*)psi_folder
, SBSP_DEFBROWSER
);
1894 static void init_toolbar(FileDialogImpl
*This
, HWND hwnd
)
1901 htoolbar
= CreateWindowExW(0, TOOLBARCLASSNAMEW
, NULL
, TBSTYLE_FLAT
| WS_CHILD
| WS_VISIBLE
,
1903 hwnd
, (HMENU
)IDC_NAV_TOOLBAR
, NULL
, NULL
);
1905 tbab
.hInst
= HINST_COMMCTRL
;
1906 tbab
.nID
= IDB_HIST_LARGE_COLOR
;
1907 SendMessageW(htoolbar
, TB_ADDBITMAP
, 0, (LPARAM
)&tbab
);
1909 button
[0].iBitmap
= HIST_BACK
;
1910 button
[0].idCommand
= IDC_NAVBACK
;
1911 button
[0].fsState
= TBSTATE_ENABLED
;
1912 button
[0].fsStyle
= BTNS_BUTTON
;
1913 button
[0].dwData
= 0;
1914 button
[0].iString
= 0;
1916 button
[1].iBitmap
= HIST_FORWARD
;
1917 button
[1].idCommand
= IDC_NAVFORWARD
;
1918 button
[1].fsState
= TBSTATE_ENABLED
;
1919 button
[1].fsStyle
= BTNS_BUTTON
;
1920 button
[1].dwData
= 0;
1921 button
[1].iString
= 0;
1923 SendMessageW(htoolbar
, TB_ADDBUTTONSW
, 2, (LPARAM
)button
);
1924 height
= MulDiv(24, This
->dpi_y
, USER_DEFAULT_SCREEN_DPI
);
1925 SendMessageW(htoolbar
, TB_SETBUTTONSIZE
, 0, MAKELPARAM(height
, height
));
1926 SendMessageW(htoolbar
, TB_AUTOSIZE
, 0, 0);
1929 static void update_control_text(FileDialogImpl
*This
)
1932 LPCWSTR custom_okbutton
;
1934 UINT min_width
= MulDiv(50, This
->dpi_x
, USER_DEFAULT_SCREEN_DPI
);
1935 UINT max_width
= MulDiv(250, This
->dpi_x
, USER_DEFAULT_SCREEN_DPI
);
1937 if(This
->custom_title
)
1938 SetWindowTextW(This
->dlg_hwnd
, This
->custom_title
);
1940 if(This
->hmenu_opendropdown
&& (item
= get_first_item(&This
->cctrl_opendropdown
)))
1941 custom_okbutton
= item
->label
;
1943 custom_okbutton
= This
->custom_okbutton
;
1945 if(custom_okbutton
&&
1946 (hitem
= GetDlgItem(This
->dlg_hwnd
, IDOK
)))
1948 SetWindowTextW(hitem
, custom_okbutton
);
1949 ctrl_resize(hitem
, min_width
, max_width
, FALSE
);
1952 if(This
->custom_cancelbutton
&&
1953 (hitem
= GetDlgItem(This
->dlg_hwnd
, IDCANCEL
)))
1955 SetWindowTextW(hitem
, This
->custom_cancelbutton
);
1956 ctrl_resize(hitem
, min_width
, max_width
, FALSE
);
1959 if(This
->custom_filenamelabel
&&
1960 (hitem
= GetDlgItem(This
->dlg_hwnd
, IDC_FILENAMESTATIC
)))
1962 SetWindowTextW(hitem
, This
->custom_filenamelabel
);
1963 ctrl_resize(hitem
, min_width
, max_width
, FALSE
);
1967 static LRESULT CALLBACK
dropdown_subclass_proc(HWND hwnd
, UINT umessage
, WPARAM wparam
, LPARAM lparam
)
1969 if (umessage
== WM_LBUTTONDOWN
)
1971 FileDialogImpl
*This
= GetPropW(hwnd
, L
"itemdlg_This");
1973 SendMessageW(hwnd
, BM_SETCHECK
, BST_CHECKED
, 0);
1974 show_opendropdown(This
);
1975 SendMessageW(hwnd
, BM_SETCHECK
, BST_UNCHECKED
, 0);
1980 return CallWindowProcW((WNDPROC
)GetPropW(hwnd
, L
"itemdlg_oldwndproc"), hwnd
, umessage
, wparam
, lparam
);
1983 static LRESULT
on_wm_initdialog(HWND hwnd
, LPARAM lParam
)
1985 FileDialogImpl
*This
= (FileDialogImpl
*)lParam
;
1988 TRACE("(%p, %p)\n", This
, hwnd
);
1990 SetWindowLongPtrW(hwnd
, GWLP_USERDATA
, (LPARAM
)This
);
1991 This
->dlg_hwnd
= hwnd
;
1993 hitem
= GetDlgItem(This
->dlg_hwnd
, pshHelp
);
1994 if(hitem
) ShowWindow(hitem
, SW_HIDE
);
1996 hitem
= GetDlgItem(This
->dlg_hwnd
, IDC_FILETYPESTATIC
);
1997 if(hitem
) ShowWindow(hitem
, SW_HIDE
);
1999 /* Fill filetypes combobox, or hide it. */
2000 hitem
= GetDlgItem(This
->dlg_hwnd
, IDC_FILETYPE
);
2001 if(This
->filterspec_count
)
2006 UINT i
, maxwidth
= 0;
2009 font
= (HFONT
)SendMessageW(hitem
, WM_GETFONT
, 0, 0);
2010 SelectObject(hdc
, font
);
2012 for(i
= 0; i
< This
->filterspec_count
; i
++)
2014 SendMessageW(hitem
, CB_ADDSTRING
, 0, (LPARAM
)This
->filterspecs
[i
].pszName
);
2016 if(GetTextExtentPoint32W(hdc
, This
->filterspecs
[i
].pszName
, lstrlenW(This
->filterspecs
[i
].pszName
), &size
))
2017 maxwidth
= max(maxwidth
, size
.cx
);
2019 ReleaseDC(hitem
, hdc
);
2023 maxwidth
+= GetSystemMetrics(SM_CXVSCROLL
) + 4;
2024 SendMessageW(hitem
, CB_SETDROPPEDWIDTH
, (WPARAM
)maxwidth
, 0);
2027 ERR("Failed to calculate width of filetype dropdown\n");
2029 SendMessageW(hitem
, CB_SETCURSEL
, This
->filetypeindex
, 0);
2032 ShowWindow(hitem
, SW_HIDE
);
2034 if(This
->set_filename
&&
2035 (hitem
= GetDlgItem(This
->dlg_hwnd
, IDC_FILENAME
)) )
2036 SendMessageW(hitem
, WM_SETTEXT
, 0, (LPARAM
)This
->set_filename
);
2038 if(This
->hmenu_opendropdown
)
2041 LOGFONTW lfw
, lfw_marlett
;
2044 dropdown_hwnd
= GetDlgItem(This
->dlg_hwnd
, psh1
);
2046 /* Change dropdown button font to Marlett */
2047 dialog_font
= (HFONT
)SendMessageW(dropdown_hwnd
, WM_GETFONT
, 0, 0);
2049 GetObjectW(dialog_font
, sizeof(lfw
), &lfw
);
2051 memset(&lfw_marlett
, 0, sizeof(lfw_marlett
));
2052 lstrcpyW(lfw_marlett
.lfFaceName
, L
"Marlett");
2053 lfw_marlett
.lfHeight
= lfw
.lfHeight
;
2054 lfw_marlett
.lfCharSet
= SYMBOL_CHARSET
;
2056 This
->hfont_opendropdown
= CreateFontIndirectW(&lfw_marlett
);
2058 SendMessageW(dropdown_hwnd
, WM_SETFONT
, (LPARAM
)This
->hfont_opendropdown
, 0);
2060 /* Subclass button so we can handle LBUTTONDOWN */
2061 SetPropW(dropdown_hwnd
, L
"itemdlg_This", This
);
2062 SetPropW(dropdown_hwnd
, L
"itemdlg_oldwndproc",
2063 (HANDLE
)SetWindowLongPtrW(dropdown_hwnd
, GWLP_WNDPROC
, (LONG_PTR
)dropdown_subclass_proc
));
2066 ctrl_container_reparent(This
, This
->dlg_hwnd
);
2067 init_explorerbrowser(This
);
2068 init_toolbar(This
, hwnd
);
2069 update_control_text(This
);
2070 update_layout(This
);
2072 if(This
->filterspec_count
)
2073 events_OnTypeChange(This
);
2075 if ((hitem
= GetDlgItem(This
->dlg_hwnd
, IDC_FILENAME
)))
2081 static LRESULT
on_wm_size(FileDialogImpl
*This
)
2083 update_layout(This
);
2087 static LRESULT
on_wm_getminmaxinfo(FileDialogImpl
*This
, LPARAM lparam
)
2089 MINMAXINFO
*mmi
= (MINMAXINFO
*)lparam
;
2090 TRACE("%p (%p)\n", This
, mmi
);
2093 mmi
->ptMinTrackSize
.x
= 640;
2094 mmi
->ptMinTrackSize
.y
= 480;
2099 static LRESULT
on_wm_destroy(FileDialogImpl
*This
)
2101 TRACE("%p\n", This
);
2105 IExplorerBrowser_Destroy(This
->peb
);
2106 IExplorerBrowser_Release(This
->peb
);
2110 ctrl_container_reparent(This
, NULL
);
2111 This
->dlg_hwnd
= NULL
;
2113 DeleteObject(This
->hfont_opendropdown
);
2114 This
->hfont_opendropdown
= NULL
;
2119 static LRESULT
on_idok(FileDialogImpl
*This
)
2121 TRACE("%p\n", This
);
2123 if(SUCCEEDED(on_default_action(This
)))
2124 EndDialog(This
->dlg_hwnd
, S_OK
);
2129 static LRESULT
on_idcancel(FileDialogImpl
*This
)
2131 TRACE("%p\n", This
);
2133 EndDialog(This
->dlg_hwnd
, HRESULT_FROM_WIN32(ERROR_CANCELLED
));
2138 static LRESULT
on_command_opendropdown(FileDialogImpl
*This
, WPARAM wparam
, LPARAM lparam
)
2140 if(HIWORD(wparam
) == BN_CLICKED
)
2142 HWND hwnd
= (HWND
)lparam
;
2143 SendMessageW(hwnd
, BM_SETCHECK
, BST_CHECKED
, 0);
2144 show_opendropdown(This
);
2145 SendMessageW(hwnd
, BM_SETCHECK
, BST_UNCHECKED
, 0);
2151 static LRESULT
on_browse_back(FileDialogImpl
*This
)
2153 TRACE("%p\n", This
);
2154 IExplorerBrowser_BrowseToIDList(This
->peb
, NULL
, SBSP_NAVIGATEBACK
);
2158 static LRESULT
on_browse_forward(FileDialogImpl
*This
)
2160 TRACE("%p\n", This
);
2161 IExplorerBrowser_BrowseToIDList(This
->peb
, NULL
, SBSP_NAVIGATEFORWARD
);
2165 static LRESULT
on_command_filetype(FileDialogImpl
*This
, WPARAM wparam
, LPARAM lparam
)
2167 if(HIWORD(wparam
) == CBN_SELCHANGE
)
2172 UINT prev_index
= This
->filetypeindex
;
2174 This
->filetypeindex
= SendMessageW((HWND
)lparam
, CB_GETCURSEL
, 0, 0);
2175 TRACE("File type selection changed to %d.\n", This
->filetypeindex
);
2177 if(prev_index
== This
->filetypeindex
)
2180 hr
= IExplorerBrowser_GetCurrentView(This
->peb
, &IID_IShellView
, (void**)&psv
);
2183 IShellView_Refresh(psv
);
2184 IShellView_Release(psv
);
2187 if(This
->dlg_type
== ITEMDLG_TYPE_SAVE
&& get_file_name(This
, &filename
))
2189 WCHAR buf
[MAX_PATH
], extbuf
[MAX_PATH
], *ext
;
2191 ext
= get_first_ext_from_spec(extbuf
, This
->filterspecs
[This
->filetypeindex
].pszSpec
);
2194 lstrcpyW(buf
, filename
);
2196 if(PathMatchSpecW(buf
, This
->filterspecs
[prev_index
].pszSpec
))
2197 PathRemoveExtensionW(buf
);
2200 set_file_name(This
, buf
);
2202 CoTaskMemFree(filename
);
2205 /* The documentation claims that OnTypeChange is called only
2206 * when the dialog is opened, but this is obviously not the
2208 events_OnTypeChange(This
);
2214 static LRESULT
on_wm_command(FileDialogImpl
*This
, WPARAM wparam
, LPARAM lparam
)
2216 switch(LOWORD(wparam
))
2218 case IDOK
: return on_idok(This
);
2219 case IDCANCEL
: return on_idcancel(This
);
2220 case psh1
: return on_command_opendropdown(This
, wparam
, lparam
);
2221 case IDC_NAVBACK
: return on_browse_back(This
);
2222 case IDC_NAVFORWARD
: return on_browse_forward(This
);
2223 case IDC_FILETYPE
: return on_command_filetype(This
, wparam
, lparam
);
2224 default: TRACE("Unknown command.\n");
2229 static INT_PTR CALLBACK
itemdlg_dlgproc(HWND hwnd
, UINT umessage
, WPARAM wparam
, LPARAM lparam
)
2231 FileDialogImpl
*This
= (FileDialogImpl
*)GetWindowLongPtrW(hwnd
, GWLP_USERDATA
);
2235 case WM_INITDIALOG
: return on_wm_initdialog(hwnd
, lparam
);
2236 case WM_COMMAND
: return on_wm_command(This
, wparam
, lparam
);
2237 case WM_SIZE
: return on_wm_size(This
);
2238 case WM_GETMINMAXINFO
: return on_wm_getminmaxinfo(This
, lparam
);
2239 case WM_DESTROY
: return on_wm_destroy(This
);
2245 static HRESULT
create_dialog(FileDialogImpl
*This
, HWND parent
)
2250 res
= DialogBoxParamW(COMDLG32_hInstance
,
2251 MAKEINTRESOURCEW(NEWFILEOPENV3ORD
),
2252 parent
, itemdlg_dlgproc
, (LPARAM
)This
);
2253 This
->dlg_hwnd
= NULL
;
2256 ERR("Failed to show dialog (LastError: %ld)\n", GetLastError());
2260 TRACE("Returning 0x%08lx\n", (HRESULT
)res
);
2261 return (HRESULT
)res
;
2264 /**************************************************************************
2265 * IFileDialog implementation
2267 static inline FileDialogImpl
*impl_from_IFileDialog2(IFileDialog2
*iface
)
2269 return CONTAINING_RECORD(iface
, FileDialogImpl
, IFileDialog2_iface
);
2272 static HRESULT WINAPI
IFileDialog2_fnQueryInterface(IFileDialog2
*iface
,
2276 FileDialogImpl
*This
= impl_from_IFileDialog2(iface
);
2277 TRACE("%p (%s, %p)\n", This
, debugstr_guid(riid
), ppvObject
);
2280 if(IsEqualGUID(riid
, &IID_IUnknown
) ||
2281 IsEqualGUID(riid
, &IID_IFileDialog
) ||
2282 IsEqualGUID(riid
, &IID_IFileDialog2
))
2286 else if(IsEqualGUID(riid
, &IID_IFileOpenDialog
) && This
->dlg_type
== ITEMDLG_TYPE_OPEN
)
2288 *ppvObject
= &This
->u
.IFileOpenDialog_iface
;
2290 else if(IsEqualGUID(riid
, &IID_IFileSaveDialog
) && This
->dlg_type
== ITEMDLG_TYPE_SAVE
)
2292 *ppvObject
= &This
->u
.IFileSaveDialog_iface
;
2294 else if(IsEqualGUID(riid
, &IID_IExplorerBrowserEvents
))
2296 *ppvObject
= &This
->IExplorerBrowserEvents_iface
;
2298 else if(IsEqualGUID(riid
, &IID_IServiceProvider
))
2300 *ppvObject
= &This
->IServiceProvider_iface
;
2302 else if(IsEqualGUID(&IID_ICommDlgBrowser3
, riid
) ||
2303 IsEqualGUID(&IID_ICommDlgBrowser2
, riid
) ||
2304 IsEqualGUID(&IID_ICommDlgBrowser
, riid
))
2306 *ppvObject
= &This
->ICommDlgBrowser3_iface
;
2308 else if(IsEqualGUID(&IID_IOleWindow
, riid
))
2310 *ppvObject
= &This
->IOleWindow_iface
;
2312 else if(IsEqualGUID(riid
, &IID_IFileDialogCustomize
) ||
2313 IsEqualGUID(riid
, &IID_IFileDialogCustomizeAlt
))
2315 *ppvObject
= &This
->IFileDialogCustomize_iface
;
2318 FIXME("Unknown interface requested: %s.\n", debugstr_guid(riid
));
2322 IUnknown_AddRef((IUnknown
*)*ppvObject
);
2326 return E_NOINTERFACE
;
2329 static ULONG WINAPI
IFileDialog2_fnAddRef(IFileDialog2
*iface
)
2331 FileDialogImpl
*This
= impl_from_IFileDialog2(iface
);
2332 LONG ref
= InterlockedIncrement(&This
->ref
);
2333 TRACE("%p - ref %ld\n", This
, ref
);
2338 static ULONG WINAPI
IFileDialog2_fnRelease(IFileDialog2
*iface
)
2340 FileDialogImpl
*This
= impl_from_IFileDialog2(iface
);
2341 LONG ref
= InterlockedDecrement(&This
->ref
);
2342 TRACE("%p - ref %ld\n", This
, ref
);
2347 for(i
= 0; i
< This
->filterspec_count
; i
++)
2349 LocalFree((void*)This
->filterspecs
[i
].pszName
);
2350 LocalFree((void*)This
->filterspecs
[i
].pszSpec
);
2352 HeapFree(GetProcessHeap(), 0, This
->filterspecs
);
2354 DestroyWindow(This
->cctrls_hwnd
);
2356 if(This
->psi_defaultfolder
) IShellItem_Release(This
->psi_defaultfolder
);
2357 if(This
->psi_setfolder
) IShellItem_Release(This
->psi_setfolder
);
2358 if(This
->psi_folder
) IShellItem_Release(This
->psi_folder
);
2359 if(This
->psia_selection
) IShellItemArray_Release(This
->psia_selection
);
2360 if(This
->psia_results
) IShellItemArray_Release(This
->psia_results
);
2362 LocalFree(This
->set_filename
);
2363 LocalFree(This
->default_ext
);
2364 LocalFree(This
->custom_title
);
2365 LocalFree(This
->custom_okbutton
);
2366 LocalFree(This
->custom_cancelbutton
);
2367 LocalFree(This
->custom_filenamelabel
);
2369 DestroyMenu(This
->hmenu_opendropdown
);
2370 DeleteObject(This
->hfont_opendropdown
);
2372 HeapFree(GetProcessHeap(), 0, This
);
2378 static HRESULT WINAPI
IFileDialog2_fnShow(IFileDialog2
*iface
, HWND hwndOwner
)
2380 FileDialogImpl
*This
= impl_from_IFileDialog2(iface
);
2381 TRACE("%p (%p)\n", iface
, hwndOwner
);
2383 This
->opendropdown_has_selection
= FALSE
;
2385 return create_dialog(This
, hwndOwner
);
2388 static HRESULT WINAPI
IFileDialog2_fnSetFileTypes(IFileDialog2
*iface
, UINT cFileTypes
,
2389 const COMDLG_FILTERSPEC
*rgFilterSpec
)
2391 FileDialogImpl
*This
= impl_from_IFileDialog2(iface
);
2393 TRACE("%p (%d, %p)\n", This
, cFileTypes
, rgFilterSpec
);
2396 return E_INVALIDARG
;
2398 if(This
->filterspecs
)
2399 return E_UNEXPECTED
;
2404 This
->filterspecs
= HeapAlloc(GetProcessHeap(), 0, sizeof(COMDLG_FILTERSPEC
)*cFileTypes
);
2405 for(i
= 0; i
< cFileTypes
; i
++)
2407 This
->filterspecs
[i
].pszName
= StrDupW(rgFilterSpec
[i
].pszName
);
2408 This
->filterspecs
[i
].pszSpec
= StrDupW(rgFilterSpec
[i
].pszSpec
);
2410 This
->filterspec_count
= cFileTypes
;
2415 static HRESULT WINAPI
IFileDialog2_fnSetFileTypeIndex(IFileDialog2
*iface
, UINT iFileType
)
2417 FileDialogImpl
*This
= impl_from_IFileDialog2(iface
);
2418 TRACE("%p (%d)\n", This
, iFileType
);
2420 if(!This
->filterspecs
)
2423 iFileType
= max(iFileType
, 1);
2424 iFileType
= min(iFileType
, This
->filterspec_count
);
2425 This
->filetypeindex
= iFileType
-1;
2430 static HRESULT WINAPI
IFileDialog2_fnGetFileTypeIndex(IFileDialog2
*iface
, UINT
*piFileType
)
2432 FileDialogImpl
*This
= impl_from_IFileDialog2(iface
);
2433 TRACE("%p (%p)\n", This
, piFileType
);
2436 return E_INVALIDARG
;
2438 if(This
->filterspec_count
== 0)
2441 *piFileType
= This
->filetypeindex
+ 1;
2446 static HRESULT WINAPI
IFileDialog2_fnAdvise(IFileDialog2
*iface
, IFileDialogEvents
*pfde
, DWORD
*pdwCookie
)
2448 FileDialogImpl
*This
= impl_from_IFileDialog2(iface
);
2449 events_client
*client
;
2450 TRACE("%p (%p, %p)\n", This
, pfde
, pdwCookie
);
2452 if(!pfde
|| !pdwCookie
)
2453 return E_INVALIDARG
;
2455 client
= HeapAlloc(GetProcessHeap(), 0, sizeof(events_client
));
2456 client
->pfde
= pfde
;
2457 client
->cookie
= ++This
->events_next_cookie
;
2459 IFileDialogEvents_AddRef(pfde
);
2460 *pdwCookie
= client
->cookie
;
2462 list_add_tail(&This
->events_clients
, &client
->entry
);
2467 static HRESULT WINAPI
IFileDialog2_fnUnadvise(IFileDialog2
*iface
, DWORD dwCookie
)
2469 FileDialogImpl
*This
= impl_from_IFileDialog2(iface
);
2470 events_client
*client
, *found
= NULL
;
2471 TRACE("%p (%ld)\n", This
, dwCookie
);
2473 LIST_FOR_EACH_ENTRY(client
, &This
->events_clients
, events_client
, entry
)
2475 if(client
->cookie
== dwCookie
)
2484 list_remove(&found
->entry
);
2485 IFileDialogEvents_Release(found
->pfde
);
2486 HeapFree(GetProcessHeap(), 0, found
);
2490 return E_INVALIDARG
;
2493 static HRESULT WINAPI
IFileDialog2_fnSetOptions(IFileDialog2
*iface
, FILEOPENDIALOGOPTIONS fos
)
2495 FileDialogImpl
*This
= impl_from_IFileDialog2(iface
);
2496 TRACE("%p (0x%lx)\n", This
, fos
);
2498 if (fos
& ~(FOS_OVERWRITEPROMPT
| FOS_STRICTFILETYPES
| FOS_NOCHANGEDIR
| FOS_PICKFOLDERS
| FOS_FORCEFILESYSTEM
2499 | FOS_ALLNONSTORAGEITEMS
| FOS_NOVALIDATE
| FOS_ALLOWMULTISELECT
| FOS_PATHMUSTEXIST
| FOS_FILEMUSTEXIST
2500 | FOS_CREATEPROMPT
| FOS_SHAREAWARE
| FOS_NOREADONLYRETURN
| FOS_NOTESTFILECREATE
| FOS_HIDEMRUPLACES
2501 | FOS_HIDEPINNEDPLACES
| FOS_NODEREFERENCELINKS
| FOS_DONTADDTORECENT
| FOS_FORCESHOWHIDDEN
2502 | FOS_DEFAULTNOMINIMODE
| FOS_FORCEPREVIEWPANEON
| FOS_SUPPORTSTREAMABLEITEMS
))
2504 WARN("Invalid option %#lx\n", fos
);
2505 return E_INVALIDARG
;
2508 if( !(This
->options
& FOS_PICKFOLDERS
) && (fos
& FOS_PICKFOLDERS
) )
2511 LoadStringW(COMDLG32_hInstance
, IDS_SELECT_FOLDER
, buf
, ARRAY_SIZE(buf
));
2512 IFileDialog2_SetTitle(iface
, buf
);
2515 This
->options
= fos
;
2520 static HRESULT WINAPI
IFileDialog2_fnGetOptions(IFileDialog2
*iface
, FILEOPENDIALOGOPTIONS
*pfos
)
2522 FileDialogImpl
*This
= impl_from_IFileDialog2(iface
);
2523 TRACE("%p (%p)\n", This
, pfos
);
2526 return E_INVALIDARG
;
2528 *pfos
= This
->options
;
2533 static HRESULT WINAPI
IFileDialog2_fnSetDefaultFolder(IFileDialog2
*iface
, IShellItem
*psi
)
2535 FileDialogImpl
*This
= impl_from_IFileDialog2(iface
);
2536 TRACE("%p (%p)\n", This
, psi
);
2537 if(This
->psi_defaultfolder
)
2538 IShellItem_Release(This
->psi_defaultfolder
);
2540 This
->psi_defaultfolder
= psi
;
2542 if(This
->psi_defaultfolder
)
2543 IShellItem_AddRef(This
->psi_defaultfolder
);
2548 static HRESULT WINAPI
IFileDialog2_fnSetFolder(IFileDialog2
*iface
, IShellItem
*psi
)
2550 FileDialogImpl
*This
= impl_from_IFileDialog2(iface
);
2551 TRACE("%p (%p)\n", This
, psi
);
2552 if(This
->psi_setfolder
)
2553 IShellItem_Release(This
->psi_setfolder
);
2555 This
->psi_setfolder
= psi
;
2557 if(This
->psi_setfolder
)
2558 IShellItem_AddRef(This
->psi_setfolder
);
2563 static HRESULT WINAPI
IFileDialog2_fnGetFolder(IFileDialog2
*iface
, IShellItem
**ppsi
)
2565 FileDialogImpl
*This
= impl_from_IFileDialog2(iface
);
2566 TRACE("%p (%p)\n", This
, ppsi
);
2568 return E_INVALIDARG
;
2571 If the dialog is shown, return the current(ly selected) folder. */
2574 if(This
->psi_folder
)
2575 *ppsi
= This
->psi_folder
;
2576 else if(This
->psi_setfolder
)
2577 *ppsi
= This
->psi_setfolder
;
2578 else if(This
->psi_defaultfolder
)
2579 *ppsi
= This
->psi_defaultfolder
;
2583 IShellItem_AddRef(*ppsi
);
2590 static HRESULT WINAPI
IFileDialog2_fnGetCurrentSelection(IFileDialog2
*iface
, IShellItem
**ppsi
)
2592 FileDialogImpl
*This
= impl_from_IFileDialog2(iface
);
2594 TRACE("%p (%p)\n", This
, ppsi
);
2597 return E_INVALIDARG
;
2599 if(This
->psia_selection
)
2601 /* FIXME: Check filename edit box */
2602 hr
= IShellItemArray_GetItemAt(This
->psia_selection
, 0, ppsi
);
2609 static HRESULT WINAPI
IFileDialog2_fnSetFileName(IFileDialog2
*iface
, LPCWSTR pszName
)
2611 FileDialogImpl
*This
= impl_from_IFileDialog2(iface
);
2612 TRACE("%p (%s)\n", iface
, debugstr_w(pszName
));
2614 set_file_name(This
, pszName
);
2619 static HRESULT WINAPI
IFileDialog2_fnGetFileName(IFileDialog2
*iface
, LPWSTR
*pszName
)
2621 FileDialogImpl
*This
= impl_from_IFileDialog2(iface
);
2622 TRACE("%p (%p)\n", iface
, pszName
);
2625 return E_INVALIDARG
;
2628 get_file_name(This
, pszName
);
2629 return *pszName
? S_OK
: E_FAIL
;
2632 static HRESULT WINAPI
IFileDialog2_fnSetTitle(IFileDialog2
*iface
, LPCWSTR pszTitle
)
2634 FileDialogImpl
*This
= impl_from_IFileDialog2(iface
);
2635 TRACE("%p (%s)\n", This
, debugstr_w(pszTitle
));
2637 LocalFree(This
->custom_title
);
2638 This
->custom_title
= StrDupW(pszTitle
);
2639 update_control_text(This
);
2644 static HRESULT WINAPI
IFileDialog2_fnSetOkButtonLabel(IFileDialog2
*iface
, LPCWSTR pszText
)
2646 FileDialogImpl
*This
= impl_from_IFileDialog2(iface
);
2647 TRACE("%p (%s)\n", This
, debugstr_w(pszText
));
2649 LocalFree(This
->custom_okbutton
);
2650 This
->custom_okbutton
= StrDupW(pszText
);
2651 update_control_text(This
);
2652 update_layout(This
);
2657 static HRESULT WINAPI
IFileDialog2_fnSetFileNameLabel(IFileDialog2
*iface
, LPCWSTR pszLabel
)
2659 FileDialogImpl
*This
= impl_from_IFileDialog2(iface
);
2660 TRACE("%p (%s)\n", This
, debugstr_w(pszLabel
));
2662 LocalFree(This
->custom_filenamelabel
);
2663 This
->custom_filenamelabel
= StrDupW(pszLabel
);
2664 update_control_text(This
);
2665 update_layout(This
);
2670 static HRESULT WINAPI
IFileDialog2_fnGetResult(IFileDialog2
*iface
, IShellItem
**ppsi
)
2672 FileDialogImpl
*This
= impl_from_IFileDialog2(iface
);
2674 TRACE("%p (%p)\n", This
, ppsi
);
2677 return E_INVALIDARG
;
2679 if(This
->psia_results
)
2682 hr
= IShellItemArray_GetCount(This
->psia_results
, &item_count
);
2688 /* Adds a reference. */
2689 hr
= IShellItemArray_GetItemAt(This
->psia_results
, 0, ppsi
);
2695 return E_UNEXPECTED
;
2698 static HRESULT WINAPI
IFileDialog2_fnAddPlace(IFileDialog2
*iface
, IShellItem
*psi
, FDAP fdap
)
2700 FileDialogImpl
*This
= impl_from_IFileDialog2(iface
);
2701 FIXME("stub - %p (%p, %d)\n", This
, psi
, fdap
);
2705 static HRESULT WINAPI
IFileDialog2_fnSetDefaultExtension(IFileDialog2
*iface
, LPCWSTR pszDefaultExtension
)
2707 FileDialogImpl
*This
= impl_from_IFileDialog2(iface
);
2708 TRACE("%p (%s)\n", This
, debugstr_w(pszDefaultExtension
));
2710 LocalFree(This
->default_ext
);
2711 This
->default_ext
= StrDupW(pszDefaultExtension
);
2716 static HRESULT WINAPI
IFileDialog2_fnClose(IFileDialog2
*iface
, HRESULT hr
)
2718 FileDialogImpl
*This
= impl_from_IFileDialog2(iface
);
2719 TRACE("%p (0x%08lx)\n", This
, hr
);
2722 EndDialog(This
->dlg_hwnd
, hr
);
2727 static HRESULT WINAPI
IFileDialog2_fnSetClientGuid(IFileDialog2
*iface
, REFGUID guid
)
2729 FileDialogImpl
*This
= impl_from_IFileDialog2(iface
);
2730 TRACE("%p (%s)\n", This
, debugstr_guid(guid
));
2731 This
->client_guid
= *guid
;
2735 static HRESULT WINAPI
IFileDialog2_fnClearClientData(IFileDialog2
*iface
)
2737 FileDialogImpl
*This
= impl_from_IFileDialog2(iface
);
2738 FIXME("stub - %p\n", This
);
2742 static HRESULT WINAPI
IFileDialog2_fnSetFilter(IFileDialog2
*iface
, IShellItemFilter
*pFilter
)
2744 FileDialogImpl
*This
= impl_from_IFileDialog2(iface
);
2745 FIXME("stub - %p (%p)\n", This
, pFilter
);
2749 static HRESULT WINAPI
IFileDialog2_fnSetCancelButtonLabel(IFileDialog2
*iface
, LPCWSTR pszLabel
)
2751 FileDialogImpl
*This
= impl_from_IFileDialog2(iface
);
2752 TRACE("%p (%s)\n", This
, debugstr_w(pszLabel
));
2754 LocalFree(This
->custom_cancelbutton
);
2755 This
->custom_cancelbutton
= StrDupW(pszLabel
);
2756 update_control_text(This
);
2757 update_layout(This
);
2762 static HRESULT WINAPI
IFileDialog2_fnSetNavigationRoot(IFileDialog2
*iface
, IShellItem
*psi
)
2764 FileDialogImpl
*This
= impl_from_IFileDialog2(iface
);
2765 FIXME("stub - %p (%p)\n", This
, psi
);
2769 static const IFileDialog2Vtbl vt_IFileDialog2
= {
2770 IFileDialog2_fnQueryInterface
,
2771 IFileDialog2_fnAddRef
,
2772 IFileDialog2_fnRelease
,
2773 IFileDialog2_fnShow
,
2774 IFileDialog2_fnSetFileTypes
,
2775 IFileDialog2_fnSetFileTypeIndex
,
2776 IFileDialog2_fnGetFileTypeIndex
,
2777 IFileDialog2_fnAdvise
,
2778 IFileDialog2_fnUnadvise
,
2779 IFileDialog2_fnSetOptions
,
2780 IFileDialog2_fnGetOptions
,
2781 IFileDialog2_fnSetDefaultFolder
,
2782 IFileDialog2_fnSetFolder
,
2783 IFileDialog2_fnGetFolder
,
2784 IFileDialog2_fnGetCurrentSelection
,
2785 IFileDialog2_fnSetFileName
,
2786 IFileDialog2_fnGetFileName
,
2787 IFileDialog2_fnSetTitle
,
2788 IFileDialog2_fnSetOkButtonLabel
,
2789 IFileDialog2_fnSetFileNameLabel
,
2790 IFileDialog2_fnGetResult
,
2791 IFileDialog2_fnAddPlace
,
2792 IFileDialog2_fnSetDefaultExtension
,
2793 IFileDialog2_fnClose
,
2794 IFileDialog2_fnSetClientGuid
,
2795 IFileDialog2_fnClearClientData
,
2796 IFileDialog2_fnSetFilter
,
2797 IFileDialog2_fnSetCancelButtonLabel
,
2798 IFileDialog2_fnSetNavigationRoot
2801 /**************************************************************************
2804 static inline FileDialogImpl
*impl_from_IFileOpenDialog(IFileOpenDialog
*iface
)
2806 return CONTAINING_RECORD(iface
, FileDialogImpl
, u
.IFileOpenDialog_iface
);
2809 static HRESULT WINAPI
IFileOpenDialog_fnQueryInterface(IFileOpenDialog
*iface
,
2810 REFIID riid
, void **ppvObject
)
2812 FileDialogImpl
*This
= impl_from_IFileOpenDialog(iface
);
2813 return IFileDialog2_QueryInterface(&This
->IFileDialog2_iface
, riid
, ppvObject
);
2816 static ULONG WINAPI
IFileOpenDialog_fnAddRef(IFileOpenDialog
*iface
)
2818 FileDialogImpl
*This
= impl_from_IFileOpenDialog(iface
);
2819 return IFileDialog2_AddRef(&This
->IFileDialog2_iface
);
2822 static ULONG WINAPI
IFileOpenDialog_fnRelease(IFileOpenDialog
*iface
)
2824 FileDialogImpl
*This
= impl_from_IFileOpenDialog(iface
);
2825 return IFileDialog2_Release(&This
->IFileDialog2_iface
);
2828 static HRESULT WINAPI
IFileOpenDialog_fnShow(IFileOpenDialog
*iface
, HWND hwndOwner
)
2830 FileDialogImpl
*This
= impl_from_IFileOpenDialog(iface
);
2831 return IFileDialog2_Show(&This
->IFileDialog2_iface
, hwndOwner
);
2834 static HRESULT WINAPI
IFileOpenDialog_fnSetFileTypes(IFileOpenDialog
*iface
, UINT cFileTypes
,
2835 const COMDLG_FILTERSPEC
*rgFilterSpec
)
2837 FileDialogImpl
*This
= impl_from_IFileOpenDialog(iface
);
2838 return IFileDialog2_SetFileTypes(&This
->IFileDialog2_iface
, cFileTypes
, rgFilterSpec
);
2841 static HRESULT WINAPI
IFileOpenDialog_fnSetFileTypeIndex(IFileOpenDialog
*iface
, UINT iFileType
)
2843 FileDialogImpl
*This
= impl_from_IFileOpenDialog(iface
);
2844 return IFileDialog2_SetFileTypeIndex(&This
->IFileDialog2_iface
, iFileType
);
2847 static HRESULT WINAPI
IFileOpenDialog_fnGetFileTypeIndex(IFileOpenDialog
*iface
, UINT
*piFileType
)
2849 FileDialogImpl
*This
= impl_from_IFileOpenDialog(iface
);
2850 return IFileDialog2_GetFileTypeIndex(&This
->IFileDialog2_iface
, piFileType
);
2853 static HRESULT WINAPI
IFileOpenDialog_fnAdvise(IFileOpenDialog
*iface
, IFileDialogEvents
*pfde
,
2856 FileDialogImpl
*This
= impl_from_IFileOpenDialog(iface
);
2857 return IFileDialog2_Advise(&This
->IFileDialog2_iface
, pfde
, pdwCookie
);
2860 static HRESULT WINAPI
IFileOpenDialog_fnUnadvise(IFileOpenDialog
*iface
, DWORD dwCookie
)
2862 FileDialogImpl
*This
= impl_from_IFileOpenDialog(iface
);
2863 return IFileDialog2_Unadvise(&This
->IFileDialog2_iface
, dwCookie
);
2866 static HRESULT WINAPI
IFileOpenDialog_fnSetOptions(IFileOpenDialog
*iface
, FILEOPENDIALOGOPTIONS fos
)
2868 FileDialogImpl
*This
= impl_from_IFileOpenDialog(iface
);
2869 return IFileDialog2_SetOptions(&This
->IFileDialog2_iface
, fos
);
2872 static HRESULT WINAPI
IFileOpenDialog_fnGetOptions(IFileOpenDialog
*iface
, FILEOPENDIALOGOPTIONS
*pfos
)
2874 FileDialogImpl
*This
= impl_from_IFileOpenDialog(iface
);
2875 return IFileDialog2_GetOptions(&This
->IFileDialog2_iface
, pfos
);
2878 static HRESULT WINAPI
IFileOpenDialog_fnSetDefaultFolder(IFileOpenDialog
*iface
, IShellItem
*psi
)
2880 FileDialogImpl
*This
= impl_from_IFileOpenDialog(iface
);
2881 return IFileDialog2_SetDefaultFolder(&This
->IFileDialog2_iface
, psi
);
2884 static HRESULT WINAPI
IFileOpenDialog_fnSetFolder(IFileOpenDialog
*iface
, IShellItem
*psi
)
2886 FileDialogImpl
*This
= impl_from_IFileOpenDialog(iface
);
2887 return IFileDialog2_SetFolder(&This
->IFileDialog2_iface
, psi
);
2890 static HRESULT WINAPI
IFileOpenDialog_fnGetFolder(IFileOpenDialog
*iface
, IShellItem
**ppsi
)
2892 FileDialogImpl
*This
= impl_from_IFileOpenDialog(iface
);
2893 return IFileDialog2_GetFolder(&This
->IFileDialog2_iface
, ppsi
);
2896 static HRESULT WINAPI
IFileOpenDialog_fnGetCurrentSelection(IFileOpenDialog
*iface
, IShellItem
**ppsi
)
2898 FileDialogImpl
*This
= impl_from_IFileOpenDialog(iface
);
2899 return IFileDialog2_GetCurrentSelection(&This
->IFileDialog2_iface
, ppsi
);
2902 static HRESULT WINAPI
IFileOpenDialog_fnSetFileName(IFileOpenDialog
*iface
, LPCWSTR pszName
)
2904 FileDialogImpl
*This
= impl_from_IFileOpenDialog(iface
);
2905 return IFileDialog2_SetFileName(&This
->IFileDialog2_iface
, pszName
);
2908 static HRESULT WINAPI
IFileOpenDialog_fnGetFileName(IFileOpenDialog
*iface
, LPWSTR
*pszName
)
2910 FileDialogImpl
*This
= impl_from_IFileOpenDialog(iface
);
2911 return IFileDialog2_GetFileName(&This
->IFileDialog2_iface
, pszName
);
2914 static HRESULT WINAPI
IFileOpenDialog_fnSetTitle(IFileOpenDialog
*iface
, LPCWSTR pszTitle
)
2916 FileDialogImpl
*This
= impl_from_IFileOpenDialog(iface
);
2917 return IFileDialog2_SetTitle(&This
->IFileDialog2_iface
, pszTitle
);
2920 static HRESULT WINAPI
IFileOpenDialog_fnSetOkButtonLabel(IFileOpenDialog
*iface
, LPCWSTR pszText
)
2922 FileDialogImpl
*This
= impl_from_IFileOpenDialog(iface
);
2923 return IFileDialog2_SetOkButtonLabel(&This
->IFileDialog2_iface
, pszText
);
2926 static HRESULT WINAPI
IFileOpenDialog_fnSetFileNameLabel(IFileOpenDialog
*iface
, LPCWSTR pszLabel
)
2928 FileDialogImpl
*This
= impl_from_IFileOpenDialog(iface
);
2929 return IFileDialog2_SetFileNameLabel(&This
->IFileDialog2_iface
, pszLabel
);
2932 static HRESULT WINAPI
IFileOpenDialog_fnGetResult(IFileOpenDialog
*iface
, IShellItem
**ppsi
)
2934 FileDialogImpl
*This
= impl_from_IFileOpenDialog(iface
);
2935 return IFileDialog2_GetResult(&This
->IFileDialog2_iface
, ppsi
);
2938 static HRESULT WINAPI
IFileOpenDialog_fnAddPlace(IFileOpenDialog
*iface
, IShellItem
*psi
, FDAP fdap
)
2940 FileDialogImpl
*This
= impl_from_IFileOpenDialog(iface
);
2941 return IFileDialog2_AddPlace(&This
->IFileDialog2_iface
, psi
, fdap
);
2944 static HRESULT WINAPI
IFileOpenDialog_fnSetDefaultExtension(IFileOpenDialog
*iface
,
2945 LPCWSTR pszDefaultExtension
)
2947 FileDialogImpl
*This
= impl_from_IFileOpenDialog(iface
);
2948 return IFileDialog2_SetDefaultExtension(&This
->IFileDialog2_iface
, pszDefaultExtension
);
2951 static HRESULT WINAPI
IFileOpenDialog_fnClose(IFileOpenDialog
*iface
, HRESULT hr
)
2953 FileDialogImpl
*This
= impl_from_IFileOpenDialog(iface
);
2954 return IFileDialog2_Close(&This
->IFileDialog2_iface
, hr
);
2957 static HRESULT WINAPI
IFileOpenDialog_fnSetClientGuid(IFileOpenDialog
*iface
, REFGUID guid
)
2959 FileDialogImpl
*This
= impl_from_IFileOpenDialog(iface
);
2960 return IFileDialog2_SetClientGuid(&This
->IFileDialog2_iface
, guid
);
2963 static HRESULT WINAPI
IFileOpenDialog_fnClearClientData(IFileOpenDialog
*iface
)
2965 FileDialogImpl
*This
= impl_from_IFileOpenDialog(iface
);
2966 return IFileDialog2_ClearClientData(&This
->IFileDialog2_iface
);
2969 static HRESULT WINAPI
IFileOpenDialog_fnSetFilter(IFileOpenDialog
*iface
, IShellItemFilter
*pFilter
)
2971 FileDialogImpl
*This
= impl_from_IFileOpenDialog(iface
);
2972 return IFileDialog2_SetFilter(&This
->IFileDialog2_iface
, pFilter
);
2975 static HRESULT WINAPI
IFileOpenDialog_fnGetResults(IFileOpenDialog
*iface
, IShellItemArray
**ppenum
)
2977 FileDialogImpl
*This
= impl_from_IFileOpenDialog(iface
);
2978 TRACE("%p (%p)\n", This
, ppenum
);
2980 *ppenum
= This
->psia_results
;
2984 IShellItemArray_AddRef(*ppenum
);
2991 static HRESULT WINAPI
IFileOpenDialog_fnGetSelectedItems(IFileOpenDialog
*iface
, IShellItemArray
**ppsai
)
2993 FileDialogImpl
*This
= impl_from_IFileOpenDialog(iface
);
2994 TRACE("%p (%p)\n", This
, ppsai
);
2996 if(This
->psia_selection
)
2998 *ppsai
= This
->psia_selection
;
2999 IShellItemArray_AddRef(*ppsai
);
3006 static const IFileOpenDialogVtbl vt_IFileOpenDialog
= {
3007 IFileOpenDialog_fnQueryInterface
,
3008 IFileOpenDialog_fnAddRef
,
3009 IFileOpenDialog_fnRelease
,
3010 IFileOpenDialog_fnShow
,
3011 IFileOpenDialog_fnSetFileTypes
,
3012 IFileOpenDialog_fnSetFileTypeIndex
,
3013 IFileOpenDialog_fnGetFileTypeIndex
,
3014 IFileOpenDialog_fnAdvise
,
3015 IFileOpenDialog_fnUnadvise
,
3016 IFileOpenDialog_fnSetOptions
,
3017 IFileOpenDialog_fnGetOptions
,
3018 IFileOpenDialog_fnSetDefaultFolder
,
3019 IFileOpenDialog_fnSetFolder
,
3020 IFileOpenDialog_fnGetFolder
,
3021 IFileOpenDialog_fnGetCurrentSelection
,
3022 IFileOpenDialog_fnSetFileName
,
3023 IFileOpenDialog_fnGetFileName
,
3024 IFileOpenDialog_fnSetTitle
,
3025 IFileOpenDialog_fnSetOkButtonLabel
,
3026 IFileOpenDialog_fnSetFileNameLabel
,
3027 IFileOpenDialog_fnGetResult
,
3028 IFileOpenDialog_fnAddPlace
,
3029 IFileOpenDialog_fnSetDefaultExtension
,
3030 IFileOpenDialog_fnClose
,
3031 IFileOpenDialog_fnSetClientGuid
,
3032 IFileOpenDialog_fnClearClientData
,
3033 IFileOpenDialog_fnSetFilter
,
3034 IFileOpenDialog_fnGetResults
,
3035 IFileOpenDialog_fnGetSelectedItems
3038 /**************************************************************************
3041 static inline FileDialogImpl
*impl_from_IFileSaveDialog(IFileSaveDialog
*iface
)
3043 return CONTAINING_RECORD(iface
, FileDialogImpl
, u
.IFileSaveDialog_iface
);
3046 static HRESULT WINAPI
IFileSaveDialog_fnQueryInterface(IFileSaveDialog
*iface
,
3050 FileDialogImpl
*This
= impl_from_IFileSaveDialog(iface
);
3051 return IFileDialog2_QueryInterface(&This
->IFileDialog2_iface
, riid
, ppvObject
);
3054 static ULONG WINAPI
IFileSaveDialog_fnAddRef(IFileSaveDialog
*iface
)
3056 FileDialogImpl
*This
= impl_from_IFileSaveDialog(iface
);
3057 return IFileDialog2_AddRef(&This
->IFileDialog2_iface
);
3060 static ULONG WINAPI
IFileSaveDialog_fnRelease(IFileSaveDialog
*iface
)
3062 FileDialogImpl
*This
= impl_from_IFileSaveDialog(iface
);
3063 return IFileDialog2_Release(&This
->IFileDialog2_iface
);
3066 static HRESULT WINAPI
IFileSaveDialog_fnShow(IFileSaveDialog
*iface
, HWND hwndOwner
)
3068 FileDialogImpl
*This
= impl_from_IFileSaveDialog(iface
);
3069 return IFileDialog2_Show(&This
->IFileDialog2_iface
, hwndOwner
);
3072 static HRESULT WINAPI
IFileSaveDialog_fnSetFileTypes(IFileSaveDialog
*iface
, UINT cFileTypes
,
3073 const COMDLG_FILTERSPEC
*rgFilterSpec
)
3075 FileDialogImpl
*This
= impl_from_IFileSaveDialog(iface
);
3076 return IFileDialog2_SetFileTypes(&This
->IFileDialog2_iface
, cFileTypes
, rgFilterSpec
);
3079 static HRESULT WINAPI
IFileSaveDialog_fnSetFileTypeIndex(IFileSaveDialog
*iface
, UINT iFileType
)
3081 FileDialogImpl
*This
= impl_from_IFileSaveDialog(iface
);
3082 return IFileDialog2_SetFileTypeIndex(&This
->IFileDialog2_iface
, iFileType
);
3085 static HRESULT WINAPI
IFileSaveDialog_fnGetFileTypeIndex(IFileSaveDialog
*iface
, UINT
*piFileType
)
3087 FileDialogImpl
*This
= impl_from_IFileSaveDialog(iface
);
3088 return IFileDialog2_GetFileTypeIndex(&This
->IFileDialog2_iface
, piFileType
);
3091 static HRESULT WINAPI
IFileSaveDialog_fnAdvise(IFileSaveDialog
*iface
, IFileDialogEvents
*pfde
,
3094 FileDialogImpl
*This
= impl_from_IFileSaveDialog(iface
);
3095 return IFileDialog2_Advise(&This
->IFileDialog2_iface
, pfde
, pdwCookie
);
3098 static HRESULT WINAPI
IFileSaveDialog_fnUnadvise(IFileSaveDialog
*iface
, DWORD dwCookie
)
3100 FileDialogImpl
*This
= impl_from_IFileSaveDialog(iface
);
3101 return IFileDialog2_Unadvise(&This
->IFileDialog2_iface
, dwCookie
);
3104 static HRESULT WINAPI
IFileSaveDialog_fnSetOptions(IFileSaveDialog
*iface
, FILEOPENDIALOGOPTIONS fos
)
3106 FileDialogImpl
*This
= impl_from_IFileSaveDialog(iface
);
3107 return IFileDialog2_SetOptions(&This
->IFileDialog2_iface
, fos
);
3110 static HRESULT WINAPI
IFileSaveDialog_fnGetOptions(IFileSaveDialog
*iface
, FILEOPENDIALOGOPTIONS
*pfos
)
3112 FileDialogImpl
*This
= impl_from_IFileSaveDialog(iface
);
3113 return IFileDialog2_GetOptions(&This
->IFileDialog2_iface
, pfos
);
3116 static HRESULT WINAPI
IFileSaveDialog_fnSetDefaultFolder(IFileSaveDialog
*iface
, IShellItem
*psi
)
3118 FileDialogImpl
*This
= impl_from_IFileSaveDialog(iface
);
3119 return IFileDialog2_SetDefaultFolder(&This
->IFileDialog2_iface
, psi
);
3122 static HRESULT WINAPI
IFileSaveDialog_fnSetFolder(IFileSaveDialog
*iface
, IShellItem
*psi
)
3124 FileDialogImpl
*This
= impl_from_IFileSaveDialog(iface
);
3125 return IFileDialog2_SetFolder(&This
->IFileDialog2_iface
, psi
);
3128 static HRESULT WINAPI
IFileSaveDialog_fnGetFolder(IFileSaveDialog
*iface
, IShellItem
**ppsi
)
3130 FileDialogImpl
*This
= impl_from_IFileSaveDialog(iface
);
3131 return IFileDialog2_GetFolder(&This
->IFileDialog2_iface
, ppsi
);
3134 static HRESULT WINAPI
IFileSaveDialog_fnGetCurrentSelection(IFileSaveDialog
*iface
, IShellItem
**ppsi
)
3136 FileDialogImpl
*This
= impl_from_IFileSaveDialog(iface
);
3137 return IFileDialog2_GetCurrentSelection(&This
->IFileDialog2_iface
, ppsi
);
3140 static HRESULT WINAPI
IFileSaveDialog_fnSetFileName(IFileSaveDialog
*iface
, LPCWSTR pszName
)
3142 FileDialogImpl
*This
= impl_from_IFileSaveDialog(iface
);
3143 return IFileDialog2_SetFileName(&This
->IFileDialog2_iface
, pszName
);
3146 static HRESULT WINAPI
IFileSaveDialog_fnGetFileName(IFileSaveDialog
*iface
, LPWSTR
*pszName
)
3148 FileDialogImpl
*This
= impl_from_IFileSaveDialog(iface
);
3149 return IFileDialog2_GetFileName(&This
->IFileDialog2_iface
, pszName
);
3152 static HRESULT WINAPI
IFileSaveDialog_fnSetTitle(IFileSaveDialog
*iface
, LPCWSTR pszTitle
)
3154 FileDialogImpl
*This
= impl_from_IFileSaveDialog(iface
);
3155 return IFileDialog2_SetTitle(&This
->IFileDialog2_iface
, pszTitle
);
3158 static HRESULT WINAPI
IFileSaveDialog_fnSetOkButtonLabel(IFileSaveDialog
*iface
, LPCWSTR pszText
)
3160 FileDialogImpl
*This
= impl_from_IFileSaveDialog(iface
);
3161 return IFileDialog2_SetOkButtonLabel(&This
->IFileDialog2_iface
, pszText
);
3164 static HRESULT WINAPI
IFileSaveDialog_fnSetFileNameLabel(IFileSaveDialog
*iface
, LPCWSTR pszLabel
)
3166 FileDialogImpl
*This
= impl_from_IFileSaveDialog(iface
);
3167 return IFileDialog2_SetFileNameLabel(&This
->IFileDialog2_iface
, pszLabel
);
3170 static HRESULT WINAPI
IFileSaveDialog_fnGetResult(IFileSaveDialog
*iface
, IShellItem
**ppsi
)
3172 FileDialogImpl
*This
= impl_from_IFileSaveDialog(iface
);
3173 return IFileDialog2_GetResult(&This
->IFileDialog2_iface
, ppsi
);
3176 static HRESULT WINAPI
IFileSaveDialog_fnAddPlace(IFileSaveDialog
*iface
, IShellItem
*psi
, FDAP fdap
)
3178 FileDialogImpl
*This
= impl_from_IFileSaveDialog(iface
);
3179 return IFileDialog2_AddPlace(&This
->IFileDialog2_iface
, psi
, fdap
);
3182 static HRESULT WINAPI
IFileSaveDialog_fnSetDefaultExtension(IFileSaveDialog
*iface
,
3183 LPCWSTR pszDefaultExtension
)
3185 FileDialogImpl
*This
= impl_from_IFileSaveDialog(iface
);
3186 return IFileDialog2_SetDefaultExtension(&This
->IFileDialog2_iface
, pszDefaultExtension
);
3189 static HRESULT WINAPI
IFileSaveDialog_fnClose(IFileSaveDialog
*iface
, HRESULT hr
)
3191 FileDialogImpl
*This
= impl_from_IFileSaveDialog(iface
);
3192 return IFileDialog2_Close(&This
->IFileDialog2_iface
, hr
);
3195 static HRESULT WINAPI
IFileSaveDialog_fnSetClientGuid(IFileSaveDialog
*iface
, REFGUID guid
)
3197 FileDialogImpl
*This
= impl_from_IFileSaveDialog(iface
);
3198 return IFileDialog2_SetClientGuid(&This
->IFileDialog2_iface
, guid
);
3201 static HRESULT WINAPI
IFileSaveDialog_fnClearClientData(IFileSaveDialog
*iface
)
3203 FileDialogImpl
*This
= impl_from_IFileSaveDialog(iface
);
3204 return IFileDialog2_ClearClientData(&This
->IFileDialog2_iface
);
3207 static HRESULT WINAPI
IFileSaveDialog_fnSetFilter(IFileSaveDialog
*iface
, IShellItemFilter
*pFilter
)
3209 FileDialogImpl
*This
= impl_from_IFileSaveDialog(iface
);
3210 return IFileDialog2_SetFilter(&This
->IFileDialog2_iface
, pFilter
);
3213 static HRESULT WINAPI
IFileSaveDialog_fnSetSaveAsItem(IFileSaveDialog
* iface
, IShellItem
*psi
)
3215 FileDialogImpl
*This
= impl_from_IFileSaveDialog(iface
);
3216 FIXME("stub - %p (%p)\n", This
, psi
);
3220 static HRESULT WINAPI
IFileSaveDialog_fnSetProperties(IFileSaveDialog
* iface
, IPropertyStore
*pStore
)
3222 FileDialogImpl
*This
= impl_from_IFileSaveDialog(iface
);
3223 FIXME("stub - %p (%p)\n", This
, pStore
);
3227 static HRESULT WINAPI
IFileSaveDialog_fnSetCollectedProperties(IFileSaveDialog
* iface
,
3228 IPropertyDescriptionList
*pList
,
3229 BOOL fAppendDefault
)
3231 FileDialogImpl
*This
= impl_from_IFileSaveDialog(iface
);
3232 FIXME("stub - %p (%p, %d)\n", This
, pList
, fAppendDefault
);
3236 static HRESULT WINAPI
IFileSaveDialog_fnGetProperties(IFileSaveDialog
* iface
, IPropertyStore
**ppStore
)
3238 FileDialogImpl
*This
= impl_from_IFileSaveDialog(iface
);
3239 FIXME("stub - %p (%p)\n", This
, ppStore
);
3243 static HRESULT WINAPI
IFileSaveDialog_fnApplyProperties(IFileSaveDialog
* iface
,
3245 IPropertyStore
*pStore
,
3247 IFileOperationProgressSink
*pSink
)
3249 FileDialogImpl
*This
= impl_from_IFileSaveDialog(iface
);
3250 FIXME("%p (%p, %p, %p, %p)\n", This
, psi
, pStore
, hwnd
, pSink
);
3254 static const IFileSaveDialogVtbl vt_IFileSaveDialog
= {
3255 IFileSaveDialog_fnQueryInterface
,
3256 IFileSaveDialog_fnAddRef
,
3257 IFileSaveDialog_fnRelease
,
3258 IFileSaveDialog_fnShow
,
3259 IFileSaveDialog_fnSetFileTypes
,
3260 IFileSaveDialog_fnSetFileTypeIndex
,
3261 IFileSaveDialog_fnGetFileTypeIndex
,
3262 IFileSaveDialog_fnAdvise
,
3263 IFileSaveDialog_fnUnadvise
,
3264 IFileSaveDialog_fnSetOptions
,
3265 IFileSaveDialog_fnGetOptions
,
3266 IFileSaveDialog_fnSetDefaultFolder
,
3267 IFileSaveDialog_fnSetFolder
,
3268 IFileSaveDialog_fnGetFolder
,
3269 IFileSaveDialog_fnGetCurrentSelection
,
3270 IFileSaveDialog_fnSetFileName
,
3271 IFileSaveDialog_fnGetFileName
,
3272 IFileSaveDialog_fnSetTitle
,
3273 IFileSaveDialog_fnSetOkButtonLabel
,
3274 IFileSaveDialog_fnSetFileNameLabel
,
3275 IFileSaveDialog_fnGetResult
,
3276 IFileSaveDialog_fnAddPlace
,
3277 IFileSaveDialog_fnSetDefaultExtension
,
3278 IFileSaveDialog_fnClose
,
3279 IFileSaveDialog_fnSetClientGuid
,
3280 IFileSaveDialog_fnClearClientData
,
3281 IFileSaveDialog_fnSetFilter
,
3282 IFileSaveDialog_fnSetSaveAsItem
,
3283 IFileSaveDialog_fnSetProperties
,
3284 IFileSaveDialog_fnSetCollectedProperties
,
3285 IFileSaveDialog_fnGetProperties
,
3286 IFileSaveDialog_fnApplyProperties
3289 /**************************************************************************
3290 * IExplorerBrowserEvents implementation
3292 static inline FileDialogImpl
*impl_from_IExplorerBrowserEvents(IExplorerBrowserEvents
*iface
)
3294 return CONTAINING_RECORD(iface
, FileDialogImpl
, IExplorerBrowserEvents_iface
);
3297 static HRESULT WINAPI
IExplorerBrowserEvents_fnQueryInterface(IExplorerBrowserEvents
*iface
,
3298 REFIID riid
, void **ppvObject
)
3300 FileDialogImpl
*This
= impl_from_IExplorerBrowserEvents(iface
);
3301 TRACE("%p (%s, %p)\n", This
, debugstr_guid(riid
), ppvObject
);
3303 return IFileDialog2_QueryInterface(&This
->IFileDialog2_iface
, riid
, ppvObject
);
3306 static ULONG WINAPI
IExplorerBrowserEvents_fnAddRef(IExplorerBrowserEvents
*iface
)
3308 FileDialogImpl
*This
= impl_from_IExplorerBrowserEvents(iface
);
3309 TRACE("%p\n", This
);
3310 return IFileDialog2_AddRef(&This
->IFileDialog2_iface
);
3313 static ULONG WINAPI
IExplorerBrowserEvents_fnRelease(IExplorerBrowserEvents
*iface
)
3315 FileDialogImpl
*This
= impl_from_IExplorerBrowserEvents(iface
);
3316 TRACE("%p\n", This
);
3317 return IFileDialog2_Release(&This
->IFileDialog2_iface
);
3320 static HRESULT WINAPI
IExplorerBrowserEvents_fnOnNavigationPending(IExplorerBrowserEvents
*iface
,
3321 PCIDLIST_ABSOLUTE pidlFolder
)
3323 FileDialogImpl
*This
= impl_from_IExplorerBrowserEvents(iface
);
3326 TRACE("%p (%p)\n", This
, pidlFolder
);
3328 hr
= SHCreateItemFromIDList(pidlFolder
, &IID_IShellItem
, (void**)&psi
);
3331 hr
= events_OnFolderChanging(This
, psi
);
3332 IShellItem_Release(psi
);
3334 /* The ExplorerBrowser treats S_FALSE as S_OK, we don't. */
3341 ERR("Failed to convert pidl (%p) to a shellitem.\n", pidlFolder
);
3346 static HRESULT WINAPI
IExplorerBrowserEvents_fnOnViewCreated(IExplorerBrowserEvents
*iface
,
3349 FileDialogImpl
*This
= impl_from_IExplorerBrowserEvents(iface
);
3350 TRACE("%p (%p)\n", This
, psv
);
3354 static HRESULT WINAPI
IExplorerBrowserEvents_fnOnNavigationComplete(IExplorerBrowserEvents
*iface
,
3355 PCIDLIST_ABSOLUTE pidlFolder
)
3357 FileDialogImpl
*This
= impl_from_IExplorerBrowserEvents(iface
);
3359 TRACE("%p (%p)\n", This
, pidlFolder
);
3361 if(This
->psi_folder
)
3362 IShellItem_Release(This
->psi_folder
);
3364 hr
= SHCreateItemFromIDList(pidlFolder
, &IID_IShellItem
, (void**)&This
->psi_folder
);
3367 ERR("Failed to get the current folder.\n");
3368 This
->psi_folder
= NULL
;
3371 events_OnFolderChange(This
);
3376 static HRESULT WINAPI
IExplorerBrowserEvents_fnOnNavigationFailed(IExplorerBrowserEvents
*iface
,
3377 PCIDLIST_ABSOLUTE pidlFolder
)
3379 FileDialogImpl
*This
= impl_from_IExplorerBrowserEvents(iface
);
3380 TRACE("%p (%p)\n", This
, pidlFolder
);
3384 static const IExplorerBrowserEventsVtbl vt_IExplorerBrowserEvents
= {
3385 IExplorerBrowserEvents_fnQueryInterface
,
3386 IExplorerBrowserEvents_fnAddRef
,
3387 IExplorerBrowserEvents_fnRelease
,
3388 IExplorerBrowserEvents_fnOnNavigationPending
,
3389 IExplorerBrowserEvents_fnOnViewCreated
,
3390 IExplorerBrowserEvents_fnOnNavigationComplete
,
3391 IExplorerBrowserEvents_fnOnNavigationFailed
3394 /**************************************************************************
3395 * IServiceProvider implementation
3397 static inline FileDialogImpl
*impl_from_IServiceProvider(IServiceProvider
*iface
)
3399 return CONTAINING_RECORD(iface
, FileDialogImpl
, IServiceProvider_iface
);
3402 static HRESULT WINAPI
IServiceProvider_fnQueryInterface(IServiceProvider
*iface
,
3403 REFIID riid
, void **ppvObject
)
3405 FileDialogImpl
*This
= impl_from_IServiceProvider(iface
);
3406 TRACE("%p\n", This
);
3407 return IFileDialog2_QueryInterface(&This
->IFileDialog2_iface
, riid
, ppvObject
);
3410 static ULONG WINAPI
IServiceProvider_fnAddRef(IServiceProvider
*iface
)
3412 FileDialogImpl
*This
= impl_from_IServiceProvider(iface
);
3413 TRACE("%p\n", This
);
3414 return IFileDialog2_AddRef(&This
->IFileDialog2_iface
);
3417 static ULONG WINAPI
IServiceProvider_fnRelease(IServiceProvider
*iface
)
3419 FileDialogImpl
*This
= impl_from_IServiceProvider(iface
);
3420 TRACE("%p\n", This
);
3421 return IFileDialog2_Release(&This
->IFileDialog2_iface
);
3424 static HRESULT WINAPI
IServiceProvider_fnQueryService(IServiceProvider
*iface
,
3425 REFGUID guidService
,
3426 REFIID riid
, void **ppv
)
3428 FileDialogImpl
*This
= impl_from_IServiceProvider(iface
);
3429 HRESULT hr
= E_NOTIMPL
;
3430 TRACE("%p (%s, %s, %p)\n", This
, debugstr_guid(guidService
), debugstr_guid(riid
), ppv
);
3433 if(IsEqualGUID(guidService
, &SID_STopLevelBrowser
) && This
->peb
)
3434 hr
= IExplorerBrowser_QueryInterface(This
->peb
, riid
, ppv
);
3435 else if(IsEqualGUID(guidService
, &SID_SExplorerBrowserFrame
))
3436 hr
= IFileDialog2_QueryInterface(&This
->IFileDialog2_iface
, riid
, ppv
);
3438 FIXME("Interface %s requested from unknown service %s\n",
3439 debugstr_guid(riid
), debugstr_guid(guidService
));
3444 static const IServiceProviderVtbl vt_IServiceProvider
= {
3445 IServiceProvider_fnQueryInterface
,
3446 IServiceProvider_fnAddRef
,
3447 IServiceProvider_fnRelease
,
3448 IServiceProvider_fnQueryService
3451 /**************************************************************************
3452 * ICommDlgBrowser3 implementation
3454 static inline FileDialogImpl
*impl_from_ICommDlgBrowser3(ICommDlgBrowser3
*iface
)
3456 return CONTAINING_RECORD(iface
, FileDialogImpl
, ICommDlgBrowser3_iface
);
3459 static HRESULT WINAPI
ICommDlgBrowser3_fnQueryInterface(ICommDlgBrowser3
*iface
,
3460 REFIID riid
, void **ppvObject
)
3462 FileDialogImpl
*This
= impl_from_ICommDlgBrowser3(iface
);
3463 TRACE("%p\n", This
);
3464 return IFileDialog2_QueryInterface(&This
->IFileDialog2_iface
, riid
, ppvObject
);
3467 static ULONG WINAPI
ICommDlgBrowser3_fnAddRef(ICommDlgBrowser3
*iface
)
3469 FileDialogImpl
*This
= impl_from_ICommDlgBrowser3(iface
);
3470 TRACE("%p\n", This
);
3471 return IFileDialog2_AddRef(&This
->IFileDialog2_iface
);
3474 static ULONG WINAPI
ICommDlgBrowser3_fnRelease(ICommDlgBrowser3
*iface
)
3476 FileDialogImpl
*This
= impl_from_ICommDlgBrowser3(iface
);
3477 TRACE("%p\n", This
);
3478 return IFileDialog2_Release(&This
->IFileDialog2_iface
);
3481 static HRESULT WINAPI
ICommDlgBrowser3_fnOnDefaultCommand(ICommDlgBrowser3
*iface
,
3484 FileDialogImpl
*This
= impl_from_ICommDlgBrowser3(iface
);
3486 TRACE("%p (%p)\n", This
, shv
);
3488 hr
= on_default_action(This
);
3491 EndDialog(This
->dlg_hwnd
, S_OK
);
3496 static HRESULT WINAPI
ICommDlgBrowser3_fnOnStateChange(ICommDlgBrowser3
*iface
,
3497 IShellView
*shv
, ULONG uChange
)
3499 FileDialogImpl
*This
= impl_from_ICommDlgBrowser3(iface
);
3500 IDataObject
*new_selection
;
3502 TRACE("%p (%p, %lx)\n", This
, shv
, uChange
);
3506 case CDBOSC_SELCHANGE
:
3507 if(This
->psia_selection
)
3509 IShellItemArray_Release(This
->psia_selection
);
3510 This
->psia_selection
= NULL
;
3513 hr
= IShellView_GetItemObject(shv
, SVGIO_SELECTION
, &IID_IDataObject
, (void**)&new_selection
);
3516 hr
= SHCreateShellItemArrayFromDataObject(new_selection
, &IID_IShellItemArray
,
3517 (void**)&This
->psia_selection
);
3520 fill_filename_from_selection(This
);
3521 events_OnSelectionChange(This
);
3524 IDataObject_Release(new_selection
);
3528 TRACE("Unhandled state change\n");
3533 static HRESULT WINAPI
ICommDlgBrowser3_fnIncludeObject(ICommDlgBrowser3
*iface
,
3534 IShellView
*shv
, LPCITEMIDLIST pidl
)
3536 FileDialogImpl
*This
= impl_from_ICommDlgBrowser3(iface
);
3539 LPITEMIDLIST parent_pidl
;
3542 TRACE("%p (%p, %p)\n", This
, shv
, pidl
);
3544 if(!This
->filterspec_count
&& !(This
->options
& FOS_PICKFOLDERS
))
3547 hr
= SHGetIDListFromObject((IUnknown
*)shv
, &parent_pidl
);
3550 LPITEMIDLIST full_pidl
= ILCombine(parent_pidl
, pidl
);
3551 hr
= SHCreateItemFromIDList(full_pidl
, &IID_IShellItem
, (void**)&psi
);
3552 ILFree(parent_pidl
);
3557 ERR("Failed to get shellitem (%08lx).\n", hr
);
3561 hr
= IShellItem_GetAttributes(psi
, SFGAO_FOLDER
|SFGAO_LINK
, &attr
);
3562 if(FAILED(hr
) || (attr
& (SFGAO_FOLDER
| SFGAO_LINK
)))
3564 IShellItem_Release(psi
);
3568 if((This
->options
& FOS_PICKFOLDERS
) && !(attr
& (SFGAO_FOLDER
| SFGAO_LINK
)))
3570 IShellItem_Release(psi
);
3575 if(SUCCEEDED(IShellItem_GetDisplayName(psi
, SIGDN_PARENTRELATIVEPARSING
, &filename
)))
3577 if(!PathMatchSpecW(filename
, This
->filterspecs
[This
->filetypeindex
].pszSpec
))
3579 CoTaskMemFree(filename
);
3582 IShellItem_Release(psi
);
3586 static HRESULT WINAPI
ICommDlgBrowser3_fnNotify(ICommDlgBrowser3
*iface
,
3587 IShellView
*ppshv
, DWORD dwNotifyType
)
3589 FileDialogImpl
*This
= impl_from_ICommDlgBrowser3(iface
);
3590 FIXME("Stub: %p (%p, 0x%lx)\n", This
, ppshv
, dwNotifyType
);
3594 static HRESULT WINAPI
ICommDlgBrowser3_fnGetDefaultMenuText(ICommDlgBrowser3
*iface
,
3596 LPWSTR pszText
, int cchMax
)
3598 FileDialogImpl
*This
= impl_from_ICommDlgBrowser3(iface
);
3599 FIXME("Stub: %p (%p, %p, %d)\n", This
, pshv
, pszText
, cchMax
);
3603 static HRESULT WINAPI
ICommDlgBrowser3_fnGetViewFlags(ICommDlgBrowser3
*iface
, DWORD
*pdwFlags
)
3605 FileDialogImpl
*This
= impl_from_ICommDlgBrowser3(iface
);
3606 FIXME("Stub: %p (%p)\n", This
, pdwFlags
);
3610 static HRESULT WINAPI
ICommDlgBrowser3_fnOnColumnClicked(ICommDlgBrowser3
*iface
,
3611 IShellView
*pshv
, int iColumn
)
3613 FileDialogImpl
*This
= impl_from_ICommDlgBrowser3(iface
);
3614 FIXME("Stub: %p (%p, %d)\n", This
, pshv
, iColumn
);
3618 static HRESULT WINAPI
ICommDlgBrowser3_fnGetCurrentFilter(ICommDlgBrowser3
*iface
,
3619 LPWSTR pszFileSpec
, int cchFileSpec
)
3621 FileDialogImpl
*This
= impl_from_ICommDlgBrowser3(iface
);
3622 FIXME("Stub: %p (%p, %d)\n", This
, pszFileSpec
, cchFileSpec
);
3626 static HRESULT WINAPI
ICommDlgBrowser3_fnOnPreviewCreated(ICommDlgBrowser3
*iface
,
3629 FileDialogImpl
*This
= impl_from_ICommDlgBrowser3(iface
);
3630 FIXME("Stub: %p (%p)\n", This
, pshv
);
3634 static const ICommDlgBrowser3Vtbl vt_ICommDlgBrowser3
= {
3635 ICommDlgBrowser3_fnQueryInterface
,
3636 ICommDlgBrowser3_fnAddRef
,
3637 ICommDlgBrowser3_fnRelease
,
3638 ICommDlgBrowser3_fnOnDefaultCommand
,
3639 ICommDlgBrowser3_fnOnStateChange
,
3640 ICommDlgBrowser3_fnIncludeObject
,
3641 ICommDlgBrowser3_fnNotify
,
3642 ICommDlgBrowser3_fnGetDefaultMenuText
,
3643 ICommDlgBrowser3_fnGetViewFlags
,
3644 ICommDlgBrowser3_fnOnColumnClicked
,
3645 ICommDlgBrowser3_fnGetCurrentFilter
,
3646 ICommDlgBrowser3_fnOnPreviewCreated
3649 /**************************************************************************
3650 * IOleWindow implementation
3652 static inline FileDialogImpl
*impl_from_IOleWindow(IOleWindow
*iface
)
3654 return CONTAINING_RECORD(iface
, FileDialogImpl
, IOleWindow_iface
);
3657 static HRESULT WINAPI
IOleWindow_fnQueryInterface(IOleWindow
*iface
, REFIID riid
, void **ppvObject
)
3659 FileDialogImpl
*This
= impl_from_IOleWindow(iface
);
3660 return IFileDialog2_QueryInterface(&This
->IFileDialog2_iface
, riid
, ppvObject
);
3663 static ULONG WINAPI
IOleWindow_fnAddRef(IOleWindow
*iface
)
3665 FileDialogImpl
*This
= impl_from_IOleWindow(iface
);
3666 return IFileDialog2_AddRef(&This
->IFileDialog2_iface
);
3669 static ULONG WINAPI
IOleWindow_fnRelease(IOleWindow
*iface
)
3671 FileDialogImpl
*This
= impl_from_IOleWindow(iface
);
3672 return IFileDialog2_Release(&This
->IFileDialog2_iface
);
3675 static HRESULT WINAPI
IOleWindow_fnContextSensitiveHelp(IOleWindow
*iface
, BOOL fEnterMOde
)
3677 FileDialogImpl
*This
= impl_from_IOleWindow(iface
);
3678 FIXME("Stub: %p (%d)\n", This
, fEnterMOde
);
3682 static HRESULT WINAPI
IOleWindow_fnGetWindow(IOleWindow
*iface
, HWND
*phwnd
)
3684 FileDialogImpl
*This
= impl_from_IOleWindow(iface
);
3685 TRACE("%p (%p)\n", This
, phwnd
);
3686 *phwnd
= This
->dlg_hwnd
;
3690 static const IOleWindowVtbl vt_IOleWindow
= {
3691 IOleWindow_fnQueryInterface
,
3692 IOleWindow_fnAddRef
,
3693 IOleWindow_fnRelease
,
3694 IOleWindow_fnGetWindow
,
3695 IOleWindow_fnContextSensitiveHelp
3698 /**************************************************************************
3699 * IFileDialogCustomize implementation
3701 static inline FileDialogImpl
*impl_from_IFileDialogCustomize(IFileDialogCustomize
*iface
)
3703 return CONTAINING_RECORD(iface
, FileDialogImpl
, IFileDialogCustomize_iface
);
3706 static HRESULT WINAPI
IFileDialogCustomize_fnQueryInterface(IFileDialogCustomize
*iface
,
3707 REFIID riid
, void **ppvObject
)
3709 FileDialogImpl
*This
= impl_from_IFileDialogCustomize(iface
);
3710 return IFileDialog2_QueryInterface(&This
->IFileDialog2_iface
, riid
, ppvObject
);
3713 static ULONG WINAPI
IFileDialogCustomize_fnAddRef(IFileDialogCustomize
*iface
)
3715 FileDialogImpl
*This
= impl_from_IFileDialogCustomize(iface
);
3716 return IFileDialog2_AddRef(&This
->IFileDialog2_iface
);
3719 static ULONG WINAPI
IFileDialogCustomize_fnRelease(IFileDialogCustomize
*iface
)
3721 FileDialogImpl
*This
= impl_from_IFileDialogCustomize(iface
);
3722 return IFileDialog2_Release(&This
->IFileDialog2_iface
);
3725 static HRESULT WINAPI
IFileDialogCustomize_fnEnableOpenDropDown(IFileDialogCustomize
*iface
,
3728 FileDialogImpl
*This
= impl_from_IFileDialogCustomize(iface
);
3730 TRACE("%p (%ld)\n", This
, dwIDCtl
);
3732 if (This
->hmenu_opendropdown
|| get_cctrl(This
, dwIDCtl
))
3733 return E_UNEXPECTED
;
3735 This
->hmenu_opendropdown
= CreatePopupMenu();
3737 if (!This
->hmenu_opendropdown
)
3738 return E_OUTOFMEMORY
;
3740 mi
.cbSize
= sizeof(mi
);
3741 mi
.fMask
= MIM_STYLE
;
3742 mi
.dwStyle
= MNS_NOTIFYBYPOS
;
3743 SetMenuInfo(This
->hmenu_opendropdown
, &mi
);
3745 This
->cctrl_opendropdown
.hwnd
= NULL
;
3746 This
->cctrl_opendropdown
.wrapper_hwnd
= NULL
;
3747 This
->cctrl_opendropdown
.id
= dwIDCtl
;
3748 This
->cctrl_opendropdown
.dlgid
= 0;
3749 This
->cctrl_opendropdown
.type
= IDLG_CCTRL_OPENDROPDOWN
;
3750 This
->cctrl_opendropdown
.cdcstate
= CDCS_ENABLED
| CDCS_VISIBLE
;
3751 list_init(&This
->cctrl_opendropdown
.sub_cctrls
);
3752 list_init(&This
->cctrl_opendropdown
.sub_items
);
3757 static HRESULT WINAPI
IFileDialogCustomize_fnAddMenu(IFileDialogCustomize
*iface
,
3761 FileDialogImpl
*This
= impl_from_IFileDialogCustomize(iface
);
3765 TRACE("%p (%ld, %p)\n", This
, dwIDCtl
, pszLabel
);
3767 hr
= cctrl_create_new(This
, dwIDCtl
, NULL
, TOOLBARCLASSNAMEW
,
3768 TBSTYLE_FLAT
| CCS_NODIVIDER
, 0,
3769 This
->cctrl_def_height
, &ctrl
);
3772 SendMessageW(ctrl
->hwnd
, TB_BUTTONSTRUCTSIZE
, sizeof(tbb
), 0);
3773 ctrl
->type
= IDLG_CCTRL_MENU
;
3775 /* Add the actual button with a popup menu. */
3776 tbb
.iBitmap
= I_IMAGENONE
;
3777 tbb
.dwData
= (DWORD_PTR
)CreatePopupMenu();
3778 tbb
.iString
= (DWORD_PTR
)pszLabel
;
3779 tbb
.fsState
= TBSTATE_ENABLED
;
3780 tbb
.fsStyle
= BTNS_WHOLEDROPDOWN
;
3783 SendMessageW(ctrl
->hwnd
, TB_ADDBUTTONSW
, 1, (LPARAM
)&tbb
);
3789 static HRESULT WINAPI
IFileDialogCustomize_fnAddPushButton(IFileDialogCustomize
*iface
,
3793 FileDialogImpl
*This
= impl_from_IFileDialogCustomize(iface
);
3796 TRACE("%p (%ld, %p)\n", This
, dwIDCtl
, pszLabel
);
3798 hr
= cctrl_create_new(This
, dwIDCtl
, pszLabel
, WC_BUTTONW
, BS_MULTILINE
, 0,
3799 This
->cctrl_def_height
, &ctrl
);
3801 ctrl
->type
= IDLG_CCTRL_PUSHBUTTON
;
3806 static HRESULT WINAPI
IFileDialogCustomize_fnAddComboBox(IFileDialogCustomize
*iface
,
3809 FileDialogImpl
*This
= impl_from_IFileDialogCustomize(iface
);
3812 TRACE("%p (%ld)\n", This
, dwIDCtl
);
3814 hr
= cctrl_create_new(This
, dwIDCtl
, NULL
, WC_COMBOBOXW
, CBS_DROPDOWNLIST
, 0,
3815 This
->cctrl_def_height
, &ctrl
);
3817 ctrl
->type
= IDLG_CCTRL_COMBOBOX
;
3822 static HRESULT WINAPI
IFileDialogCustomize_fnAddRadioButtonList(IFileDialogCustomize
*iface
,
3825 FileDialogImpl
*This
= impl_from_IFileDialogCustomize(iface
);
3828 TRACE("%p (%ld)\n", This
, dwIDCtl
);
3830 hr
= cctrl_create_new(This
, dwIDCtl
, NULL
, L
"RadioButtonList", 0, 0, 0, &ctrl
);
3833 ctrl
->type
= IDLG_CCTRL_RADIOBUTTONLIST
;
3834 SetWindowLongPtrW(ctrl
->hwnd
, GWLP_USERDATA
, (LPARAM
)This
);
3840 static HRESULT WINAPI
IFileDialogCustomize_fnAddCheckButton(IFileDialogCustomize
*iface
,
3845 FileDialogImpl
*This
= impl_from_IFileDialogCustomize(iface
);
3848 TRACE("%p (%ld, %p, %d)\n", This
, dwIDCtl
, pszLabel
, bChecked
);
3850 hr
= cctrl_create_new(This
, dwIDCtl
, pszLabel
, WC_BUTTONW
, BS_AUTOCHECKBOX
|BS_MULTILINE
, 0,
3851 This
->cctrl_def_height
, &ctrl
);
3854 ctrl
->type
= IDLG_CCTRL_CHECKBUTTON
;
3855 SendMessageW(ctrl
->hwnd
, BM_SETCHECK
, bChecked
? BST_CHECKED
: BST_UNCHECKED
, 0);
3861 static HRESULT WINAPI
IFileDialogCustomize_fnAddEditBox(IFileDialogCustomize
*iface
,
3865 FileDialogImpl
*This
= impl_from_IFileDialogCustomize(iface
);
3868 TRACE("%p (%ld, %p)\n", This
, dwIDCtl
, pszText
);
3870 hr
= cctrl_create_new(This
, dwIDCtl
, pszText
, WC_EDITW
, ES_AUTOHSCROLL
, WS_EX_CLIENTEDGE
,
3871 This
->cctrl_def_height
, &ctrl
);
3873 ctrl
->type
= IDLG_CCTRL_EDITBOX
;
3878 static HRESULT WINAPI
IFileDialogCustomize_fnAddSeparator(IFileDialogCustomize
*iface
,
3881 FileDialogImpl
*This
= impl_from_IFileDialogCustomize(iface
);
3884 TRACE("%p (%ld)\n", This
, dwIDCtl
);
3886 hr
= cctrl_create_new(This
, dwIDCtl
, NULL
, WC_STATICW
, SS_ETCHEDHORZ
, 0,
3887 GetSystemMetrics(SM_CYEDGE
), &ctrl
);
3889 ctrl
->type
= IDLG_CCTRL_SEPARATOR
;
3894 static HRESULT WINAPI
IFileDialogCustomize_fnAddText(IFileDialogCustomize
*iface
,
3898 FileDialogImpl
*This
= impl_from_IFileDialogCustomize(iface
);
3901 TRACE("%p (%ld, %p)\n", This
, dwIDCtl
, pszText
);
3903 hr
= cctrl_create_new(This
, dwIDCtl
, pszText
, WC_STATICW
, 0, 0,
3904 This
->cctrl_def_height
, &ctrl
);
3906 ctrl
->type
= IDLG_CCTRL_TEXT
;
3911 static HRESULT WINAPI
IFileDialogCustomize_fnSetControlLabel(IFileDialogCustomize
*iface
,
3915 FileDialogImpl
*This
= impl_from_IFileDialogCustomize(iface
);
3916 customctrl
*ctrl
= get_cctrl(This
, dwIDCtl
);
3917 TRACE("%p (%ld, %p)\n", This
, dwIDCtl
, pszLabel
);
3919 if(!ctrl
) return E_INVALIDARG
;
3923 case IDLG_CCTRL_MENU
:
3924 case IDLG_CCTRL_PUSHBUTTON
:
3925 case IDLG_CCTRL_CHECKBUTTON
:
3926 case IDLG_CCTRL_TEXT
:
3927 case IDLG_CCTRL_VISUALGROUP
:
3928 SendMessageW(ctrl
->hwnd
, WM_SETTEXT
, 0, (LPARAM
)pszLabel
);
3930 case IDLG_CCTRL_OPENDROPDOWN
:
3939 static HRESULT WINAPI
IFileDialogCustomize_fnGetControlState(IFileDialogCustomize
*iface
,
3941 CDCONTROLSTATEF
*pdwState
)
3943 FileDialogImpl
*This
= impl_from_IFileDialogCustomize(iface
);
3944 customctrl
*ctrl
= get_cctrl(This
, dwIDCtl
);
3945 TRACE("%p (%ld, %p)\n", This
, dwIDCtl
, pdwState
);
3947 if(!ctrl
|| ctrl
->type
== IDLG_CCTRL_OPENDROPDOWN
) return E_NOTIMPL
;
3949 *pdwState
= ctrl
->cdcstate
;
3953 static HRESULT WINAPI
IFileDialogCustomize_fnSetControlState(IFileDialogCustomize
*iface
,
3955 CDCONTROLSTATEF dwState
)
3957 FileDialogImpl
*This
= impl_from_IFileDialogCustomize(iface
);
3958 customctrl
*ctrl
= get_cctrl(This
,dwIDCtl
);
3959 TRACE("%p (%ld, %x)\n", This
, dwIDCtl
, dwState
);
3961 if(ctrl
&& ctrl
->hwnd
)
3963 LONG wndstyle
= GetWindowLongW(ctrl
->hwnd
, GWL_STYLE
);
3965 if(dwState
& CDCS_ENABLED
)
3966 wndstyle
&= ~(WS_DISABLED
);
3968 wndstyle
|= WS_DISABLED
;
3970 if(dwState
& CDCS_VISIBLE
)
3971 wndstyle
|= WS_VISIBLE
;
3973 wndstyle
&= ~(WS_VISIBLE
);
3975 SetWindowLongW(ctrl
->hwnd
, GWL_STYLE
, wndstyle
);
3977 /* We save the state separately since at least one application
3978 * relies on being able to hide a control. */
3979 ctrl
->cdcstate
= dwState
;
3985 static HRESULT WINAPI
IFileDialogCustomize_fnGetEditBoxText(IFileDialogCustomize
*iface
,
3989 FileDialogImpl
*This
= impl_from_IFileDialogCustomize(iface
);
3990 customctrl
*ctrl
= get_cctrl(This
, dwIDCtl
);
3992 TRACE("%p (%ld, %p)\n", This
, dwIDCtl
, ppszText
);
3994 if(!ctrl
|| !ctrl
->hwnd
|| !(len
= SendMessageW(ctrl
->hwnd
, WM_GETTEXTLENGTH
, 0, 0)))
3997 text
= CoTaskMemAlloc(sizeof(WCHAR
)*(len
+1));
3998 if(!text
) return E_FAIL
;
4000 SendMessageW(ctrl
->hwnd
, WM_GETTEXT
, len
+1, (LPARAM
)text
);
4005 static HRESULT WINAPI
IFileDialogCustomize_fnSetEditBoxText(IFileDialogCustomize
*iface
,
4009 FileDialogImpl
*This
= impl_from_IFileDialogCustomize(iface
);
4010 customctrl
*ctrl
= get_cctrl(This
, dwIDCtl
);
4011 TRACE("%p (%ld, %s)\n", This
, dwIDCtl
, debugstr_w(pszText
));
4013 if(!ctrl
|| ctrl
->type
!= IDLG_CCTRL_EDITBOX
)
4016 SendMessageW(ctrl
->hwnd
, WM_SETTEXT
, 0, (LPARAM
)pszText
);
4020 static HRESULT WINAPI
IFileDialogCustomize_fnGetCheckButtonState(IFileDialogCustomize
*iface
,
4024 FileDialogImpl
*This
= impl_from_IFileDialogCustomize(iface
);
4025 customctrl
*ctrl
= get_cctrl(This
, dwIDCtl
);
4026 TRACE("%p (%ld, %p)\n", This
, dwIDCtl
, pbChecked
);
4028 if(ctrl
&& ctrl
->hwnd
)
4029 *pbChecked
= (SendMessageW(ctrl
->hwnd
, BM_GETCHECK
, 0, 0) == BST_CHECKED
);
4034 static HRESULT WINAPI
IFileDialogCustomize_fnSetCheckButtonState(IFileDialogCustomize
*iface
,
4038 FileDialogImpl
*This
= impl_from_IFileDialogCustomize(iface
);
4039 customctrl
*ctrl
= get_cctrl(This
, dwIDCtl
);
4040 TRACE("%p (%ld, %d)\n", This
, dwIDCtl
, bChecked
);
4042 if(ctrl
&& ctrl
->hwnd
)
4043 SendMessageW(ctrl
->hwnd
, BM_SETCHECK
, bChecked
? BST_CHECKED
:BST_UNCHECKED
, 0);
4048 static UINT
get_combobox_index_from_id(HWND cb_hwnd
, DWORD dwIDItem
)
4050 UINT count
= SendMessageW(cb_hwnd
, CB_GETCOUNT
, 0, 0);
4052 if(!count
|| (count
== CB_ERR
))
4055 for(i
= 0; i
< count
; i
++)
4056 if(SendMessageW(cb_hwnd
, CB_GETITEMDATA
, i
, 0) == dwIDItem
)
4059 TRACE("Item with id %ld not found in combobox %p (item count: %d)\n", dwIDItem
, cb_hwnd
, count
);
4063 static HRESULT WINAPI
IFileDialogCustomize_fnAddControlItem(IFileDialogCustomize
*iface
,
4068 FileDialogImpl
*This
= impl_from_IFileDialogCustomize(iface
);
4069 customctrl
*ctrl
= get_cctrl(This
, dwIDCtl
);
4071 TRACE("%p (%ld, %ld, %s)\n", This
, dwIDCtl
, dwIDItem
, debugstr_w(pszLabel
));
4073 if(!ctrl
) return E_FAIL
;
4077 case IDLG_CCTRL_COMBOBOX
:
4082 hr
= add_item(ctrl
, dwIDItem
, pszLabel
, &item
);
4084 if (FAILED(hr
)) return hr
;
4086 index
= SendMessageW(ctrl
->hwnd
, CB_ADDSTRING
, 0, (LPARAM
)pszLabel
);
4087 SendMessageW(ctrl
->hwnd
, CB_SETITEMDATA
, index
, dwIDItem
);
4091 case IDLG_CCTRL_MENU
:
4092 case IDLG_CCTRL_OPENDROPDOWN
:
4097 hr
= add_item(ctrl
, dwIDItem
, pszLabel
, &item
);
4099 if (FAILED(hr
)) return hr
;
4101 if (ctrl
->type
== IDLG_CCTRL_MENU
)
4104 SendMessageW(ctrl
->hwnd
, TB_GETBUTTON
, 0, (LPARAM
)&tbb
);
4105 hmenu
= (HMENU
)tbb
.dwData
;
4107 else /* ctrl->type == IDLG_CCTRL_OPENDROPDOWN */
4108 hmenu
= This
->hmenu_opendropdown
;
4110 AppendMenuW(hmenu
, MF_STRING
, dwIDItem
, pszLabel
);
4113 case IDLG_CCTRL_RADIOBUTTONLIST
:
4117 hr
= add_item(ctrl
, dwIDItem
, pszLabel
, &item
);
4121 item
->hwnd
= CreateWindowExW(0, WC_BUTTONW
, pszLabel
,
4122 WS_CHILD
|WS_VISIBLE
|WS_CLIPSIBLINGS
|BS_RADIOBUTTON
|BS_MULTILINE
,
4123 0, 0, 0, 0, ctrl
->hwnd
, ULongToHandle(dwIDItem
), COMDLG32_hInstance
, 0);
4127 ERR("Failed to create radio button\n");
4128 list_remove(&item
->entry
);
4140 return E_NOINTERFACE
; /* win7 */
4143 static HRESULT WINAPI
IFileDialogCustomize_fnRemoveControlItem(IFileDialogCustomize
*iface
,
4147 FileDialogImpl
*This
= impl_from_IFileDialogCustomize(iface
);
4148 customctrl
*ctrl
= get_cctrl(This
, dwIDCtl
);
4149 TRACE("%p (%ld, %ld)\n", This
, dwIDCtl
, dwIDItem
);
4151 if(!ctrl
) return E_FAIL
;
4155 case IDLG_CCTRL_COMBOBOX
:
4160 item
= get_item(ctrl
, dwIDItem
, CDCS_VISIBLE
|CDCS_ENABLED
, &position
);
4163 return E_INVALIDARG
;
4165 if ((item
->cdcstate
& (CDCS_VISIBLE
|CDCS_ENABLED
)) == (CDCS_VISIBLE
|CDCS_ENABLED
))
4167 if(SendMessageW(ctrl
->hwnd
, CB_DELETESTRING
, position
, 0) == CB_ERR
)
4171 list_remove(&item
->entry
);
4176 case IDLG_CCTRL_MENU
:
4177 case IDLG_CCTRL_OPENDROPDOWN
:
4182 item
= get_item(ctrl
, dwIDItem
, 0, NULL
);
4185 return E_UNEXPECTED
;
4187 if (item
->cdcstate
& CDCS_VISIBLE
)
4189 if (ctrl
->type
== IDLG_CCTRL_MENU
)
4192 SendMessageW(ctrl
->hwnd
, TB_GETBUTTON
, 0, (LPARAM
)&tbb
);
4193 hmenu
= (HMENU
)tbb
.dwData
;
4195 else /* ctrl->type == IDLG_CCTRL_OPENDROPDOWN */
4196 hmenu
= This
->hmenu_opendropdown
;
4198 if(!hmenu
|| !DeleteMenu(hmenu
, dwIDItem
, MF_BYCOMMAND
))
4199 return E_UNEXPECTED
;
4202 list_remove(&item
->entry
);
4207 case IDLG_CCTRL_RADIOBUTTONLIST
:
4211 item
= get_item(ctrl
, dwIDItem
, 0, NULL
);
4214 return E_UNEXPECTED
;
4216 list_remove(&item
->entry
);
4228 static HRESULT WINAPI
IFileDialogCustomize_fnRemoveAllControlItems(IFileDialogCustomize
*iface
,
4231 FileDialogImpl
*This
= impl_from_IFileDialogCustomize(iface
);
4232 TRACE("%p (%ld)\n", This
, dwIDCtl
);
4234 /* Not implemented by native */
4238 static HRESULT WINAPI
IFileDialogCustomize_fnGetControlItemState(IFileDialogCustomize
*iface
,
4241 CDCONTROLSTATEF
*pdwState
)
4243 FileDialogImpl
*This
= impl_from_IFileDialogCustomize(iface
);
4244 customctrl
*ctrl
= get_cctrl(This
, dwIDCtl
);
4245 TRACE("%p (%ld, %ld, %p)\n", This
, dwIDCtl
, dwIDItem
, pdwState
);
4247 if(!ctrl
) return E_FAIL
;
4251 case IDLG_CCTRL_COMBOBOX
:
4252 case IDLG_CCTRL_MENU
:
4253 case IDLG_CCTRL_OPENDROPDOWN
:
4254 case IDLG_CCTRL_RADIOBUTTONLIST
:
4258 item
= get_item(ctrl
, dwIDItem
, 0, NULL
);
4261 return E_UNEXPECTED
;
4263 *pdwState
= item
->cdcstate
;
4274 static HRESULT WINAPI
IFileDialogCustomize_fnSetControlItemState(IFileDialogCustomize
*iface
,
4277 CDCONTROLSTATEF dwState
)
4279 FileDialogImpl
*This
= impl_from_IFileDialogCustomize(iface
);
4280 customctrl
*ctrl
= get_cctrl(This
, dwIDCtl
);
4281 TRACE("%p (%ld, %ld, %x)\n", This
, dwIDCtl
, dwIDItem
, dwState
);
4283 if(!ctrl
) return E_FAIL
;
4287 case IDLG_CCTRL_COMBOBOX
:
4290 BOOL visible
, was_visible
;
4293 item
= get_item(ctrl
, dwIDItem
, CDCS_VISIBLE
|CDCS_ENABLED
, &position
);
4296 return E_UNEXPECTED
;
4298 visible
= ((dwState
& (CDCS_VISIBLE
|CDCS_ENABLED
)) == (CDCS_VISIBLE
|CDCS_ENABLED
));
4299 was_visible
= ((item
->cdcstate
& (CDCS_VISIBLE
|CDCS_ENABLED
)) == (CDCS_VISIBLE
|CDCS_ENABLED
));
4301 if (visible
&& !was_visible
)
4303 SendMessageW(ctrl
->hwnd
, CB_INSERTSTRING
, position
, (LPARAM
)item
->label
);
4304 SendMessageW(ctrl
->hwnd
, CB_SETITEMDATA
, position
, dwIDItem
);
4306 else if (!visible
&& was_visible
)
4308 SendMessageW(ctrl
->hwnd
, CB_DELETESTRING
, position
, 0);
4311 item
->cdcstate
= dwState
;
4315 case IDLG_CCTRL_MENU
:
4316 case IDLG_CCTRL_OPENDROPDOWN
:
4320 CDCONTROLSTATEF prev_state
;
4323 item
= get_item(ctrl
, dwIDItem
, CDCS_VISIBLE
, &position
);
4326 return E_UNEXPECTED
;
4328 prev_state
= item
->cdcstate
;
4330 if (ctrl
->type
== IDLG_CCTRL_MENU
)
4333 SendMessageW(ctrl
->hwnd
, TB_GETBUTTON
, 0, (LPARAM
)&tbb
);
4334 hmenu
= (HMENU
)tbb
.dwData
;
4336 else /* ctrl->type == IDLG_CCTRL_OPENDROPDOWN */
4337 hmenu
= This
->hmenu_opendropdown
;
4339 if (dwState
& CDCS_VISIBLE
)
4341 if (prev_state
& CDCS_VISIBLE
)
4344 EnableMenuItem(hmenu
, dwIDItem
,
4345 MF_BYCOMMAND
|((dwState
& CDCS_ENABLED
) ? MFS_ENABLED
: MFS_DISABLED
));
4352 mii
.cbSize
= sizeof(mii
);
4353 mii
.fMask
= MIIM_ID
|MIIM_STATE
|MIIM_STRING
;
4354 mii
.fState
= (dwState
& CDCS_ENABLED
) ? MFS_ENABLED
: MFS_DISABLED
;
4356 mii
.dwTypeData
= item
->label
;
4358 InsertMenuItemW(hmenu
, position
, TRUE
, &mii
);
4361 else if (prev_state
& CDCS_VISIBLE
)
4364 DeleteMenu(hmenu
, dwIDItem
, MF_BYCOMMAND
);
4367 item
->cdcstate
= dwState
;
4369 if (ctrl
->type
== IDLG_CCTRL_OPENDROPDOWN
)
4371 update_control_text(This
);
4372 update_layout(This
);
4377 case IDLG_CCTRL_RADIOBUTTONLIST
:
4381 item
= get_item(ctrl
, dwIDItem
, CDCS_VISIBLE
, NULL
);
4384 return E_UNEXPECTED
;
4386 /* Oddly, native allows setting this but doesn't seem to do anything with it. */
4387 item
->cdcstate
= dwState
;
4398 static HRESULT WINAPI
IFileDialogCustomize_fnGetSelectedControlItem(IFileDialogCustomize
*iface
,
4402 FileDialogImpl
*This
= impl_from_IFileDialogCustomize(iface
);
4403 customctrl
*ctrl
= get_cctrl(This
, dwIDCtl
);
4404 TRACE("%p (%ld, %p)\n", This
, dwIDCtl
, pdwIDItem
);
4406 if(!ctrl
) return E_FAIL
;
4410 case IDLG_CCTRL_COMBOBOX
:
4412 UINT index
= SendMessageW(ctrl
->hwnd
, CB_GETCURSEL
, 0, 0);
4416 *pdwIDItem
= SendMessageW(ctrl
->hwnd
, CB_GETITEMDATA
, index
, 0);
4419 case IDLG_CCTRL_OPENDROPDOWN
:
4420 if (This
->opendropdown_has_selection
)
4422 *pdwIDItem
= This
->opendropdown_selection
;
4427 /* Return first enabled item. */
4428 cctrl_item
* item
= get_first_item(ctrl
);
4432 *pdwIDItem
= item
->id
;
4436 WARN("no enabled items in open dropdown\n");
4439 case IDLG_CCTRL_RADIOBUTTONLIST
:
4443 LIST_FOR_EACH_ENTRY(item
, &ctrl
->sub_items
, cctrl_item
, entry
)
4445 if (SendMessageW(item
->hwnd
, BM_GETCHECK
, 0, 0) == BST_CHECKED
)
4447 *pdwIDItem
= item
->id
;
4452 WARN("no checked items in radio button list\n");
4456 FIXME("Unsupported control type %d\n", ctrl
->type
);
4462 static HRESULT WINAPI
IFileDialogCustomize_fnSetSelectedControlItem(IFileDialogCustomize
*iface
,
4466 FileDialogImpl
*This
= impl_from_IFileDialogCustomize(iface
);
4467 customctrl
*ctrl
= get_cctrl(This
, dwIDCtl
);
4468 TRACE("%p (%ld, %ld)\n", This
, dwIDCtl
, dwIDItem
);
4470 if(!ctrl
) return E_INVALIDARG
;
4474 case IDLG_CCTRL_COMBOBOX
:
4476 UINT index
= get_combobox_index_from_id(ctrl
->hwnd
, dwIDItem
);
4479 return E_INVALIDARG
;
4481 if(SendMessageW(ctrl
->hwnd
, CB_SETCURSEL
, index
, 0) == CB_ERR
)
4486 case IDLG_CCTRL_RADIOBUTTONLIST
:
4490 item
= get_item(ctrl
, dwIDItem
, 0, NULL
);
4494 radiobuttonlist_set_selected_item(This
, ctrl
, item
);
4498 return E_INVALIDARG
;
4501 FIXME("Unsupported control type %d\n", ctrl
->type
);
4504 return E_INVALIDARG
;
4507 static HRESULT WINAPI
IFileDialogCustomize_fnStartVisualGroup(IFileDialogCustomize
*iface
,
4511 FileDialogImpl
*This
= impl_from_IFileDialogCustomize(iface
);
4514 TRACE("%p (%ld, %s)\n", This
, dwIDCtl
, debugstr_w(pszLabel
));
4516 if(This
->cctrl_active_vg
)
4517 return E_UNEXPECTED
;
4519 hr
= cctrl_create_new(This
, dwIDCtl
, pszLabel
, WC_STATICW
, 0, 0,
4520 This
->cctrl_def_height
, &vg
);
4523 vg
->type
= IDLG_CCTRL_VISUALGROUP
;
4524 This
->cctrl_active_vg
= vg
;
4530 static HRESULT WINAPI
IFileDialogCustomize_fnEndVisualGroup(IFileDialogCustomize
*iface
)
4532 FileDialogImpl
*This
= impl_from_IFileDialogCustomize(iface
);
4533 TRACE("%p\n", This
);
4535 This
->cctrl_active_vg
= NULL
;
4540 static HRESULT WINAPI
IFileDialogCustomize_fnMakeProminent(IFileDialogCustomize
*iface
,
4543 FileDialogImpl
*This
= impl_from_IFileDialogCustomize(iface
);
4544 FIXME("stub - %p (%ld)\n", This
, dwIDCtl
);
4548 static HRESULT WINAPI
IFileDialogCustomize_fnSetControlItemText(IFileDialogCustomize
*iface
,
4553 FileDialogImpl
*This
= impl_from_IFileDialogCustomize(iface
);
4554 FIXME("stub - %p (%ld, %ld, %s)\n", This
, dwIDCtl
, dwIDItem
, debugstr_w(pszLabel
));
4558 static const IFileDialogCustomizeVtbl vt_IFileDialogCustomize
= {
4559 IFileDialogCustomize_fnQueryInterface
,
4560 IFileDialogCustomize_fnAddRef
,
4561 IFileDialogCustomize_fnRelease
,
4562 IFileDialogCustomize_fnEnableOpenDropDown
,
4563 IFileDialogCustomize_fnAddMenu
,
4564 IFileDialogCustomize_fnAddPushButton
,
4565 IFileDialogCustomize_fnAddComboBox
,
4566 IFileDialogCustomize_fnAddRadioButtonList
,
4567 IFileDialogCustomize_fnAddCheckButton
,
4568 IFileDialogCustomize_fnAddEditBox
,
4569 IFileDialogCustomize_fnAddSeparator
,
4570 IFileDialogCustomize_fnAddText
,
4571 IFileDialogCustomize_fnSetControlLabel
,
4572 IFileDialogCustomize_fnGetControlState
,
4573 IFileDialogCustomize_fnSetControlState
,
4574 IFileDialogCustomize_fnGetEditBoxText
,
4575 IFileDialogCustomize_fnSetEditBoxText
,
4576 IFileDialogCustomize_fnGetCheckButtonState
,
4577 IFileDialogCustomize_fnSetCheckButtonState
,
4578 IFileDialogCustomize_fnAddControlItem
,
4579 IFileDialogCustomize_fnRemoveControlItem
,
4580 IFileDialogCustomize_fnRemoveAllControlItems
,
4581 IFileDialogCustomize_fnGetControlItemState
,
4582 IFileDialogCustomize_fnSetControlItemState
,
4583 IFileDialogCustomize_fnGetSelectedControlItem
,
4584 IFileDialogCustomize_fnSetSelectedControlItem
,
4585 IFileDialogCustomize_fnStartVisualGroup
,
4586 IFileDialogCustomize_fnEndVisualGroup
,
4587 IFileDialogCustomize_fnMakeProminent
,
4588 IFileDialogCustomize_fnSetControlItemText
4591 static HRESULT
FileDialog_constructor(IUnknown
*pUnkOuter
, REFIID riid
, void **ppv
, enum ITEMDLG_TYPE type
)
4593 FileDialogImpl
*fdimpl
;
4596 TRACE("%p, %s, %p\n", pUnkOuter
, debugstr_guid(riid
), ppv
);
4601 return CLASS_E_NOAGGREGATION
;
4603 fdimpl
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(FileDialogImpl
));
4605 return E_OUTOFMEMORY
;
4608 fdimpl
->IFileDialog2_iface
.lpVtbl
= &vt_IFileDialog2
;
4609 fdimpl
->IExplorerBrowserEvents_iface
.lpVtbl
= &vt_IExplorerBrowserEvents
;
4610 fdimpl
->IServiceProvider_iface
.lpVtbl
= &vt_IServiceProvider
;
4611 fdimpl
->ICommDlgBrowser3_iface
.lpVtbl
= &vt_ICommDlgBrowser3
;
4612 fdimpl
->IOleWindow_iface
.lpVtbl
= &vt_IOleWindow
;
4613 fdimpl
->IFileDialogCustomize_iface
.lpVtbl
= &vt_IFileDialogCustomize
;
4615 if(type
== ITEMDLG_TYPE_OPEN
)
4617 fdimpl
->dlg_type
= ITEMDLG_TYPE_OPEN
;
4618 fdimpl
->u
.IFileOpenDialog_iface
.lpVtbl
= &vt_IFileOpenDialog
;
4619 fdimpl
->options
= FOS_PATHMUSTEXIST
| FOS_FILEMUSTEXIST
| FOS_NOCHANGEDIR
;
4620 fdimpl
->custom_title
= fdimpl
->custom_okbutton
= NULL
;
4625 fdimpl
->dlg_type
= ITEMDLG_TYPE_SAVE
;
4626 fdimpl
->u
.IFileSaveDialog_iface
.lpVtbl
= &vt_IFileSaveDialog
;
4627 fdimpl
->options
= FOS_OVERWRITEPROMPT
| FOS_NOREADONLYRETURN
| FOS_PATHMUSTEXIST
| FOS_NOCHANGEDIR
;
4629 LoadStringW(COMDLG32_hInstance
, IDS_SAVE
, buf
, ARRAY_SIZE(buf
));
4630 fdimpl
->custom_title
= StrDupW(buf
);
4631 fdimpl
->custom_okbutton
= StrDupW(buf
);
4634 list_init(&fdimpl
->events_clients
);
4636 /* FIXME: The default folder setting should be restored for the
4637 * application if it was previously set. */
4638 SHGetDesktopFolder(&psf
);
4639 SHGetItemFromObject((IUnknown
*)psf
, &IID_IShellItem
, (void**)&fdimpl
->psi_defaultfolder
);
4640 IShellFolder_Release(psf
);
4642 hr
= init_custom_controls(fdimpl
);
4645 ERR("Failed to initialize custom controls (0x%08lx).\n", hr
);
4646 IFileDialog2_Release(&fdimpl
->IFileDialog2_iface
);
4650 hr
= IFileDialog2_QueryInterface(&fdimpl
->IFileDialog2_iface
, riid
, ppv
);
4651 IFileDialog2_Release(&fdimpl
->IFileDialog2_iface
);
4655 HRESULT
FileOpenDialog_Constructor(IUnknown
*pUnkOuter
, REFIID riid
, void **ppv
)
4657 return FileDialog_constructor(pUnkOuter
, riid
, ppv
, ITEMDLG_TYPE_OPEN
);
4660 HRESULT
FileSaveDialog_Constructor(IUnknown
*pUnkOuter
, REFIID riid
, void **ppv
)
4662 return FileDialog_constructor(pUnkOuter
, riid
, ppv
, ITEMDLG_TYPE_SAVE
);