1 #include "win7filedialog.h"
4 #include "win32_utf8.h"
7 Win7FileDialog::Win7FileDialog(const char *name
, int issave
)
14 CoCreateInstance(__uuidof(FileOpenDialog
), NULL
, CLSCTX_INPROC_SERVER
, IID_IUnknown
, reinterpret_cast<void**>(&m_fod
));
16 CoCreateInstance(__uuidof(FileSaveDialog
), NULL
, CLSCTX_INPROC_SERVER
, IID_IUnknown
, reinterpret_cast<void**>(&m_fod
));
22 #if defined(WDL_NO_SUPPORT_UTF8)
24 mbstowcs(tmp
, name
, 1023);
28 WCHAR
*tmp
= WDL_UTF8ToWC(name
, false, 0, NULL
);
35 Win7FileDialog::~Win7FileDialog()
39 void Win7FileDialog::setFilterList(const char *list
)
41 //generate wchar filter list
42 WDL_PtrList
<WCHAR
> wlist
;
47 #if defined(WDL_NO_SUPPORT_UTF8)
49 WCHAR
*n
= (WCHAR
*)malloc(sizeof(WCHAR
)*(l
+1));
53 wlist
.Add(WDL_UTF8ToWC(p
, false, 0, NULL
));
58 m_fod
->SetFileTypes(wlist
.GetSize()/2, (_COMDLG_FILTERSPEC
*)wlist
.GetList());
59 wlist
.Empty(true,free
);
62 void Win7FileDialog::addOptions(DWORD o
)
64 DWORD fileOpenDialogOptions
;
65 m_fod
->GetOptions(&fileOpenDialogOptions
);
66 fileOpenDialogOptions
|= o
;
67 m_fod
->SetOptions(fileOpenDialogOptions
);
70 void Win7FileDialog::setDefaultExtension(const char *ext
)
72 #if defined(WDL_NO_SUPPORT_UTF8)
74 mbstowcs(tmp
, ext
, 1023);
76 m_fod
->SetDefaultExtension(tmp
);
78 WCHAR
*tmp
= WDL_UTF8ToWC(ext
, false, 0, NULL
);
79 m_fod
->SetDefaultExtension(tmp
);
84 void Win7FileDialog::setFileTypeIndex(int i
)
86 m_fod
->SetFileTypeIndex(i
);
89 void Win7FileDialog::setFolder(const char *folder
, int def
)
91 static HRESULT (WINAPI
*my_SHCreateItemFromParsingName
)(PCWSTR pszPath
, IBindCtx
*pbc
, REFIID riid
, void **ppv
) = NULL
;
92 if(!my_SHCreateItemFromParsingName
)
94 HMODULE dll
= LoadLibrary("shell32.dll");
97 *((void **)(&my_SHCreateItemFromParsingName
)) = (void *)GetProcAddress(dll
, "SHCreateItemFromParsingName");
100 if(!my_SHCreateItemFromParsingName
) return;
102 #if defined(WDL_NO_SUPPORT_UTF8)
104 mbstowcs(tmp
, folder
, 4095);
107 WCHAR
*tmp
= WDL_UTF8ToWC(folder
, false, 0, NULL
);
111 my_SHCreateItemFromParsingName(tmp
, NULL
, __uuidof(IShellItem
), (void **)&si
);
113 #if !defined(WDL_NO_SUPPORT_UTF8)
117 if(si
== NULL
) return;
120 m_fod
->SetDefaultFolder(si
);
122 m_fod
->SetFolder(si
);
125 void Win7FileDialog::addText(DWORD id
, char *txt
)
127 if(m_fdc
== NULL
) return;
128 #if defined(WDL_NO_SUPPORT_UTF8)
130 mbstowcs(tmp
, txt
, 1023);
132 m_fdc
->AddText(id
, tmp
);
134 WCHAR
*tmp
= WDL_UTF8ToWC(txt
, false, 0, NULL
);
135 m_fdc
->AddText(id
, tmp
);
140 void Win7FileDialog::addCheckbox(char *name
, DWORD id
, int defval
)
142 if(m_fdc
== NULL
) return;
144 #if defined(WDL_NO_SUPPORT_UTF8)
146 mbstowcs(tmp
, name
, 1023);
148 m_fdc
->AddCheckButton(id
, tmp
, defval
);
150 WCHAR
*tmp
= WDL_UTF8ToWC(name
, false, 0, NULL
);
151 m_fdc
->AddCheckButton(id
, tmp
, defval
);
156 void Win7FileDialog::startGroup(DWORD id
, char *label
)
158 if(m_fdc
== NULL
) return;
159 #if defined(WDL_NO_SUPPORT_UTF8)
161 mbstowcs(tmp
, label
, 1023);
163 m_fdc
->StartVisualGroup(id
, tmp
);
165 WCHAR
*tmp
= WDL_UTF8ToWC(label
, false, 0, NULL
);
166 m_fdc
->StartVisualGroup(id
, tmp
);
171 void Win7FileDialog::endGroup()
173 if(m_fdc
== NULL
) return;
174 m_fdc
->EndVisualGroup();
177 void Win7FileDialog::getResult(char *fn
, int maxlen
)
180 m_fod
->GetResult(&si
);
187 si
->GetDisplayName(SIGDN_FILESYSPATH
, &res
);
194 #if defined(WDL_NO_SUPPORT_UTF8)
195 if (wcstombs(fn
,res
,maxlen
) == (size_t)-1) fn
[0]=0;
197 int len
= WideCharToMultiByte(CP_UTF8
,0,res
,-1,fn
,maxlen
-1,NULL
,NULL
);
204 int Win7FileDialog::getResult(int i
, char *fn
, int maxlen
)
206 IShellItemArrayPtr sia
;
207 ((IFileOpenDialogPtr
)m_fod
)->GetResults(&sia
); // good enough: only makes sense with IFileOpenDialog
215 if (SUCCEEDED(sia
->GetItemAt(i
, &item
)))
218 item
->GetDisplayName(SIGDN_FILESYSPATH
, &res
);
226 #if defined(WDL_NO_SUPPORT_UTF8)
227 size_t l
= wcstombs(fn
, res
, maxlen
);
228 if (l
==(size_t)-1) fn
[0]=0;
231 len
= WideCharToMultiByte(CP_UTF8
,0,res
,-1,fn
,maxlen
-1,NULL
,NULL
);
240 int Win7FileDialog::getResultCount()
242 IShellItemArrayPtr sia
;
243 ((IFileOpenDialogPtr
)m_fod
)->GetResults(&sia
); // good enough: only makes sense with IFileOpenDialog
244 if (sia
== NULL
) return 0;
247 return SUCCEEDED(sia
->GetCount(&cnt
)) ? cnt
: 0;
250 int Win7FileDialog::getState(DWORD id
)
253 m_fdc
->GetCheckButtonState(id
, &c
);
257 static WNDPROC m_oldproc
, m_oldproc2
;
258 static LRESULT CALLBACK
newWndProc(HWND hwnd
, UINT msg
, WPARAM wparam
, LPARAM lparam
)
262 //disable the win7 dialog to resize our custom dialog
263 static int reent
= 0;
268 GetWindowRect(hwnd
, &r2
);
269 SetWindowPos(hwnd
, NULL
, r2
.left
, r2
.top
, 1000, r2
.bottom
-r2
.top
, SWP_NOMOVE
|SWP_NOACTIVATE
|SWP_NOZORDER
);
274 if(msg
== WM_GETDLGCODE
)
278 return CallWindowProc(m_oldproc
, hwnd
, msg
, wparam
, lparam
);
281 class myEvent
: public IFileDialogEvents
284 myEvent(HINSTANCE inst
, char *dlgid
, LPOFNHOOKPROC proc
, char *statictxt
)
292 m_statictxt
.Set(statictxt
);
295 STDMETHODIMP
QueryInterface(REFIID riid
, void **ppv
)
297 return E_NOINTERFACE
;
299 STDMETHODIMP_(ULONG
) AddRef()
303 STDMETHODIMP_(ULONG
) Release()
305 if(m_crwnd
) DestroyWindow(m_crwnd
);
309 virtual HRESULT STDMETHODCALLTYPE
OnFileOk(
310 /* [in] */ __RPC__in_opt IFileDialog
*pfd
)
315 virtual HRESULT STDMETHODCALLTYPE
OnFolderChanging(
316 /* [in] */ __RPC__in_opt IFileDialog
*pfd
,
317 /* [in] */ __RPC__in_opt IShellItem
*psiFolder
)
322 virtual HRESULT STDMETHODCALLTYPE
OnFolderChange(
323 /* [in] */ __RPC__in_opt IFileDialog
*pfd
)
325 doHook2(pfd
); //post a msg for the actual hook
329 virtual HRESULT STDMETHODCALLTYPE
OnSelectionChange(
330 /* [in] */ __RPC__in_opt IFileDialog
*pfd
)
332 doHook2(pfd
); //post a msg for the actual hook
336 virtual HRESULT STDMETHODCALLTYPE
OnShareViolation(
337 /* [in] */ __RPC__in_opt IFileDialog
*pfd
,
338 /* [in] */ __RPC__in_opt IShellItem
*psi
,
339 /* [out] */ __RPC__out FDE_SHAREVIOLATION_RESPONSE
*pResponse
)
344 virtual HRESULT STDMETHODCALLTYPE
OnTypeChange(
345 /* [in] */ __RPC__in_opt IFileDialog
*pfd
)
350 virtual HRESULT STDMETHODCALLTYPE
OnOverwrite(
351 /* [in] */ __RPC__in_opt IFileDialog
*pfd
,
352 /* [in] */ __RPC__in_opt IShellItem
*psi
,
353 /* [out] */ __RPC__out FDE_OVERWRITE_RESPONSE
*pResponse
)
358 static BOOL CALLBACK
enumProc(HWND hwnd
, LPARAM lParam
)
361 GetClassName(hwnd
, tmp
, 1023);
362 if(!stricmp(tmp
,"FloatNotifySink"))
364 myEvent
*me
= (myEvent
*)lParam
;
365 if(!FindWindowEx(hwnd
, NULL
, NULL
, me
->m_statictxt
.Get()))
367 me
->m_findwnd
= hwnd
;
375 if(m_dlgid
&& !m_didhook
)
377 IOleWindowPtr ow
= m_lastpfd
;
380 HWND filehwnd
= NULL
;
381 ow
->GetWindow(&filehwnd
);
385 EnumChildWindows(filehwnd
, enumProc
, (LPARAM
)this);
390 HWND h5
= FindWindowEx(h3
, NULL
, NULL
, NULL
);
391 ShowWindow(h5
, SW_HIDE
);
395 GetWindowRect(h3
, &r2
);
396 SetWindowPos(h3
, NULL
, r2
.left
, r2
.top
, 1000, r2
.bottom
-r2
.top
, SWP_NOMOVE
|SWP_NOACTIVATE
|SWP_NOZORDER
);
398 //put our own dialog instead
399 HWND h4
= CreateDialog(m_inst
, m_dlgid
, h3
, (DLGPROC
)m_proc
);
401 //SetWindowLong(h4, GWL_ID, 1001);
402 //SetWindowLong(h4, GWL_STYLE, GetWindowLong(h4, GWL_STYLE)&~(DS_CONTROL|DS_3DLOOK|DS_SETFONT));
403 //SetWindowLong(h4, GWL_STYLE, GetWindowLong(h4, GWL_STYLE)|WS_GROUP);
404 SetWindowLong(h3
, GWL_STYLE
, GetWindowLong(h3
, GWL_STYLE
)|WS_TABSTOP
);
407 ShowWindow(h4
, SW_SHOW
);
409 GetClientRect(h3
, &r
);
410 SetWindowPos(h4
, NULL
, 0, 0, r
.right
, r
.bottom
, 0);
412 //disable the win7 dialog to resize our custom dialog sink
413 m_oldproc
= (WNDPROC
)SetWindowLongPtr(h3
, GWLP_WNDPROC
, (LPARAM
)&newWndProc
);
421 static LRESULT CALLBACK
newWndProc2(HWND hwnd
, UINT msg
, WPARAM wparam
, LPARAM lparam
)
423 if(msg
== WM_USER
+666)
425 myEvent
*me
= (myEvent
*)lparam
;
428 return CallWindowProc(m_oldproc2
, hwnd
, msg
, wparam
, lparam
);
431 void doHook2(IFileDialog
*pfd
)
433 if(m_dlgid
&& !m_didhook2
)
435 IOleWindowPtr ow
= pfd
;
436 HWND filehwnd
= NULL
;
437 ow
->GetWindow(&filehwnd
);
441 m_oldproc2
= (WNDPROC
)SetWindowLongPtr(filehwnd
, GWLP_WNDPROC
, (LPARAM
)&newWndProc2
);
442 PostMessage(filehwnd
, WM_USER
+666,0,(LPARAM
)this);
448 int m_didhook
, m_didhook2
;
451 LPOFNHOOKPROC m_proc
;
454 WDL_String m_statictxt
;
455 IFileDialog
*m_lastpfd
;
458 int Win7FileDialog::show(HWND parent
)
461 myEvent
*ev
= new myEvent(m_inst
, (char*)m_dlgid
, m_proc
, m_statictxt
.Get());
462 m_fod
->Advise(ev
, &c
);
464 int res
= SUCCEEDED(m_fod
->Show(parent
));
471 #ifndef DLGTEMPLATEEX
472 #pragma pack(push, 1)
489 void Win7FileDialog::setTemplate(HINSTANCE inst
, const char *dlgid
, LPOFNHOOKPROC proc
)
491 //get the dialog height size
492 HRSRC r
= FindResource(inst
, dlgid
, RT_DIALOG
);
494 HGLOBAL hTemplate
= LoadResource(inst
, r
);
495 if(!hTemplate
) return;
497 DLGTEMPLATEEX
* pTemplate
= (DLGTEMPLATEEX
*)LockResource(hTemplate
);
498 if(pTemplate
->signature
== 0xffff)
499 ysizedlg
= pTemplate
->cy
;
502 DLGTEMPLATE
*p2
= (DLGTEMPLATE
*)pTemplate
;
505 UnlockResource(hTemplate
);
506 FreeResource(hTemplate
);
508 int ysize
= ysizedlg
/8;
510 //make room for our custom template dialog
519 addText(1, txt
.Get());
520 m_statictxt
.Set(txt
.Get());
528 void Win7FileDialog::setFilename(const char *fn
)
530 if(m_fod
== NULL
) return;
532 #if defined(WDL_NO_SUPPORT_UTF8)
534 mbstowcs(tmp
, fn
, 4095);
536 m_fod
->SetFileName(tmp
);
538 WCHAR
*tmp
= WDL_UTF8ToWC(fn
, false, 0, NULL
);
539 m_fod
->SetFileName(tmp
);