X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/6fa6d65956285379aa1d99b76d92db76aaecf11e..fe218f1e4ba6548606a15e231f2982c9f25d77b7:/src/msw/filedlg.cpp diff --git a/src/msw/filedlg.cpp b/src/msw/filedlg.cpp index 7b5ac99870..27dfd888e5 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/testing.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 // ---------------------------------------------------------------------------- @@ -86,6 +161,7 @@ wxFileDialogHookFunction(HWND hDlg, { switch ( iMsg ) { +#ifndef __WXWINCE__ case WM_INITDIALOG: { OPENFILENAME* ofn = reinterpret_cast(lParam); @@ -93,6 +169,7 @@ wxFileDialogHookFunction(HWND hDlg, ->MSWOnInitDialogHook((WXHWND)hDlg); } break; +#endif // __WXWINCE__ case WM_NOTIFY: { @@ -154,8 +231,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++ ) @@ -172,14 +249,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 ) @@ -231,7 +300,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); @@ -349,7 +418,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); } @@ -368,6 +437,7 @@ static bool ShowCommFileDialog(OPENFILENAME *of, long style) return true; } +#ifndef __WXWINCE__ void wxFileDialog::MSWOnInitDialogHook(WXHWND hwnd) { SetHWND(hwnd); @@ -376,9 +446,12 @@ void wxFileDialog::MSWOnInitDialogHook(WXHWND hwnd) SetHWND(NULL); } +#endif // __WXWINCE__ int wxFileDialog::ShowModal() { + WX_TESTING_SHOW_MODAL_HOOK(); + HWND hWnd = 0; if (m_parent) hWnd = (HWND) m_parent->GetHWND(); if (!hWnd && wxTheApp->GetTopWindow()) @@ -404,12 +477,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 @@ -434,7 +510,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; @@ -455,12 +531,11 @@ int wxFileDialog::ShowModal() lpdt->x = 0; lpdt->y = 0; - wxSize extra_size = GetExtraControlSize(); - // setting cx doesn't change the width of the dialog - lpdt->cx = extra_size.GetWidth(); - // Dividing by 2 gives expected height on WinXP and Wine. - // I don't know why (MW). - lpdt->cy = extra_size.GetHeight() / 2; + // convert the size of the extra controls to the dialog units + const wxSize extraSize = GetExtraControlSize(); + const LONG baseUnits = ::GetDialogBaseUnits(); + lpdt->cx = ::MulDiv(extraSize.x, 4, LOWORD(baseUnits)); + lpdt->cy = ::MulDiv(extraSize.y, 8, HIWORD(baseUnits)); // after the DLGTEMPLATE there are 3 additional WORDs for dialog menu, // class and title, all three set to zeros. @@ -481,17 +556,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 @@ -518,7 +593,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; @@ -537,7 +612,7 @@ int wxFileDialog::ShowModal() } } - of.lpstrFilter = (LPTSTR)filterBuffer.wx_str(); + of.lpstrFilter = filterBuffer.t_str(); of.nFilterIndex = m_filterIndex + 1; //=== Setting defaultFileName >>========================================= @@ -554,7 +629,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 @@ -610,7 +685,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); @@ -620,8 +695,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; @@ -636,7 +711,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