diff --git a/include/wx/dc.h b/include/wx/dc.h index aa5110066d..4981bda64a 100644 --- a/include/wx/dc.h +++ b/include/wx/dc.h @@ -1199,7 +1199,50 @@ public: #endif // WXWIN_COMPATIBILITY_2_8 #ifdef __WXMSW__ + // GetHDC() is the simplest way to retrieve an HDC From a wxDC but only + // works if this wxDC is GDI-based and fails for GDI+ contexts (and + // anything else without HDC, e.g. wxPostScriptDC) WXHDC GetHDC() const; + + // don't use these methods manually, use GetTempHDC() instead + virtual WXHDC AcquireHDC() { return GetHDC(); } + virtual void ReleaseHDC(WXHDC WXUNUSED(hdc)) { } + + // helper class holding the result of GetTempHDC() with std::auto_ptr<>-like + // semantics, i.e. it is moved when copied + class TempHDC + { + public: + TempHDC(wxDC& dc) + : m_dc(dc), + m_hdc(dc.AcquireHDC()) + { + } + + TempHDC(const TempHDC& thdc) + : m_dc(thdc.m_dc), + m_hdc(thdc.m_hdc) + { + const_cast(thdc).m_hdc = 0; + } + + ~TempHDC() + { + if ( m_hdc ) + m_dc.ReleaseHDC(m_hdc); + } + + WXHDC GetHDC() const { return m_hdc; } + + private: + wxDC& m_dc; + WXHDC m_hdc; + + wxDECLARE_NO_ASSIGN_CLASS(TempHDC); + }; + + // GetTempHDC() also works for wxGCDC (but still not for wxPostScriptDC &c) + TempHDC GetTempHDC() { return TempHDC(*this); } #endif // __WXMSW__ protected: diff --git a/include/wx/dcgraph.h b/include/wx/dcgraph.h index de977b7577..a5c7e6ff97 100644 --- a/include/wx/dcgraph.h +++ b/include/wx/dcgraph.h @@ -35,6 +35,14 @@ public: wxGraphicsContext* GetGraphicsContext(); void SetGraphicsContext( wxGraphicsContext* ctx ); +#ifdef __WXMSW__ + // override wxDC virtual functions to provide access to HDC associated with + // this Graphics object (implemented in src/msw/graphics.cpp) + virtual WXHDC AcquireHDC(); + virtual void ReleaseHDC(WXHDC hdc); +#endif // __WXMSW__ + +private: DECLARE_DYNAMIC_CLASS(wxGCDC) wxDECLARE_NO_COPY_CLASS(wxGCDC); }; diff --git a/src/msw/graphics.cpp b/src/msw/graphics.cpp index 6562a8a55e..71ef3d4a34 100644 --- a/src/msw/graphics.cpp +++ b/src/msw/graphics.cpp @@ -40,6 +40,7 @@ #include "wx/private/graphics.h" #include "wx/msw/wrapgdip.h" #include "wx/msw/dc.h" +#include "wx/dcgraph.h" #include "wx/stack.h" @@ -1850,4 +1851,32 @@ private: IMPLEMENT_DYNAMIC_CLASS(wxGDIPlusRendererModule, wxModule) +// ---------------------------------------------------------------------------- +// wxMSW-specific parts of wxGCDC +// ---------------------------------------------------------------------------- + +WXHDC wxGCDC::AcquireHDC() +{ + wxGraphicsContext * const gc = GetGraphicsContext(); + if ( !gc ) + return NULL; + + Graphics * const g = static_cast(gc->GetNativeContext()); + return g ? g->GetHDC() : NULL; +} + +void wxGCDC::ReleaseHDC(WXHDC hdc) +{ + if ( !hdc ) + return; + + wxGraphicsContext * const gc = GetGraphicsContext(); + wxCHECK_RET( gc, "can't release HDC because there is no wxGraphicsContext" ); + + Graphics * const g = static_cast(gc->GetNativeContext()); + wxCHECK_RET( g, "can't release HDC because there is no Graphics" ); + + g->ReleaseHDC((HDC)hdc); +} + #endif // wxUSE_GRAPHICS_CONTEXT diff --git a/src/msw/renderer.cpp b/src/msw/renderer.cpp index dab3795115..6ae0300275 100644 --- a/src/msw/renderer.cpp +++ b/src/msw/renderer.cpp @@ -35,24 +35,8 @@ #include "wx/splitter.h" #include "wx/renderer.h" #include "wx/msw/private.h" -#include "wx/msw/dc.h" #include "wx/msw/uxtheme.h" -#if wxUSE_GRAPHICS_CONTEXT -// TODO remove this dependency (gdiplus needs the macros) -#ifndef max -#define max(a,b) (((a) > (b)) ? (a) : (b)) -#endif - -#ifndef min -#define min(a,b) (((a) < (b)) ? (a) : (b)) -#endif - -#include "wx/dcgraph.h" -#include "gdiplus.h" -using namespace Gdiplus; -#endif // wxUSE_GRAPHICS_CONTEXT - // tmschema.h is in Win32 Platform SDK and might not be available with earlier // compilers #ifndef CP_DROPDOWNBUTTON @@ -110,45 +94,6 @@ using namespace Gdiplus; #define TMT_EDGEFILLCOLOR 3808 #endif - -// ---------------------------------------------------------------------------- -// If the DC is a wxGCDC then pull out the HDC from the GraphicsContext when -// it is needed, and handle the Release when done. - -class GraphicsHDC -{ -public: - GraphicsHDC(wxDC* dc) - { -#if wxUSE_GRAPHICS_CONTEXT - m_graphics = NULL; - wxGCDC* gcdc = wxDynamicCast(dc, wxGCDC); - if (gcdc) { - m_graphics = (Graphics*)gcdc->GetGraphicsContext()->GetNativeContext(); - m_hdc = m_graphics->GetHDC(); - } - else -#endif - m_hdc = GetHdcOf(*((wxMSWDCImpl*)dc->GetImpl())); - } - - ~GraphicsHDC() - { -#if wxUSE_GRAPHICS_CONTEXT - if (m_graphics) - m_graphics->ReleaseHDC(m_hdc); -#endif - } - - operator HDC() const { return m_hdc; } - -private: - HDC m_hdc; -#if wxUSE_GRAPHICS_CONTEXT - Graphics* m_graphics; -#endif -}; - #if defined(__WXWINCE__) #ifndef DFCS_FLAT #define DFCS_FLAT 0 @@ -345,7 +290,7 @@ void wxRendererMSWBase::DrawFocusRect(wxWindow * WXUNUSED(win), RECT rc; wxCopyRectToRECT(rect, rc); - ::DrawFocusRect(GraphicsHDC(&dc), &rc); + ::DrawFocusRect(GetHdcOf(dc.GetTempHDC()), &rc); } void wxRendererMSWBase::DrawItemSelectionRect(wxWindow *win, @@ -418,7 +363,7 @@ wxRendererMSW::DrawComboBoxDropButton(wxWindow * WXUNUSED(win), if ( flags & wxCONTROL_PRESSED ) style |= DFCS_PUSHED | DFCS_FLAT; - ::DrawFrameControl(GraphicsHDC(&dc), &r, DFC_SCROLL, style); + ::DrawFrameControl(GetHdcOf(dc.GetTempHDC()), &r, DFC_SCROLL, style); } void @@ -443,7 +388,7 @@ wxRendererMSW::DoDrawButton(UINT kind, if ( flags & wxCONTROL_CURRENT ) style |= DFCS_HOT; - ::DrawFrameControl(GraphicsHDC(&dc), &r, DFC_BUTTON, style); + ::DrawFrameControl(GetHdcOf(dc.GetTempHDC()), &r, DFC_BUTTON, style); } void @@ -602,7 +547,7 @@ wxRendererXP::DrawComboBoxDropButton(wxWindow * win, wxUxThemeEngine::Get()->DrawThemeBackground ( hTheme, - GetHdcOf(*((wxMSWDCImpl*)dc.GetImpl())), + GetHdcOf(dc.GetTempHDC()), CP_DROPDOWNBUTTON, state, &r, @@ -638,7 +583,7 @@ wxRendererXP::DrawHeaderButton(wxWindow *win, wxUxThemeEngine::Get()->DrawThemeBackground ( hTheme, - GetHdcOf(*((wxMSWDCImpl*)dc.GetImpl())), + GetHdcOf(dc.GetTempHDC()), HP_HEADERITEM, state, &r, @@ -674,7 +619,7 @@ wxRendererXP::DrawTreeItemButton(wxWindow *win, wxUxThemeEngine::Get()->DrawThemeBackground ( hTheme, - GetHdcOf(*((wxMSWDCImpl*)dc.GetImpl())), + GetHdcOf(dc.GetTempHDC()), TVP_GLYPH, state, &r, @@ -748,7 +693,7 @@ wxRendererXP::DoDrawXPButton(int kind, wxUxThemeEngine::Get()->DrawThemeBackground ( hTheme, - GetHdcOf(*((wxMSWDCImpl*)dc.GetImpl())), + GetHdcOf(dc.GetTempHDC()), kind, state, &r,