+void wxFileDialog::DoGetPosition(int *x, int *y) const
+{
+ if ( x )
+ *x = gs_rectDialog.x;
+ if ( y )
+ *y = gs_rectDialog.y;
+}
+
+void wxFileDialog::DoGetSize(int *width, int *height) const
+{
+ if ( width )
+ *width = gs_rectDialog.width;
+ if ( height )
+ *height = gs_rectDialog.height;
+}
+
+void wxFileDialog::DoMoveWindow(int x, int y, int WXUNUSED(w), int WXUNUSED(h))
+{
+ gs_rectDialog.x = x;
+ gs_rectDialog.y = y;
+
+ // our HWND is only set when we're called from MSWOnInitDone(), test if
+ // this is the case
+ HWND hwnd = GetHwnd();
+ if ( hwnd )
+ {
+ // size of the dialog can't be changed because the controls are not
+ // laid out correctly then
+ ::SetWindowPos(hwnd, HWND_TOP, x, y, 0, 0, SWP_NOZORDER | SWP_NOSIZE);
+ }
+ else // just remember that we were requested to move the window
+ {
+ m_bMovedWindow = true;
+
+ // if Centre() had been called before, it shouldn't be taken into
+ // account now
+ m_centreDir = 0;
+ }
+}
+
+void wxFileDialog::DoCentre(int dir)
+{
+ m_centreDir = dir;
+ m_bMovedWindow = true;
+
+ // it's unnecessary to do anything else at this stage as we'll redo it in
+ // MSWOnInitDone() anyhow
+}
+
+void wxFileDialog::MSWOnInitDone(WXHWND hDlg)
+{
+ // note the the dialog is the parent window: hDlg is a child of it when
+ // OFN_EXPLORER is used
+ HWND hFileDlg = ::GetParent((HWND)hDlg);
+
+ // set HWND so that our DoMoveWindow() works correctly
+ SetHWND((WXHWND)hFileDlg);
+
+ if ( m_centreDir )
+ {
+ // now we have the real dialog size, remember it
+ RECT rect;
+ GetWindowRect(hFileDlg, &rect);
+ gs_rectDialog = wxRectFromRECT(rect);
+
+ // and position the window correctly: notice that we must use the base
+ // class version as our own doesn't do anything except setting flags
+ wxFileDialogBase::DoCentre(m_centreDir);
+ }
+ else // need to just move it to the correct place
+ {
+ SetPosition(gs_rectDialog.GetPosition());
+ }
+
+ // we shouldn't destroy this HWND
+ SetHWND(NULL);
+}
+
+// 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
+// err is filled with the CDERR_XXX constant
+static bool DoShowCommFileDialog(OPENFILENAME *of, long style, DWORD *err)
+{
+ if ( style & wxFD_SAVE ? GetSaveFileName(of) : GetOpenFileName(of) )
+ return true;
+
+ if ( err )
+ {
+#ifdef __WXWINCE__
+ // according to MSDN, CommDlgExtendedError() should work under CE as
+ // well but apparently in practice it doesn't (anybody has more
+ // details?)
+ *err = GetLastError();
+#else
+ *err = CommDlgExtendedError();
+#endif
+ }
+
+ return false;
+}
+
+// We want to use OPENFILENAME struct version 5 (Windows 2000/XP) but we don't
+// know if the OPENFILENAME declared in the currently used headers is a V5 or
+// V4 (smaller) one so we try to manually extend the struct in case it is the
+// old one.
+//
+// We don't do this on Windows CE nor under Win64, however, as there are no
+// compilers with old headers for these architectures
+#if defined(__WXWINCE__) || defined(__WIN64__)
+ typedef OPENFILENAME wxOPENFILENAME;
+
+ static const DWORD gs_ofStructSize = sizeof(OPENFILENAME);
+#else // !__WXWINCE__ || __WIN64__
+ #define wxTRY_SMALLER_OPENFILENAME
+
+ struct wxOPENFILENAME : public OPENFILENAME
+ {
+ // fields added in Windows 2000/XP comdlg32.dll version
+ void *pVoid;
+ DWORD dw1;
+ DWORD dw2;
+ };
+
+ // hardcoded sizeof(OPENFILENAME) in the Platform SDK: we have to do it
+ // because sizeof(OPENFILENAME) in the headers we use when compiling the
+ // library could be less if _WIN32_WINNT is not >= 0x500
+ static const DWORD wxOPENFILENAME_V5_SIZE = 88;
+
+ // this is hardcoded sizeof(OPENFILENAME_NT4) from Platform SDK
+ static const DWORD wxOPENFILENAME_V4_SIZE = 76;
+
+ // always try the new one first
+ static DWORD gs_ofStructSize = wxOPENFILENAME_V5_SIZE;
+#endif // __WXWINCE__ || __WIN64__/!...
+
+static bool ShowCommFileDialog(OPENFILENAME *of, long style)
+{
+ DWORD errCode;
+ bool success = DoShowCommFileDialog(of, style, &errCode);
+
+#ifdef wxTRY_SMALLER_OPENFILENAME
+ // the system might be too old to support the new version file dialog
+ // boxes, try with the old size
+ if ( !success && errCode == CDERR_STRUCTSIZE &&
+ of->lStructSize != wxOPENFILENAME_V4_SIZE )
+ {
+ of->lStructSize = wxOPENFILENAME_V4_SIZE;
+
+ success = DoShowCommFileDialog(of, style, &errCode);
+
+ if ( success || !errCode )
+ {
+ // use this struct size for subsequent dialogs
+ gs_ofStructSize = of->lStructSize;
+ }
+ }
+#endif // wxTRY_SMALLER_OPENFILENAME
+
+ if ( !success &&
+ // FNERR_INVALIDFILENAME is not defined under CE (besides we don't
+ // use CommDlgExtendedError() there anyhow)
+#ifndef __WXWINCE__
+ errCode == FNERR_INVALIDFILENAME &&
+#endif // !__WXWINCE__
+ of->lpstrFile[0] )
+ {
+ // this can happen if the default file name is invalid, try without it
+ // now
+ of->lpstrFile[0] = _T('\0');
+ success = DoShowCommFileDialog(of, style, &errCode);
+ }
+
+ if ( !success )
+ {
+ // common dialog failed - why?
+ if ( errCode != 0 )
+ {
+ wxLogError(_("File dialog failed with error code %0lx."), errCode);
+ }
+ //else: it was just cancelled
+
+ return false;
+ }
+
+ return true;
+}
+