30 #include <wx/msw/wrapcdlg.h>
31 #include <wx/msw/missing.h>
33 #include <wx/msgdlg.h>
34 #include <wx/filefn.h>
45#include <wx/filename.h>
46#include <wx/scopeguard.h>
48#include <wx/tokenzr.h>
49#include <wx/modalhook.h>
50#include <wx/filectrl.h>
52#include "../FileDialog.h"
61# define wxMAXPATH 65534
63# define wxMAXPATH 1024
66# define wxMAXFILE 1024
90typedef BOOL (WINAPI *GetProcessUserModeExceptionPolicy_t)(LPDWORD);
91typedef BOOL (WINAPI *SetProcessUserModeExceptionPolicy_t)(DWORD);
93GetProcessUserModeExceptionPolicy_t gs_pfnGetProcessUserModeExceptionPolicy
94 = (GetProcessUserModeExceptionPolicy_t) -1;
96SetProcessUserModeExceptionPolicy_t gs_pfnSetProcessUserModeExceptionPolicy
97 = (SetProcessUserModeExceptionPolicy_t) -1;
99DWORD gs_oldExceptionPolicyFlags = 0;
101bool gs_changedPolicy =
false;
114#if wxUSE_DYNLIB_CLASS
115 gs_changedPolicy =
false;
117 wxLoadedDLL dllKernel32(
wxT(
"kernel32.dll"));
119 if ( gs_pfnGetProcessUserModeExceptionPolicy
120 == (GetProcessUserModeExceptionPolicy_t) -1)
122 wxDL_INIT_FUNC(gs_pfn, GetProcessUserModeExceptionPolicy, dllKernel32);
123 wxDL_INIT_FUNC(gs_pfn, SetProcessUserModeExceptionPolicy, dllKernel32);
126 if ( !gs_pfnGetProcessUserModeExceptionPolicy
127 || !gs_pfnSetProcessUserModeExceptionPolicy
128 || !gs_pfnGetProcessUserModeExceptionPolicy(&gs_oldExceptionPolicyFlags) )
133 if ( gs_pfnSetProcessUserModeExceptionPolicy(gs_oldExceptionPolicyFlags
136 gs_changedPolicy =
true;
144#if wxUSE_DYNLIB_CLASS
145 if (gs_changedPolicy)
147 gs_changedPolicy =
false;
148 (void) gs_pfnSetProcessUserModeExceptionPolicy(gs_oldExceptionPolicyFlags);
161 OPENFILENAME *pOfn =
reinterpret_cast<OPENFILENAME *
>(GetWindowLongPtr(hDlg, GWLP_USERDATA));
168 UINT_PTR ret = CallWindowProc(
mParentProc, hDlg, iMsg, wParam, lParam);
175 if (iMsg == WM_GETMINMAXINFO)
186 wxCopyRECTToRect(wxGetClientRect(hDlg), r);
196 SWP_NOZORDER | SWP_NOMOVE);
202 mRoot->SetSize(r.GetWidth(),
mRoot->GetSize().GetHeight());
229 if (iMsg == WM_INITDIALOG)
231 pOfn =
reinterpret_cast<OPENFILENAME *
>(lParam);
235 pOfn =
reinterpret_cast<OPENFILENAME *
>(GetWindowLongPtr(hDlg, GWLP_USERDATA));
255 NMHDR *
const pNM =
reinterpret_cast<NMHDR *
>(lParam);
256 if (pNM->code > CDN_LAST && pNM->code <= CDN_FIRST)
258 OFNOTIFY *
const pNotifyCode =
reinterpret_cast<OFNOTIFY *
>(lParam);
259 switch (pNotifyCode->hdr.code)
265 case CDN_FOLDERCHANGE:
298 SetWindowLongPtr(
mParentDlg, GWLP_USERDATA,
reinterpret_cast<LPARAM
>(pOfn));
299 SetWindowLongPtr(
mChildDlg, GWLP_USERDATA,
reinterpret_cast<LPARAM
>(pOfn));
310 wxBoxSizer *verticalSizer =
new wxBoxSizer(wxVERTICAL);
311 mRoot =
new wxPanel(
this, wxID_ANY);
313 wxPanel *userpane =
new wxPanel(
mRoot, wxID_ANY);
316 wxBoxSizer *horizontalSizer =
new wxBoxSizer(wxHORIZONTAL);
317 horizontalSizer->Add(userpane, 1, wxEXPAND);
318 verticalSizer->Add(horizontalSizer, 1, wxEXPAND);
320 mRoot->SetSizer(verticalSizer);
325 wxSize sz =
mRoot->GetBestSize();
332 SWP_NOZORDER | SWP_NOMOVE);
359 mMinSize = {r.right - r.left, r.bottom - r.top};
389 int result = CommDlg_OpenSave_GetFolderPath(::GetParent(hDlg), path, WXSIZEOF(path));
390 if (result < 0 || result > WXSIZEOF(path))
397 wxFileCtrlEvent event(wxEVT_FILECTRL_FOLDERCHANGED,
this, GetId());
398 event.SetDirectory(m_dir);
399 GetEventHandler()->ProcessEvent(event);
408 HWND lv = ::GetDlgItem(::GetDlgItem(
mParentDlg, lst2), 1);
415 int result = CommDlg_OpenSave_GetFilePath(::GetParent(hDlg), path, WXSIZEOF(path));
416 if (result < 0 || result > WXSIZEOF(path))
422 m_fileName = wxFileNameFromPath(m_path);
423 m_dir = wxPathOnly(m_path);
428 wxFileCtrlEvent event(wxEVT_FILECTRL_SELECTIONCHANGED,
this, GetId());
429 event.SetDirectory(m_dir);
431 GetEventHandler()->ProcessEvent(event);
445 m_filterIndex = pOfn->nFilterIndex - 1;
447 wxFileCtrlEvent event(wxEVT_FILECTRL_FILTERCHANGED,
this, GetId());
448 event.SetFilterIndex(m_filterIndex);
449 GetEventHandler()->ProcessEvent(event);
455#define WM_GETISHELLBROWSER WM_USER + 7
459 IShellFolder *ishell = NULL;
460 IShellBrowser *ishellbrowser = NULL;
461 IShellView *ishellview = NULL;
462 IFolderView *ifolderview = NULL;
463 LPMALLOC imalloc = NULL;
467 HWND lv = ::GetDlgItem(::GetDlgItem(hwnd, lst2), 1);
474 hr = SHGetMalloc(&imalloc);
475 if ((hr != NOERROR) || (imalloc == NULL))
477 wxASSERT((hr == NOERROR) && (imalloc != NULL));
486 if (ishellbrowser->QueryActiveShellView(&ishellview) == S_OK)
489 ishellview->QueryInterface(IID_IFolderView, (
void **)&ifolderview);
499 int itmcnt = ListView_GetItemCount(lv);
500 for (
int itm = 0; itm < itmcnt; itm++)
504 lvi.mask = LVIF_PARAM;
505 if (ListView_GetItem(lv, &lvi) != TRUE)
511 LPCITEMIDLIST fidl = (LPCITEMIDLIST) lvi.lParam;
517 if (fidl == NULL && ifolderview != NULL)
519 ifolderview->Item(itm, (LPITEMIDLIST *) &fidl);
524 wxASSERT(fidl != NULL);
531 hr = SHBindToParent(fidl, IID_IShellFolder, (
void **)&ishell, NULL);
534 wxASSERT(SUCCEEDED(hr));
540 DWORD attr = SFGAO_FOLDER | SFGAO_BROWSABLE;
541 hr = ishell->GetAttributesOf(1, &fidl, &attr);
544 wxASSERT(SUCCEEDED(hr));
549 if ((attr & (SFGAO_FOLDER)) && !(attr & SFGAO_BROWSABLE))
556 hr = ishell->GetDisplayNameOf(fidl, SHGDN_INFOLDER | SHGDN_FORPARSING, &
str);
572 filename =
str.pOleStr;
573 imalloc->Free(
str.pOleStr);
577 filename = wxString(((
char *)fidl) +
str.uOffset, wxConvISO8859_1);
581 filename = wxString(
str.cStr, wxConvISO8859_1);
586 filename = filename.Lower();
590 for (
int flt = 0; flt < fltcnt; flt++)
592 if (wxMatchWild(
m_Filters[flt], filename,
false))
602 ListView_DeleteItem(lv, itm);
612 if (ishellview && refresh)
614 ishellview->Refresh();
620 ifolderview->Release();
626 ishellview->Release();
648 while (tokenWild.HasMoreTokens())
650 wxString token = tokenWild.GetNextToken();
651 if (
m_Filters.Index(token,
false) == wxNOT_FOUND)
669 const wxString& message,
670 const wxString& defaultDir,
671 const wxString& defaultFile,
672 const wxString& wildCard,
676 const wxString&
name)
681 FileDialogBase::Create(parent,message,defaultDir,defaultFile,wildCard,
style,pos,sz,
name);
706 if (m_dir.empty() || m_dir.Last() !=
wxT(
'\\'))
710 for (
size_t n = 0; n < count; n++)
730 if (CommDlg_OpenSave_GetFilePath(
mParentDlg, path, WXSIZEOF(path)))
736 CommDlg_OpenSave_SetControlText(
mParentDlg, edt1,
fn.GetFullName().t_str());
741 CommDlg_OpenSave_SetDefExt(
mParentDlg,
fn.GetExt().t_str());
771 HWND hwnd = GetHwnd();
776 ::SetWindowPos(hwnd, HWND_TOP, x, y, 0, 0, SWP_NOZORDER | SWP_NOSIZE);
803 if (
style & wxFD_SAVE ? GetSaveFileName(of) : GetOpenFileName(of))
808 *err = CommDlgExtendedError();
821#if defined(__WXWINCE__) || defined(__WIN64__)
826#define wxTRY_SMALLER_OPENFILENAME
853#ifdef wxTRY_SMALLER_OPENFILENAME
856 if (!success && errCode == CDERR_STRUCTSIZE &&
863 if (success || !errCode)
871 if (!success && errCode == FNERR_INVALIDFILENAME && of->lpstrFile[0])
875 of->lpstrFile[0] =
wxT(
'\0');
884 wxLogError(
wxT(
"File dialog failed with error code %0lx."), errCode);
896 WX_HOOK_MODAL_DIALOG();
899 if (m_parent) hWnd = (HWND) m_parent->GetHWND();
900 if (!hWnd && wxTheApp->GetTopWindow())
901 hWnd = (HWND) wxTheApp->GetTopWindow()->GetHWND();
903 static wxChar fileNameBuffer [
wxMAXPATH ];
906 *fileNameBuffer =
wxT(
'\0');
907 *titleBuffer =
wxT(
'\0');
910 DWORD msw_flags = OFN_HIDEREADONLY | OFN_EXPLORER | OFN_ENABLEHOOK | OFN_ENABLESIZING | OFN_ENABLETEMPLATEHANDLE;
912 if (HasFdFlag(wxFD_FILE_MUST_EXIST))
913 msw_flags |= OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST;
926 msw_flags |= OFN_EXPLORER|OFN_ENABLEHOOK;
928 msw_flags |= OFN_ENABLESIZING;
934 if (HasFdFlag(wxFD_MULTIPLE))
937 msw_flags |= OFN_EXPLORER | OFN_ALLOWMULTISELECT;
943 if (!HasFdFlag(wxFD_CHANGE_DIR))
945 msw_flags |= OFN_NOCHANGEDIR;
948 if (HasFdFlag(wxFD_OVERWRITE_PROMPT))
950 msw_flags |= OFN_OVERWRITEPROMPT;
954 GlobalPtr hgbl(256, GMEM_ZEROINIT);
955 GlobalPtrLock hgblLock(hgbl);
956 LPDLGTEMPLATE lpdt =
static_cast<LPDLGTEMPLATE
>((
void *)hgblLock);
957 lpdt->style = DS_CONTROL | WS_CHILD | WS_CLIPSIBLINGS;
968 of.lStructSize =
sizeof(OPENFILENAME);
970 of.lpstrTitle = m_message.t_str();
971 of.lpstrFileTitle = titleBuffer;
973 of.hInstance = (HINSTANCE) lpdt;
980 size_t i, len = m_dir.length();
982 for ( i = 0; i < len; i++ )
984 wxChar ch = m_dir[i];
994 while ( i < len - 1 )
996 wxChar chNext = m_dir[i + 1];
997 if ( chNext !=
wxT(
'\\') && chNext !=
wxT(
'/') )
1014 of.lpstrInitialDir = dir.c_str();
1016 of.Flags = msw_flags;
1018 of.lCustData = (LPARAM)
this;
1020 wxArrayString wildDescriptions;
1022 size_t items = wxParseCommonDialogsFilter(m_wildCard, wildDescriptions,
m_FilterGroups);
1024 wxASSERT_MSG( items > 0 ,
wxT(
"empty wildcard list") );
1026 wxString filterBuffer;
1028 for (i = 0; i < items ; i++)
1030 filterBuffer += wildDescriptions[i];
1031 filterBuffer +=
wxT(
"|");
1033 filterBuffer +=
wxT(
"|");
1037 for (i = 0; i < filterBuffer.Len(); i++ )
1039 if ( filterBuffer.GetChar(i) ==
wxT(
'|') )
1041 filterBuffer[i] =
wxT(
'\0');
1045 of.lpstrFilter = (LPCTSTR)filterBuffer.c_str();
1046 of.nFilterIndex = m_filterIndex + 1;
1052 wxStrlcpy(fileNameBuffer, m_fileName.c_str(), WXSIZEOF(fileNameBuffer));
1054 of.lpstrFile = fileNameBuffer;
1061 wxString defextBuffer;
1062 if (HasFdFlag(wxFD_SAVE))
1065 int maxFilter = (int)(of.nFilterIndex*2L) - 1;
1067 for(
int i = 0; i < maxFilter; i++ )
1072 if (defextBuffer.StartsWith(
wxT(
"a.")))
1074 defextBuffer = defextBuffer.Mid(2);
1075 of.lpstrDefExt = defextBuffer.c_str();
1080 const wxString cwdOrig = wxGetCwd();
1092 if (msw_flags & OFN_NOCHANGEDIR)
1094 wxSetWorkingDirectory(cwdOrig);
1099 if ((HasFdFlag(wxFD_MULTIPLE)) &&
1100#
if defined(OFN_EXPLORER)
1101 ( fileNameBuffer[of.nFileOffset-1] ==
wxT(
'\0') )
1103 ( fileNameBuffer[of.nFileOffset-1] ==
wxT(
' ') )
1107#if defined(OFN_EXPLORER)
1108 m_dir = fileNameBuffer;
1110 m_fileName = &fileNameBuffer[i];
1112 i += m_fileName.Len() + 1;
1114 while (fileNameBuffer[i] !=
wxT(
'\0'))
1117 i += wxStrlen(&fileNameBuffer[i]) + 1;
1120 wxStringTokenizer toke(fileNameBuffer,
wxT(
" \t\r\n"));
1121 m_dir = toke.GetNextToken();
1122 m_fileName = toke.GetNextToken();
1125 while (toke.HasMoreTokens())
1129 wxString dir(m_dir);
1130 if ( m_dir.Last() !=
wxT(
'\\') )
1133 m_path = dir + m_fileName;
1134 m_filterIndex = (int)of.nFilterIndex - 1;
1139 m_filterIndex = (int)of.nFilterIndex - 1;
1141 if ( !of.nFileExtension || fileNameBuffer[of.nFileExtension] ==
wxT(
'\0') )
1145 int maxFilter = (int)(of.nFilterIndex*2L) - 1;
1147 for(
int i = 0; i < maxFilter; i++ )
1150 m_fileName = AppendExtension(fileNameBuffer,
extension);
1151 wxStrlcpy(fileNameBuffer, m_fileName.c_str(), WXSIZEOF(fileNameBuffer));
1154 m_path = fileNameBuffer;
1155 m_fileName = wxFileNameFromPath(fileNameBuffer);
1157 m_dir = wxPathOnly(fileNameBuffer);
1166 mHwnd = (HWND) INVALID_HANDLE_VALUE;
1180 if (mHwnd != (HWND) INVALID_HANDLE_VALUE)
1182 if (IsChild(dialog)) {
1183 ::EnableWindow(mHwnd, FALSE);
1193 if (mHwnd != (HWND) INVALID_HANDLE_VALUE)
1195 if (IsChild(dialog))
1198 if (mModalCount == 0)
1200 ::EnableWindow(mHwnd, TRUE);
1201 ::SetWindowPos(mHwnd, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
1214 for (
const wxWindow *w = dialog->GetParent(); w != NULL; w = w->GetParent())
int Enter(wxDialog *dialog)
bool IsChild(const wxDialog *dialog) const
void Init(wxWindow *root, HWND hwnd)
void Exit(wxDialog *dialog)
void CreateUserPane(wxWindow *parent)
virtual bool HasUserPaneCreator() const
Dialog used to present platform specific "Save As" dialog with custom controls.
virtual void MSWOnDestroy(HWND hwnd, LPOPENFILENAME pOfn)
virtual void DoCentre(int dir)
virtual void DoGetPosition(int *x, int *y) const
FileDialog::Disabler mDisabler
static UINT_PTR APIENTRY ParentHook(HWND hDlg, UINT iMsg, WPARAM wParam, LPARAM lParam)
virtual void SetFileExtension(const wxString &extension)
virtual void MSWOnFolderChange(HWND hwnd, LPOPENFILENAME pOfn)
wxArrayString m_FilterGroups
virtual void DoGetSize(int *width, int *height) const
virtual void MSWOnSelChange(HWND hwnd, LPOPENFILENAME pOfn)
virtual void MSWOnSize(HWND hwnd, LPOPENFILENAME pOfn)
virtual UINT_PTR MSWDialogHook(HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam, OPENFILENAME *pOfn)
virtual void GetFilenames(wxArrayString &files) const
virtual void GetPaths(wxArrayString &paths) const
virtual void MSWOnGetMinMaxInfo(HWND hwnd, LPOPENFILENAME pOfn, LPMINMAXINFO pMmi)
wxArrayString m_fileNames
void FilterFiles(HWND hwnd, bool refresh)
virtual void MSWOnTypeChange(HWND hwnd, LPOPENFILENAME pOfn)
virtual void MSWOnInitDone(HWND hwnd, LPOPENFILENAME pOfn)
virtual void MSWOnInitDialog(HWND hwnd, LPOPENFILENAME pOfn)
virtual UINT_PTR MSWParentHook(HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam, OPENFILENAME *pOfn)
static UINT_PTR APIENTRY DialogHook(HWND hDlg, UINT iMsg, WPARAM wParam, LPARAM lParam)
void ParseFilter(int index)
virtual void DoMoveWindow(int x, int y, int width, int height)
ProjectFileIOExtensionRegistry::Extension extension
void RestoreExceptionPolicy()
void ChangeExceptionPolicy()
static wxRect gs_rectDialog(0, 0, 428, 266)
static bool DoShowCommFileDialog(OPENFILENAME *of, long style, DWORD *err)
#define WM_GETISHELLBROWSER
static const DWORD wxOPENFILENAME_V4_SIZE
static bool ShowCommFileDialog(OPENFILENAME *of, long style)
static DWORD gs_ofStructSize
static const DWORD wxOPENFILENAME_V5_SIZE