X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/d1477745151751c22989d22886893389d82e1deb..300aaa8f77daee5cd740c8c4cce63f40c6bfae4b:/src/msw/dialog.cpp diff --git a/src/msw/dialog.cpp b/src/msw/dialog.cpp index 480836f8f9..c7b8c547d1 100644 --- a/src/msw/dialog.cpp +++ b/src/msw/dialog.cpp @@ -116,8 +116,7 @@ bool wxDialog::Create(wxWindow *parent, wxWindowID id, SetBackgroundColour(wxSystemSettings::GetSystemColour(wxSYS_COLOUR_3DFACE)); SetName(name); - if (!parent) - wxTopLevelWindows.Append(this); + wxTopLevelWindows.Append(this); // windowFont = wxTheFontList->FindOrCreateFont(11, wxSWISS, wxNORMAL, wxNORMAL); @@ -154,6 +153,10 @@ bool wxDialog::Create(wxWindow *parent, wxWindowID id, if (m_windowStyle & wxSTAY_ON_TOP) extendedStyle |= WS_EX_TOPMOST; +#ifndef __WIN16__ + if (m_exStyle & wxDIALOG_EX_CONTEXTHELP) + extendedStyle |= WS_EX_CONTEXTHELP; +#endif // Allows creation of dialogs with & without captions under MSWindows, // resizeable or not (but a resizeable dialog always has caption - // otherwise it would look too strange) @@ -174,7 +177,7 @@ bool wxDialog::Create(wxWindow *parent, wxWindowID id, if ( !hwnd ) { - wxLogError(_("Failed to create dialog.")); + wxFAIL_MSG(_("Failed to create dialog. You probably forgot to include wx/msw/wx.rc in your resources.")); return FALSE; } @@ -235,24 +238,26 @@ wxDialog::~wxDialog() // By default, pressing escape cancels the dialog void wxDialog::OnCharHook(wxKeyEvent& event) { - if (GetHWND()) - { - if (event.m_keyCode == WXK_ESCAPE) + if (GetHWND()) { - // Behaviour changed in 2.0: we'll send a Cancel message - // to the dialog instead of Close. - wxCommandEvent cancelEvent(wxEVT_COMMAND_BUTTON_CLICKED, wxID_CANCEL); - cancelEvent.SetEventObject( this ); - GetEventHandler()->ProcessEvent(cancelEvent); - - // ensure that there is another message for this window so the - // ShowModal loop will exit and won't get stuck in GetMessage(). - ::PostMessage(GetHwnd(), WM_NULL, 0, 0); - return; + // "Esc" works as an accelerator for the "Cancel" button, but it + // shouldn't close the dialog which doesn't have any cancel button + if ( (event.m_keyCode == WXK_ESCAPE) && FindWindow(wxID_CANCEL) ) + { + wxCommandEvent cancelEvent(wxEVT_COMMAND_BUTTON_CLICKED, wxID_CANCEL); + cancelEvent.SetEventObject( this ); + GetEventHandler()->ProcessEvent(cancelEvent); + + // ensure that there is another message for this window so the + // ShowModal loop will exit and won't get stuck in GetMessage(). + ::PostMessage(GetHwnd(), WM_NULL, 0, 0); + + return; + } } - } - // We didn't process this event. - event.Skip(); + + // We didn't process this event. + event.Skip(); } // ---------------------------------------------------------------------------- @@ -322,52 +327,62 @@ bool wxDialog::IsModalShowing() const void wxDialog::DoShowModal() { wxCHECK_RET( !IsModalShowing(), _T("DoShowModal() called twice") ); + wxCHECK_RET( IsModal(), _T("can't DoShowModal() modeless dialog") ); wxModalDialogs.Append(this); wxWindow *parent = GetParent(); - // remember where the focus was - if ( !m_oldFocus ) - { - m_oldFocus = parent; - } - if ( !m_oldFocus ) - { - m_oldFocus = wxTheApp->GetTopWindow(); - } + wxWindow* oldFocus = m_oldFocus; - // disable the parent window first - HWND hwndParent = parent ? GetHwndOf(parent) : (HWND)NULL; - if ( hwndParent ) - { - ::EnableWindow(hwndParent, FALSE); - } + // We have to remember the HWND because we need to check + // the HWND still exists (oldFocus can be garbage when the dialog + // exits, if it has been destroyed) + HWND hwndOldFocus = 0; + if (oldFocus) + hwndOldFocus = (HWND) oldFocus->GetHWND(); - // enter the modal loop - while ( IsModalShowing() ) + // inside this block, all app windows are disabled { + wxWindowDisabler wd(this); + + // remember where the focus was + if ( !oldFocus ) + { + oldFocus = parent; + if (parent) + hwndOldFocus = (HWND) parent->GetHWND(); + } + + // enter the modal loop + while ( IsModalShowing() ) + { #if wxUSE_THREADS - wxMutexGuiLeaveOrEnter(); + wxMutexGuiLeaveOrEnter(); #endif // wxUSE_THREADS - while ( !wxTheApp->Pending() && wxTheApp->ProcessIdle() ) - ; + while ( !wxTheApp->Pending() && wxTheApp->ProcessIdle() ) + ; - // a message came or no more idle processing to do - wxTheApp->DoMessage(); + // a message came or no more idle processing to do + wxTheApp->DoMessage(); + } } - // reenable the parent window if any - if ( hwndParent ) - { - ::EnableWindow(hwndParent, TRUE); - } +#ifdef __WIN32__ + if ( parent ) + ::SetActiveWindow(GetHwndOf(parent)); +#endif // __WIN32__ // and restore focus - if ( m_oldFocus && (m_oldFocus != this) ) + // Note that this code MUST NOT access the dialog object's data + // in case the object has been deleted (which will be the case + // for a modal dialog that has been destroyed before calling EndModal). + if ( oldFocus && (oldFocus != this) && ::IsWindow(hwndOldFocus)) { - m_oldFocus->SetFocus(); + // This is likely to prove that the object still exists + if (wxFindWinFromHandle((WXHWND) hwndOldFocus) == oldFocus) + oldFocus->SetFocus(); } } @@ -403,6 +418,17 @@ bool wxDialog::Show(bool show) { if ( show ) { + // modal dialog needs a parent window, so try to find one + if ( !GetParent() ) + { + wxWindow *parent = wxTheApp->GetTopWindow(); + if ( parent && parent != this && parent->IsShown() ) + { + // use it + m_parent = parent; + } + } + DoShowModal(); } else // end of modal dialog @@ -416,11 +442,16 @@ bool wxDialog::Show(bool show) return TRUE; } -// Replacement for Show(TRUE) for modal dialogs - returns return code +// a special version for Show(TRUE) for modal dialogs which returns return code int wxDialog::ShowModal() { - m_windowStyle |= wxDIALOG_MODAL; + if ( !IsModal() ) + { + SetModal(TRUE); + } + Show(TRUE); + return GetReturnCode(); } @@ -521,6 +552,33 @@ long wxDialog::MSWWindowProc(WXUINT message, WXWPARAM wParam, WXLPARAM lParam) switch ( message ) { + case WM_ACTIVATE: + switch ( LOWORD(wParam) ) + { + case WA_ACTIVE: + case WA_CLICKACTIVE: + if ( IsModalShowing() && GetParent() ) + { + // bring the owner window to top as the standard dialog + // boxes do + if ( !::SetWindowPos + ( + GetHwndOf(GetParent()), + GetHwnd(), + 0, 0, + 0, 0, + SWP_NOACTIVATE | + SWP_NOMOVE | + SWP_NOSIZE + ) ) + { + wxLogLastError(wxT("SetWindowPos(SWP_NOACTIVATE)")); + } + } + // fall through to process it normally as well + } + break; + case WM_CLOSE: // if we can't close, tell the system that we processed the // message - otherwise it would close us