diff --git a/include/wx/msw/private/dc.h b/include/wx/msw/private/dc.h new file mode 100644 index 0000000000..85b4140f6b --- /dev/null +++ b/include/wx/msw/private/dc.h @@ -0,0 +1,148 @@ +/////////////////////////////////////////////////////////////////////////////// +// Name: msw/private/dc.h +// Purpose: private wxMSW helpers for working with HDCs +// Author: Vadim Zeitlin +// Created: 2009-06-16 (extracted from src/msw/dc.cpp) +// RCS-ID: $Id$ +// Copyright: (c) 2009 Vadim Zeitlin +// Licence: wxWindows licence +/////////////////////////////////////////////////////////////////////////////// + +#ifndef _MSW_PRIVATE_DC_H_ +#define _MSW_PRIVATE_DC_H_ + +#include "wx/msw/dc.h" +#include "wx/msw/wrapwin.h" + +namespace wxMSWImpl +{ + +// various classes to change some DC property temporarily + +// text background and foreground colours +class wxTextColoursChanger +{ +public: + wxTextColoursChanger(HDC hdc, const wxMSWDCImpl& dc) + : m_hdc(hdc) + { + Change(dc.GetTextForeground(), dc.GetTextBackground()); + } + + wxTextColoursChanger(HDC hdc, const wxColour& colFg, const wxColour& colBg) + : m_hdc(hdc) + { + Change(colFg, colBg); + } + + wxTextColoursChanger(HDC hdc, COLORREF colFg, COLORREF colBg) + : m_hdc(hdc) + { + Change(colFg, colBg); + } + + ~wxTextColoursChanger() + { + if ( m_oldColFg != CLR_INVALID ) + ::SetTextColor(m_hdc, m_oldColFg); + if ( m_oldColBg != CLR_INVALID ) + ::SetBkColor(m_hdc, m_oldColBg); + } + +protected: + // this ctor doesn't change mode immediately, call Change() later to do it + // only if needed + wxTextColoursChanger(HDC hdc) + : m_hdc(hdc) + { + m_oldColFg = + m_oldColBg = CLR_INVALID; + } + + void Change(const wxColour& colFg, const wxColour& colBg) + { + Change(colFg.IsOk() ? colFg.GetPixel() : CLR_INVALID, + colBg.IsOk() ? colBg.GetPixel() : CLR_INVALID); + } + + void Change(COLORREF colFg, COLORREF colBg) + { + if ( colFg != CLR_INVALID ) + { + m_oldColFg = ::SetTextColor(m_hdc, colFg); + if ( m_oldColFg == CLR_INVALID ) + { + wxLogLastError(_T("SetTextColor")); + } + } + else + { + m_oldColFg = CLR_INVALID; + } + + if ( colBg != CLR_INVALID ) + { + m_oldColBg = ::SetBkColor(m_hdc, colBg); + if ( m_oldColBg == CLR_INVALID ) + { + wxLogLastError(_T("SetBkColor")); + } + } + else + { + m_oldColBg = CLR_INVALID; + } + } + +private: + const HDC m_hdc; + COLORREF m_oldColFg, + m_oldColBg; + + wxDECLARE_NO_COPY_CLASS(wxTextColoursChanger); +}; + +// background mode +class wxBkModeChanger +{ +public: + // set background mode to opaque if mode != wxBRUSHSTYLE_TRANSPARENT + wxBkModeChanger(HDC hdc, int mode) + : m_hdc(hdc) + { + Change(mode); + } + + ~wxBkModeChanger() + { + if ( m_oldMode ) + ::SetBkMode(m_hdc, m_oldMode); + } + +protected: + // this ctor doesn't change mode immediately, call Change() later to do it + // only if needed + wxBkModeChanger(HDC hdc) : m_hdc(hdc) { m_oldMode = 0; } + + void Change(int mode) + { + m_oldMode = ::SetBkMode(m_hdc, mode == wxBRUSHSTYLE_TRANSPARENT + ? TRANSPARENT + : OPAQUE); + if ( !m_oldMode ) + { + wxLogLastError(_T("SetBkMode")); + } + } + +private: + const HDC m_hdc; + int m_oldMode; + + wxDECLARE_NO_COPY_CLASS(wxBkModeChanger); +}; + +} // namespace wxMSWImpl + +#endif // _MSW_PRIVATE_DC_H_ + diff --git a/src/msw/button.cpp b/src/msw/button.cpp index ead9214d2c..1d4e9fa0da 100644 --- a/src/msw/button.cpp +++ b/src/msw/button.cpp @@ -43,6 +43,9 @@ #include "wx/stockitem.h" #include "wx/msw/private.h" #include "wx/msw/private/button.h" +#include "wx/msw/private/dc.h" + +using namespace wxMSWImpl; #if wxUSE_UXTHEME #include "wx/msw/uxtheme.h" @@ -887,15 +890,17 @@ void wxButton::DoSetBitmapPosition(wxDirection dir) // ---------------------------------------------------------------------------- // drawing helpers - -static void DrawButtonText(HDC hdc, - RECT *pRect, - const wxString& text, - COLORREF col, - int flags) +namespace { - COLORREF colOld = SetTextColor(hdc, col); - int modeOld = SetBkMode(hdc, TRANSPARENT); + +void DrawButtonText(HDC hdc, + RECT *pRect, + const wxString& text, + COLORREF col, + int flags) +{ + wxTextColoursChanger changeFg(hdc, col, CLR_INVALID); + wxBkModeChanger changeBkMode(hdc, wxBRUSHSTYLE_TRANSPARENT); // center text horizontally in any case flags |= DT_CENTER; @@ -927,12 +932,9 @@ static void DrawButtonText(HDC hdc, ::DrawText(hdc, text.wx_str(), text.length(), pRect, flags | DT_SINGLELINE | DT_VCENTER); } - - SetBkMode(hdc, modeOld); - SetTextColor(hdc, colOld); } -static void DrawRect(HDC hdc, const RECT& r) +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); @@ -940,47 +942,6 @@ static void DrawRect(HDC hdc, const RECT& r) 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: @@ -1016,9 +977,8 @@ bool wxButton::SetForegroundColour(const wxColour &colour) BGGGGGGGGGGGGGGGGGB BBBBBBBBBBBBBBBBBBB */ - -static void DrawButtonFrame(HDC hdc, const RECT& rectBtn, - bool selected, bool pushed) +void DrawButtonFrame(HDC hdc, const RECT& rectBtn, + bool selected, bool pushed) { RECT r; CopyRect(&r, &rectBtn); @@ -1075,7 +1035,6 @@ static void DrawButtonFrame(HDC hdc, const RECT& rectBtn, } #if wxUSE_UXTHEME -static void MSWDrawXPBackground(wxButton *button, WXDRAWITEMSTRUCT *wxdis) { LPDRAWITEMSTRUCT lpDIS = (LPDRAWITEMSTRUCT)wxdis; @@ -1147,6 +1106,53 @@ void MSWDrawXPBackground(wxButton *button, WXDRAWITEMSTRUCT *wxdis) } #endif // wxUSE_UXTHEME +} // anonymous namespace + +// ---------------------------------------------------------------------------- +// owner drawn buttons support +// ---------------------------------------------------------------------------- + +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; +} + bool wxButton::MSWOnDraw(WXDRAWITEMSTRUCT *wxdis) { LPDRAWITEMSTRUCT lpDIS = (LPDRAWITEMSTRUCT)wxdis; diff --git a/src/msw/dc.cpp b/src/msw/dc.cpp index 8c7adc9768..320d587437 100644 --- a/src/msw/dc.cpp +++ b/src/msw/dc.cpp @@ -44,14 +44,14 @@ #include "wx/dynlib.h" #ifdef wxHAS_RAW_BITMAP -#include "wx/rawbmp.h" + #include "wx/rawbmp.h" #endif #include -#ifndef __WIN32__ - #include -#endif +#include "wx/msw/private/dc.h" + +using namespace wxMSWImpl; #ifndef AC_SRC_ALPHA #define AC_SRC_ALPHA 1 @@ -149,119 +149,6 @@ wxAlphaBlend(HDC hdcDst, int xDst, int yDst, // private classes // ---------------------------------------------------------------------------- -// various classes to change some DC property temporarily - -// text background and foreground colours -class wxTextColoursChanger -{ -public: - wxTextColoursChanger(HDC hdc, const wxMSWDCImpl& dc) - : m_hdc(hdc) - { - Change(dc.GetTextForeground(), dc.GetTextBackground()); - } - - wxTextColoursChanger(HDC hdc, const wxColour& colFg, const wxColour& colBg) - : m_hdc(hdc) - { - Change(colFg, colBg); - } - - ~wxTextColoursChanger() - { - if ( m_oldColFg != CLR_INVALID ) - ::SetTextColor(m_hdc, m_oldColFg); - if ( m_oldColBg != CLR_INVALID ) - ::SetBkColor(m_hdc, m_oldColBg); - } - -protected: - // this ctor doesn't change mode immediately, call Change() later to do it - // only if needed - wxTextColoursChanger(HDC hdc) - : m_hdc(hdc) - { - m_oldColFg = - m_oldColBg = CLR_INVALID; - } - - void Change(const wxColour& colFg, const wxColour& colBg) - { - if ( colFg.IsOk() ) - { - m_oldColFg = ::SetTextColor(m_hdc, colFg.GetPixel()); - if ( m_oldColFg == CLR_INVALID ) - { - wxLogLastError(_T("SetTextColor")); - } - } - else - { - m_oldColFg = CLR_INVALID; - } - - if ( colBg.IsOk() ) - { - m_oldColBg = ::SetBkColor(m_hdc, colBg.GetPixel()); - if ( m_oldColBg == CLR_INVALID ) - { - wxLogLastError(_T("SetBkColor")); - } - } - else - { - m_oldColBg = CLR_INVALID; - } - } - -private: - const HDC m_hdc; - COLORREF m_oldColFg, - m_oldColBg; - - wxDECLARE_NO_COPY_CLASS(wxTextColoursChanger); -}; - -// background mode -class wxBkModeChanger -{ -public: - // set background mode to opaque if mode != wxBRUSHSTYLE_TRANSPARENT - wxBkModeChanger(HDC hdc, int mode) - : m_hdc(hdc) - { - Change(mode); - } - - ~wxBkModeChanger() - { - if ( m_oldMode ) - ::SetBkMode(m_hdc, m_oldMode); - } - -protected: - // this ctor doesn't change mode immediately, call Change() later to do it - // only if needed - wxBkModeChanger(HDC hdc) : m_hdc(hdc) { m_oldMode = 0; } - - void Change(int mode) - { - m_oldMode = ::SetBkMode(m_hdc, mode == wxBRUSHSTYLE_TRANSPARENT - ? TRANSPARENT - : OPAQUE); - if ( !m_oldMode ) - { - wxLogLastError(_T("SetBkMode")); - } - } - -private: - const HDC m_hdc; - int m_oldMode; - - wxDECLARE_NO_COPY_CLASS(wxBkModeChanger); -}; - // instead of duplicating the same code which sets and then restores text // colours in each wxDC method working with wxSTIPPLE_MASK_OPAQUE brushes, // encapsulate this in a small helper class