]> git.saurik.com Git - wxWidgets.git/blobdiff - src/msw/msgdlg.cpp
Tidy up the ie backend a little, make sure all com objects are correctly released.
[wxWidgets.git] / src / msw / msgdlg.cpp
index 50191c6f77c09a6ef4ddb47da755d5288cbf3942..2334638d8294480e4f9bb01f7cff302c8445cffa 100644 (file)
@@ -18,8 +18,6 @@
 
 #if wxUSE_MSGDLG
 
-#include "wx/ptr_scpd.h"
-
 // there is no hook support under CE so we can't use the code for message box
 // positioning there
 #ifndef __WXWINCE__
 #endif
 
 #ifndef WX_PRECOMP
+    #include "wx/msgdlg.h"
     #include "wx/app.h"
     #include "wx/intl.h"
     #include "wx/utils.h"
-    #include "wx/dialog.h"
+    #include "wx/msw/private.h"
     #if wxUSE_MSGBOX_HOOK
         #include "wx/hashmap.h"
     #endif
 #endif
 
+#include "wx/ptr_scpd.h"
 #include "wx/dynlib.h"
-#include "wx/msw/private.h"
 #include "wx/msw/private/button.h"
 #include "wx/msw/private/metrics.h"
 #include "wx/msw/private/msgdlg.h"
-#include "wx/msgdlg.h"
 
 #if wxUSE_MSGBOX_HOOK
     #include "wx/fontutil.h"
@@ -255,8 +253,10 @@ void wxMessageDialog::ReplaceStaticWithEdit()
     {
         if ( *i != '\n' )
         {
-            // found last non-newline char, remove everything after it and stop
-            text.erase(i.base() + 1, text.end());
+            // found last non-newline char, remove anything after it if
+            // necessary and stop in any case
+            if ( i != text.rbegin() )
+                text.erase(i.base() + 1, text.end());
             break;
         }
     }
@@ -573,41 +573,44 @@ int wxMessageDialog::ShowMessageBox()
     return MSWTranslateReturnCode(msAns);
 }
 
-int wxMessageDialog::ShowTaskDialog()
+int wxMessageDialog::ShowModal()
 {
 #ifdef wxHAS_MSW_TASKDIALOG
-    TaskDialogIndirect_t taskDialogIndirect = GetTaskDialogIndirectFunc();
-    if ( !taskDialogIndirect )
-        return wxID_CANCEL;
-
-    WinStruct<TASKDIALOGCONFIG> tdc;
-    wxMSWTaskDialogConfig wxTdc( *this );
-    wxTdc.MSWCommonTaskDialogInit( tdc );
-
-    int msAns;
-    HRESULT hr = taskDialogIndirect( &tdc, &msAns, NULL, NULL );
-    if ( FAILED(hr) )
+    if ( HasNativeTaskDialog() )
     {
-        wxLogApiError( "TaskDialogIndirect", hr );
-        return wxID_CANCEL;
-    }
+        TaskDialogIndirect_t taskDialogIndirect = GetTaskDialogIndirectFunc();
+        wxCHECK_MSG( taskDialogIndirect, wxID_CANCEL, wxS("no task dialog?") );
 
-    return MSWTranslateReturnCode( msAns );
-#else
-    wxFAIL_MSG( "Task dialogs are unavailable." );
+        WinStruct<TASKDIALOGCONFIG> tdc;
+        wxMSWTaskDialogConfig wxTdc( *this );
+        wxTdc.MSWCommonTaskDialogInit( tdc );
 
-    return wxID_CANCEL;
-#endif // wxHAS_MSW_TASKDIALOG
-}
+        int msAns;
+        HRESULT hr = taskDialogIndirect( &tdc, &msAns, NULL, NULL );
+        if ( FAILED(hr) )
+        {
+            wxLogApiError( "TaskDialogIndirect", hr );
+            return wxID_CANCEL;
+        }
 
+        return MSWTranslateReturnCode( msAns );
+    }
+#endif // wxHAS_MSW_TASKDIALOG
 
+    return ShowMessageBox();
+}
 
-int wxMessageDialog::ShowModal()
+void wxMessageDialog::DoCentre(int dir)
 {
+#ifdef wxHAS_MSW_TASKDIALOG
+    // Task dialog is always centered on its parent window and trying to center
+    // it manually doesn't work because its HWND is not created yet so don't
+    // even try as this would only result in (debug) error messages.
     if ( HasNativeTaskDialog() )
-        return ShowTaskDialog();
+        return;
+#endif // wxHAS_MSW_TASKDIALOG
 
-    return ShowMessageBox();
+    wxMessageDialogBase::DoCentre(dir);
 }
 
 // ----------------------------------------------------------------------------
@@ -623,6 +626,28 @@ wxMSWTaskDialogConfig::wxMSWTaskDialogConfig(const wxMessageDialogBase& dlg)
     caption = dlg.GetCaption();
     message = dlg.GetMessage();
     extendedMessage = dlg.GetExtendedMessage();
+
+    // Before wxMessageDialog added support for extended message it was common
+    // practice to have long multiline texts in the message box with the first
+    // line playing the role of the main message and the rest of the extended
+    // one. Try to detect such usage automatically here by synthesizing the
+    // extended message on our own if it wasn't given.
+    if ( extendedMessage.empty() )
+    {
+        // Check if there is a blank separating line after the first line (this
+        // is not the same as searching for "\n\n" as we want the automatically
+        // recognized main message be single line to avoid embarrassing false
+        // positives).
+        const size_t posNL = message.find('\n');
+        if ( posNL != wxString::npos &&
+                posNL < message.length() - 1 &&
+                    message[posNL + 1 ] == '\n' )
+        {
+            extendedMessage.assign(message, posNL + 2, wxString::npos);
+            message.erase(posNL);
+        }
+    }
+
     iconId = dlg.GetEffectiveIcon();
     style = dlg.GetMessageDialogStyle();
     useCustomLabels = dlg.HasCustomLabels();
@@ -643,8 +668,23 @@ void wxMSWTaskDialogConfig::MSWCommonTaskDialogInit(TASKDIALOGCONFIG &tdc)
 
     if ( wxTheApp->GetLayoutDirection() == wxLayout_RightToLeft )
         tdc.dwFlags |= TDF_RTL_LAYOUT;
-    tdc.pszMainInstruction = message.wx_str();
-    tdc.pszContent = extendedMessage.wx_str();
+
+    // If we have both the main and extended messages, just use them as
+    // intended. However if only one message is given we normally use it as the
+    // content and not as the main instruction because the latter is supposed
+    // to stand out compared to the former and doesn't look good if there is
+    // nothing for it to contrast with. Finally, notice that the extended
+    // message we use here might be automatically extracted from the main
+    // message in our ctor, see comment there.
+    if ( !extendedMessage.empty() )
+    {
+        tdc.pszMainInstruction = message.wx_str();
+        tdc.pszContent = extendedMessage.wx_str();
+    }
+    else
+    {
+        tdc.pszContent = message.wx_str();
+    }
 
     // set an icon to be used, if possible
     switch ( iconId )
@@ -681,16 +721,29 @@ void wxMSWTaskDialogConfig::MSWCommonTaskDialogInit(TASKDIALOGCONFIG &tdc)
     }
     else // without Yes/No we're going to have an OK button
     {
-        AddTaskDialogButton(tdc, IDOK, TDCBF_OK_BUTTON, btnOKLabel);
-
         if ( style & wxCANCEL )
         {
+            AddTaskDialogButton(tdc, IDOK, TDCBF_OK_BUTTON, btnOKLabel);
             AddTaskDialogButton(tdc, IDCANCEL,
                                 TDCBF_CANCEL_BUTTON, btnCancelLabel);
 
             if ( style & wxCANCEL_DEFAULT )
                 tdc.nDefaultButton = IDCANCEL;
         }
+        else // Only "OK"
+        {
+            // We actually create a "Cancel" button instead because we want to
+            // allow closing the dialog box with Escape (and also Alt-F4 or
+            // clicking the close button in the title bar) which wouldn't work
+            // without a Cancel button.
+            if ( !useCustomLabels )
+            {
+                useCustomLabels = true;
+                btnOKLabel = _("OK");
+            }
+
+            AddTaskDialogButton(tdc, IDCANCEL, TDCBF_CANCEL_BUTTON, btnOKLabel);
+        }
     }
 }
 
@@ -721,19 +774,20 @@ wxCRIT_SECT_DECLARE(gs_csTaskDialogIndirect);
 
 TaskDialogIndirect_t wxMSWMessageDialog::GetTaskDialogIndirectFunc()
 {
-    static TaskDialogIndirect_t s_TaskDialogIndirect = NULL;
+    // Initialize the function pointer to an invalid value different from NULL
+    // to avoid reloading comctl32.dll and trying to resolve it every time
+    // we're called if task dialog is not available (notice that this may
+    // happen even under Vista+ if we don't use comctl32.dll v6).
+    static const TaskDialogIndirect_t
+        INVALID_TASKDIALOG_FUNC = reinterpret_cast<TaskDialogIndirect_t>(-1);
+    static TaskDialogIndirect_t s_TaskDialogIndirect = INVALID_TASKDIALOG_FUNC;
 
     wxCRIT_SECT_LOCKER(lock, gs_csTaskDialogIndirect);
 
-    if ( !s_TaskDialogIndirect )
+    if ( s_TaskDialogIndirect == INVALID_TASKDIALOG_FUNC )
     {
         wxLoadedDLL dllComCtl32("comctl32.dll");
         wxDL_INIT_FUNC(s_, TaskDialogIndirect, dllComCtl32);
-
-        // We must always succeed as this code is only executed under Vista and
-        // later which must have task dialog support.
-        wxASSERT_MSG( s_TaskDialogIndirect,
-                      "Task dialog support unexpectedly not available" );
     }
 
     return s_TaskDialogIndirect;
@@ -744,10 +798,14 @@ TaskDialogIndirect_t wxMSWMessageDialog::GetTaskDialogIndirectFunc()
 bool wxMSWMessageDialog::HasNativeTaskDialog()
 {
 #ifdef wxHAS_MSW_TASKDIALOG
-    return wxGetWinVersion() >= wxWinVersion_6;
-#else
+    if ( wxGetWinVersion() >= wxWinVersion_6 )
+    {
+        if ( wxMSWMessageDialog::GetTaskDialogIndirectFunc() )
+            return true;
+    }
+#endif // wxHAS_MSW_TASKDIALOG
+
     return false;
-#endif
 }
 
 int wxMSWMessageDialog::MSWTranslateReturnCode(int msAns)