X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/7430a4bbf8bcbff0497449568f51eef0907ad790..0d1903dbda864780eec30efdc4e91776bdbfd21b:/src/msw/filedlg.cpp diff --git a/src/msw/filedlg.cpp b/src/msw/filedlg.cpp index 1fb4bc288c..7327c7bdd7 100644 --- a/src/msw/filedlg.cpp +++ b/src/msw/filedlg.cpp @@ -4,7 +4,6 @@ // Author: Julian Smart // Modified by: // Created: 01/02/97 -// RCS-ID: $Id$ // Copyright: (c) Julian Smart // Licence: wxWindows licence ///////////////////////////////////////////////////////////////////////////// @@ -43,8 +42,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 +67,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 +76,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 +172,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,7 +240,7 @@ void wxFileDialog::GetPaths(wxArrayString& paths) const paths.Empty(); wxString dir(m_dir); - if ( m_dir.Last() != wxT('\\') ) + if ( m_dir.empty() || m_dir.Last() != wxT('\\') ) dir += wxT('\\'); size_t count = m_fileNames.GetCount(); @@ -225,7 +309,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); @@ -248,10 +332,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 @@ -375,6 +478,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()) @@ -400,12 +505,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 @@ -430,7 +538,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; @@ -532,7 +640,7 @@ int wxFileDialog::ShowModal() } } - of.lpstrFilter = (LPTSTR)filterBuffer.wx_str(); + of.lpstrFilter = filterBuffer.t_str(); of.nFilterIndex = m_filterIndex + 1; //=== Setting defaultFileName >>========================================= @@ -549,7 +657,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 @@ -631,7 +739,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