Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
wine-mirror
GitHub Repository: wine-mirror/wine
Path: blob/master/dlls/comdlg32/itemdlg.c
8841 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 = malloc(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 = malloc(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
free(string);
552
}
553
554
free(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
free(files);
626
return hr;
627
}
628
629
TRACE("Acting on %d file(s).\n", file_count);
630
631
pidla = malloc(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
free(files);
798
ILFree(current_folder);
799
for(i = 0; i < file_count; i++)
800
ILFree(pidla[i]);
801
free(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
free(item->label);
844
free(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 = malloc(sizeof(*item));
890
label_copy = malloc((lstrlenW(label)+1)*sizeof(WCHAR));
891
892
if (!item || !label_copy)
893
{
894
free(item);
895
free(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 = malloc(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
free(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
free(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 = calloc(1, 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, SW_SHOW);
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, SW_HIDE);
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_IModalWindow) ||
2424
IsEqualGUID(riid, &IID_IFileDialog) ||
2425
IsEqualGUID(riid, &IID_IFileDialog2))
2426
{
2427
*ppvObject = iface;
2428
}
2429
else if(IsEqualGUID(riid, &IID_IFileOpenDialog) && This->dlg_type == ITEMDLG_TYPE_OPEN)
2430
{
2431
*ppvObject = &This->u.IFileOpenDialog_iface;
2432
}
2433
else if(IsEqualGUID(riid, &IID_IFileSaveDialog) && This->dlg_type == ITEMDLG_TYPE_SAVE)
2434
{
2435
*ppvObject = &This->u.IFileSaveDialog_iface;
2436
}
2437
else if(IsEqualGUID(riid, &IID_IExplorerBrowserEvents))
2438
{
2439
*ppvObject = &This->IExplorerBrowserEvents_iface;
2440
}
2441
else if(IsEqualGUID(riid, &IID_IServiceProvider))
2442
{
2443
*ppvObject = &This->IServiceProvider_iface;
2444
}
2445
else if(IsEqualGUID(&IID_ICommDlgBrowser3, riid) ||
2446
IsEqualGUID(&IID_ICommDlgBrowser2, riid) ||
2447
IsEqualGUID(&IID_ICommDlgBrowser, riid))
2448
{
2449
*ppvObject = &This->ICommDlgBrowser3_iface;
2450
}
2451
else if(IsEqualGUID(&IID_IOleWindow, riid))
2452
{
2453
*ppvObject = &This->IOleWindow_iface;
2454
}
2455
else if(IsEqualGUID(riid, &IID_IFileDialogCustomize) ||
2456
IsEqualGUID(riid, &IID_IFileDialogCustomizeAlt))
2457
{
2458
*ppvObject = &This->IFileDialogCustomize_iface;
2459
}
2460
else
2461
FIXME("Unknown interface requested: %s.\n", debugstr_guid(riid));
2462
2463
if(*ppvObject)
2464
{
2465
IUnknown_AddRef((IUnknown*)*ppvObject);
2466
return S_OK;
2467
}
2468
2469
return E_NOINTERFACE;
2470
}
2471
2472
static ULONG WINAPI IFileDialog2_fnAddRef(IFileDialog2 *iface)
2473
{
2474
FileDialogImpl *This = impl_from_IFileDialog2(iface);
2475
LONG ref = InterlockedIncrement(&This->ref);
2476
TRACE("%p - ref %ld\n", This, ref);
2477
2478
return ref;
2479
}
2480
2481
static ULONG WINAPI IFileDialog2_fnRelease(IFileDialog2 *iface)
2482
{
2483
FileDialogImpl *This = impl_from_IFileDialog2(iface);
2484
LONG ref = InterlockedDecrement(&This->ref);
2485
TRACE("%p - ref %ld\n", This, ref);
2486
2487
if(!ref)
2488
{
2489
UINT i;
2490
for(i = 0; i < This->filterspec_count; i++)
2491
{
2492
LocalFree((void*)This->filterspecs[i].pszName);
2493
LocalFree((void*)This->filterspecs[i].pszSpec);
2494
}
2495
free(This->filterspecs);
2496
2497
DestroyWindow(This->cctrls_hwnd);
2498
2499
if(This->psi_defaultfolder) IShellItem_Release(This->psi_defaultfolder);
2500
if(This->psi_setfolder) IShellItem_Release(This->psi_setfolder);
2501
if(This->psi_folder) IShellItem_Release(This->psi_folder);
2502
if(This->psia_selection) IShellItemArray_Release(This->psia_selection);
2503
if(This->psia_results) IShellItemArray_Release(This->psia_results);
2504
2505
LocalFree(This->set_filename);
2506
LocalFree(This->default_ext);
2507
LocalFree(This->custom_title);
2508
LocalFree(This->custom_okbutton);
2509
LocalFree(This->custom_cancelbutton);
2510
LocalFree(This->custom_filenamelabel);
2511
LocalFree(This->current_filter);
2512
2513
DestroyMenu(This->hmenu_opendropdown);
2514
DeleteObject(This->hfont_opendropdown);
2515
2516
free(This);
2517
}
2518
2519
return ref;
2520
}
2521
2522
static HRESULT WINAPI IFileDialog2_fnShow(IFileDialog2 *iface, HWND hwndOwner)
2523
{
2524
FileDialogImpl *This = impl_from_IFileDialog2(iface);
2525
TRACE("%p (%p)\n", iface, hwndOwner);
2526
2527
This->opendropdown_has_selection = FALSE;
2528
2529
return create_dialog(This, hwndOwner);
2530
}
2531
2532
static HRESULT WINAPI IFileDialog2_fnSetFileTypes(IFileDialog2 *iface, UINT cFileTypes,
2533
const COMDLG_FILTERSPEC *rgFilterSpec)
2534
{
2535
FileDialogImpl *This = impl_from_IFileDialog2(iface);
2536
UINT i;
2537
TRACE("%p (%d, %p)\n", This, cFileTypes, rgFilterSpec);
2538
2539
if(!rgFilterSpec)
2540
return E_INVALIDARG;
2541
2542
if(This->filterspecs)
2543
return E_UNEXPECTED;
2544
2545
if(!cFileTypes)
2546
return S_OK;
2547
2548
This->filterspecs = malloc(sizeof(COMDLG_FILTERSPEC)*cFileTypes);
2549
for(i = 0; i < cFileTypes; i++)
2550
{
2551
This->filterspecs[i].pszName = StrDupW(rgFilterSpec[i].pszName);
2552
This->filterspecs[i].pszSpec = StrDupW(rgFilterSpec[i].pszSpec);
2553
2554
if (This->filterspecs[i].pszName != NULL && This->filterspecs[i].pszSpec != NULL)
2555
{
2556
DWORD name_len = lstrlenW(This->filterspecs[i].pszName);
2557
2558
if (name_len == 0 || This->filterspecs[i].pszName[name_len - 1] != L')')
2559
{
2560
DWORD spec_len = lstrlenW(This->filterspecs[i].pszSpec);
2561
2562
DWORD total_len = name_len + spec_len + 4;
2563
2564
WCHAR* pszName = LocalAlloc(LMEM_FIXED, total_len * sizeof(WCHAR));
2565
if (pszName != NULL)
2566
{
2567
swprintf(pszName, total_len, L"%s (%s)", This->filterspecs[i].pszName, This->filterspecs[i].pszSpec);
2568
LocalFree((void *)This->filterspecs[i].pszName);
2569
This->filterspecs[i].pszName = pszName;
2570
}
2571
}
2572
}
2573
}
2574
This->filterspec_count = cFileTypes;
2575
2576
set_current_filter(This, This->filterspecs[This->filetypeindex].pszSpec);
2577
2578
return S_OK;
2579
}
2580
2581
static HRESULT WINAPI IFileDialog2_fnSetFileTypeIndex(IFileDialog2 *iface, UINT iFileType)
2582
{
2583
FileDialogImpl *This = impl_from_IFileDialog2(iface);
2584
TRACE("%p (%d)\n", This, iFileType);
2585
2586
if(!This->filterspecs)
2587
return E_FAIL;
2588
2589
iFileType = max(iFileType, 1);
2590
iFileType = min(iFileType, This->filterspec_count);
2591
This->filetypeindex = iFileType-1;
2592
2593
set_current_filter(This, This->filterspecs[This->filetypeindex].pszSpec);
2594
2595
return S_OK;
2596
}
2597
2598
static HRESULT WINAPI IFileDialog2_fnGetFileTypeIndex(IFileDialog2 *iface, UINT *piFileType)
2599
{
2600
FileDialogImpl *This = impl_from_IFileDialog2(iface);
2601
TRACE("%p (%p)\n", This, piFileType);
2602
2603
if(!piFileType)
2604
return E_INVALIDARG;
2605
2606
if(This->filterspec_count == 0)
2607
*piFileType = 0;
2608
else
2609
*piFileType = This->filetypeindex + 1;
2610
2611
return S_OK;
2612
}
2613
2614
static HRESULT WINAPI IFileDialog2_fnAdvise(IFileDialog2 *iface, IFileDialogEvents *pfde, DWORD *pdwCookie)
2615
{
2616
FileDialogImpl *This = impl_from_IFileDialog2(iface);
2617
events_client *client;
2618
TRACE("%p (%p, %p)\n", This, pfde, pdwCookie);
2619
2620
if(!pfde || !pdwCookie)
2621
return E_INVALIDARG;
2622
2623
client = malloc(sizeof(events_client));
2624
client->pfde = pfde;
2625
client->cookie = ++This->events_next_cookie;
2626
2627
IFileDialogEvents_AddRef(pfde);
2628
*pdwCookie = client->cookie;
2629
2630
list_add_tail(&This->events_clients, &client->entry);
2631
2632
return S_OK;
2633
}
2634
2635
static HRESULT WINAPI IFileDialog2_fnUnadvise(IFileDialog2 *iface, DWORD dwCookie)
2636
{
2637
FileDialogImpl *This = impl_from_IFileDialog2(iface);
2638
events_client *client, *found = NULL;
2639
TRACE("%p (%ld)\n", This, dwCookie);
2640
2641
LIST_FOR_EACH_ENTRY(client, &This->events_clients, events_client, entry)
2642
{
2643
if(client->cookie == dwCookie)
2644
{
2645
found = client;
2646
break;
2647
}
2648
}
2649
2650
if(found)
2651
{
2652
list_remove(&found->entry);
2653
IFileDialogEvents_Release(found->pfde);
2654
free(found);
2655
return S_OK;
2656
}
2657
2658
return E_INVALIDARG;
2659
}
2660
2661
static HRESULT WINAPI IFileDialog2_fnSetOptions(IFileDialog2 *iface, FILEOPENDIALOGOPTIONS fos)
2662
{
2663
FileDialogImpl *This = impl_from_IFileDialog2(iface);
2664
TRACE("%p (0x%lx)\n", This, fos);
2665
2666
if (fos & ~(FOS_OVERWRITEPROMPT | FOS_STRICTFILETYPES | FOS_NOCHANGEDIR | FOS_PICKFOLDERS | FOS_FORCEFILESYSTEM
2667
| FOS_ALLNONSTORAGEITEMS | FOS_NOVALIDATE | FOS_ALLOWMULTISELECT | FOS_PATHMUSTEXIST | FOS_FILEMUSTEXIST
2668
| FOS_CREATEPROMPT | FOS_SHAREAWARE | FOS_NOREADONLYRETURN | FOS_NOTESTFILECREATE | FOS_HIDEMRUPLACES
2669
| FOS_HIDEPINNEDPLACES | FOS_NODEREFERENCELINKS | FOS_DONTADDTORECENT | FOS_FORCESHOWHIDDEN
2670
| FOS_DEFAULTNOMINIMODE | FOS_FORCEPREVIEWPANEON | FOS_SUPPORTSTREAMABLEITEMS))
2671
{
2672
WARN("Invalid option %#lx\n", fos);
2673
return E_INVALIDARG;
2674
}
2675
2676
if( !(This->options & FOS_PICKFOLDERS) && (fos & FOS_PICKFOLDERS) )
2677
{
2678
WCHAR buf[30];
2679
LoadStringW(COMDLG32_hInstance, IDS_SELECT_FOLDER, buf, ARRAY_SIZE(buf));
2680
IFileDialog2_SetTitle(iface, buf);
2681
}
2682
2683
This->options = fos;
2684
2685
return S_OK;
2686
}
2687
2688
static HRESULT WINAPI IFileDialog2_fnGetOptions(IFileDialog2 *iface, FILEOPENDIALOGOPTIONS *pfos)
2689
{
2690
FileDialogImpl *This = impl_from_IFileDialog2(iface);
2691
TRACE("%p (%p)\n", This, pfos);
2692
2693
if(!pfos)
2694
return E_INVALIDARG;
2695
2696
*pfos = This->options;
2697
2698
return S_OK;
2699
}
2700
2701
static HRESULT WINAPI IFileDialog2_fnSetDefaultFolder(IFileDialog2 *iface, IShellItem *psi)
2702
{
2703
FileDialogImpl *This = impl_from_IFileDialog2(iface);
2704
TRACE("%p (%p)\n", This, psi);
2705
if(This->psi_defaultfolder)
2706
IShellItem_Release(This->psi_defaultfolder);
2707
2708
This->psi_defaultfolder = psi;
2709
2710
if(This->psi_defaultfolder)
2711
IShellItem_AddRef(This->psi_defaultfolder);
2712
2713
return S_OK;
2714
}
2715
2716
static HRESULT WINAPI IFileDialog2_fnSetFolder(IFileDialog2 *iface, IShellItem *psi)
2717
{
2718
FileDialogImpl *This = impl_from_IFileDialog2(iface);
2719
TRACE("%p (%p)\n", This, psi);
2720
if(This->psi_setfolder)
2721
IShellItem_Release(This->psi_setfolder);
2722
2723
This->psi_setfolder = psi;
2724
2725
if(This->psi_setfolder)
2726
IShellItem_AddRef(This->psi_setfolder);
2727
2728
return S_OK;
2729
}
2730
2731
static HRESULT WINAPI IFileDialog2_fnGetFolder(IFileDialog2 *iface, IShellItem **ppsi)
2732
{
2733
FileDialogImpl *This = impl_from_IFileDialog2(iface);
2734
TRACE("%p (%p)\n", This, ppsi);
2735
if(!ppsi)
2736
return E_INVALIDARG;
2737
2738
/* FIXME:
2739
If the dialog is shown, return the current(ly selected) folder. */
2740
2741
*ppsi = NULL;
2742
if(This->psi_folder)
2743
*ppsi = This->psi_folder;
2744
else if(This->psi_setfolder)
2745
*ppsi = This->psi_setfolder;
2746
else if(This->psi_defaultfolder)
2747
*ppsi = This->psi_defaultfolder;
2748
2749
if(*ppsi)
2750
{
2751
IShellItem_AddRef(*ppsi);
2752
return S_OK;
2753
}
2754
2755
return E_FAIL;
2756
}
2757
2758
static HRESULT WINAPI IFileDialog2_fnGetCurrentSelection(IFileDialog2 *iface, IShellItem **ppsi)
2759
{
2760
FileDialogImpl *This = impl_from_IFileDialog2(iface);
2761
HRESULT hr;
2762
TRACE("%p (%p)\n", This, ppsi);
2763
2764
if(!ppsi)
2765
return E_INVALIDARG;
2766
2767
if(This->psia_selection)
2768
{
2769
/* FIXME: Check filename edit box */
2770
hr = IShellItemArray_GetItemAt(This->psia_selection, 0, ppsi);
2771
return hr;
2772
}
2773
2774
return E_FAIL;
2775
}
2776
2777
static HRESULT WINAPI IFileDialog2_fnSetFileName(IFileDialog2 *iface, LPCWSTR pszName)
2778
{
2779
FileDialogImpl *This = impl_from_IFileDialog2(iface);
2780
TRACE("%p (%s)\n", iface, debugstr_w(pszName));
2781
2782
set_file_name(This, pszName);
2783
2784
return S_OK;
2785
}
2786
2787
static HRESULT WINAPI IFileDialog2_fnGetFileName(IFileDialog2 *iface, LPWSTR *pszName)
2788
{
2789
FileDialogImpl *This = impl_from_IFileDialog2(iface);
2790
TRACE("%p (%p)\n", iface, pszName);
2791
2792
if(!pszName)
2793
return E_INVALIDARG;
2794
2795
*pszName = NULL;
2796
get_file_name(This, pszName);
2797
return *pszName ? S_OK : E_FAIL;
2798
}
2799
2800
static HRESULT WINAPI IFileDialog2_fnSetTitle(IFileDialog2 *iface, LPCWSTR pszTitle)
2801
{
2802
FileDialogImpl *This = impl_from_IFileDialog2(iface);
2803
TRACE("%p (%s)\n", This, debugstr_w(pszTitle));
2804
2805
LocalFree(This->custom_title);
2806
This->custom_title = StrDupW(pszTitle);
2807
update_control_text(This);
2808
2809
return S_OK;
2810
}
2811
2812
static HRESULT WINAPI IFileDialog2_fnSetOkButtonLabel(IFileDialog2 *iface, LPCWSTR pszText)
2813
{
2814
FileDialogImpl *This = impl_from_IFileDialog2(iface);
2815
TRACE("%p (%s)\n", This, debugstr_w(pszText));
2816
2817
LocalFree(This->custom_okbutton);
2818
This->custom_okbutton = StrDupW(pszText);
2819
update_control_text(This);
2820
update_layout(This);
2821
2822
return S_OK;
2823
}
2824
2825
static HRESULT WINAPI IFileDialog2_fnSetFileNameLabel(IFileDialog2 *iface, LPCWSTR pszLabel)
2826
{
2827
FileDialogImpl *This = impl_from_IFileDialog2(iface);
2828
TRACE("%p (%s)\n", This, debugstr_w(pszLabel));
2829
2830
LocalFree(This->custom_filenamelabel);
2831
This->custom_filenamelabel = StrDupW(pszLabel);
2832
update_control_text(This);
2833
update_layout(This);
2834
2835
return S_OK;
2836
}
2837
2838
static HRESULT WINAPI IFileDialog2_fnGetResult(IFileDialog2 *iface, IShellItem **ppsi)
2839
{
2840
FileDialogImpl *This = impl_from_IFileDialog2(iface);
2841
HRESULT hr;
2842
TRACE("%p (%p)\n", This, ppsi);
2843
2844
if(!ppsi)
2845
return E_INVALIDARG;
2846
2847
if(This->psia_results)
2848
{
2849
DWORD item_count;
2850
hr = IShellItemArray_GetCount(This->psia_results, &item_count);
2851
if(SUCCEEDED(hr))
2852
{
2853
if(item_count != 1)
2854
return E_FAIL;
2855
2856
/* Adds a reference. */
2857
hr = IShellItemArray_GetItemAt(This->psia_results, 0, ppsi);
2858
}
2859
2860
return hr;
2861
}
2862
2863
return E_UNEXPECTED;
2864
}
2865
2866
static HRESULT WINAPI IFileDialog2_fnAddPlace(IFileDialog2 *iface, IShellItem *psi, FDAP fdap)
2867
{
2868
FileDialogImpl *This = impl_from_IFileDialog2(iface);
2869
FIXME("stub - %p (%p, %d)\n", This, psi, fdap);
2870
return S_OK;
2871
}
2872
2873
static HRESULT WINAPI IFileDialog2_fnSetDefaultExtension(IFileDialog2 *iface, LPCWSTR pszDefaultExtension)
2874
{
2875
FileDialogImpl *This = impl_from_IFileDialog2(iface);
2876
TRACE("%p (%s)\n", This, debugstr_w(pszDefaultExtension));
2877
2878
LocalFree(This->default_ext);
2879
This->default_ext = StrDupW(pszDefaultExtension);
2880
2881
return S_OK;
2882
}
2883
2884
static HRESULT WINAPI IFileDialog2_fnClose(IFileDialog2 *iface, HRESULT hr)
2885
{
2886
FileDialogImpl *This = impl_from_IFileDialog2(iface);
2887
TRACE("%p (0x%08lx)\n", This, hr);
2888
2889
if(This->dlg_hwnd)
2890
EndDialog(This->dlg_hwnd, hr);
2891
2892
return S_OK;
2893
}
2894
2895
static HRESULT WINAPI IFileDialog2_fnSetClientGuid(IFileDialog2 *iface, REFGUID guid)
2896
{
2897
FileDialogImpl *This = impl_from_IFileDialog2(iface);
2898
TRACE("%p (%s)\n", This, debugstr_guid(guid));
2899
This->client_guid = *guid;
2900
return S_OK;
2901
}
2902
2903
static HRESULT WINAPI IFileDialog2_fnClearClientData(IFileDialog2 *iface)
2904
{
2905
FileDialogImpl *This = impl_from_IFileDialog2(iface);
2906
FIXME("stub - %p\n", This);
2907
return E_NOTIMPL;
2908
}
2909
2910
static HRESULT WINAPI IFileDialog2_fnSetFilter(IFileDialog2 *iface, IShellItemFilter *pFilter)
2911
{
2912
FileDialogImpl *This = impl_from_IFileDialog2(iface);
2913
FIXME("stub - %p (%p)\n", This, pFilter);
2914
return E_NOTIMPL;
2915
}
2916
2917
static HRESULT WINAPI IFileDialog2_fnSetCancelButtonLabel(IFileDialog2 *iface, LPCWSTR pszLabel)
2918
{
2919
FileDialogImpl *This = impl_from_IFileDialog2(iface);
2920
TRACE("%p (%s)\n", This, debugstr_w(pszLabel));
2921
2922
LocalFree(This->custom_cancelbutton);
2923
This->custom_cancelbutton = StrDupW(pszLabel);
2924
update_control_text(This);
2925
update_layout(This);
2926
2927
return S_OK;
2928
}
2929
2930
static HRESULT WINAPI IFileDialog2_fnSetNavigationRoot(IFileDialog2 *iface, IShellItem *psi)
2931
{
2932
FileDialogImpl *This = impl_from_IFileDialog2(iface);
2933
FIXME("stub - %p (%p)\n", This, psi);
2934
return E_NOTIMPL;
2935
}
2936
2937
static const IFileDialog2Vtbl vt_IFileDialog2 = {
2938
IFileDialog2_fnQueryInterface,
2939
IFileDialog2_fnAddRef,
2940
IFileDialog2_fnRelease,
2941
IFileDialog2_fnShow,
2942
IFileDialog2_fnSetFileTypes,
2943
IFileDialog2_fnSetFileTypeIndex,
2944
IFileDialog2_fnGetFileTypeIndex,
2945
IFileDialog2_fnAdvise,
2946
IFileDialog2_fnUnadvise,
2947
IFileDialog2_fnSetOptions,
2948
IFileDialog2_fnGetOptions,
2949
IFileDialog2_fnSetDefaultFolder,
2950
IFileDialog2_fnSetFolder,
2951
IFileDialog2_fnGetFolder,
2952
IFileDialog2_fnGetCurrentSelection,
2953
IFileDialog2_fnSetFileName,
2954
IFileDialog2_fnGetFileName,
2955
IFileDialog2_fnSetTitle,
2956
IFileDialog2_fnSetOkButtonLabel,
2957
IFileDialog2_fnSetFileNameLabel,
2958
IFileDialog2_fnGetResult,
2959
IFileDialog2_fnAddPlace,
2960
IFileDialog2_fnSetDefaultExtension,
2961
IFileDialog2_fnClose,
2962
IFileDialog2_fnSetClientGuid,
2963
IFileDialog2_fnClearClientData,
2964
IFileDialog2_fnSetFilter,
2965
IFileDialog2_fnSetCancelButtonLabel,
2966
IFileDialog2_fnSetNavigationRoot
2967
};
2968
2969
/**************************************************************************
2970
* IFileOpenDialog
2971
*/
2972
static inline FileDialogImpl *impl_from_IFileOpenDialog(IFileOpenDialog *iface)
2973
{
2974
return CONTAINING_RECORD(iface, FileDialogImpl, u.IFileOpenDialog_iface);
2975
}
2976
2977
static HRESULT WINAPI IFileOpenDialog_fnQueryInterface(IFileOpenDialog *iface,
2978
REFIID riid, void **ppvObject)
2979
{
2980
FileDialogImpl *This = impl_from_IFileOpenDialog(iface);
2981
return IFileDialog2_QueryInterface(&This->IFileDialog2_iface, riid, ppvObject);
2982
}
2983
2984
static ULONG WINAPI IFileOpenDialog_fnAddRef(IFileOpenDialog *iface)
2985
{
2986
FileDialogImpl *This = impl_from_IFileOpenDialog(iface);
2987
return IFileDialog2_AddRef(&This->IFileDialog2_iface);
2988
}
2989
2990
static ULONG WINAPI IFileOpenDialog_fnRelease(IFileOpenDialog *iface)
2991
{
2992
FileDialogImpl *This = impl_from_IFileOpenDialog(iface);
2993
return IFileDialog2_Release(&This->IFileDialog2_iface);
2994
}
2995
2996
static HRESULT WINAPI IFileOpenDialog_fnShow(IFileOpenDialog *iface, HWND hwndOwner)
2997
{
2998
FileDialogImpl *This = impl_from_IFileOpenDialog(iface);
2999
return IFileDialog2_Show(&This->IFileDialog2_iface, hwndOwner);
3000
}
3001
3002
static HRESULT WINAPI IFileOpenDialog_fnSetFileTypes(IFileOpenDialog *iface, UINT cFileTypes,
3003
const COMDLG_FILTERSPEC *rgFilterSpec)
3004
{
3005
FileDialogImpl *This = impl_from_IFileOpenDialog(iface);
3006
return IFileDialog2_SetFileTypes(&This->IFileDialog2_iface, cFileTypes, rgFilterSpec);
3007
}
3008
3009
static HRESULT WINAPI IFileOpenDialog_fnSetFileTypeIndex(IFileOpenDialog *iface, UINT iFileType)
3010
{
3011
FileDialogImpl *This = impl_from_IFileOpenDialog(iface);
3012
return IFileDialog2_SetFileTypeIndex(&This->IFileDialog2_iface, iFileType);
3013
}
3014
3015
static HRESULT WINAPI IFileOpenDialog_fnGetFileTypeIndex(IFileOpenDialog *iface, UINT *piFileType)
3016
{
3017
FileDialogImpl *This = impl_from_IFileOpenDialog(iface);
3018
return IFileDialog2_GetFileTypeIndex(&This->IFileDialog2_iface, piFileType);
3019
}
3020
3021
static HRESULT WINAPI IFileOpenDialog_fnAdvise(IFileOpenDialog *iface, IFileDialogEvents *pfde,
3022
DWORD *pdwCookie)
3023
{
3024
FileDialogImpl *This = impl_from_IFileOpenDialog(iface);
3025
return IFileDialog2_Advise(&This->IFileDialog2_iface, pfde, pdwCookie);
3026
}
3027
3028
static HRESULT WINAPI IFileOpenDialog_fnUnadvise(IFileOpenDialog *iface, DWORD dwCookie)
3029
{
3030
FileDialogImpl *This = impl_from_IFileOpenDialog(iface);
3031
return IFileDialog2_Unadvise(&This->IFileDialog2_iface, dwCookie);
3032
}
3033
3034
static HRESULT WINAPI IFileOpenDialog_fnSetOptions(IFileOpenDialog *iface, FILEOPENDIALOGOPTIONS fos)
3035
{
3036
FileDialogImpl *This = impl_from_IFileOpenDialog(iface);
3037
return IFileDialog2_SetOptions(&This->IFileDialog2_iface, fos);
3038
}
3039
3040
static HRESULT WINAPI IFileOpenDialog_fnGetOptions(IFileOpenDialog *iface, FILEOPENDIALOGOPTIONS *pfos)
3041
{
3042
FileDialogImpl *This = impl_from_IFileOpenDialog(iface);
3043
return IFileDialog2_GetOptions(&This->IFileDialog2_iface, pfos);
3044
}
3045
3046
static HRESULT WINAPI IFileOpenDialog_fnSetDefaultFolder(IFileOpenDialog *iface, IShellItem *psi)
3047
{
3048
FileDialogImpl *This = impl_from_IFileOpenDialog(iface);
3049
return IFileDialog2_SetDefaultFolder(&This->IFileDialog2_iface, psi);
3050
}
3051
3052
static HRESULT WINAPI IFileOpenDialog_fnSetFolder(IFileOpenDialog *iface, IShellItem *psi)
3053
{
3054
FileDialogImpl *This = impl_from_IFileOpenDialog(iface);
3055
return IFileDialog2_SetFolder(&This->IFileDialog2_iface, psi);
3056
}
3057
3058
static HRESULT WINAPI IFileOpenDialog_fnGetFolder(IFileOpenDialog *iface, IShellItem **ppsi)
3059
{
3060
FileDialogImpl *This = impl_from_IFileOpenDialog(iface);
3061
return IFileDialog2_GetFolder(&This->IFileDialog2_iface, ppsi);
3062
}
3063
3064
static HRESULT WINAPI IFileOpenDialog_fnGetCurrentSelection(IFileOpenDialog *iface, IShellItem **ppsi)
3065
{
3066
FileDialogImpl *This = impl_from_IFileOpenDialog(iface);
3067
return IFileDialog2_GetCurrentSelection(&This->IFileDialog2_iface, ppsi);
3068
}
3069
3070
static HRESULT WINAPI IFileOpenDialog_fnSetFileName(IFileOpenDialog *iface, LPCWSTR pszName)
3071
{
3072
FileDialogImpl *This = impl_from_IFileOpenDialog(iface);
3073
return IFileDialog2_SetFileName(&This->IFileDialog2_iface, pszName);
3074
}
3075
3076
static HRESULT WINAPI IFileOpenDialog_fnGetFileName(IFileOpenDialog *iface, LPWSTR *pszName)
3077
{
3078
FileDialogImpl *This = impl_from_IFileOpenDialog(iface);
3079
return IFileDialog2_GetFileName(&This->IFileDialog2_iface, pszName);
3080
}
3081
3082
static HRESULT WINAPI IFileOpenDialog_fnSetTitle(IFileOpenDialog *iface, LPCWSTR pszTitle)
3083
{
3084
FileDialogImpl *This = impl_from_IFileOpenDialog(iface);
3085
return IFileDialog2_SetTitle(&This->IFileDialog2_iface, pszTitle);
3086
}
3087
3088
static HRESULT WINAPI IFileOpenDialog_fnSetOkButtonLabel(IFileOpenDialog *iface, LPCWSTR pszText)
3089
{
3090
FileDialogImpl *This = impl_from_IFileOpenDialog(iface);
3091
return IFileDialog2_SetOkButtonLabel(&This->IFileDialog2_iface, pszText);
3092
}
3093
3094
static HRESULT WINAPI IFileOpenDialog_fnSetFileNameLabel(IFileOpenDialog *iface, LPCWSTR pszLabel)
3095
{
3096
FileDialogImpl *This = impl_from_IFileOpenDialog(iface);
3097
return IFileDialog2_SetFileNameLabel(&This->IFileDialog2_iface, pszLabel);
3098
}
3099
3100
static HRESULT WINAPI IFileOpenDialog_fnGetResult(IFileOpenDialog *iface, IShellItem **ppsi)
3101
{
3102
FileDialogImpl *This = impl_from_IFileOpenDialog(iface);
3103
return IFileDialog2_GetResult(&This->IFileDialog2_iface, ppsi);
3104
}
3105
3106
static HRESULT WINAPI IFileOpenDialog_fnAddPlace(IFileOpenDialog *iface, IShellItem *psi, FDAP fdap)
3107
{
3108
FileDialogImpl *This = impl_from_IFileOpenDialog(iface);
3109
return IFileDialog2_AddPlace(&This->IFileDialog2_iface, psi, fdap);
3110
}
3111
3112
static HRESULT WINAPI IFileOpenDialog_fnSetDefaultExtension(IFileOpenDialog *iface,
3113
LPCWSTR pszDefaultExtension)
3114
{
3115
FileDialogImpl *This = impl_from_IFileOpenDialog(iface);
3116
return IFileDialog2_SetDefaultExtension(&This->IFileDialog2_iface, pszDefaultExtension);
3117
}
3118
3119
static HRESULT WINAPI IFileOpenDialog_fnClose(IFileOpenDialog *iface, HRESULT hr)
3120
{
3121
FileDialogImpl *This = impl_from_IFileOpenDialog(iface);
3122
return IFileDialog2_Close(&This->IFileDialog2_iface, hr);
3123
}
3124
3125
static HRESULT WINAPI IFileOpenDialog_fnSetClientGuid(IFileOpenDialog *iface, REFGUID guid)
3126
{
3127
FileDialogImpl *This = impl_from_IFileOpenDialog(iface);
3128
return IFileDialog2_SetClientGuid(&This->IFileDialog2_iface, guid);
3129
}
3130
3131
static HRESULT WINAPI IFileOpenDialog_fnClearClientData(IFileOpenDialog *iface)
3132
{
3133
FileDialogImpl *This = impl_from_IFileOpenDialog(iface);
3134
return IFileDialog2_ClearClientData(&This->IFileDialog2_iface);
3135
}
3136
3137
static HRESULT WINAPI IFileOpenDialog_fnSetFilter(IFileOpenDialog *iface, IShellItemFilter *pFilter)
3138
{
3139
FileDialogImpl *This = impl_from_IFileOpenDialog(iface);
3140
return IFileDialog2_SetFilter(&This->IFileDialog2_iface, pFilter);
3141
}
3142
3143
static HRESULT WINAPI IFileOpenDialog_fnGetResults(IFileOpenDialog *iface, IShellItemArray **ppenum)
3144
{
3145
FileDialogImpl *This = impl_from_IFileOpenDialog(iface);
3146
TRACE("%p (%p)\n", This, ppenum);
3147
3148
*ppenum = This->psia_results;
3149
3150
if(*ppenum)
3151
{
3152
IShellItemArray_AddRef(*ppenum);
3153
return S_OK;
3154
}
3155
3156
return E_FAIL;
3157
}
3158
3159
static HRESULT WINAPI IFileOpenDialog_fnGetSelectedItems(IFileOpenDialog *iface, IShellItemArray **ppsai)
3160
{
3161
FileDialogImpl *This = impl_from_IFileOpenDialog(iface);
3162
TRACE("%p (%p)\n", This, ppsai);
3163
3164
if(This->psia_selection)
3165
{
3166
*ppsai = This->psia_selection;
3167
IShellItemArray_AddRef(*ppsai);
3168
return S_OK;
3169
}
3170
3171
return E_FAIL;
3172
}
3173
3174
static const IFileOpenDialogVtbl vt_IFileOpenDialog = {
3175
IFileOpenDialog_fnQueryInterface,
3176
IFileOpenDialog_fnAddRef,
3177
IFileOpenDialog_fnRelease,
3178
IFileOpenDialog_fnShow,
3179
IFileOpenDialog_fnSetFileTypes,
3180
IFileOpenDialog_fnSetFileTypeIndex,
3181
IFileOpenDialog_fnGetFileTypeIndex,
3182
IFileOpenDialog_fnAdvise,
3183
IFileOpenDialog_fnUnadvise,
3184
IFileOpenDialog_fnSetOptions,
3185
IFileOpenDialog_fnGetOptions,
3186
IFileOpenDialog_fnSetDefaultFolder,
3187
IFileOpenDialog_fnSetFolder,
3188
IFileOpenDialog_fnGetFolder,
3189
IFileOpenDialog_fnGetCurrentSelection,
3190
IFileOpenDialog_fnSetFileName,
3191
IFileOpenDialog_fnGetFileName,
3192
IFileOpenDialog_fnSetTitle,
3193
IFileOpenDialog_fnSetOkButtonLabel,
3194
IFileOpenDialog_fnSetFileNameLabel,
3195
IFileOpenDialog_fnGetResult,
3196
IFileOpenDialog_fnAddPlace,
3197
IFileOpenDialog_fnSetDefaultExtension,
3198
IFileOpenDialog_fnClose,
3199
IFileOpenDialog_fnSetClientGuid,
3200
IFileOpenDialog_fnClearClientData,
3201
IFileOpenDialog_fnSetFilter,
3202
IFileOpenDialog_fnGetResults,
3203
IFileOpenDialog_fnGetSelectedItems
3204
};
3205
3206
/**************************************************************************
3207
* IFileSaveDialog
3208
*/
3209
static inline FileDialogImpl *impl_from_IFileSaveDialog(IFileSaveDialog *iface)
3210
{
3211
return CONTAINING_RECORD(iface, FileDialogImpl, u.IFileSaveDialog_iface);
3212
}
3213
3214
static HRESULT WINAPI IFileSaveDialog_fnQueryInterface(IFileSaveDialog *iface,
3215
REFIID riid,
3216
void **ppvObject)
3217
{
3218
FileDialogImpl *This = impl_from_IFileSaveDialog(iface);
3219
return IFileDialog2_QueryInterface(&This->IFileDialog2_iface, riid, ppvObject);
3220
}
3221
3222
static ULONG WINAPI IFileSaveDialog_fnAddRef(IFileSaveDialog *iface)
3223
{
3224
FileDialogImpl *This = impl_from_IFileSaveDialog(iface);
3225
return IFileDialog2_AddRef(&This->IFileDialog2_iface);
3226
}
3227
3228
static ULONG WINAPI IFileSaveDialog_fnRelease(IFileSaveDialog *iface)
3229
{
3230
FileDialogImpl *This = impl_from_IFileSaveDialog(iface);
3231
return IFileDialog2_Release(&This->IFileDialog2_iface);
3232
}
3233
3234
static HRESULT WINAPI IFileSaveDialog_fnShow(IFileSaveDialog *iface, HWND hwndOwner)
3235
{
3236
FileDialogImpl *This = impl_from_IFileSaveDialog(iface);
3237
return IFileDialog2_Show(&This->IFileDialog2_iface, hwndOwner);
3238
}
3239
3240
static HRESULT WINAPI IFileSaveDialog_fnSetFileTypes(IFileSaveDialog *iface, UINT cFileTypes,
3241
const COMDLG_FILTERSPEC *rgFilterSpec)
3242
{
3243
FileDialogImpl *This = impl_from_IFileSaveDialog(iface);
3244
return IFileDialog2_SetFileTypes(&This->IFileDialog2_iface, cFileTypes, rgFilterSpec);
3245
}
3246
3247
static HRESULT WINAPI IFileSaveDialog_fnSetFileTypeIndex(IFileSaveDialog *iface, UINT iFileType)
3248
{
3249
FileDialogImpl *This = impl_from_IFileSaveDialog(iface);
3250
return IFileDialog2_SetFileTypeIndex(&This->IFileDialog2_iface, iFileType);
3251
}
3252
3253
static HRESULT WINAPI IFileSaveDialog_fnGetFileTypeIndex(IFileSaveDialog *iface, UINT *piFileType)
3254
{
3255
FileDialogImpl *This = impl_from_IFileSaveDialog(iface);
3256
return IFileDialog2_GetFileTypeIndex(&This->IFileDialog2_iface, piFileType);
3257
}
3258
3259
static HRESULT WINAPI IFileSaveDialog_fnAdvise(IFileSaveDialog *iface, IFileDialogEvents *pfde,
3260
DWORD *pdwCookie)
3261
{
3262
FileDialogImpl *This = impl_from_IFileSaveDialog(iface);
3263
return IFileDialog2_Advise(&This->IFileDialog2_iface, pfde, pdwCookie);
3264
}
3265
3266
static HRESULT WINAPI IFileSaveDialog_fnUnadvise(IFileSaveDialog *iface, DWORD dwCookie)
3267
{
3268
FileDialogImpl *This = impl_from_IFileSaveDialog(iface);
3269
return IFileDialog2_Unadvise(&This->IFileDialog2_iface, dwCookie);
3270
}
3271
3272
static HRESULT WINAPI IFileSaveDialog_fnSetOptions(IFileSaveDialog *iface, FILEOPENDIALOGOPTIONS fos)
3273
{
3274
FileDialogImpl *This = impl_from_IFileSaveDialog(iface);
3275
return IFileDialog2_SetOptions(&This->IFileDialog2_iface, fos);
3276
}
3277
3278
static HRESULT WINAPI IFileSaveDialog_fnGetOptions(IFileSaveDialog *iface, FILEOPENDIALOGOPTIONS *pfos)
3279
{
3280
FileDialogImpl *This = impl_from_IFileSaveDialog(iface);
3281
return IFileDialog2_GetOptions(&This->IFileDialog2_iface, pfos);
3282
}
3283
3284
static HRESULT WINAPI IFileSaveDialog_fnSetDefaultFolder(IFileSaveDialog *iface, IShellItem *psi)
3285
{
3286
FileDialogImpl *This = impl_from_IFileSaveDialog(iface);
3287
return IFileDialog2_SetDefaultFolder(&This->IFileDialog2_iface, psi);
3288
}
3289
3290
static HRESULT WINAPI IFileSaveDialog_fnSetFolder(IFileSaveDialog *iface, IShellItem *psi)
3291
{
3292
FileDialogImpl *This = impl_from_IFileSaveDialog(iface);
3293
return IFileDialog2_SetFolder(&This->IFileDialog2_iface, psi);
3294
}
3295
3296
static HRESULT WINAPI IFileSaveDialog_fnGetFolder(IFileSaveDialog *iface, IShellItem **ppsi)
3297
{
3298
FileDialogImpl *This = impl_from_IFileSaveDialog(iface);
3299
return IFileDialog2_GetFolder(&This->IFileDialog2_iface, ppsi);
3300
}
3301
3302
static HRESULT WINAPI IFileSaveDialog_fnGetCurrentSelection(IFileSaveDialog *iface, IShellItem **ppsi)
3303
{
3304
FileDialogImpl *This = impl_from_IFileSaveDialog(iface);
3305
return IFileDialog2_GetCurrentSelection(&This->IFileDialog2_iface, ppsi);
3306
}
3307
3308
static HRESULT WINAPI IFileSaveDialog_fnSetFileName(IFileSaveDialog *iface, LPCWSTR pszName)
3309
{
3310
FileDialogImpl *This = impl_from_IFileSaveDialog(iface);
3311
return IFileDialog2_SetFileName(&This->IFileDialog2_iface, pszName);
3312
}
3313
3314
static HRESULT WINAPI IFileSaveDialog_fnGetFileName(IFileSaveDialog *iface, LPWSTR *pszName)
3315
{
3316
FileDialogImpl *This = impl_from_IFileSaveDialog(iface);
3317
return IFileDialog2_GetFileName(&This->IFileDialog2_iface, pszName);
3318
}
3319
3320
static HRESULT WINAPI IFileSaveDialog_fnSetTitle(IFileSaveDialog *iface, LPCWSTR pszTitle)
3321
{
3322
FileDialogImpl *This = impl_from_IFileSaveDialog(iface);
3323
return IFileDialog2_SetTitle(&This->IFileDialog2_iface, pszTitle);
3324
}
3325
3326
static HRESULT WINAPI IFileSaveDialog_fnSetOkButtonLabel(IFileSaveDialog *iface, LPCWSTR pszText)
3327
{
3328
FileDialogImpl *This = impl_from_IFileSaveDialog(iface);
3329
return IFileDialog2_SetOkButtonLabel(&This->IFileDialog2_iface, pszText);
3330
}
3331
3332
static HRESULT WINAPI IFileSaveDialog_fnSetFileNameLabel(IFileSaveDialog *iface, LPCWSTR pszLabel)
3333
{
3334
FileDialogImpl *This = impl_from_IFileSaveDialog(iface);
3335
return IFileDialog2_SetFileNameLabel(&This->IFileDialog2_iface, pszLabel);
3336
}
3337
3338
static HRESULT WINAPI IFileSaveDialog_fnGetResult(IFileSaveDialog *iface, IShellItem **ppsi)
3339
{
3340
FileDialogImpl *This = impl_from_IFileSaveDialog(iface);
3341
return IFileDialog2_GetResult(&This->IFileDialog2_iface, ppsi);
3342
}
3343
3344
static HRESULT WINAPI IFileSaveDialog_fnAddPlace(IFileSaveDialog *iface, IShellItem *psi, FDAP fdap)
3345
{
3346
FileDialogImpl *This = impl_from_IFileSaveDialog(iface);
3347
return IFileDialog2_AddPlace(&This->IFileDialog2_iface, psi, fdap);
3348
}
3349
3350
static HRESULT WINAPI IFileSaveDialog_fnSetDefaultExtension(IFileSaveDialog *iface,
3351
LPCWSTR pszDefaultExtension)
3352
{
3353
FileDialogImpl *This = impl_from_IFileSaveDialog(iface);
3354
return IFileDialog2_SetDefaultExtension(&This->IFileDialog2_iface, pszDefaultExtension);
3355
}
3356
3357
static HRESULT WINAPI IFileSaveDialog_fnClose(IFileSaveDialog *iface, HRESULT hr)
3358
{
3359
FileDialogImpl *This = impl_from_IFileSaveDialog(iface);
3360
return IFileDialog2_Close(&This->IFileDialog2_iface, hr);
3361
}
3362
3363
static HRESULT WINAPI IFileSaveDialog_fnSetClientGuid(IFileSaveDialog *iface, REFGUID guid)
3364
{
3365
FileDialogImpl *This = impl_from_IFileSaveDialog(iface);
3366
return IFileDialog2_SetClientGuid(&This->IFileDialog2_iface, guid);
3367
}
3368
3369
static HRESULT WINAPI IFileSaveDialog_fnClearClientData(IFileSaveDialog *iface)
3370
{
3371
FileDialogImpl *This = impl_from_IFileSaveDialog(iface);
3372
return IFileDialog2_ClearClientData(&This->IFileDialog2_iface);
3373
}
3374
3375
static HRESULT WINAPI IFileSaveDialog_fnSetFilter(IFileSaveDialog *iface, IShellItemFilter *pFilter)
3376
{
3377
FileDialogImpl *This = impl_from_IFileSaveDialog(iface);
3378
return IFileDialog2_SetFilter(&This->IFileDialog2_iface, pFilter);
3379
}
3380
3381
static HRESULT WINAPI IFileSaveDialog_fnSetSaveAsItem(IFileSaveDialog* iface, IShellItem *psi)
3382
{
3383
FileDialogImpl *This = impl_from_IFileSaveDialog(iface);
3384
FIXME("stub - %p (%p)\n", This, psi);
3385
return E_NOTIMPL;
3386
}
3387
3388
static HRESULT WINAPI IFileSaveDialog_fnSetProperties(IFileSaveDialog* iface, IPropertyStore *pStore)
3389
{
3390
FileDialogImpl *This = impl_from_IFileSaveDialog(iface);
3391
FIXME("stub - %p (%p)\n", This, pStore);
3392
return E_NOTIMPL;
3393
}
3394
3395
static HRESULT WINAPI IFileSaveDialog_fnSetCollectedProperties(IFileSaveDialog* iface,
3396
IPropertyDescriptionList *pList,
3397
BOOL fAppendDefault)
3398
{
3399
FileDialogImpl *This = impl_from_IFileSaveDialog(iface);
3400
FIXME("stub - %p (%p, %d)\n", This, pList, fAppendDefault);
3401
return E_NOTIMPL;
3402
}
3403
3404
static HRESULT WINAPI IFileSaveDialog_fnGetProperties(IFileSaveDialog* iface, IPropertyStore **ppStore)
3405
{
3406
FileDialogImpl *This = impl_from_IFileSaveDialog(iface);
3407
FIXME("stub - %p (%p)\n", This, ppStore);
3408
return E_NOTIMPL;
3409
}
3410
3411
static HRESULT WINAPI IFileSaveDialog_fnApplyProperties(IFileSaveDialog* iface,
3412
IShellItem *psi,
3413
IPropertyStore *pStore,
3414
HWND hwnd,
3415
IFileOperationProgressSink *pSink)
3416
{
3417
FileDialogImpl *This = impl_from_IFileSaveDialog(iface);
3418
FIXME("%p (%p, %p, %p, %p)\n", This, psi, pStore, hwnd, pSink);
3419
return E_NOTIMPL;
3420
}
3421
3422
static const IFileSaveDialogVtbl vt_IFileSaveDialog = {
3423
IFileSaveDialog_fnQueryInterface,
3424
IFileSaveDialog_fnAddRef,
3425
IFileSaveDialog_fnRelease,
3426
IFileSaveDialog_fnShow,
3427
IFileSaveDialog_fnSetFileTypes,
3428
IFileSaveDialog_fnSetFileTypeIndex,
3429
IFileSaveDialog_fnGetFileTypeIndex,
3430
IFileSaveDialog_fnAdvise,
3431
IFileSaveDialog_fnUnadvise,
3432
IFileSaveDialog_fnSetOptions,
3433
IFileSaveDialog_fnGetOptions,
3434
IFileSaveDialog_fnSetDefaultFolder,
3435
IFileSaveDialog_fnSetFolder,
3436
IFileSaveDialog_fnGetFolder,
3437
IFileSaveDialog_fnGetCurrentSelection,
3438
IFileSaveDialog_fnSetFileName,
3439
IFileSaveDialog_fnGetFileName,
3440
IFileSaveDialog_fnSetTitle,
3441
IFileSaveDialog_fnSetOkButtonLabel,
3442
IFileSaveDialog_fnSetFileNameLabel,
3443
IFileSaveDialog_fnGetResult,
3444
IFileSaveDialog_fnAddPlace,
3445
IFileSaveDialog_fnSetDefaultExtension,
3446
IFileSaveDialog_fnClose,
3447
IFileSaveDialog_fnSetClientGuid,
3448
IFileSaveDialog_fnClearClientData,
3449
IFileSaveDialog_fnSetFilter,
3450
IFileSaveDialog_fnSetSaveAsItem,
3451
IFileSaveDialog_fnSetProperties,
3452
IFileSaveDialog_fnSetCollectedProperties,
3453
IFileSaveDialog_fnGetProperties,
3454
IFileSaveDialog_fnApplyProperties
3455
};
3456
3457
/**************************************************************************
3458
* IExplorerBrowserEvents implementation
3459
*/
3460
static inline FileDialogImpl *impl_from_IExplorerBrowserEvents(IExplorerBrowserEvents *iface)
3461
{
3462
return CONTAINING_RECORD(iface, FileDialogImpl, IExplorerBrowserEvents_iface);
3463
}
3464
3465
static HRESULT WINAPI IExplorerBrowserEvents_fnQueryInterface(IExplorerBrowserEvents *iface,
3466
REFIID riid, void **ppvObject)
3467
{
3468
FileDialogImpl *This = impl_from_IExplorerBrowserEvents(iface);
3469
TRACE("%p (%s, %p)\n", This, debugstr_guid(riid), ppvObject);
3470
3471
return IFileDialog2_QueryInterface(&This->IFileDialog2_iface, riid, ppvObject);
3472
}
3473
3474
static ULONG WINAPI IExplorerBrowserEvents_fnAddRef(IExplorerBrowserEvents *iface)
3475
{
3476
FileDialogImpl *This = impl_from_IExplorerBrowserEvents(iface);
3477
TRACE("%p\n", This);
3478
return IFileDialog2_AddRef(&This->IFileDialog2_iface);
3479
}
3480
3481
static ULONG WINAPI IExplorerBrowserEvents_fnRelease(IExplorerBrowserEvents *iface)
3482
{
3483
FileDialogImpl *This = impl_from_IExplorerBrowserEvents(iface);
3484
TRACE("%p\n", This);
3485
return IFileDialog2_Release(&This->IFileDialog2_iface);
3486
}
3487
3488
static HRESULT WINAPI IExplorerBrowserEvents_fnOnNavigationPending(IExplorerBrowserEvents *iface,
3489
PCIDLIST_ABSOLUTE pidlFolder)
3490
{
3491
FileDialogImpl *This = impl_from_IExplorerBrowserEvents(iface);
3492
IShellItem *psi;
3493
HRESULT hr;
3494
TRACE("%p (%p)\n", This, pidlFolder);
3495
3496
hr = SHCreateItemFromIDList(pidlFolder, &IID_IShellItem, (void**)&psi);
3497
if(SUCCEEDED(hr))
3498
{
3499
hr = events_OnFolderChanging(This, psi);
3500
IShellItem_Release(psi);
3501
3502
/* The ExplorerBrowser treats S_FALSE as S_OK, we don't. */
3503
if(hr == S_FALSE)
3504
hr = E_FAIL;
3505
3506
return hr;
3507
}
3508
else
3509
ERR("Failed to convert pidl (%p) to a shellitem.\n", pidlFolder);
3510
3511
return S_OK;
3512
}
3513
3514
static HRESULT WINAPI IExplorerBrowserEvents_fnOnViewCreated(IExplorerBrowserEvents *iface,
3515
IShellView *psv)
3516
{
3517
FileDialogImpl *This = impl_from_IExplorerBrowserEvents(iface);
3518
TRACE("%p (%p)\n", This, psv);
3519
return S_OK;
3520
}
3521
3522
static HRESULT WINAPI IExplorerBrowserEvents_fnOnNavigationComplete(IExplorerBrowserEvents *iface,
3523
PCIDLIST_ABSOLUTE pidlFolder)
3524
{
3525
FileDialogImpl *This = impl_from_IExplorerBrowserEvents(iface);
3526
HRESULT hr;
3527
TRACE("%p (%p)\n", This, pidlFolder);
3528
3529
if(This->psi_folder)
3530
IShellItem_Release(This->psi_folder);
3531
3532
hr = SHCreateItemFromIDList(pidlFolder, &IID_IShellItem, (void**)&This->psi_folder);
3533
if(FAILED(hr))
3534
{
3535
ERR("Failed to get the current folder.\n");
3536
This->psi_folder = NULL;
3537
}
3538
3539
events_OnFolderChange(This);
3540
3541
return S_OK;
3542
}
3543
3544
static HRESULT WINAPI IExplorerBrowserEvents_fnOnNavigationFailed(IExplorerBrowserEvents *iface,
3545
PCIDLIST_ABSOLUTE pidlFolder)
3546
{
3547
FileDialogImpl *This = impl_from_IExplorerBrowserEvents(iface);
3548
TRACE("%p (%p)\n", This, pidlFolder);
3549
return S_OK;
3550
}
3551
3552
static const IExplorerBrowserEventsVtbl vt_IExplorerBrowserEvents = {
3553
IExplorerBrowserEvents_fnQueryInterface,
3554
IExplorerBrowserEvents_fnAddRef,
3555
IExplorerBrowserEvents_fnRelease,
3556
IExplorerBrowserEvents_fnOnNavigationPending,
3557
IExplorerBrowserEvents_fnOnViewCreated,
3558
IExplorerBrowserEvents_fnOnNavigationComplete,
3559
IExplorerBrowserEvents_fnOnNavigationFailed
3560
};
3561
3562
/**************************************************************************
3563
* IServiceProvider implementation
3564
*/
3565
static inline FileDialogImpl *impl_from_IServiceProvider(IServiceProvider *iface)
3566
{
3567
return CONTAINING_RECORD(iface, FileDialogImpl, IServiceProvider_iface);
3568
}
3569
3570
static HRESULT WINAPI IServiceProvider_fnQueryInterface(IServiceProvider *iface,
3571
REFIID riid, void **ppvObject)
3572
{
3573
FileDialogImpl *This = impl_from_IServiceProvider(iface);
3574
TRACE("%p\n", This);
3575
return IFileDialog2_QueryInterface(&This->IFileDialog2_iface, riid, ppvObject);
3576
}
3577
3578
static ULONG WINAPI IServiceProvider_fnAddRef(IServiceProvider *iface)
3579
{
3580
FileDialogImpl *This = impl_from_IServiceProvider(iface);
3581
TRACE("%p\n", This);
3582
return IFileDialog2_AddRef(&This->IFileDialog2_iface);
3583
}
3584
3585
static ULONG WINAPI IServiceProvider_fnRelease(IServiceProvider *iface)
3586
{
3587
FileDialogImpl *This = impl_from_IServiceProvider(iface);
3588
TRACE("%p\n", This);
3589
return IFileDialog2_Release(&This->IFileDialog2_iface);
3590
}
3591
3592
static HRESULT WINAPI IServiceProvider_fnQueryService(IServiceProvider *iface,
3593
REFGUID guidService,
3594
REFIID riid, void **ppv)
3595
{
3596
FileDialogImpl *This = impl_from_IServiceProvider(iface);
3597
HRESULT hr = E_NOTIMPL;
3598
TRACE("%p (%s, %s, %p)\n", This, debugstr_guid(guidService), debugstr_guid(riid), ppv);
3599
3600
*ppv = NULL;
3601
if(IsEqualGUID(guidService, &SID_STopLevelBrowser) && This->peb)
3602
hr = IExplorerBrowser_QueryInterface(This->peb, riid, ppv);
3603
else if(IsEqualGUID(guidService, &SID_SExplorerBrowserFrame))
3604
hr = IFileDialog2_QueryInterface(&This->IFileDialog2_iface, riid, ppv);
3605
else
3606
FIXME("Interface %s requested from unknown service %s\n",
3607
debugstr_guid(riid), debugstr_guid(guidService));
3608
3609
return hr;
3610
}
3611
3612
static const IServiceProviderVtbl vt_IServiceProvider = {
3613
IServiceProvider_fnQueryInterface,
3614
IServiceProvider_fnAddRef,
3615
IServiceProvider_fnRelease,
3616
IServiceProvider_fnQueryService
3617
};
3618
3619
/**************************************************************************
3620
* ICommDlgBrowser3 implementation
3621
*/
3622
static inline FileDialogImpl *impl_from_ICommDlgBrowser3(ICommDlgBrowser3 *iface)
3623
{
3624
return CONTAINING_RECORD(iface, FileDialogImpl, ICommDlgBrowser3_iface);
3625
}
3626
3627
static HRESULT WINAPI ICommDlgBrowser3_fnQueryInterface(ICommDlgBrowser3 *iface,
3628
REFIID riid, void **ppvObject)
3629
{
3630
FileDialogImpl *This = impl_from_ICommDlgBrowser3(iface);
3631
TRACE("%p\n", This);
3632
return IFileDialog2_QueryInterface(&This->IFileDialog2_iface, riid, ppvObject);
3633
}
3634
3635
static ULONG WINAPI ICommDlgBrowser3_fnAddRef(ICommDlgBrowser3 *iface)
3636
{
3637
FileDialogImpl *This = impl_from_ICommDlgBrowser3(iface);
3638
TRACE("%p\n", This);
3639
return IFileDialog2_AddRef(&This->IFileDialog2_iface);
3640
}
3641
3642
static ULONG WINAPI ICommDlgBrowser3_fnRelease(ICommDlgBrowser3 *iface)
3643
{
3644
FileDialogImpl *This = impl_from_ICommDlgBrowser3(iface);
3645
TRACE("%p\n", This);
3646
return IFileDialog2_Release(&This->IFileDialog2_iface);
3647
}
3648
3649
static HRESULT WINAPI ICommDlgBrowser3_fnOnDefaultCommand(ICommDlgBrowser3 *iface,
3650
IShellView *shv)
3651
{
3652
FileDialogImpl *This = impl_from_ICommDlgBrowser3(iface);
3653
HRESULT hr;
3654
TRACE("%p (%p)\n", This, shv);
3655
3656
hr = on_default_action(This);
3657
3658
if(SUCCEEDED(hr))
3659
EndDialog(This->dlg_hwnd, S_OK);
3660
3661
return S_OK;
3662
}
3663
3664
static HRESULT WINAPI ICommDlgBrowser3_fnOnStateChange(ICommDlgBrowser3 *iface,
3665
IShellView *shv, ULONG uChange )
3666
{
3667
FileDialogImpl *This = impl_from_ICommDlgBrowser3(iface);
3668
IDataObject *new_selection;
3669
HRESULT hr;
3670
TRACE("%p (%p, %lx)\n", This, shv, uChange);
3671
3672
switch(uChange)
3673
{
3674
case CDBOSC_SELCHANGE:
3675
if(This->psia_selection)
3676
{
3677
IShellItemArray_Release(This->psia_selection);
3678
This->psia_selection = NULL;
3679
}
3680
3681
hr = IShellView_GetItemObject(shv, SVGIO_SELECTION, &IID_IDataObject, (void**)&new_selection);
3682
if(SUCCEEDED(hr))
3683
{
3684
hr = SHCreateShellItemArrayFromDataObject(new_selection, &IID_IShellItemArray,
3685
(void**)&This->psia_selection);
3686
if(SUCCEEDED(hr))
3687
{
3688
fill_filename_from_selection(This);
3689
events_OnSelectionChange(This);
3690
}
3691
3692
IDataObject_Release(new_selection);
3693
}
3694
break;
3695
default:
3696
TRACE("Unhandled state change\n");
3697
}
3698
return S_OK;
3699
}
3700
3701
static HRESULT WINAPI ICommDlgBrowser3_fnIncludeObject(ICommDlgBrowser3 *iface,
3702
IShellView *shv, LPCITEMIDLIST pidl)
3703
{
3704
FileDialogImpl *This = impl_from_ICommDlgBrowser3(iface);
3705
IShellItem *psi;
3706
LPWSTR filename;
3707
LPITEMIDLIST parent_pidl;
3708
HRESULT hr;
3709
ULONG attr;
3710
TRACE("%p (%p, %p)\n", This, shv, pidl);
3711
3712
if(!This->current_filter && !(This->options & FOS_PICKFOLDERS))
3713
return S_OK;
3714
3715
hr = SHGetIDListFromObject((IUnknown*)shv, &parent_pidl);
3716
if(SUCCEEDED(hr))
3717
{
3718
LPITEMIDLIST full_pidl = ILCombine(parent_pidl, pidl);
3719
hr = SHCreateItemFromIDList(full_pidl, &IID_IShellItem, (void**)&psi);
3720
ILFree(parent_pidl);
3721
ILFree(full_pidl);
3722
}
3723
if(FAILED(hr))
3724
{
3725
ERR("Failed to get shellitem (%08lx).\n", hr);
3726
return S_OK;
3727
}
3728
3729
hr = IShellItem_GetAttributes(psi, SFGAO_FOLDER|SFGAO_LINK, &attr);
3730
if(FAILED(hr) || (attr & (SFGAO_FOLDER | SFGAO_LINK)))
3731
{
3732
IShellItem_Release(psi);
3733
return S_OK;
3734
}
3735
3736
if((This->options & FOS_PICKFOLDERS) && !(attr & (SFGAO_FOLDER | SFGAO_LINK)))
3737
{
3738
IShellItem_Release(psi);
3739
return S_FALSE;
3740
}
3741
3742
hr = S_OK;
3743
if(SUCCEEDED(IShellItem_GetDisplayName(psi, SIGDN_PARENTRELATIVEPARSING, &filename)))
3744
{
3745
if(!PathMatchSpecW(filename, This->current_filter))
3746
hr = S_FALSE;
3747
CoTaskMemFree(filename);
3748
}
3749
3750
IShellItem_Release(psi);
3751
return hr;
3752
}
3753
3754
static HRESULT WINAPI ICommDlgBrowser3_fnNotify(ICommDlgBrowser3 *iface,
3755
IShellView *ppshv, DWORD dwNotifyType)
3756
{
3757
FileDialogImpl *This = impl_from_ICommDlgBrowser3(iface);
3758
FIXME("Stub: %p (%p, 0x%lx)\n", This, ppshv, dwNotifyType);
3759
return E_NOTIMPL;
3760
}
3761
3762
static HRESULT WINAPI ICommDlgBrowser3_fnGetDefaultMenuText(ICommDlgBrowser3 *iface,
3763
IShellView *pshv,
3764
LPWSTR pszText, int cchMax)
3765
{
3766
FileDialogImpl *This = impl_from_ICommDlgBrowser3(iface);
3767
FIXME("Stub: %p (%p, %p, %d)\n", This, pshv, pszText, cchMax);
3768
return E_NOTIMPL;
3769
}
3770
3771
static HRESULT WINAPI ICommDlgBrowser3_fnGetViewFlags(ICommDlgBrowser3 *iface, DWORD *pdwFlags)
3772
{
3773
FileDialogImpl *This = impl_from_ICommDlgBrowser3(iface);
3774
FIXME("Stub: %p (%p)\n", This, pdwFlags);
3775
return E_NOTIMPL;
3776
}
3777
3778
static HRESULT WINAPI ICommDlgBrowser3_fnOnColumnClicked(ICommDlgBrowser3 *iface,
3779
IShellView *pshv, int iColumn)
3780
{
3781
FileDialogImpl *This = impl_from_ICommDlgBrowser3(iface);
3782
FIXME("Stub: %p (%p, %d)\n", This, pshv, iColumn);
3783
return E_NOTIMPL;
3784
}
3785
3786
static HRESULT WINAPI ICommDlgBrowser3_fnGetCurrentFilter(ICommDlgBrowser3 *iface,
3787
LPWSTR pszFileSpec, int cchFileSpec)
3788
{
3789
FileDialogImpl *This = impl_from_ICommDlgBrowser3(iface);
3790
FIXME("Stub: %p (%p, %d)\n", This, pszFileSpec, cchFileSpec);
3791
return E_NOTIMPL;
3792
}
3793
3794
static HRESULT WINAPI ICommDlgBrowser3_fnOnPreviewCreated(ICommDlgBrowser3 *iface,
3795
IShellView *pshv)
3796
{
3797
FileDialogImpl *This = impl_from_ICommDlgBrowser3(iface);
3798
FIXME("Stub: %p (%p)\n", This, pshv);
3799
return E_NOTIMPL;
3800
}
3801
3802
static const ICommDlgBrowser3Vtbl vt_ICommDlgBrowser3 = {
3803
ICommDlgBrowser3_fnQueryInterface,
3804
ICommDlgBrowser3_fnAddRef,
3805
ICommDlgBrowser3_fnRelease,
3806
ICommDlgBrowser3_fnOnDefaultCommand,
3807
ICommDlgBrowser3_fnOnStateChange,
3808
ICommDlgBrowser3_fnIncludeObject,
3809
ICommDlgBrowser3_fnNotify,
3810
ICommDlgBrowser3_fnGetDefaultMenuText,
3811
ICommDlgBrowser3_fnGetViewFlags,
3812
ICommDlgBrowser3_fnOnColumnClicked,
3813
ICommDlgBrowser3_fnGetCurrentFilter,
3814
ICommDlgBrowser3_fnOnPreviewCreated
3815
};
3816
3817
/**************************************************************************
3818
* IOleWindow implementation
3819
*/
3820
static inline FileDialogImpl *impl_from_IOleWindow(IOleWindow *iface)
3821
{
3822
return CONTAINING_RECORD(iface, FileDialogImpl, IOleWindow_iface);
3823
}
3824
3825
static HRESULT WINAPI IOleWindow_fnQueryInterface(IOleWindow *iface, REFIID riid, void **ppvObject)
3826
{
3827
FileDialogImpl *This = impl_from_IOleWindow(iface);
3828
return IFileDialog2_QueryInterface(&This->IFileDialog2_iface, riid, ppvObject);
3829
}
3830
3831
static ULONG WINAPI IOleWindow_fnAddRef(IOleWindow *iface)
3832
{
3833
FileDialogImpl *This = impl_from_IOleWindow(iface);
3834
return IFileDialog2_AddRef(&This->IFileDialog2_iface);
3835
}
3836
3837
static ULONG WINAPI IOleWindow_fnRelease(IOleWindow *iface)
3838
{
3839
FileDialogImpl *This = impl_from_IOleWindow(iface);
3840
return IFileDialog2_Release(&This->IFileDialog2_iface);
3841
}
3842
3843
static HRESULT WINAPI IOleWindow_fnContextSensitiveHelp(IOleWindow *iface, BOOL fEnterMOde)
3844
{
3845
FileDialogImpl *This = impl_from_IOleWindow(iface);
3846
FIXME("Stub: %p (%d)\n", This, fEnterMOde);
3847
return E_NOTIMPL;
3848
}
3849
3850
static HRESULT WINAPI IOleWindow_fnGetWindow(IOleWindow *iface, HWND *phwnd)
3851
{
3852
FileDialogImpl *This = impl_from_IOleWindow(iface);
3853
TRACE("%p (%p)\n", This, phwnd);
3854
*phwnd = This->dlg_hwnd;
3855
return S_OK;
3856
}
3857
3858
static const IOleWindowVtbl vt_IOleWindow = {
3859
IOleWindow_fnQueryInterface,
3860
IOleWindow_fnAddRef,
3861
IOleWindow_fnRelease,
3862
IOleWindow_fnGetWindow,
3863
IOleWindow_fnContextSensitiveHelp
3864
};
3865
3866
/**************************************************************************
3867
* IFileDialogCustomize implementation
3868
*/
3869
static inline FileDialogImpl *impl_from_IFileDialogCustomize(IFileDialogCustomize *iface)
3870
{
3871
return CONTAINING_RECORD(iface, FileDialogImpl, IFileDialogCustomize_iface);
3872
}
3873
3874
static HRESULT WINAPI IFileDialogCustomize_fnQueryInterface(IFileDialogCustomize *iface,
3875
REFIID riid, void **ppvObject)
3876
{
3877
FileDialogImpl *This = impl_from_IFileDialogCustomize(iface);
3878
return IFileDialog2_QueryInterface(&This->IFileDialog2_iface, riid, ppvObject);
3879
}
3880
3881
static ULONG WINAPI IFileDialogCustomize_fnAddRef(IFileDialogCustomize *iface)
3882
{
3883
FileDialogImpl *This = impl_from_IFileDialogCustomize(iface);
3884
return IFileDialog2_AddRef(&This->IFileDialog2_iface);
3885
}
3886
3887
static ULONG WINAPI IFileDialogCustomize_fnRelease(IFileDialogCustomize *iface)
3888
{
3889
FileDialogImpl *This = impl_from_IFileDialogCustomize(iface);
3890
return IFileDialog2_Release(&This->IFileDialog2_iface);
3891
}
3892
3893
static HRESULT WINAPI IFileDialogCustomize_fnEnableOpenDropDown(IFileDialogCustomize *iface,
3894
DWORD dwIDCtl)
3895
{
3896
FileDialogImpl *This = impl_from_IFileDialogCustomize(iface);
3897
MENUINFO mi;
3898
TRACE("%p (%ld)\n", This, dwIDCtl);
3899
3900
if (This->hmenu_opendropdown || get_cctrl(This, dwIDCtl))
3901
return E_UNEXPECTED;
3902
3903
This->hmenu_opendropdown = CreatePopupMenu();
3904
3905
if (!This->hmenu_opendropdown)
3906
return E_OUTOFMEMORY;
3907
3908
mi.cbSize = sizeof(mi);
3909
mi.fMask = MIM_STYLE;
3910
mi.dwStyle = MNS_NOTIFYBYPOS;
3911
SetMenuInfo(This->hmenu_opendropdown, &mi);
3912
3913
This->cctrl_opendropdown.hwnd = NULL;
3914
This->cctrl_opendropdown.wrapper_hwnd = NULL;
3915
This->cctrl_opendropdown.id = dwIDCtl;
3916
This->cctrl_opendropdown.dlgid = 0;
3917
This->cctrl_opendropdown.type = IDLG_CCTRL_OPENDROPDOWN;
3918
This->cctrl_opendropdown.cdcstate = CDCS_ENABLED | CDCS_VISIBLE;
3919
list_init(&This->cctrl_opendropdown.sub_cctrls);
3920
list_init(&This->cctrl_opendropdown.sub_items);
3921
3922
return S_OK;
3923
}
3924
3925
static HRESULT WINAPI IFileDialogCustomize_fnAddMenu(IFileDialogCustomize *iface,
3926
DWORD dwIDCtl,
3927
LPCWSTR pszLabel)
3928
{
3929
FileDialogImpl *This = impl_from_IFileDialogCustomize(iface);
3930
customctrl *ctrl;
3931
TBBUTTON tbb;
3932
HRESULT hr;
3933
TRACE("%p (%ld, %p)\n", This, dwIDCtl, pszLabel);
3934
3935
hr = cctrl_create_new(This, dwIDCtl, NULL, TOOLBARCLASSNAMEW,
3936
TBSTYLE_FLAT | CCS_NODIVIDER, 0,
3937
This->cctrl_def_height, &ctrl);
3938
if(SUCCEEDED(hr))
3939
{
3940
SendMessageW(ctrl->hwnd, TB_BUTTONSTRUCTSIZE, sizeof(tbb), 0);
3941
ctrl->type = IDLG_CCTRL_MENU;
3942
3943
/* Add the actual button with a popup menu. */
3944
tbb.iBitmap = I_IMAGENONE;
3945
tbb.dwData = (DWORD_PTR)CreatePopupMenu();
3946
tbb.iString = (DWORD_PTR)pszLabel;
3947
tbb.fsState = TBSTATE_ENABLED;
3948
tbb.fsStyle = BTNS_WHOLEDROPDOWN;
3949
tbb.idCommand = 1;
3950
3951
SendMessageW(ctrl->hwnd, TB_ADDBUTTONSW, 1, (LPARAM)&tbb);
3952
}
3953
3954
return hr;
3955
}
3956
3957
static HRESULT WINAPI IFileDialogCustomize_fnAddPushButton(IFileDialogCustomize *iface,
3958
DWORD dwIDCtl,
3959
LPCWSTR pszLabel)
3960
{
3961
FileDialogImpl *This = impl_from_IFileDialogCustomize(iface);
3962
customctrl *ctrl;
3963
HRESULT hr;
3964
TRACE("%p (%ld, %p)\n", This, dwIDCtl, pszLabel);
3965
3966
hr = cctrl_create_new(This, dwIDCtl, pszLabel, WC_BUTTONW, BS_MULTILINE, 0,
3967
This->cctrl_def_height, &ctrl);
3968
if(SUCCEEDED(hr))
3969
ctrl->type = IDLG_CCTRL_PUSHBUTTON;
3970
3971
return hr;
3972
}
3973
3974
static HRESULT WINAPI IFileDialogCustomize_fnAddComboBox(IFileDialogCustomize *iface,
3975
DWORD dwIDCtl)
3976
{
3977
FileDialogImpl *This = impl_from_IFileDialogCustomize(iface);
3978
customctrl *ctrl;
3979
HRESULT hr;
3980
TRACE("%p (%ld)\n", This, dwIDCtl);
3981
3982
hr = cctrl_create_new(This, dwIDCtl, NULL, WC_COMBOBOXW, CBS_DROPDOWNLIST, 0,
3983
This->cctrl_def_height, &ctrl);
3984
if(SUCCEEDED(hr))
3985
ctrl->type = IDLG_CCTRL_COMBOBOX;
3986
3987
return hr;
3988
}
3989
3990
static HRESULT WINAPI IFileDialogCustomize_fnAddRadioButtonList(IFileDialogCustomize *iface,
3991
DWORD dwIDCtl)
3992
{
3993
FileDialogImpl *This = impl_from_IFileDialogCustomize(iface);
3994
customctrl *ctrl;
3995
HRESULT hr;
3996
TRACE("%p (%ld)\n", This, dwIDCtl);
3997
3998
hr = cctrl_create_new(This, dwIDCtl, NULL, L"RadioButtonList", 0, 0, 0, &ctrl);
3999
if(SUCCEEDED(hr))
4000
{
4001
ctrl->type = IDLG_CCTRL_RADIOBUTTONLIST;
4002
SetWindowLongPtrW(ctrl->hwnd, GWLP_USERDATA, (LPARAM)This);
4003
}
4004
4005
return hr;
4006
}
4007
4008
static HRESULT WINAPI IFileDialogCustomize_fnAddCheckButton(IFileDialogCustomize *iface,
4009
DWORD dwIDCtl,
4010
LPCWSTR pszLabel,
4011
BOOL bChecked)
4012
{
4013
FileDialogImpl *This = impl_from_IFileDialogCustomize(iface);
4014
customctrl *ctrl;
4015
HRESULT hr;
4016
TRACE("%p (%ld, %p, %d)\n", This, dwIDCtl, pszLabel, bChecked);
4017
4018
hr = cctrl_create_new(This, dwIDCtl, pszLabel, WC_BUTTONW, BS_AUTOCHECKBOX|BS_MULTILINE, 0,
4019
This->cctrl_def_height, &ctrl);
4020
if(SUCCEEDED(hr))
4021
{
4022
ctrl->type = IDLG_CCTRL_CHECKBUTTON;
4023
SendMessageW(ctrl->hwnd, BM_SETCHECK, bChecked ? BST_CHECKED : BST_UNCHECKED, 0);
4024
}
4025
4026
return hr;
4027
}
4028
4029
static HRESULT WINAPI IFileDialogCustomize_fnAddEditBox(IFileDialogCustomize *iface,
4030
DWORD dwIDCtl,
4031
LPCWSTR pszText)
4032
{
4033
FileDialogImpl *This = impl_from_IFileDialogCustomize(iface);
4034
customctrl *ctrl;
4035
HRESULT hr;
4036
TRACE("%p (%ld, %p)\n", This, dwIDCtl, pszText);
4037
4038
hr = cctrl_create_new(This, dwIDCtl, pszText, WC_EDITW, ES_AUTOHSCROLL, WS_EX_CLIENTEDGE,
4039
This->cctrl_def_height, &ctrl);
4040
if(SUCCEEDED(hr))
4041
ctrl->type = IDLG_CCTRL_EDITBOX;
4042
4043
return hr;
4044
}
4045
4046
static HRESULT WINAPI IFileDialogCustomize_fnAddSeparator(IFileDialogCustomize *iface,
4047
DWORD dwIDCtl)
4048
{
4049
FileDialogImpl *This = impl_from_IFileDialogCustomize(iface);
4050
customctrl *ctrl;
4051
HRESULT hr;
4052
TRACE("%p (%ld)\n", This, dwIDCtl);
4053
4054
hr = cctrl_create_new(This, dwIDCtl, NULL, WC_STATICW, SS_ETCHEDHORZ, 0,
4055
GetSystemMetrics(SM_CYEDGE), &ctrl);
4056
if(SUCCEEDED(hr))
4057
ctrl->type = IDLG_CCTRL_SEPARATOR;
4058
4059
return hr;
4060
}
4061
4062
static HRESULT WINAPI IFileDialogCustomize_fnAddText(IFileDialogCustomize *iface,
4063
DWORD dwIDCtl,
4064
LPCWSTR pszText)
4065
{
4066
FileDialogImpl *This = impl_from_IFileDialogCustomize(iface);
4067
customctrl *ctrl;
4068
HRESULT hr;
4069
TRACE("%p (%ld, %p)\n", This, dwIDCtl, pszText);
4070
4071
hr = cctrl_create_new(This, dwIDCtl, pszText, WC_STATICW, 0, 0,
4072
This->cctrl_def_height, &ctrl);
4073
if(SUCCEEDED(hr))
4074
ctrl->type = IDLG_CCTRL_TEXT;
4075
4076
return hr;
4077
}
4078
4079
static HRESULT WINAPI IFileDialogCustomize_fnSetControlLabel(IFileDialogCustomize *iface,
4080
DWORD dwIDCtl,
4081
LPCWSTR pszLabel)
4082
{
4083
FileDialogImpl *This = impl_from_IFileDialogCustomize(iface);
4084
customctrl *ctrl = get_cctrl(This, dwIDCtl);
4085
TRACE("%p (%ld, %p)\n", This, dwIDCtl, pszLabel);
4086
4087
if(!ctrl) return E_INVALIDARG;
4088
4089
switch(ctrl->type)
4090
{
4091
case IDLG_CCTRL_MENU:
4092
case IDLG_CCTRL_PUSHBUTTON:
4093
case IDLG_CCTRL_CHECKBUTTON:
4094
case IDLG_CCTRL_TEXT:
4095
case IDLG_CCTRL_VISUALGROUP:
4096
SendMessageW(ctrl->hwnd, WM_SETTEXT, 0, (LPARAM)pszLabel);
4097
break;
4098
case IDLG_CCTRL_OPENDROPDOWN:
4099
return E_NOTIMPL;
4100
default:
4101
break;
4102
}
4103
4104
return S_OK;
4105
}
4106
4107
static HRESULT WINAPI IFileDialogCustomize_fnGetControlState(IFileDialogCustomize *iface,
4108
DWORD dwIDCtl,
4109
CDCONTROLSTATEF *pdwState)
4110
{
4111
FileDialogImpl *This = impl_from_IFileDialogCustomize(iface);
4112
customctrl *ctrl = get_cctrl(This, dwIDCtl);
4113
TRACE("%p (%ld, %p)\n", This, dwIDCtl, pdwState);
4114
4115
if(!ctrl || ctrl->type == IDLG_CCTRL_OPENDROPDOWN) return E_NOTIMPL;
4116
4117
*pdwState = ctrl->cdcstate;
4118
return S_OK;
4119
}
4120
4121
static HRESULT WINAPI IFileDialogCustomize_fnSetControlState(IFileDialogCustomize *iface,
4122
DWORD dwIDCtl,
4123
CDCONTROLSTATEF dwState)
4124
{
4125
FileDialogImpl *This = impl_from_IFileDialogCustomize(iface);
4126
customctrl *ctrl = get_cctrl(This,dwIDCtl);
4127
TRACE("%p (%ld, %x)\n", This, dwIDCtl, dwState);
4128
4129
if(ctrl && ctrl->hwnd)
4130
{
4131
LONG wndstyle = GetWindowLongW(ctrl->hwnd, GWL_STYLE);
4132
4133
if(dwState & CDCS_ENABLED)
4134
wndstyle &= ~(WS_DISABLED);
4135
else
4136
wndstyle |= WS_DISABLED;
4137
4138
if(dwState & CDCS_VISIBLE)
4139
wndstyle |= WS_VISIBLE;
4140
else
4141
wndstyle &= ~(WS_VISIBLE);
4142
4143
SetWindowLongW(ctrl->hwnd, GWL_STYLE, wndstyle);
4144
4145
/* We save the state separately since at least one application
4146
* relies on being able to hide a control. */
4147
ctrl->cdcstate = dwState;
4148
}
4149
4150
return S_OK;
4151
}
4152
4153
static HRESULT WINAPI IFileDialogCustomize_fnGetEditBoxText(IFileDialogCustomize *iface,
4154
DWORD dwIDCtl,
4155
WCHAR **ppszText)
4156
{
4157
FileDialogImpl *This = impl_from_IFileDialogCustomize(iface);
4158
customctrl *ctrl = get_cctrl(This, dwIDCtl);
4159
WCHAR len, *text;
4160
TRACE("%p (%ld, %p)\n", This, dwIDCtl, ppszText);
4161
4162
if(!ctrl || !ctrl->hwnd || !(len = SendMessageW(ctrl->hwnd, WM_GETTEXTLENGTH, 0, 0)))
4163
return E_FAIL;
4164
4165
text = CoTaskMemAlloc(sizeof(WCHAR)*(len+1));
4166
if(!text) return E_FAIL;
4167
4168
SendMessageW(ctrl->hwnd, WM_GETTEXT, len+1, (LPARAM)text);
4169
*ppszText = text;
4170
return S_OK;
4171
}
4172
4173
static HRESULT WINAPI IFileDialogCustomize_fnSetEditBoxText(IFileDialogCustomize *iface,
4174
DWORD dwIDCtl,
4175
LPCWSTR pszText)
4176
{
4177
FileDialogImpl *This = impl_from_IFileDialogCustomize(iface);
4178
customctrl *ctrl = get_cctrl(This, dwIDCtl);
4179
TRACE("%p (%ld, %s)\n", This, dwIDCtl, debugstr_w(pszText));
4180
4181
if(!ctrl || ctrl->type != IDLG_CCTRL_EDITBOX)
4182
return E_FAIL;
4183
4184
SendMessageW(ctrl->hwnd, WM_SETTEXT, 0, (LPARAM)pszText);
4185
return S_OK;
4186
}
4187
4188
static HRESULT WINAPI IFileDialogCustomize_fnGetCheckButtonState(IFileDialogCustomize *iface,
4189
DWORD dwIDCtl,
4190
BOOL *pbChecked)
4191
{
4192
FileDialogImpl *This = impl_from_IFileDialogCustomize(iface);
4193
customctrl *ctrl = get_cctrl(This, dwIDCtl);
4194
TRACE("%p (%ld, %p)\n", This, dwIDCtl, pbChecked);
4195
4196
if(ctrl && ctrl->hwnd)
4197
*pbChecked = (SendMessageW(ctrl->hwnd, BM_GETCHECK, 0, 0) == BST_CHECKED);
4198
4199
return S_OK;
4200
}
4201
4202
static HRESULT WINAPI IFileDialogCustomize_fnSetCheckButtonState(IFileDialogCustomize *iface,
4203
DWORD dwIDCtl,
4204
BOOL bChecked)
4205
{
4206
FileDialogImpl *This = impl_from_IFileDialogCustomize(iface);
4207
customctrl *ctrl = get_cctrl(This, dwIDCtl);
4208
TRACE("%p (%ld, %d)\n", This, dwIDCtl, bChecked);
4209
4210
if(ctrl && ctrl->hwnd)
4211
SendMessageW(ctrl->hwnd, BM_SETCHECK, bChecked ? BST_CHECKED:BST_UNCHECKED, 0);
4212
4213
return S_OK;
4214
}
4215
4216
static UINT get_combobox_index_from_id(HWND cb_hwnd, DWORD dwIDItem)
4217
{
4218
UINT count = SendMessageW(cb_hwnd, CB_GETCOUNT, 0, 0);
4219
UINT i;
4220
if(!count || (count == CB_ERR))
4221
return -1;
4222
4223
for(i = 0; i < count; i++)
4224
if(SendMessageW(cb_hwnd, CB_GETITEMDATA, i, 0) == dwIDItem)
4225
return i;
4226
4227
TRACE("Item with id %ld not found in combobox %p (item count: %d)\n", dwIDItem, cb_hwnd, count);
4228
return -1;
4229
}
4230
4231
static HRESULT WINAPI IFileDialogCustomize_fnAddControlItem(IFileDialogCustomize *iface,
4232
DWORD dwIDCtl,
4233
DWORD dwIDItem,
4234
LPCWSTR pszLabel)
4235
{
4236
FileDialogImpl *This = impl_from_IFileDialogCustomize(iface);
4237
customctrl *ctrl = get_cctrl(This, dwIDCtl);
4238
HRESULT hr;
4239
TRACE("%p (%ld, %ld, %s)\n", This, dwIDCtl, dwIDItem, debugstr_w(pszLabel));
4240
4241
if(!ctrl) return E_FAIL;
4242
4243
switch(ctrl->type)
4244
{
4245
case IDLG_CCTRL_COMBOBOX:
4246
{
4247
UINT index;
4248
cctrl_item* item;
4249
4250
hr = add_item(ctrl, dwIDItem, pszLabel, &item);
4251
4252
if (FAILED(hr)) return hr;
4253
4254
index = SendMessageW(ctrl->hwnd, CB_ADDSTRING, 0, (LPARAM)pszLabel);
4255
SendMessageW(ctrl->hwnd, CB_SETITEMDATA, index, dwIDItem);
4256
4257
return S_OK;
4258
}
4259
case IDLG_CCTRL_MENU:
4260
case IDLG_CCTRL_OPENDROPDOWN:
4261
{
4262
cctrl_item* item;
4263
HMENU hmenu;
4264
4265
hr = add_item(ctrl, dwIDItem, pszLabel, &item);
4266
4267
if (FAILED(hr)) return hr;
4268
4269
if (ctrl->type == IDLG_CCTRL_MENU)
4270
{
4271
TBBUTTON tbb;
4272
SendMessageW(ctrl->hwnd, TB_GETBUTTON, 0, (LPARAM)&tbb);
4273
hmenu = (HMENU)tbb.dwData;
4274
}
4275
else /* ctrl->type == IDLG_CCTRL_OPENDROPDOWN */
4276
hmenu = This->hmenu_opendropdown;
4277
4278
AppendMenuW(hmenu, MF_STRING, dwIDItem, pszLabel);
4279
return S_OK;
4280
}
4281
case IDLG_CCTRL_RADIOBUTTONLIST:
4282
{
4283
cctrl_item* item;
4284
4285
hr = add_item(ctrl, dwIDItem, pszLabel, &item);
4286
4287
if (SUCCEEDED(hr))
4288
{
4289
item->hwnd = CreateWindowExW(0, WC_BUTTONW, pszLabel,
4290
WS_CHILD|WS_VISIBLE|WS_CLIPSIBLINGS|BS_RADIOBUTTON|BS_MULTILINE,
4291
0, 0, 0, 0, ctrl->hwnd, ULongToHandle(dwIDItem), COMDLG32_hInstance, 0);
4292
4293
if (!item->hwnd)
4294
{
4295
ERR("Failed to create radio button\n");
4296
list_remove(&item->entry);
4297
item_free(item);
4298
return E_FAIL;
4299
}
4300
}
4301
4302
return hr;
4303
}
4304
default:
4305
break;
4306
}
4307
4308
return E_NOINTERFACE; /* win7 */
4309
}
4310
4311
static HRESULT WINAPI IFileDialogCustomize_fnRemoveControlItem(IFileDialogCustomize *iface,
4312
DWORD dwIDCtl,
4313
DWORD dwIDItem)
4314
{
4315
FileDialogImpl *This = impl_from_IFileDialogCustomize(iface);
4316
customctrl *ctrl = get_cctrl(This, dwIDCtl);
4317
TRACE("%p (%ld, %ld)\n", This, dwIDCtl, dwIDItem);
4318
4319
if(!ctrl) return E_FAIL;
4320
4321
switch(ctrl->type)
4322
{
4323
case IDLG_CCTRL_COMBOBOX:
4324
{
4325
cctrl_item* item;
4326
DWORD position;
4327
4328
item = get_item(ctrl, dwIDItem, CDCS_VISIBLE|CDCS_ENABLED, &position);
4329
4330
if (!item)
4331
return E_INVALIDARG;
4332
4333
if ((item->cdcstate & (CDCS_VISIBLE|CDCS_ENABLED)) == (CDCS_VISIBLE|CDCS_ENABLED))
4334
{
4335
if(SendMessageW(ctrl->hwnd, CB_DELETESTRING, position, 0) == CB_ERR)
4336
return E_FAIL;
4337
}
4338
4339
list_remove(&item->entry);
4340
item_free(item);
4341
4342
return S_OK;
4343
}
4344
case IDLG_CCTRL_MENU:
4345
case IDLG_CCTRL_OPENDROPDOWN:
4346
{
4347
HMENU hmenu;
4348
cctrl_item* item;
4349
4350
item = get_item(ctrl, dwIDItem, 0, NULL);
4351
4352
if (!item)
4353
return E_UNEXPECTED;
4354
4355
if (item->cdcstate & CDCS_VISIBLE)
4356
{
4357
if (ctrl->type == IDLG_CCTRL_MENU)
4358
{
4359
TBBUTTON tbb;
4360
SendMessageW(ctrl->hwnd, TB_GETBUTTON, 0, (LPARAM)&tbb);
4361
hmenu = (HMENU)tbb.dwData;
4362
}
4363
else /* ctrl->type == IDLG_CCTRL_OPENDROPDOWN */
4364
hmenu = This->hmenu_opendropdown;
4365
4366
if(!hmenu || !DeleteMenu(hmenu, dwIDItem, MF_BYCOMMAND))
4367
return E_UNEXPECTED;
4368
}
4369
4370
list_remove(&item->entry);
4371
item_free(item);
4372
4373
return S_OK;
4374
}
4375
case IDLG_CCTRL_RADIOBUTTONLIST:
4376
{
4377
cctrl_item* item;
4378
4379
item = get_item(ctrl, dwIDItem, 0, NULL);
4380
4381
if (!item)
4382
return E_UNEXPECTED;
4383
4384
list_remove(&item->entry);
4385
item_free(item);
4386
4387
return S_OK;
4388
}
4389
default:
4390
break;
4391
}
4392
4393
return E_FAIL;
4394
}
4395
4396
static HRESULT WINAPI IFileDialogCustomize_fnRemoveAllControlItems(IFileDialogCustomize *iface,
4397
DWORD dwIDCtl)
4398
{
4399
FileDialogImpl *This = impl_from_IFileDialogCustomize(iface);
4400
TRACE("%p (%ld)\n", This, dwIDCtl);
4401
4402
/* Not implemented by native */
4403
return E_NOTIMPL;
4404
}
4405
4406
static HRESULT WINAPI IFileDialogCustomize_fnGetControlItemState(IFileDialogCustomize *iface,
4407
DWORD dwIDCtl,
4408
DWORD dwIDItem,
4409
CDCONTROLSTATEF *pdwState)
4410
{
4411
FileDialogImpl *This = impl_from_IFileDialogCustomize(iface);
4412
customctrl *ctrl = get_cctrl(This, dwIDCtl);
4413
TRACE("%p (%ld, %ld, %p)\n", This, dwIDCtl, dwIDItem, pdwState);
4414
4415
if(!ctrl) return E_FAIL;
4416
4417
switch(ctrl->type)
4418
{
4419
case IDLG_CCTRL_COMBOBOX:
4420
case IDLG_CCTRL_MENU:
4421
case IDLG_CCTRL_OPENDROPDOWN:
4422
case IDLG_CCTRL_RADIOBUTTONLIST:
4423
{
4424
cctrl_item* item;
4425
4426
item = get_item(ctrl, dwIDItem, 0, NULL);
4427
4428
if (!item)
4429
return E_UNEXPECTED;
4430
4431
*pdwState = item->cdcstate;
4432
4433
return S_OK;
4434
}
4435
default:
4436
break;
4437
}
4438
4439
return E_FAIL;
4440
}
4441
4442
static HRESULT WINAPI IFileDialogCustomize_fnSetControlItemState(IFileDialogCustomize *iface,
4443
DWORD dwIDCtl,
4444
DWORD dwIDItem,
4445
CDCONTROLSTATEF dwState)
4446
{
4447
FileDialogImpl *This = impl_from_IFileDialogCustomize(iface);
4448
customctrl *ctrl = get_cctrl(This, dwIDCtl);
4449
TRACE("%p (%ld, %ld, %x)\n", This, dwIDCtl, dwIDItem, dwState);
4450
4451
if(!ctrl) return E_FAIL;
4452
4453
switch(ctrl->type)
4454
{
4455
case IDLG_CCTRL_COMBOBOX:
4456
{
4457
cctrl_item* item;
4458
BOOL visible, was_visible;
4459
DWORD position;
4460
4461
item = get_item(ctrl, dwIDItem, CDCS_VISIBLE|CDCS_ENABLED, &position);
4462
4463
if (!item)
4464
return E_UNEXPECTED;
4465
4466
visible = ((dwState & (CDCS_VISIBLE|CDCS_ENABLED)) == (CDCS_VISIBLE|CDCS_ENABLED));
4467
was_visible = ((item->cdcstate & (CDCS_VISIBLE|CDCS_ENABLED)) == (CDCS_VISIBLE|CDCS_ENABLED));
4468
4469
if (visible && !was_visible)
4470
{
4471
SendMessageW(ctrl->hwnd, CB_INSERTSTRING, position, (LPARAM)item->label);
4472
SendMessageW(ctrl->hwnd, CB_SETITEMDATA, position, dwIDItem);
4473
}
4474
else if (!visible && was_visible)
4475
{
4476
SendMessageW(ctrl->hwnd, CB_DELETESTRING, position, 0);
4477
}
4478
4479
item->cdcstate = dwState;
4480
4481
return S_OK;
4482
}
4483
case IDLG_CCTRL_MENU:
4484
case IDLG_CCTRL_OPENDROPDOWN:
4485
{
4486
HMENU hmenu;
4487
cctrl_item* item;
4488
CDCONTROLSTATEF prev_state;
4489
DWORD position;
4490
4491
item = get_item(ctrl, dwIDItem, CDCS_VISIBLE, &position);
4492
4493
if (!item)
4494
return E_UNEXPECTED;
4495
4496
prev_state = item->cdcstate;
4497
4498
if (ctrl->type == IDLG_CCTRL_MENU)
4499
{
4500
TBBUTTON tbb;
4501
SendMessageW(ctrl->hwnd, TB_GETBUTTON, 0, (LPARAM)&tbb);
4502
hmenu = (HMENU)tbb.dwData;
4503
}
4504
else /* ctrl->type == IDLG_CCTRL_OPENDROPDOWN */
4505
hmenu = This->hmenu_opendropdown;
4506
4507
if (dwState & CDCS_VISIBLE)
4508
{
4509
if (prev_state & CDCS_VISIBLE)
4510
{
4511
/* change state */
4512
EnableMenuItem(hmenu, dwIDItem,
4513
MF_BYCOMMAND|((dwState & CDCS_ENABLED) ? MFS_ENABLED : MFS_DISABLED));
4514
}
4515
else
4516
{
4517
/* show item */
4518
MENUITEMINFOW mii;
4519
4520
mii.cbSize = sizeof(mii);
4521
mii.fMask = MIIM_ID|MIIM_STATE|MIIM_STRING;
4522
mii.fState = (dwState & CDCS_ENABLED) ? MFS_ENABLED : MFS_DISABLED;
4523
mii.wID = dwIDItem;
4524
mii.dwTypeData = item->label;
4525
4526
InsertMenuItemW(hmenu, position, TRUE, &mii);
4527
}
4528
}
4529
else if (prev_state & CDCS_VISIBLE)
4530
{
4531
/* hide item */
4532
DeleteMenu(hmenu, dwIDItem, MF_BYCOMMAND);
4533
}
4534
4535
item->cdcstate = dwState;
4536
4537
if (ctrl->type == IDLG_CCTRL_OPENDROPDOWN)
4538
{
4539
update_control_text(This);
4540
update_layout(This);
4541
}
4542
4543
return S_OK;
4544
}
4545
case IDLG_CCTRL_RADIOBUTTONLIST:
4546
{
4547
cctrl_item* item;
4548
4549
item = get_item(ctrl, dwIDItem, CDCS_VISIBLE, NULL);
4550
4551
if (!item)
4552
return E_UNEXPECTED;
4553
4554
/* Oddly, native allows setting this but doesn't seem to do anything with it. */
4555
item->cdcstate = dwState;
4556
4557
return S_OK;
4558
}
4559
default:
4560
break;
4561
}
4562
4563
return E_FAIL;
4564
}
4565
4566
static HRESULT WINAPI IFileDialogCustomize_fnGetSelectedControlItem(IFileDialogCustomize *iface,
4567
DWORD dwIDCtl,
4568
DWORD *pdwIDItem)
4569
{
4570
FileDialogImpl *This = impl_from_IFileDialogCustomize(iface);
4571
customctrl *ctrl = get_cctrl(This, dwIDCtl);
4572
TRACE("%p (%ld, %p)\n", This, dwIDCtl, pdwIDItem);
4573
4574
if(!ctrl) return E_FAIL;
4575
4576
switch(ctrl->type)
4577
{
4578
case IDLG_CCTRL_COMBOBOX:
4579
{
4580
UINT index = SendMessageW(ctrl->hwnd, CB_GETCURSEL, 0, 0);
4581
if(index == CB_ERR)
4582
return E_FAIL;
4583
4584
*pdwIDItem = SendMessageW(ctrl->hwnd, CB_GETITEMDATA, index, 0);
4585
return S_OK;
4586
}
4587
case IDLG_CCTRL_OPENDROPDOWN:
4588
if (This->opendropdown_has_selection)
4589
{
4590
*pdwIDItem = This->opendropdown_selection;
4591
return S_OK;
4592
}
4593
else
4594
{
4595
/* Return first enabled item. */
4596
cctrl_item* item = get_first_item(ctrl);
4597
4598
if (item)
4599
{
4600
*pdwIDItem = item->id;
4601
return S_OK;
4602
}
4603
4604
WARN("no enabled items in open dropdown\n");
4605
return E_FAIL;
4606
}
4607
case IDLG_CCTRL_RADIOBUTTONLIST:
4608
{
4609
cctrl_item* item;
4610
4611
LIST_FOR_EACH_ENTRY(item, &ctrl->sub_items, cctrl_item, entry)
4612
{
4613
if (SendMessageW(item->hwnd, BM_GETCHECK, 0, 0) == BST_CHECKED)
4614
{
4615
*pdwIDItem = item->id;
4616
return S_OK;
4617
}
4618
}
4619
4620
WARN("no checked items in radio button list\n");
4621
return E_FAIL;
4622
}
4623
default:
4624
FIXME("Unsupported control type %d\n", ctrl->type);
4625
}
4626
4627
return E_NOTIMPL;
4628
}
4629
4630
static HRESULT WINAPI IFileDialogCustomize_fnSetSelectedControlItem(IFileDialogCustomize *iface,
4631
DWORD dwIDCtl,
4632
DWORD dwIDItem)
4633
{
4634
FileDialogImpl *This = impl_from_IFileDialogCustomize(iface);
4635
customctrl *ctrl = get_cctrl(This, dwIDCtl);
4636
TRACE("%p (%ld, %ld)\n", This, dwIDCtl, dwIDItem);
4637
4638
if(!ctrl) return E_INVALIDARG;
4639
4640
switch(ctrl->type)
4641
{
4642
case IDLG_CCTRL_COMBOBOX:
4643
{
4644
UINT index = get_combobox_index_from_id(ctrl->hwnd, dwIDItem);
4645
4646
if(index == -1)
4647
return E_INVALIDARG;
4648
4649
if(SendMessageW(ctrl->hwnd, CB_SETCURSEL, index, 0) == CB_ERR)
4650
return E_FAIL;
4651
4652
return S_OK;
4653
}
4654
case IDLG_CCTRL_RADIOBUTTONLIST:
4655
{
4656
cctrl_item* item;
4657
4658
item = get_item(ctrl, dwIDItem, 0, NULL);
4659
4660
if (item)
4661
{
4662
radiobuttonlist_set_selected_item(This, ctrl, item);
4663
return S_OK;
4664
}
4665
4666
return E_INVALIDARG;
4667
}
4668
default:
4669
FIXME("Unsupported control type %d\n", ctrl->type);
4670
}
4671
4672
return E_INVALIDARG;
4673
}
4674
4675
static HRESULT WINAPI IFileDialogCustomize_fnStartVisualGroup(IFileDialogCustomize *iface,
4676
DWORD dwIDCtl,
4677
LPCWSTR pszLabel)
4678
{
4679
FileDialogImpl *This = impl_from_IFileDialogCustomize(iface);
4680
customctrl *vg;
4681
HRESULT hr;
4682
TRACE("%p (%ld, %s)\n", This, dwIDCtl, debugstr_w(pszLabel));
4683
4684
if(This->cctrl_active_vg)
4685
return E_UNEXPECTED;
4686
4687
hr = cctrl_create_new(This, dwIDCtl, pszLabel, WC_STATICW, 0, 0,
4688
This->cctrl_def_height, &vg);
4689
if(SUCCEEDED(hr))
4690
{
4691
vg->type = IDLG_CCTRL_VISUALGROUP;
4692
This->cctrl_active_vg = vg;
4693
}
4694
4695
return hr;
4696
}
4697
4698
static HRESULT WINAPI IFileDialogCustomize_fnEndVisualGroup(IFileDialogCustomize *iface)
4699
{
4700
FileDialogImpl *This = impl_from_IFileDialogCustomize(iface);
4701
TRACE("%p\n", This);
4702
4703
This->cctrl_active_vg = NULL;
4704
4705
return S_OK;
4706
}
4707
4708
static HRESULT WINAPI IFileDialogCustomize_fnMakeProminent(IFileDialogCustomize *iface,
4709
DWORD dwIDCtl)
4710
{
4711
FileDialogImpl *This = impl_from_IFileDialogCustomize(iface);
4712
FIXME("stub - %p (%ld)\n", This, dwIDCtl);
4713
return S_OK;
4714
}
4715
4716
static HRESULT WINAPI IFileDialogCustomize_fnSetControlItemText(IFileDialogCustomize *iface,
4717
DWORD dwIDCtl,
4718
DWORD dwIDItem,
4719
LPCWSTR pszLabel)
4720
{
4721
FileDialogImpl *This = impl_from_IFileDialogCustomize(iface);
4722
FIXME("stub - %p (%ld, %ld, %s)\n", This, dwIDCtl, dwIDItem, debugstr_w(pszLabel));
4723
return E_NOTIMPL;
4724
}
4725
4726
static const IFileDialogCustomizeVtbl vt_IFileDialogCustomize = {
4727
IFileDialogCustomize_fnQueryInterface,
4728
IFileDialogCustomize_fnAddRef,
4729
IFileDialogCustomize_fnRelease,
4730
IFileDialogCustomize_fnEnableOpenDropDown,
4731
IFileDialogCustomize_fnAddMenu,
4732
IFileDialogCustomize_fnAddPushButton,
4733
IFileDialogCustomize_fnAddComboBox,
4734
IFileDialogCustomize_fnAddRadioButtonList,
4735
IFileDialogCustomize_fnAddCheckButton,
4736
IFileDialogCustomize_fnAddEditBox,
4737
IFileDialogCustomize_fnAddSeparator,
4738
IFileDialogCustomize_fnAddText,
4739
IFileDialogCustomize_fnSetControlLabel,
4740
IFileDialogCustomize_fnGetControlState,
4741
IFileDialogCustomize_fnSetControlState,
4742
IFileDialogCustomize_fnGetEditBoxText,
4743
IFileDialogCustomize_fnSetEditBoxText,
4744
IFileDialogCustomize_fnGetCheckButtonState,
4745
IFileDialogCustomize_fnSetCheckButtonState,
4746
IFileDialogCustomize_fnAddControlItem,
4747
IFileDialogCustomize_fnRemoveControlItem,
4748
IFileDialogCustomize_fnRemoveAllControlItems,
4749
IFileDialogCustomize_fnGetControlItemState,
4750
IFileDialogCustomize_fnSetControlItemState,
4751
IFileDialogCustomize_fnGetSelectedControlItem,
4752
IFileDialogCustomize_fnSetSelectedControlItem,
4753
IFileDialogCustomize_fnStartVisualGroup,
4754
IFileDialogCustomize_fnEndVisualGroup,
4755
IFileDialogCustomize_fnMakeProminent,
4756
IFileDialogCustomize_fnSetControlItemText
4757
};
4758
4759
static HRESULT FileDialog_constructor(IUnknown *pUnkOuter, REFIID riid, void **ppv, enum ITEMDLG_TYPE type)
4760
{
4761
FileDialogImpl *fdimpl;
4762
HRESULT hr;
4763
IShellFolder *psf;
4764
TRACE("%p, %s, %p\n", pUnkOuter, debugstr_guid(riid), ppv);
4765
4766
if(!ppv)
4767
return E_POINTER;
4768
if(pUnkOuter)
4769
return CLASS_E_NOAGGREGATION;
4770
4771
fdimpl = calloc(1, sizeof(FileDialogImpl));
4772
if(!fdimpl)
4773
return E_OUTOFMEMORY;
4774
4775
fdimpl->ref = 1;
4776
fdimpl->IFileDialog2_iface.lpVtbl = &vt_IFileDialog2;
4777
fdimpl->IExplorerBrowserEvents_iface.lpVtbl = &vt_IExplorerBrowserEvents;
4778
fdimpl->IServiceProvider_iface.lpVtbl = &vt_IServiceProvider;
4779
fdimpl->ICommDlgBrowser3_iface.lpVtbl = &vt_ICommDlgBrowser3;
4780
fdimpl->IOleWindow_iface.lpVtbl = &vt_IOleWindow;
4781
fdimpl->IFileDialogCustomize_iface.lpVtbl = &vt_IFileDialogCustomize;
4782
4783
if(type == ITEMDLG_TYPE_OPEN)
4784
{
4785
fdimpl->dlg_type = ITEMDLG_TYPE_OPEN;
4786
fdimpl->u.IFileOpenDialog_iface.lpVtbl = &vt_IFileOpenDialog;
4787
fdimpl->options = FOS_PATHMUSTEXIST | FOS_FILEMUSTEXIST | FOS_NOCHANGEDIR;
4788
fdimpl->custom_title = fdimpl->custom_okbutton = NULL;
4789
}
4790
else
4791
{
4792
WCHAR buf[16];
4793
fdimpl->dlg_type = ITEMDLG_TYPE_SAVE;
4794
fdimpl->u.IFileSaveDialog_iface.lpVtbl = &vt_IFileSaveDialog;
4795
fdimpl->options = FOS_OVERWRITEPROMPT | FOS_NOREADONLYRETURN | FOS_PATHMUSTEXIST | FOS_NOCHANGEDIR;
4796
4797
LoadStringW(COMDLG32_hInstance, IDS_SAVE, buf, ARRAY_SIZE(buf));
4798
fdimpl->custom_title = StrDupW(buf);
4799
fdimpl->custom_okbutton = StrDupW(buf);
4800
}
4801
4802
list_init(&fdimpl->events_clients);
4803
4804
/* FIXME: The default folder setting should be restored for the
4805
* application if it was previously set. */
4806
SHGetDesktopFolder(&psf);
4807
SHGetItemFromObject((IUnknown*)psf, &IID_IShellItem, (void**)&fdimpl->psi_defaultfolder);
4808
IShellFolder_Release(psf);
4809
4810
hr = init_custom_controls(fdimpl);
4811
if(FAILED(hr))
4812
{
4813
ERR("Failed to initialize custom controls (0x%08lx).\n", hr);
4814
IFileDialog2_Release(&fdimpl->IFileDialog2_iface);
4815
return E_FAIL;
4816
}
4817
4818
fdimpl->user_actctx = INVALID_HANDLE_VALUE;
4819
4820
hr = IFileDialog2_QueryInterface(&fdimpl->IFileDialog2_iface, riid, ppv);
4821
IFileDialog2_Release(&fdimpl->IFileDialog2_iface);
4822
return hr;
4823
}
4824
4825
HRESULT FileOpenDialog_Constructor(IUnknown *pUnkOuter, REFIID riid, void **ppv)
4826
{
4827
return FileDialog_constructor(pUnkOuter, riid, ppv, ITEMDLG_TYPE_OPEN);
4828
}
4829
4830
HRESULT FileSaveDialog_Constructor(IUnknown *pUnkOuter, REFIID riid, void **ppv)
4831
{
4832
return FileDialog_constructor(pUnkOuter, riid, ppv, ITEMDLG_TYPE_SAVE);
4833
}
4834
4835