1 /////////////////////////////////////////////////////////////////////////////
2 // Name:        src/msw/commandlinkbutton.cpp
3 // Purpose:     wxCommandLinkButton
4 // Author:      Rickard Westerlund
5 // Created:     2010-06-14
6 // Copyright:   (c) 2010 wxWidgets team
7 // Licence:     wxWindows licence
8 /////////////////////////////////////////////////////////////////////////////
9 
10 // ----------------------------------------------------------------------------
11 // headers
12 // ----------------------------------------------------------------------------
13 
14 // For compilers that support precompilation, includes "wx.h".
15 #include "wx/wxprec.h"
16 
17 #ifdef __BORLANDC__
18     #pragma hdrstop
19 #endif
20 
21 #if wxUSE_COMMANDLINKBUTTON
22 
23 #ifndef WX_PRECOMP
24     #include "wx/app.h"
25     #include "wx/dcclient.h"
26 #endif
27 
28 #include "wx/commandlinkbutton.h"
29 #include "wx/msw/private.h"
30 #include "wx/msw/private/button.h"
31 #include "wx/msw/private/dc.h"
32 #include "wx/private/window.h"
33 
34 #ifndef BCM_SETNOTE
35     #define BCM_SETNOTE 0x1609
36 #endif
37 
38 #ifndef BS_COMMANDLINK
39     #define BS_COMMANDLINK 0xE
40 #endif
41 
42 // ----------------------------------------------------------------------------
43 // Helper functions
44 // ----------------------------------------------------------------------------
45 
46 namespace
47 {
48 
HasNativeCommandLinkButton()49 inline bool HasNativeCommandLinkButton()
50 {
51     return wxGetWinVersion() >= wxWinVersion_6;
52 }
53 
54 } // anonymous namespace
55 
56 // ----------------------------------------------------------------------------
57 // Command link button
58 // ----------------------------------------------------------------------------
59 
Create(wxWindow * parent,wxWindowID id,const wxString & mainLabel,const wxString & note,const wxPoint & pos,const wxSize & size,long style,const wxValidator & validator,const wxString & name)60 bool wxCommandLinkButton::Create(wxWindow *parent,
61                                  wxWindowID id,
62                                  const wxString& mainLabel,
63                                  const wxString& note,
64                                  const wxPoint& pos,
65                                  const wxSize& size,
66                                  long style,
67                                  const wxValidator& validator,
68                                  const wxString& name)
69 {
70     if ( ! wxGenericCommandLinkButton::Create(parent,
71                                               id,
72                                               mainLabel,
73                                               note,
74                                               pos,
75                                               size,
76                                               style,
77                                               validator,
78                                               name) )
79         return false;
80 
81     SetMainLabelAndNote(mainLabel, note);
82     SetInitialSize();
83 
84     return true;
85 }
86 
87 void
SetMainLabelAndNote(const wxString & mainLabel,const wxString & note)88 wxCommandLinkButton::SetMainLabelAndNote(const wxString& mainLabel,
89                                          const wxString& note)
90 {
91     if ( HasNativeCommandLinkButton() )
92     {
93         wxButton::SetLabel(mainLabel);
94         ::SendMessage(m_hWnd, BCM_SETNOTE, 0, wxMSW_CONV_LPARAM(note));
95 
96         // Preserve the user-specified label for GetLabel()
97         m_labelOrig = mainLabel;
98         if ( !note.empty() )
99             m_labelOrig << '\n' << note;
100     }
101     else
102     {
103         wxGenericCommandLinkButton::SetMainLabelAndNote(mainLabel, note);
104     }
105 }
106 
MSWGetStyle(long style,WXDWORD * exstyle) const107 WXDWORD wxCommandLinkButton::MSWGetStyle(long style, WXDWORD *exstyle) const
108 {
109     WXDWORD ret = wxButton::MSWGetStyle(style, exstyle);
110     if ( HasNativeCommandLinkButton() )
111         ret |= BS_COMMANDLINK;
112 
113     return ret;
114 }
115 
HasNativeBitmap() const116 bool wxCommandLinkButton::HasNativeBitmap() const
117 {
118     return HasNativeCommandLinkButton();
119 }
120 
121 // ----------------------------------------------------------------------------
122 // size management including autosizing
123 // ----------------------------------------------------------------------------
124 
125 // Margin measures can be found at
126 // http://expression.microsoft.com/en-us/ee662150.aspx
127 namespace
128 {
129     const int MAINLABEL_TOP_MARGIN = 16; // Includes image top margin.
130     const int MAINLABEL_NOTE_LEFT_MARGIN = 23;
131     const int NOTE_TOP_MARGIN = 21;
132     const int NOTE_BOTTOM_MARGIN = 1;
133     const int MAINLABEL_NOTE_MARGIN = NOTE_TOP_MARGIN - MAINLABEL_TOP_MARGIN;
134 };
135 
DoGetBestSize() const136 wxSize wxCommandLinkButton::DoGetBestSize() const
137 {
138     wxSize size;
139 
140     // account for the text part if we have it or if we don't have any image at
141     // all (buttons initially created with empty label should still have a non
142     // zero size)
143     if ( ShowsLabel() || !m_imageData )
144     {
145         int flags = 0;
146         if ( GetAuthNeeded() )
147             flags |= wxMSWButton::Size_AuthNeeded;
148 
149         wxCommandLinkButton *thisButton =
150             const_cast<wxCommandLinkButton *>(this);
151         wxClientDC dc(thisButton);
152 
153         wxFont noteFont = dc.GetFont();
154 
155         // 4/3 is the relationship between main label and note font sizes.
156         dc.SetFont(noteFont.Scaled(4.0f/3.0f));
157         size = dc.GetMultiLineTextExtent(GetLabelText(GetMainLabel()));
158 
159         dc.SetFont(noteFont);
160         wxSize noteSize = dc.GetMultiLineTextExtent(GetLabelText(GetNote()));
161 
162         if ( noteSize.x > size.x )
163             size.x = noteSize.x;
164         size.y += noteSize.y;
165 
166         size = wxMSWButton::GetFittingSize(thisButton,
167                                            size,
168                                            flags);
169 
170         // The height of a standard command link button is 25 and 35 DLUs for
171         // single lines and two lines respectively. Width is not accounted for.
172         int heightDef = GetNote().AfterFirst('\n').empty() ? 25 : 35;
173         wxSize sizeDef = thisButton->ConvertDialogToPixels(wxSize(50,
174                                                                   heightDef));
175 
176         if ( size.y < sizeDef.y )
177             size.y = sizeDef.y;
178     }
179 
180     if ( m_imageData )
181     {
182         AdjustForBitmapSize(size);
183     }
184     else
185     {
186         // The default image size is 16x16.
187         size.x += 16;
188         if ( size.y < 16 )
189             size.y = 16;
190     }
191 
192     size.x += MAINLABEL_NOTE_LEFT_MARGIN;
193     size.y += MAINLABEL_TOP_MARGIN + NOTE_BOTTOM_MARGIN;
194     if ( !GetNote().empty() )
195         size.y += MAINLABEL_NOTE_MARGIN;
196 
197     CacheBestSize(size);
198 
199     return size;
200 }
201 
202 #endif // wxUSE_COMMANDLINKBUTTON
203