X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/86ac84b8ce086e6bbda58f422d41f84268606e35..15b850072622e84759c9592e1e591ecdee4aee1c:/src/msw/button.cpp diff --git a/src/msw/button.cpp b/src/msw/button.cpp index 39845f6cbf..2f68d8b362 100644 --- a/src/msw/button.cpp +++ b/src/msw/button.cpp @@ -37,13 +37,14 @@ #include "wx/dcscreen.h" #include "wx/dcclient.h" #include "wx/toplevel.h" - #include "wx/imaglist.h" #endif +#include "wx/imaglist.h" #include "wx/stockitem.h" #include "wx/msw/private.h" #include "wx/msw/private/button.h" #include "wx/msw/private/dc.h" +#include "wx/private/window.h" using namespace wxMSWImpl; @@ -423,7 +424,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; - if ( label.find(_T('\n')) != wxString::npos ) + if ( label.find(wxT('\n')) != wxString::npos ) styleNew = styleOld | BS_MULTILINE; else styleNew = styleOld & ~BS_MULTILINE; @@ -457,7 +458,10 @@ wxSize wxMSWButton::ComputeBestSize(wxControl *btn) // creating the button if ( !btn->HasFlag(wxBU_EXACTFIT) ) { - wxSize sizeDef = wxButton::GetDefaultSize(); + // The size of a standard button in the dialog units is 50x14, use it. + // Note that we intentionally don't use GetDefaultSize() here, because + // it's inexact -- dialog units depend on this dialog's font. + wxSize sizeDef = btn->ConvertDialogToPixels(wxSize(50, 14)); if ( sizeBtn.x < sizeDef.x ) sizeBtn.x = sizeDef.x; if ( sizeBtn.y < sizeDef.y ) @@ -509,7 +513,7 @@ bool wxButton::Create(wxWindow *parent, // 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() @@ -574,8 +578,10 @@ wxSize wxButton::DoGetBestSize() const { wxSize size; - // account for the text part - if ( ShowsLabel() ) + // 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(this)); } @@ -657,16 +663,20 @@ wxSize wxButtonBase::GetDefaultSize() wxScreenDC dc; dc.SetFont(wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT)); - // the size of a standard button in the dialog units is 50x14, - // translate this to pixels - // NB1: the multipliers come from the Windows convention - // NB2: the extra +1/+2 were needed to get the size be the same as the - // size of the buttons in the standard dialog - I don't know how - // this happens, but on my system this size is 75x23 in pixels and - // 23*8 isn't even divisible by 14... Would be nice to understand - // why these constants are needed though! - s_sizeBtn.x = (50 * (dc.GetCharWidth() + 1))/4; - s_sizeBtn.y = ((14 * dc.GetCharHeight()) + 2)/8; + // The size of a standard button in the dialog units is 50x14, + // translate this to pixels. + // + // Windows' computes dialog units using average character width over + // upper- and lower-case ASCII alphabet and not using the average + // character width metadata stored in the font; see + // http://support.microsoft.com/default.aspx/kb/145994 for detailed + // discussion. + // + // NB: wxMulDivInt32() is used, because it correctly rounds the result + + const wxSize base = wxPrivate::GetAverageASCIILetterSize(dc); + s_sizeBtn.x = wxMulDivInt32(50, base.x, 4); + s_sizeBtn.y = wxMulDivInt32(14, base.y, 8); } return s_sizeBtn; @@ -677,6 +687,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?" @@ -743,10 +761,10 @@ static wxTopLevelWindow *GetTLWParentIfNotBeingDeleted(wxWindow *win) 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); - wxASSERT_MSG( tlw, _T("logic error in GetTLWParentIfNotBeingDeleted()") ); + wxASSERT_MSG( tlw, wxT("logic error in GetTLWParentIfNotBeingDeleted()") ); return tlw; } @@ -798,7 +816,7 @@ wxButton::SetDefaultStyle(wxButton *btn, bool on) 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); @@ -959,16 +977,18 @@ void wxButton::DoSetBitmap(const wxBitmap& bitmap, State which) 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); } + // 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(); } @@ -1030,7 +1050,7 @@ void DrawButtonText(HDC hdc, // 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