+ // changing the button labels is the easy part but we also need to ensure
+ // that the buttons are big enough for the label strings and increase their
+ // size (and maybe the size of the message box itself) if they are not
+
+ // TODO-RTL: check whether this works correctly in RTL
+
+ // we want to use this font in GetTextExtent() calls below but we don't
+ // want to send WM_SETFONT to the message box, who knows how is it going to
+ // react to it (right now it doesn't seem to do anything but what if this
+ // changes)
+ wxWindowBase::SetFont(GetMessageFont());
+
+ // first iteration: find the widest button and update the buttons labels
+ int wBtnOld = 0, // current buttons width
+ wBtnNew = 0; // required new buttons width
+ RECT rcBtn; // stores the button height and y positions
+ unsigned numButtons = 0; // total number of buttons in the message box
+ unsigned n;
+ for ( n = 0; n < WXSIZEOF(ms_buttons); n++ )
+ {
+ const HWND hwndBtn = ::GetDlgItem(GetHwnd(), ms_buttons[n].id);
+ if ( !hwndBtn )
+ continue; // it's ok, not all buttons are always present
+
+ numButtons++;
+
+ const wxString label = (this->*ms_buttons[n].getter)();
+ const wxSize sizeLabel = wxWindowBase::GetTextExtent(label);
+
+ // check if the button is big enough for this label
+ const RECT rc = wxGetWindowRect(hwndBtn);
+ if ( !wBtnOld )
+ {
+ // initialize wBtnOld using the first button width, all the other
+ // ones should have the same one
+ wBtnOld = rc.right - rc.left;
+
+ rcBtn = rc; // remember for use below when we reposition the buttons
+ }
+ else
+ {
+ wxASSERT_MSG( wBtnOld == rc.right - rc.left,
+ "all buttons are supposed to be of same width" );
+ }
+
+ const int widthNeeded = wxMSWButton::GetFittingSize(this, sizeLabel).x;
+ if ( widthNeeded > wBtnNew )
+ wBtnNew = widthNeeded;
+
+ ::SetWindowText(hwndBtn, label.t_str());
+ }
+
+ if ( wBtnNew <= wBtnOld )
+ {
+ // all buttons fit, nothing else to do
+ return;
+ }
+
+ // resize the message box to be wider if needed
+ const int wBoxOld = wxGetClientRect(GetHwnd()).right;
+
+ const int CHAR_WIDTH = GetCharWidth();
+ const int MARGIN_OUTER = 2*CHAR_WIDTH; // margin between box and buttons
+ const int MARGIN_INNER = CHAR_WIDTH; // margin between buttons
+
+ RECT rcBox = wxGetWindowRect(GetHwnd());
+
+ const int wAllButtons = numButtons*(wBtnNew + MARGIN_INNER) - MARGIN_INNER;
+ int wBoxNew = 2*MARGIN_OUTER + wAllButtons;
+ if ( wBoxNew > wBoxOld )
+ {
+ const int dw = wBoxNew - wBoxOld;
+ rcBox.left -= dw/2;
+ rcBox.right += dw - dw/2;
+
+ SetWindowRect(GetHwnd(), rcBox);
+
+ // surprisingly, we don't need to resize the static text control, it
+ // seems to adjust itself to the new size, at least under Windows 2003
+ // (TODO: test if this happens on older Windows versions)
+ }
+ else // the current width is big enough
+ {
+ wBoxNew = wBoxOld;
+ }
+
+
+ // finally position all buttons
+
+ // notice that we have to take into account the difference between window
+ // and client width
+ rcBtn.left = (rcBox.left + rcBox.right - wxGetClientRect(GetHwnd()).right +
+ wBoxNew - wAllButtons) / 2;
+ rcBtn.right = rcBtn.left + wBtnNew;
+
+ for ( n = 0; n < WXSIZEOF(ms_buttons); n++ )
+ {
+ const HWND hwndBtn = ::GetDlgItem(GetHwnd(), ms_buttons[n].id);
+ if ( !hwndBtn )
+ continue;
+
+ MoveWindowToScreenRect(hwndBtn, rcBtn);
+
+ rcBtn.left += wBtnNew + MARGIN_INNER;
+ rcBtn.right += wBtnNew + MARGIN_INNER;
+ }
+}
+
+#endif // wxUSE_MSGBOX_HOOK
+
+/* static */
+wxFont wxMessageDialog::GetMessageFont()
+{
+ const NONCLIENTMETRICS& ncm = wxMSWImpl::GetNonClientMetrics();
+ return wxNativeFontInfo(ncm.lfMessageFont);
+}
+
+int wxMessageDialog::ShowMessageBox()
+{
+ if ( !wxTheApp->GetTopWindow() )
+ {
+ // when the message box is shown from wxApp::OnInit() (i.e. before the
+ // message loop is entered), this must be done or the next message box
+ // will never be shown - just try putting 2 calls to wxMessageBox() in
+ // OnInit() to see it
+ while ( wxTheApp->Pending() )
+ wxTheApp->Dispatch();
+ }
+
+ // use the top level window as parent if none specified
+ m_parent = GetParentForModalDialog();
+ HWND hWnd = m_parent ? GetHwndOf(m_parent) : NULL;
+
+#if wxUSE_INTL
+ // native message box always uses the current user locale but the program
+ // may be using a different one and in this case we need to manually
+ // translate the default button labels (if they're non default we have no
+ // way to translate them and so we must assume they were already
+ // translated) to avoid mismatch between the language of the message box
+ // text and its buttons
+ wxLocale * const loc = wxGetLocale();
+ if ( loc && loc->GetLanguage() != wxLocale::GetSystemLanguage() )
+ {
+ if ( m_dialogStyle & wxYES_NO &&
+ (GetCustomYesLabel().empty() && GetCustomNoLabel().empty()) )
+
+ {
+ // use the strings with mnemonics here as the native message box
+ // does
+ SetYesNoLabels(_("&Yes"), _("&No"));
+ }
+
+ // we may or not have the Ok/Cancel buttons but either we do have them
+ // or we already made the labels custom because we called
+ // SetYesNoLabels() above so doing this does no harm -- and is
+ // necessary in wxYES_NO | wxCANCEL case
+ //
+ // note that we don't use mnemonics here for consistency with the
+ // native message box (which probably doesn't use them because
+ // Enter/Esc keys can be already used to dismiss the message box
+ // using keyboard)
+ if ( GetCustomOKLabel().empty() && GetCustomCancelLabel().empty() )
+ SetOKCancelLabels(_("OK"), _("Cancel"));
+ }
+#endif // wxUSE_INTL
+
+ // translate wx style in MSW
+ unsigned int msStyle;
+ const long wxStyle = GetMessageDialogStyle();
+ if ( wxStyle & wxYES_NO )
+ {
+#if !(defined(__SMARTPHONE__) && defined(__WXWINCE__))
+ if (wxStyle & wxCANCEL)
+ msStyle = MB_YESNOCANCEL;
+ else
+#endif // !(__SMARTPHONE__ && __WXWINCE__)
+ msStyle = MB_YESNO;
+
+ if ( wxStyle & wxNO_DEFAULT )
+ msStyle |= MB_DEFBUTTON2;
+ else if ( wxStyle & wxCANCEL_DEFAULT )
+ msStyle |= MB_DEFBUTTON3;
+ }
+ else // without Yes/No we're going to have an OK button
+ {
+ if ( wxStyle & wxCANCEL )
+ {
+ msStyle = MB_OKCANCEL;
+
+ if ( wxStyle & wxCANCEL_DEFAULT )
+ msStyle |= MB_DEFBUTTON2;
+ }
+ else // just "OK"
+ {
+ msStyle = MB_OK;
+ }
+ }
+
+ if ( wxStyle & wxHELP )
+ {
+ msStyle |= MB_HELP;
+ }
+
+ // set the icon style
+ switch ( GetEffectiveIcon() )
+ {
+ case wxICON_ERROR:
+ msStyle |= MB_ICONHAND;
+ break;
+
+ case wxICON_WARNING:
+ msStyle |= MB_ICONEXCLAMATION;
+ break;
+
+ case wxICON_QUESTION:
+ msStyle |= MB_ICONQUESTION;
+ break;
+
+ case wxICON_INFORMATION:
+ msStyle |= MB_ICONINFORMATION;
+ break;
+ }
+
+ if ( wxStyle & wxSTAY_ON_TOP )
+ msStyle |= MB_TOPMOST;
+
+#ifndef __WXWINCE__
+ if ( wxTheApp->GetLayoutDirection() == wxLayout_RightToLeft )
+ msStyle |= MB_RTLREADING | MB_RIGHT;
+#endif
+
+ if (hWnd)
+ msStyle |= MB_APPLMODAL;