]> git.saurik.com Git - wxWidgets.git/blobdiff - src/msw/button.cpp
Handle the case of NSNotFound result properly.
[wxWidgets.git] / src / msw / button.cpp
index b789a6ccc2cae4e4aeae93fb15234e5b0ffee5e5..67494356d6945d474ca012e5e00d19d34b62f29c 100644 (file)
@@ -37,9 +37,9 @@
     #include "wx/dcscreen.h"
     #include "wx/dcclient.h"
     #include "wx/toplevel.h"
     #include "wx/dcscreen.h"
     #include "wx/dcclient.h"
     #include "wx/toplevel.h"
-    #include "wx/imaglist.h"
 #endif
 
 #endif
 
+#include "wx/imaglist.h"
 #include "wx/stockitem.h"
 #include "wx/msw/private.h"
 #include "wx/msw/private/button.h"
 #include "wx/stockitem.h"
 #include "wx/msw/private.h"
 #include "wx/msw/private/button.h"
@@ -145,7 +145,7 @@ public:
 
         // we use margins when we have both bitmap and text, but when we have
         // only the bitmap it should take up the entire button area
 
         // we use margins when we have both bitmap and text, but when we have
         // only the bitmap it should take up the entire button area
-        if ( !btn->GetLabel().empty() )
+        if ( btn->ShowsLabel() )
         {
             m_margin.x = btn->GetCharWidth();
             m_margin.y = btn->GetCharHeight() / 2;
         {
             m_margin.x = btn->GetCharWidth();
             m_margin.y = btn->GetCharHeight() / 2;
@@ -423,7 +423,7 @@ void wxMSWButton::UpdateMultilineStyle(HWND hwnd, const wxString& label)
     // the control unless it already has new lines in its label)
     long styleOld = ::GetWindowLong(hwnd, GWL_STYLE),
          styleNew;
     // the control unless it already has new lines in its label)
     long styleOld = ::GetWindowLong(hwnd, GWL_STYLE),
          styleNew;
-    if ( label.find(_T('\n')) != wxString::npos )
+    if ( label.find(wxT('\n')) != wxString::npos )
         styleNew = styleOld | BS_MULTILINE;
     else
         styleNew = styleOld & ~BS_MULTILINE;
         styleNew = styleOld | BS_MULTILINE;
     else
         styleNew = styleOld & ~BS_MULTILINE;
@@ -509,7 +509,7 @@ bool wxButton::Create(wxWindow *parent,
     //     value and the label is not set yet when MSWGetStyle() is called
     msStyle |= wxMSWButton::GetMultilineStyle(label);
 
     //     value and the label is not set yet when MSWGetStyle() is called
     msStyle |= wxMSWButton::GetMultilineStyle(label);
 
-    return MSWCreateControl(_T("BUTTON"), msStyle, pos, size, label, exstyle);
+    return MSWCreateControl(wxT("BUTTON"), msStyle, pos, size, label, exstyle);
 }
 
 wxButton::~wxButton()
 }
 
 wxButton::~wxButton()
@@ -574,8 +574,10 @@ wxSize wxButton::DoGetBestSize() const
 {
     wxSize size;
 
 {
     wxSize size;
 
-    // account for the text part
-    if ( !GetLabel().empty() )
+    // account for the text part if we have it or if we don't have any image at
+    // all (buttons initially created with empty label should still have a non
+    // zero size)
+    if ( ShowsLabel() || !m_imageData )
     {
         size = wxMSWButton::ComputeBestSize(const_cast<wxButton *>(this));
     }
     {
         size = wxMSWButton::ComputeBestSize(const_cast<wxButton *>(this));
     }
@@ -601,42 +603,45 @@ wxSize wxButton::DoGetBestSize() const
         // account for the user-specified margins
         size += 2*m_imageData->GetBitmapMargins();
 
         // account for the user-specified margins
         size += 2*m_imageData->GetBitmapMargins();
 
-        // and also for the margins we always add internally
-        int marginH = 0,
-            marginV = 0;
-#if wxUSE_UXTHEME
-        if ( wxUxThemeEngine::GetIfActive() )
+        // and also for the margins we always add internally (unless we have no
+        // border at all in which case the button has exactly the same size as
+        // bitmap and so no margins should be used)
+        if ( !HasFlag(wxBORDER_NONE) )
         {
         {
-            wxUxThemeHandle theme(const_cast<wxButton *>(this), L"BUTTON");
+            int marginH = 0,
+                marginV = 0;
+#if wxUSE_UXTHEME
+            if ( wxUxThemeEngine::GetIfActive() )
+            {
+                wxUxThemeHandle theme(const_cast<wxButton *>(this), L"BUTTON");
 
 
-            MARGINS margins;
-            wxUxThemeEngine::Get()->GetThemeMargins(theme, NULL,
-                                                    BP_PUSHBUTTON, PBS_NORMAL,
-                                                    TMT_CONTENTMARGINS, NULL,
-                                                    &margins);
+                MARGINS margins;
+                wxUxThemeEngine::Get()->GetThemeMargins(theme, NULL,
+                                                        BP_PUSHBUTTON,
+                                                        PBS_NORMAL,
+                                                        TMT_CONTENTMARGINS,
+                                                        NULL,
+                                                        &margins);
 
 
-            // XP doesn't draw themed buttons correctly when the client area is
-            // smaller than 8x8 - enforce this minimum size for small bitmaps
-            size.IncTo(wxSize(8, 8));
+                // XP doesn't draw themed buttons correctly when the client
+                // area is smaller than 8x8 - enforce this minimum size for
+                // small bitmaps
+                size.IncTo(wxSize(8, 8));
 
 
-            // don't add margins for the borderless buttons, they don't need
-            // them and it just makes them appear larger than needed
-            if ( !HasFlag(wxBORDER_NONE) )
-            {
                 marginH = margins.cxLeftWidth + margins.cxRightWidth
                             + 2*XP_BUTTON_EXTRA_MARGIN;
                 marginV = margins.cyTopHeight + margins.cyBottomHeight
                             + 2*XP_BUTTON_EXTRA_MARGIN;
             }
                 marginH = margins.cxLeftWidth + margins.cxRightWidth
                             + 2*XP_BUTTON_EXTRA_MARGIN;
                 marginV = margins.cyTopHeight + margins.cyBottomHeight
                             + 2*XP_BUTTON_EXTRA_MARGIN;
             }
-        }
-        else
+            else
 #endif // wxUSE_UXTHEME
 #endif // wxUSE_UXTHEME
-        {
-            marginH =
-            marginV = OD_BUTTON_MARGIN;
-        }
+            {
+                marginH =
+                marginV = OD_BUTTON_MARGIN;
+            }
 
 
-        size.IncBy(marginH, marginV);
+            size.IncBy(marginH, marginV);
+        }
 
         CacheBestSize(size);
     }
 
         CacheBestSize(size);
     }
@@ -674,6 +679,14 @@ wxSize wxButtonBase::GetDefaultSize()
 // ----------------------------------------------------------------------------
 
 /*
 // ----------------------------------------------------------------------------
 
 /*
+   The comment below and all this code is probably due to not using WM_NEXTDLGCTL
+   message when changing focus (but just SetFocus() which is not enough), see
+   http://blogs.msdn.com/oldnewthing/archive/2004/08/02/205624.aspx for the
+   full explanation.
+
+   TODO: Do use WM_NEXTDLGCTL and get rid of all this code.
+
+
    "Everything you ever wanted to know about the default buttons" or "Why do we
    have to do all this?"
 
    "Everything you ever wanted to know about the default buttons" or "Why do we
    have to do all this?"
 
@@ -740,10 +753,10 @@ static wxTopLevelWindow *GetTLWParentIfNotBeingDeleted(wxWindow *win)
         win = parent;
     }
 
         win = parent;
     }
 
-    wxASSERT_MSG( win, _T("button without top level parent?") );
+    wxASSERT_MSG( win, wxT("button without top level parent?") );
 
     wxTopLevelWindow * const tlw = wxDynamicCast(win, wxTopLevelWindow);
 
     wxTopLevelWindow * const tlw = wxDynamicCast(win, wxTopLevelWindow);
-    wxASSERT_MSG( tlw, _T("logic error in GetTLWParentIfNotBeingDeleted()") );
+    wxASSERT_MSG( tlw, wxT("logic error in GetTLWParentIfNotBeingDeleted()") );
 
     return tlw;
 }
 
     return tlw;
 }
@@ -795,7 +808,7 @@ wxButton::SetDefaultStyle(wxButton *btn, bool on)
             return;
 
         wxWindow * const tlw = wxGetTopLevelParent(btn);
             return;
 
         wxWindow * const tlw = wxGetTopLevelParent(btn);
-        wxCHECK_RET( tlw, _T("button without top level window?") );
+        wxCHECK_RET( tlw, wxT("button without top level window?") );
 
         ::SendMessage(GetHwndOf(tlw), DM_SETDEFID, btn->GetId(), 0L);
 
 
         ::SendMessage(GetHwndOf(tlw), DM_SETDEFID, btn->GetId(), 0L);
 
@@ -946,7 +959,7 @@ void wxButton::DoSetBitmap(const wxBitmap& bitmap, State which)
         // (even if we use BUTTON_IMAGELIST_ALIGN_CENTER alignment and
         // BS_BITMAP style), at least under Windows 2003 so use owner drawn
         // strategy for bitmap-only buttons
         // (even if we use BUTTON_IMAGELIST_ALIGN_CENTER alignment and
         // BS_BITMAP style), at least under Windows 2003 so use owner drawn
         // strategy for bitmap-only buttons
-        if ( !GetLabel().empty() && wxUxThemeEngine::GetIfActive() )
+        if ( ShowsLabel() && wxUxThemeEngine::GetIfActive() )
         {
             m_imageData = new wxXPButtonImageData(this, bitmap);
         }
         {
             m_imageData = new wxXPButtonImageData(this, bitmap);
         }
@@ -956,16 +969,18 @@ void wxButton::DoSetBitmap(const wxBitmap& bitmap, State which)
             m_imageData = new wxODButtonImageData(this, bitmap);
             MakeOwnerDrawn();
         }
             m_imageData = new wxODButtonImageData(this, bitmap);
             MakeOwnerDrawn();
         }
-
-        // if a bitmap was assigned to the bitmap, its best size must be
-        // changed to account for it
-        InvalidateBestSize();
     }
     else
     {
         m_imageData->SetBitmap(bitmap, which);
     }
 
     }
     else
     {
         m_imageData->SetBitmap(bitmap, which);
     }
 
+    // it should be enough to only invalidate the best size when the normal
+    // bitmap changes as all bitmaps assigned to the button should be of the
+    // same size anyhow
+    if ( which == State_Normal )
+        InvalidateBestSize();
+
     Refresh();
 }
 
     Refresh();
 }
 
@@ -1027,7 +1042,7 @@ void DrawButtonText(HDC hdc,
     // center text horizontally in any case
     flags |= DT_CENTER;
 
     // center text horizontally in any case
     flags |= DT_CENTER;
 
-    if ( text.find(_T('\n')) != wxString::npos )
+    if ( text.find(wxT('\n')) != wxString::npos )
     {
         // draw multiline label
 
     {
         // draw multiline label
 
@@ -1262,51 +1277,52 @@ bool wxButton::MSWOnDraw(WXDRAWITEMSTRUCT *wxdis)
     RECT rectBtn;
     CopyRect(&rectBtn, &lpDIS->rcItem);
 
     RECT rectBtn;
     CopyRect(&rectBtn, &lpDIS->rcItem);
 
-    const wxString label = GetLabel();
-
     // draw the button background
     // draw the button background
-#if wxUSE_UXTHEME
-    if ( wxUxThemeEngine::GetIfActive() )
+    if ( !HasFlag(wxBORDER_NONE) )
     {
     {
-        DrawXPBackground(this, hdc, rectBtn, state);
-    }
-    else
+#if wxUSE_UXTHEME
+        if ( wxUxThemeEngine::GetIfActive() )
+        {
+            DrawXPBackground(this, hdc, rectBtn, state);
+        }
+        else
 #endif // wxUSE_UXTHEME
 #endif // wxUSE_UXTHEME
-    {
-        COLORREF colBg = wxColourToRGB(GetBackgroundColour());
+        {
+            COLORREF colBg = wxColourToRGB(GetBackgroundColour());
 
 
-        // first, draw the background
-        AutoHBRUSH hbrushBackground(colBg);
-        FillRect(hdc, &rectBtn, hbrushBackground);
+            // first, draw the background
+            AutoHBRUSH hbrushBackground(colBg);
+            FillRect(hdc, &rectBtn, hbrushBackground);
 
 
-        // draw the border for the current state
-        bool selected = (state & ODS_SELECTED) != 0;
-        if ( !selected )
-        {
-            wxTopLevelWindow *
-                tlw = wxDynamicCast(wxGetTopLevelParent(this), wxTopLevelWindow);
-            if ( tlw )
+            // draw the border for the current state
+            bool selected = (state & ODS_SELECTED) != 0;
+            if ( !selected )
             {
             {
-                selected = tlw->GetDefaultItem() == this;
+                wxTopLevelWindow *
+                    tlw = wxDynamicCast(wxGetTopLevelParent(this), wxTopLevelWindow);
+                if ( tlw )
+                {
+                    selected = tlw->GetDefaultItem() == this;
+                }
             }
             }
-        }
 
 
-        DrawButtonFrame(hdc, rectBtn, selected, pushed);
-    }
+            DrawButtonFrame(hdc, rectBtn, selected, pushed);
+        }
 
 
-    // draw the focus rectangle if we need it
-    if ( (state & ODS_FOCUS) && !(state & ODS_NOFOCUSRECT) )
-    {
-        DrawFocusRect(hdc, &rectBtn);
+        // draw the focus rectangle if we need it
+        if ( (state & ODS_FOCUS) && !(state & ODS_NOFOCUSRECT) )
+        {
+            DrawFocusRect(hdc, &rectBtn);
 
 #if wxUSE_UXTHEME
 
 #if wxUSE_UXTHEME
-        if ( !wxUxThemeEngine::GetIfActive() )
+            if ( !wxUxThemeEngine::GetIfActive() )
 #endif // wxUSE_UXTHEME
 #endif // wxUSE_UXTHEME
-        {
-            if ( pushed )
             {
             {
-                // the label is shifted by 1 pixel to create "pushed" effect
-                OffsetRect(&rectBtn, 1, 1);
+                if ( pushed )
+                {
+                    // the label is shifted by 1 pixel to create "pushed" effect
+                    OffsetRect(&rectBtn, 1, 1);
+                }
             }
         }
     }
             }
         }
     }
@@ -1364,7 +1380,7 @@ bool wxButton::MSWOnDraw(WXDRAWITEMSTRUCT *wxdis)
 
 
     // finally draw the label
 
 
     // finally draw the label
-    if ( !label.empty() )
+    if ( ShowsLabel() )
     {
         COLORREF colFg = state & ODS_DISABLED
                             ? ::GetSysColor(COLOR_GRAYTEXT)
     {
         COLORREF colFg = state & ODS_DISABLED
                             ? ::GetSysColor(COLOR_GRAYTEXT)
@@ -1373,7 +1389,7 @@ bool wxButton::MSWOnDraw(WXDRAWITEMSTRUCT *wxdis)
         // notice that DT_HIDEPREFIX doesn't work on old (pre-Windows 2000)
         // systems but by happy coincidence ODS_NOACCEL is not used under them
         // neither so DT_HIDEPREFIX should never be used there
         // notice that DT_HIDEPREFIX doesn't work on old (pre-Windows 2000)
         // systems but by happy coincidence ODS_NOACCEL is not used under them
         // neither so DT_HIDEPREFIX should never be used there
-        DrawButtonText(hdc, &rectBtn, label, colFg,
+        DrawButtonText(hdc, &rectBtn, GetLabel(), colFg,
                        state & ODS_NOACCEL ? DT_HIDEPREFIX : 0);
     }
 
                        state & ODS_NOACCEL ? DT_HIDEPREFIX : 0);
     }