X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/c10c791ba99839bd5fb5216cbf8dc8e8bd3f1fb3..12bb29f5432174ecbd65549bda832d70d34a98ae:/src/msw/filedlg.cpp diff --git a/src/msw/filedlg.cpp b/src/msw/filedlg.cpp index c553328fb4..fd71dc6b9c 100644 --- a/src/msw/filedlg.cpp +++ b/src/msw/filedlg.cpp @@ -43,8 +43,11 @@ #include #include +#include "wx/dynlib.h" #include "wx/filename.h" +#include "wx/scopeguard.h" #include "wx/tokenzr.h" +#include "wx/modalhook.h" // ---------------------------------------------------------------------------- // constants @@ -65,7 +68,7 @@ // ---------------------------------------------------------------------------- // standard dialog size for the old Windows systems where the dialog wasn't -// resizeable +// resizable static wxRect gs_rectDialog(0, 0, 428, 266); // ============================================================================ @@ -74,6 +77,78 @@ static wxRect gs_rectDialog(0, 0, 428, 266); IMPLEMENT_CLASS(wxFileDialog, wxFileDialogBase) +// ---------------------------------------------------------------------------- + +namespace +{ + +#if wxUSE_DYNLIB_CLASS + +typedef BOOL (WINAPI *GetProcessUserModeExceptionPolicy_t)(LPDWORD); +typedef BOOL (WINAPI *SetProcessUserModeExceptionPolicy_t)(DWORD); + +GetProcessUserModeExceptionPolicy_t gs_pfnGetProcessUserModeExceptionPolicy + = (GetProcessUserModeExceptionPolicy_t) -1; + +SetProcessUserModeExceptionPolicy_t gs_pfnSetProcessUserModeExceptionPolicy + = (SetProcessUserModeExceptionPolicy_t) -1; + +DWORD gs_oldExceptionPolicyFlags = 0; + +bool gs_changedPolicy = false; + +#endif // #if wxUSE_DYNLIB_CLASS + +/* +Since Windows 7 by default (callback) exceptions aren't swallowed anymore +with native x64 applications. Exceptions can occur in a file dialog when +using the hook procedure in combination with third-party utilities. +Since Windows 7 SP1 the swallowing of exceptions can be enabled again +by using SetProcessUserModeExceptionPolicy. +*/ +void ChangeExceptionPolicy() +{ +#if wxUSE_DYNLIB_CLASS + gs_changedPolicy = false; + + wxLoadedDLL dllKernel32(wxT("kernel32.dll")); + + if ( gs_pfnGetProcessUserModeExceptionPolicy + == (GetProcessUserModeExceptionPolicy_t) -1) + { + wxDL_INIT_FUNC(gs_pfn, GetProcessUserModeExceptionPolicy, dllKernel32); + wxDL_INIT_FUNC(gs_pfn, SetProcessUserModeExceptionPolicy, dllKernel32); + } + + if ( !gs_pfnGetProcessUserModeExceptionPolicy + || !gs_pfnSetProcessUserModeExceptionPolicy + || !gs_pfnGetProcessUserModeExceptionPolicy(&gs_oldExceptionPolicyFlags) ) + { + return; + } + + if ( gs_pfnSetProcessUserModeExceptionPolicy(gs_oldExceptionPolicyFlags + | 0x1 /* PROCESS_CALLBACK_FILTER_ENABLED */ ) ) + { + gs_changedPolicy = true; + } + +#endif // wxUSE_DYNLIB_CLASS +} + +void RestoreExceptionPolicy() +{ +#if wxUSE_DYNLIB_CLASS + if (gs_changedPolicy) + { + gs_changedPolicy = false; + (void) gs_pfnSetProcessUserModeExceptionPolicy(gs_oldExceptionPolicyFlags); + } +#endif // wxUSE_DYNLIB_CLASS +} + +} // unnamed namespace + // ---------------------------------------------------------------------------- // hook function for moving the dialog // ---------------------------------------------------------------------------- @@ -98,13 +173,23 @@ wxFileDialogHookFunction(HWND hDlg, case WM_NOTIFY: { - OFNOTIFY *pNotifyCode = reinterpret_cast(lParam); - if ( pNotifyCode->hdr.code == CDN_INITDONE ) + OFNOTIFY* const + pNotifyCode = reinterpret_cast(lParam); + wxFileDialog* const + dialog = reinterpret_cast( + pNotifyCode->lpOFN->lCustData + ); + + switch ( pNotifyCode->hdr.code ) { - reinterpret_cast( - pNotifyCode->lpOFN->lCustData) - ->MSWOnInitDone((WXHWND)hDlg); - } + case CDN_INITDONE: + dialog->MSWOnInitDone((WXHWND)hDlg); + break; + + case CDN_SELCHANGE: + dialog->MSWOnSelChange((WXHWND)hDlg); + break; + } } break; @@ -156,8 +241,8 @@ void wxFileDialog::GetPaths(wxArrayString& paths) const paths.Empty(); wxString dir(m_dir); - if ( m_dir.Last() != _T('\\') ) - dir += _T('\\'); + if ( m_dir.empty() || m_dir.Last() != wxT('\\') ) + dir += wxT('\\'); size_t count = m_fileNames.GetCount(); for ( size_t n = 0; n < count; n++ ) @@ -174,14 +259,6 @@ void wxFileDialog::GetFilenames(wxArrayString& files) const files = m_fileNames; } -void wxFileDialog::SetPath(const wxString& path) -{ - wxString ext; - wxFileName::SplitPath(path, &m_dir, &m_fileName, &ext); - if ( !ext.empty() ) - m_fileName << _T('.') << ext; -} - void wxFileDialog::DoGetPosition(int *x, int *y) const { if ( x ) @@ -233,7 +310,7 @@ void wxFileDialog::DoCentre(int dir) void wxFileDialog::MSWOnInitDone(WXHWND hDlg) { - // note the the dialog is the parent window: hDlg is a child of it when + // note the dialog is the parent window: hDlg is a child of it when // OFN_EXPLORER is used HWND hFileDlg = ::GetParent((HWND)hDlg); @@ -256,10 +333,29 @@ void wxFileDialog::MSWOnInitDone(WXHWND hDlg) SetPosition(gs_rectDialog.GetPosition()); } + // Call selection change handler so that update handler will be + // called once with no selection. + MSWOnSelChange(hDlg); + // we shouldn't destroy this HWND SetHWND(NULL); } +void wxFileDialog::MSWOnSelChange(WXHWND hDlg) +{ + TCHAR buf[MAX_PATH]; + LRESULT len = SendMessage(::GetParent(hDlg), CDM_GETFILEPATH, + MAX_PATH, reinterpret_cast(buf)); + + if ( len > 0 ) + m_currentlySelectedFilename = buf; + else + m_currentlySelectedFilename.clear(); + + if ( m_extraControl ) + m_extraControl->UpdateWindowUI(wxUPDATE_UI_RECURSE); +} + // helper used below in ShowCommFileDialog(): style is used to determine // whether to show the "Save file" dialog (if it contains wxFD_SAVE bit) or // "Open file" one; returns true on success or false on failure in which case @@ -351,7 +447,7 @@ static bool ShowCommFileDialog(OPENFILENAME *of, long style) { // this can happen if the default file name is invalid, try without it // now - of->lpstrFile[0] = _T('\0'); + of->lpstrFile[0] = wxT('\0'); success = DoShowCommFileDialog(of, style, &errCode); } @@ -383,6 +479,8 @@ void wxFileDialog::MSWOnInitDialogHook(WXHWND hwnd) int wxFileDialog::ShowModal() { + WX_HOOK_MODAL_DIALOG(); + HWND hWnd = 0; if (m_parent) hWnd = (HWND) m_parent->GetHWND(); if (!hWnd && wxTheApp->GetTopWindow()) @@ -408,12 +506,15 @@ int wxFileDialog::ShowModal() */ if (m_bMovedWindow || HasExtraControlCreator()) // we need these flags. { + ChangeExceptionPolicy(); msw_flags |= OFN_EXPLORER|OFN_ENABLEHOOK; #ifndef __WXWINCE__ msw_flags |= OFN_ENABLESIZING; #endif } + wxON_BLOCK_EXIT0(RestoreExceptionPolicy); + if ( HasFdFlag(wxFD_MULTIPLE) ) { // OFN_EXPLORER must always be specified with OFN_ALLOWMULTISELECT @@ -438,7 +539,7 @@ int wxFileDialog::ShowModal() of.lStructSize = gs_ofStructSize; of.hwndOwner = hWnd; - of.lpstrTitle = m_message.wx_str(); + of.lpstrTitle = m_message.t_str(); of.lpstrFileTitle = titleBuffer; of.nMaxFileTitle = wxMAXFILE + 1 + wxMAXEXT; @@ -484,17 +585,17 @@ int wxFileDialog::ShowModal() wxChar ch = m_dir[i]; switch ( ch ) { - case _T('/'): + case wxT('/'): // convert to backslash - ch = _T('\\'); + ch = wxT('\\'); // fall through - case _T('\\'): + case wxT('\\'): while ( i < len - 1 ) { wxChar chNext = m_dir[i + 1]; - if ( chNext != _T('\\') && chNext != _T('/') ) + if ( chNext != wxT('\\') && chNext != wxT('/') ) break; // ignore the next one, unless it is at the start of a UNC path @@ -521,7 +622,7 @@ int wxFileDialog::ShowModal() size_t items = wxParseCommonDialogsFilter(m_wildCard, wildDescriptions, wildFilters); - wxASSERT_MSG( items > 0 , _T("empty wildcard list") ); + wxASSERT_MSG( items > 0 , wxT("empty wildcard list") ); wxString filterBuffer; @@ -540,7 +641,7 @@ int wxFileDialog::ShowModal() } } - of.lpstrFilter = (LPTSTR)filterBuffer.wx_str(); + of.lpstrFilter = filterBuffer.t_str(); of.nFilterIndex = m_filterIndex + 1; //=== Setting defaultFileName >>========================================= @@ -557,7 +658,7 @@ int wxFileDialog::ShowModal() wxString defextBuffer; // we need it to be alive until GetSaveFileName()! if (HasFdFlag(wxFD_SAVE)) { - const wxChar* extension = filterBuffer.wx_str(); + const wxChar* extension = filterBuffer.t_str(); int maxFilter = (int)(of.nFilterIndex*2L) - 1; for( int i = 0; i < maxFilter; i++ ) // get extension @@ -613,7 +714,7 @@ int wxFileDialog::ShowModal() i += wxStrlen(&fileNameBuffer[i]) + 1; } #else - wxStringTokenizer toke(fileNameBuffer, _T(" \t\r\n")); + wxStringTokenizer toke(fileNameBuffer, wxT(" \t\r\n")); m_dir = toke.GetNextToken(); m_fileName = toke.GetNextToken(); m_fileNames.Add(m_fileName); @@ -623,8 +724,8 @@ int wxFileDialog::ShowModal() #endif // OFN_EXPLORER wxString dir(m_dir); - if ( m_dir.Last() != _T('\\') ) - dir += _T('\\'); + if ( m_dir.Last() != wxT('\\') ) + dir += wxT('\\'); m_path = dir + m_fileName; m_filterIndex = (int)of.nFilterIndex - 1; @@ -639,7 +740,7 @@ int wxFileDialog::ShowModal() (of.nFileExtension && fileNameBuffer[of.nFileExtension] == wxT('\0')) ) { // User has typed a filename without an extension: - const wxChar* extension = filterBuffer.wx_str(); + const wxChar* extension = filterBuffer.t_str(); int maxFilter = (int)(of.nFilterIndex*2L) - 1; for( int i = 0; i < maxFilter; i++ ) // get extension