Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
wine-mirror
GitHub Repository: wine-mirror/wine
Path: blob/master/dlls/comdlg32/itemdlg.c
4389 views
1
/*
2
* Common Item Dialog
3
*
4
* Copyright 2010,2011 David Hedberg
5
*
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.
10
*
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.
15
*
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
19
*/
20
21
#include <stdarg.h>
22
23
#define COBJMACROS
24
#include "windef.h"
25
#include "winbase.h"
26
#include "winuser.h"
27
#include "wingdi.h"
28
#include "winreg.h"
29
#include "shlwapi.h"
30
31
#include "commdlg.h"
32
#include "cdlg.h"
33
#include "filedlgbrowser.h"
34
35
#include "wine/debug.h"
36
#include "wine/list.h"
37
38
#define IDC_NAV_TOOLBAR 200
39
#define IDC_NAVBACK 201
40
#define IDC_NAVFORWARD 202
41
#define IDC_NAVUP 203
42
43
#include <initguid.h>
44
/* This seems to be another version of IID_IFileDialogCustomize. If
45
* there is any difference I have yet to find it. */
46
DEFINE_GUID(IID_IFileDialogCustomizeAlt, 0x8016B7B3, 0x3D49, 0x4504, 0xA0,0xAA, 0x2A,0x37,0x49,0x4E,0x60,0x6F);
47
48
WINE_DEFAULT_DEBUG_CHANNEL(commdlg);
49
50
enum ITEMDLG_TYPE {
51
ITEMDLG_TYPE_OPEN,
52
ITEMDLG_TYPE_SAVE
53
};
54
55
enum ITEMDLG_CCTRL_TYPE {
56
IDLG_CCTRL_MENU,
57
IDLG_CCTRL_PUSHBUTTON,
58
IDLG_CCTRL_COMBOBOX,
59
IDLG_CCTRL_RADIOBUTTONLIST,
60
IDLG_CCTRL_CHECKBUTTON,
61
IDLG_CCTRL_EDITBOX,
62
IDLG_CCTRL_SEPARATOR,
63
IDLG_CCTRL_TEXT,
64
IDLG_CCTRL_OPENDROPDOWN,
65
IDLG_CCTRL_VISUALGROUP
66
};
67
68
typedef struct cctrl_item {
69
DWORD id, parent_id;
70
LPWSTR label;
71
CDCONTROLSTATEF cdcstate;
72
HWND hwnd;
73
struct list entry;
74
} cctrl_item;
75
76
typedef struct {
77
HWND hwnd, wrapper_hwnd;
78
UINT id, dlgid;
79
enum ITEMDLG_CCTRL_TYPE type;
80
CDCONTROLSTATEF cdcstate;
81
struct list entry;
82
83
struct list sub_cctrls;
84
struct list sub_cctrls_entry;
85
struct list sub_items;
86
} customctrl;
87
88
typedef struct {
89
struct list entry;
90
IFileDialogEvents *pfde;
91
DWORD cookie;
92
} events_client;
93
94
typedef struct FileDialogImpl {
95
IFileDialog2 IFileDialog2_iface;
96
union {
97
IFileOpenDialog IFileOpenDialog_iface;
98
IFileSaveDialog IFileSaveDialog_iface;
99
} u;
100
enum ITEMDLG_TYPE dlg_type;
101
IExplorerBrowserEvents IExplorerBrowserEvents_iface;
102
IServiceProvider IServiceProvider_iface;
103
ICommDlgBrowser3 ICommDlgBrowser3_iface;
104
IOleWindow IOleWindow_iface;
105
IFileDialogCustomize IFileDialogCustomize_iface;
106
LONG ref;
107
108
FILEOPENDIALOGOPTIONS options;
109
COMDLG_FILTERSPEC *filterspecs;
110
UINT filterspec_count;
111
UINT filetypeindex;
112
113
struct list events_clients;
114
DWORD events_next_cookie;
115
116
IShellItemArray *psia_selection;
117
IShellItemArray *psia_results;
118
IShellItem *psi_defaultfolder;
119
IShellItem *psi_setfolder;
120
IShellItem *psi_folder;
121
122
HWND dlg_hwnd;
123
IExplorerBrowser *peb;
124
DWORD ebevents_cookie;
125
126
LPWSTR set_filename;
127
LPWSTR default_ext;
128
LPWSTR custom_title;
129
LPWSTR custom_okbutton;
130
LPWSTR custom_cancelbutton;
131
LPWSTR custom_filenamelabel;
132
LPWSTR current_filter;
133
134
UINT cctrl_width, cctrl_def_height, cctrls_cols;
135
UINT cctrl_indent, dpi_x, dpi_y;
136
HWND cctrls_hwnd;
137
struct list cctrls;
138
UINT_PTR cctrl_next_dlgid;
139
customctrl *cctrl_active_vg;
140
141
HMENU hmenu_opendropdown;
142
customctrl cctrl_opendropdown;
143
HFONT hfont_opendropdown;
144
BOOL opendropdown_has_selection;
145
DWORD opendropdown_selection;
146
147
GUID client_guid;
148
149
HANDLE user_actctx;
150
} FileDialogImpl;
151
152
/**************************************************************************
153
* Event wrappers.
154
*/
155
static HRESULT events_OnFileOk(FileDialogImpl *This)
156
{
157
ULONG_PTR ctx_cookie = 0;
158
events_client *cursor;
159
HRESULT hr = S_OK;
160
TRACE("%p\n", This);
161
162
if (This->user_actctx != INVALID_HANDLE_VALUE)
163
ActivateActCtx(This->user_actctx, &ctx_cookie);
164
165
LIST_FOR_EACH_ENTRY(cursor, &This->events_clients, events_client, entry)
166
{
167
TRACE("Notifying %p\n", cursor);
168
hr = IFileDialogEvents_OnFileOk(cursor->pfde, (IFileDialog*)&This->IFileDialog2_iface);
169
if(FAILED(hr) && hr != E_NOTIMPL)
170
break;
171
}
172
173
if (This->user_actctx != INVALID_HANDLE_VALUE)
174
DeactivateActCtx(0, ctx_cookie);
175
176
if(hr == E_NOTIMPL)
177
hr = S_OK;
178
179
return hr;
180
}
181
182
static HRESULT events_OnFolderChanging(FileDialogImpl *This, IShellItem *folder)
183
{
184
ULONG_PTR ctx_cookie = 0;
185
events_client *cursor;
186
HRESULT hr = S_OK;
187
TRACE("%p (%p)\n", This, folder);
188
189
if (This->user_actctx != INVALID_HANDLE_VALUE)
190
ActivateActCtx(This->user_actctx, &ctx_cookie);
191
192
LIST_FOR_EACH_ENTRY(cursor, &This->events_clients, events_client, entry)
193
{
194
TRACE("Notifying %p\n", cursor);
195
hr = IFileDialogEvents_OnFolderChanging(cursor->pfde, (IFileDialog*)&This->IFileDialog2_iface, folder);
196
if(FAILED(hr) && hr != E_NOTIMPL)
197
break;
198
}
199
200
if (This->user_actctx != INVALID_HANDLE_VALUE)
201
DeactivateActCtx(0, ctx_cookie);
202
203
if(hr == E_NOTIMPL)
204
hr = S_OK;
205
206
return hr;
207
}
208
209
static void events_OnFolderChange(FileDialogImpl *This)
210
{
211
ULONG_PTR ctx_cookie = 0;
212
events_client *cursor;
213
TRACE("%p\n", This);
214
215
if (This->user_actctx != INVALID_HANDLE_VALUE)
216
ActivateActCtx(This->user_actctx, &ctx_cookie);
217
218
LIST_FOR_EACH_ENTRY(cursor, &This->events_clients, events_client, entry)
219
{
220
TRACE("Notifying %p\n", cursor);
221
IFileDialogEvents_OnFolderChange(cursor->pfde, (IFileDialog*)&This->IFileDialog2_iface);
222
}
223
224
if (This->user_actctx != INVALID_HANDLE_VALUE)
225
DeactivateActCtx(0, ctx_cookie);
226
}
227
228
static void events_OnSelectionChange(FileDialogImpl *This)
229
{
230
ULONG_PTR ctx_cookie = 0;
231
events_client *cursor;
232
TRACE("%p\n", This);
233
234
if (This->user_actctx != INVALID_HANDLE_VALUE)
235
ActivateActCtx(This->user_actctx, &ctx_cookie);
236
237
LIST_FOR_EACH_ENTRY(cursor, &This->events_clients, events_client, entry)
238
{
239
TRACE("Notifying %p\n", cursor);
240
IFileDialogEvents_OnSelectionChange(cursor->pfde, (IFileDialog*)&This->IFileDialog2_iface);
241
}
242
243
if (This->user_actctx != INVALID_HANDLE_VALUE)
244
DeactivateActCtx(0, ctx_cookie);
245
}
246
247
static void events_OnTypeChange(FileDialogImpl *This)
248
{
249
ULONG_PTR ctx_cookie = 0;
250
events_client *cursor;
251
TRACE("%p\n", This);
252
253
if (This->user_actctx != INVALID_HANDLE_VALUE)
254
ActivateActCtx(This->user_actctx, &ctx_cookie);
255
256
LIST_FOR_EACH_ENTRY(cursor, &This->events_clients, events_client, entry)
257
{
258
TRACE("Notifying %p\n", cursor);
259
IFileDialogEvents_OnTypeChange(cursor->pfde, (IFileDialog*)&This->IFileDialog2_iface);
260
}
261
262
if (This->user_actctx != INVALID_HANDLE_VALUE)
263
DeactivateActCtx(0, ctx_cookie);
264
}
265
266
static HRESULT events_OnOverwrite(FileDialogImpl *This, IShellItem *shellitem)
267
{
268
ULONG_PTR ctx_cookie = 0;
269
events_client *cursor;
270
HRESULT hr = S_OK;
271
FDE_OVERWRITE_RESPONSE response = FDEOR_DEFAULT;
272
TRACE("%p %p\n", This, shellitem);
273
274
if (This->user_actctx != INVALID_HANDLE_VALUE)
275
ActivateActCtx(This->user_actctx, &ctx_cookie);
276
277
LIST_FOR_EACH_ENTRY(cursor, &This->events_clients, events_client, entry)
278
{
279
TRACE("Notifying %p\n", cursor);
280
hr = IFileDialogEvents_OnOverwrite(cursor->pfde, (IFileDialog*)&This->IFileDialog2_iface, shellitem, &response);
281
TRACE("<-- hr=%lx response=%u\n", hr, response);
282
if(FAILED(hr) && hr != E_NOTIMPL)
283
break;
284
}
285
286
if (This->user_actctx != INVALID_HANDLE_VALUE)
287
DeactivateActCtx(0, ctx_cookie);
288
289
if(hr == E_NOTIMPL)
290
hr = S_OK;
291
292
if(SUCCEEDED(hr))
293
{
294
if (response == FDEOR_DEFAULT)
295
{
296
WCHAR buf[100];
297
int answer;
298
299
LoadStringW(COMDLG32_hInstance, IDS_OVERWRITEFILE, buf, 100);
300
answer = MessageBoxW(This->dlg_hwnd, buf, This->custom_title,
301
MB_YESNO | MB_ICONEXCLAMATION);
302
if (answer == IDNO || answer == IDCANCEL)
303
{
304
hr = E_FAIL;
305
}
306
}
307
else if (response == FDEOR_REFUSE)
308
hr = E_FAIL;
309
}
310
311
return hr;
312
}
313
314
static inline HRESULT get_cctrl_event(IFileDialogEvents *pfde, IFileDialogControlEvents **pfdce)
315
{
316
return IFileDialogEvents_QueryInterface(pfde, &IID_IFileDialogControlEvents, (void**)pfdce);
317
}
318
319
static HRESULT cctrl_event_OnButtonClicked(FileDialogImpl *This, DWORD ctl_id)
320
{
321
ULONG_PTR ctx_cookie = 0;
322
events_client *cursor;
323
TRACE("%p\n", This);
324
325
if (This->user_actctx != INVALID_HANDLE_VALUE)
326
ActivateActCtx(This->user_actctx, &ctx_cookie);
327
328
LIST_FOR_EACH_ENTRY(cursor, &This->events_clients, events_client, entry)
329
{
330
IFileDialogControlEvents *pfdce;
331
if(SUCCEEDED(get_cctrl_event(cursor->pfde, &pfdce)))
332
{
333
TRACE("Notifying %p\n", cursor);
334
IFileDialogControlEvents_OnButtonClicked(pfdce, &This->IFileDialogCustomize_iface, ctl_id);
335
IFileDialogControlEvents_Release(pfdce);
336
}
337
}
338
339
if (This->user_actctx != INVALID_HANDLE_VALUE)
340
DeactivateActCtx(0, ctx_cookie);
341
342
return S_OK;
343
}
344
345
static HRESULT cctrl_event_OnItemSelected(FileDialogImpl *This, DWORD ctl_id, DWORD item_id)
346
{
347
ULONG_PTR ctx_cookie = 0;
348
events_client *cursor;
349
TRACE("%p %li %li\n", This, ctl_id, item_id);
350
351
if (This->user_actctx != INVALID_HANDLE_VALUE)
352
ActivateActCtx(This->user_actctx, &ctx_cookie);
353
354
LIST_FOR_EACH_ENTRY(cursor, &This->events_clients, events_client, entry)
355
{
356
IFileDialogControlEvents *pfdce;
357
if(SUCCEEDED(get_cctrl_event(cursor->pfde, &pfdce)))
358
{
359
TRACE("Notifying %p\n", cursor);
360
IFileDialogControlEvents_OnItemSelected(pfdce, &This->IFileDialogCustomize_iface, ctl_id, item_id);
361
IFileDialogControlEvents_Release(pfdce);
362
}
363
}
364
365
if (This->user_actctx != INVALID_HANDLE_VALUE)
366
DeactivateActCtx(0, ctx_cookie);
367
368
return S_OK;
369
}
370
371
static HRESULT cctrl_event_OnCheckButtonToggled(FileDialogImpl *This, DWORD ctl_id, BOOL checked)
372
{
373
ULONG_PTR ctx_cookie = 0;
374
events_client *cursor;
375
TRACE("%p\n", This);
376
377
if (This->user_actctx != INVALID_HANDLE_VALUE)
378
ActivateActCtx(This->user_actctx, &ctx_cookie);
379
380
LIST_FOR_EACH_ENTRY(cursor, &This->events_clients, events_client, entry)
381
{
382
IFileDialogControlEvents *pfdce;
383
if(SUCCEEDED(get_cctrl_event(cursor->pfde, &pfdce)))
384
{
385
TRACE("Notifying %p\n", cursor);
386
IFileDialogControlEvents_OnCheckButtonToggled(pfdce, &This->IFileDialogCustomize_iface, ctl_id, checked);
387
IFileDialogControlEvents_Release(pfdce);
388
}
389
}
390
391
if (This->user_actctx != INVALID_HANDLE_VALUE)
392
DeactivateActCtx(0, ctx_cookie);
393
394
return S_OK;
395
}
396
397
static HRESULT cctrl_event_OnControlActivating(FileDialogImpl *This,
398
DWORD ctl_id)
399
{
400
ULONG_PTR ctx_cookie = 0;
401
events_client *cursor;
402
TRACE("%p\n", This);
403
404
if (This->user_actctx != INVALID_HANDLE_VALUE)
405
ActivateActCtx(This->user_actctx, &ctx_cookie);
406
407
LIST_FOR_EACH_ENTRY(cursor, &This->events_clients, events_client, entry)
408
{
409
IFileDialogControlEvents *pfdce;
410
if(SUCCEEDED(get_cctrl_event(cursor->pfde, &pfdce)))
411
{
412
TRACE("Notifying %p\n", cursor);
413
IFileDialogControlEvents_OnControlActivating(pfdce, &This->IFileDialogCustomize_iface, ctl_id);
414
IFileDialogControlEvents_Release(pfdce);
415
}
416
}
417
418
if (This->user_actctx != INVALID_HANDLE_VALUE)
419
DeactivateActCtx(0, ctx_cookie);
420
421
return S_OK;
422
}
423
424
/**************************************************************************
425
* Helper functions.
426
*/
427
static UINT get_file_name(FileDialogImpl *This, LPWSTR *str)
428
{
429
HWND hwnd_edit = GetDlgItem(This->dlg_hwnd, IDC_FILENAME);
430
UINT len;
431
432
if(!hwnd_edit)
433
{
434
if(This->set_filename)
435
{
436
len = lstrlenW(This->set_filename);
437
*str = CoTaskMemAlloc(sizeof(WCHAR)*(len+1));
438
lstrcpyW(*str, This->set_filename);
439
return len;
440
}
441
return 0;
442
}
443
444
len = SendMessageW(hwnd_edit, WM_GETTEXTLENGTH, 0, 0);
445
*str = CoTaskMemAlloc(sizeof(WCHAR)*(len+1));
446
if(!*str)
447
return 0;
448
449
SendMessageW(hwnd_edit, WM_GETTEXT, len+1, (LPARAM)*str);
450
return len;
451
}
452
453
static void set_current_filter(FileDialogImpl *This, LPCWSTR str)
454
{
455
IShellView *psv;
456
457
if(str && !str[0])
458
return;
459
460
if(This->current_filter)
461
LocalFree(This->current_filter);
462
463
This->current_filter = str ? StrDupW(str) : NULL;
464
465
if (This->peb && SUCCEEDED(IExplorerBrowser_GetCurrentView(This->peb, &IID_IShellView, (void**)&psv)))
466
{
467
IShellView_Refresh(psv);
468
IShellView_Release(psv);
469
}
470
}
471
472
static BOOL set_file_name(FileDialogImpl *This, LPCWSTR str)
473
{
474
if(This->set_filename)
475
LocalFree(This->set_filename);
476
477
This->set_filename = str ? StrDupW(str) : NULL;
478
479
if (str && wcspbrk(str, L"*?"))
480
set_current_filter(This, str);
481
482
return SetDlgItemTextW(This->dlg_hwnd, IDC_FILENAME, This->set_filename);
483
}
484
485
static void fill_filename_from_selection(FileDialogImpl *This)
486
{
487
IShellItem *psi;
488
LPWSTR *names;
489
HRESULT hr;
490
DWORD item_count;
491
UINT valid_count;
492
UINT len_total, i;
493
494
if(!This->psia_selection)
495
return;
496
497
hr = IShellItemArray_GetCount(This->psia_selection, &item_count);
498
if(FAILED(hr) || !item_count)
499
return;
500
501
names = HeapAlloc(GetProcessHeap(), 0, item_count*sizeof(LPWSTR));
502
503
/* Get names of the selected items */
504
valid_count = 0; len_total = 0;
505
for(i = 0; i < item_count; i++)
506
{
507
hr = IShellItemArray_GetItemAt(This->psia_selection, i, &psi);
508
if(SUCCEEDED(hr))
509
{
510
DWORD attr;
511
512
hr = IShellItem_GetAttributes(psi, SFGAO_FOLDER, &attr);
513
if(SUCCEEDED(hr) &&
514
(( (This->options & FOS_PICKFOLDERS) && !(attr & SFGAO_FOLDER)) ||
515
(!(This->options & FOS_PICKFOLDERS) && (attr & SFGAO_FOLDER))))
516
continue;
517
518
hr = IShellItem_GetDisplayName(psi, (This->options & FOS_PICKFOLDERS) ? SIGDN_FILESYSPATH : SIGDN_PARENTRELATIVEPARSING, &names[valid_count]);
519
if(SUCCEEDED(hr))
520
{
521
len_total += lstrlenW(names[valid_count]) + 3;
522
valid_count++;
523
}
524
IShellItem_Release(psi);
525
}
526
}
527
528
if(valid_count == 1)
529
{
530
set_file_name(This, names[0]);
531
CoTaskMemFree(names[0]);
532
}
533
else if(valid_count > 1)
534
{
535
LPWSTR string = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR)*len_total);
536
LPWSTR cur_point = string;
537
538
for(i = 0; i < valid_count; i++)
539
{
540
LPWSTR file = names[i];
541
*cur_point++ = '\"';
542
lstrcpyW(cur_point, file);
543
cur_point += lstrlenW(file);
544
*cur_point++ = '\"';
545
*cur_point++ = ' ';
546
CoTaskMemFree(file);
547
}
548
*(cur_point-1) = '\0';
549
550
set_file_name(This, string);
551
HeapFree(GetProcessHeap(), 0, string);
552
}
553
554
HeapFree(GetProcessHeap(), 0, names);
555
return;
556
}
557
558
static LPWSTR get_first_ext_from_spec(LPWSTR buf, LPCWSTR spec)
559
{
560
WCHAR *endpos, *ext;
561
INT len;
562
563
if( (endpos = StrChrW(spec, ';')) )
564
len = endpos-spec+1;
565
else
566
len = lstrlenW(spec)+1;
567
568
if (len > MAX_PATH)
569
return NULL;
570
571
lstrcpynW(buf, spec, len);
572
573
ext = PathFindExtensionW(buf);
574
if(StrChrW(ext, '*'))
575
return NULL;
576
577
return ext;
578
}
579
580
static BOOL shell_item_exists(IShellItem* shellitem)
581
{
582
LPWSTR filename;
583
HRESULT hr;
584
BOOL result;
585
586
hr = IShellItem_GetDisplayName(shellitem, SIGDN_FILESYSPATH, &filename);
587
if (SUCCEEDED(hr))
588
{
589
/* FIXME: Implement SFGAO_VALIDATE in Wine and use it instead. */
590
result = (GetFileAttributesW(filename) != INVALID_FILE_ATTRIBUTES);
591
CoTaskMemFree(filename);
592
}
593
else
594
{
595
SFGAOF attributes;
596
result = SUCCEEDED(IShellItem_GetAttributes(shellitem, SFGAO_VALIDATE, &attributes));
597
}
598
599
return result;
600
}
601
602
static HRESULT on_default_action(FileDialogImpl *This)
603
{
604
IShellFolder *psf_parent, *psf_desktop;
605
LPITEMIDLIST *pidla;
606
LPITEMIDLIST current_folder;
607
LPWSTR fn_iter, files = NULL, tmp_files, filter = NULL;
608
UINT file_count = 0, len, i;
609
int open_action;
610
HRESULT hr, ret = E_FAIL;
611
612
len = get_file_name(This, &tmp_files);
613
if(len)
614
{
615
UINT size_used;
616
file_count = COMDLG32_SplitFileNames(tmp_files, len, &files, &size_used);
617
CoTaskMemFree(tmp_files);
618
}
619
if(!file_count) return E_FAIL;
620
621
hr = SHGetIDListFromObject((IUnknown*)This->psi_folder, &current_folder);
622
if(FAILED(hr))
623
{
624
ERR("Failed to get pidl for current directory.\n");
625
HeapFree(GetProcessHeap(), 0, files);
626
return hr;
627
}
628
629
TRACE("Acting on %d file(s).\n", file_count);
630
631
pidla = HeapAlloc(GetProcessHeap(), 0, sizeof(LPITEMIDLIST) * file_count);
632
open_action = ONOPEN_OPEN;
633
fn_iter = files;
634
635
for(i = 0; i < file_count && open_action == ONOPEN_OPEN; i++)
636
{
637
WCHAR canon_filename[MAX_PATH];
638
psf_parent = NULL;
639
640
COMDLG32_GetCanonicalPath(current_folder, fn_iter, canon_filename);
641
642
if( (This->options & FOS_NOVALIDATE) &&
643
!(This->options & FOS_FILEMUSTEXIST) )
644
open_action = ONOPEN_OPEN;
645
else
646
open_action = ONOPEN_BROWSE;
647
648
open_action = FILEDLG95_ValidatePathAction(canon_filename, &psf_parent, This->dlg_hwnd,
649
This->options & ~FOS_FILEMUSTEXIST,
650
(This->dlg_type == ITEMDLG_TYPE_SAVE),
651
open_action);
652
653
/* Add the proper extension */
654
if(open_action == ONOPEN_OPEN)
655
{
656
WCHAR extbuf[MAX_PATH], *newext = NULL;
657
658
if(This->current_filter)
659
{
660
newext = get_first_ext_from_spec(extbuf, This->current_filter);
661
}
662
663
if(!newext && This->default_ext)
664
{
665
lstrcpyW(extbuf, L".");
666
lstrcatW(extbuf, This->default_ext);
667
newext = extbuf;
668
}
669
670
if(This->dlg_type == ITEMDLG_TYPE_SAVE)
671
{
672
if(newext)
673
{
674
WCHAR *ext = PathFindExtensionW(canon_filename);
675
if(lstrcmpiW(ext, newext))
676
lstrcatW(canon_filename, newext);
677
}
678
}
679
else
680
{
681
if( !(This->options & FOS_NOVALIDATE) && (This->options & FOS_FILEMUSTEXIST) &&
682
!PathFileExistsW(canon_filename))
683
{
684
if(newext)
685
{
686
lstrcatW(canon_filename, newext);
687
688
if(!PathFileExistsW(canon_filename))
689
{
690
FILEDLG95_OnOpenMessage(This->dlg_hwnd, 0, IDS_FILENOTEXISTING);
691
open_action = ONOPEN_BROWSE;
692
}
693
}
694
else
695
{
696
FILEDLG95_OnOpenMessage(This->dlg_hwnd, 0, IDS_FILENOTEXISTING);
697
open_action = ONOPEN_BROWSE;
698
}
699
}
700
}
701
} else if (open_action == ONOPEN_SEARCH) {
702
filter = fn_iter;
703
}
704
705
pidla[i] = SHSimpleIDListFromPath(canon_filename);
706
707
if(psf_parent && !(open_action == ONOPEN_BROWSE))
708
IShellFolder_Release(psf_parent);
709
710
fn_iter += (WCHAR)lstrlenW(fn_iter) + 1;
711
}
712
713
714
if((This->options & FOS_PICKFOLDERS) && open_action == ONOPEN_BROWSE)
715
open_action = ONOPEN_OPEN; /* FIXME: Multiple folders? */
716
717
switch(open_action)
718
{
719
case ONOPEN_SEARCH:
720
set_current_filter(This, filter);
721
break;
722
723
case ONOPEN_BROWSE:
724
hr = IExplorerBrowser_BrowseToObject(This->peb, (IUnknown*)psf_parent, SBSP_DEFBROWSER);
725
if(FAILED(hr))
726
ERR("Failed to browse to directory: %08lx\n", hr);
727
728
IShellFolder_Release(psf_parent);
729
break;
730
731
case ONOPEN_OPEN:
732
hr = SHGetDesktopFolder(&psf_desktop);
733
if(SUCCEEDED(hr))
734
{
735
if(This->psia_results)
736
{
737
IShellItemArray_Release(This->psia_results);
738
This->psia_results = NULL;
739
}
740
741
hr = SHCreateShellItemArray(NULL, psf_desktop, file_count, (PCUITEMID_CHILD_ARRAY)pidla,
742
&This->psia_results);
743
744
IShellFolder_Release(psf_desktop);
745
746
if(FAILED(hr))
747
break;
748
749
if(This->options & FOS_PICKFOLDERS)
750
{
751
SFGAOF attributes;
752
hr = IShellItemArray_GetAttributes(This->psia_results, SIATTRIBFLAGS_AND, SFGAO_FOLDER, &attributes);
753
if(hr != S_OK)
754
{
755
WCHAR buf[64];
756
LoadStringW(COMDLG32_hInstance, IDS_INVALID_FOLDERNAME, buf, ARRAY_SIZE(buf));
757
758
MessageBoxW(This->dlg_hwnd, buf, This->custom_title, MB_OK | MB_ICONEXCLAMATION);
759
760
IShellItemArray_Release(This->psia_results);
761
This->psia_results = NULL;
762
break;
763
}
764
}
765
766
if((This->options & FOS_OVERWRITEPROMPT) && This->dlg_type == ITEMDLG_TYPE_SAVE)
767
{
768
IShellItem *shellitem;
769
770
for (i=0; SUCCEEDED(hr) && i<file_count; i++)
771
{
772
hr = IShellItemArray_GetItemAt(This->psia_results, i, &shellitem);
773
if (SUCCEEDED(hr))
774
{
775
if (shell_item_exists(shellitem))
776
hr = events_OnOverwrite(This, shellitem);
777
778
IShellItem_Release(shellitem);
779
}
780
}
781
782
if (FAILED(hr))
783
break;
784
}
785
786
if(events_OnFileOk(This) == S_OK)
787
ret = S_OK;
788
}
789
break;
790
791
default:
792
ERR("Failed.\n");
793
break;
794
}
795
796
/* Clean up */
797
HeapFree(GetProcessHeap(), 0, files);
798
ILFree(current_folder);
799
for(i = 0; i < file_count; i++)
800
ILFree(pidla[i]);
801
HeapFree(GetProcessHeap(), 0, pidla);
802
803
/* Success closes the dialog */
804
return ret;
805
}
806
807
static void show_opendropdown(FileDialogImpl *This)
808
{
809
HWND open_hwnd;
810
RECT open_rc;
811
MSG msg;
812
813
open_hwnd = GetDlgItem(This->dlg_hwnd, IDOK);
814
815
GetWindowRect(open_hwnd, &open_rc);
816
817
if (TrackPopupMenu(This->hmenu_opendropdown, 0, open_rc.left, open_rc.bottom, 0, This->dlg_hwnd, NULL) &&
818
PeekMessageW(&msg, This->dlg_hwnd, WM_MENUCOMMAND, WM_MENUCOMMAND, PM_REMOVE))
819
{
820
MENUITEMINFOW mii;
821
822
This->opendropdown_has_selection = TRUE;
823
824
mii.cbSize = sizeof(mii);
825
mii.fMask = MIIM_ID;
826
GetMenuItemInfoW((HMENU)msg.lParam, msg.wParam, TRUE, &mii);
827
This->opendropdown_selection = mii.wID;
828
829
if(SUCCEEDED(on_default_action(This)))
830
EndDialog(This->dlg_hwnd, S_OK);
831
else
832
This->opendropdown_has_selection = FALSE;
833
}
834
}
835
836
/**************************************************************************
837
* Control item functions.
838
*/
839
840
static void item_free(cctrl_item *item)
841
{
842
DestroyWindow(item->hwnd);
843
HeapFree(GetProcessHeap(), 0, item->label);
844
HeapFree(GetProcessHeap(), 0, item);
845
}
846
847
static cctrl_item* get_item(customctrl* parent, DWORD itemid, CDCONTROLSTATEF visible_flags, DWORD* position)
848
{
849
DWORD dummy;
850
cctrl_item* item;
851
852
if (!position) position = &dummy;
853
854
*position = 0;
855
856
LIST_FOR_EACH_ENTRY(item, &parent->sub_items, cctrl_item, entry)
857
{
858
if (item->id == itemid)
859
return item;
860
861
if ((item->cdcstate & visible_flags) == visible_flags)
862
(*position)++;
863
}
864
865
return NULL;
866
}
867
868
static cctrl_item* get_first_item(customctrl* parent)
869
{
870
cctrl_item* item;
871
872
LIST_FOR_EACH_ENTRY(item, &parent->sub_items, cctrl_item, entry)
873
{
874
if ((item->cdcstate & (CDCS_VISIBLE|CDCS_ENABLED)) == (CDCS_VISIBLE|CDCS_ENABLED))
875
return item;
876
}
877
878
return NULL;
879
}
880
881
static HRESULT add_item(customctrl* parent, DWORD itemid, LPCWSTR label, cctrl_item** result)
882
{
883
cctrl_item* item;
884
LPWSTR label_copy;
885
886
if (get_item(parent, itemid, 0, NULL))
887
return E_INVALIDARG;
888
889
item = HeapAlloc(GetProcessHeap(), 0, sizeof(*item));
890
label_copy = HeapAlloc(GetProcessHeap(), 0, (lstrlenW(label)+1)*sizeof(WCHAR));
891
892
if (!item || !label_copy)
893
{
894
HeapFree(GetProcessHeap(), 0, item);
895
HeapFree(GetProcessHeap(), 0, label_copy);
896
return E_OUTOFMEMORY;
897
}
898
899
item->id = itemid;
900
item->parent_id = parent->id;
901
lstrcpyW(label_copy, label);
902
item->label = label_copy;
903
item->cdcstate = CDCS_VISIBLE|CDCS_ENABLED;
904
item->hwnd = NULL;
905
list_add_tail(&parent->sub_items, &item->entry);
906
907
*result = item;
908
909
return S_OK;
910
}
911
912
/**************************************************************************
913
* Control functions.
914
*/
915
static inline customctrl *get_cctrl_from_dlgid(FileDialogImpl *This, DWORD dlgid)
916
{
917
customctrl *ctrl, *sub_ctrl;
918
919
LIST_FOR_EACH_ENTRY(ctrl, &This->cctrls, customctrl, entry)
920
{
921
if(ctrl->dlgid == dlgid)
922
return ctrl;
923
924
LIST_FOR_EACH_ENTRY(sub_ctrl, &ctrl->sub_cctrls, customctrl, sub_cctrls_entry)
925
if(sub_ctrl->dlgid == dlgid)
926
return sub_ctrl;
927
}
928
929
ERR("Failed to find control with dialog id %ld\n", dlgid);
930
return NULL;
931
}
932
933
static inline customctrl *get_cctrl(FileDialogImpl *This, DWORD ctlid)
934
{
935
customctrl *ctrl, *sub_ctrl;
936
937
LIST_FOR_EACH_ENTRY(ctrl, &This->cctrls, customctrl, entry)
938
{
939
if(ctrl->id == ctlid)
940
return ctrl;
941
942
LIST_FOR_EACH_ENTRY(sub_ctrl, &ctrl->sub_cctrls, customctrl, sub_cctrls_entry)
943
if(sub_ctrl->id == ctlid)
944
return sub_ctrl;
945
}
946
947
if (This->hmenu_opendropdown && This->cctrl_opendropdown.id == ctlid)
948
return &This->cctrl_opendropdown;
949
950
TRACE("No existing control with control id %ld\n", ctlid);
951
return NULL;
952
}
953
954
static void ctrl_resize(HWND hctrl, UINT min_width, UINT max_width, BOOL multiline)
955
{
956
LPWSTR text;
957
UINT len, final_width;
958
UINT lines, final_height;
959
SIZE size;
960
RECT rc;
961
HDC hdc;
962
WCHAR *c;
963
HFONT font;
964
965
TRACE("\n");
966
967
len = SendMessageW(hctrl, WM_GETTEXTLENGTH, 0, 0);
968
text = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR)*(len+1));
969
if(!text) return;
970
SendMessageW(hctrl, WM_GETTEXT, len+1, (LPARAM)text);
971
972
hdc = GetDC(hctrl);
973
font = (HFONT)SendMessageW(hctrl, WM_GETFONT, 0, 0);
974
font = SelectObject(hdc, font);
975
GetTextExtentPoint32W(hdc, text, lstrlenW(text), &size);
976
SelectObject(hdc, font);
977
ReleaseDC(hctrl, hdc);
978
979
if(len && multiline)
980
{
981
/* FIXME: line-wrap */
982
for(lines = 1, c = text; *c != '\0'; c++)
983
if(*c == '\n') lines++;
984
985
final_height = size.cy*lines + 2*4;
986
}
987
else
988
{
989
GetWindowRect(hctrl, &rc);
990
final_height = rc.bottom - rc.top;
991
}
992
993
final_width = min(max(size.cx, min_width) + 4, max_width);
994
SetWindowPos(hctrl, NULL, 0, 0, final_width, final_height,
995
SWP_NOZORDER | SWP_NOMOVE | SWP_NOACTIVATE);
996
997
HeapFree(GetProcessHeap(), 0, text);
998
}
999
1000
static UINT ctrl_get_height(customctrl *ctrl) {
1001
RECT rc;
1002
GetWindowRect(ctrl->wrapper_hwnd, &rc);
1003
return rc.bottom - rc.top;
1004
}
1005
1006
static void ctrl_free(customctrl *ctrl)
1007
{
1008
customctrl *sub_cur1, *sub_cur2;
1009
cctrl_item *item_cur1, *item_cur2;
1010
1011
TRACE("Freeing control %p\n", ctrl);
1012
if(ctrl->type == IDLG_CCTRL_MENU)
1013
{
1014
TBBUTTON tbb;
1015
SendMessageW(ctrl->hwnd, TB_GETBUTTON, 0, (LPARAM)&tbb);
1016
DestroyMenu((HMENU)tbb.dwData);
1017
}
1018
1019
LIST_FOR_EACH_ENTRY_SAFE(sub_cur1, sub_cur2, &ctrl->sub_cctrls, customctrl, sub_cctrls_entry)
1020
{
1021
list_remove(&sub_cur1->sub_cctrls_entry);
1022
ctrl_free(sub_cur1);
1023
}
1024
1025
LIST_FOR_EACH_ENTRY_SAFE(item_cur1, item_cur2, &ctrl->sub_items, cctrl_item, entry)
1026
{
1027
list_remove(&item_cur1->entry);
1028
item_free(item_cur1);
1029
}
1030
1031
DestroyWindow(ctrl->hwnd);
1032
HeapFree(GetProcessHeap(), 0, ctrl);
1033
}
1034
1035
static void customctrl_resize(FileDialogImpl *This, customctrl *ctrl)
1036
{
1037
RECT rc;
1038
UINT total_height;
1039
UINT max_width, size;
1040
customctrl *sub_ctrl;
1041
1042
switch(ctrl->type)
1043
{
1044
case IDLG_CCTRL_PUSHBUTTON:
1045
case IDLG_CCTRL_COMBOBOX:
1046
case IDLG_CCTRL_CHECKBUTTON:
1047
case IDLG_CCTRL_TEXT:
1048
size = MulDiv(160, This->dpi_x, USER_DEFAULT_SCREEN_DPI);
1049
ctrl_resize(ctrl->hwnd, size, size, TRUE);
1050
GetWindowRect(ctrl->hwnd, &rc);
1051
SetWindowPos(ctrl->wrapper_hwnd, NULL, 0, 0, rc.right-rc.left, rc.bottom-rc.top,
1052
SWP_NOZORDER|SWP_NOMOVE);
1053
break;
1054
case IDLG_CCTRL_VISUALGROUP:
1055
total_height = 0;
1056
ctrl_resize(ctrl->hwnd, 0, This->cctrl_indent, TRUE);
1057
1058
LIST_FOR_EACH_ENTRY(sub_ctrl, &ctrl->sub_cctrls, customctrl, sub_cctrls_entry)
1059
{
1060
customctrl_resize(This, sub_ctrl);
1061
SetWindowPos(sub_ctrl->wrapper_hwnd, NULL, This->cctrl_indent, total_height, 0, 0,
1062
SWP_NOZORDER|SWP_NOSIZE);
1063
1064
total_height += ctrl_get_height(sub_ctrl);
1065
}
1066
1067
/* The label should be right adjusted */
1068
{
1069
UINT width, height;
1070
1071
GetWindowRect(ctrl->hwnd, &rc);
1072
width = rc.right - rc.left;
1073
height = rc.bottom - rc.top;
1074
1075
SetWindowPos(ctrl->hwnd, NULL, This->cctrl_indent - width, 0, width, height, SWP_NOZORDER);
1076
}
1077
1078
/* Resize the wrapper window to fit all the sub controls */
1079
SetWindowPos(ctrl->wrapper_hwnd, NULL, 0, 0, This->cctrl_width + This->cctrl_indent, total_height,
1080
SWP_NOZORDER|SWP_NOMOVE);
1081
break;
1082
case IDLG_CCTRL_RADIOBUTTONLIST:
1083
{
1084
cctrl_item* item;
1085
1086
total_height = 0;
1087
max_width = 0;
1088
1089
LIST_FOR_EACH_ENTRY(item, &ctrl->sub_items, cctrl_item, entry)
1090
{
1091
size = MulDiv(160, This->dpi_x, USER_DEFAULT_SCREEN_DPI);
1092
ctrl_resize(item->hwnd, size, size, TRUE);
1093
SetWindowPos(item->hwnd, NULL, 0, total_height, 0, 0,
1094
SWP_NOZORDER|SWP_NOSIZE);
1095
1096
GetWindowRect(item->hwnd, &rc);
1097
1098
total_height += rc.bottom - rc.top;
1099
max_width = max(rc.right - rc.left, max_width);
1100
}
1101
1102
SetWindowPos(ctrl->hwnd, NULL, 0, 0, max_width, total_height,
1103
SWP_NOZORDER|SWP_NOMOVE);
1104
1105
SetWindowPos(ctrl->wrapper_hwnd, NULL, 0, 0, max_width, total_height,
1106
SWP_NOZORDER|SWP_NOMOVE);
1107
1108
break;
1109
}
1110
case IDLG_CCTRL_EDITBOX:
1111
case IDLG_CCTRL_SEPARATOR:
1112
case IDLG_CCTRL_MENU:
1113
case IDLG_CCTRL_OPENDROPDOWN:
1114
/* Nothing */
1115
break;
1116
}
1117
}
1118
1119
static LRESULT notifysink_on_create(HWND hwnd, CREATESTRUCTW *crs)
1120
{
1121
FileDialogImpl *This = crs->lpCreateParams;
1122
TRACE("%p\n", This);
1123
1124
SetWindowLongPtrW(hwnd, GWLP_USERDATA, (LPARAM)This);
1125
return TRUE;
1126
}
1127
1128
static LRESULT notifysink_on_bn_clicked(FileDialogImpl *This, HWND hwnd, WPARAM wparam)
1129
{
1130
customctrl *ctrl = get_cctrl_from_dlgid(This, LOWORD(wparam));
1131
1132
TRACE("%p, %Ix\n", This, wparam);
1133
1134
if(ctrl)
1135
{
1136
if(ctrl->type == IDLG_CCTRL_CHECKBUTTON)
1137
{
1138
BOOL checked = (SendMessageW(ctrl->hwnd, BM_GETCHECK, 0, 0) == BST_CHECKED);
1139
cctrl_event_OnCheckButtonToggled(This, ctrl->id, checked);
1140
}
1141
else
1142
cctrl_event_OnButtonClicked(This, ctrl->id);
1143
}
1144
1145
return TRUE;
1146
}
1147
1148
static LRESULT notifysink_on_cbn_selchange(FileDialogImpl *This, HWND hwnd, WPARAM wparam)
1149
{
1150
customctrl *ctrl = get_cctrl_from_dlgid(This, LOWORD(wparam));
1151
TRACE("%p, %p (%Ix)\n", This, ctrl, wparam);
1152
1153
if(ctrl)
1154
{
1155
UINT index = SendMessageW(ctrl->hwnd, CB_GETCURSEL, 0, 0);
1156
UINT selid = SendMessageW(ctrl->hwnd, CB_GETITEMDATA, index, 0);
1157
1158
cctrl_event_OnItemSelected(This, ctrl->id, selid);
1159
}
1160
return TRUE;
1161
}
1162
1163
static LRESULT notifysink_on_tvn_dropdown(FileDialogImpl *This, LPARAM lparam)
1164
{
1165
NMTOOLBARW *nmtb = (NMTOOLBARW*)lparam;
1166
customctrl *ctrl = get_cctrl_from_dlgid(This, GetDlgCtrlID(nmtb->hdr.hwndFrom));
1167
POINT pt = { 0, nmtb->rcButton.bottom };
1168
TBBUTTON tbb;
1169
UINT idcmd;
1170
1171
TRACE("%p, %p (%Ix)\n", This, ctrl, lparam);
1172
1173
if(ctrl)
1174
{
1175
cctrl_event_OnControlActivating(This,ctrl->id);
1176
1177
SendMessageW(ctrl->hwnd, TB_GETBUTTON, 0, (LPARAM)&tbb);
1178
ClientToScreen(ctrl->hwnd, &pt);
1179
idcmd = TrackPopupMenu((HMENU)tbb.dwData, TPM_RETURNCMD, pt.x, pt.y, 0, This->dlg_hwnd, NULL);
1180
if(idcmd)
1181
cctrl_event_OnItemSelected(This, ctrl->id, idcmd);
1182
}
1183
1184
return TBDDRET_DEFAULT;
1185
}
1186
1187
static LRESULT notifysink_on_wm_command(FileDialogImpl *This, HWND hwnd, WPARAM wparam, LPARAM lparam)
1188
{
1189
switch(HIWORD(wparam))
1190
{
1191
case BN_CLICKED: return notifysink_on_bn_clicked(This, hwnd, wparam);
1192
case CBN_SELCHANGE: return notifysink_on_cbn_selchange(This, hwnd, wparam);
1193
}
1194
1195
return FALSE;
1196
}
1197
1198
static LRESULT notifysink_on_wm_notify(FileDialogImpl *This, HWND hwnd, WPARAM wparam, LPARAM lparam)
1199
{
1200
NMHDR *nmhdr = (NMHDR*)lparam;
1201
1202
switch(nmhdr->code)
1203
{
1204
case TBN_DROPDOWN: return notifysink_on_tvn_dropdown(This, lparam);
1205
}
1206
1207
return FALSE;
1208
}
1209
1210
static LRESULT CALLBACK notifysink_proc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam)
1211
{
1212
FileDialogImpl *This = (FileDialogImpl*)GetWindowLongPtrW(hwnd, GWLP_USERDATA);
1213
customctrl *ctrl;
1214
HWND hwnd_child;
1215
RECT rc;
1216
1217
switch(message)
1218
{
1219
case WM_NCCREATE: return notifysink_on_create(hwnd, (CREATESTRUCTW*)lparam);
1220
case WM_COMMAND: return notifysink_on_wm_command(This, hwnd, wparam, lparam);
1221
case WM_NOTIFY: return notifysink_on_wm_notify(This, hwnd, wparam, lparam);
1222
case WM_SIZE:
1223
hwnd_child = GetPropW(hwnd, L"nfs_child");
1224
ctrl = (customctrl*)GetWindowLongPtrW(hwnd_child, GWLP_USERDATA);
1225
if(ctrl && ctrl->type != IDLG_CCTRL_VISUALGROUP)
1226
{
1227
GetClientRect(hwnd, &rc);
1228
SetWindowPos(hwnd_child, NULL, 0, 0, rc.right, rc.bottom, SWP_NOMOVE|SWP_NOACTIVATE|SWP_NOZORDER);
1229
}
1230
return TRUE;
1231
}
1232
1233
return DefWindowProcW(hwnd, message, wparam, lparam);
1234
}
1235
1236
static HRESULT cctrl_create_new(FileDialogImpl *This, DWORD id,
1237
LPCWSTR text, LPCWSTR wndclass, DWORD ctrl_wsflags,
1238
DWORD ctrl_exflags, UINT height, customctrl **ppctrl)
1239
{
1240
HWND ns_hwnd, control_hwnd, parent_hwnd;
1241
DWORD wsflags = WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS;
1242
customctrl *ctrl;
1243
1244
if(get_cctrl(This, id))
1245
return E_UNEXPECTED; /* Duplicate id */
1246
1247
if(This->cctrl_active_vg)
1248
parent_hwnd = This->cctrl_active_vg->wrapper_hwnd;
1249
else
1250
parent_hwnd = This->cctrls_hwnd;
1251
1252
ns_hwnd = CreateWindowExW(0, L"FloatNotifySink", NULL, wsflags,
1253
0, 0, This->cctrl_width, height, parent_hwnd,
1254
(HMENU)This->cctrl_next_dlgid, COMDLG32_hInstance, This);
1255
control_hwnd = CreateWindowExW(ctrl_exflags, wndclass, text, wsflags | ctrl_wsflags,
1256
0, 0, This->cctrl_width, height, ns_hwnd,
1257
(HMENU)This->cctrl_next_dlgid, COMDLG32_hInstance, 0);
1258
1259
if(!ns_hwnd || !control_hwnd)
1260
{
1261
ERR("Failed to create wrapper (%p) or control (%p)\n", ns_hwnd, control_hwnd);
1262
DestroyWindow(ns_hwnd);
1263
DestroyWindow(control_hwnd);
1264
1265
return E_FAIL;
1266
}
1267
1268
SetPropW(ns_hwnd, L"nfs_child", control_hwnd);
1269
1270
ctrl = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(customctrl));
1271
if(!ctrl)
1272
return E_OUTOFMEMORY;
1273
1274
ctrl->hwnd = control_hwnd;
1275
ctrl->wrapper_hwnd = ns_hwnd;
1276
ctrl->id = id;
1277
ctrl->dlgid = This->cctrl_next_dlgid;
1278
ctrl->cdcstate = CDCS_ENABLED | CDCS_VISIBLE;
1279
list_init(&ctrl->sub_cctrls);
1280
list_init(&ctrl->sub_items);
1281
1282
if(This->cctrl_active_vg)
1283
list_add_tail(&This->cctrl_active_vg->sub_cctrls, &ctrl->sub_cctrls_entry);
1284
else
1285
list_add_tail(&This->cctrls, &ctrl->entry);
1286
1287
SetWindowLongPtrW(ctrl->hwnd, GWLP_USERDATA, (LPARAM)ctrl);
1288
1289
if(ppctrl) *ppctrl = ctrl;
1290
1291
This->cctrl_next_dlgid++;
1292
return S_OK;
1293
}
1294
1295
/**************************************************************************
1296
* Container functions.
1297
*/
1298
static UINT ctrl_container_resize(FileDialogImpl *This, UINT container_width)
1299
{
1300
UINT container_height;
1301
UINT column_width;
1302
UINT nr_of_cols;
1303
UINT max_control_height, total_height = 0;
1304
UINT cur_col_pos, cur_row_pos;
1305
customctrl *ctrl;
1306
BOOL fits_height;
1307
UINT cspacing = MulDiv(90, This->dpi_x, USER_DEFAULT_SCREEN_DPI); /* Columns are spaced with 90px */
1308
UINT rspacing = MulDiv(4, This->dpi_y, USER_DEFAULT_SCREEN_DPI); /* Rows are spaced with 4 px. */
1309
1310
/* Given the new width of the container, this function determines the
1311
* needed height of the container and places the controls according to
1312
* the new layout. Returns the new height.
1313
*/
1314
1315
TRACE("%p\n", This);
1316
1317
column_width = This->cctrl_width + cspacing;
1318
nr_of_cols = (container_width - This->cctrl_indent + cspacing) / column_width;
1319
1320
/* We don't need to do anything unless the number of visible columns has changed. */
1321
if(nr_of_cols == This->cctrls_cols)
1322
{
1323
RECT rc;
1324
GetWindowRect(This->cctrls_hwnd, &rc);
1325
return rc.bottom - rc.top;
1326
}
1327
1328
This->cctrls_cols = nr_of_cols;
1329
1330
/* Get the size of the tallest control, and the total size of
1331
* all the controls to figure out the number of slots we need.
1332
*/
1333
max_control_height = 0;
1334
LIST_FOR_EACH_ENTRY(ctrl, &This->cctrls, customctrl, entry)
1335
{
1336
if(ctrl->cdcstate & CDCS_VISIBLE)
1337
{
1338
UINT control_height = ctrl_get_height(ctrl);
1339
max_control_height = max(max_control_height, control_height);
1340
1341
total_height += control_height + rspacing;
1342
}
1343
}
1344
1345
if(!total_height)
1346
return 0;
1347
1348
container_height = max(total_height / nr_of_cols, max_control_height + rspacing);
1349
TRACE("Guess: container_height: %d\n",container_height);
1350
1351
/* Incrementally increase container_height until all the controls
1352
* fit.
1353
*/
1354
do {
1355
UINT columns_needed = 1;
1356
cur_row_pos = 0;
1357
1358
fits_height = TRUE;
1359
LIST_FOR_EACH_ENTRY(ctrl, &This->cctrls, customctrl, entry)
1360
{
1361
if(ctrl->cdcstate & CDCS_VISIBLE)
1362
{
1363
UINT control_height = ctrl_get_height(ctrl);
1364
1365
if(cur_row_pos + control_height > container_height)
1366
{
1367
if(++columns_needed > nr_of_cols)
1368
{
1369
container_height += 1;
1370
fits_height = FALSE;
1371
break;
1372
}
1373
cur_row_pos = 0;
1374
}
1375
1376
cur_row_pos += control_height + rspacing;
1377
}
1378
}
1379
} while(!fits_height);
1380
1381
TRACE("Final container height: %d\n", container_height);
1382
1383
/* Move the controls to their final destination
1384
*/
1385
cur_col_pos = 0; cur_row_pos = 0;
1386
LIST_FOR_EACH_ENTRY(ctrl, &This->cctrls, customctrl, entry)
1387
{
1388
if(ctrl->cdcstate & CDCS_VISIBLE)
1389
{
1390
RECT rc;
1391
UINT control_height, control_indent;
1392
GetWindowRect(ctrl->wrapper_hwnd, &rc);
1393
control_height = rc.bottom - rc.top;
1394
1395
if(cur_row_pos + control_height > container_height)
1396
{
1397
cur_row_pos = 0;
1398
cur_col_pos += This->cctrl_width + cspacing;
1399
}
1400
1401
1402
if(ctrl->type == IDLG_CCTRL_VISUALGROUP)
1403
control_indent = 0;
1404
else
1405
control_indent = This->cctrl_indent;
1406
1407
SetWindowPos(ctrl->wrapper_hwnd, NULL, cur_col_pos + control_indent, cur_row_pos, 0, 0,
1408
SWP_NOACTIVATE | SWP_NOSIZE | SWP_NOZORDER);
1409
1410
cur_row_pos += control_height + rspacing;
1411
}
1412
}
1413
1414
/* Sanity check */
1415
if(cur_row_pos + This->cctrl_width > container_width)
1416
ERR("-- Failed to place controls properly.\n");
1417
1418
return container_height;
1419
}
1420
1421
static void ctrl_set_font(customctrl *ctrl, HFONT font)
1422
{
1423
customctrl *sub_ctrl;
1424
cctrl_item* item;
1425
1426
SendMessageW(ctrl->hwnd, WM_SETFONT, (WPARAM)font, TRUE);
1427
1428
LIST_FOR_EACH_ENTRY(sub_ctrl, &ctrl->sub_cctrls, customctrl, sub_cctrls_entry)
1429
{
1430
ctrl_set_font(sub_ctrl, font);
1431
}
1432
1433
if (ctrl->type == IDLG_CCTRL_RADIOBUTTONLIST)
1434
{
1435
LIST_FOR_EACH_ENTRY(item, &ctrl->sub_items, cctrl_item, entry)
1436
{
1437
SendMessageW(item->hwnd, WM_SETFONT, (WPARAM)font, TRUE);
1438
}
1439
}
1440
}
1441
1442
static void ctrl_container_reparent(FileDialogImpl *This, HWND parent)
1443
{
1444
LONG wndstyle;
1445
1446
if(parent)
1447
{
1448
customctrl *ctrl;
1449
HFONT font;
1450
1451
wndstyle = GetWindowLongW(This->cctrls_hwnd, GWL_STYLE);
1452
wndstyle &= ~(WS_POPUP);
1453
wndstyle |= WS_CHILD;
1454
SetWindowLongW(This->cctrls_hwnd, GWL_STYLE, wndstyle);
1455
1456
SetParent(This->cctrls_hwnd, parent);
1457
ShowWindow(This->cctrls_hwnd, TRUE);
1458
1459
/* Set the fonts to match the dialog font. */
1460
font = (HFONT)SendMessageW(parent, WM_GETFONT, 0, 0);
1461
if(!font)
1462
ERR("Failed to get font handle from dialog.\n");
1463
1464
LIST_FOR_EACH_ENTRY(ctrl, &This->cctrls, customctrl, entry)
1465
{
1466
if(font) ctrl_set_font(ctrl, font);
1467
customctrl_resize(This, ctrl);
1468
}
1469
}
1470
else
1471
{
1472
ShowWindow(This->cctrls_hwnd, FALSE);
1473
1474
wndstyle = GetWindowLongW(This->cctrls_hwnd, GWL_STYLE);
1475
wndstyle &= ~(WS_CHILD);
1476
wndstyle |= WS_POPUP;
1477
SetWindowLongW(This->cctrls_hwnd, GWL_STYLE, wndstyle);
1478
1479
SetParent(This->cctrls_hwnd, NULL);
1480
}
1481
}
1482
1483
static LRESULT ctrl_container_on_create(HWND hwnd, CREATESTRUCTW *crs)
1484
{
1485
FileDialogImpl *This = crs->lpCreateParams;
1486
TRACE("%p\n", This);
1487
1488
SetWindowLongPtrW(hwnd, GWLP_USERDATA, (LPARAM)This);
1489
return TRUE;
1490
}
1491
1492
static LRESULT ctrl_container_on_wm_destroy(FileDialogImpl *This)
1493
{
1494
customctrl *cur1, *cur2;
1495
TRACE("%p\n", This);
1496
1497
LIST_FOR_EACH_ENTRY_SAFE(cur1, cur2, &This->cctrls, customctrl, entry)
1498
{
1499
list_remove(&cur1->entry);
1500
ctrl_free(cur1);
1501
}
1502
1503
return TRUE;
1504
}
1505
1506
static LRESULT CALLBACK ctrl_container_wndproc(HWND hwnd, UINT umessage, WPARAM wparam, LPARAM lparam)
1507
{
1508
FileDialogImpl *This = (FileDialogImpl*)GetWindowLongPtrW(hwnd, GWLP_USERDATA);
1509
1510
switch(umessage)
1511
{
1512
case WM_NCCREATE: return ctrl_container_on_create(hwnd, (CREATESTRUCTW*)lparam);
1513
case WM_DESTROY: return ctrl_container_on_wm_destroy(This);
1514
default: return DefWindowProcW(hwnd, umessage, wparam, lparam);
1515
}
1516
1517
return FALSE;
1518
}
1519
1520
static void radiobuttonlist_set_selected_item(FileDialogImpl *This, customctrl *ctrl, cctrl_item *item)
1521
{
1522
cctrl_item *cursor;
1523
1524
LIST_FOR_EACH_ENTRY(cursor, &ctrl->sub_items, cctrl_item, entry)
1525
{
1526
SendMessageW(cursor->hwnd, BM_SETCHECK, (cursor == item) ? BST_CHECKED : BST_UNCHECKED, 0);
1527
}
1528
}
1529
1530
static LRESULT radiobuttonlist_on_bn_clicked(FileDialogImpl *This, HWND hwnd, HWND child)
1531
{
1532
DWORD ctrl_id = (DWORD)GetWindowLongPtrW(hwnd, GWLP_ID);
1533
customctrl *ctrl;
1534
cctrl_item *item;
1535
BOOL found_item=FALSE;
1536
1537
ctrl = get_cctrl_from_dlgid(This, ctrl_id);
1538
1539
if (!ctrl)
1540
{
1541
ERR("Can't find this control\n");
1542
return 0;
1543
}
1544
1545
LIST_FOR_EACH_ENTRY(item, &ctrl->sub_items, cctrl_item, entry)
1546
{
1547
if (item->hwnd == child)
1548
{
1549
found_item = TRUE;
1550
break;
1551
}
1552
}
1553
1554
if (!found_item)
1555
{
1556
ERR("Can't find control item\n");
1557
return 0;
1558
}
1559
1560
radiobuttonlist_set_selected_item(This, ctrl, item);
1561
1562
cctrl_event_OnItemSelected(This, ctrl->id, item->id);
1563
1564
return 0;
1565
}
1566
1567
static LRESULT radiobuttonlist_on_wm_command(FileDialogImpl *This, HWND hwnd, WPARAM wparam, LPARAM lparam)
1568
{
1569
switch(HIWORD(wparam))
1570
{
1571
case BN_CLICKED: return radiobuttonlist_on_bn_clicked(This, hwnd, (HWND)lparam);
1572
}
1573
1574
return FALSE;
1575
}
1576
1577
static LRESULT CALLBACK radiobuttonlist_proc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam)
1578
{
1579
FileDialogImpl *This = (FileDialogImpl*)GetWindowLongPtrW(hwnd, GWLP_USERDATA);
1580
1581
switch(message)
1582
{
1583
case WM_COMMAND: return radiobuttonlist_on_wm_command(This, hwnd, wparam, lparam);
1584
}
1585
1586
return DefWindowProcW(hwnd, message, wparam, lparam);
1587
}
1588
1589
static HRESULT init_custom_controls(FileDialogImpl *This)
1590
{
1591
WNDCLASSW wc;
1592
HDC hdc;
1593
static const WCHAR ctrl_container_classname[] = L"idlg_container_pane";
1594
1595
InitCommonControlsEx(NULL);
1596
1597
if( !GetClassInfoW(COMDLG32_hInstance, ctrl_container_classname, &wc) )
1598
{
1599
wc.style = CS_HREDRAW | CS_VREDRAW;
1600
wc.lpfnWndProc = ctrl_container_wndproc;
1601
wc.cbClsExtra = 0;
1602
wc.cbWndExtra = 0;
1603
wc.hInstance = COMDLG32_hInstance;
1604
wc.hIcon = 0;
1605
wc.hCursor = LoadCursorW(0, (LPWSTR)IDC_ARROW);
1606
wc.hbrBackground = (HBRUSH)(COLOR_BTNFACE + 1);
1607
wc.lpszMenuName = NULL;
1608
wc.lpszClassName = ctrl_container_classname;
1609
1610
if(!RegisterClassW(&wc)) return E_FAIL;
1611
}
1612
1613
This->cctrls_hwnd = CreateWindowExW(0, ctrl_container_classname, NULL,
1614
WS_CLIPSIBLINGS | WS_CLIPCHILDREN,
1615
0, 0, 0, 0, NULL, 0,
1616
COMDLG32_hInstance, This);
1617
if(!This->cctrls_hwnd)
1618
return E_FAIL;
1619
1620
hdc = GetDC(This->cctrls_hwnd);
1621
This->dpi_x = GetDeviceCaps(hdc, LOGPIXELSX);
1622
This->dpi_y = GetDeviceCaps(hdc, LOGPIXELSY);
1623
ReleaseDC(This->cctrls_hwnd, hdc);
1624
1625
This->cctrl_width = MulDiv(160, This->dpi_x, USER_DEFAULT_SCREEN_DPI); /* Controls have a fixed width */
1626
This->cctrl_indent = MulDiv(100, This->dpi_x, USER_DEFAULT_SCREEN_DPI);
1627
This->cctrl_def_height = MulDiv(23, This->dpi_y, USER_DEFAULT_SCREEN_DPI);
1628
This->cctrls_cols = 0;
1629
1630
This->cctrl_next_dlgid = 0x2000;
1631
list_init(&This->cctrls);
1632
This->cctrl_active_vg = NULL;
1633
1634
SetWindowLongW(This->cctrls_hwnd, GWL_STYLE, WS_TABSTOP);
1635
1636
/* Register class for */
1637
if (!GetClassInfoW(COMDLG32_hInstance, L"FloatNotifySink", &wc) ||
1638
wc.hInstance != COMDLG32_hInstance)
1639
{
1640
wc.style = CS_HREDRAW | CS_VREDRAW;
1641
wc.lpfnWndProc = notifysink_proc;
1642
wc.cbClsExtra = 0;
1643
wc.cbWndExtra = 0;
1644
wc.hInstance = COMDLG32_hInstance;
1645
wc.hIcon = 0;
1646
wc.hCursor = LoadCursorW(0, (LPWSTR)IDC_ARROW);
1647
wc.hbrBackground = (HBRUSH)(COLOR_BTNFACE + 1);
1648
wc.lpszMenuName = NULL;
1649
wc.lpszClassName = L"FloatNotifySink";
1650
1651
if (!RegisterClassW(&wc))
1652
ERR("Failed to register FloatNotifySink window class.\n");
1653
}
1654
1655
if (!GetClassInfoW(COMDLG32_hInstance, L"RadioButtonList", &wc) ||
1656
wc.hInstance != COMDLG32_hInstance)
1657
{
1658
wc.style = CS_HREDRAW | CS_VREDRAW;
1659
wc.lpfnWndProc = radiobuttonlist_proc;
1660
wc.cbClsExtra = 0;
1661
wc.cbWndExtra = 0;
1662
wc.hInstance = COMDLG32_hInstance;
1663
wc.hIcon = 0;
1664
wc.hCursor = LoadCursorW(0, (LPWSTR)IDC_ARROW);
1665
wc.hbrBackground = (HBRUSH)(COLOR_BTNFACE + 1);
1666
wc.lpszMenuName = NULL;
1667
wc.lpszClassName = L"RadioButtonList";
1668
1669
if (!RegisterClassW(&wc))
1670
ERR("Failed to register RadioButtonList window class.\n");
1671
}
1672
1673
return S_OK;
1674
}
1675
1676
/**************************************************************************
1677
* Window related functions.
1678
*/
1679
static BOOL update_open_dropdown(FileDialogImpl *This)
1680
{
1681
/* Show or hide the open dropdown button as appropriate */
1682
BOOL show=FALSE, showing;
1683
HWND open_hwnd, dropdown_hwnd;
1684
1685
if (This->hmenu_opendropdown)
1686
{
1687
INT num_visible_items=0;
1688
cctrl_item* item;
1689
1690
LIST_FOR_EACH_ENTRY(item, &This->cctrl_opendropdown.sub_items, cctrl_item, entry)
1691
{
1692
if (item->cdcstate & CDCS_VISIBLE)
1693
{
1694
num_visible_items++;
1695
if (num_visible_items >= 2)
1696
{
1697
show = TRUE;
1698
break;
1699
}
1700
}
1701
}
1702
}
1703
1704
open_hwnd = GetDlgItem(This->dlg_hwnd, IDOK);
1705
dropdown_hwnd = GetDlgItem(This->dlg_hwnd, psh1);
1706
1707
showing = (GetWindowLongPtrW(dropdown_hwnd, GWL_STYLE) & WS_VISIBLE) != 0;
1708
1709
if (showing != show)
1710
{
1711
RECT open_rc, dropdown_rc;
1712
1713
GetWindowRect(open_hwnd, &open_rc);
1714
GetWindowRect(dropdown_hwnd, &dropdown_rc);
1715
1716
if (show)
1717
{
1718
ShowWindow(dropdown_hwnd, SW_SHOW);
1719
1720
SetWindowPos(open_hwnd, NULL, 0, 0,
1721
(open_rc.right - open_rc.left) - (dropdown_rc.right - dropdown_rc.left),
1722
open_rc.bottom - open_rc.top, SWP_NOZORDER | SWP_NOMOVE | SWP_NOACTIVATE);
1723
}
1724
else
1725
{
1726
ShowWindow(dropdown_hwnd, SW_HIDE);
1727
1728
SetWindowPos(open_hwnd, NULL, 0, 0,
1729
(open_rc.right - open_rc.left) + (dropdown_rc.right - dropdown_rc.left),
1730
open_rc.bottom - open_rc.top, SWP_NOZORDER | SWP_NOMOVE | SWP_NOACTIVATE);
1731
}
1732
}
1733
1734
return show;
1735
}
1736
1737
static void update_layout(FileDialogImpl *This)
1738
{
1739
HDWP hdwp;
1740
HWND hwnd;
1741
RECT dialog_rc;
1742
RECT cancel_rc, dropdown_rc, open_rc;
1743
RECT filetype_rc, filename_rc, filenamelabel_rc;
1744
RECT toolbar_rc, ebrowser_rc, customctrls_rc;
1745
static const UINT vspacing = 4, hspacing = 4;
1746
static const UINT min_width = 320, min_height = 200;
1747
BOOL show_dropdown;
1748
1749
if (!GetClientRect(This->dlg_hwnd, &dialog_rc))
1750
{
1751
TRACE("Invalid dialog window, not updating layout\n");
1752
return;
1753
}
1754
1755
if(dialog_rc.right < min_width || dialog_rc.bottom < min_height)
1756
{
1757
TRACE("Dialog size (%ld, %ld) too small, not updating layout\n", dialog_rc.right, dialog_rc.bottom);
1758
return;
1759
}
1760
1761
/****
1762
* Calculate the size of the dialog and all the parts.
1763
*/
1764
1765
/* Cancel button */
1766
hwnd = GetDlgItem(This->dlg_hwnd, IDCANCEL);
1767
if(hwnd)
1768
{
1769
int cancel_width, cancel_height;
1770
GetWindowRect(hwnd, &cancel_rc);
1771
cancel_width = cancel_rc.right - cancel_rc.left;
1772
cancel_height = cancel_rc.bottom - cancel_rc.top;
1773
1774
cancel_rc.left = dialog_rc.right - cancel_width - hspacing;
1775
cancel_rc.top = dialog_rc.bottom - cancel_height - vspacing;
1776
cancel_rc.right = cancel_rc.left + cancel_width;
1777
cancel_rc.bottom = cancel_rc.top + cancel_height;
1778
}
1779
1780
/* Open/Save dropdown */
1781
show_dropdown = update_open_dropdown(This);
1782
1783
if(show_dropdown)
1784
{
1785
int dropdown_width, dropdown_height;
1786
hwnd = GetDlgItem(This->dlg_hwnd, psh1);
1787
1788
GetWindowRect(hwnd, &dropdown_rc);
1789
dropdown_width = dropdown_rc.right - dropdown_rc.left;
1790
dropdown_height = dropdown_rc.bottom - dropdown_rc.top;
1791
1792
dropdown_rc.left = cancel_rc.left - dropdown_width - hspacing;
1793
dropdown_rc.top = cancel_rc.top;
1794
dropdown_rc.right = dropdown_rc.left + dropdown_width;
1795
dropdown_rc.bottom = dropdown_rc.top + dropdown_height;
1796
}
1797
else
1798
{
1799
dropdown_rc.left = dropdown_rc.right = cancel_rc.left - hspacing;
1800
dropdown_rc.top = cancel_rc.top;
1801
dropdown_rc.bottom = cancel_rc.bottom;
1802
}
1803
1804
/* Open/Save button */
1805
hwnd = GetDlgItem(This->dlg_hwnd, IDOK);
1806
if(hwnd)
1807
{
1808
int open_width, open_height;
1809
GetWindowRect(hwnd, &open_rc);
1810
open_width = open_rc.right - open_rc.left;
1811
open_height = open_rc.bottom - open_rc.top;
1812
1813
open_rc.left = dropdown_rc.left - open_width;
1814
open_rc.top = dropdown_rc.top;
1815
open_rc.right = open_rc.left + open_width;
1816
open_rc.bottom = open_rc.top + open_height;
1817
}
1818
1819
/* The filetype combobox. */
1820
hwnd = GetDlgItem(This->dlg_hwnd, IDC_FILETYPE);
1821
if(hwnd)
1822
{
1823
int filetype_width, filetype_height;
1824
GetWindowRect(hwnd, &filetype_rc);
1825
1826
filetype_width = filetype_rc.right - filetype_rc.left;
1827
filetype_height = filetype_rc.bottom - filetype_rc.top;
1828
1829
filetype_rc.right = cancel_rc.right;
1830
1831
filetype_rc.left = filetype_rc.right - filetype_width;
1832
filetype_rc.top = cancel_rc.top - filetype_height - vspacing;
1833
filetype_rc.bottom = filetype_rc.top + filetype_height;
1834
1835
if(!This->filterspec_count)
1836
filetype_rc.left = filetype_rc.right;
1837
}
1838
1839
/* Filename label. */
1840
hwnd = GetDlgItem(This->dlg_hwnd, IDC_FILENAMESTATIC);
1841
if(hwnd)
1842
{
1843
int filetypelabel_width, filetypelabel_height;
1844
GetWindowRect(hwnd, &filenamelabel_rc);
1845
1846
filetypelabel_width = filenamelabel_rc.right - filenamelabel_rc.left;
1847
filetypelabel_height = filenamelabel_rc.bottom - filenamelabel_rc.top;
1848
1849
filenamelabel_rc.left = 160; /* FIXME */
1850
filenamelabel_rc.top = filetype_rc.top;
1851
filenamelabel_rc.right = filenamelabel_rc.left + filetypelabel_width;
1852
filenamelabel_rc.bottom = filenamelabel_rc.top + filetypelabel_height;
1853
}
1854
1855
/* Filename edit box. */
1856
hwnd = GetDlgItem(This->dlg_hwnd, IDC_FILENAME);
1857
if(hwnd)
1858
{
1859
int filename_width, filename_height;
1860
GetWindowRect(hwnd, &filename_rc);
1861
1862
filename_width = filetype_rc.left - filenamelabel_rc.right - hspacing*2;
1863
filename_height = filename_rc.bottom - filename_rc.top;
1864
1865
filename_rc.left = filenamelabel_rc.right + hspacing;
1866
filename_rc.top = filetype_rc.top;
1867
filename_rc.right = filename_rc.left + filename_width;
1868
filename_rc.bottom = filename_rc.top + filename_height;
1869
}
1870
1871
hwnd = GetDlgItem(This->dlg_hwnd, IDC_NAV_TOOLBAR);
1872
if(hwnd)
1873
{
1874
GetWindowRect(hwnd, &toolbar_rc);
1875
MapWindowPoints(NULL, This->dlg_hwnd, (POINT*)&toolbar_rc, 2);
1876
}
1877
1878
/* The custom controls */
1879
customctrls_rc.left = dialog_rc.left + hspacing;
1880
customctrls_rc.right = dialog_rc.right - hspacing;
1881
customctrls_rc.bottom = filename_rc.top - vspacing;
1882
customctrls_rc.top = customctrls_rc.bottom -
1883
ctrl_container_resize(This, customctrls_rc.right - customctrls_rc.left);
1884
1885
/* The ExplorerBrowser control. */
1886
ebrowser_rc.left = dialog_rc.left + hspacing;
1887
ebrowser_rc.top = toolbar_rc.bottom + vspacing;
1888
ebrowser_rc.right = dialog_rc.right - hspacing;
1889
ebrowser_rc.bottom = customctrls_rc.top - vspacing;
1890
1891
/****
1892
* Move everything to the right place.
1893
*/
1894
1895
/* FIXME: The Save Dialog uses a slightly different layout. */
1896
hdwp = BeginDeferWindowPos(7);
1897
1898
if(hdwp && This->peb)
1899
IExplorerBrowser_SetRect(This->peb, &hdwp, ebrowser_rc);
1900
1901
if(hdwp && This->cctrls_hwnd)
1902
DeferWindowPos(hdwp, This->cctrls_hwnd, NULL,
1903
customctrls_rc.left, customctrls_rc.top,
1904
customctrls_rc.right - customctrls_rc.left, customctrls_rc.bottom - customctrls_rc.top,
1905
SWP_NOZORDER | SWP_NOACTIVATE);
1906
1907
/* The default controls */
1908
if(hdwp && (hwnd = GetDlgItem(This->dlg_hwnd, IDC_FILETYPE)) )
1909
DeferWindowPos(hdwp, hwnd, NULL, filetype_rc.left, filetype_rc.top, 0, 0,
1910
SWP_NOZORDER | SWP_NOSIZE | SWP_NOACTIVATE);
1911
1912
if(hdwp && (hwnd = GetDlgItem(This->dlg_hwnd, IDC_FILENAME)) )
1913
DeferWindowPos(hdwp, hwnd, NULL, filename_rc.left, filename_rc.top,
1914
filename_rc.right - filename_rc.left, filename_rc.bottom - filename_rc.top,
1915
SWP_NOZORDER | SWP_NOACTIVATE);
1916
1917
if(hdwp && (hwnd = GetDlgItem(This->dlg_hwnd, IDC_FILENAMESTATIC)) )
1918
DeferWindowPos(hdwp, hwnd, NULL, filenamelabel_rc.left, filenamelabel_rc.top, 0, 0,
1919
SWP_NOZORDER | SWP_NOSIZE | SWP_NOACTIVATE);
1920
1921
if(hdwp && (hwnd = GetDlgItem(This->dlg_hwnd, IDOK)) )
1922
DeferWindowPos(hdwp, hwnd, NULL, open_rc.left, open_rc.top, 0, 0,
1923
SWP_NOZORDER | SWP_NOSIZE | SWP_NOACTIVATE);
1924
1925
if(hdwp && This->hmenu_opendropdown && (hwnd = GetDlgItem(This->dlg_hwnd, psh1)))
1926
DeferWindowPos(hdwp, hwnd, NULL, dropdown_rc.left, dropdown_rc.top, 0, 0,
1927
SWP_NOZORDER | SWP_NOSIZE | SWP_NOACTIVATE);
1928
1929
if(hdwp && (hwnd = GetDlgItem(This->dlg_hwnd, IDCANCEL)) )
1930
DeferWindowPos(hdwp, hwnd, NULL, cancel_rc.left, cancel_rc.top, 0, 0,
1931
SWP_NOZORDER | SWP_NOSIZE | SWP_NOACTIVATE);
1932
1933
if(hdwp)
1934
EndDeferWindowPos(hdwp);
1935
else
1936
ERR("Failed to position dialog controls.\n");
1937
1938
return;
1939
}
1940
1941
static HRESULT init_explorerbrowser(FileDialogImpl *This)
1942
{
1943
IShellItem *psi_folder;
1944
IObjectWithSite *client;
1945
FOLDERSETTINGS fos;
1946
RECT rc = {0};
1947
HRESULT hr;
1948
1949
/* Create ExplorerBrowser instance */
1950
OleInitialize(NULL);
1951
1952
hr = CoCreateInstance(&CLSID_ExplorerBrowser, NULL, CLSCTX_INPROC_SERVER,
1953
&IID_IExplorerBrowser, (void**)&This->peb);
1954
if(FAILED(hr))
1955
{
1956
ERR("Failed to instantiate ExplorerBrowser control.\n");
1957
return hr;
1958
}
1959
1960
IExplorerBrowser_SetOptions(This->peb, EBO_SHOWFRAMES | EBO_NOBORDER);
1961
1962
hr = IExplorerBrowser_Initialize(This->peb, This->dlg_hwnd, &rc, NULL);
1963
if(FAILED(hr))
1964
{
1965
ERR("Failed to initialize the ExplorerBrowser control.\n");
1966
IExplorerBrowser_Release(This->peb);
1967
This->peb = NULL;
1968
return hr;
1969
}
1970
hr = IExplorerBrowser_Advise(This->peb, &This->IExplorerBrowserEvents_iface, &This->ebevents_cookie);
1971
if(FAILED(hr))
1972
ERR("Advise (ExplorerBrowser) failed.\n");
1973
1974
/* Get previous options? */
1975
fos.ViewMode = fos.fFlags = 0;
1976
if(!(This->options & FOS_ALLOWMULTISELECT))
1977
fos.fFlags |= FWF_SINGLESEL;
1978
1979
IExplorerBrowser_SetFolderSettings(This->peb, &fos);
1980
1981
hr = IExplorerBrowser_QueryInterface(This->peb, &IID_IObjectWithSite, (void**)&client);
1982
if (hr == S_OK)
1983
{
1984
hr = IObjectWithSite_SetSite(client, (IUnknown*)&This->IFileDialog2_iface);
1985
IObjectWithSite_Release(client);
1986
if(FAILED(hr))
1987
ERR("SetSite failed, 0x%08lx\n", hr);
1988
}
1989
1990
/* Browse somewhere */
1991
psi_folder = This->psi_setfolder ? This->psi_setfolder : This->psi_defaultfolder;
1992
IExplorerBrowser_BrowseToObject(This->peb, (IUnknown*)psi_folder, SBSP_DEFBROWSER);
1993
1994
return S_OK;
1995
}
1996
1997
static void init_toolbar(FileDialogImpl *This, HWND hwnd)
1998
{
1999
HWND htoolbar;
2000
TBADDBITMAP tbab;
2001
TBBUTTON button[3];
2002
int height;
2003
int navUpImgIndex;
2004
2005
htoolbar = CreateWindowExW(0, TOOLBARCLASSNAMEW, NULL, TBSTYLE_FLAT | WS_CHILD | WS_VISIBLE,
2006
0, 0, 0, 0,
2007
hwnd, (HMENU)IDC_NAV_TOOLBAR, NULL, NULL);
2008
2009
tbab.hInst = HINST_COMMCTRL;
2010
tbab.nID = IDB_HIST_LARGE_COLOR;
2011
SendMessageW(htoolbar, TB_ADDBITMAP, 0, (LPARAM)&tbab);
2012
tbab.nID = IDB_VIEW_LARGE_COLOR;
2013
navUpImgIndex = SendMessageW(htoolbar, TB_ADDBITMAP, 0, (LPARAM)&tbab);
2014
navUpImgIndex += VIEW_PARENTFOLDER;
2015
2016
button[0].iBitmap = HIST_BACK;
2017
button[0].idCommand = IDC_NAVBACK;
2018
button[0].fsState = TBSTATE_ENABLED;
2019
button[0].fsStyle = BTNS_BUTTON;
2020
button[0].dwData = 0;
2021
button[0].iString = 0;
2022
2023
button[1].iBitmap = HIST_FORWARD;
2024
button[1].idCommand = IDC_NAVFORWARD;
2025
button[1].fsState = TBSTATE_ENABLED;
2026
button[1].fsStyle = BTNS_BUTTON;
2027
button[1].dwData = 0;
2028
button[1].iString = 0;
2029
2030
button[2].iBitmap = navUpImgIndex;
2031
button[2].idCommand = IDC_NAVUP;
2032
button[2].fsState = TBSTATE_ENABLED;
2033
button[2].fsStyle = BTNS_BUTTON;
2034
button[2].dwData = 0;
2035
button[2].iString = 0;
2036
2037
SendMessageW(htoolbar, TB_ADDBUTTONSW, 3, (LPARAM)button);
2038
height = MulDiv(24, This->dpi_y, USER_DEFAULT_SCREEN_DPI);
2039
SendMessageW(htoolbar, TB_SETBUTTONSIZE, 0, MAKELPARAM(height, height));
2040
SendMessageW(htoolbar, TB_AUTOSIZE, 0, 0);
2041
}
2042
2043
static void update_control_text(FileDialogImpl *This)
2044
{
2045
HWND hitem;
2046
LPCWSTR custom_okbutton;
2047
cctrl_item* item;
2048
UINT min_width = MulDiv(50, This->dpi_x, USER_DEFAULT_SCREEN_DPI);
2049
UINT max_width = MulDiv(250, This->dpi_x, USER_DEFAULT_SCREEN_DPI);
2050
2051
if(This->custom_title)
2052
SetWindowTextW(This->dlg_hwnd, This->custom_title);
2053
2054
if(This->hmenu_opendropdown && (item = get_first_item(&This->cctrl_opendropdown)))
2055
custom_okbutton = item->label;
2056
else
2057
custom_okbutton = This->custom_okbutton;
2058
2059
if(custom_okbutton &&
2060
(hitem = GetDlgItem(This->dlg_hwnd, IDOK)))
2061
{
2062
SetWindowTextW(hitem, custom_okbutton);
2063
ctrl_resize(hitem, min_width, max_width, FALSE);
2064
}
2065
2066
if(This->custom_cancelbutton &&
2067
(hitem = GetDlgItem(This->dlg_hwnd, IDCANCEL)))
2068
{
2069
SetWindowTextW(hitem, This->custom_cancelbutton);
2070
ctrl_resize(hitem, min_width, max_width, FALSE);
2071
}
2072
2073
if(This->custom_filenamelabel &&
2074
(hitem = GetDlgItem(This->dlg_hwnd, IDC_FILENAMESTATIC)))
2075
{
2076
SetWindowTextW(hitem, This->custom_filenamelabel);
2077
ctrl_resize(hitem, min_width, max_width, FALSE);
2078
}
2079
}
2080
2081
static LRESULT CALLBACK dropdown_subclass_proc(HWND hwnd, UINT umessage, WPARAM wparam, LPARAM lparam)
2082
{
2083
if (umessage == WM_LBUTTONDOWN)
2084
{
2085
FileDialogImpl *This = GetPropW(hwnd, L"itemdlg_This");
2086
2087
SendMessageW(hwnd, BM_SETCHECK, BST_CHECKED, 0);
2088
show_opendropdown(This);
2089
SendMessageW(hwnd, BM_SETCHECK, BST_UNCHECKED, 0);
2090
2091
return 0;
2092
}
2093
2094
return CallWindowProcW((WNDPROC)GetPropW(hwnd, L"itemdlg_oldwndproc"), hwnd, umessage, wparam, lparam);
2095
}
2096
2097
static LRESULT on_wm_initdialog(HWND hwnd, LPARAM lParam)
2098
{
2099
FileDialogImpl *This = (FileDialogImpl*)lParam;
2100
HWND hitem;
2101
2102
TRACE("(%p, %p)\n", This, hwnd);
2103
2104
SetWindowLongPtrW(hwnd, GWLP_USERDATA, (LPARAM)This);
2105
This->dlg_hwnd = hwnd;
2106
2107
hitem = GetDlgItem(This->dlg_hwnd, pshHelp);
2108
if(hitem) ShowWindow(hitem, SW_HIDE);
2109
2110
hitem = GetDlgItem(This->dlg_hwnd, IDC_FILETYPESTATIC);
2111
if(hitem) ShowWindow(hitem, SW_HIDE);
2112
2113
/* Fill filetypes combobox, or hide it. */
2114
hitem = GetDlgItem(This->dlg_hwnd, IDC_FILETYPE);
2115
if(This->filterspec_count)
2116
{
2117
HDC hdc;
2118
HFONT font;
2119
SIZE size;
2120
UINT i, maxwidth = 0;
2121
2122
hdc = GetDC(hitem);
2123
font = (HFONT)SendMessageW(hitem, WM_GETFONT, 0, 0);
2124
SelectObject(hdc, font);
2125
2126
for(i = 0; i < This->filterspec_count; i++)
2127
{
2128
SendMessageW(hitem, CB_ADDSTRING, 0, (LPARAM)This->filterspecs[i].pszName);
2129
2130
if(GetTextExtentPoint32W(hdc, This->filterspecs[i].pszName, lstrlenW(This->filterspecs[i].pszName), &size))
2131
maxwidth = max(maxwidth, size.cx);
2132
}
2133
ReleaseDC(hitem, hdc);
2134
2135
if(maxwidth > 0)
2136
{
2137
maxwidth += GetSystemMetrics(SM_CXVSCROLL) + 4;
2138
SendMessageW(hitem, CB_SETDROPPEDWIDTH, (WPARAM)maxwidth, 0);
2139
}
2140
else
2141
ERR("Failed to calculate width of filetype dropdown\n");
2142
2143
SendMessageW(hitem, CB_SETCURSEL, This->filetypeindex, 0);
2144
}
2145
else
2146
ShowWindow(hitem, SW_HIDE);
2147
2148
if(This->set_filename &&
2149
(hitem = GetDlgItem(This->dlg_hwnd, IDC_FILENAME)) )
2150
SendMessageW(hitem, WM_SETTEXT, 0, (LPARAM)This->set_filename);
2151
2152
if(This->hmenu_opendropdown)
2153
{
2154
HWND dropdown_hwnd;
2155
LOGFONTW lfw, lfw_marlett;
2156
HFONT dialog_font;
2157
2158
dropdown_hwnd = GetDlgItem(This->dlg_hwnd, psh1);
2159
2160
/* Change dropdown button font to Marlett */
2161
dialog_font = (HFONT)SendMessageW(dropdown_hwnd, WM_GETFONT, 0, 0);
2162
2163
GetObjectW(dialog_font, sizeof(lfw), &lfw);
2164
2165
memset(&lfw_marlett, 0, sizeof(lfw_marlett));
2166
lstrcpyW(lfw_marlett.lfFaceName, L"Marlett");
2167
lfw_marlett.lfHeight = lfw.lfHeight;
2168
lfw_marlett.lfCharSet = SYMBOL_CHARSET;
2169
2170
This->hfont_opendropdown = CreateFontIndirectW(&lfw_marlett);
2171
2172
SendMessageW(dropdown_hwnd, WM_SETFONT, (LPARAM)This->hfont_opendropdown, 0);
2173
2174
/* Subclass button so we can handle LBUTTONDOWN */
2175
SetPropW(dropdown_hwnd, L"itemdlg_This", This);
2176
SetPropW(dropdown_hwnd, L"itemdlg_oldwndproc",
2177
(HANDLE)SetWindowLongPtrW(dropdown_hwnd, GWLP_WNDPROC, (LONG_PTR)dropdown_subclass_proc));
2178
}
2179
2180
ctrl_container_reparent(This, This->dlg_hwnd);
2181
init_explorerbrowser(This);
2182
init_toolbar(This, hwnd);
2183
update_control_text(This);
2184
update_layout(This);
2185
2186
if(This->filterspec_count)
2187
events_OnTypeChange(This);
2188
2189
if ((hitem = GetDlgItem(This->dlg_hwnd, IDC_FILENAME)))
2190
SetFocus(hitem);
2191
2192
return FALSE;
2193
}
2194
2195
static LRESULT on_wm_size(FileDialogImpl *This)
2196
{
2197
update_layout(This);
2198
return FALSE;
2199
}
2200
2201
static LRESULT on_wm_getminmaxinfo(FileDialogImpl *This, LPARAM lparam)
2202
{
2203
MINMAXINFO *mmi = (MINMAXINFO*)lparam;
2204
TRACE("%p (%p)\n", This, mmi);
2205
2206
/* FIXME */
2207
mmi->ptMinTrackSize.x = 640;
2208
mmi->ptMinTrackSize.y = 480;
2209
2210
return FALSE;
2211
}
2212
2213
static LRESULT on_wm_destroy(FileDialogImpl *This)
2214
{
2215
TRACE("%p\n", This);
2216
2217
if(This->peb)
2218
{
2219
IExplorerBrowser_Destroy(This->peb);
2220
IExplorerBrowser_Release(This->peb);
2221
This->peb = NULL;
2222
}
2223
2224
ctrl_container_reparent(This, NULL);
2225
This->dlg_hwnd = NULL;
2226
2227
DeleteObject(This->hfont_opendropdown);
2228
This->hfont_opendropdown = NULL;
2229
2230
return TRUE;
2231
}
2232
2233
static LRESULT on_idok(FileDialogImpl *This)
2234
{
2235
TRACE("%p\n", This);
2236
2237
if(SUCCEEDED(on_default_action(This)))
2238
EndDialog(This->dlg_hwnd, S_OK);
2239
2240
return FALSE;
2241
}
2242
2243
static LRESULT on_idcancel(FileDialogImpl *This)
2244
{
2245
TRACE("%p\n", This);
2246
2247
EndDialog(This->dlg_hwnd, HRESULT_FROM_WIN32(ERROR_CANCELLED));
2248
2249
return FALSE;
2250
}
2251
2252
static LRESULT on_command_opendropdown(FileDialogImpl *This, WPARAM wparam, LPARAM lparam)
2253
{
2254
if(HIWORD(wparam) == BN_CLICKED)
2255
{
2256
HWND hwnd = (HWND)lparam;
2257
SendMessageW(hwnd, BM_SETCHECK, BST_CHECKED, 0);
2258
show_opendropdown(This);
2259
SendMessageW(hwnd, BM_SETCHECK, BST_UNCHECKED, 0);
2260
}
2261
2262
return FALSE;
2263
}
2264
2265
static LRESULT on_browse_back(FileDialogImpl *This)
2266
{
2267
TRACE("%p\n", This);
2268
IExplorerBrowser_BrowseToIDList(This->peb, NULL, SBSP_NAVIGATEBACK);
2269
return FALSE;
2270
}
2271
2272
static LRESULT on_browse_forward(FileDialogImpl *This)
2273
{
2274
TRACE("%p\n", This);
2275
IExplorerBrowser_BrowseToIDList(This->peb, NULL, SBSP_NAVIGATEFORWARD);
2276
return FALSE;
2277
}
2278
2279
static LRESULT on_command_filetype(FileDialogImpl *This, WPARAM wparam, LPARAM lparam)
2280
{
2281
if(HIWORD(wparam) == CBN_SELCHANGE)
2282
{
2283
LPWSTR filename = NULL;
2284
UINT prev_index = This->filetypeindex;
2285
2286
This->filetypeindex = SendMessageW((HWND)lparam, CB_GETCURSEL, 0, 0);
2287
TRACE("File type selection changed to %d.\n", This->filetypeindex);
2288
2289
if(prev_index == This->filetypeindex)
2290
return FALSE;
2291
2292
set_current_filter(This, This->filterspecs[This->filetypeindex].pszSpec);
2293
2294
get_file_name(This, &filename);
2295
2296
if(filename && wcspbrk(filename, L"*?") != NULL && This->filterspecs[This->filetypeindex].pszSpec[0])
2297
{
2298
set_file_name(This, L"");
2299
}
2300
else if(filename && This->dlg_type == ITEMDLG_TYPE_SAVE)
2301
{
2302
WCHAR buf[MAX_PATH], extbuf[MAX_PATH], *ext;
2303
2304
ext = get_first_ext_from_spec(extbuf, This->filterspecs[This->filetypeindex].pszSpec);
2305
if(ext)
2306
{
2307
lstrcpyW(buf, filename);
2308
2309
if(PathMatchSpecW(buf, This->filterspecs[prev_index].pszSpec))
2310
PathRemoveExtensionW(buf);
2311
2312
lstrcatW(buf, ext);
2313
set_file_name(This, buf);
2314
}
2315
}
2316
2317
CoTaskMemFree(filename);
2318
2319
/* The documentation claims that OnTypeChange is called only
2320
* when the dialog is opened, but this is obviously not the
2321
* case. */
2322
events_OnTypeChange(This);
2323
}
2324
2325
return FALSE;
2326
}
2327
2328
static LRESULT on_browse_up(FileDialogImpl *This)
2329
{
2330
TRACE("%p\n", This);
2331
IExplorerBrowser_BrowseToIDList(This->peb, NULL, SBSP_PARENT);
2332
return FALSE;
2333
}
2334
2335
static LRESULT on_wm_command(FileDialogImpl *This, WPARAM wparam, LPARAM lparam)
2336
{
2337
switch(LOWORD(wparam))
2338
{
2339
case IDOK: return on_idok(This);
2340
case IDCANCEL: return on_idcancel(This);
2341
case psh1: return on_command_opendropdown(This, wparam, lparam);
2342
case IDC_NAVBACK: return on_browse_back(This);
2343
case IDC_NAVFORWARD: return on_browse_forward(This);
2344
case IDC_FILETYPE: return on_command_filetype(This, wparam, lparam);
2345
case IDC_NAVUP: return on_browse_up(This);
2346
default: TRACE("Unknown command.\n");
2347
}
2348
return FALSE;
2349
}
2350
2351
static INT_PTR CALLBACK itemdlg_dlgproc(HWND hwnd, UINT umessage, WPARAM wparam, LPARAM lparam)
2352
{
2353
FileDialogImpl *This = (FileDialogImpl*)GetWindowLongPtrW(hwnd, GWLP_USERDATA);
2354
2355
switch(umessage)
2356
{
2357
case WM_INITDIALOG: return on_wm_initdialog(hwnd, lparam);
2358
case WM_COMMAND: return on_wm_command(This, wparam, lparam);
2359
case WM_SIZE: return on_wm_size(This);
2360
case WM_GETMINMAXINFO: return on_wm_getminmaxinfo(This, lparam);
2361
case WM_DESTROY: return on_wm_destroy(This);
2362
}
2363
2364
return FALSE;
2365
}
2366
2367
static HRESULT create_dialog(FileDialogImpl *This, HWND parent)
2368
{
2369
ULONG_PTR ctx_cookie = 0;
2370
INT_PTR res;
2371
2372
if (This->dlg_hwnd)
2373
return E_UNEXPECTED;
2374
2375
if (!GetCurrentActCtx(&This->user_actctx))
2376
This->user_actctx = INVALID_HANDLE_VALUE;
2377
2378
if (COMDLG32_hActCtx != INVALID_HANDLE_VALUE)
2379
ActivateActCtx(COMDLG32_hActCtx, &ctx_cookie);
2380
2381
SetLastError(0);
2382
res = DialogBoxParamW(COMDLG32_hInstance,
2383
MAKEINTRESOURCEW(NEWFILEOPENV3ORD),
2384
parent, itemdlg_dlgproc, (LPARAM)This);
2385
This->dlg_hwnd = NULL;
2386
2387
if (COMDLG32_hActCtx != INVALID_HANDLE_VALUE)
2388
DeactivateActCtx(0, ctx_cookie);
2389
2390
if (This->user_actctx != INVALID_HANDLE_VALUE)
2391
{
2392
ReleaseActCtx(This->user_actctx);
2393
This->user_actctx = INVALID_HANDLE_VALUE;
2394
}
2395
2396
if(res == -1)
2397
{
2398
ERR("Failed to show dialog (LastError: %ld)\n", GetLastError());
2399
return E_FAIL;
2400
}
2401
2402
TRACE("Returning 0x%08lx\n", (HRESULT)res);
2403
return (HRESULT)res;
2404
}
2405
2406
/**************************************************************************
2407
* IFileDialog implementation
2408
*/
2409
static inline FileDialogImpl *impl_from_IFileDialog2(IFileDialog2 *iface)
2410
{
2411
return CONTAINING_RECORD(iface, FileDialogImpl, IFileDialog2_iface);
2412
}
2413
2414
static HRESULT WINAPI IFileDialog2_fnQueryInterface(IFileDialog2 *iface,
2415
REFIID riid,
2416
void **ppvObject)
2417
{
2418
FileDialogImpl *This = impl_from_IFileDialog2(iface);
2419
TRACE("%p (%s, %p)\n", This, debugstr_guid(riid), ppvObject);
2420
2421
*ppvObject = NULL;
2422
if(IsEqualGUID(riid, &IID_IUnknown) ||
2423
IsEqualGUID(riid, &IID_IFileDialog) ||
2424
IsEqualGUID(riid, &IID_IFileDialog2))
2425
{
2426
*ppvObject = iface;
2427
}
2428
else if(IsEqualGUID(riid, &IID_IFileOpenDialog) && This->dlg_type == ITEMDLG_TYPE_OPEN)
2429
{
2430
*ppvObject = &This->u.IFileOpenDialog_iface;
2431
}
2432
else if(IsEqualGUID(riid, &IID_IFileSaveDialog) && This->dlg_type == ITEMDLG_TYPE_SAVE)
2433
{
2434
*ppvObject = &This->u.IFileSaveDialog_iface;
2435
}
2436
else if(IsEqualGUID(riid, &IID_IExplorerBrowserEvents))
2437
{
2438
*ppvObject = &This->IExplorerBrowserEvents_iface;
2439
}
2440
else if(IsEqualGUID(riid, &IID_IServiceProvider))
2441
{
2442
*ppvObject = &This->IServiceProvider_iface;
2443
}
2444
else if(IsEqualGUID(&IID_ICommDlgBrowser3, riid) ||
2445
IsEqualGUID(&IID_ICommDlgBrowser2, riid) ||
2446
IsEqualGUID(&IID_ICommDlgBrowser, riid))
2447
{
2448
*ppvObject = &This->ICommDlgBrowser3_iface;
2449
}
2450
else if(IsEqualGUID(&IID_IOleWindow, riid))
2451
{
2452
*ppvObject = &This->IOleWindow_iface;
2453
}
2454
else if(IsEqualGUID(riid, &IID_IFileDialogCustomize) ||
2455
IsEqualGUID(riid, &IID_IFileDialogCustomizeAlt))
2456
{
2457
*ppvObject = &This->IFileDialogCustomize_iface;
2458
}
2459
else
2460
FIXME("Unknown interface requested: %s.\n", debugstr_guid(riid));
2461
2462
if(*ppvObject)
2463
{
2464
IUnknown_AddRef((IUnknown*)*ppvObject);
2465
return S_OK;
2466
}
2467
2468
return E_NOINTERFACE;
2469
}
2470
2471
static ULONG WINAPI IFileDialog2_fnAddRef(IFileDialog2 *iface)
2472
{
2473
FileDialogImpl *This = impl_from_IFileDialog2(iface);
2474
LONG ref = InterlockedIncrement(&This->ref);
2475
TRACE("%p - ref %ld\n", This, ref);
2476
2477
return ref;
2478
}
2479
2480
static ULONG WINAPI IFileDialog2_fnRelease(IFileDialog2 *iface)
2481
{
2482
FileDialogImpl *This = impl_from_IFileDialog2(iface);
2483
LONG ref = InterlockedDecrement(&This->ref);
2484
TRACE("%p - ref %ld\n", This, ref);
2485
2486
if(!ref)
2487
{
2488
UINT i;
2489
for(i = 0; i < This->filterspec_count; i++)
2490
{
2491
LocalFree((void*)This->filterspecs[i].pszName);
2492
LocalFree((void*)This->filterspecs[i].pszSpec);
2493
}
2494
HeapFree(GetProcessHeap(), 0, This->filterspecs);
2495
2496
DestroyWindow(This->cctrls_hwnd);
2497
2498
if(This->psi_defaultfolder) IShellItem_Release(This->psi_defaultfolder);
2499
if(This->psi_setfolder) IShellItem_Release(This->psi_setfolder);
2500
if(This->psi_folder) IShellItem_Release(This->psi_folder);
2501
if(This->psia_selection) IShellItemArray_Release(This->psia_selection);
2502
if(This->psia_results) IShellItemArray_Release(This->psia_results);
2503
2504
LocalFree(This->set_filename);
2505
LocalFree(This->default_ext);
2506
LocalFree(This->custom_title);
2507
LocalFree(This->custom_okbutton);
2508
LocalFree(This->custom_cancelbutton);
2509
LocalFree(This->custom_filenamelabel);
2510
LocalFree(This->current_filter);
2511
2512
DestroyMenu(This->hmenu_opendropdown);
2513
DeleteObject(This->hfont_opendropdown);
2514
2515
HeapFree(GetProcessHeap(), 0, This);
2516
}
2517
2518
return ref;
2519
}
2520
2521
static HRESULT WINAPI IFileDialog2_fnShow(IFileDialog2 *iface, HWND hwndOwner)
2522
{
2523
FileDialogImpl *This = impl_from_IFileDialog2(iface);
2524
TRACE("%p (%p)\n", iface, hwndOwner);
2525
2526
This->opendropdown_has_selection = FALSE;
2527
2528
return create_dialog(This, hwndOwner);
2529
}
2530
2531
static HRESULT WINAPI IFileDialog2_fnSetFileTypes(IFileDialog2 *iface, UINT cFileTypes,
2532
const COMDLG_FILTERSPEC *rgFilterSpec)
2533
{
2534
FileDialogImpl *This = impl_from_IFileDialog2(iface);
2535
UINT i;
2536
TRACE("%p (%d, %p)\n", This, cFileTypes, rgFilterSpec);
2537
2538
if(!rgFilterSpec)
2539
return E_INVALIDARG;
2540
2541
if(This->filterspecs)
2542
return E_UNEXPECTED;
2543
2544
if(!cFileTypes)
2545
return S_OK;
2546
2547
This->filterspecs = HeapAlloc(GetProcessHeap(), 0, sizeof(COMDLG_FILTERSPEC)*cFileTypes);
2548
for(i = 0; i < cFileTypes; i++)
2549
{
2550
This->filterspecs[i].pszName = StrDupW(rgFilterSpec[i].pszName);
2551
This->filterspecs[i].pszSpec = StrDupW(rgFilterSpec[i].pszSpec);
2552
2553
if (This->filterspecs[i].pszName != NULL && This->filterspecs[i].pszSpec != NULL)
2554
{
2555
DWORD name_len = lstrlenW(This->filterspecs[i].pszName);
2556
2557
if (name_len == 0 || This->filterspecs[i].pszName[name_len - 1] != L')')
2558
{
2559
DWORD spec_len = lstrlenW(This->filterspecs[i].pszSpec);
2560
2561
DWORD total_len = name_len + spec_len + 4;
2562
2563
WCHAR* pszName = LocalAlloc(LMEM_FIXED, total_len * sizeof(WCHAR));
2564
if (pszName != NULL)
2565
{
2566
swprintf(pszName, total_len, L"%s (%s)", This->filterspecs[i].pszName, This->filterspecs[i].pszSpec);
2567
LocalFree((void *)This->filterspecs[i].pszName);
2568
This->filterspecs[i].pszName = pszName;
2569
}
2570
}
2571
}
2572
}
2573
This->filterspec_count = cFileTypes;
2574
2575
set_current_filter(This, This->filterspecs[This->filetypeindex].pszSpec);
2576
2577
return S_OK;
2578
}
2579
2580
static HRESULT WINAPI IFileDialog2_fnSetFileTypeIndex(IFileDialog2 *iface, UINT iFileType)
2581
{
2582
FileDialogImpl *This = impl_from_IFileDialog2(iface);
2583
TRACE("%p (%d)\n", This, iFileType);
2584
2585
if(!This->filterspecs)
2586
return E_FAIL;
2587
2588
iFileType = max(iFileType, 1);
2589
iFileType = min(iFileType, This->filterspec_count);
2590
This->filetypeindex = iFileType-1;
2591
2592
set_current_filter(This, This->filterspecs[This->filetypeindex].pszSpec);
2593
2594
return S_OK;
2595
}
2596
2597
static HRESULT WINAPI IFileDialog2_fnGetFileTypeIndex(IFileDialog2 *iface, UINT *piFileType)
2598
{
2599
FileDialogImpl *This = impl_from_IFileDialog2(iface);
2600
TRACE("%p (%p)\n", This, piFileType);
2601
2602
if(!piFileType)
2603
return E_INVALIDARG;
2604
2605
if(This->filterspec_count == 0)
2606
*piFileType = 0;
2607
else
2608
*piFileType = This->filetypeindex + 1;
2609
2610
return S_OK;
2611
}
2612
2613
static HRESULT WINAPI IFileDialog2_fnAdvise(IFileDialog2 *iface, IFileDialogEvents *pfde, DWORD *pdwCookie)
2614
{
2615
FileDialogImpl *This = impl_from_IFileDialog2(iface);
2616
events_client *client;
2617
TRACE("%p (%p, %p)\n", This, pfde, pdwCookie);
2618
2619
if(!pfde || !pdwCookie)
2620
return E_INVALIDARG;
2621
2622
client = HeapAlloc(GetProcessHeap(), 0, sizeof(events_client));
2623
client->pfde = pfde;
2624
client->cookie = ++This->events_next_cookie;
2625
2626
IFileDialogEvents_AddRef(pfde);
2627
*pdwCookie = client->cookie;
2628
2629
list_add_tail(&This->events_clients, &client->entry);
2630
2631
return S_OK;
2632
}
2633
2634
static HRESULT WINAPI IFileDialog2_fnUnadvise(IFileDialog2 *iface, DWORD dwCookie)
2635
{
2636
FileDialogImpl *This = impl_from_IFileDialog2(iface);
2637
events_client *client, *found = NULL;
2638
TRACE("%p (%ld)\n", This, dwCookie);
2639
2640
LIST_FOR_EACH_ENTRY(client, &This->events_clients, events_client, entry)
2641
{
2642
if(client->cookie == dwCookie)
2643
{
2644
found = client;
2645
break;
2646
}
2647
}
2648
2649
if(found)
2650
{
2651
list_remove(&found->entry);
2652
IFileDialogEvents_Release(found->pfde);
2653
HeapFree(GetProcessHeap(), 0, found);
2654
return S_OK;
2655
}
2656
2657
return E_INVALIDARG;
2658
}
2659
2660
static HRESULT WINAPI IFileDialog2_fnSetOptions(IFileDialog2 *iface, FILEOPENDIALOGOPTIONS fos)
2661
{
2662
FileDialogImpl *This = impl_from_IFileDialog2(iface);
2663
TRACE("%p (0x%lx)\n", This, fos);
2664
2665
if (fos & ~(FOS_OVERWRITEPROMPT | FOS_STRICTFILETYPES | FOS_NOCHANGEDIR | FOS_PICKFOLDERS | FOS_FORCEFILESYSTEM
2666
| FOS_ALLNONSTORAGEITEMS | FOS_NOVALIDATE | FOS_ALLOWMULTISELECT | FOS_PATHMUSTEXIST | FOS_FILEMUSTEXIST
2667
| FOS_CREATEPROMPT | FOS_SHAREAWARE | FOS_NOREADONLYRETURN | FOS_NOTESTFILECREATE | FOS_HIDEMRUPLACES
2668
| FOS_HIDEPINNEDPLACES | FOS_NODEREFERENCELINKS | FOS_DONTADDTORECENT | FOS_FORCESHOWHIDDEN
2669
| FOS_DEFAULTNOMINIMODE | FOS_FORCEPREVIEWPANEON | FOS_SUPPORTSTREAMABLEITEMS))
2670
{
2671
WARN("Invalid option %#lx\n", fos);
2672
return E_INVALIDARG;
2673
}
2674
2675
if( !(This->options & FOS_PICKFOLDERS) && (fos & FOS_PICKFOLDERS) )
2676
{
2677
WCHAR buf[30];
2678
LoadStringW(COMDLG32_hInstance, IDS_SELECT_FOLDER, buf, ARRAY_SIZE(buf));
2679
IFileDialog2_SetTitle(iface, buf);
2680
}
2681
2682
This->options = fos;
2683
2684
return S_OK;
2685
}
2686
2687
static HRESULT WINAPI IFileDialog2_fnGetOptions(IFileDialog2 *iface, FILEOPENDIALOGOPTIONS *pfos)
2688
{
2689
FileDialogImpl *This = impl_from_IFileDialog2(iface);
2690
TRACE("%p (%p)\n", This, pfos);
2691
2692
if(!pfos)
2693
return E_INVALIDARG;
2694
2695
*pfos = This->options;
2696
2697
return S_OK;
2698
}
2699
2700
static HRESULT WINAPI IFileDialog2_fnSetDefaultFolder(IFileDialog2 *iface, IShellItem *psi)
2701
{
2702
FileDialogImpl *This = impl_from_IFileDialog2(iface);
2703
TRACE("%p (%p)\n", This, psi);
2704
if(This->psi_defaultfolder)
2705
IShellItem_Release(This->psi_defaultfolder);
2706
2707
This->psi_defaultfolder = psi;
2708
2709
if(This->psi_defaultfolder)
2710
IShellItem_AddRef(This->psi_defaultfolder);
2711
2712
return S_OK;
2713
}
2714
2715
static HRESULT WINAPI IFileDialog2_fnSetFolder(IFileDialog2 *iface, IShellItem *psi)
2716
{
2717
FileDialogImpl *This = impl_from_IFileDialog2(iface);
2718
TRACE("%p (%p)\n", This, psi);
2719
if(This->psi_setfolder)
2720
IShellItem_Release(This->psi_setfolder);
2721
2722
This->psi_setfolder = psi;
2723
2724
if(This->psi_setfolder)
2725
IShellItem_AddRef(This->psi_setfolder);
2726
2727
return S_OK;
2728
}
2729
2730
static HRESULT WINAPI IFileDialog2_fnGetFolder(IFileDialog2 *iface, IShellItem **ppsi)
2731
{
2732
FileDialogImpl *This = impl_from_IFileDialog2(iface);
2733
TRACE("%p (%p)\n", This, ppsi);
2734
if(!ppsi)
2735
return E_INVALIDARG;
2736
2737
/* FIXME:
2738
If the dialog is shown, return the current(ly selected) folder. */
2739
2740
*ppsi = NULL;
2741
if(This->psi_folder)
2742
*ppsi = This->psi_folder;
2743
else if(This->psi_setfolder)
2744
*ppsi = This->psi_setfolder;
2745
else if(This->psi_defaultfolder)
2746
*ppsi = This->psi_defaultfolder;
2747
2748
if(*ppsi)
2749
{
2750
IShellItem_AddRef(*ppsi);
2751
return S_OK;
2752
}
2753
2754
return E_FAIL;
2755
}
2756
2757
static HRESULT WINAPI IFileDialog2_fnGetCurrentSelection(IFileDialog2 *iface, IShellItem **ppsi)
2758
{
2759
FileDialogImpl *This = impl_from_IFileDialog2(iface);
2760
HRESULT hr;
2761
TRACE("%p (%p)\n", This, ppsi);
2762
2763
if(!ppsi)
2764
return E_INVALIDARG;
2765
2766
if(This->psia_selection)
2767
{
2768
/* FIXME: Check filename edit box */
2769
hr = IShellItemArray_GetItemAt(This->psia_selection, 0, ppsi);
2770
return hr;
2771
}
2772
2773
return E_FAIL;
2774
}
2775
2776
static HRESULT WINAPI IFileDialog2_fnSetFileName(IFileDialog2 *iface, LPCWSTR pszName)
2777
{
2778
FileDialogImpl *This = impl_from_IFileDialog2(iface);
2779
TRACE("%p (%s)\n", iface, debugstr_w(pszName));
2780
2781
set_file_name(This, pszName);
2782
2783
return S_OK;
2784
}
2785
2786
static HRESULT WINAPI IFileDialog2_fnGetFileName(IFileDialog2 *iface, LPWSTR *pszName)
2787
{
2788
FileDialogImpl *This = impl_from_IFileDialog2(iface);
2789
TRACE("%p (%p)\n", iface, pszName);
2790
2791
if(!pszName)
2792
return E_INVALIDARG;
2793
2794
*pszName = NULL;
2795
get_file_name(This, pszName);
2796
return *pszName ? S_OK : E_FAIL;
2797
}
2798
2799
static HRESULT WINAPI IFileDialog2_fnSetTitle(IFileDialog2 *iface, LPCWSTR pszTitle)
2800
{
2801
FileDialogImpl *This = impl_from_IFileDialog2(iface);
2802
TRACE("%p (%s)\n", This, debugstr_w(pszTitle));
2803
2804
LocalFree(This->custom_title);
2805
This->custom_title = StrDupW(pszTitle);
2806
update_control_text(This);
2807
2808
return S_OK;
2809
}
2810
2811
static HRESULT WINAPI IFileDialog2_fnSetOkButtonLabel(IFileDialog2 *iface, LPCWSTR pszText)
2812
{
2813
FileDialogImpl *This = impl_from_IFileDialog2(iface);
2814
TRACE("%p (%s)\n", This, debugstr_w(pszText));
2815
2816
LocalFree(This->custom_okbutton);
2817
This->custom_okbutton = StrDupW(pszText);
2818
update_control_text(This);
2819
update_layout(This);
2820
2821
return S_OK;
2822
}
2823
2824
static HRESULT WINAPI IFileDialog2_fnSetFileNameLabel(IFileDialog2 *iface, LPCWSTR pszLabel)
2825
{
2826
FileDialogImpl *This = impl_from_IFileDialog2(iface);
2827
TRACE("%p (%s)\n", This, debugstr_w(pszLabel));
2828
2829
LocalFree(This->custom_filenamelabel);
2830
This->custom_filenamelabel = StrDupW(pszLabel);
2831
update_control_text(This);
2832
update_layout(This);
2833
2834
return S_OK;
2835
}
2836
2837
static HRESULT WINAPI IFileDialog2_fnGetResult(IFileDialog2 *iface, IShellItem **ppsi)
2838
{
2839
FileDialogImpl *This = impl_from_IFileDialog2(iface);
2840
HRESULT hr;
2841
TRACE("%p (%p)\n", This, ppsi);
2842
2843
if(!ppsi)
2844
return E_INVALIDARG;
2845
2846
if(This->psia_results)
2847
{
2848
DWORD item_count;
2849
hr = IShellItemArray_GetCount(This->psia_results, &item_count);
2850
if(SUCCEEDED(hr))
2851
{
2852
if(item_count != 1)
2853
return E_FAIL;
2854
2855
/* Adds a reference. */
2856
hr = IShellItemArray_GetItemAt(This->psia_results, 0, ppsi);
2857
}
2858
2859
return hr;
2860
}
2861
2862
return E_UNEXPECTED;
2863
}
2864
2865
static HRESULT WINAPI IFileDialog2_fnAddPlace(IFileDialog2 *iface, IShellItem *psi, FDAP fdap)
2866
{
2867
FileDialogImpl *This = impl_from_IFileDialog2(iface);
2868
FIXME("stub - %p (%p, %d)\n", This, psi, fdap);
2869
return S_OK;
2870
}
2871
2872
static HRESULT WINAPI IFileDialog2_fnSetDefaultExtension(IFileDialog2 *iface, LPCWSTR pszDefaultExtension)
2873
{
2874
FileDialogImpl *This = impl_from_IFileDialog2(iface);
2875
TRACE("%p (%s)\n", This, debugstr_w(pszDefaultExtension));
2876
2877
LocalFree(This->default_ext);
2878
This->default_ext = StrDupW(pszDefaultExtension);
2879
2880
return S_OK;
2881
}
2882
2883
static HRESULT WINAPI IFileDialog2_fnClose(IFileDialog2 *iface, HRESULT hr)
2884
{
2885
FileDialogImpl *This = impl_from_IFileDialog2(iface);
2886
TRACE("%p (0x%08lx)\n", This, hr);
2887
2888
if(This->dlg_hwnd)
2889
EndDialog(This->dlg_hwnd, hr);
2890
2891
return S_OK;
2892
}
2893
2894
static HRESULT WINAPI IFileDialog2_fnSetClientGuid(IFileDialog2 *iface, REFGUID guid)
2895
{
2896
FileDialogImpl *This = impl_from_IFileDialog2(iface);
2897
TRACE("%p (%s)\n", This, debugstr_guid(guid));
2898
This->client_guid = *guid;
2899
return S_OK;
2900
}
2901
2902
static HRESULT WINAPI IFileDialog2_fnClearClientData(IFileDialog2 *iface)
2903
{
2904
FileDialogImpl *This = impl_from_IFileDialog2(iface);
2905
FIXME("stub - %p\n", This);
2906
return E_NOTIMPL;
2907
}
2908
2909
static HRESULT WINAPI IFileDialog2_fnSetFilter(IFileDialog2 *iface, IShellItemFilter *pFilter)
2910
{
2911
FileDialogImpl *This = impl_from_IFileDialog2(iface);
2912
FIXME("stub - %p (%p)\n", This, pFilter);
2913
return E_NOTIMPL;
2914
}
2915
2916
static HRESULT WINAPI IFileDialog2_fnSetCancelButtonLabel(IFileDialog2 *iface, LPCWSTR pszLabel)
2917
{
2918
FileDialogImpl *This = impl_from_IFileDialog2(iface);
2919
TRACE("%p (%s)\n", This, debugstr_w(pszLabel));
2920
2921
LocalFree(This->custom_cancelbutton);
2922
This->custom_cancelbutton = StrDupW(pszLabel);
2923
update_control_text(This);
2924
update_layout(This);
2925
2926
return S_OK;
2927
}
2928
2929
static HRESULT WINAPI IFileDialog2_fnSetNavigationRoot(IFileDialog2 *iface, IShellItem *psi)
2930
{
2931
FileDialogImpl *This = impl_from_IFileDialog2(iface);
2932
FIXME("stub - %p (%p)\n", This, psi);
2933
return E_NOTIMPL;
2934
}
2935
2936
static const IFileDialog2Vtbl vt_IFileDialog2 = {
2937
IFileDialog2_fnQueryInterface,
2938
IFileDialog2_fnAddRef,
2939
IFileDialog2_fnRelease,
2940
IFileDialog2_fnShow,
2941
IFileDialog2_fnSetFileTypes,
2942
IFileDialog2_fnSetFileTypeIndex,
2943
IFileDialog2_fnGetFileTypeIndex,
2944
IFileDialog2_fnAdvise,
2945
IFileDialog2_fnUnadvise,
2946
IFileDialog2_fnSetOptions,
2947
IFileDialog2_fnGetOptions,
2948
IFileDialog2_fnSetDefaultFolder,
2949
IFileDialog2_fnSetFolder,
2950
IFileDialog2_fnGetFolder,
2951
IFileDialog2_fnGetCurrentSelection,
2952
IFileDialog2_fnSetFileName,
2953
IFileDialog2_fnGetFileName,
2954
IFileDialog2_fnSetTitle,
2955
IFileDialog2_fnSetOkButtonLabel,
2956
IFileDialog2_fnSetFileNameLabel,
2957
IFileDialog2_fnGetResult,
2958
IFileDialog2_fnAddPlace,
2959
IFileDialog2_fnSetDefaultExtension,
2960
IFileDialog2_fnClose,
2961
IFileDialog2_fnSetClientGuid,
2962
IFileDialog2_fnClearClientData,
2963
IFileDialog2_fnSetFilter,
2964
IFileDialog2_fnSetCancelButtonLabel,
2965
IFileDialog2_fnSetNavigationRoot
2966
};
2967
2968
/**************************************************************************
2969
* IFileOpenDialog
2970
*/
2971
static inline FileDialogImpl *impl_from_IFileOpenDialog(IFileOpenDialog *iface)
2972
{
2973
return CONTAINING_RECORD(iface, FileDialogImpl, u.IFileOpenDialog_iface);
2974
}
2975
2976
static HRESULT WINAPI IFileOpenDialog_fnQueryInterface(IFileOpenDialog *iface,
2977
REFIID riid, void **ppvObject)
2978
{
2979
FileDialogImpl *This = impl_from_IFileOpenDialog(iface);
2980
return IFileDialog2_QueryInterface(&This->IFileDialog2_iface, riid, ppvObject);
2981
}
2982
2983
static ULONG WINAPI IFileOpenDialog_fnAddRef(IFileOpenDialog *iface)
2984
{
2985
FileDialogImpl *This = impl_from_IFileOpenDialog(iface);
2986
return IFileDialog2_AddRef(&This->IFileDialog2_iface);
2987
}
2988
2989
static ULONG WINAPI IFileOpenDialog_fnRelease(IFileOpenDialog *iface)
2990
{
2991
FileDialogImpl *This = impl_from_IFileOpenDialog(iface);
2992
return IFileDialog2_Release(&This->IFileDialog2_iface);
2993
}
2994
2995
static HRESULT WINAPI IFileOpenDialog_fnShow(IFileOpenDialog *iface, HWND hwndOwner)
2996
{
2997
FileDialogImpl *This = impl_from_IFileOpenDialog(iface);
2998
return IFileDialog2_Show(&This->IFileDialog2_iface, hwndOwner);
2999
}
3000
3001
static HRESULT WINAPI IFileOpenDialog_fnSetFileTypes(IFileOpenDialog *iface, UINT cFileTypes,
3002
const COMDLG_FILTERSPEC *rgFilterSpec)
3003
{
3004
FileDialogImpl *This = impl_from_IFileOpenDialog(iface);
3005
return IFileDialog2_SetFileTypes(&This->IFileDialog2_iface, cFileTypes, rgFilterSpec);
3006
}
3007
3008
static HRESULT WINAPI IFileOpenDialog_fnSetFileTypeIndex(IFileOpenDialog *iface, UINT iFileType)
3009
{
3010
FileDialogImpl *This = impl_from_IFileOpenDialog(iface);
3011
return IFileDialog2_SetFileTypeIndex(&This->IFileDialog2_iface, iFileType);
3012
}
3013
3014
static HRESULT WINAPI IFileOpenDialog_fnGetFileTypeIndex(IFileOpenDialog *iface, UINT *piFileType)
3015
{
3016
FileDialogImpl *This = impl_from_IFileOpenDialog(iface);
3017
return IFileDialog2_GetFileTypeIndex(&This->IFileDialog2_iface, piFileType);
3018
}
3019
3020
static HRESULT WINAPI IFileOpenDialog_fnAdvise(IFileOpenDialog *iface, IFileDialogEvents *pfde,
3021
DWORD *pdwCookie)
3022
{
3023
FileDialogImpl *This = impl_from_IFileOpenDialog(iface);
3024
return IFileDialog2_Advise(&This->IFileDialog2_iface, pfde, pdwCookie);
3025
}
3026
3027
static HRESULT WINAPI IFileOpenDialog_fnUnadvise(IFileOpenDialog *iface, DWORD dwCookie)
3028
{
3029
FileDialogImpl *This = impl_from_IFileOpenDialog(iface);
3030
return IFileDialog2_Unadvise(&This->IFileDialog2_iface, dwCookie);
3031
}
3032
3033
static HRESULT WINAPI IFileOpenDialog_fnSetOptions(IFileOpenDialog *iface, FILEOPENDIALOGOPTIONS fos)
3034
{
3035
FileDialogImpl *This = impl_from_IFileOpenDialog(iface);
3036
return IFileDialog2_SetOptions(&This->IFileDialog2_iface, fos);
3037
}
3038
3039
static HRESULT WINAPI IFileOpenDialog_fnGetOptions(IFileOpenDialog *iface, FILEOPENDIALOGOPTIONS *pfos)
3040
{
3041
FileDialogImpl *This = impl_from_IFileOpenDialog(iface);
3042
return IFileDialog2_GetOptions(&This->IFileDialog2_iface, pfos);
3043
}
3044
3045
static HRESULT WINAPI IFileOpenDialog_fnSetDefaultFolder(IFileOpenDialog *iface, IShellItem *psi)
3046
{
3047
FileDialogImpl *This = impl_from_IFileOpenDialog(iface);
3048
return IFileDialog2_SetDefaultFolder(&This->IFileDialog2_iface, psi);
3049
}
3050
3051
static HRESULT WINAPI IFileOpenDialog_fnSetFolder(IFileOpenDialog *iface, IShellItem *psi)
3052
{
3053
FileDialogImpl *This = impl_from_IFileOpenDialog(iface);
3054
return IFileDialog2_SetFolder(&This->IFileDialog2_iface, psi);
3055
}
3056
3057
static HRESULT WINAPI IFileOpenDialog_fnGetFolder(IFileOpenDialog *iface, IShellItem **ppsi)
3058
{
3059
FileDialogImpl *This = impl_from_IFileOpenDialog(iface);
3060
return IFileDialog2_GetFolder(&This->IFileDialog2_iface, ppsi);
3061
}
3062
3063
static HRESULT WINAPI IFileOpenDialog_fnGetCurrentSelection(IFileOpenDialog *iface, IShellItem **ppsi)
3064
{
3065
FileDialogImpl *This = impl_from_IFileOpenDialog(iface);
3066
return IFileDialog2_GetCurrentSelection(&This->IFileDialog2_iface, ppsi);
3067
}
3068
3069
static HRESULT WINAPI IFileOpenDialog_fnSetFileName(IFileOpenDialog *iface, LPCWSTR pszName)
3070
{
3071
FileDialogImpl *This = impl_from_IFileOpenDialog(iface);
3072
return IFileDialog2_SetFileName(&This->IFileDialog2_iface, pszName);
3073
}
3074
3075
static HRESULT WINAPI IFileOpenDialog_fnGetFileName(IFileOpenDialog *iface, LPWSTR *pszName)
3076
{
3077
FileDialogImpl *This = impl_from_IFileOpenDialog(iface);
3078
return IFileDialog2_GetFileName(&This->IFileDialog2_iface, pszName);
3079
}
3080
3081
static HRESULT WINAPI IFileOpenDialog_fnSetTitle(IFileOpenDialog *iface, LPCWSTR pszTitle)
3082
{
3083
FileDialogImpl *This = impl_from_IFileOpenDialog(iface);
3084
return IFileDialog2_SetTitle(&This->IFileDialog2_iface, pszTitle);
3085
}
3086
3087
static HRESULT WINAPI IFileOpenDialog_fnSetOkButtonLabel(IFileOpenDialog *iface, LPCWSTR pszText)
3088
{
3089
FileDialogImpl *This = impl_from_IFileOpenDialog(iface);
3090
return IFileDialog2_SetOkButtonLabel(&This->IFileDialog2_iface, pszText);
3091
}
3092
3093
static HRESULT WINAPI IFileOpenDialog_fnSetFileNameLabel(IFileOpenDialog *iface, LPCWSTR pszLabel)
3094
{
3095
FileDialogImpl *This = impl_from_IFileOpenDialog(iface);
3096
return IFileDialog2_SetFileNameLabel(&This->IFileDialog2_iface, pszLabel);
3097
}
3098
3099
static HRESULT WINAPI IFileOpenDialog_fnGetResult(IFileOpenDialog *iface, IShellItem **ppsi)
3100
{
3101
FileDialogImpl *This = impl_from_IFileOpenDialog(iface);
3102
return IFileDialog2_GetResult(&This->IFileDialog2_iface, ppsi);
3103
}
3104
3105
static HRESULT WINAPI IFileOpenDialog_fnAddPlace(IFileOpenDialog *iface, IShellItem *psi, FDAP fdap)
3106
{
3107
FileDialogImpl *This = impl_from_IFileOpenDialog(iface);
3108
return IFileDialog2_AddPlace(&This->IFileDialog2_iface, psi, fdap);
3109
}
3110
3111
static HRESULT WINAPI IFileOpenDialog_fnSetDefaultExtension(IFileOpenDialog *iface,
3112
LPCWSTR pszDefaultExtension)
3113
{
3114
FileDialogImpl *This = impl_from_IFileOpenDialog(iface);
3115
return IFileDialog2_SetDefaultExtension(&This->IFileDialog2_iface, pszDefaultExtension);
3116
}
3117
3118
static HRESULT WINAPI IFileOpenDialog_fnClose(IFileOpenDialog *iface, HRESULT hr)
3119
{
3120
FileDialogImpl *This = impl_from_IFileOpenDialog(iface);
3121
return IFileDialog2_Close(&This->IFileDialog2_iface, hr);
3122
}
3123
3124
static HRESULT WINAPI IFileOpenDialog_fnSetClientGuid(IFileOpenDialog *iface, REFGUID guid)
3125
{
3126
FileDialogImpl *This = impl_from_IFileOpenDialog(iface);
3127
return IFileDialog2_SetClientGuid(&This->IFileDialog2_iface, guid);
3128
}
3129
3130
static HRESULT WINAPI IFileOpenDialog_fnClearClientData(IFileOpenDialog *iface)
3131
{
3132
FileDialogImpl *This = impl_from_IFileOpenDialog(iface);
3133
return IFileDialog2_ClearClientData(&This->IFileDialog2_iface);
3134
}
3135
3136
static HRESULT WINAPI IFileOpenDialog_fnSetFilter(IFileOpenDialog *iface, IShellItemFilter *pFilter)
3137
{
3138
FileDialogImpl *This = impl_from_IFileOpenDialog(iface);
3139
return IFileDialog2_SetFilter(&This->IFileDialog2_iface, pFilter);
3140
}
3141
3142
static HRESULT WINAPI IFileOpenDialog_fnGetResults(IFileOpenDialog *iface, IShellItemArray **ppenum)
3143
{
3144
FileDialogImpl *This = impl_from_IFileOpenDialog(iface);
3145
TRACE("%p (%p)\n", This, ppenum);
3146
3147
*ppenum = This->psia_results;
3148
3149
if(*ppenum)
3150
{
3151
IShellItemArray_AddRef(*ppenum);
3152
return S_OK;
3153
}
3154
3155
return E_FAIL;
3156
}
3157
3158
static HRESULT WINAPI IFileOpenDialog_fnGetSelectedItems(IFileOpenDialog *iface, IShellItemArray **ppsai)
3159
{
3160
FileDialogImpl *This = impl_from_IFileOpenDialog(iface);
3161
TRACE("%p (%p)\n", This, ppsai);
3162
3163
if(This->psia_selection)
3164
{
3165
*ppsai = This->psia_selection;
3166
IShellItemArray_AddRef(*ppsai);
3167
return S_OK;
3168
}
3169
3170
return E_FAIL;
3171
}
3172
3173
static const IFileOpenDialogVtbl vt_IFileOpenDialog = {
3174
IFileOpenDialog_fnQueryInterface,
3175
IFileOpenDialog_fnAddRef,
3176
IFileOpenDialog_fnRelease,
3177
IFileOpenDialog_fnShow,
3178
IFileOpenDialog_fnSetFileTypes,
3179
IFileOpenDialog_fnSetFileTypeIndex,
3180
IFileOpenDialog_fnGetFileTypeIndex,
3181
IFileOpenDialog_fnAdvise,
3182
IFileOpenDialog_fnUnadvise,
3183
IFileOpenDialog_fnSetOptions,
3184
IFileOpenDialog_fnGetOptions,
3185
IFileOpenDialog_fnSetDefaultFolder,
3186
IFileOpenDialog_fnSetFolder,
3187
IFileOpenDialog_fnGetFolder,
3188
IFileOpenDialog_fnGetCurrentSelection,
3189
IFileOpenDialog_fnSetFileName,
3190
IFileOpenDialog_fnGetFileName,
3191
IFileOpenDialog_fnSetTitle,
3192
IFileOpenDialog_fnSetOkButtonLabel,
3193
IFileOpenDialog_fnSetFileNameLabel,
3194
IFileOpenDialog_fnGetResult,
3195
IFileOpenDialog_fnAddPlace,
3196
IFileOpenDialog_fnSetDefaultExtension,
3197
IFileOpenDialog_fnClose,
3198
IFileOpenDialog_fnSetClientGuid,
3199
IFileOpenDialog_fnClearClientData,
3200
IFileOpenDialog_fnSetFilter,
3201
IFileOpenDialog_fnGetResults,
3202
IFileOpenDialog_fnGetSelectedItems
3203
};
3204
3205
/**************************************************************************
3206
* IFileSaveDialog
3207
*/
3208
static inline FileDialogImpl *impl_from_IFileSaveDialog(IFileSaveDialog *iface)
3209
{
3210
return CONTAINING_RECORD(iface, FileDialogImpl, u.IFileSaveDialog_iface);
3211
}
3212
3213
static HRESULT WINAPI IFileSaveDialog_fnQueryInterface(IFileSaveDialog *iface,
3214
REFIID riid,
3215
void **ppvObject)
3216
{
3217
FileDialogImpl *This = impl_from_IFileSaveDialog(iface);
3218
return IFileDialog2_QueryInterface(&This->IFileDialog2_iface, riid, ppvObject);
3219
}
3220
3221
static ULONG WINAPI IFileSaveDialog_fnAddRef(IFileSaveDialog *iface)
3222
{
3223
FileDialogImpl *This = impl_from_IFileSaveDialog(iface);
3224
return IFileDialog2_AddRef(&This->IFileDialog2_iface);
3225
}
3226
3227
static ULONG WINAPI IFileSaveDialog_fnRelease(IFileSaveDialog *iface)
3228
{
3229
FileDialogImpl *This = impl_from_IFileSaveDialog(iface);
3230
return IFileDialog2_Release(&This->IFileDialog2_iface);
3231
}
3232
3233
static HRESULT WINAPI IFileSaveDialog_fnShow(IFileSaveDialog *iface, HWND hwndOwner)
3234
{
3235
FileDialogImpl *This = impl_from_IFileSaveDialog(iface);
3236
return IFileDialog2_Show(&This->IFileDialog2_iface, hwndOwner);
3237
}
3238
3239
static HRESULT WINAPI IFileSaveDialog_fnSetFileTypes(IFileSaveDialog *iface, UINT cFileTypes,
3240
const COMDLG_FILTERSPEC *rgFilterSpec)
3241
{
3242
FileDialogImpl *This = impl_from_IFileSaveDialog(iface);
3243
return IFileDialog2_SetFileTypes(&This->IFileDialog2_iface, cFileTypes, rgFilterSpec);
3244
}
3245
3246
static HRESULT WINAPI IFileSaveDialog_fnSetFileTypeIndex(IFileSaveDialog *iface, UINT iFileType)
3247
{
3248
FileDialogImpl *This = impl_from_IFileSaveDialog(iface);
3249
return IFileDialog2_SetFileTypeIndex(&This->IFileDialog2_iface, iFileType);
3250
}
3251
3252
static HRESULT WINAPI IFileSaveDialog_fnGetFileTypeIndex(IFileSaveDialog *iface, UINT *piFileType)
3253
{
3254
FileDialogImpl *This = impl_from_IFileSaveDialog(iface);
3255
return IFileDialog2_GetFileTypeIndex(&This->IFileDialog2_iface, piFileType);
3256
}
3257
3258
static HRESULT WINAPI IFileSaveDialog_fnAdvise(IFileSaveDialog *iface, IFileDialogEvents *pfde,
3259
DWORD *pdwCookie)
3260
{
3261
FileDialogImpl *This = impl_from_IFileSaveDialog(iface);
3262
return IFileDialog2_Advise(&This->IFileDialog2_iface, pfde, pdwCookie);
3263
}
3264
3265
static HRESULT WINAPI IFileSaveDialog_fnUnadvise(IFileSaveDialog *iface, DWORD dwCookie)
3266
{
3267
FileDialogImpl *This = impl_from_IFileSaveDialog(iface);
3268
return IFileDialog2_Unadvise(&This->IFileDialog2_iface, dwCookie);
3269
}
3270
3271
static HRESULT WINAPI IFileSaveDialog_fnSetOptions(IFileSaveDialog *iface, FILEOPENDIALOGOPTIONS fos)
3272
{
3273
FileDialogImpl *This = impl_from_IFileSaveDialog(iface);
3274
return IFileDialog2_SetOptions(&This->IFileDialog2_iface, fos);
3275
}
3276
3277
static HRESULT WINAPI IFileSaveDialog_fnGetOptions(IFileSaveDialog *iface, FILEOPENDIALOGOPTIONS *pfos)
3278
{
3279
FileDialogImpl *This = impl_from_IFileSaveDialog(iface);
3280
return IFileDialog2_GetOptions(&This->IFileDialog2_iface, pfos);
3281
}
3282
3283
static HRESULT WINAPI IFileSaveDialog_fnSetDefaultFolder(IFileSaveDialog *iface, IShellItem *psi)
3284
{
3285
FileDialogImpl *This = impl_from_IFileSaveDialog(iface);
3286
return IFileDialog2_SetDefaultFolder(&This->IFileDialog2_iface, psi);
3287
}
3288
3289
static HRESULT WINAPI IFileSaveDialog_fnSetFolder(IFileSaveDialog *iface, IShellItem *psi)
3290
{
3291
FileDialogImpl *This = impl_from_IFileSaveDialog(iface);
3292
return IFileDialog2_SetFolder(&This->IFileDialog2_iface, psi);
3293
}
3294
3295
static HRESULT WINAPI IFileSaveDialog_fnGetFolder(IFileSaveDialog *iface, IShellItem **ppsi)
3296
{
3297
FileDialogImpl *This = impl_from_IFileSaveDialog(iface);
3298
return IFileDialog2_GetFolder(&This->IFileDialog2_iface, ppsi);
3299
}
3300
3301
static HRESULT WINAPI IFileSaveDialog_fnGetCurrentSelection(IFileSaveDialog *iface, IShellItem **ppsi)
3302
{
3303
FileDialogImpl *This = impl_from_IFileSaveDialog(iface);
3304
return IFileDialog2_GetCurrentSelection(&This->IFileDialog2_iface, ppsi);
3305
}
3306
3307
static HRESULT WINAPI IFileSaveDialog_fnSetFileName(IFileSaveDialog *iface, LPCWSTR pszName)
3308
{
3309
FileDialogImpl *This = impl_from_IFileSaveDialog(iface);
3310
return IFileDialog2_SetFileName(&This->IFileDialog2_iface, pszName);
3311
}
3312
3313
static HRESULT WINAPI IFileSaveDialog_fnGetFileName(IFileSaveDialog *iface, LPWSTR *pszName)
3314
{
3315
FileDialogImpl *This = impl_from_IFileSaveDialog(iface);
3316
return IFileDialog2_GetFileName(&This->IFileDialog2_iface, pszName);
3317
}
3318
3319
static HRESULT WINAPI IFileSaveDialog_fnSetTitle(IFileSaveDialog *iface, LPCWSTR pszTitle)
3320
{
3321
FileDialogImpl *This = impl_from_IFileSaveDialog(iface);
3322
return IFileDialog2_SetTitle(&This->IFileDialog2_iface, pszTitle);
3323
}
3324
3325
static HRESULT WINAPI IFileSaveDialog_fnSetOkButtonLabel(IFileSaveDialog *iface, LPCWSTR pszText)
3326
{
3327
FileDialogImpl *This = impl_from_IFileSaveDialog(iface);
3328
return IFileDialog2_SetOkButtonLabel(&This->IFileDialog2_iface, pszText);
3329
}
3330
3331
static HRESULT WINAPI IFileSaveDialog_fnSetFileNameLabel(IFileSaveDialog *iface, LPCWSTR pszLabel)
3332
{
3333
FileDialogImpl *This = impl_from_IFileSaveDialog(iface);
3334
return IFileDialog2_SetFileNameLabel(&This->IFileDialog2_iface, pszLabel);
3335
}
3336
3337
static HRESULT WINAPI IFileSaveDialog_fnGetResult(IFileSaveDialog *iface, IShellItem **ppsi)
3338
{
3339
FileDialogImpl *This = impl_from_IFileSaveDialog(iface);
3340
return IFileDialog2_GetResult(&This->IFileDialog2_iface, ppsi);
3341
}
3342
3343
static HRESULT WINAPI IFileSaveDialog_fnAddPlace(IFileSaveDialog *iface, IShellItem *psi, FDAP fdap)
3344
{
3345
FileDialogImpl *This = impl_from_IFileSaveDialog(iface);
3346
return IFileDialog2_AddPlace(&This->IFileDialog2_iface, psi, fdap);
3347
}
3348
3349
static HRESULT WINAPI IFileSaveDialog_fnSetDefaultExtension(IFileSaveDialog *iface,
3350
LPCWSTR pszDefaultExtension)
3351
{
3352
FileDialogImpl *This = impl_from_IFileSaveDialog(iface);
3353
return IFileDialog2_SetDefaultExtension(&This->IFileDialog2_iface, pszDefaultExtension);
3354
}
3355
3356
static HRESULT WINAPI IFileSaveDialog_fnClose(IFileSaveDialog *iface, HRESULT hr)
3357
{
3358
FileDialogImpl *This = impl_from_IFileSaveDialog(iface);
3359
return IFileDialog2_Close(&This->IFileDialog2_iface, hr);
3360
}
3361
3362
static HRESULT WINAPI IFileSaveDialog_fnSetClientGuid(IFileSaveDialog *iface, REFGUID guid)
3363
{
3364
FileDialogImpl *This = impl_from_IFileSaveDialog(iface);
3365
return IFileDialog2_SetClientGuid(&This->IFileDialog2_iface, guid);
3366
}
3367
3368
static HRESULT WINAPI IFileSaveDialog_fnClearClientData(IFileSaveDialog *iface)
3369
{
3370
FileDialogImpl *This = impl_from_IFileSaveDialog(iface);
3371
return IFileDialog2_ClearClientData(&This->IFileDialog2_iface);
3372
}
3373
3374
static HRESULT WINAPI IFileSaveDialog_fnSetFilter(IFileSaveDialog *iface, IShellItemFilter *pFilter)
3375
{
3376
FileDialogImpl *This = impl_from_IFileSaveDialog(iface);
3377
return IFileDialog2_SetFilter(&This->IFileDialog2_iface, pFilter);
3378
}
3379
3380
static HRESULT WINAPI IFileSaveDialog_fnSetSaveAsItem(IFileSaveDialog* iface, IShellItem *psi)
3381
{
3382
FileDialogImpl *This = impl_from_IFileSaveDialog(iface);
3383
FIXME("stub - %p (%p)\n", This, psi);
3384
return E_NOTIMPL;
3385
}
3386
3387
static HRESULT WINAPI IFileSaveDialog_fnSetProperties(IFileSaveDialog* iface, IPropertyStore *pStore)
3388
{
3389
FileDialogImpl *This = impl_from_IFileSaveDialog(iface);
3390
FIXME("stub - %p (%p)\n", This, pStore);
3391
return E_NOTIMPL;
3392
}
3393
3394
static HRESULT WINAPI IFileSaveDialog_fnSetCollectedProperties(IFileSaveDialog* iface,
3395
IPropertyDescriptionList *pList,
3396
BOOL fAppendDefault)
3397
{
3398
FileDialogImpl *This = impl_from_IFileSaveDialog(iface);
3399
FIXME("stub - %p (%p, %d)\n", This, pList, fAppendDefault);
3400
return E_NOTIMPL;
3401
}
3402
3403
static HRESULT WINAPI IFileSaveDialog_fnGetProperties(IFileSaveDialog* iface, IPropertyStore **ppStore)
3404
{
3405
FileDialogImpl *This = impl_from_IFileSaveDialog(iface);
3406
FIXME("stub - %p (%p)\n", This, ppStore);
3407
return E_NOTIMPL;
3408
}
3409
3410
static HRESULT WINAPI IFileSaveDialog_fnApplyProperties(IFileSaveDialog* iface,
3411
IShellItem *psi,
3412
IPropertyStore *pStore,
3413
HWND hwnd,
3414
IFileOperationProgressSink *pSink)
3415
{
3416
FileDialogImpl *This = impl_from_IFileSaveDialog(iface);
3417
FIXME("%p (%p, %p, %p, %p)\n", This, psi, pStore, hwnd, pSink);
3418
return E_NOTIMPL;
3419
}
3420
3421
static const IFileSaveDialogVtbl vt_IFileSaveDialog = {
3422
IFileSaveDialog_fnQueryInterface,
3423
IFileSaveDialog_fnAddRef,
3424
IFileSaveDialog_fnRelease,
3425
IFileSaveDialog_fnShow,
3426
IFileSaveDialog_fnSetFileTypes,
3427
IFileSaveDialog_fnSetFileTypeIndex,
3428
IFileSaveDialog_fnGetFileTypeIndex,
3429
IFileSaveDialog_fnAdvise,
3430
IFileSaveDialog_fnUnadvise,
3431
IFileSaveDialog_fnSetOptions,
3432
IFileSaveDialog_fnGetOptions,
3433
IFileSaveDialog_fnSetDefaultFolder,
3434
IFileSaveDialog_fnSetFolder,
3435
IFileSaveDialog_fnGetFolder,
3436
IFileSaveDialog_fnGetCurrentSelection,
3437
IFileSaveDialog_fnSetFileName,
3438
IFileSaveDialog_fnGetFileName,
3439
IFileSaveDialog_fnSetTitle,
3440
IFileSaveDialog_fnSetOkButtonLabel,
3441
IFileSaveDialog_fnSetFileNameLabel,
3442
IFileSaveDialog_fnGetResult,
3443
IFileSaveDialog_fnAddPlace,
3444
IFileSaveDialog_fnSetDefaultExtension,
3445
IFileSaveDialog_fnClose,
3446
IFileSaveDialog_fnSetClientGuid,
3447
IFileSaveDialog_fnClearClientData,
3448
IFileSaveDialog_fnSetFilter,
3449
IFileSaveDialog_fnSetSaveAsItem,
3450
IFileSaveDialog_fnSetProperties,
3451
IFileSaveDialog_fnSetCollectedProperties,
3452
IFileSaveDialog_fnGetProperties,
3453
IFileSaveDialog_fnApplyProperties
3454
};
3455
3456
/**************************************************************************
3457
* IExplorerBrowserEvents implementation
3458
*/
3459
static inline FileDialogImpl *impl_from_IExplorerBrowserEvents(IExplorerBrowserEvents *iface)
3460
{
3461
return CONTAINING_RECORD(iface, FileDialogImpl, IExplorerBrowserEvents_iface);
3462
}
3463
3464
static HRESULT WINAPI IExplorerBrowserEvents_fnQueryInterface(IExplorerBrowserEvents *iface,
3465
REFIID riid, void **ppvObject)
3466
{
3467
FileDialogImpl *This = impl_from_IExplorerBrowserEvents(iface);
3468
TRACE("%p (%s, %p)\n", This, debugstr_guid(riid), ppvObject);
3469
3470
return IFileDialog2_QueryInterface(&This->IFileDialog2_iface, riid, ppvObject);
3471
}
3472
3473
static ULONG WINAPI IExplorerBrowserEvents_fnAddRef(IExplorerBrowserEvents *iface)
3474
{
3475
FileDialogImpl *This = impl_from_IExplorerBrowserEvents(iface);
3476
TRACE("%p\n", This);
3477
return IFileDialog2_AddRef(&This->IFileDialog2_iface);
3478
}
3479
3480
static ULONG WINAPI IExplorerBrowserEvents_fnRelease(IExplorerBrowserEvents *iface)
3481
{
3482
FileDialogImpl *This = impl_from_IExplorerBrowserEvents(iface);
3483
TRACE("%p\n", This);
3484
return IFileDialog2_Release(&This->IFileDialog2_iface);
3485
}
3486
3487
static HRESULT WINAPI IExplorerBrowserEvents_fnOnNavigationPending(IExplorerBrowserEvents *iface,
3488
PCIDLIST_ABSOLUTE pidlFolder)
3489
{
3490
FileDialogImpl *This = impl_from_IExplorerBrowserEvents(iface);
3491
IShellItem *psi;
3492
HRESULT hr;
3493
TRACE("%p (%p)\n", This, pidlFolder);
3494
3495
hr = SHCreateItemFromIDList(pidlFolder, &IID_IShellItem, (void**)&psi);
3496
if(SUCCEEDED(hr))
3497
{
3498
hr = events_OnFolderChanging(This, psi);
3499
IShellItem_Release(psi);
3500
3501
/* The ExplorerBrowser treats S_FALSE as S_OK, we don't. */
3502
if(hr == S_FALSE)
3503
hr = E_FAIL;
3504
3505
return hr;
3506
}
3507
else
3508
ERR("Failed to convert pidl (%p) to a shellitem.\n", pidlFolder);
3509
3510
return S_OK;
3511
}
3512
3513
static HRESULT WINAPI IExplorerBrowserEvents_fnOnViewCreated(IExplorerBrowserEvents *iface,
3514
IShellView *psv)
3515
{
3516
FileDialogImpl *This = impl_from_IExplorerBrowserEvents(iface);
3517
TRACE("%p (%p)\n", This, psv);
3518
return S_OK;
3519
}
3520
3521
static HRESULT WINAPI IExplorerBrowserEvents_fnOnNavigationComplete(IExplorerBrowserEvents *iface,
3522
PCIDLIST_ABSOLUTE pidlFolder)
3523
{
3524
FileDialogImpl *This = impl_from_IExplorerBrowserEvents(iface);
3525
HRESULT hr;
3526
TRACE("%p (%p)\n", This, pidlFolder);
3527
3528
if(This->psi_folder)
3529
IShellItem_Release(This->psi_folder);
3530
3531
hr = SHCreateItemFromIDList(pidlFolder, &IID_IShellItem, (void**)&This->psi_folder);
3532
if(FAILED(hr))
3533
{
3534
ERR("Failed to get the current folder.\n");
3535
This->psi_folder = NULL;
3536
}
3537
3538
events_OnFolderChange(This);
3539
3540
return S_OK;
3541
}
3542
3543
static HRESULT WINAPI IExplorerBrowserEvents_fnOnNavigationFailed(IExplorerBrowserEvents *iface,
3544
PCIDLIST_ABSOLUTE pidlFolder)
3545
{
3546
FileDialogImpl *This = impl_from_IExplorerBrowserEvents(iface);
3547
TRACE("%p (%p)\n", This, pidlFolder);
3548
return S_OK;
3549
}
3550
3551
static const IExplorerBrowserEventsVtbl vt_IExplorerBrowserEvents = {
3552
IExplorerBrowserEvents_fnQueryInterface,
3553
IExplorerBrowserEvents_fnAddRef,
3554
IExplorerBrowserEvents_fnRelease,
3555
IExplorerBrowserEvents_fnOnNavigationPending,
3556
IExplorerBrowserEvents_fnOnViewCreated,
3557
IExplorerBrowserEvents_fnOnNavigationComplete,
3558
IExplorerBrowserEvents_fnOnNavigationFailed
3559
};
3560
3561
/**************************************************************************
3562
* IServiceProvider implementation
3563
*/
3564
static inline FileDialogImpl *impl_from_IServiceProvider(IServiceProvider *iface)
3565
{
3566
return CONTAINING_RECORD(iface, FileDialogImpl, IServiceProvider_iface);
3567
}
3568
3569
static HRESULT WINAPI IServiceProvider_fnQueryInterface(IServiceProvider *iface,
3570
REFIID riid, void **ppvObject)
3571
{
3572
FileDialogImpl *This = impl_from_IServiceProvider(iface);
3573
TRACE("%p\n", This);
3574
return IFileDialog2_QueryInterface(&This->IFileDialog2_iface, riid, ppvObject);
3575
}
3576
3577
static ULONG WINAPI IServiceProvider_fnAddRef(IServiceProvider *iface)
3578
{
3579
FileDialogImpl *This = impl_from_IServiceProvider(iface);
3580
TRACE("%p\n", This);
3581
return IFileDialog2_AddRef(&This->IFileDialog2_iface);
3582
}
3583
3584
static ULONG WINAPI IServiceProvider_fnRelease(IServiceProvider *iface)
3585
{
3586
FileDialogImpl *This = impl_from_IServiceProvider(iface);
3587
TRACE("%p\n", This);
3588
return IFileDialog2_Release(&This->IFileDialog2_iface);
3589
}
3590
3591
static HRESULT WINAPI IServiceProvider_fnQueryService(IServiceProvider *iface,
3592
REFGUID guidService,
3593
REFIID riid, void **ppv)
3594
{
3595
FileDialogImpl *This = impl_from_IServiceProvider(iface);
3596
HRESULT hr = E_NOTIMPL;
3597
TRACE("%p (%s, %s, %p)\n", This, debugstr_guid(guidService), debugstr_guid(riid), ppv);
3598
3599
*ppv = NULL;
3600
if(IsEqualGUID(guidService, &SID_STopLevelBrowser) && This->peb)
3601
hr = IExplorerBrowser_QueryInterface(This->peb, riid, ppv);
3602
else if(IsEqualGUID(guidService, &SID_SExplorerBrowserFrame))
3603
hr = IFileDialog2_QueryInterface(&This->IFileDialog2_iface, riid, ppv);
3604
else
3605
FIXME("Interface %s requested from unknown service %s\n",
3606
debugstr_guid(riid), debugstr_guid(guidService));
3607
3608
return hr;
3609
}
3610
3611
static const IServiceProviderVtbl vt_IServiceProvider = {
3612
IServiceProvider_fnQueryInterface,
3613
IServiceProvider_fnAddRef,
3614
IServiceProvider_fnRelease,
3615
IServiceProvider_fnQueryService
3616
};
3617
3618
/**************************************************************************
3619
* ICommDlgBrowser3 implementation
3620
*/
3621
static inline FileDialogImpl *impl_from_ICommDlgBrowser3(ICommDlgBrowser3 *iface)
3622
{
3623
return CONTAINING_RECORD(iface, FileDialogImpl, ICommDlgBrowser3_iface);
3624
}
3625
3626
static HRESULT WINAPI ICommDlgBrowser3_fnQueryInterface(ICommDlgBrowser3 *iface,
3627
REFIID riid, void **ppvObject)
3628
{
3629
FileDialogImpl *This = impl_from_ICommDlgBrowser3(iface);
3630
TRACE("%p\n", This);
3631
return IFileDialog2_QueryInterface(&This->IFileDialog2_iface, riid, ppvObject);
3632
}
3633
3634
static ULONG WINAPI ICommDlgBrowser3_fnAddRef(ICommDlgBrowser3 *iface)
3635
{
3636
FileDialogImpl *This = impl_from_ICommDlgBrowser3(iface);
3637
TRACE("%p\n", This);
3638
return IFileDialog2_AddRef(&This->IFileDialog2_iface);
3639
}
3640
3641
static ULONG WINAPI ICommDlgBrowser3_fnRelease(ICommDlgBrowser3 *iface)
3642
{
3643
FileDialogImpl *This = impl_from_ICommDlgBrowser3(iface);
3644
TRACE("%p\n", This);
3645
return IFileDialog2_Release(&This->IFileDialog2_iface);
3646
}
3647
3648
static HRESULT WINAPI ICommDlgBrowser3_fnOnDefaultCommand(ICommDlgBrowser3 *iface,
3649
IShellView *shv)
3650
{
3651
FileDialogImpl *This = impl_from_ICommDlgBrowser3(iface);
3652
HRESULT hr;
3653
TRACE("%p (%p)\n", This, shv);
3654
3655
hr = on_default_action(This);
3656
3657
if(SUCCEEDED(hr))
3658
EndDialog(This->dlg_hwnd, S_OK);
3659
3660
return S_OK;
3661
}
3662
3663
static HRESULT WINAPI ICommDlgBrowser3_fnOnStateChange(ICommDlgBrowser3 *iface,
3664
IShellView *shv, ULONG uChange )
3665
{
3666
FileDialogImpl *This = impl_from_ICommDlgBrowser3(iface);
3667
IDataObject *new_selection;
3668
HRESULT hr;
3669
TRACE("%p (%p, %lx)\n", This, shv, uChange);
3670
3671
switch(uChange)
3672
{
3673
case CDBOSC_SELCHANGE:
3674
if(This->psia_selection)
3675
{
3676
IShellItemArray_Release(This->psia_selection);
3677
This->psia_selection = NULL;
3678
}
3679
3680
hr = IShellView_GetItemObject(shv, SVGIO_SELECTION, &IID_IDataObject, (void**)&new_selection);
3681
if(SUCCEEDED(hr))
3682
{
3683
hr = SHCreateShellItemArrayFromDataObject(new_selection, &IID_IShellItemArray,
3684
(void**)&This->psia_selection);
3685
if(SUCCEEDED(hr))
3686
{
3687
fill_filename_from_selection(This);
3688
events_OnSelectionChange(This);
3689
}
3690
3691
IDataObject_Release(new_selection);
3692
}
3693
break;
3694
default:
3695
TRACE("Unhandled state change\n");
3696
}
3697
return S_OK;
3698
}
3699
3700
static HRESULT WINAPI ICommDlgBrowser3_fnIncludeObject(ICommDlgBrowser3 *iface,
3701
IShellView *shv, LPCITEMIDLIST pidl)
3702
{
3703
FileDialogImpl *This = impl_from_ICommDlgBrowser3(iface);
3704
IShellItem *psi;
3705
LPWSTR filename;
3706
LPITEMIDLIST parent_pidl;
3707
HRESULT hr;
3708
ULONG attr;
3709
TRACE("%p (%p, %p)\n", This, shv, pidl);
3710
3711
if(!This->current_filter && !(This->options & FOS_PICKFOLDERS))
3712
return S_OK;
3713
3714
hr = SHGetIDListFromObject((IUnknown*)shv, &parent_pidl);
3715
if(SUCCEEDED(hr))
3716
{
3717
LPITEMIDLIST full_pidl = ILCombine(parent_pidl, pidl);
3718
hr = SHCreateItemFromIDList(full_pidl, &IID_IShellItem, (void**)&psi);
3719
ILFree(parent_pidl);
3720
ILFree(full_pidl);
3721
}
3722
if(FAILED(hr))
3723
{
3724
ERR("Failed to get shellitem (%08lx).\n", hr);
3725
return S_OK;
3726
}
3727
3728
hr = IShellItem_GetAttributes(psi, SFGAO_FOLDER|SFGAO_LINK, &attr);
3729
if(FAILED(hr) || (attr & (SFGAO_FOLDER | SFGAO_LINK)))
3730
{
3731
IShellItem_Release(psi);
3732
return S_OK;
3733
}
3734
3735
if((This->options & FOS_PICKFOLDERS) && !(attr & (SFGAO_FOLDER | SFGAO_LINK)))
3736
{
3737
IShellItem_Release(psi);
3738
return S_FALSE;
3739
}
3740
3741
hr = S_OK;
3742
if(SUCCEEDED(IShellItem_GetDisplayName(psi, SIGDN_PARENTRELATIVEPARSING, &filename)))
3743
{
3744
if(!PathMatchSpecW(filename, This->current_filter))
3745
hr = S_FALSE;
3746
CoTaskMemFree(filename);
3747
}
3748
3749
IShellItem_Release(psi);
3750
return hr;
3751
}
3752
3753
static HRESULT WINAPI ICommDlgBrowser3_fnNotify(ICommDlgBrowser3 *iface,
3754
IShellView *ppshv, DWORD dwNotifyType)
3755
{
3756
FileDialogImpl *This = impl_from_ICommDlgBrowser3(iface);
3757
FIXME("Stub: %p (%p, 0x%lx)\n", This, ppshv, dwNotifyType);
3758
return E_NOTIMPL;
3759
}
3760
3761
static HRESULT WINAPI ICommDlgBrowser3_fnGetDefaultMenuText(ICommDlgBrowser3 *iface,
3762
IShellView *pshv,
3763
LPWSTR pszText, int cchMax)
3764
{
3765
FileDialogImpl *This = impl_from_ICommDlgBrowser3(iface);
3766
FIXME("Stub: %p (%p, %p, %d)\n", This, pshv, pszText, cchMax);
3767
return E_NOTIMPL;
3768
}
3769
3770
static HRESULT WINAPI ICommDlgBrowser3_fnGetViewFlags(ICommDlgBrowser3 *iface, DWORD *pdwFlags)
3771
{
3772
FileDialogImpl *This = impl_from_ICommDlgBrowser3(iface);
3773
FIXME("Stub: %p (%p)\n", This, pdwFlags);
3774
return E_NOTIMPL;
3775
}
3776
3777
static HRESULT WINAPI ICommDlgBrowser3_fnOnColumnClicked(ICommDlgBrowser3 *iface,
3778
IShellView *pshv, int iColumn)
3779
{
3780
FileDialogImpl *This = impl_from_ICommDlgBrowser3(iface);
3781
FIXME("Stub: %p (%p, %d)\n", This, pshv, iColumn);
3782
return E_NOTIMPL;
3783
}
3784
3785
static HRESULT WINAPI ICommDlgBrowser3_fnGetCurrentFilter(ICommDlgBrowser3 *iface,
3786
LPWSTR pszFileSpec, int cchFileSpec)
3787
{
3788
FileDialogImpl *This = impl_from_ICommDlgBrowser3(iface);
3789
FIXME("Stub: %p (%p, %d)\n", This, pszFileSpec, cchFileSpec);
3790
return E_NOTIMPL;
3791
}
3792
3793
static HRESULT WINAPI ICommDlgBrowser3_fnOnPreviewCreated(ICommDlgBrowser3 *iface,
3794
IShellView *pshv)
3795
{
3796
FileDialogImpl *This = impl_from_ICommDlgBrowser3(iface);
3797
FIXME("Stub: %p (%p)\n", This, pshv);
3798
return E_NOTIMPL;
3799
}
3800
3801
static const ICommDlgBrowser3Vtbl vt_ICommDlgBrowser3 = {
3802
ICommDlgBrowser3_fnQueryInterface,
3803
ICommDlgBrowser3_fnAddRef,
3804
ICommDlgBrowser3_fnRelease,
3805
ICommDlgBrowser3_fnOnDefaultCommand,
3806
ICommDlgBrowser3_fnOnStateChange,
3807
ICommDlgBrowser3_fnIncludeObject,
3808
ICommDlgBrowser3_fnNotify,
3809
ICommDlgBrowser3_fnGetDefaultMenuText,
3810
ICommDlgBrowser3_fnGetViewFlags,
3811
ICommDlgBrowser3_fnOnColumnClicked,
3812
ICommDlgBrowser3_fnGetCurrentFilter,
3813
ICommDlgBrowser3_fnOnPreviewCreated
3814
};
3815
3816
/**************************************************************************
3817
* IOleWindow implementation
3818
*/
3819
static inline FileDialogImpl *impl_from_IOleWindow(IOleWindow *iface)
3820
{
3821
return CONTAINING_RECORD(iface, FileDialogImpl, IOleWindow_iface);
3822
}
3823
3824
static HRESULT WINAPI IOleWindow_fnQueryInterface(IOleWindow *iface, REFIID riid, void **ppvObject)
3825
{
3826
FileDialogImpl *This = impl_from_IOleWindow(iface);
3827
return IFileDialog2_QueryInterface(&This->IFileDialog2_iface, riid, ppvObject);
3828
}
3829
3830
static ULONG WINAPI IOleWindow_fnAddRef(IOleWindow *iface)
3831
{
3832
FileDialogImpl *This = impl_from_IOleWindow(iface);
3833
return IFileDialog2_AddRef(&This->IFileDialog2_iface);
3834
}
3835
3836
static ULONG WINAPI IOleWindow_fnRelease(IOleWindow *iface)
3837
{
3838
FileDialogImpl *This = impl_from_IOleWindow(iface);
3839
return IFileDialog2_Release(&This->IFileDialog2_iface);
3840
}
3841
3842
static HRESULT WINAPI IOleWindow_fnContextSensitiveHelp(IOleWindow *iface, BOOL fEnterMOde)
3843
{
3844
FileDialogImpl *This = impl_from_IOleWindow(iface);
3845
FIXME("Stub: %p (%d)\n", This, fEnterMOde);
3846
return E_NOTIMPL;
3847
}
3848
3849
static HRESULT WINAPI IOleWindow_fnGetWindow(IOleWindow *iface, HWND *phwnd)
3850
{
3851
FileDialogImpl *This = impl_from_IOleWindow(iface);
3852
TRACE("%p (%p)\n", This, phwnd);
3853
*phwnd = This->dlg_hwnd;
3854
return S_OK;
3855
}
3856
3857
static const IOleWindowVtbl vt_IOleWindow = {
3858
IOleWindow_fnQueryInterface,
3859
IOleWindow_fnAddRef,
3860
IOleWindow_fnRelease,
3861
IOleWindow_fnGetWindow,
3862
IOleWindow_fnContextSensitiveHelp
3863
};
3864
3865
/**************************************************************************
3866
* IFileDialogCustomize implementation
3867
*/
3868
static inline FileDialogImpl *impl_from_IFileDialogCustomize(IFileDialogCustomize *iface)
3869
{
3870
return CONTAINING_RECORD(iface, FileDialogImpl, IFileDialogCustomize_iface);
3871
}
3872
3873
static HRESULT WINAPI IFileDialogCustomize_fnQueryInterface(IFileDialogCustomize *iface,
3874
REFIID riid, void **ppvObject)
3875
{
3876
FileDialogImpl *This = impl_from_IFileDialogCustomize(iface);
3877
return IFileDialog2_QueryInterface(&This->IFileDialog2_iface, riid, ppvObject);
3878
}
3879
3880
static ULONG WINAPI IFileDialogCustomize_fnAddRef(IFileDialogCustomize *iface)
3881
{
3882
FileDialogImpl *This = impl_from_IFileDialogCustomize(iface);
3883
return IFileDialog2_AddRef(&This->IFileDialog2_iface);
3884
}
3885
3886
static ULONG WINAPI IFileDialogCustomize_fnRelease(IFileDialogCustomize *iface)
3887
{
3888
FileDialogImpl *This = impl_from_IFileDialogCustomize(iface);
3889
return IFileDialog2_Release(&This->IFileDialog2_iface);
3890
}
3891
3892
static HRESULT WINAPI IFileDialogCustomize_fnEnableOpenDropDown(IFileDialogCustomize *iface,
3893
DWORD dwIDCtl)
3894
{
3895
FileDialogImpl *This = impl_from_IFileDialogCustomize(iface);
3896
MENUINFO mi;
3897
TRACE("%p (%ld)\n", This, dwIDCtl);
3898
3899
if (This->hmenu_opendropdown || get_cctrl(This, dwIDCtl))
3900
return E_UNEXPECTED;
3901
3902
This->hmenu_opendropdown = CreatePopupMenu();
3903
3904
if (!This->hmenu_opendropdown)
3905
return E_OUTOFMEMORY;
3906
3907
mi.cbSize = sizeof(mi);
3908
mi.fMask = MIM_STYLE;
3909
mi.dwStyle = MNS_NOTIFYBYPOS;
3910
SetMenuInfo(This->hmenu_opendropdown, &mi);
3911
3912
This->cctrl_opendropdown.hwnd = NULL;
3913
This->cctrl_opendropdown.wrapper_hwnd = NULL;
3914
This->cctrl_opendropdown.id = dwIDCtl;
3915
This->cctrl_opendropdown.dlgid = 0;
3916
This->cctrl_opendropdown.type = IDLG_CCTRL_OPENDROPDOWN;
3917
This->cctrl_opendropdown.cdcstate = CDCS_ENABLED | CDCS_VISIBLE;
3918
list_init(&This->cctrl_opendropdown.sub_cctrls);
3919
list_init(&This->cctrl_opendropdown.sub_items);
3920
3921
return S_OK;
3922
}
3923
3924
static HRESULT WINAPI IFileDialogCustomize_fnAddMenu(IFileDialogCustomize *iface,
3925
DWORD dwIDCtl,
3926
LPCWSTR pszLabel)
3927
{
3928
FileDialogImpl *This = impl_from_IFileDialogCustomize(iface);
3929
customctrl *ctrl;
3930
TBBUTTON tbb;
3931
HRESULT hr;
3932
TRACE("%p (%ld, %p)\n", This, dwIDCtl, pszLabel);
3933
3934
hr = cctrl_create_new(This, dwIDCtl, NULL, TOOLBARCLASSNAMEW,
3935
TBSTYLE_FLAT | CCS_NODIVIDER, 0,
3936
This->cctrl_def_height, &ctrl);
3937
if(SUCCEEDED(hr))
3938
{
3939
SendMessageW(ctrl->hwnd, TB_BUTTONSTRUCTSIZE, sizeof(tbb), 0);
3940
ctrl->type = IDLG_CCTRL_MENU;
3941
3942
/* Add the actual button with a popup menu. */
3943
tbb.iBitmap = I_IMAGENONE;
3944
tbb.dwData = (DWORD_PTR)CreatePopupMenu();
3945
tbb.iString = (DWORD_PTR)pszLabel;
3946
tbb.fsState = TBSTATE_ENABLED;
3947
tbb.fsStyle = BTNS_WHOLEDROPDOWN;
3948
tbb.idCommand = 1;
3949
3950
SendMessageW(ctrl->hwnd, TB_ADDBUTTONSW, 1, (LPARAM)&tbb);
3951
}
3952
3953
return hr;
3954
}
3955
3956
static HRESULT WINAPI IFileDialogCustomize_fnAddPushButton(IFileDialogCustomize *iface,
3957
DWORD dwIDCtl,
3958
LPCWSTR pszLabel)
3959
{
3960
FileDialogImpl *This = impl_from_IFileDialogCustomize(iface);
3961
customctrl *ctrl;
3962
HRESULT hr;
3963
TRACE("%p (%ld, %p)\n", This, dwIDCtl, pszLabel);
3964
3965
hr = cctrl_create_new(This, dwIDCtl, pszLabel, WC_BUTTONW, BS_MULTILINE, 0,
3966
This->cctrl_def_height, &ctrl);
3967
if(SUCCEEDED(hr))
3968
ctrl->type = IDLG_CCTRL_PUSHBUTTON;
3969
3970
return hr;
3971
}
3972
3973
static HRESULT WINAPI IFileDialogCustomize_fnAddComboBox(IFileDialogCustomize *iface,
3974
DWORD dwIDCtl)
3975
{
3976
FileDialogImpl *This = impl_from_IFileDialogCustomize(iface);
3977
customctrl *ctrl;
3978
HRESULT hr;
3979
TRACE("%p (%ld)\n", This, dwIDCtl);
3980
3981
hr = cctrl_create_new(This, dwIDCtl, NULL, WC_COMBOBOXW, CBS_DROPDOWNLIST, 0,
3982
This->cctrl_def_height, &ctrl);
3983
if(SUCCEEDED(hr))
3984
ctrl->type = IDLG_CCTRL_COMBOBOX;
3985
3986
return hr;
3987
}
3988
3989
static HRESULT WINAPI IFileDialogCustomize_fnAddRadioButtonList(IFileDialogCustomize *iface,
3990
DWORD dwIDCtl)
3991
{
3992
FileDialogImpl *This = impl_from_IFileDialogCustomize(iface);
3993
customctrl *ctrl;
3994
HRESULT hr;
3995
TRACE("%p (%ld)\n", This, dwIDCtl);
3996
3997
hr = cctrl_create_new(This, dwIDCtl, NULL, L"RadioButtonList", 0, 0, 0, &ctrl);
3998
if(SUCCEEDED(hr))
3999
{
4000
ctrl->type = IDLG_CCTRL_RADIOBUTTONLIST;
4001
SetWindowLongPtrW(ctrl->hwnd, GWLP_USERDATA, (LPARAM)This);
4002
}
4003
4004
return hr;
4005
}
4006
4007
static HRESULT WINAPI IFileDialogCustomize_fnAddCheckButton(IFileDialogCustomize *iface,
4008
DWORD dwIDCtl,
4009
LPCWSTR pszLabel,
4010
BOOL bChecked)
4011
{
4012
FileDialogImpl *This = impl_from_IFileDialogCustomize(iface);
4013
customctrl *ctrl;
4014
HRESULT hr;
4015
TRACE("%p (%ld, %p, %d)\n", This, dwIDCtl, pszLabel, bChecked);
4016
4017
hr = cctrl_create_new(This, dwIDCtl, pszLabel, WC_BUTTONW, BS_AUTOCHECKBOX|BS_MULTILINE, 0,
4018
This->cctrl_def_height, &ctrl);
4019
if(SUCCEEDED(hr))
4020
{
4021
ctrl->type = IDLG_CCTRL_CHECKBUTTON;
4022
SendMessageW(ctrl->hwnd, BM_SETCHECK, bChecked ? BST_CHECKED : BST_UNCHECKED, 0);
4023
}
4024
4025
return hr;
4026
}
4027
4028
static HRESULT WINAPI IFileDialogCustomize_fnAddEditBox(IFileDialogCustomize *iface,
4029
DWORD dwIDCtl,
4030
LPCWSTR pszText)
4031
{
4032
FileDialogImpl *This = impl_from_IFileDialogCustomize(iface);
4033
customctrl *ctrl;
4034
HRESULT hr;
4035
TRACE("%p (%ld, %p)\n", This, dwIDCtl, pszText);
4036
4037
hr = cctrl_create_new(This, dwIDCtl, pszText, WC_EDITW, ES_AUTOHSCROLL, WS_EX_CLIENTEDGE,
4038
This->cctrl_def_height, &ctrl);
4039
if(SUCCEEDED(hr))
4040
ctrl->type = IDLG_CCTRL_EDITBOX;
4041
4042
return hr;
4043
}
4044
4045
static HRESULT WINAPI IFileDialogCustomize_fnAddSeparator(IFileDialogCustomize *iface,
4046
DWORD dwIDCtl)
4047
{
4048
FileDialogImpl *This = impl_from_IFileDialogCustomize(iface);
4049
customctrl *ctrl;
4050
HRESULT hr;
4051
TRACE("%p (%ld)\n", This, dwIDCtl);
4052
4053
hr = cctrl_create_new(This, dwIDCtl, NULL, WC_STATICW, SS_ETCHEDHORZ, 0,
4054
GetSystemMetrics(SM_CYEDGE), &ctrl);
4055
if(SUCCEEDED(hr))
4056
ctrl->type = IDLG_CCTRL_SEPARATOR;
4057
4058
return hr;
4059
}
4060
4061
static HRESULT WINAPI IFileDialogCustomize_fnAddText(IFileDialogCustomize *iface,
4062
DWORD dwIDCtl,
4063
LPCWSTR pszText)
4064
{
4065
FileDialogImpl *This = impl_from_IFileDialogCustomize(iface);
4066
customctrl *ctrl;
4067
HRESULT hr;
4068
TRACE("%p (%ld, %p)\n", This, dwIDCtl, pszText);
4069
4070
hr = cctrl_create_new(This, dwIDCtl, pszText, WC_STATICW, 0, 0,
4071
This->cctrl_def_height, &ctrl);
4072
if(SUCCEEDED(hr))
4073
ctrl->type = IDLG_CCTRL_TEXT;
4074
4075
return hr;
4076
}
4077
4078
static HRESULT WINAPI IFileDialogCustomize_fnSetControlLabel(IFileDialogCustomize *iface,
4079
DWORD dwIDCtl,
4080
LPCWSTR pszLabel)
4081
{
4082
FileDialogImpl *This = impl_from_IFileDialogCustomize(iface);
4083
customctrl *ctrl = get_cctrl(This, dwIDCtl);
4084
TRACE("%p (%ld, %p)\n", This, dwIDCtl, pszLabel);
4085
4086
if(!ctrl) return E_INVALIDARG;
4087
4088
switch(ctrl->type)
4089
{
4090
case IDLG_CCTRL_MENU:
4091
case IDLG_CCTRL_PUSHBUTTON:
4092
case IDLG_CCTRL_CHECKBUTTON:
4093
case IDLG_CCTRL_TEXT:
4094
case IDLG_CCTRL_VISUALGROUP:
4095
SendMessageW(ctrl->hwnd, WM_SETTEXT, 0, (LPARAM)pszLabel);
4096
break;
4097
case IDLG_CCTRL_OPENDROPDOWN:
4098
return E_NOTIMPL;
4099
default:
4100
break;
4101
}
4102
4103
return S_OK;
4104
}
4105
4106
static HRESULT WINAPI IFileDialogCustomize_fnGetControlState(IFileDialogCustomize *iface,
4107
DWORD dwIDCtl,
4108
CDCONTROLSTATEF *pdwState)
4109
{
4110
FileDialogImpl *This = impl_from_IFileDialogCustomize(iface);
4111
customctrl *ctrl = get_cctrl(This, dwIDCtl);
4112
TRACE("%p (%ld, %p)\n", This, dwIDCtl, pdwState);
4113
4114
if(!ctrl || ctrl->type == IDLG_CCTRL_OPENDROPDOWN) return E_NOTIMPL;
4115
4116
*pdwState = ctrl->cdcstate;
4117
return S_OK;
4118
}
4119
4120
static HRESULT WINAPI IFileDialogCustomize_fnSetControlState(IFileDialogCustomize *iface,
4121
DWORD dwIDCtl,
4122
CDCONTROLSTATEF dwState)
4123
{
4124
FileDialogImpl *This = impl_from_IFileDialogCustomize(iface);
4125
customctrl *ctrl = get_cctrl(This,dwIDCtl);
4126
TRACE("%p (%ld, %x)\n", This, dwIDCtl, dwState);
4127
4128
if(ctrl && ctrl->hwnd)
4129
{
4130
LONG wndstyle = GetWindowLongW(ctrl->hwnd, GWL_STYLE);
4131
4132
if(dwState & CDCS_ENABLED)
4133
wndstyle &= ~(WS_DISABLED);
4134
else
4135
wndstyle |= WS_DISABLED;
4136
4137
if(dwState & CDCS_VISIBLE)
4138
wndstyle |= WS_VISIBLE;
4139
else
4140
wndstyle &= ~(WS_VISIBLE);
4141
4142
SetWindowLongW(ctrl->hwnd, GWL_STYLE, wndstyle);
4143
4144
/* We save the state separately since at least one application
4145
* relies on being able to hide a control. */
4146
ctrl->cdcstate = dwState;
4147
}
4148
4149
return S_OK;
4150
}
4151
4152
static HRESULT WINAPI IFileDialogCustomize_fnGetEditBoxText(IFileDialogCustomize *iface,
4153
DWORD dwIDCtl,
4154
WCHAR **ppszText)
4155
{
4156
FileDialogImpl *This = impl_from_IFileDialogCustomize(iface);
4157
customctrl *ctrl = get_cctrl(This, dwIDCtl);
4158
WCHAR len, *text;
4159
TRACE("%p (%ld, %p)\n", This, dwIDCtl, ppszText);
4160
4161
if(!ctrl || !ctrl->hwnd || !(len = SendMessageW(ctrl->hwnd, WM_GETTEXTLENGTH, 0, 0)))
4162
return E_FAIL;
4163
4164
text = CoTaskMemAlloc(sizeof(WCHAR)*(len+1));
4165
if(!text) return E_FAIL;
4166
4167
SendMessageW(ctrl->hwnd, WM_GETTEXT, len+1, (LPARAM)text);
4168
*ppszText = text;
4169
return S_OK;
4170
}
4171
4172
static HRESULT WINAPI IFileDialogCustomize_fnSetEditBoxText(IFileDialogCustomize *iface,
4173
DWORD dwIDCtl,
4174
LPCWSTR pszText)
4175
{
4176
FileDialogImpl *This = impl_from_IFileDialogCustomize(iface);
4177
customctrl *ctrl = get_cctrl(This, dwIDCtl);
4178
TRACE("%p (%ld, %s)\n", This, dwIDCtl, debugstr_w(pszText));
4179
4180
if(!ctrl || ctrl->type != IDLG_CCTRL_EDITBOX)
4181
return E_FAIL;
4182
4183
SendMessageW(ctrl->hwnd, WM_SETTEXT, 0, (LPARAM)pszText);
4184
return S_OK;
4185
}
4186
4187
static HRESULT WINAPI IFileDialogCustomize_fnGetCheckButtonState(IFileDialogCustomize *iface,
4188
DWORD dwIDCtl,
4189
BOOL *pbChecked)
4190
{
4191
FileDialogImpl *This = impl_from_IFileDialogCustomize(iface);
4192
customctrl *ctrl = get_cctrl(This, dwIDCtl);
4193
TRACE("%p (%ld, %p)\n", This, dwIDCtl, pbChecked);
4194
4195
if(ctrl && ctrl->hwnd)
4196
*pbChecked = (SendMessageW(ctrl->hwnd, BM_GETCHECK, 0, 0) == BST_CHECKED);
4197
4198
return S_OK;
4199
}
4200
4201
static HRESULT WINAPI IFileDialogCustomize_fnSetCheckButtonState(IFileDialogCustomize *iface,
4202
DWORD dwIDCtl,
4203
BOOL bChecked)
4204
{
4205
FileDialogImpl *This = impl_from_IFileDialogCustomize(iface);
4206
customctrl *ctrl = get_cctrl(This, dwIDCtl);
4207
TRACE("%p (%ld, %d)\n", This, dwIDCtl, bChecked);
4208
4209
if(ctrl && ctrl->hwnd)
4210
SendMessageW(ctrl->hwnd, BM_SETCHECK, bChecked ? BST_CHECKED:BST_UNCHECKED, 0);
4211
4212
return S_OK;
4213
}
4214
4215
static UINT get_combobox_index_from_id(HWND cb_hwnd, DWORD dwIDItem)
4216
{
4217
UINT count = SendMessageW(cb_hwnd, CB_GETCOUNT, 0, 0);
4218
UINT i;
4219
if(!count || (count == CB_ERR))
4220
return -1;
4221
4222
for(i = 0; i < count; i++)
4223
if(SendMessageW(cb_hwnd, CB_GETITEMDATA, i, 0) == dwIDItem)
4224
return i;
4225
4226
TRACE("Item with id %ld not found in combobox %p (item count: %d)\n", dwIDItem, cb_hwnd, count);
4227
return -1;
4228
}
4229
4230
static HRESULT WINAPI IFileDialogCustomize_fnAddControlItem(IFileDialogCustomize *iface,
4231
DWORD dwIDCtl,
4232
DWORD dwIDItem,
4233
LPCWSTR pszLabel)
4234
{
4235
FileDialogImpl *This = impl_from_IFileDialogCustomize(iface);
4236
customctrl *ctrl = get_cctrl(This, dwIDCtl);
4237
HRESULT hr;
4238
TRACE("%p (%ld, %ld, %s)\n", This, dwIDCtl, dwIDItem, debugstr_w(pszLabel));
4239
4240
if(!ctrl) return E_FAIL;
4241
4242
switch(ctrl->type)
4243
{
4244
case IDLG_CCTRL_COMBOBOX:
4245
{
4246
UINT index;
4247
cctrl_item* item;
4248
4249
hr = add_item(ctrl, dwIDItem, pszLabel, &item);
4250
4251
if (FAILED(hr)) return hr;
4252
4253
index = SendMessageW(ctrl->hwnd, CB_ADDSTRING, 0, (LPARAM)pszLabel);
4254
SendMessageW(ctrl->hwnd, CB_SETITEMDATA, index, dwIDItem);
4255
4256
return S_OK;
4257
}
4258
case IDLG_CCTRL_MENU:
4259
case IDLG_CCTRL_OPENDROPDOWN:
4260
{
4261
cctrl_item* item;
4262
HMENU hmenu;
4263
4264
hr = add_item(ctrl, dwIDItem, pszLabel, &item);
4265
4266
if (FAILED(hr)) return hr;
4267
4268
if (ctrl->type == IDLG_CCTRL_MENU)
4269
{
4270
TBBUTTON tbb;
4271
SendMessageW(ctrl->hwnd, TB_GETBUTTON, 0, (LPARAM)&tbb);
4272
hmenu = (HMENU)tbb.dwData;
4273
}
4274
else /* ctrl->type == IDLG_CCTRL_OPENDROPDOWN */
4275
hmenu = This->hmenu_opendropdown;
4276
4277
AppendMenuW(hmenu, MF_STRING, dwIDItem, pszLabel);
4278
return S_OK;
4279
}
4280
case IDLG_CCTRL_RADIOBUTTONLIST:
4281
{
4282
cctrl_item* item;
4283
4284
hr = add_item(ctrl, dwIDItem, pszLabel, &item);
4285
4286
if (SUCCEEDED(hr))
4287
{
4288
item->hwnd = CreateWindowExW(0, WC_BUTTONW, pszLabel,
4289
WS_CHILD|WS_VISIBLE|WS_CLIPSIBLINGS|BS_RADIOBUTTON|BS_MULTILINE,
4290
0, 0, 0, 0, ctrl->hwnd, ULongToHandle(dwIDItem), COMDLG32_hInstance, 0);
4291
4292
if (!item->hwnd)
4293
{
4294
ERR("Failed to create radio button\n");
4295
list_remove(&item->entry);
4296
item_free(item);
4297
return E_FAIL;
4298
}
4299
}
4300
4301
return hr;
4302
}
4303
default:
4304
break;
4305
}
4306
4307
return E_NOINTERFACE; /* win7 */
4308
}
4309
4310
static HRESULT WINAPI IFileDialogCustomize_fnRemoveControlItem(IFileDialogCustomize *iface,
4311
DWORD dwIDCtl,
4312
DWORD dwIDItem)
4313
{
4314
FileDialogImpl *This = impl_from_IFileDialogCustomize(iface);
4315
customctrl *ctrl = get_cctrl(This, dwIDCtl);
4316
TRACE("%p (%ld, %ld)\n", This, dwIDCtl, dwIDItem);
4317
4318
if(!ctrl) return E_FAIL;
4319
4320
switch(ctrl->type)
4321
{
4322
case IDLG_CCTRL_COMBOBOX:
4323
{
4324
cctrl_item* item;
4325
DWORD position;
4326
4327
item = get_item(ctrl, dwIDItem, CDCS_VISIBLE|CDCS_ENABLED, &position);
4328
4329
if (!item)
4330
return E_INVALIDARG;
4331
4332
if ((item->cdcstate & (CDCS_VISIBLE|CDCS_ENABLED)) == (CDCS_VISIBLE|CDCS_ENABLED))
4333
{
4334
if(SendMessageW(ctrl->hwnd, CB_DELETESTRING, position, 0) == CB_ERR)
4335
return E_FAIL;
4336
}
4337
4338
list_remove(&item->entry);
4339
item_free(item);
4340
4341
return S_OK;
4342
}
4343
case IDLG_CCTRL_MENU:
4344
case IDLG_CCTRL_OPENDROPDOWN:
4345
{
4346
HMENU hmenu;
4347
cctrl_item* item;
4348
4349
item = get_item(ctrl, dwIDItem, 0, NULL);
4350
4351
if (!item)
4352
return E_UNEXPECTED;
4353
4354
if (item->cdcstate & CDCS_VISIBLE)
4355
{
4356
if (ctrl->type == IDLG_CCTRL_MENU)
4357
{
4358
TBBUTTON tbb;
4359
SendMessageW(ctrl->hwnd, TB_GETBUTTON, 0, (LPARAM)&tbb);
4360
hmenu = (HMENU)tbb.dwData;
4361
}
4362
else /* ctrl->type == IDLG_CCTRL_OPENDROPDOWN */
4363
hmenu = This->hmenu_opendropdown;
4364
4365
if(!hmenu || !DeleteMenu(hmenu, dwIDItem, MF_BYCOMMAND))
4366
return E_UNEXPECTED;
4367
}
4368
4369
list_remove(&item->entry);
4370
item_free(item);
4371
4372
return S_OK;
4373
}
4374
case IDLG_CCTRL_RADIOBUTTONLIST:
4375
{
4376
cctrl_item* item;
4377
4378
item = get_item(ctrl, dwIDItem, 0, NULL);
4379
4380
if (!item)
4381
return E_UNEXPECTED;
4382
4383
list_remove(&item->entry);
4384
item_free(item);
4385
4386
return S_OK;
4387
}
4388
default:
4389
break;
4390
}
4391
4392
return E_FAIL;
4393
}
4394
4395
static HRESULT WINAPI IFileDialogCustomize_fnRemoveAllControlItems(IFileDialogCustomize *iface,
4396
DWORD dwIDCtl)
4397
{
4398
FileDialogImpl *This = impl_from_IFileDialogCustomize(iface);
4399
TRACE("%p (%ld)\n", This, dwIDCtl);
4400
4401
/* Not implemented by native */
4402
return E_NOTIMPL;
4403
}
4404
4405
static HRESULT WINAPI IFileDialogCustomize_fnGetControlItemState(IFileDialogCustomize *iface,
4406
DWORD dwIDCtl,
4407
DWORD dwIDItem,
4408
CDCONTROLSTATEF *pdwState)
4409
{
4410
FileDialogImpl *This = impl_from_IFileDialogCustomize(iface);
4411
customctrl *ctrl = get_cctrl(This, dwIDCtl);
4412
TRACE("%p (%ld, %ld, %p)\n", This, dwIDCtl, dwIDItem, pdwState);
4413
4414
if(!ctrl) return E_FAIL;
4415
4416
switch(ctrl->type)
4417
{
4418
case IDLG_CCTRL_COMBOBOX:
4419
case IDLG_CCTRL_MENU:
4420
case IDLG_CCTRL_OPENDROPDOWN:
4421
case IDLG_CCTRL_RADIOBUTTONLIST:
4422
{
4423
cctrl_item* item;
4424
4425
item = get_item(ctrl, dwIDItem, 0, NULL);
4426
4427
if (!item)
4428
return E_UNEXPECTED;
4429
4430
*pdwState = item->cdcstate;
4431
4432
return S_OK;
4433
}
4434
default:
4435
break;
4436
}
4437
4438
return E_FAIL;
4439
}
4440
4441
static HRESULT WINAPI IFileDialogCustomize_fnSetControlItemState(IFileDialogCustomize *iface,
4442
DWORD dwIDCtl,
4443
DWORD dwIDItem,
4444
CDCONTROLSTATEF dwState)
4445
{
4446
FileDialogImpl *This = impl_from_IFileDialogCustomize(iface);
4447
customctrl *ctrl = get_cctrl(This, dwIDCtl);
4448
TRACE("%p (%ld, %ld, %x)\n", This, dwIDCtl, dwIDItem, dwState);
4449
4450
if(!ctrl) return E_FAIL;
4451
4452
switch(ctrl->type)
4453
{
4454
case IDLG_CCTRL_COMBOBOX:
4455
{
4456
cctrl_item* item;
4457
BOOL visible, was_visible;
4458
DWORD position;
4459
4460
item = get_item(ctrl, dwIDItem, CDCS_VISIBLE|CDCS_ENABLED, &position);
4461
4462
if (!item)
4463
return E_UNEXPECTED;
4464
4465
visible = ((dwState & (CDCS_VISIBLE|CDCS_ENABLED)) == (CDCS_VISIBLE|CDCS_ENABLED));
4466
was_visible = ((item->cdcstate & (CDCS_VISIBLE|CDCS_ENABLED)) == (CDCS_VISIBLE|CDCS_ENABLED));
4467
4468
if (visible && !was_visible)
4469
{
4470
SendMessageW(ctrl->hwnd, CB_INSERTSTRING, position, (LPARAM)item->label);
4471
SendMessageW(ctrl->hwnd, CB_SETITEMDATA, position, dwIDItem);
4472
}
4473
else if (!visible && was_visible)
4474
{
4475
SendMessageW(ctrl->hwnd, CB_DELETESTRING, position, 0);
4476
}
4477
4478
item->cdcstate = dwState;
4479
4480
return S_OK;
4481
}
4482
case IDLG_CCTRL_MENU:
4483
case IDLG_CCTRL_OPENDROPDOWN:
4484
{
4485
HMENU hmenu;
4486
cctrl_item* item;
4487
CDCONTROLSTATEF prev_state;
4488
DWORD position;
4489
4490
item = get_item(ctrl, dwIDItem, CDCS_VISIBLE, &position);
4491
4492
if (!item)
4493
return E_UNEXPECTED;
4494
4495
prev_state = item->cdcstate;
4496
4497
if (ctrl->type == IDLG_CCTRL_MENU)
4498
{
4499
TBBUTTON tbb;
4500
SendMessageW(ctrl->hwnd, TB_GETBUTTON, 0, (LPARAM)&tbb);
4501
hmenu = (HMENU)tbb.dwData;
4502
}
4503
else /* ctrl->type == IDLG_CCTRL_OPENDROPDOWN */
4504
hmenu = This->hmenu_opendropdown;
4505
4506
if (dwState & CDCS_VISIBLE)
4507
{
4508
if (prev_state & CDCS_VISIBLE)
4509
{
4510
/* change state */
4511
EnableMenuItem(hmenu, dwIDItem,
4512
MF_BYCOMMAND|((dwState & CDCS_ENABLED) ? MFS_ENABLED : MFS_DISABLED));
4513
}
4514
else
4515
{
4516
/* show item */
4517
MENUITEMINFOW mii;
4518
4519
mii.cbSize = sizeof(mii);
4520
mii.fMask = MIIM_ID|MIIM_STATE|MIIM_STRING;
4521
mii.fState = (dwState & CDCS_ENABLED) ? MFS_ENABLED : MFS_DISABLED;
4522
mii.wID = dwIDItem;
4523
mii.dwTypeData = item->label;
4524
4525
InsertMenuItemW(hmenu, position, TRUE, &mii);
4526
}
4527
}
4528
else if (prev_state & CDCS_VISIBLE)
4529
{
4530
/* hide item */
4531
DeleteMenu(hmenu, dwIDItem, MF_BYCOMMAND);
4532
}
4533
4534
item->cdcstate = dwState;
4535
4536
if (ctrl->type == IDLG_CCTRL_OPENDROPDOWN)
4537
{
4538
update_control_text(This);
4539
update_layout(This);
4540
}
4541
4542
return S_OK;
4543
}
4544
case IDLG_CCTRL_RADIOBUTTONLIST:
4545
{
4546
cctrl_item* item;
4547
4548
item = get_item(ctrl, dwIDItem, CDCS_VISIBLE, NULL);
4549
4550
if (!item)
4551
return E_UNEXPECTED;
4552
4553
/* Oddly, native allows setting this but doesn't seem to do anything with it. */
4554
item->cdcstate = dwState;
4555
4556
return S_OK;
4557
}
4558
default:
4559
break;
4560
}
4561
4562
return E_FAIL;
4563
}
4564
4565
static HRESULT WINAPI IFileDialogCustomize_fnGetSelectedControlItem(IFileDialogCustomize *iface,
4566
DWORD dwIDCtl,
4567
DWORD *pdwIDItem)
4568
{
4569
FileDialogImpl *This = impl_from_IFileDialogCustomize(iface);
4570
customctrl *ctrl = get_cctrl(This, dwIDCtl);
4571
TRACE("%p (%ld, %p)\n", This, dwIDCtl, pdwIDItem);
4572
4573
if(!ctrl) return E_FAIL;
4574
4575
switch(ctrl->type)
4576
{
4577
case IDLG_CCTRL_COMBOBOX:
4578
{
4579
UINT index = SendMessageW(ctrl->hwnd, CB_GETCURSEL, 0, 0);
4580
if(index == CB_ERR)
4581
return E_FAIL;
4582
4583
*pdwIDItem = SendMessageW(ctrl->hwnd, CB_GETITEMDATA, index, 0);
4584
return S_OK;
4585
}
4586
case IDLG_CCTRL_OPENDROPDOWN:
4587
if (This->opendropdown_has_selection)
4588
{
4589
*pdwIDItem = This->opendropdown_selection;
4590
return S_OK;
4591
}
4592
else
4593
{
4594
/* Return first enabled item. */
4595
cctrl_item* item = get_first_item(ctrl);
4596
4597
if (item)
4598
{
4599
*pdwIDItem = item->id;
4600
return S_OK;
4601
}
4602
4603
WARN("no enabled items in open dropdown\n");
4604
return E_FAIL;
4605
}
4606
case IDLG_CCTRL_RADIOBUTTONLIST:
4607
{
4608
cctrl_item* item;
4609
4610
LIST_FOR_EACH_ENTRY(item, &ctrl->sub_items, cctrl_item, entry)
4611
{
4612
if (SendMessageW(item->hwnd, BM_GETCHECK, 0, 0) == BST_CHECKED)
4613
{
4614
*pdwIDItem = item->id;
4615
return S_OK;
4616
}
4617
}
4618
4619
WARN("no checked items in radio button list\n");
4620
return E_FAIL;
4621
}
4622
default:
4623
FIXME("Unsupported control type %d\n", ctrl->type);
4624
}
4625
4626
return E_NOTIMPL;
4627
}
4628
4629
static HRESULT WINAPI IFileDialogCustomize_fnSetSelectedControlItem(IFileDialogCustomize *iface,
4630
DWORD dwIDCtl,
4631
DWORD dwIDItem)
4632
{
4633
FileDialogImpl *This = impl_from_IFileDialogCustomize(iface);
4634
customctrl *ctrl = get_cctrl(This, dwIDCtl);
4635
TRACE("%p (%ld, %ld)\n", This, dwIDCtl, dwIDItem);
4636
4637
if(!ctrl) return E_INVALIDARG;
4638
4639
switch(ctrl->type)
4640
{
4641
case IDLG_CCTRL_COMBOBOX:
4642
{
4643
UINT index = get_combobox_index_from_id(ctrl->hwnd, dwIDItem);
4644
4645
if(index == -1)
4646
return E_INVALIDARG;
4647
4648
if(SendMessageW(ctrl->hwnd, CB_SETCURSEL, index, 0) == CB_ERR)
4649
return E_FAIL;
4650
4651
return S_OK;
4652
}
4653
case IDLG_CCTRL_RADIOBUTTONLIST:
4654
{
4655
cctrl_item* item;
4656
4657
item = get_item(ctrl, dwIDItem, 0, NULL);
4658
4659
if (item)
4660
{
4661
radiobuttonlist_set_selected_item(This, ctrl, item);
4662
return S_OK;
4663
}
4664
4665
return E_INVALIDARG;
4666
}
4667
default:
4668
FIXME("Unsupported control type %d\n", ctrl->type);
4669
}
4670
4671
return E_INVALIDARG;
4672
}
4673
4674
static HRESULT WINAPI IFileDialogCustomize_fnStartVisualGroup(IFileDialogCustomize *iface,
4675
DWORD dwIDCtl,
4676
LPCWSTR pszLabel)
4677
{
4678
FileDialogImpl *This = impl_from_IFileDialogCustomize(iface);
4679
customctrl *vg;
4680
HRESULT hr;
4681
TRACE("%p (%ld, %s)\n", This, dwIDCtl, debugstr_w(pszLabel));
4682
4683
if(This->cctrl_active_vg)
4684
return E_UNEXPECTED;
4685
4686
hr = cctrl_create_new(This, dwIDCtl, pszLabel, WC_STATICW, 0, 0,
4687
This->cctrl_def_height, &vg);
4688
if(SUCCEEDED(hr))
4689
{
4690
vg->type = IDLG_CCTRL_VISUALGROUP;
4691
This->cctrl_active_vg = vg;
4692
}
4693
4694
return hr;
4695
}
4696
4697
static HRESULT WINAPI IFileDialogCustomize_fnEndVisualGroup(IFileDialogCustomize *iface)
4698
{
4699
FileDialogImpl *This = impl_from_IFileDialogCustomize(iface);
4700
TRACE("%p\n", This);
4701
4702
This->cctrl_active_vg = NULL;
4703
4704
return S_OK;
4705
}
4706
4707
static HRESULT WINAPI IFileDialogCustomize_fnMakeProminent(IFileDialogCustomize *iface,
4708
DWORD dwIDCtl)
4709
{
4710
FileDialogImpl *This = impl_from_IFileDialogCustomize(iface);
4711
FIXME("stub - %p (%ld)\n", This, dwIDCtl);
4712
return S_OK;
4713
}
4714
4715
static HRESULT WINAPI IFileDialogCustomize_fnSetControlItemText(IFileDialogCustomize *iface,
4716
DWORD dwIDCtl,
4717
DWORD dwIDItem,
4718
LPCWSTR pszLabel)
4719
{
4720
FileDialogImpl *This = impl_from_IFileDialogCustomize(iface);
4721
FIXME("stub - %p (%ld, %ld, %s)\n", This, dwIDCtl, dwIDItem, debugstr_w(pszLabel));
4722
return E_NOTIMPL;
4723
}
4724
4725
static const IFileDialogCustomizeVtbl vt_IFileDialogCustomize = {
4726
IFileDialogCustomize_fnQueryInterface,
4727
IFileDialogCustomize_fnAddRef,
4728
IFileDialogCustomize_fnRelease,
4729
IFileDialogCustomize_fnEnableOpenDropDown,
4730
IFileDialogCustomize_fnAddMenu,
4731
IFileDialogCustomize_fnAddPushButton,
4732
IFileDialogCustomize_fnAddComboBox,
4733
IFileDialogCustomize_fnAddRadioButtonList,
4734
IFileDialogCustomize_fnAddCheckButton,
4735
IFileDialogCustomize_fnAddEditBox,
4736
IFileDialogCustomize_fnAddSeparator,
4737
IFileDialogCustomize_fnAddText,
4738
IFileDialogCustomize_fnSetControlLabel,
4739
IFileDialogCustomize_fnGetControlState,
4740
IFileDialogCustomize_fnSetControlState,
4741
IFileDialogCustomize_fnGetEditBoxText,
4742
IFileDialogCustomize_fnSetEditBoxText,
4743
IFileDialogCustomize_fnGetCheckButtonState,
4744
IFileDialogCustomize_fnSetCheckButtonState,
4745
IFileDialogCustomize_fnAddControlItem,
4746
IFileDialogCustomize_fnRemoveControlItem,
4747
IFileDialogCustomize_fnRemoveAllControlItems,
4748
IFileDialogCustomize_fnGetControlItemState,
4749
IFileDialogCustomize_fnSetControlItemState,
4750
IFileDialogCustomize_fnGetSelectedControlItem,
4751
IFileDialogCustomize_fnSetSelectedControlItem,
4752
IFileDialogCustomize_fnStartVisualGroup,
4753
IFileDialogCustomize_fnEndVisualGroup,
4754
IFileDialogCustomize_fnMakeProminent,
4755
IFileDialogCustomize_fnSetControlItemText
4756
};
4757
4758
static HRESULT FileDialog_constructor(IUnknown *pUnkOuter, REFIID riid, void **ppv, enum ITEMDLG_TYPE type)
4759
{
4760
FileDialogImpl *fdimpl;
4761
HRESULT hr;
4762
IShellFolder *psf;
4763
TRACE("%p, %s, %p\n", pUnkOuter, debugstr_guid(riid), ppv);
4764
4765
if(!ppv)
4766
return E_POINTER;
4767
if(pUnkOuter)
4768
return CLASS_E_NOAGGREGATION;
4769
4770
fdimpl = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(FileDialogImpl));
4771
if(!fdimpl)
4772
return E_OUTOFMEMORY;
4773
4774
fdimpl->ref = 1;
4775
fdimpl->IFileDialog2_iface.lpVtbl = &vt_IFileDialog2;
4776
fdimpl->IExplorerBrowserEvents_iface.lpVtbl = &vt_IExplorerBrowserEvents;
4777
fdimpl->IServiceProvider_iface.lpVtbl = &vt_IServiceProvider;
4778
fdimpl->ICommDlgBrowser3_iface.lpVtbl = &vt_ICommDlgBrowser3;
4779
fdimpl->IOleWindow_iface.lpVtbl = &vt_IOleWindow;
4780
fdimpl->IFileDialogCustomize_iface.lpVtbl = &vt_IFileDialogCustomize;
4781
4782
if(type == ITEMDLG_TYPE_OPEN)
4783
{
4784
fdimpl->dlg_type = ITEMDLG_TYPE_OPEN;
4785
fdimpl->u.IFileOpenDialog_iface.lpVtbl = &vt_IFileOpenDialog;
4786
fdimpl->options = FOS_PATHMUSTEXIST | FOS_FILEMUSTEXIST | FOS_NOCHANGEDIR;
4787
fdimpl->custom_title = fdimpl->custom_okbutton = NULL;
4788
}
4789
else
4790
{
4791
WCHAR buf[16];
4792
fdimpl->dlg_type = ITEMDLG_TYPE_SAVE;
4793
fdimpl->u.IFileSaveDialog_iface.lpVtbl = &vt_IFileSaveDialog;
4794
fdimpl->options = FOS_OVERWRITEPROMPT | FOS_NOREADONLYRETURN | FOS_PATHMUSTEXIST | FOS_NOCHANGEDIR;
4795
4796
LoadStringW(COMDLG32_hInstance, IDS_SAVE, buf, ARRAY_SIZE(buf));
4797
fdimpl->custom_title = StrDupW(buf);
4798
fdimpl->custom_okbutton = StrDupW(buf);
4799
}
4800
4801
list_init(&fdimpl->events_clients);
4802
4803
/* FIXME: The default folder setting should be restored for the
4804
* application if it was previously set. */
4805
SHGetDesktopFolder(&psf);
4806
SHGetItemFromObject((IUnknown*)psf, &IID_IShellItem, (void**)&fdimpl->psi_defaultfolder);
4807
IShellFolder_Release(psf);
4808
4809
hr = init_custom_controls(fdimpl);
4810
if(FAILED(hr))
4811
{
4812
ERR("Failed to initialize custom controls (0x%08lx).\n", hr);
4813
IFileDialog2_Release(&fdimpl->IFileDialog2_iface);
4814
return E_FAIL;
4815
}
4816
4817
fdimpl->user_actctx = INVALID_HANDLE_VALUE;
4818
4819
hr = IFileDialog2_QueryInterface(&fdimpl->IFileDialog2_iface, riid, ppv);
4820
IFileDialog2_Release(&fdimpl->IFileDialog2_iface);
4821
return hr;
4822
}
4823
4824
HRESULT FileOpenDialog_Constructor(IUnknown *pUnkOuter, REFIID riid, void **ppv)
4825
{
4826
return FileDialog_constructor(pUnkOuter, riid, ppv, ITEMDLG_TYPE_OPEN);
4827
}
4828
4829
HRESULT FileSaveDialog_Constructor(IUnknown *pUnkOuter, REFIID riid, void **ppv)
4830
{
4831
return FileDialog_constructor(pUnkOuter, riid, ppv, ITEMDLG_TYPE_SAVE);
4832
}
4833
4834