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
25 #define NONAMELESSSTRUCT
36 #include "filedlgbrowser.h"
38 #include "wine/debug.h"
39 #include "wine/list.h"
41 #define IDC_NAV_TOOLBAR 200
42 #define IDC_NAVBACK 201
43 #define IDC_NAVFORWARD 202
46 /* This seems to be another version of IID_IFileDialogCustomize. If
47 * there is any difference I have yet to find it. */
48 DEFINE_GUID(IID_IFileDialogCustomizeAlt, 0x8016B7B3, 0x3D49, 0x4504, 0xA0,0xAA, 0x2A,0x37,0x49,0x4E,0x60,0x6F);
50 WINE_DEFAULT_DEBUG_CHANNEL(commdlg);
52 static const WCHAR notifysink_childW[] = {'n','f','s','_','c','h','i','l','d',0};
53 static const WCHAR floatnotifysinkW[] = {'F','l','o','a','t','N','o','t','i','f','y','S','i','n','k',0};
60 enum ITEMDLG_CCTRL_TYPE {
62 IDLG_CCTRL_PUSHBUTTON,
64 IDLG_CCTRL_RADIOBUTTONLIST,
65 IDLG_CCTRL_CHECKBUTTON,
72 HWND hwnd, wrapper_hwnd;
74 enum ITEMDLG_CCTRL_TYPE type;
75 CDCONTROLSTATEF cdcstate;
81 IFileDialogEvents *pfde;
85 typedef struct FileDialogImpl {
86 IFileDialog2 IFileDialog2_iface;
88 IFileOpenDialog IFileOpenDialog_iface;
89 IFileSaveDialog IFileSaveDialog_iface;
91 enum ITEMDLG_TYPE dlg_type;
92 IExplorerBrowserEvents IExplorerBrowserEvents_iface;
93 IServiceProvider IServiceProvider_iface;
94 ICommDlgBrowser3 ICommDlgBrowser3_iface;
95 IOleWindow IOleWindow_iface;
96 IFileDialogCustomize IFileDialogCustomize_iface;
99 FILEOPENDIALOGOPTIONS options;
100 COMDLG_FILTERSPEC *filterspecs;
101 UINT filterspec_count;
104 struct list events_clients;
105 DWORD events_next_cookie;
107 IShellItemArray *psia_selection;
108 IShellItemArray *psia_results;
109 IShellItem *psi_defaultfolder;
110 IShellItem *psi_setfolder;
111 IShellItem *psi_folder;
114 IExplorerBrowser *peb;
115 DWORD ebevents_cookie;
120 LPWSTR custom_okbutton;
121 LPWSTR custom_cancelbutton;
122 LPWSTR custom_filenamelabel;
124 UINT cctrl_width, cctrl_def_height, cctrls_cols;
127 UINT_PTR cctrl_next_dlgid;
130 /**************************************************************************
133 static HRESULT events_OnFileOk(FileDialogImpl *This)
135 events_client *cursor;
139 LIST_FOR_EACH_ENTRY(cursor, &This->events_clients, events_client, entry)
141 TRACE("Notifying %p\n", cursor);
142 hr = IFileDialogEvents_OnFileOk(cursor->pfde, (IFileDialog*)&This->IFileDialog2_iface);
143 if(FAILED(hr) && hr != E_NOTIMPL)
153 static HRESULT events_OnFolderChanging(FileDialogImpl *This, IShellItem *folder)
155 events_client *cursor;
157 TRACE("%p (%p)\n", This, folder);
159 LIST_FOR_EACH_ENTRY(cursor, &This->events_clients, events_client, entry)
161 TRACE("Notifying %p\n", cursor);
162 hr = IFileDialogEvents_OnFolderChanging(cursor->pfde, (IFileDialog*)&This->IFileDialog2_iface, folder);
163 if(FAILED(hr) && hr != E_NOTIMPL)
173 static void events_OnFolderChange(FileDialogImpl *This)
175 events_client *cursor;
178 LIST_FOR_EACH_ENTRY(cursor, &This->events_clients, events_client, entry)
180 TRACE("Notifying %p\n", cursor);
181 IFileDialogEvents_OnFolderChange(cursor->pfde, (IFileDialog*)&This->IFileDialog2_iface);
185 static void events_OnSelectionChange(FileDialogImpl *This)
187 events_client *cursor;
190 LIST_FOR_EACH_ENTRY(cursor, &This->events_clients, events_client, entry)
192 TRACE("Notifying %p\n", cursor);
193 IFileDialogEvents_OnSelectionChange(cursor->pfde, (IFileDialog*)&This->IFileDialog2_iface);
197 static inline HRESULT get_cctrl_event(IFileDialogEvents *pfde, IFileDialogControlEvents **pfdce)
199 return IFileDialogEvents_QueryInterface(pfde, &IID_IFileDialogControlEvents, (void**)pfdce);
202 static HRESULT cctrl_event_OnButtonClicked(FileDialogImpl *This, DWORD ctl_id)
204 events_client *cursor;
207 LIST_FOR_EACH_ENTRY(cursor, &This->events_clients, events_client, entry)
209 IFileDialogControlEvents *pfdce;
210 if(SUCCEEDED(get_cctrl_event(cursor->pfde, &pfdce)))
212 TRACE("Notifying %p\n", cursor);
213 IFileDialogControlEvents_OnButtonClicked(pfdce, &This->IFileDialogCustomize_iface, ctl_id);
214 IFileDialogControlEvents_Release(pfdce);
221 static HRESULT cctrl_event_OnItemSelected(FileDialogImpl *This, DWORD ctl_id, DWORD item_id)
223 events_client *cursor;
226 LIST_FOR_EACH_ENTRY(cursor, &This->events_clients, events_client, entry)
228 IFileDialogControlEvents *pfdce;
229 if(SUCCEEDED(get_cctrl_event(cursor->pfde, &pfdce)))
231 TRACE("Notifying %p\n", cursor);
232 IFileDialogControlEvents_OnItemSelected(pfdce, &This->IFileDialogCustomize_iface, ctl_id, item_id);
233 IFileDialogControlEvents_Release(pfdce);
240 static HRESULT cctrl_event_OnCheckButtonToggled(FileDialogImpl *This, DWORD ctl_id, BOOL checked)
242 events_client *cursor;
245 LIST_FOR_EACH_ENTRY(cursor, &This->events_clients, events_client, entry)
247 IFileDialogControlEvents *pfdce;
248 if(SUCCEEDED(get_cctrl_event(cursor->pfde, &pfdce)))
250 TRACE("Notifying %p\n", cursor);
251 IFileDialogControlEvents_OnCheckButtonToggled(pfdce, &This->IFileDialogCustomize_iface, ctl_id, checked);
252 IFileDialogControlEvents_Release(pfdce);
259 static HRESULT cctrl_event_OnControlActivating(FileDialogImpl *This,
262 events_client *cursor;
265 LIST_FOR_EACH_ENTRY(cursor, &This->events_clients, events_client, entry)
267 IFileDialogControlEvents *pfdce;
268 if(SUCCEEDED(get_cctrl_event(cursor->pfde, &pfdce)))
270 TRACE("Notifying %p\n", cursor);
271 IFileDialogControlEvents_OnControlActivating(pfdce, &This->IFileDialogCustomize_iface, ctl_id);
272 IFileDialogControlEvents_Release(pfdce);
279 /**************************************************************************
282 static UINT get_file_name(FileDialogImpl *This, LPWSTR *str)
284 HWND hwnd_edit = GetDlgItem(This->dlg_hwnd, IDC_FILENAME);
289 if(This->set_filename)
291 len = lstrlenW(This->set_filename);
292 *str = CoTaskMemAlloc(sizeof(WCHAR)*(len+1));
293 lstrcpyW(*str, This->set_filename);
299 len = SendMessageW(hwnd_edit, WM_GETTEXTLENGTH, 0, 0);
300 *str = CoTaskMemAlloc(sizeof(WCHAR)*(len+1));
304 SendMessageW(hwnd_edit, WM_GETTEXT, len+1, (LPARAM)*str);
308 static BOOL set_file_name(FileDialogImpl *This, LPCWSTR str)
310 HWND hwnd_edit = GetDlgItem(This->dlg_hwnd, IDC_FILENAME);
312 if(This->set_filename)
313 LocalFree(This->set_filename);
315 This->set_filename = StrDupW(str);
317 return SendMessageW(hwnd_edit, WM_SETTEXT, 0, (LPARAM)str);
320 static void fill_filename_from_selection(FileDialogImpl *This)
325 UINT item_count, valid_count;
328 if(!This->psia_selection)
331 hr = IShellItemArray_GetCount(This->psia_selection, &item_count);
332 if(FAILED(hr) || !item_count)
335 names = HeapAlloc(GetProcessHeap(), 0, item_count*sizeof(LPWSTR));
337 /* Get names of the selected items */
338 valid_count = 0; len_total = 0;
339 for(i = 0; i < item_count; i++)
341 hr = IShellItemArray_GetItemAt(This->psia_selection, i, &psi);
346 hr = IShellItem_GetAttributes(psi, SFGAO_FOLDER, &attr);
347 if(SUCCEEDED(hr) && (attr & SFGAO_FOLDER))
348 continue; /* FIXME: FOS_PICKFOLDERS */
350 hr = IShellItem_GetDisplayName(psi, SIGDN_PARENTRELATIVEPARSING, &names[valid_count]);
353 len_total += lstrlenW(names[valid_count]) + 3;
356 IShellItem_Release(psi);
362 set_file_name(This, names[0]);
363 CoTaskMemFree(names[0]);
365 else if(valid_count > 1)
367 LPWSTR string = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR)*len_total);
368 LPWSTR cur_point = string;
370 for(i = 0; i < valid_count; i++)
372 LPWSTR file = names[i];
374 lstrcpyW(cur_point, file);
375 cur_point += lstrlenW(file);
380 *(cur_point-1) = '\0';
382 set_file_name(This, string);
383 HeapFree(GetProcessHeap(), 0, string);
386 HeapFree(GetProcessHeap(), 0, names);
390 static LPWSTR get_first_ext_from_spec(LPWSTR buf, LPCWSTR spec)
395 if( (endpos = StrChrW(buf, ';')) )
398 ext = PathFindExtensionW(buf);
399 if(StrChrW(ext, '*'))
405 static HRESULT on_default_action(FileDialogImpl *This)
407 IShellFolder *psf_parent, *psf_desktop;
409 LPITEMIDLIST current_folder;
410 LPWSTR fn_iter, files, tmp_files;
411 UINT file_count = 0, len, i;
413 HRESULT hr, ret = E_FAIL;
415 len = get_file_name(This, &tmp_files);
419 file_count = COMDLG32_SplitFileNames(tmp_files, len, &files, &size_used);
421 if(!file_count) return E_FAIL;
423 hr = SHGetIDListFromObject((IUnknown*)This->psi_folder, ¤t_folder);
426 ERR("Failed to get pidl for current directory.\n");
430 TRACE("Acting on %d file(s).\n", file_count);
432 pidla = HeapAlloc(GetProcessHeap(), 0, sizeof(LPITEMIDLIST) * file_count);
433 open_action = ONOPEN_OPEN;
436 for(i = 0; i < file_count && open_action == ONOPEN_OPEN; i++)
438 WCHAR canon_filename[MAX_PATH];
441 COMDLG32_GetCanonicalPath(current_folder, fn_iter, canon_filename);
443 if( (This->options & FOS_NOVALIDATE) &&
444 !(This->options & FOS_FILEMUSTEXIST) )
445 open_action = ONOPEN_OPEN;
447 open_action = ONOPEN_BROWSE;
449 open_action = FILEDLG95_ValidatePathAction(canon_filename, &psf_parent, This->dlg_hwnd,
450 This->options & ~FOS_FILEMUSTEXIST,
451 (This->dlg_type == ITEMDLG_TYPE_SAVE),
454 /* Add the proper extension */
455 if(open_action == ONOPEN_OPEN)
457 static const WCHAR dotW[] = {'.',0};
459 if(This->dlg_type == ITEMDLG_TYPE_SAVE)
461 WCHAR extbuf[MAX_PATH], *newext = NULL;
463 if(This->filterspec_count)
465 newext = get_first_ext_from_spec(extbuf, This->filterspecs[This->filetypeindex].pszSpec);
467 else if(This->default_ext)
469 lstrcpyW(extbuf, dotW);
470 lstrcatW(extbuf, This->default_ext);
476 WCHAR *ext = PathFindExtensionW(canon_filename);
477 if(lstrcmpW(ext, newext))
478 lstrcatW(canon_filename, newext);
483 if( !(This->options & FOS_NOVALIDATE) && (This->options & FOS_FILEMUSTEXIST) &&
484 !PathFileExistsW(canon_filename))
486 if(This->default_ext)
488 lstrcatW(canon_filename, dotW);
489 lstrcatW(canon_filename, This->default_ext);
491 if(!PathFileExistsW(canon_filename))
493 FILEDLG95_OnOpenMessage(This->dlg_hwnd, 0, IDS_FILENOTEXISTING);
494 open_action = ONOPEN_BROWSE;
499 FILEDLG95_OnOpenMessage(This->dlg_hwnd, 0, IDS_FILENOTEXISTING);
500 open_action = ONOPEN_BROWSE;
506 pidla[i] = COMDLG32_SHSimpleIDListFromPathAW(canon_filename);
508 if(psf_parent && !(open_action == ONOPEN_BROWSE))
509 IShellItem_Release(psf_parent);
511 fn_iter += (WCHAR)lstrlenW(fn_iter) + 1;
514 HeapFree(GetProcessHeap(), 0, files);
515 ILFree(current_folder);
517 if((This->options & FOS_PICKFOLDERS) && open_action == ONOPEN_BROWSE)
518 open_action = ONOPEN_OPEN; /* FIXME: Multiple folders? */
523 FIXME("Filtering not implemented.\n");
527 hr = IExplorerBrowser_BrowseToObject(This->peb, (IUnknown*)psf_parent, SBSP_DEFBROWSER);
529 ERR("Failed to browse to directory: %08x\n", hr);
531 IShellItem_Release(psf_parent);
535 if(events_OnFileOk(This) != S_OK)
538 hr = SHGetDesktopFolder(&psf_desktop);
541 if(This->psia_results)
542 IShellItemArray_Release(This->psia_results);
544 hr = SHCreateShellItemArray(NULL, psf_desktop, file_count, (PCUITEMID_CHILD_ARRAY)pidla,
545 &This->psia_results);
549 IShellFolder_Release(psf_desktop);
559 for(i = 0; i < file_count; i++)
561 HeapFree(GetProcessHeap(), 0, pidla);
563 /* Success closes the dialog */
567 /**************************************************************************
570 static inline customctrl *get_cctrl_from_dlgid(FileDialogImpl *This, DWORD dlgid)
574 LIST_FOR_EACH_ENTRY(ctrl, &This->cctrls, customctrl, entry)
575 if(ctrl->dlgid == dlgid)
578 ERR("Failed to find control with dialog id %d\n", dlgid);
582 static inline customctrl *get_cctrl(FileDialogImpl *This, DWORD ctlid)
586 LIST_FOR_EACH_ENTRY(ctrl, &This->cctrls, customctrl, entry)
587 if(ctrl->id == ctlid)
590 ERR("Failed to find control with control id %d\n", ctlid);
594 static void ctrl_resize(HWND hctrl, UINT min_width, UINT max_width, BOOL multiline)
597 UINT len, final_width;
598 UINT lines, final_height;
606 len = SendMessageW(hctrl, WM_GETTEXTLENGTH, 0, 0);
607 text = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR)*(len+1));
609 SendMessageW(hctrl, WM_GETTEXT, len+1, (LPARAM)text);
612 GetTextExtentPoint32W(hdc, text, lstrlenW(text), &size);
613 ReleaseDC(hctrl, hdc);
617 /* FIXME: line-wrap */
618 for(lines = 1, c = text; *c != '\0'; c++)
619 if(*c == '\n') lines++;
621 final_height = size.cy*lines + 2*4;
625 GetWindowRect(hctrl, &rc);
626 final_height = rc.bottom - rc.top;
629 final_width = min(max(size.cx, min_width) + 4, max_width);
630 SetWindowPos(hctrl, NULL, 0, 0, final_width, final_height,
631 SWP_NOZORDER | SWP_NOMOVE | SWP_NOACTIVATE);
633 HeapFree(GetProcessHeap(), 0, text);
636 static void customctrl_resize(FileDialogImpl *This, customctrl *ctrl)
642 case IDLG_CCTRL_PUSHBUTTON:
643 case IDLG_CCTRL_COMBOBOX:
644 case IDLG_CCTRL_CHECKBUTTON:
645 case IDLG_CCTRL_TEXT:
646 ctrl_resize(ctrl->hwnd, 160, 160, TRUE);
647 GetWindowRect(ctrl->hwnd, &rc);
648 SetWindowPos(ctrl->wrapper_hwnd, NULL, 0, 0, rc.right-rc.left, rc.bottom-rc.top,
649 SWP_NOZORDER|SWP_NOMOVE|SWP_NOZORDER);
650 case IDLG_CCTRL_RADIOBUTTONLIST:
651 case IDLG_CCTRL_EDITBOX:
652 case IDLG_CCTRL_SEPARATOR:
653 case IDLG_CCTRL_MENU:
659 static LRESULT notifysink_on_create(HWND hwnd, CREATESTRUCTW *crs)
661 FileDialogImpl *This = crs->lpCreateParams;
664 SetWindowLongPtrW(hwnd, GWLP_USERDATA, (LPARAM)This);
668 static LRESULT notifysink_on_bn_clicked(FileDialogImpl *This, HWND hwnd, WPARAM wparam)
670 customctrl *ctrl = get_cctrl_from_dlgid(This, LOWORD(wparam));
672 TRACE("%p, %lx\n", This, wparam);
676 if(ctrl->type == IDLG_CCTRL_CHECKBUTTON)
678 BOOL checked = (SendMessageW(ctrl->hwnd, BM_GETCHECK, 0, 0) == BST_CHECKED);
679 cctrl_event_OnCheckButtonToggled(This, ctrl->id, checked);
682 cctrl_event_OnButtonClicked(This, ctrl->id);
688 static LRESULT notifysink_on_cbn_selchange(FileDialogImpl *This, HWND hwnd, WPARAM wparam)
690 customctrl *ctrl = get_cctrl_from_dlgid(This, LOWORD(wparam));
691 TRACE("%p, %p (%lx)\n", This, ctrl, wparam);
695 UINT index = SendMessageW(ctrl->hwnd, CB_GETCURSEL, 0, 0);
696 UINT selid = SendMessageW(ctrl->hwnd, CB_GETITEMDATA, index, 0);
698 cctrl_event_OnItemSelected(This, ctrl->id, selid);
703 static LRESULT notifysink_on_tvn_dropdown(FileDialogImpl *This, LPARAM lparam)
705 NMTOOLBARW *nmtb = (NMTOOLBARW*)lparam;
706 customctrl *ctrl = get_cctrl_from_dlgid(This, GetDlgCtrlID(nmtb->hdr.hwndFrom));
707 POINT pt = { 0, nmtb->rcButton.bottom };
711 TRACE("%p, %p (%lx)\n", This, ctrl, lparam);
715 cctrl_event_OnControlActivating(This,ctrl->id);
717 SendMessageW(ctrl->hwnd, TB_GETBUTTON, 0, (LPARAM)&tbb);
718 ClientToScreen(ctrl->hwnd, &pt);
719 idcmd = TrackPopupMenu((HMENU)tbb.dwData, TPM_RETURNCMD, pt.x, pt.y, 0, This->dlg_hwnd, NULL);
721 cctrl_event_OnItemSelected(This, ctrl->id, idcmd);
724 return TBDDRET_DEFAULT;
727 static LRESULT notifysink_on_wm_command(FileDialogImpl *This, HWND hwnd, WPARAM wparam, LPARAM lparam)
729 switch(HIWORD(wparam))
731 case BN_CLICKED: return notifysink_on_bn_clicked(This, hwnd, wparam);
732 case CBN_SELCHANGE: return notifysink_on_cbn_selchange(This, hwnd, wparam);
738 static LRESULT notifysink_on_wm_notify(FileDialogImpl *This, HWND hwnd, WPARAM wparam, LPARAM lparam)
740 NMHDR *nmhdr = (NMHDR*)lparam;
744 case TBN_DROPDOWN: return notifysink_on_tvn_dropdown(This, lparam);
750 static LRESULT CALLBACK notifysink_proc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam)
752 FileDialogImpl *This = (FileDialogImpl*)GetWindowLongPtrW(hwnd, GWLP_USERDATA);
758 case WM_NCCREATE: return notifysink_on_create(hwnd, (CREATESTRUCTW*)lparam);
759 case WM_COMMAND: return notifysink_on_wm_command(This, hwnd, wparam, lparam);
760 case WM_NOTIFY: return notifysink_on_wm_notify(This, hwnd, wparam, lparam);
762 hwnd_child = GetPropW(hwnd, notifysink_childW);
763 GetClientRect(hwnd, &rc);
764 SetWindowPos(hwnd_child, NULL, 0, 0, rc.right, rc.bottom, SWP_NOMOVE|SWP_NOACTIVATE|SWP_NOZORDER);
768 return DefWindowProcW(hwnd, message, wparam, lparam);
771 static HRESULT cctrl_create_new(FileDialogImpl *This, DWORD id,
772 LPCWSTR text, LPCWSTR wndclass, DWORD ctrl_wsflags,
773 DWORD ctrl_exflags, UINT height, customctrl **ppctrl)
775 HWND ns_hwnd, control_hwnd;
776 DWORD wsflags = WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS;
779 if(get_cctrl(This, id))
780 return E_UNEXPECTED; /* Duplicate id */
782 ns_hwnd = CreateWindowExW(0, floatnotifysinkW, NULL, wsflags,
783 0, 0, This->cctrl_width, height, This->cctrls_hwnd,
784 (HMENU)This->cctrl_next_dlgid, COMDLG32_hInstance, This);
785 control_hwnd = CreateWindowExW(ctrl_exflags, wndclass, text, wsflags | ctrl_wsflags,
786 0, 0, This->cctrl_width, height, ns_hwnd,
787 (HMENU)This->cctrl_next_dlgid, COMDLG32_hInstance, 0);
789 if(!ns_hwnd || !control_hwnd)
791 ERR("Failed to create wrapper (%p) or control (%p)\n", ns_hwnd, control_hwnd);
792 DestroyWindow(ns_hwnd);
793 DestroyWindow(control_hwnd);
798 SetPropW(ns_hwnd, notifysink_childW, control_hwnd);
800 ctrl = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(customctrl));
802 return E_OUTOFMEMORY;
804 ctrl->hwnd = control_hwnd;
805 ctrl->wrapper_hwnd = ns_hwnd;
807 ctrl->dlgid = This->cctrl_next_dlgid;
808 ctrl->cdcstate = CDCS_ENABLED | CDCS_VISIBLE;
809 list_add_tail(&This->cctrls, &ctrl->entry);
810 if(ppctrl) *ppctrl = ctrl;
812 This->cctrl_next_dlgid++;
816 /**************************************************************************
817 * Container functions.
819 static UINT ctrl_container_resize(FileDialogImpl *This, UINT container_width)
821 UINT container_height;
824 UINT max_control_height, total_height = 0;
825 UINT cur_col_pos, cur_row_pos;
828 static const UINT col_indent = 100; /* The first column is indented 100px */
829 static const UINT cspacing = 90; /* Columns are spaced with 90px */
830 static const UINT rspacing = 4; /* Rows are spaced with 4 px. */
832 /* Given the new width of the container, this function determines the
833 * needed height of the container and places the controls according to
834 * the new layout. Returns the new height.
839 column_width = This->cctrl_width + cspacing;
840 nr_of_cols = (container_width - col_indent + cspacing) / column_width;
842 /* We don't need to do anything unless the number of visible columns has changed. */
843 if(nr_of_cols == This->cctrls_cols)
846 GetWindowRect(This->cctrls_hwnd, &rc);
847 return rc.bottom - rc.top;
850 This->cctrls_cols = nr_of_cols;
852 /* Get the size of the tallest control, and the total size of
853 * all the controls to figure out the number of slots we need.
855 max_control_height = 0;
856 LIST_FOR_EACH_ENTRY(ctrl, &This->cctrls, customctrl, entry)
858 if(ctrl->cdcstate & CDCS_VISIBLE)
862 GetWindowRect(ctrl->wrapper_hwnd, &rc);
863 control_height = rc.bottom - rc.top;
864 max_control_height = max(max_control_height, control_height);
866 total_height += control_height + rspacing;
873 container_height = max(total_height / nr_of_cols, max_control_height + rspacing);
874 TRACE("Guess: container_height: %d\n",container_height);
876 /* Incrementally increase container_height until all the controls
880 UINT columns_needed = 1;
884 LIST_FOR_EACH_ENTRY(ctrl, &This->cctrls, customctrl, entry)
886 if(ctrl->cdcstate & CDCS_VISIBLE)
890 GetWindowRect(ctrl->wrapper_hwnd, &rc);
891 control_height = rc.bottom - rc.top;
893 if(cur_row_pos + control_height > container_height)
895 if(++columns_needed > nr_of_cols)
897 container_height += 1;
904 cur_row_pos += control_height + rspacing;
907 } while(!fits_height);
909 TRACE("Final container height: %d\n", container_height);
911 /* Move the controls to their final destination
913 cur_col_pos = col_indent, cur_row_pos = 0;
914 LIST_FOR_EACH_ENTRY(ctrl, &This->cctrls, customctrl, entry)
916 if(ctrl->cdcstate & CDCS_VISIBLE)
920 GetWindowRect(ctrl->wrapper_hwnd, &rc);
921 control_height = rc.bottom - rc.top;
923 if(cur_row_pos + control_height > container_height)
926 cur_col_pos += This->cctrl_width + cspacing;
929 SetWindowPos(ctrl->wrapper_hwnd, NULL, cur_col_pos, cur_row_pos, 0, 0,
930 SWP_NOACTIVATE | SWP_NOSIZE | SWP_NOZORDER);
932 cur_row_pos += control_height + rspacing;
937 if(cur_row_pos + This->cctrl_width > container_width)
938 ERR("-- Failed to place controls properly.\n");
940 return container_height;
943 static void ctrl_container_reparent(FileDialogImpl *This, HWND parent)
952 wndstyle = GetWindowLongW(This->cctrls_hwnd, GWL_STYLE);
953 wndstyle &= ~(WS_POPUP);
954 wndstyle |= WS_CHILD;
955 SetWindowLongW(This->cctrls_hwnd, GWL_STYLE, wndstyle);
957 SetParent(This->cctrls_hwnd, parent);
958 ShowWindow(This->cctrls_hwnd, TRUE);
960 /* Set the fonts to match the dialog font. */
961 font = (HFONT)SendMessageW(parent, WM_GETFONT, 0, 0);
963 ERR("Failed to get font handle from dialog.\n");
965 LIST_FOR_EACH_ENTRY(ctrl, &This->cctrls, customctrl, entry)
967 if(font) SendMessageW(ctrl->hwnd, WM_SETFONT, (WPARAM)font, TRUE);
968 customctrl_resize(This, ctrl);
973 ShowWindow(This->cctrls_hwnd, FALSE);
975 wndstyle = GetWindowLongW(This->cctrls_hwnd, GWL_STYLE);
976 wndstyle &= ~(WS_CHILD);
977 wndstyle |= WS_POPUP;
978 SetWindowLongW(This->cctrls_hwnd, GWL_STYLE, wndstyle);
980 SetParent(This->cctrls_hwnd, NULL);
984 static LRESULT ctrl_container_on_create(HWND hwnd, CREATESTRUCTW *crs)
986 FileDialogImpl *This = crs->lpCreateParams;
989 SetWindowLongPtrW(hwnd, GWLP_USERDATA, (LPARAM)This);
993 static LRESULT ctrl_container_on_wm_destroy(FileDialogImpl *This)
995 customctrl *cur1, *cur2;
998 LIST_FOR_EACH_ENTRY_SAFE(cur1, cur2, &This->cctrls, customctrl, entry)
1000 TRACE("Freeing control %p\n", cur1);
1001 list_remove(&cur1->entry);
1003 if(cur1->type == IDLG_CCTRL_MENU)
1006 SendMessageW(cur1->hwnd, TB_GETBUTTON, 0, (LPARAM)&tbb);
1007 DestroyMenu((HMENU)tbb.dwData);
1010 DestroyWindow(cur1->hwnd);
1011 HeapFree(GetProcessHeap(), 0, cur1);
1017 static LRESULT CALLBACK ctrl_container_wndproc(HWND hwnd, UINT umessage, WPARAM wparam, LPARAM lparam)
1019 FileDialogImpl *This = (FileDialogImpl*)GetWindowLongPtrW(hwnd, GWLP_USERDATA);
1023 case WM_NCCREATE: return ctrl_container_on_create(hwnd, (CREATESTRUCTW*)lparam);
1024 case WM_DESTROY: return ctrl_container_on_wm_destroy(This);
1025 default: return DefWindowProcW(hwnd, umessage, wparam, lparam);
1031 static HRESULT init_custom_controls(FileDialogImpl *This)
1034 static const WCHAR ctrl_container_classname[] =
1035 {'i','d','l','g','_','c','o','n','t','a','i','n','e','r','_','p','a','n','e',0};
1037 InitCommonControlsEx(NULL);
1039 This->cctrl_width = 160; /* Controls have a fixed width */
1040 This->cctrl_def_height = 23;
1041 This->cctrls_cols = 0;
1043 This->cctrl_next_dlgid = 0x2000;
1044 list_init(&This->cctrls);
1046 if( !GetClassInfoW(COMDLG32_hInstance, ctrl_container_classname, &wc) )
1048 wc.style = CS_HREDRAW | CS_VREDRAW;
1049 wc.lpfnWndProc = ctrl_container_wndproc;
1052 wc.hInstance = COMDLG32_hInstance;
1054 wc.hCursor = LoadCursorW(0, (LPWSTR)IDC_ARROW);
1055 wc.hbrBackground = (HBRUSH)(COLOR_BTNFACE + 1);
1056 wc.lpszMenuName = NULL;
1057 wc.lpszClassName = ctrl_container_classname;
1059 if(!RegisterClassW(&wc)) return E_FAIL;
1062 This->cctrls_hwnd = CreateWindowExW(0, ctrl_container_classname, NULL,
1063 WS_CLIPSIBLINGS | WS_CLIPCHILDREN,
1064 0, 0, 0, 0, NULL, 0,
1065 COMDLG32_hInstance, (void*)This);
1066 if(!This->cctrls_hwnd)
1069 SetWindowLongW(This->cctrls_hwnd, GWL_STYLE, WS_TABSTOP);
1071 /* Register class for */
1072 if( !GetClassInfoW(COMDLG32_hInstance, floatnotifysinkW, &wc) ||
1073 wc.hInstance != COMDLG32_hInstance)
1075 wc.style = CS_HREDRAW | CS_VREDRAW;
1076 wc.lpfnWndProc = notifysink_proc;
1079 wc.hInstance = COMDLG32_hInstance;
1081 wc.hCursor = LoadCursorW(0, (LPWSTR)IDC_ARROW);
1082 wc.hbrBackground = (HBRUSH)(COLOR_BTNFACE + 1);
1083 wc.lpszMenuName = NULL;
1084 wc.lpszClassName = floatnotifysinkW;
1086 if (!RegisterClassW(&wc))
1087 ERR("Failed to register FloatNotifySink window class.\n");
1093 /**************************************************************************
1094 * Window related functions.
1096 static SIZE update_layout(FileDialogImpl *This)
1101 RECT cancel_rc, open_rc;
1102 RECT filetype_rc, filename_rc, filenamelabel_rc;
1103 RECT toolbar_rc, ebrowser_rc, customctrls_rc;
1104 int missing_width, missing_height;
1105 static const UINT vspacing = 4, hspacing = 4;
1108 GetClientRect(This->dlg_hwnd, &dialog_rc);
1110 missing_width = max(0, 320 - dialog_rc.right);
1111 missing_height = max(0, 200 - dialog_rc.bottom);
1113 if(missing_width || missing_height)
1115 TRACE("Missing (%d, %d)\n", missing_width, missing_height);
1116 ret.cx = missing_width;
1117 ret.cy = missing_height;
1122 * Calculate the size of the dialog and all the parts.
1126 hwnd = GetDlgItem(This->dlg_hwnd, IDCANCEL);
1129 int cancel_width, cancel_height;
1130 GetWindowRect(hwnd, &cancel_rc);
1131 cancel_width = cancel_rc.right - cancel_rc.left;
1132 cancel_height = cancel_rc.bottom - cancel_rc.top;
1134 cancel_rc.left = dialog_rc.right - cancel_width - hspacing;
1135 cancel_rc.top = dialog_rc.bottom - cancel_height - vspacing;
1136 cancel_rc.right = cancel_rc.left + cancel_width;
1137 cancel_rc.bottom = cancel_rc.top + cancel_height;
1140 /* Open/Save button */
1141 hwnd = GetDlgItem(This->dlg_hwnd, IDOK);
1144 int open_width, open_height;
1145 GetWindowRect(hwnd, &open_rc);
1146 open_width = open_rc.right - open_rc.left;
1147 open_height = open_rc.bottom - open_rc.top;
1149 open_rc.left = cancel_rc.left - open_width - hspacing;
1150 open_rc.top = cancel_rc.top;
1151 open_rc.right = open_rc.left + open_width;
1152 open_rc.bottom = open_rc.top + open_height;
1155 /* The filetype combobox. */
1156 hwnd = GetDlgItem(This->dlg_hwnd, IDC_FILETYPE);
1159 int filetype_width, filetype_height;
1160 GetWindowRect(hwnd, &filetype_rc);
1162 filetype_width = filetype_rc.right - filetype_rc.left;
1163 filetype_height = filetype_rc.bottom - filetype_rc.top;
1165 filetype_rc.right = cancel_rc.right;
1167 filetype_rc.left = filetype_rc.right - filetype_width;
1168 filetype_rc.top = cancel_rc.top - filetype_height - vspacing;
1169 filetype_rc.bottom = filetype_rc.top + filetype_height;
1171 if(!This->filterspec_count)
1172 filetype_rc.left = filetype_rc.right;
1175 /* Filename label. */
1176 hwnd = GetDlgItem(This->dlg_hwnd, IDC_FILENAMESTATIC);
1179 int filetypelabel_width, filetypelabel_height;
1180 GetWindowRect(hwnd, &filenamelabel_rc);
1182 filetypelabel_width = filenamelabel_rc.right - filenamelabel_rc.left;
1183 filetypelabel_height = filenamelabel_rc.bottom - filenamelabel_rc.top;
1185 filenamelabel_rc.left = 160; /* FIXME */
1186 filenamelabel_rc.top = filetype_rc.top;
1187 filenamelabel_rc.right = filenamelabel_rc.left + filetypelabel_width;
1188 filenamelabel_rc.bottom = filenamelabel_rc.top + filetypelabel_height;
1191 /* Filename edit box. */
1192 hwnd = GetDlgItem(This->dlg_hwnd, IDC_FILENAME);
1195 int filename_width, filename_height;
1196 GetWindowRect(hwnd, &filename_rc);
1198 filename_width = filetype_rc.left - filenamelabel_rc.right - hspacing*2;
1199 filename_height = filename_rc.bottom - filename_rc.top;
1201 filename_rc.left = filenamelabel_rc.right + hspacing;
1202 filename_rc.top = filetype_rc.top;
1203 filename_rc.right = filename_rc.left + filename_width;
1204 filename_rc.bottom = filename_rc.top + filename_height;
1207 hwnd = GetDlgItem(This->dlg_hwnd, IDC_NAV_TOOLBAR);
1210 GetWindowRect(hwnd, &toolbar_rc);
1211 MapWindowPoints(NULL, This->dlg_hwnd, (POINT*)&toolbar_rc, 2);
1214 /* The custom controls */
1215 customctrls_rc.left = dialog_rc.left + vspacing;
1216 customctrls_rc.right = dialog_rc.right - vspacing;
1217 customctrls_rc.bottom = filename_rc.top - hspacing;
1218 customctrls_rc.top = customctrls_rc.bottom -
1219 ctrl_container_resize(This, customctrls_rc.right - customctrls_rc.left);
1221 /* The ExplorerBrowser control. */
1222 ebrowser_rc.left = dialog_rc.left + vspacing;
1223 ebrowser_rc.top = toolbar_rc.bottom + vspacing;
1224 ebrowser_rc.right = dialog_rc.right - hspacing;
1225 ebrowser_rc.bottom = customctrls_rc.top - hspacing;
1228 * Move everything to the right place.
1231 /* FIXME: The Save Dialog uses a slightly different layout. */
1232 hdwp = BeginDeferWindowPos(7);
1234 if(hdwp && This->peb)
1235 IExplorerBrowser_SetRect(This->peb, &hdwp, ebrowser_rc);
1237 if(hdwp && This->cctrls_hwnd)
1238 DeferWindowPos(hdwp, This->cctrls_hwnd, NULL,
1239 customctrls_rc.left, customctrls_rc.top,
1240 customctrls_rc.right - customctrls_rc.left, customctrls_rc.bottom - customctrls_rc.top,
1241 SWP_NOZORDER | SWP_NOACTIVATE);
1243 /* The default controls */
1244 if(hdwp && (hwnd = GetDlgItem(This->dlg_hwnd, IDC_FILETYPE)) )
1245 DeferWindowPos(hdwp, hwnd, NULL, filetype_rc.left, filetype_rc.top, 0, 0,
1246 SWP_NOZORDER | SWP_NOSIZE | SWP_NOACTIVATE);
1248 if(hdwp && (hwnd = GetDlgItem(This->dlg_hwnd, IDC_FILENAME)) )
1249 DeferWindowPos(hdwp, hwnd, NULL, filename_rc.left, filename_rc.top,
1250 filename_rc.right - filename_rc.left, filename_rc.bottom - filename_rc.top,
1251 SWP_NOZORDER | SWP_NOACTIVATE);
1253 if(hdwp && (hwnd = GetDlgItem(This->dlg_hwnd, IDC_FILENAMESTATIC)) )
1254 DeferWindowPos(hdwp, hwnd, NULL, filenamelabel_rc.left, filenamelabel_rc.top, 0, 0,
1255 SWP_NOZORDER | SWP_NOSIZE | SWP_NOACTIVATE);
1257 if(hdwp && (hwnd = GetDlgItem(This->dlg_hwnd, IDOK)) )
1258 DeferWindowPos(hdwp, hwnd, NULL, open_rc.left, open_rc.top, 0, 0,
1259 SWP_NOZORDER | SWP_NOSIZE | SWP_NOACTIVATE);
1261 if(hdwp && (hwnd = GetDlgItem(This->dlg_hwnd, IDCANCEL)) )
1262 DeferWindowPos(hdwp, hwnd, NULL, cancel_rc.left, cancel_rc.top, 0, 0,
1263 SWP_NOZORDER | SWP_NOSIZE | SWP_NOACTIVATE);
1266 EndDeferWindowPos(hdwp);
1268 ERR("Failed to position dialog controls.\n");
1270 ret.cx = 0; ret.cy = 0;
1274 static HRESULT init_explorerbrowser(FileDialogImpl *This)
1276 IShellItem *psi_folder;
1281 /* Create ExplorerBrowser instance */
1282 OleInitialize(NULL);
1284 hr = CoCreateInstance(&CLSID_ExplorerBrowser, NULL, CLSCTX_INPROC_SERVER,
1285 &IID_IExplorerBrowser, (void**)&This->peb);
1288 ERR("Failed to instantiate ExplorerBrowser control.\n");
1292 IExplorerBrowser_SetOptions(This->peb, EBO_SHOWFRAMES);
1294 hr = IExplorerBrowser_Initialize(This->peb, This->dlg_hwnd, &rc, NULL);
1297 ERR("Failed to initialize the ExplorerBrowser control.\n");
1298 IExplorerBrowser_Release(This->peb);
1302 hr = IExplorerBrowser_Advise(This->peb, &This->IExplorerBrowserEvents_iface, &This->ebevents_cookie);
1304 ERR("Advise (ExplorerBrowser) failed.\n");
1306 /* Get previous options? */
1307 fos.ViewMode = fos.fFlags = 0;
1308 if(!(This->options & FOS_ALLOWMULTISELECT))
1309 fos.fFlags |= FWF_SINGLESEL;
1311 IExplorerBrowser_SetFolderSettings(This->peb, &fos);
1313 hr = IUnknown_SetSite((IUnknown*)This->peb, (IUnknown*)This);
1315 ERR("SetSite (ExplorerBrowser) failed.\n");
1317 /* Browse somewhere */
1318 psi_folder = This->psi_setfolder ? This->psi_setfolder : This->psi_defaultfolder;
1319 IExplorerBrowser_BrowseToObject(This->peb, (IUnknown*)psi_folder, SBSP_DEFBROWSER);
1324 static void init_toolbar(FileDialogImpl *This, HWND hwnd)
1330 htoolbar = CreateWindowExW(0, TOOLBARCLASSNAMEW, NULL, TBSTYLE_FLAT | WS_CHILD | WS_VISIBLE,
1332 hwnd, (HMENU)IDC_NAV_TOOLBAR, NULL, NULL);
1334 tbab.hInst = HINST_COMMCTRL;
1335 tbab.nID = IDB_HIST_LARGE_COLOR;
1336 SendMessageW(htoolbar, TB_ADDBITMAP, 0, (LPARAM)&tbab);
1338 button[0].iBitmap = HIST_BACK;
1339 button[0].idCommand = IDC_NAVBACK;
1340 button[0].fsState = TBSTATE_ENABLED;
1341 button[0].fsStyle = BTNS_BUTTON;
1342 button[0].dwData = 0;
1343 button[0].iString = 0;
1345 button[1].iBitmap = HIST_FORWARD;
1346 button[1].idCommand = IDC_NAVFORWARD;
1347 button[1].fsState = TBSTATE_ENABLED;
1348 button[1].fsStyle = BTNS_BUTTON;
1349 button[1].dwData = 0;
1350 button[1].iString = 0;
1352 SendMessageW(htoolbar, TB_ADDBUTTONSW, 2, (LPARAM)&button);
1353 SendMessageW(htoolbar, TB_SETBUTTONSIZE, 0, MAKELPARAM(24,24));
1354 SendMessageW(htoolbar, TB_AUTOSIZE, 0, 0);
1357 static void update_control_text(FileDialogImpl *This)
1360 if(This->custom_title)
1361 SetWindowTextW(This->dlg_hwnd, This->custom_title);
1363 if(This->custom_okbutton &&
1364 (hitem = GetDlgItem(This->dlg_hwnd, IDOK)))
1366 SetWindowTextW(hitem, This->custom_okbutton);
1367 ctrl_resize(hitem, 50, 250, FALSE);
1370 if(This->custom_cancelbutton &&
1371 (hitem = GetDlgItem(This->dlg_hwnd, IDCANCEL)))
1373 SetWindowTextW(hitem, This->custom_cancelbutton);
1374 ctrl_resize(hitem, 50, 250, FALSE);
1377 if(This->custom_filenamelabel &&
1378 (hitem = GetDlgItem(This->dlg_hwnd, IDC_FILENAMESTATIC)))
1380 SetWindowTextW(hitem, This->custom_filenamelabel);
1381 ctrl_resize(hitem, 50, 250, FALSE);
1385 static LRESULT on_wm_initdialog(HWND hwnd, LPARAM lParam)
1387 FileDialogImpl *This = (FileDialogImpl*)lParam;
1390 TRACE("(%p, %p)\n", This, hwnd);
1392 SetWindowLongPtrW(hwnd, GWLP_USERDATA, (LPARAM)This);
1393 This->dlg_hwnd = hwnd;
1395 hitem = GetDlgItem(This->dlg_hwnd, pshHelp);
1396 if(hitem) ShowWindow(hitem, SW_HIDE);
1398 hitem = GetDlgItem(This->dlg_hwnd, IDC_FILETYPESTATIC);
1399 if(hitem) ShowWindow(hitem, SW_HIDE);
1401 /* Fill filetypes combobox, or hide it. */
1402 hitem = GetDlgItem(This->dlg_hwnd, IDC_FILETYPE);
1403 if(This->filterspec_count)
1406 for(i = 0; i < This->filterspec_count; i++)
1407 SendMessageW(hitem, CB_ADDSTRING, 0, (LPARAM)This->filterspecs[i].pszName);
1409 SendMessageW(hitem, CB_SETCURSEL, This->filetypeindex, 0);
1412 ShowWindow(hitem, SW_HIDE);
1414 if(This->set_filename &&
1415 (hitem = GetDlgItem(This->dlg_hwnd, IDC_FILENAME)) )
1416 SendMessageW(hitem, WM_SETTEXT, 0, (LPARAM)This->set_filename);
1418 ctrl_container_reparent(This, This->dlg_hwnd);
1419 init_explorerbrowser(This);
1420 init_toolbar(This, hwnd);
1421 update_control_text(This);
1422 update_layout(This);
1427 static LRESULT on_wm_size(FileDialogImpl *This)
1429 update_layout(This);
1433 static LRESULT on_wm_getminmaxinfo(FileDialogImpl *This, LPARAM lparam)
1435 MINMAXINFO *mmi = (MINMAXINFO*)lparam;
1436 TRACE("%p (%p)\n", This, mmi);
1439 mmi->ptMinTrackSize.x = 640;
1440 mmi->ptMinTrackSize.y = 480;
1445 static LRESULT on_wm_destroy(FileDialogImpl *This)
1447 TRACE("%p\n", This);
1451 IExplorerBrowser_Destroy(This->peb);
1452 IExplorerBrowser_Release(This->peb);
1456 ctrl_container_reparent(This, NULL);
1457 This->dlg_hwnd = NULL;
1462 static LRESULT on_idok(FileDialogImpl *This)
1464 TRACE("%p\n", This);
1466 if(SUCCEEDED(on_default_action(This)))
1467 EndDialog(This->dlg_hwnd, S_OK);
1472 static LRESULT on_idcancel(FileDialogImpl *This)
1474 TRACE("%p\n", This);
1476 EndDialog(This->dlg_hwnd, HRESULT_FROM_WIN32(ERROR_CANCELLED));
1481 static LRESULT on_browse_back(FileDialogImpl *This)
1483 TRACE("%p\n", This);
1484 IExplorerBrowser_BrowseToIDList(This->peb, NULL, SBSP_NAVIGATEBACK);
1488 static LRESULT on_browse_forward(FileDialogImpl *This)
1490 TRACE("%p\n", This);
1491 IExplorerBrowser_BrowseToIDList(This->peb, NULL, SBSP_NAVIGATEFORWARD);
1495 static LRESULT on_command_filetype(FileDialogImpl *This, WPARAM wparam, LPARAM lparam)
1497 if(HIWORD(wparam) == CBN_SELCHANGE)
1502 UINT prev_index = This->filetypeindex;
1504 This->filetypeindex = SendMessageW((HWND)lparam, CB_GETCURSEL, 0, 0);
1505 TRACE("File type selection changed to %d.\n", This->filetypeindex);
1507 if(prev_index == This->filetypeindex)
1510 hr = IExplorerBrowser_GetCurrentView(This->peb, &IID_IShellView, (void**)&psv);
1513 IShellView_Refresh(psv);
1514 IShellView_Release(psv);
1517 if(This->dlg_type == ITEMDLG_TYPE_SAVE && get_file_name(This, &filename))
1519 WCHAR buf[MAX_PATH], extbuf[MAX_PATH], *ext;
1521 ext = get_first_ext_from_spec(extbuf, This->filterspecs[This->filetypeindex].pszSpec);
1524 lstrcpyW(buf, filename);
1526 if(PathMatchSpecW(buf, This->filterspecs[prev_index].pszSpec))
1527 PathRemoveExtensionW(buf);
1530 set_file_name(This, buf);
1532 CoTaskMemFree(filename);
1539 static LRESULT on_wm_command(FileDialogImpl *This, WPARAM wparam, LPARAM lparam)
1541 switch(LOWORD(wparam))
1543 case IDOK: return on_idok(This);
1544 case IDCANCEL: return on_idcancel(This);
1545 case IDC_NAVBACK: return on_browse_back(This);
1546 case IDC_NAVFORWARD: return on_browse_forward(This);
1547 case IDC_FILETYPE: return on_command_filetype(This, wparam, lparam);
1548 default: TRACE("Unknown command.\n");
1553 static LRESULT CALLBACK itemdlg_dlgproc(HWND hwnd, UINT umessage, WPARAM wparam, LPARAM lparam)
1555 FileDialogImpl *This = (FileDialogImpl*)GetWindowLongPtrW(hwnd, GWLP_USERDATA);
1559 case WM_INITDIALOG: return on_wm_initdialog(hwnd, lparam);
1560 case WM_COMMAND: return on_wm_command(This, wparam, lparam);
1561 case WM_SIZE: return on_wm_size(This);
1562 case WM_GETMINMAXINFO: return on_wm_getminmaxinfo(This, lparam);
1563 case WM_DESTROY: return on_wm_destroy(This);
1569 static HRESULT create_dialog(FileDialogImpl *This, HWND parent)
1574 res = DialogBoxParamW(COMDLG32_hInstance,
1575 MAKEINTRESOURCEW(NEWFILEOPENV3ORD),
1576 parent, itemdlg_dlgproc, (LPARAM)This);
1577 This->dlg_hwnd = NULL;
1580 ERR("Failed to show dialog (LastError: %d)\n", GetLastError());
1584 TRACE("Returning 0x%08x\n", (HRESULT)res);
1585 return (HRESULT)res;
1588 /**************************************************************************
1589 * IFileDialog implementation
1591 static inline FileDialogImpl *impl_from_IFileDialog2(IFileDialog2 *iface)
1593 return CONTAINING_RECORD(iface, FileDialogImpl, IFileDialog2_iface);
1596 static HRESULT WINAPI IFileDialog2_fnQueryInterface(IFileDialog2 *iface,
1600 FileDialogImpl *This = impl_from_IFileDialog2(iface);
1601 TRACE("%p (%s, %p)\n", This, debugstr_guid(riid), ppvObject);
1604 if(IsEqualGUID(riid, &IID_IUnknown) ||
1605 IsEqualGUID(riid, &IID_IFileDialog) ||
1606 IsEqualGUID(riid, &IID_IFileDialog2))
1610 else if(IsEqualGUID(riid, &IID_IFileOpenDialog) && This->dlg_type == ITEMDLG_TYPE_OPEN)
1612 *ppvObject = &This->u.IFileOpenDialog_iface;
1614 else if(IsEqualGUID(riid, &IID_IFileSaveDialog) && This->dlg_type == ITEMDLG_TYPE_SAVE)
1616 *ppvObject = &This->u.IFileSaveDialog_iface;
1618 else if(IsEqualGUID(riid, &IID_IExplorerBrowserEvents))
1620 *ppvObject = &This->IExplorerBrowserEvents_iface;
1622 else if(IsEqualGUID(riid, &IID_IServiceProvider))
1624 *ppvObject = &This->IServiceProvider_iface;
1626 else if(IsEqualGUID(&IID_ICommDlgBrowser3, riid) ||
1627 IsEqualGUID(&IID_ICommDlgBrowser2, riid) ||
1628 IsEqualGUID(&IID_ICommDlgBrowser, riid))
1630 *ppvObject = &This->ICommDlgBrowser3_iface;
1632 else if(IsEqualGUID(&IID_IOleWindow, riid))
1634 *ppvObject = &This->IOleWindow_iface;
1636 else if(IsEqualGUID(riid, &IID_IFileDialogCustomize) ||
1637 IsEqualGUID(riid, &IID_IFileDialogCustomizeAlt))
1639 *ppvObject = &This->IFileDialogCustomize_iface;
1642 FIXME("Unknown interface requested: %s.\n", debugstr_guid(riid));
1646 IUnknown_AddRef((IUnknown*)*ppvObject);
1650 return E_NOINTERFACE;
1653 static ULONG WINAPI IFileDialog2_fnAddRef(IFileDialog2 *iface)
1655 FileDialogImpl *This = impl_from_IFileDialog2(iface);
1656 LONG ref = InterlockedIncrement(&This->ref);
1657 TRACE("%p - ref %d\n", This, ref);
1662 static ULONG WINAPI IFileDialog2_fnRelease(IFileDialog2 *iface)
1664 FileDialogImpl *This = impl_from_IFileDialog2(iface);
1665 LONG ref = InterlockedDecrement(&This->ref);
1666 TRACE("%p - ref %d\n", This, ref);
1671 for(i = 0; i < This->filterspec_count; i++)
1673 LocalFree((void*)This->filterspecs[i].pszName);
1674 LocalFree((void*)This->filterspecs[i].pszSpec);
1676 HeapFree(GetProcessHeap(), 0, This->filterspecs);
1678 DestroyWindow(This->cctrls_hwnd);
1680 if(This->psi_defaultfolder) IShellItem_Release(This->psi_defaultfolder);
1681 if(This->psi_setfolder) IShellItem_Release(This->psi_setfolder);
1682 if(This->psi_folder) IShellItem_Release(This->psi_folder);
1683 if(This->psia_selection) IShellItemArray_Release(This->psia_selection);
1684 if(This->psia_results) IShellItemArray_Release(This->psia_results);
1686 LocalFree(This->set_filename);
1687 LocalFree(This->default_ext);
1688 LocalFree(This->custom_title);
1689 LocalFree(This->custom_okbutton);
1690 LocalFree(This->custom_cancelbutton);
1691 LocalFree(This->custom_filenamelabel);
1693 HeapFree(GetProcessHeap(), 0, This);
1699 static HRESULT WINAPI IFileDialog2_fnShow(IFileDialog2 *iface, HWND hwndOwner)
1701 FileDialogImpl *This = impl_from_IFileDialog2(iface);
1702 TRACE("%p (%p)\n", iface, hwndOwner);
1704 return create_dialog(This, hwndOwner);
1707 static HRESULT WINAPI IFileDialog2_fnSetFileTypes(IFileDialog2 *iface, UINT cFileTypes,
1708 const COMDLG_FILTERSPEC *rgFilterSpec)
1710 FileDialogImpl *This = impl_from_IFileDialog2(iface);
1712 TRACE("%p (%d, %p)\n", This, cFileTypes, rgFilterSpec);
1714 if(This->filterspecs)
1715 return E_UNEXPECTED;
1718 return E_INVALIDARG;
1723 This->filterspecs = HeapAlloc(GetProcessHeap(), 0, sizeof(COMDLG_FILTERSPEC)*cFileTypes);
1724 for(i = 0; i < cFileTypes; i++)
1726 This->filterspecs[i].pszName = StrDupW(rgFilterSpec[i].pszName);
1727 This->filterspecs[i].pszSpec = StrDupW(rgFilterSpec[i].pszSpec);
1729 This->filterspec_count = cFileTypes;
1734 static HRESULT WINAPI IFileDialog2_fnSetFileTypeIndex(IFileDialog2 *iface, UINT iFileType)
1736 FileDialogImpl *This = impl_from_IFileDialog2(iface);
1737 TRACE("%p (%d)\n", This, iFileType);
1739 if(!This->filterspecs)
1742 if(iFileType >= This->filterspec_count)
1743 This->filetypeindex = This->filterspec_count - 1;
1745 This->filetypeindex = iFileType;
1750 static HRESULT WINAPI IFileDialog2_fnGetFileTypeIndex(IFileDialog2 *iface, UINT *piFileType)
1752 FileDialogImpl *This = impl_from_IFileDialog2(iface);
1753 TRACE("%p (%p)\n", This, piFileType);
1756 return E_INVALIDARG;
1758 *piFileType = This->filetypeindex;
1763 static HRESULT WINAPI IFileDialog2_fnAdvise(IFileDialog2 *iface, IFileDialogEvents *pfde, DWORD *pdwCookie)
1765 FileDialogImpl *This = impl_from_IFileDialog2(iface);
1766 events_client *client;
1767 TRACE("%p (%p, %p)\n", This, pfde, pdwCookie);
1769 if(!pfde || !pdwCookie)
1770 return E_INVALIDARG;
1772 client = HeapAlloc(GetProcessHeap(), 0, sizeof(events_client));
1773 client->pfde = pfde;
1774 client->cookie = ++This->events_next_cookie;
1776 IFileDialogEvents_AddRef(pfde);
1777 *pdwCookie = client->cookie;
1779 list_add_tail(&This->events_clients, &client->entry);
1784 static HRESULT WINAPI IFileDialog2_fnUnadvise(IFileDialog2 *iface, DWORD dwCookie)
1786 FileDialogImpl *This = impl_from_IFileDialog2(iface);
1787 events_client *client, *found = NULL;
1788 TRACE("%p (%d)\n", This, dwCookie);
1790 LIST_FOR_EACH_ENTRY(client, &This->events_clients, events_client, entry)
1792 if(client->cookie == dwCookie)
1801 list_remove(&found->entry);
1802 IFileDialogEvents_Release(found->pfde);
1803 HeapFree(GetProcessHeap(), 0, found);
1807 return E_INVALIDARG;
1810 static HRESULT WINAPI IFileDialog2_fnSetOptions(IFileDialog2 *iface, FILEOPENDIALOGOPTIONS fos)
1812 FileDialogImpl *This = impl_from_IFileDialog2(iface);
1813 TRACE("%p (0x%x)\n", This, fos);
1815 This->options = fos;
1820 static HRESULT WINAPI IFileDialog2_fnGetOptions(IFileDialog2 *iface, FILEOPENDIALOGOPTIONS *pfos)
1822 FileDialogImpl *This = impl_from_IFileDialog2(iface);
1823 TRACE("%p (%p)\n", This, pfos);
1826 return E_INVALIDARG;
1828 *pfos = This->options;
1833 static HRESULT WINAPI IFileDialog2_fnSetDefaultFolder(IFileDialog2 *iface, IShellItem *psi)
1835 FileDialogImpl *This = impl_from_IFileDialog2(iface);
1836 TRACE("%p (%p)\n", This, psi);
1837 if(This->psi_defaultfolder)
1838 IShellItem_Release(This->psi_defaultfolder);
1840 This->psi_defaultfolder = psi;
1842 if(This->psi_defaultfolder)
1843 IShellItem_AddRef(This->psi_defaultfolder);
1848 static HRESULT WINAPI IFileDialog2_fnSetFolder(IFileDialog2 *iface, IShellItem *psi)
1850 FileDialogImpl *This = impl_from_IFileDialog2(iface);
1851 TRACE("%p (%p)\n", This, psi);
1852 if(This->psi_setfolder)
1853 IShellItem_Release(This->psi_setfolder);
1855 This->psi_setfolder = psi;
1857 if(This->psi_setfolder)
1858 IShellItem_AddRef(This->psi_setfolder);
1863 static HRESULT WINAPI IFileDialog2_fnGetFolder(IFileDialog2 *iface, IShellItem **ppsi)
1865 FileDialogImpl *This = impl_from_IFileDialog2(iface);
1866 TRACE("%p (%p)\n", This, ppsi);
1868 return E_INVALIDARG;
1871 If the dialog is shown, return the current(ly selected) folder. */
1874 if(This->psi_folder)
1875 *ppsi = This->psi_folder;
1876 else if(This->psi_setfolder)
1877 *ppsi = This->psi_setfolder;
1878 else if(This->psi_defaultfolder)
1879 *ppsi = This->psi_defaultfolder;
1883 IShellItem_AddRef(*ppsi);
1890 static HRESULT WINAPI IFileDialog2_fnGetCurrentSelection(IFileDialog2 *iface, IShellItem **ppsi)
1892 FileDialogImpl *This = impl_from_IFileDialog2(iface);
1894 TRACE("%p (%p)\n", This, ppsi);
1897 return E_INVALIDARG;
1899 if(This->psia_selection)
1901 /* FIXME: Check filename edit box */
1902 hr = IShellItemArray_GetItemAt(This->psia_selection, 0, ppsi);
1909 static HRESULT WINAPI IFileDialog2_fnSetFileName(IFileDialog2 *iface, LPCWSTR pszName)
1911 FileDialogImpl *This = impl_from_IFileDialog2(iface);
1912 TRACE("%p (%s)\n", iface, debugstr_w(pszName));
1914 set_file_name(This, pszName);
1919 static HRESULT WINAPI IFileDialog2_fnGetFileName(IFileDialog2 *iface, LPWSTR *pszName)
1921 FileDialogImpl *This = impl_from_IFileDialog2(iface);
1922 TRACE("%p (%p)\n", iface, pszName);
1925 return E_INVALIDARG;
1928 if(get_file_name(This, pszName))
1934 static HRESULT WINAPI IFileDialog2_fnSetTitle(IFileDialog2 *iface, LPCWSTR pszTitle)
1936 FileDialogImpl *This = impl_from_IFileDialog2(iface);
1937 TRACE("%p (%s)\n", This, debugstr_w(pszTitle));
1939 LocalFree(This->custom_title);
1940 This->custom_title = StrDupW(pszTitle);
1941 update_control_text(This);
1946 static HRESULT WINAPI IFileDialog2_fnSetOkButtonLabel(IFileDialog2 *iface, LPCWSTR pszText)
1948 FileDialogImpl *This = impl_from_IFileDialog2(iface);
1949 TRACE("%p (%s)\n", This, debugstr_w(pszText));
1951 LocalFree(This->custom_okbutton);
1952 This->custom_okbutton = StrDupW(pszText);
1953 update_control_text(This);
1954 update_layout(This);
1959 static HRESULT WINAPI IFileDialog2_fnSetFileNameLabel(IFileDialog2 *iface, LPCWSTR pszLabel)
1961 FileDialogImpl *This = impl_from_IFileDialog2(iface);
1962 TRACE("%p (%s)\n", This, debugstr_w(pszLabel));
1964 LocalFree(This->custom_filenamelabel);
1965 This->custom_filenamelabel = StrDupW(pszLabel);
1966 update_control_text(This);
1967 update_layout(This);
1972 static HRESULT WINAPI IFileDialog2_fnGetResult(IFileDialog2 *iface, IShellItem **ppsi)
1974 FileDialogImpl *This = impl_from_IFileDialog2(iface);
1976 TRACE("%p (%p)\n", This, ppsi);
1979 return E_INVALIDARG;
1981 if(This->psia_results)
1984 hr = IShellItemArray_GetCount(This->psia_results, &item_count);
1990 /* Adds a reference. */
1991 hr = IShellItemArray_GetItemAt(This->psia_results, 0, ppsi);
1997 return E_UNEXPECTED;
2000 static HRESULT WINAPI IFileDialog2_fnAddPlace(IFileDialog2 *iface, IShellItem *psi, FDAP fdap)
2002 FileDialogImpl *This = impl_from_IFileDialog2(iface);
2003 FIXME("stub - %p (%p, %d)\n", This, psi, fdap);
2007 static HRESULT WINAPI IFileDialog2_fnSetDefaultExtension(IFileDialog2 *iface, LPCWSTR pszDefaultExtension)
2009 FileDialogImpl *This = impl_from_IFileDialog2(iface);
2010 TRACE("%p (%s)\n", This, debugstr_w(pszDefaultExtension));
2012 LocalFree(This->default_ext);
2013 This->default_ext = StrDupW(pszDefaultExtension);
2018 static HRESULT WINAPI IFileDialog2_fnClose(IFileDialog2 *iface, HRESULT hr)
2020 FileDialogImpl *This = impl_from_IFileDialog2(iface);
2021 TRACE("%p (0x%08x)\n", This, hr);
2024 EndDialog(This->dlg_hwnd, hr);
2029 static HRESULT WINAPI IFileDialog2_fnSetClientGuid(IFileDialog2 *iface, REFGUID guid)
2031 FileDialogImpl *This = impl_from_IFileDialog2(iface);
2032 FIXME("stub - %p (%s)\n", This, debugstr_guid(guid));
2036 static HRESULT WINAPI IFileDialog2_fnClearClientData(IFileDialog2 *iface)
2038 FileDialogImpl *This = impl_from_IFileDialog2(iface);
2039 FIXME("stub - %p\n", This);
2043 static HRESULT WINAPI IFileDialog2_fnSetFilter(IFileDialog2 *iface, IShellItemFilter *pFilter)
2045 FileDialogImpl *This = impl_from_IFileDialog2(iface);
2046 FIXME("stub - %p (%p)\n", This, pFilter);
2050 static HRESULT WINAPI IFileDialog2_fnSetCancelButtonLabel(IFileDialog2 *iface, LPCWSTR pszLabel)
2052 FileDialogImpl *This = impl_from_IFileDialog2(iface);
2053 TRACE("%p (%s)\n", This, debugstr_w(pszLabel));
2055 LocalFree(This->custom_cancelbutton);
2056 This->custom_cancelbutton = StrDupW(pszLabel);
2057 update_control_text(This);
2058 update_layout(This);
2063 static HRESULT WINAPI IFileDialog2_fnSetNavigationRoot(IFileDialog2 *iface, IShellItem *psi)
2065 FileDialogImpl *This = impl_from_IFileDialog2(iface);
2066 FIXME("stub - %p (%p)\n", This, psi);
2070 static const IFileDialog2Vtbl vt_IFileDialog2 = {
2071 IFileDialog2_fnQueryInterface,
2072 IFileDialog2_fnAddRef,
2073 IFileDialog2_fnRelease,
2074 IFileDialog2_fnShow,
2075 IFileDialog2_fnSetFileTypes,
2076 IFileDialog2_fnSetFileTypeIndex,
2077 IFileDialog2_fnGetFileTypeIndex,
2078 IFileDialog2_fnAdvise,
2079 IFileDialog2_fnUnadvise,
2080 IFileDialog2_fnSetOptions,
2081 IFileDialog2_fnGetOptions,
2082 IFileDialog2_fnSetDefaultFolder,
2083 IFileDialog2_fnSetFolder,
2084 IFileDialog2_fnGetFolder,
2085 IFileDialog2_fnGetCurrentSelection,
2086 IFileDialog2_fnSetFileName,
2087 IFileDialog2_fnGetFileName,
2088 IFileDialog2_fnSetTitle,
2089 IFileDialog2_fnSetOkButtonLabel,
2090 IFileDialog2_fnSetFileNameLabel,
2091 IFileDialog2_fnGetResult,
2092 IFileDialog2_fnAddPlace,
2093 IFileDialog2_fnSetDefaultExtension,
2094 IFileDialog2_fnClose,
2095 IFileDialog2_fnSetClientGuid,
2096 IFileDialog2_fnClearClientData,
2097 IFileDialog2_fnSetFilter,
2098 IFileDialog2_fnSetCancelButtonLabel,
2099 IFileDialog2_fnSetNavigationRoot
2102 /**************************************************************************
2105 static inline FileDialogImpl *impl_from_IFileOpenDialog(IFileOpenDialog *iface)
2107 return CONTAINING_RECORD(iface, FileDialogImpl, u.IFileOpenDialog_iface);
2110 static HRESULT WINAPI IFileOpenDialog_fnQueryInterface(IFileOpenDialog *iface,
2111 REFIID riid, void **ppvObject)
2113 FileDialogImpl *This = impl_from_IFileOpenDialog(iface);
2114 return IFileDialog2_QueryInterface(&This->IFileDialog2_iface, riid, ppvObject);
2117 static ULONG WINAPI IFileOpenDialog_fnAddRef(IFileOpenDialog *iface)
2119 FileDialogImpl *This = impl_from_IFileOpenDialog(iface);
2120 return IFileDialog2_AddRef(&This->IFileDialog2_iface);
2123 static ULONG WINAPI IFileOpenDialog_fnRelease(IFileOpenDialog *iface)
2125 FileDialogImpl *This = impl_from_IFileOpenDialog(iface);
2126 return IFileDialog2_Release(&This->IFileDialog2_iface);
2129 static HRESULT WINAPI IFileOpenDialog_fnShow(IFileOpenDialog *iface, HWND hwndOwner)
2131 FileDialogImpl *This = impl_from_IFileOpenDialog(iface);
2132 return IFileDialog2_Show(&This->IFileDialog2_iface, hwndOwner);
2135 static HRESULT WINAPI IFileOpenDialog_fnSetFileTypes(IFileOpenDialog *iface, UINT cFileTypes,
2136 const COMDLG_FILTERSPEC *rgFilterSpec)
2138 FileDialogImpl *This = impl_from_IFileOpenDialog(iface);
2139 return IFileDialog2_SetFileTypes(&This->IFileDialog2_iface, cFileTypes, rgFilterSpec);
2142 static HRESULT WINAPI IFileOpenDialog_fnSetFileTypeIndex(IFileOpenDialog *iface, UINT iFileType)
2144 FileDialogImpl *This = impl_from_IFileOpenDialog(iface);
2145 return IFileDialog2_SetFileTypeIndex(&This->IFileDialog2_iface, iFileType);
2148 static HRESULT WINAPI IFileOpenDialog_fnGetFileTypeIndex(IFileOpenDialog *iface, UINT *piFileType)
2150 FileDialogImpl *This = impl_from_IFileOpenDialog(iface);
2151 return IFileDialog2_GetFileTypeIndex(&This->IFileDialog2_iface, piFileType);
2154 static HRESULT WINAPI IFileOpenDialog_fnAdvise(IFileOpenDialog *iface, IFileDialogEvents *pfde,
2157 FileDialogImpl *This = impl_from_IFileOpenDialog(iface);
2158 return IFileDialog2_Advise(&This->IFileDialog2_iface, pfde, pdwCookie);
2161 static HRESULT WINAPI IFileOpenDialog_fnUnadvise(IFileOpenDialog *iface, DWORD dwCookie)
2163 FileDialogImpl *This = impl_from_IFileOpenDialog(iface);
2164 return IFileDialog2_Unadvise(&This->IFileDialog2_iface, dwCookie);
2167 static HRESULT WINAPI IFileOpenDialog_fnSetOptions(IFileOpenDialog *iface, FILEOPENDIALOGOPTIONS fos)
2169 FileDialogImpl *This = impl_from_IFileOpenDialog(iface);
2170 return IFileDialog2_SetOptions(&This->IFileDialog2_iface, fos);
2173 static HRESULT WINAPI IFileOpenDialog_fnGetOptions(IFileOpenDialog *iface, FILEOPENDIALOGOPTIONS *pfos)
2175 FileDialogImpl *This = impl_from_IFileOpenDialog(iface);
2176 return IFileDialog2_GetOptions(&This->IFileDialog2_iface, pfos);
2179 static HRESULT WINAPI IFileOpenDialog_fnSetDefaultFolder(IFileOpenDialog *iface, IShellItem *psi)
2181 FileDialogImpl *This = impl_from_IFileOpenDialog(iface);
2182 return IFileDialog2_SetDefaultFolder(&This->IFileDialog2_iface, psi);
2185 static HRESULT WINAPI IFileOpenDialog_fnSetFolder(IFileOpenDialog *iface, IShellItem *psi)
2187 FileDialogImpl *This = impl_from_IFileOpenDialog(iface);
2188 return IFileDialog2_SetFolder(&This->IFileDialog2_iface, psi);
2191 static HRESULT WINAPI IFileOpenDialog_fnGetFolder(IFileOpenDialog *iface, IShellItem **ppsi)
2193 FileDialogImpl *This = impl_from_IFileOpenDialog(iface);
2194 return IFileDialog2_GetFolder(&This->IFileDialog2_iface, ppsi);
2197 static HRESULT WINAPI IFileOpenDialog_fnGetCurrentSelection(IFileOpenDialog *iface, IShellItem **ppsi)
2199 FileDialogImpl *This = impl_from_IFileOpenDialog(iface);
2200 return IFileDialog2_GetCurrentSelection(&This->IFileDialog2_iface, ppsi);
2203 static HRESULT WINAPI IFileOpenDialog_fnSetFileName(IFileOpenDialog *iface, LPCWSTR pszName)
2205 FileDialogImpl *This = impl_from_IFileOpenDialog(iface);
2206 return IFileDialog2_SetFileName(&This->IFileDialog2_iface, pszName);
2209 static HRESULT WINAPI IFileOpenDialog_fnGetFileName(IFileOpenDialog *iface, LPWSTR *pszName)
2211 FileDialogImpl *This = impl_from_IFileOpenDialog(iface);
2212 return IFileDialog2_GetFileName(&This->IFileDialog2_iface, pszName);
2215 static HRESULT WINAPI IFileOpenDialog_fnSetTitle(IFileOpenDialog *iface, LPCWSTR pszTitle)
2217 FileDialogImpl *This = impl_from_IFileOpenDialog(iface);
2218 return IFileDialog2_SetTitle(&This->IFileDialog2_iface, pszTitle);
2221 static HRESULT WINAPI IFileOpenDialog_fnSetOkButtonLabel(IFileOpenDialog *iface, LPCWSTR pszText)
2223 FileDialogImpl *This = impl_from_IFileOpenDialog(iface);
2224 return IFileDialog2_SetOkButtonLabel(&This->IFileDialog2_iface, pszText);
2227 static HRESULT WINAPI IFileOpenDialog_fnSetFileNameLabel(IFileOpenDialog *iface, LPCWSTR pszLabel)
2229 FileDialogImpl *This = impl_from_IFileOpenDialog(iface);
2230 return IFileDialog2_SetFileNameLabel(&This->IFileDialog2_iface, pszLabel);
2233 static HRESULT WINAPI IFileOpenDialog_fnGetResult(IFileOpenDialog *iface, IShellItem **ppsi)
2235 FileDialogImpl *This = impl_from_IFileOpenDialog(iface);
2236 return IFileDialog2_GetResult(&This->IFileDialog2_iface, ppsi);
2239 static HRESULT WINAPI IFileOpenDialog_fnAddPlace(IFileOpenDialog *iface, IShellItem *psi, FDAP fdap)
2241 FileDialogImpl *This = impl_from_IFileOpenDialog(iface);
2242 return IFileDialog2_AddPlace(&This->IFileDialog2_iface, psi, fdap);
2245 static HRESULT WINAPI IFileOpenDialog_fnSetDefaultExtension(IFileOpenDialog *iface,
2246 LPCWSTR pszDefaultExtension)
2248 FileDialogImpl *This = impl_from_IFileOpenDialog(iface);
2249 return IFileDialog2_SetDefaultExtension(&This->IFileDialog2_iface, pszDefaultExtension);
2252 static HRESULT WINAPI IFileOpenDialog_fnClose(IFileOpenDialog *iface, HRESULT hr)
2254 FileDialogImpl *This = impl_from_IFileOpenDialog(iface);
2255 return IFileDialog2_Close(&This->IFileDialog2_iface, hr);
2258 static HRESULT WINAPI IFileOpenDialog_fnSetClientGuid(IFileOpenDialog *iface, REFGUID guid)
2260 FileDialogImpl *This = impl_from_IFileOpenDialog(iface);
2261 return IFileDialog2_SetClientGuid(&This->IFileDialog2_iface, guid);
2264 static HRESULT WINAPI IFileOpenDialog_fnClearClientData(IFileOpenDialog *iface)
2266 FileDialogImpl *This = impl_from_IFileOpenDialog(iface);
2267 return IFileDialog2_ClearClientData(&This->IFileDialog2_iface);
2270 static HRESULT WINAPI IFileOpenDialog_fnSetFilter(IFileOpenDialog *iface, IShellItemFilter *pFilter)
2272 FileDialogImpl *This = impl_from_IFileOpenDialog(iface);
2273 return IFileDialog2_SetFilter(&This->IFileDialog2_iface, pFilter);
2276 static HRESULT WINAPI IFileOpenDialog_fnGetResults(IFileOpenDialog *iface, IShellItemArray **ppenum)
2278 FileDialogImpl *This = impl_from_IFileOpenDialog(iface);
2279 TRACE("%p (%p)\n", This, ppenum);
2281 *ppenum = This->psia_results;
2285 IShellItemArray_AddRef(*ppenum);
2292 static HRESULT WINAPI IFileOpenDialog_fnGetSelectedItems(IFileOpenDialog *iface, IShellItemArray **ppsai)
2294 FileDialogImpl *This = impl_from_IFileOpenDialog(iface);
2295 TRACE("%p (%p)\n", This, ppsai);
2297 if(This->psia_selection)
2299 *ppsai = This->psia_selection;
2300 IShellItemArray_AddRef(*ppsai);
2307 static const IFileOpenDialogVtbl vt_IFileOpenDialog = {
2308 IFileOpenDialog_fnQueryInterface,
2309 IFileOpenDialog_fnAddRef,
2310 IFileOpenDialog_fnRelease,
2311 IFileOpenDialog_fnShow,
2312 IFileOpenDialog_fnSetFileTypes,
2313 IFileOpenDialog_fnSetFileTypeIndex,
2314 IFileOpenDialog_fnGetFileTypeIndex,
2315 IFileOpenDialog_fnAdvise,
2316 IFileOpenDialog_fnUnadvise,
2317 IFileOpenDialog_fnSetOptions,
2318 IFileOpenDialog_fnGetOptions,
2319 IFileOpenDialog_fnSetDefaultFolder,
2320 IFileOpenDialog_fnSetFolder,
2321 IFileOpenDialog_fnGetFolder,
2322 IFileOpenDialog_fnGetCurrentSelection,
2323 IFileOpenDialog_fnSetFileName,
2324 IFileOpenDialog_fnGetFileName,
2325 IFileOpenDialog_fnSetTitle,
2326 IFileOpenDialog_fnSetOkButtonLabel,
2327 IFileOpenDialog_fnSetFileNameLabel,
2328 IFileOpenDialog_fnGetResult,
2329 IFileOpenDialog_fnAddPlace,
2330 IFileOpenDialog_fnSetDefaultExtension,
2331 IFileOpenDialog_fnClose,
2332 IFileOpenDialog_fnSetClientGuid,
2333 IFileOpenDialog_fnClearClientData,
2334 IFileOpenDialog_fnSetFilter,
2335 IFileOpenDialog_fnGetResults,
2336 IFileOpenDialog_fnGetSelectedItems
2339 /**************************************************************************
2342 static inline FileDialogImpl *impl_from_IFileSaveDialog(IFileSaveDialog *iface)
2344 return CONTAINING_RECORD(iface, FileDialogImpl, u.IFileSaveDialog_iface);
2347 static HRESULT WINAPI IFileSaveDialog_fnQueryInterface(IFileSaveDialog *iface,
2351 FileDialogImpl *This = impl_from_IFileSaveDialog(iface);
2352 return IFileDialog2_QueryInterface(&This->IFileDialog2_iface, riid, ppvObject);
2355 static ULONG WINAPI IFileSaveDialog_fnAddRef(IFileSaveDialog *iface)
2357 FileDialogImpl *This = impl_from_IFileSaveDialog(iface);
2358 return IFileDialog2_AddRef(&This->IFileDialog2_iface);
2361 static ULONG WINAPI IFileSaveDialog_fnRelease(IFileSaveDialog *iface)
2363 FileDialogImpl *This = impl_from_IFileSaveDialog(iface);
2364 return IFileDialog2_Release(&This->IFileDialog2_iface);
2367 static HRESULT WINAPI IFileSaveDialog_fnShow(IFileSaveDialog *iface, HWND hwndOwner)
2369 FileDialogImpl *This = impl_from_IFileSaveDialog(iface);
2370 return IFileDialog2_Show(&This->IFileDialog2_iface, hwndOwner);
2373 static HRESULT WINAPI IFileSaveDialog_fnSetFileTypes(IFileSaveDialog *iface, UINT cFileTypes,
2374 const COMDLG_FILTERSPEC *rgFilterSpec)
2376 FileDialogImpl *This = impl_from_IFileSaveDialog(iface);
2377 return IFileDialog2_SetFileTypes(&This->IFileDialog2_iface, cFileTypes, rgFilterSpec);
2380 static HRESULT WINAPI IFileSaveDialog_fnSetFileTypeIndex(IFileSaveDialog *iface, UINT iFileType)
2382 FileDialogImpl *This = impl_from_IFileSaveDialog(iface);
2383 return IFileDialog2_SetFileTypeIndex(&This->IFileDialog2_iface, iFileType);
2386 static HRESULT WINAPI IFileSaveDialog_fnGetFileTypeIndex(IFileSaveDialog *iface, UINT *piFileType)
2388 FileDialogImpl *This = impl_from_IFileSaveDialog(iface);
2389 return IFileDialog2_GetFileTypeIndex(&This->IFileDialog2_iface, piFileType);
2392 static HRESULT WINAPI IFileSaveDialog_fnAdvise(IFileSaveDialog *iface, IFileDialogEvents *pfde,
2395 FileDialogImpl *This = impl_from_IFileSaveDialog(iface);
2396 return IFileDialog2_Advise(&This->IFileDialog2_iface, pfde, pdwCookie);
2399 static HRESULT WINAPI IFileSaveDialog_fnUnadvise(IFileSaveDialog *iface, DWORD dwCookie)
2401 FileDialogImpl *This = impl_from_IFileSaveDialog(iface);
2402 return IFileDialog2_Unadvise(&This->IFileDialog2_iface, dwCookie);
2405 static HRESULT WINAPI IFileSaveDialog_fnSetOptions(IFileSaveDialog *iface, FILEOPENDIALOGOPTIONS fos)
2407 FileDialogImpl *This = impl_from_IFileSaveDialog(iface);
2408 return IFileDialog2_SetOptions(&This->IFileDialog2_iface, fos);
2411 static HRESULT WINAPI IFileSaveDialog_fnGetOptions(IFileSaveDialog *iface, FILEOPENDIALOGOPTIONS *pfos)
2413 FileDialogImpl *This = impl_from_IFileSaveDialog(iface);
2414 return IFileDialog2_GetOptions(&This->IFileDialog2_iface, pfos);
2417 static HRESULT WINAPI IFileSaveDialog_fnSetDefaultFolder(IFileSaveDialog *iface, IShellItem *psi)
2419 FileDialogImpl *This = impl_from_IFileSaveDialog(iface);
2420 return IFileDialog2_SetDefaultFolder(&This->IFileDialog2_iface, psi);
2423 static HRESULT WINAPI IFileSaveDialog_fnSetFolder(IFileSaveDialog *iface, IShellItem *psi)
2425 FileDialogImpl *This = impl_from_IFileSaveDialog(iface);
2426 return IFileDialog2_SetFolder(&This->IFileDialog2_iface, psi);
2429 static HRESULT WINAPI IFileSaveDialog_fnGetFolder(IFileSaveDialog *iface, IShellItem **ppsi)
2431 FileDialogImpl *This = impl_from_IFileSaveDialog(iface);
2432 return IFileDialog2_GetFolder(&This->IFileDialog2_iface, ppsi);
2435 static HRESULT WINAPI IFileSaveDialog_fnGetCurrentSelection(IFileSaveDialog *iface, IShellItem **ppsi)
2437 FileDialogImpl *This = impl_from_IFileSaveDialog(iface);
2438 return IFileDialog2_GetCurrentSelection(&This->IFileDialog2_iface, ppsi);
2441 static HRESULT WINAPI IFileSaveDialog_fnSetFileName(IFileSaveDialog *iface, LPCWSTR pszName)
2443 FileDialogImpl *This = impl_from_IFileSaveDialog(iface);
2444 return IFileDialog2_SetFileName(&This->IFileDialog2_iface, pszName);
2447 static HRESULT WINAPI IFileSaveDialog_fnGetFileName(IFileSaveDialog *iface, LPWSTR *pszName)
2449 FileDialogImpl *This = impl_from_IFileSaveDialog(iface);
2450 return IFileDialog2_GetFileName(&This->IFileDialog2_iface, pszName);
2453 static HRESULT WINAPI IFileSaveDialog_fnSetTitle(IFileSaveDialog *iface, LPCWSTR pszTitle)
2455 FileDialogImpl *This = impl_from_IFileSaveDialog(iface);
2456 return IFileDialog2_SetTitle(&This->IFileDialog2_iface, pszTitle);
2459 static HRESULT WINAPI IFileSaveDialog_fnSetOkButtonLabel(IFileSaveDialog *iface, LPCWSTR pszText)
2461 FileDialogImpl *This = impl_from_IFileSaveDialog(iface);
2462 return IFileDialog2_SetOkButtonLabel(&This->IFileDialog2_iface, pszText);
2465 static HRESULT WINAPI IFileSaveDialog_fnSetFileNameLabel(IFileSaveDialog *iface, LPCWSTR pszLabel)
2467 FileDialogImpl *This = impl_from_IFileSaveDialog(iface);
2468 return IFileDialog2_SetFileNameLabel(&This->IFileDialog2_iface, pszLabel);
2471 static HRESULT WINAPI IFileSaveDialog_fnGetResult(IFileSaveDialog *iface, IShellItem **ppsi)
2473 FileDialogImpl *This = impl_from_IFileSaveDialog(iface);
2474 return IFileDialog2_GetResult(&This->IFileDialog2_iface, ppsi);
2477 static HRESULT WINAPI IFileSaveDialog_fnAddPlace(IFileSaveDialog *iface, IShellItem *psi, FDAP fdap)
2479 FileDialogImpl *This = impl_from_IFileSaveDialog(iface);
2480 return IFileDialog2_AddPlace(&This->IFileDialog2_iface, psi, fdap);
2483 static HRESULT WINAPI IFileSaveDialog_fnSetDefaultExtension(IFileSaveDialog *iface,
2484 LPCWSTR pszDefaultExtension)
2486 FileDialogImpl *This = impl_from_IFileSaveDialog(iface);
2487 return IFileDialog2_SetDefaultExtension(&This->IFileDialog2_iface, pszDefaultExtension);
2490 static HRESULT WINAPI IFileSaveDialog_fnClose(IFileSaveDialog *iface, HRESULT hr)
2492 FileDialogImpl *This = impl_from_IFileSaveDialog(iface);
2493 return IFileDialog2_Close(&This->IFileDialog2_iface, hr);
2496 static HRESULT WINAPI IFileSaveDialog_fnSetClientGuid(IFileSaveDialog *iface, REFGUID guid)
2498 FileDialogImpl *This = impl_from_IFileSaveDialog(iface);
2499 return IFileDialog2_SetClientGuid(&This->IFileDialog2_iface, guid);
2502 static HRESULT WINAPI IFileSaveDialog_fnClearClientData(IFileSaveDialog *iface)
2504 FileDialogImpl *This = impl_from_IFileSaveDialog(iface);
2505 return IFileDialog2_ClearClientData(&This->IFileDialog2_iface);
2508 static HRESULT WINAPI IFileSaveDialog_fnSetFilter(IFileSaveDialog *iface, IShellItemFilter *pFilter)
2510 FileDialogImpl *This = impl_from_IFileSaveDialog(iface);
2511 return IFileDialog2_SetFilter(&This->IFileDialog2_iface, pFilter);
2514 static HRESULT WINAPI IFileSaveDialog_fnSetSaveAsItem(IFileSaveDialog* iface, IShellItem *psi)
2516 FileDialogImpl *This = impl_from_IFileSaveDialog(iface);
2517 FIXME("stub - %p (%p)\n", This, psi);
2521 static HRESULT WINAPI IFileSaveDialog_fnSetProperties(IFileSaveDialog* iface, IPropertyStore *pStore)
2523 FileDialogImpl *This = impl_from_IFileSaveDialog(iface);
2524 FIXME("stub - %p (%p)\n", This, pStore);
2528 static HRESULT WINAPI IFileSaveDialog_fnSetCollectedProperties(IFileSaveDialog* iface,
2529 IPropertyDescriptionList *pList,
2530 BOOL fAppendDefault)
2532 FileDialogImpl *This = impl_from_IFileSaveDialog(iface);
2533 FIXME("stub - %p (%p, %d)\n", This, pList, fAppendDefault);
2537 static HRESULT WINAPI IFileSaveDialog_fnGetProperties(IFileSaveDialog* iface, IPropertyStore **ppStore)
2539 FileDialogImpl *This = impl_from_IFileSaveDialog(iface);
2540 FIXME("stub - %p (%p)\n", This, ppStore);
2544 static HRESULT WINAPI IFileSaveDialog_fnApplyProperties(IFileSaveDialog* iface,
2546 IPropertyStore *pStore,
2548 IFileOperationProgressSink *pSink)
2550 FileDialogImpl *This = impl_from_IFileSaveDialog(iface);
2551 FIXME("%p (%p, %p, %p, %p)\n", This, psi, pStore, hwnd, pSink);
2555 static const IFileSaveDialogVtbl vt_IFileSaveDialog = {
2556 IFileSaveDialog_fnQueryInterface,
2557 IFileSaveDialog_fnAddRef,
2558 IFileSaveDialog_fnRelease,
2559 IFileSaveDialog_fnShow,
2560 IFileSaveDialog_fnSetFileTypes,
2561 IFileSaveDialog_fnSetFileTypeIndex,
2562 IFileSaveDialog_fnGetFileTypeIndex,
2563 IFileSaveDialog_fnAdvise,
2564 IFileSaveDialog_fnUnadvise,
2565 IFileSaveDialog_fnSetOptions,
2566 IFileSaveDialog_fnGetOptions,
2567 IFileSaveDialog_fnSetDefaultFolder,
2568 IFileSaveDialog_fnSetFolder,
2569 IFileSaveDialog_fnGetFolder,
2570 IFileSaveDialog_fnGetCurrentSelection,
2571 IFileSaveDialog_fnSetFileName,
2572 IFileSaveDialog_fnGetFileName,
2573 IFileSaveDialog_fnSetTitle,
2574 IFileSaveDialog_fnSetOkButtonLabel,
2575 IFileSaveDialog_fnSetFileNameLabel,
2576 IFileSaveDialog_fnGetResult,
2577 IFileSaveDialog_fnAddPlace,
2578 IFileSaveDialog_fnSetDefaultExtension,
2579 IFileSaveDialog_fnClose,
2580 IFileSaveDialog_fnSetClientGuid,
2581 IFileSaveDialog_fnClearClientData,
2582 IFileSaveDialog_fnSetFilter,
2583 IFileSaveDialog_fnSetSaveAsItem,
2584 IFileSaveDialog_fnSetProperties,
2585 IFileSaveDialog_fnSetCollectedProperties,
2586 IFileSaveDialog_fnGetProperties,
2587 IFileSaveDialog_fnApplyProperties
2590 /**************************************************************************
2591 * IExplorerBrowserEvents implementation
2593 static inline FileDialogImpl *impl_from_IExplorerBrowserEvents(IExplorerBrowserEvents *iface)
2595 return CONTAINING_RECORD(iface, FileDialogImpl, IExplorerBrowserEvents_iface);
2598 static HRESULT WINAPI IExplorerBrowserEvents_fnQueryInterface(IExplorerBrowserEvents *iface,
2599 REFIID riid, void **ppvObject)
2601 FileDialogImpl *This = impl_from_IExplorerBrowserEvents(iface);
2602 TRACE("%p (%s, %p)\n", This, debugstr_guid(riid), ppvObject);
2604 return IFileDialog2_QueryInterface(&This->IFileDialog2_iface, riid, ppvObject);
2607 static ULONG WINAPI IExplorerBrowserEvents_fnAddRef(IExplorerBrowserEvents *iface)
2609 FileDialogImpl *This = impl_from_IExplorerBrowserEvents(iface);
2610 TRACE("%p\n", This);
2611 return IFileDialog2_AddRef(&This->IFileDialog2_iface);
2614 static ULONG WINAPI IExplorerBrowserEvents_fnRelease(IExplorerBrowserEvents *iface)
2616 FileDialogImpl *This = impl_from_IExplorerBrowserEvents(iface);
2617 TRACE("%p\n", This);
2618 return IFileDialog2_Release(&This->IFileDialog2_iface);
2621 static HRESULT WINAPI IExplorerBrowserEvents_fnOnNavigationPending(IExplorerBrowserEvents *iface,
2622 PCIDLIST_ABSOLUTE pidlFolder)
2624 FileDialogImpl *This = impl_from_IExplorerBrowserEvents(iface);
2627 TRACE("%p (%p)\n", This, pidlFolder);
2629 hr = SHCreateItemFromIDList(pidlFolder, &IID_IShellItem, (void**)&psi);
2632 hr = events_OnFolderChanging(This, psi);
2633 IShellItem_Release(psi);
2635 /* The ExplorerBrowser treats S_FALSE as S_OK, we don't. */
2642 ERR("Failed to convert pidl (%p) to a shellitem.\n", pidlFolder);
2647 static HRESULT WINAPI IExplorerBrowserEvents_fnOnViewCreated(IExplorerBrowserEvents *iface,
2650 FileDialogImpl *This = impl_from_IExplorerBrowserEvents(iface);
2651 TRACE("%p (%p)\n", This, psv);
2655 static HRESULT WINAPI IExplorerBrowserEvents_fnOnNavigationComplete(IExplorerBrowserEvents *iface,
2656 PCIDLIST_ABSOLUTE pidlFolder)
2658 FileDialogImpl *This = impl_from_IExplorerBrowserEvents(iface);
2660 TRACE("%p (%p)\n", This, pidlFolder);
2662 if(This->psi_folder)
2663 IShellItem_Release(This->psi_folder);
2665 hr = SHCreateItemFromIDList(pidlFolder, &IID_IShellItem, (void**)&This->psi_folder);
2668 ERR("Failed to get the current folder.\n");
2669 This->psi_folder = NULL;
2672 events_OnFolderChange(This);
2677 static HRESULT WINAPI IExplorerBrowserEvents_fnOnNavigationFailed(IExplorerBrowserEvents *iface,
2678 PCIDLIST_ABSOLUTE pidlFolder)
2680 FileDialogImpl *This = impl_from_IExplorerBrowserEvents(iface);
2681 TRACE("%p (%p)\n", This, pidlFolder);
2685 static const IExplorerBrowserEventsVtbl vt_IExplorerBrowserEvents = {
2686 IExplorerBrowserEvents_fnQueryInterface,
2687 IExplorerBrowserEvents_fnAddRef,
2688 IExplorerBrowserEvents_fnRelease,
2689 IExplorerBrowserEvents_fnOnNavigationPending,
2690 IExplorerBrowserEvents_fnOnViewCreated,
2691 IExplorerBrowserEvents_fnOnNavigationComplete,
2692 IExplorerBrowserEvents_fnOnNavigationFailed
2695 /**************************************************************************
2696 * IServiceProvider implementation
2698 static inline FileDialogImpl *impl_from_IServiceProvider(IServiceProvider *iface)
2700 return CONTAINING_RECORD(iface, FileDialogImpl, IServiceProvider_iface);
2703 static HRESULT WINAPI IServiceProvider_fnQueryInterface(IServiceProvider *iface,
2704 REFIID riid, void **ppvObject)
2706 FileDialogImpl *This = impl_from_IServiceProvider(iface);
2707 TRACE("%p\n", This);
2708 return IFileDialog2_QueryInterface(&This->IFileDialog2_iface, riid, ppvObject);
2711 static ULONG WINAPI IServiceProvider_fnAddRef(IServiceProvider *iface)
2713 FileDialogImpl *This = impl_from_IServiceProvider(iface);
2714 TRACE("%p\n", This);
2715 return IFileDialog2_AddRef(&This->IFileDialog2_iface);
2718 static ULONG WINAPI IServiceProvider_fnRelease(IServiceProvider *iface)
2720 FileDialogImpl *This = impl_from_IServiceProvider(iface);
2721 TRACE("%p\n", This);
2722 return IFileDialog2_Release(&This->IFileDialog2_iface);
2725 static HRESULT WINAPI IServiceProvider_fnQueryService(IServiceProvider *iface,
2726 REFGUID guidService,
2727 REFIID riid, void **ppv)
2729 FileDialogImpl *This = impl_from_IServiceProvider(iface);
2730 HRESULT hr = E_FAIL;
2731 TRACE("%p (%s, %s, %p)\n", This, debugstr_guid(guidService), debugstr_guid(riid), ppv);
2734 if(IsEqualGUID(guidService, &SID_STopLevelBrowser) && This->peb)
2735 hr = IExplorerBrowser_QueryInterface(This->peb, riid, ppv);
2736 else if(IsEqualGUID(guidService, &SID_SExplorerBrowserFrame))
2737 hr = IFileDialog2_QueryInterface(&This->IFileDialog2_iface, riid, ppv);
2739 FIXME("Interface %s requested from unknown service %s\n",
2740 debugstr_guid(riid), debugstr_guid(guidService));
2745 static const IServiceProviderVtbl vt_IServiceProvider = {
2746 IServiceProvider_fnQueryInterface,
2747 IServiceProvider_fnAddRef,
2748 IServiceProvider_fnRelease,
2749 IServiceProvider_fnQueryService
2752 /**************************************************************************
2753 * ICommDlgBrowser3 implementation
2755 static inline FileDialogImpl *impl_from_ICommDlgBrowser3(ICommDlgBrowser3 *iface)
2757 return CONTAINING_RECORD(iface, FileDialogImpl, ICommDlgBrowser3_iface);
2760 static HRESULT WINAPI ICommDlgBrowser3_fnQueryInterface(ICommDlgBrowser3 *iface,
2761 REFIID riid, void **ppvObject)
2763 FileDialogImpl *This = impl_from_ICommDlgBrowser3(iface);
2764 TRACE("%p\n", This);
2765 return IFileDialog2_QueryInterface(&This->IFileDialog2_iface, riid, ppvObject);
2768 static ULONG WINAPI ICommDlgBrowser3_fnAddRef(ICommDlgBrowser3 *iface)
2770 FileDialogImpl *This = impl_from_ICommDlgBrowser3(iface);
2771 TRACE("%p\n", This);
2772 return IFileDialog2_AddRef(&This->IFileDialog2_iface);
2775 static ULONG WINAPI ICommDlgBrowser3_fnRelease(ICommDlgBrowser3 *iface)
2777 FileDialogImpl *This = impl_from_ICommDlgBrowser3(iface);
2778 TRACE("%p\n", This);
2779 return IFileDialog2_Release(&This->IFileDialog2_iface);
2782 static HRESULT WINAPI ICommDlgBrowser3_fnOnDefaultCommand(ICommDlgBrowser3 *iface,
2785 FileDialogImpl *This = impl_from_ICommDlgBrowser3(iface);
2787 TRACE("%p (%p)\n", This, shv);
2789 hr = on_default_action(This);
2792 EndDialog(This->dlg_hwnd, S_OK);
2797 static HRESULT WINAPI ICommDlgBrowser3_fnOnStateChange(ICommDlgBrowser3 *iface,
2798 IShellView *shv, ULONG uChange )
2800 FileDialogImpl *This = impl_from_ICommDlgBrowser3(iface);
2801 IDataObject *new_selection;
2803 TRACE("%p (%p, %x)\n", This, shv, uChange);
2807 case CDBOSC_SELCHANGE:
2808 if(This->psia_selection)
2810 IShellItemArray_Release(This->psia_selection);
2811 This->psia_selection = NULL;
2814 hr = IShellView_GetItemObject(shv, SVGIO_SELECTION, &IID_IDataObject, (void**)&new_selection);
2817 hr = SHCreateShellItemArrayFromDataObject(new_selection, &IID_IShellItemArray,
2818 (void**)&This->psia_selection);
2821 fill_filename_from_selection(This);
2822 events_OnSelectionChange(This);
2825 IDataObject_Release(new_selection);
2829 TRACE("Unhandled state change\n");
2834 static HRESULT WINAPI ICommDlgBrowser3_fnIncludeObject(ICommDlgBrowser3 *iface,
2835 IShellView *shv, LPCITEMIDLIST pidl)
2837 FileDialogImpl *This = impl_from_ICommDlgBrowser3(iface);
2840 LPITEMIDLIST parent_pidl;
2843 TRACE("%p (%p, %p)\n", This, shv, pidl);
2845 if(!This->filterspec_count)
2848 hr = SHGetIDListFromObject((IUnknown*)shv, &parent_pidl);
2851 LPITEMIDLIST full_pidl = ILCombine(parent_pidl, pidl);
2852 hr = SHCreateItemFromIDList(full_pidl, &IID_IShellItem, (void**)&psi);
2853 ILFree(parent_pidl);
2858 ERR("Failed to get shellitem (%08x).\n", hr);
2862 hr = IShellItem_GetAttributes(psi, SFGAO_FOLDER|SFGAO_LINK, &attr);
2863 if(FAILED(hr) || (attr & (SFGAO_FOLDER | SFGAO_LINK)))
2865 IShellItem_Release(psi);
2870 if(SUCCEEDED(IShellItem_GetDisplayName(psi, SIGDN_PARENTRELATIVEPARSING, &filename)))
2872 if(!PathMatchSpecW(filename, This->filterspecs[This->filetypeindex].pszSpec))
2874 CoTaskMemFree(filename);
2877 IShellItem_Release(psi);
2881 static HRESULT WINAPI ICommDlgBrowser3_fnNotify(ICommDlgBrowser3 *iface,
2882 IShellView *ppshv, DWORD dwNotifyType)
2884 FileDialogImpl *This = impl_from_ICommDlgBrowser3(iface);
2885 FIXME("Stub: %p (%p, 0x%x)\n", This, ppshv, dwNotifyType);
2889 static HRESULT WINAPI ICommDlgBrowser3_fnGetDefaultMenuText(ICommDlgBrowser3 *iface,
2891 LPWSTR pszText, int cchMax)
2893 FileDialogImpl *This = impl_from_ICommDlgBrowser3(iface);
2894 FIXME("Stub: %p (%p, %p, %d)\n", This, pshv, pszText, cchMax);
2898 static HRESULT WINAPI ICommDlgBrowser3_fnGetViewFlags(ICommDlgBrowser3 *iface, DWORD *pdwFlags)
2900 FileDialogImpl *This = impl_from_ICommDlgBrowser3(iface);
2901 FIXME("Stub: %p (%p)\n", This, pdwFlags);
2905 static HRESULT WINAPI ICommDlgBrowser3_fnOnColumnClicked(ICommDlgBrowser3 *iface,
2906 IShellView *pshv, int iColumn)
2908 FileDialogImpl *This = impl_from_ICommDlgBrowser3(iface);
2909 FIXME("Stub: %p (%p, %d)\n", This, pshv, iColumn);
2913 static HRESULT WINAPI ICommDlgBrowser3_fnGetCurrentFilter(ICommDlgBrowser3 *iface,
2914 LPWSTR pszFileSpec, int cchFileSpec)
2916 FileDialogImpl *This = impl_from_ICommDlgBrowser3(iface);
2917 FIXME("Stub: %p (%p, %d)\n", This, pszFileSpec, cchFileSpec);
2921 static HRESULT WINAPI ICommDlgBrowser3_fnOnPreviewCreated(ICommDlgBrowser3 *iface,
2924 FileDialogImpl *This = impl_from_ICommDlgBrowser3(iface);
2925 FIXME("Stub: %p (%p)\n", This, pshv);
2929 static const ICommDlgBrowser3Vtbl vt_ICommDlgBrowser3 = {
2930 ICommDlgBrowser3_fnQueryInterface,
2931 ICommDlgBrowser3_fnAddRef,
2932 ICommDlgBrowser3_fnRelease,
2933 ICommDlgBrowser3_fnOnDefaultCommand,
2934 ICommDlgBrowser3_fnOnStateChange,
2935 ICommDlgBrowser3_fnIncludeObject,
2936 ICommDlgBrowser3_fnNotify,
2937 ICommDlgBrowser3_fnGetDefaultMenuText,
2938 ICommDlgBrowser3_fnGetViewFlags,
2939 ICommDlgBrowser3_fnOnColumnClicked,
2940 ICommDlgBrowser3_fnGetCurrentFilter,
2941 ICommDlgBrowser3_fnOnPreviewCreated
2944 /**************************************************************************
2945 * IOleWindow implementation
2947 static inline FileDialogImpl *impl_from_IOleWindow(IOleWindow *iface)
2949 return CONTAINING_RECORD(iface, FileDialogImpl, IOleWindow_iface);
2952 static HRESULT WINAPI IOleWindow_fnQueryInterface(IOleWindow *iface, REFIID riid, void **ppvObject)
2954 FileDialogImpl *This = impl_from_IOleWindow(iface);
2955 return IFileDialog2_QueryInterface(&This->IFileDialog2_iface, riid, ppvObject);
2958 static ULONG WINAPI IOleWindow_fnAddRef(IOleWindow *iface)
2960 FileDialogImpl *This = impl_from_IOleWindow(iface);
2961 return IFileDialog2_AddRef(&This->IFileDialog2_iface);
2964 static ULONG WINAPI IOleWindow_fnRelease(IOleWindow *iface)
2966 FileDialogImpl *This = impl_from_IOleWindow(iface);
2967 return IFileDialog2_Release(&This->IFileDialog2_iface);
2970 static HRESULT WINAPI IOleWindow_fnContextSensitiveHelp(IOleWindow *iface, BOOL fEnterMOde)
2972 FileDialogImpl *This = impl_from_IOleWindow(iface);
2973 FIXME("Stub: %p (%d)\n", This, fEnterMOde);
2977 static HRESULT WINAPI IOleWindow_fnGetWindow(IOleWindow *iface, HWND *phwnd)
2979 FileDialogImpl *This = impl_from_IOleWindow(iface);
2980 TRACE("%p (%p)\n", This, phwnd);
2981 *phwnd = This->dlg_hwnd;
2985 static const IOleWindowVtbl vt_IOleWindow = {
2986 IOleWindow_fnQueryInterface,
2987 IOleWindow_fnAddRef,
2988 IOleWindow_fnRelease,
2989 IOleWindow_fnGetWindow,
2990 IOleWindow_fnContextSensitiveHelp
2993 /**************************************************************************
2994 * IFileDialogCustomize implementation
2996 static inline FileDialogImpl *impl_from_IFileDialogCustomize(IFileDialogCustomize *iface)
2998 return CONTAINING_RECORD(iface, FileDialogImpl, IFileDialogCustomize_iface);
3001 static HRESULT WINAPI IFileDialogCustomize_fnQueryInterface(IFileDialogCustomize *iface,
3002 REFIID riid, void **ppvObject)
3004 FileDialogImpl *This = impl_from_IFileDialogCustomize(iface);
3005 return IFileDialog2_QueryInterface(&This->IFileDialog2_iface, riid, ppvObject);
3008 static ULONG WINAPI IFileDialogCustomize_fnAddRef(IFileDialogCustomize *iface)
3010 FileDialogImpl *This = impl_from_IFileDialogCustomize(iface);
3011 return IFileDialog2_AddRef(&This->IFileDialog2_iface);
3014 static ULONG WINAPI IFileDialogCustomize_fnRelease(IFileDialogCustomize *iface)
3016 FileDialogImpl *This = impl_from_IFileDialogCustomize(iface);
3017 return IFileDialog2_Release(&This->IFileDialog2_iface);
3020 static HRESULT WINAPI IFileDialogCustomize_fnEnableOpenDropDown(IFileDialogCustomize *iface,
3023 FileDialogImpl *This = impl_from_IFileDialogCustomize(iface);
3024 FIXME("stub - %p (%d)\n", This, dwIDCtl);
3028 static HRESULT WINAPI IFileDialogCustomize_fnAddMenu(IFileDialogCustomize *iface,
3032 FileDialogImpl *This = impl_from_IFileDialogCustomize(iface);
3036 TRACE("%p (%d, %p)\n", This, dwIDCtl, pszLabel);
3038 hr = cctrl_create_new(This, dwIDCtl, NULL, TOOLBARCLASSNAMEW,
3039 TBSTYLE_FLAT | CCS_NODIVIDER, 0,
3040 This->cctrl_def_height, &ctrl);
3043 ctrl->type = IDLG_CCTRL_MENU;
3045 /* Add the actual button with a popup menu. */
3046 tbb.iBitmap = I_IMAGENONE;
3047 tbb.dwData = (DWORD_PTR)CreatePopupMenu();
3048 tbb.iString = (DWORD_PTR)pszLabel;
3049 tbb.fsState = TBSTATE_ENABLED;
3050 tbb.fsStyle = BTNS_WHOLEDROPDOWN;
3053 SendMessageW(ctrl->hwnd, TB_ADDBUTTONSW, 1, (LPARAM)&tbb);
3059 static HRESULT WINAPI IFileDialogCustomize_fnAddPushButton(IFileDialogCustomize *iface,
3063 FileDialogImpl *This = impl_from_IFileDialogCustomize(iface);
3066 TRACE("%p (%d, %p)\n", This, dwIDCtl, pszLabel);
3068 hr = cctrl_create_new(This, dwIDCtl, pszLabel, WC_BUTTONW, BS_MULTILINE, 0,
3069 This->cctrl_def_height, &ctrl);
3071 ctrl->type = IDLG_CCTRL_PUSHBUTTON;
3076 static HRESULT WINAPI IFileDialogCustomize_fnAddComboBox(IFileDialogCustomize *iface,
3079 FileDialogImpl *This = impl_from_IFileDialogCustomize(iface);
3082 TRACE("%p (%d)\n", This, dwIDCtl);
3084 hr = cctrl_create_new(This, dwIDCtl, NULL, WC_COMBOBOXW, CBS_DROPDOWNLIST, 0,
3085 This->cctrl_def_height, &ctrl);
3087 ctrl->type = IDLG_CCTRL_COMBOBOX;
3092 static HRESULT WINAPI IFileDialogCustomize_fnAddRadioButtonList(IFileDialogCustomize *iface,
3095 FileDialogImpl *This = impl_from_IFileDialogCustomize(iface);
3096 FIXME("stub - %p (%d)\n", This, dwIDCtl);
3100 static HRESULT WINAPI IFileDialogCustomize_fnAddCheckButton(IFileDialogCustomize *iface,
3105 FileDialogImpl *This = impl_from_IFileDialogCustomize(iface);
3108 TRACE("%p (%d, %p, %d)\n", This, dwIDCtl, pszLabel, bChecked);
3110 hr = cctrl_create_new(This, dwIDCtl, pszLabel, WC_BUTTONW, BS_AUTOCHECKBOX, 0,
3111 This->cctrl_def_height, &ctrl);
3114 ctrl->type = IDLG_CCTRL_CHECKBUTTON;
3115 SendMessageW(ctrl->hwnd, BM_SETCHECK, bChecked ? BST_CHECKED : BST_UNCHECKED, 0);
3121 static HRESULT WINAPI IFileDialogCustomize_fnAddEditBox(IFileDialogCustomize *iface,
3125 FileDialogImpl *This = impl_from_IFileDialogCustomize(iface);
3128 TRACE("%p (%d, %p)\n", This, dwIDCtl, pszText);
3130 hr = cctrl_create_new(This, dwIDCtl, pszText, WC_EDITW, ES_AUTOHSCROLL, WS_EX_CLIENTEDGE,
3131 This->cctrl_def_height, &ctrl);
3133 ctrl->type = IDLG_CCTRL_EDITBOX;
3138 static HRESULT WINAPI IFileDialogCustomize_fnAddSeparator(IFileDialogCustomize *iface,
3141 FileDialogImpl *This = impl_from_IFileDialogCustomize(iface);
3144 TRACE("%p (%d)\n", This, dwIDCtl);
3146 hr = cctrl_create_new(This, dwIDCtl, NULL, WC_STATICW, SS_ETCHEDHORZ, 0,
3147 GetSystemMetrics(SM_CYEDGE), &ctrl);
3149 ctrl->type = IDLG_CCTRL_SEPARATOR;
3154 static HRESULT WINAPI IFileDialogCustomize_fnAddText(IFileDialogCustomize *iface,
3158 FileDialogImpl *This = impl_from_IFileDialogCustomize(iface);
3161 TRACE("%p (%d, %p)\n", This, dwIDCtl, pszText);
3163 hr = cctrl_create_new(This, dwIDCtl, pszText, WC_STATICW, 0, 0,
3164 This->cctrl_def_height, &ctrl);
3166 ctrl->type = IDLG_CCTRL_TEXT;
3171 static HRESULT WINAPI IFileDialogCustomize_fnSetControlLabel(IFileDialogCustomize *iface,
3175 FileDialogImpl *This = impl_from_IFileDialogCustomize(iface);
3176 customctrl *ctrl = get_cctrl(This, dwIDCtl);
3177 TRACE("%p (%d, %p)\n", This, dwIDCtl, pszLabel);
3179 if(!ctrl) return E_INVALIDARG;
3183 case IDLG_CCTRL_MENU:
3184 case IDLG_CCTRL_PUSHBUTTON:
3185 case IDLG_CCTRL_CHECKBUTTON:
3186 case IDLG_CCTRL_TEXT:
3187 SendMessageW(ctrl->hwnd, WM_SETTEXT, 0, (LPARAM)pszLabel);
3196 static HRESULT WINAPI IFileDialogCustomize_fnGetControlState(IFileDialogCustomize *iface,
3198 CDCONTROLSTATEF *pdwState)
3200 FileDialogImpl *This = impl_from_IFileDialogCustomize(iface);
3201 customctrl *ctrl = get_cctrl(This, dwIDCtl);
3202 TRACE("%p (%d, %p)\n", This, dwIDCtl, pdwState);
3204 if(!ctrl) return E_NOTIMPL;
3206 *pdwState = ctrl->cdcstate;
3210 static HRESULT WINAPI IFileDialogCustomize_fnSetControlState(IFileDialogCustomize *iface,
3212 CDCONTROLSTATEF dwState)
3214 FileDialogImpl *This = impl_from_IFileDialogCustomize(iface);
3215 customctrl *ctrl = get_cctrl(This,dwIDCtl);
3216 TRACE("%p (%d, %x)\n", This, dwIDCtl, dwState);
3220 LONG wndstyle = GetWindowLongW(ctrl->hwnd, GWL_STYLE);
3222 if(dwState & CDCS_ENABLED)
3223 wndstyle &= ~(WS_DISABLED);
3225 wndstyle |= WS_DISABLED;
3227 if(dwState & CDCS_VISIBLE)
3228 wndstyle |= WS_VISIBLE;
3230 wndstyle &= ~(WS_VISIBLE);
3232 SetWindowLongW(ctrl->hwnd, GWL_STYLE, wndstyle);
3234 /* We save the state separately since at least one application
3235 * relies on being able to hide a control. */
3236 ctrl->cdcstate = dwState;
3242 static HRESULT WINAPI IFileDialogCustomize_fnGetEditBoxText(IFileDialogCustomize *iface,
3246 FileDialogImpl *This = impl_from_IFileDialogCustomize(iface);
3247 customctrl *ctrl = get_cctrl(This, dwIDCtl);
3249 TRACE("%p (%d, %p)\n", This, dwIDCtl, ppszText);
3251 if(!ctrl || !(len = SendMessageW(ctrl->hwnd, WM_GETTEXTLENGTH, 0, 0)))
3254 text = CoTaskMemAlloc(sizeof(WCHAR)*(len+1));
3255 if(!text) return E_FAIL;
3257 SendMessageW(ctrl->hwnd, WM_GETTEXT, len+1, (LPARAM)text);
3262 static HRESULT WINAPI IFileDialogCustomize_fnSetEditBoxText(IFileDialogCustomize *iface,
3266 FileDialogImpl *This = impl_from_IFileDialogCustomize(iface);
3267 customctrl *ctrl = get_cctrl(This, dwIDCtl);
3268 TRACE("%p (%d, %s)\n", This, dwIDCtl, debugstr_w(pszText));
3270 if(!ctrl || ctrl->type != IDLG_CCTRL_EDITBOX)
3273 SendMessageW(ctrl->hwnd, WM_SETTEXT, 0, (LPARAM)pszText);
3277 static HRESULT WINAPI IFileDialogCustomize_fnGetCheckButtonState(IFileDialogCustomize *iface,
3281 FileDialogImpl *This = impl_from_IFileDialogCustomize(iface);
3282 customctrl *ctrl = get_cctrl(This, dwIDCtl);
3283 TRACE("%p (%d, %p)\n", This, dwIDCtl, pbChecked);
3286 *pbChecked = (SendMessageW(ctrl->hwnd, BM_GETCHECK, 0, 0) == BST_CHECKED);
3291 static HRESULT WINAPI IFileDialogCustomize_fnSetCheckButtonState(IFileDialogCustomize *iface,
3295 FileDialogImpl *This = impl_from_IFileDialogCustomize(iface);
3296 customctrl *ctrl = get_cctrl(This, dwIDCtl);
3297 TRACE("%p (%d, %d)\n", This, dwIDCtl, bChecked);
3300 SendMessageW(ctrl->hwnd, BM_SETCHECK, bChecked ? BST_CHECKED:BST_UNCHECKED, 0);
3305 static UINT get_combobox_index_from_id(HWND cb_hwnd, DWORD dwIDItem)
3307 UINT count = SendMessageW(cb_hwnd, CB_GETCOUNT, 0, 0);
3309 if(!count || (count == CB_ERR))
3312 for(i = 0; i < count; i++)
3313 if(SendMessageW(cb_hwnd, CB_GETITEMDATA, i, 0) == dwIDItem)
3316 TRACE("Item with id %d not found in combobox %p (item count: %d)\n", dwIDItem, cb_hwnd, count);
3320 static HRESULT WINAPI IFileDialogCustomize_fnAddControlItem(IFileDialogCustomize *iface,
3325 FileDialogImpl *This = impl_from_IFileDialogCustomize(iface);
3326 customctrl *ctrl = get_cctrl(This, dwIDCtl);
3327 TRACE("%p (%d, %d, %s)\n", This, dwIDCtl, dwIDItem, debugstr_w(pszLabel));
3329 if(!ctrl) return E_FAIL;
3333 case IDLG_CCTRL_COMBOBOX:
3337 if(get_combobox_index_from_id(ctrl->hwnd, dwIDItem) != -1)
3338 return E_INVALIDARG;
3340 index = SendMessageW(ctrl->hwnd, CB_ADDSTRING, 0, (LPARAM)pszLabel);
3341 SendMessageW(ctrl->hwnd, CB_SETITEMDATA, index, dwIDItem);
3345 case IDLG_CCTRL_MENU:
3348 SendMessageW(ctrl->hwnd, TB_GETBUTTON, 0, (LPARAM)&tbb);
3350 if(GetMenuState((HMENU)tbb.dwData, dwIDItem, MF_BYCOMMAND) != -1)
3351 return E_INVALIDARG;
3353 AppendMenuW((HMENU)tbb.dwData, MF_STRING, dwIDItem, pszLabel);
3360 return E_NOINTERFACE; /* win7 */
3363 static HRESULT WINAPI IFileDialogCustomize_fnRemoveControlItem(IFileDialogCustomize *iface,
3367 FileDialogImpl *This = impl_from_IFileDialogCustomize(iface);
3368 customctrl *ctrl = get_cctrl(This, dwIDCtl);
3369 TRACE("%p (%d, %d)\n", This, dwIDCtl, dwIDItem);
3371 if(!ctrl) return E_FAIL;
3375 case IDLG_CCTRL_COMBOBOX:
3377 UINT i, count = SendMessageW(ctrl->hwnd, CB_GETCOUNT, 0, 0);
3378 if(!count || (count == CB_ERR))
3381 for(i = 0; i < count; i++)
3382 if(SendMessageW(ctrl->hwnd, CB_GETITEMDATA, 0, 0) == dwIDItem)
3384 if(SendMessageW(ctrl->hwnd, CB_DELETESTRING, i, 0) == CB_ERR)
3389 return E_UNEXPECTED;
3391 case IDLG_CCTRL_MENU:
3395 SendMessageW(ctrl->hwnd, TB_GETBUTTON, 0, (LPARAM)&tbb);
3396 hmenu = (HMENU)tbb.dwData;
3398 if(!hmenu || !DeleteMenu(hmenu, dwIDItem, MF_BYCOMMAND))
3399 return E_UNEXPECTED;
3410 static HRESULT WINAPI IFileDialogCustomize_fnRemoveAllControlItems(IFileDialogCustomize *iface,
3413 FileDialogImpl *This = impl_from_IFileDialogCustomize(iface);
3414 TRACE("%p (%d)\n", This, dwIDCtl);
3416 /* Not implemented by native */
3420 static HRESULT WINAPI IFileDialogCustomize_fnGetControlItemState(IFileDialogCustomize *iface,
3423 CDCONTROLSTATEF *pdwState)
3425 FileDialogImpl *This = impl_from_IFileDialogCustomize(iface);
3426 FIXME("stub - %p\n", This);
3430 static HRESULT WINAPI IFileDialogCustomize_fnSetControlItemState(IFileDialogCustomize *iface,
3433 CDCONTROLSTATEF dwState)
3435 FileDialogImpl *This = impl_from_IFileDialogCustomize(iface);
3436 FIXME("stub - %p\n", This);
3440 static HRESULT WINAPI IFileDialogCustomize_fnGetSelectedControlItem(IFileDialogCustomize *iface,
3444 FileDialogImpl *This = impl_from_IFileDialogCustomize(iface);
3445 customctrl *ctrl = get_cctrl(This, dwIDCtl);
3446 TRACE("%p (%d, %p)\n", This, dwIDCtl, pdwIDItem);
3448 if(!ctrl) return E_FAIL;
3452 case IDLG_CCTRL_COMBOBOX:
3454 UINT index = SendMessageW(ctrl->hwnd, CB_GETCURSEL, 0, 0);
3458 *pdwIDItem = SendMessageW(ctrl->hwnd, CB_GETITEMDATA, index, 0);
3462 FIXME("Unsupported control type %d\n", ctrl->type);
3468 static HRESULT WINAPI IFileDialogCustomize_fnSetSelectedControlItem(IFileDialogCustomize *iface,
3472 FileDialogImpl *This = impl_from_IFileDialogCustomize(iface);
3473 customctrl *ctrl = get_cctrl(This, dwIDCtl);
3474 TRACE("%p (%d, %d)\n", This, dwIDCtl, dwIDItem);
3476 if(!ctrl) return E_INVALIDARG;
3480 case IDLG_CCTRL_COMBOBOX:
3482 UINT index = get_combobox_index_from_id(ctrl->hwnd, dwIDItem);
3485 return E_INVALIDARG;
3487 if(SendMessageW(ctrl->hwnd, CB_SETCURSEL, index, 0) == CB_ERR)
3493 FIXME("Unsupported control type %d\n", ctrl->type);
3496 return E_INVALIDARG;
3499 static HRESULT WINAPI IFileDialogCustomize_fnStartVisualGroup(IFileDialogCustomize *iface,
3503 FileDialogImpl *This = impl_from_IFileDialogCustomize(iface);
3504 FIXME("stub - %p (%d, %s)\n", This, dwIDCtl, debugstr_w(pszLabel));
3508 static HRESULT WINAPI IFileDialogCustomize_fnEndVisualGroup(IFileDialogCustomize *iface)
3510 FileDialogImpl *This = impl_from_IFileDialogCustomize(iface);
3511 FIXME("stub - %p\n", This);
3515 static HRESULT WINAPI IFileDialogCustomize_fnMakeProminent(IFileDialogCustomize *iface,
3518 FileDialogImpl *This = impl_from_IFileDialogCustomize(iface);
3519 FIXME("stub - %p (%d)\n", This, dwIDCtl);
3523 static HRESULT WINAPI IFileDialogCustomize_fnSetControlItemText(IFileDialogCustomize *iface,
3528 FileDialogImpl *This = impl_from_IFileDialogCustomize(iface);
3529 FIXME("stub - %p (%d, %d, %p)\n", This, dwIDCtl, dwIDItem, debugstr_w(pszLabel));
3533 static const IFileDialogCustomizeVtbl vt_IFileDialogCustomize = {
3534 IFileDialogCustomize_fnQueryInterface,
3535 IFileDialogCustomize_fnAddRef,
3536 IFileDialogCustomize_fnRelease,
3537 IFileDialogCustomize_fnEnableOpenDropDown,
3538 IFileDialogCustomize_fnAddMenu,
3539 IFileDialogCustomize_fnAddPushButton,
3540 IFileDialogCustomize_fnAddComboBox,
3541 IFileDialogCustomize_fnAddRadioButtonList,
3542 IFileDialogCustomize_fnAddCheckButton,
3543 IFileDialogCustomize_fnAddEditBox,
3544 IFileDialogCustomize_fnAddSeparator,
3545 IFileDialogCustomize_fnAddText,
3546 IFileDialogCustomize_fnSetControlLabel,
3547 IFileDialogCustomize_fnGetControlState,
3548 IFileDialogCustomize_fnSetControlState,
3549 IFileDialogCustomize_fnGetEditBoxText,
3550 IFileDialogCustomize_fnSetEditBoxText,
3551 IFileDialogCustomize_fnGetCheckButtonState,
3552 IFileDialogCustomize_fnSetCheckButtonState,
3553 IFileDialogCustomize_fnAddControlItem,
3554 IFileDialogCustomize_fnRemoveControlItem,
3555 IFileDialogCustomize_fnRemoveAllControlItems,
3556 IFileDialogCustomize_fnGetControlItemState,
3557 IFileDialogCustomize_fnSetControlItemState,
3558 IFileDialogCustomize_fnGetSelectedControlItem,
3559 IFileDialogCustomize_fnSetSelectedControlItem,
3560 IFileDialogCustomize_fnStartVisualGroup,
3561 IFileDialogCustomize_fnEndVisualGroup,
3562 IFileDialogCustomize_fnMakeProminent,
3563 IFileDialogCustomize_fnSetControlItemText
3566 static HRESULT FileDialog_constructor(IUnknown *pUnkOuter, REFIID riid, void **ppv, enum ITEMDLG_TYPE type)
3568 FileDialogImpl *fdimpl;
3571 TRACE("%p, %s, %p\n", pUnkOuter, debugstr_guid(riid), ppv);
3576 return CLASS_E_NOAGGREGATION;
3578 fdimpl = HeapAlloc(GetProcessHeap(), 0, sizeof(FileDialogImpl));
3580 return E_OUTOFMEMORY;
3583 fdimpl->IFileDialog2_iface.lpVtbl = &vt_IFileDialog2;
3584 fdimpl->IExplorerBrowserEvents_iface.lpVtbl = &vt_IExplorerBrowserEvents;
3585 fdimpl->IServiceProvider_iface.lpVtbl = &vt_IServiceProvider;
3586 fdimpl->ICommDlgBrowser3_iface.lpVtbl = &vt_ICommDlgBrowser3;
3587 fdimpl->IOleWindow_iface.lpVtbl = &vt_IOleWindow;
3588 fdimpl->IFileDialogCustomize_iface.lpVtbl = &vt_IFileDialogCustomize;
3590 if(type == ITEMDLG_TYPE_OPEN)
3592 fdimpl->dlg_type = ITEMDLG_TYPE_OPEN;
3593 fdimpl->u.IFileOpenDialog_iface.lpVtbl = &vt_IFileOpenDialog;
3594 fdimpl->options = FOS_PATHMUSTEXIST | FOS_FILEMUSTEXIST | FOS_NOCHANGEDIR;
3595 fdimpl->custom_title = fdimpl->custom_okbutton = NULL;
3600 fdimpl->dlg_type = ITEMDLG_TYPE_SAVE;
3601 fdimpl->u.IFileSaveDialog_iface.lpVtbl = &vt_IFileSaveDialog;
3602 fdimpl->options = FOS_OVERWRITEPROMPT | FOS_NOREADONLYRETURN | FOS_PATHMUSTEXIST | FOS_NOCHANGEDIR;
3604 LoadStringW(COMDLG32_hInstance, IDS_SAVE, buf, sizeof(buf)/sizeof(WCHAR));
3605 fdimpl->custom_title = StrDupW(buf);
3606 fdimpl->custom_okbutton = StrDupW(buf);
3609 fdimpl->filterspecs = NULL;
3610 fdimpl->filterspec_count = 0;
3611 fdimpl->filetypeindex = 0;
3613 fdimpl->psia_selection = fdimpl->psia_results = NULL;
3614 fdimpl->psi_setfolder = fdimpl->psi_folder = NULL;
3616 list_init(&fdimpl->events_clients);
3617 fdimpl->events_next_cookie = 0;
3619 fdimpl->dlg_hwnd = NULL;
3622 fdimpl->set_filename = NULL;
3623 fdimpl->default_ext = NULL;
3624 fdimpl->custom_cancelbutton = fdimpl->custom_filenamelabel = NULL;
3626 /* FIXME: The default folder setting should be restored for the
3627 * application if it was previously set. */
3628 SHGetDesktopFolder(&psf);
3629 SHGetItemFromObject((IUnknown*)psf, &IID_IShellItem, (void**)&fdimpl->psi_defaultfolder);
3630 IShellFolder_Release(psf);
3632 hr = init_custom_controls(fdimpl);
3635 ERR("Failed to initialize custom controls (0x%08x).\n", hr);
3636 IUnknown_Release((IUnknown*)fdimpl);
3640 hr = IUnknown_QueryInterface((IUnknown*)fdimpl, riid, ppv);
3641 IUnknown_Release((IUnknown*)fdimpl);
3645 HRESULT FileOpenDialog_Constructor(IUnknown *pUnkOuter, REFIID riid, void **ppv)
3647 return FileDialog_constructor(pUnkOuter, riid, ppv, ITEMDLG_TYPE_OPEN);
3650 HRESULT FileSaveDialog_Constructor(IUnknown *pUnkOuter, REFIID riid, void **ppv)
3652 return FileDialog_constructor(pUnkOuter, riid, ppv, ITEMDLG_TYPE_SAVE);