+WXLRESULT wxButton::MSWWindowProc(WXUINT nMsg, WXWPARAM wParam, WXLPARAM lParam)
+{
+ // when we receive focus, we want to temporarily become the default button in
+ // our parent panel so that pressing "Enter" would activate us -- and when
+ // losing it we should restore the previous default button as well
+ if ( nMsg == WM_SETFOCUS )
+ {
+ SetTmpDefault();
+
+ // let the default processing take place too
+ }
+ else if ( nMsg == WM_KILLFOCUS )
+ {
+ UnsetTmpDefault();
+ }
+ else if ( nMsg == WM_LBUTTONDBLCLK )
+ {
+ // emulate a click event to force an owner-drawn button to change its
+ // appearance - without this, it won't do it
+ (void)wxControl::MSWWindowProc(WM_LBUTTONDOWN, wParam, lParam);
+
+ // and continue with processing the message normally as well
+ }
+
+ // let the base class do all real processing
+ return wxControl::MSWWindowProc(nMsg, wParam, lParam);
+}
+
+// ----------------------------------------------------------------------------
+// owner-drawn buttons support
+// ----------------------------------------------------------------------------
+
+#ifdef __WIN32__
+
+// drawing helpers
+
+static void DrawButtonText(HDC hdc,
+ RECT *pRect,
+ const wxString& text,
+ COLORREF col)
+{
+ COLORREF colOld = SetTextColor(hdc, col);
+ int modeOld = SetBkMode(hdc, TRANSPARENT);
+
+ if ( text.find(_T('\n')) != wxString::npos )
+ {
+ // draw multiline label
+
+ // first we need to compute its bounding rect
+ RECT rc;
+ ::CopyRect(&rc, pRect);
+ ::DrawText(hdc, text, text.length(), &rc, DT_CENTER | DT_CALCRECT);
+
+ // now center this rect inside the entire button area
+ const LONG w = rc.right - rc.left;
+ const LONG h = rc.bottom - rc.top;
+ rc.left = (pRect->right - pRect->left)/2 - w/2;
+ rc.right = rc.left+w;
+ rc.top = (pRect->bottom - pRect->top)/2 - h/2;
+ rc.bottom = rc.top+h;
+
+ ::DrawText(hdc, text, text.length(), &rc, DT_CENTER);
+ }
+ else // single line label
+ {
+ // Note: we must have DT_SINGLELINE for DT_VCENTER to work.
+ ::DrawText(hdc, text, text.length(), pRect,
+ DT_SINGLELINE | DT_CENTER | DT_VCENTER);
+ }
+
+ SetBkMode(hdc, modeOld);
+ SetTextColor(hdc, colOld);
+}
+
+static void DrawRect(HDC hdc, const RECT& r)
+{
+ wxDrawLine(hdc, r.left, r.top, r.right, r.top);
+ wxDrawLine(hdc, r.right, r.top, r.right, r.bottom);
+ wxDrawLine(hdc, r.right, r.bottom, r.left, r.bottom);
+ wxDrawLine(hdc, r.left, r.bottom, r.left, r.top);
+}
+
+void wxButton::MakeOwnerDrawn()
+{
+ long style = GetWindowLong(GetHwnd(), GWL_STYLE);
+ if ( (style & BS_OWNERDRAW) != BS_OWNERDRAW )
+ {
+ // make it so
+ style |= BS_OWNERDRAW;
+ SetWindowLong(GetHwnd(), GWL_STYLE, style);
+ }
+}
+
+bool wxButton::SetBackgroundColour(const wxColour &colour)
+{
+ if ( !wxControl::SetBackgroundColour(colour) )
+ {
+ // nothing to do
+ return false;
+ }
+
+ MakeOwnerDrawn();
+
+ Refresh();
+
+ return true;
+}
+
+bool wxButton::SetForegroundColour(const wxColour &colour)
+{
+ if ( !wxControl::SetForegroundColour(colour) )
+ {
+ // nothing to do
+ return false;
+ }
+
+ MakeOwnerDrawn();
+
+ Refresh();
+
+ return true;
+}
+
+/*
+ The button frame looks like this normally:
+
+ WWWWWWWWWWWWWWWWWWB
+ WHHHHHHHHHHHHHHHHGB W = white (HILIGHT)
+ WH GB H = light grey (LIGHT)
+ WH GB G = dark grey (SHADOW)
+ WH GB B = black (DKSHADOW)
+ WH GB
+ WGGGGGGGGGGGGGGGGGB
+ BBBBBBBBBBBBBBBBBBB
+
+ When the button is selected, the button becomes like this (the total button
+ size doesn't change):
+
+ BBBBBBBBBBBBBBBBBBB
+ BWWWWWWWWWWWWWWWWBB
+ BWHHHHHHHHHHHHHHGBB
+ BWH GBB
+ BWH GBB
+ BWGGGGGGGGGGGGGGGBB
+ BBBBBBBBBBBBBBBBBBB
+ BBBBBBBBBBBBBBBBBBB
+
+ When the button is pushed (while selected) it is like:
+
+ BBBBBBBBBBBBBBBBBBB
+ BGGGGGGGGGGGGGGGGGB
+ BG GB
+ BG GB
+ BG GB
+ BG GB
+ BGGGGGGGGGGGGGGGGGB
+ BBBBBBBBBBBBBBBBBBB
+*/
+
+static void DrawButtonFrame(HDC hdc, const RECT& rectBtn,
+ bool selected, bool pushed)