]> git.saurik.com Git - wxWidgets.git/blob - src/msw/dcmemory.cpp
Added wxDC::CreateGraphicsContext and implemented it for a few DCs
[wxWidgets.git] / src / msw / dcmemory.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/msw/dcmemory.cpp
3 // Purpose: wxMemoryDC class
4 // Author: Julian Smart
5 // Modified by:
6 // Created: 01/02/97
7 // RCS-ID: $Id$
8 // Copyright: (c) Julian Smart
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
11
12 // ============================================================================
13 // declarations
14 // ============================================================================
15
16 // ----------------------------------------------------------------------------
17 // headers
18 // ----------------------------------------------------------------------------
19
20 // For compilers that support precompilation, includes "wx.h".
21 #include "wx/wxprec.h"
22
23 #ifdef __BORLANDC__
24 #pragma hdrstop
25 #endif
26
27 #include "wx/dcmemory.h"
28 #include "wx/msw/dcmemory.h"
29
30 #ifndef WX_PRECOMP
31 #include "wx/utils.h"
32 #include "wx/log.h"
33 #endif
34
35 #if wxUSE_GRAPHICS_CONTEXT
36 #include "wx/graphics.h"
37 #endif
38
39 #include "wx/msw/private.h"
40
41 // ----------------------------------------------------------------------------
42 // wxMemoryDCImpl
43 // ----------------------------------------------------------------------------
44
45 IMPLEMENT_ABSTRACT_CLASS(wxMemoryDCImpl, wxMSWDCImpl)
46
47 wxMemoryDCImpl::wxMemoryDCImpl( wxMemoryDC *owner )
48 : wxMSWDCImpl( owner )
49 {
50 CreateCompatible(NULL);
51 Init();
52 }
53
54 wxMemoryDCImpl::wxMemoryDCImpl( wxMemoryDC *owner, wxBitmap& bitmap )
55 : wxMSWDCImpl( owner )
56 {
57 CreateCompatible(NULL);
58 Init();
59 DoSelect(bitmap);
60 }
61
62 wxMemoryDCImpl::wxMemoryDCImpl( wxMemoryDC *owner, wxDC *dc )
63 : wxMSWDCImpl( owner )
64 {
65 wxCHECK_RET( dc, _T("NULL dc in wxMemoryDC ctor") );
66
67 CreateCompatible(dc);
68
69 Init();
70 }
71
72 void wxMemoryDCImpl::Init()
73 {
74 if ( m_ok )
75 {
76 SetBrush(*wxWHITE_BRUSH);
77 SetPen(*wxBLACK_PEN);
78
79 // the background mode is only used for text background and is set in
80 // DrawText() to OPAQUE as required, otherwise always TRANSPARENT
81 ::SetBkMode( GetHdc(), TRANSPARENT );
82 }
83 }
84
85 #if wxUSE_GRAPHICS_CONTEXT
86 wxGraphicsContext* wxMemoryDCImpl::CreateGraphicsContext()
87 {
88 wxMemoryDC *memdc = (wxMemoryDC*) GetOwner();
89 return wxGraphicsRenderer::GetDefaultRenderer()->CreateContext( *memdc );
90 }
91 #endif
92
93 bool wxMemoryDCImpl::CreateCompatible(wxDC *dc)
94 {
95 wxDCImpl *impl = dc ? dc->GetImpl() : NULL ;
96 wxMSWDCImpl *msw_impl = wxDynamicCast( impl, wxMSWDCImpl );
97 if ( dc && !msw_impl)
98 {
99 m_ok = false;
100 return false;
101 }
102
103 m_hDC = (WXHDC)::CreateCompatibleDC(dc ? GetHdcOf(*msw_impl) : NULL);
104
105 // as we created the DC, we must delete it in the dtor
106 m_bOwnsDC = true;
107
108 m_ok = m_hDC != 0;
109
110 return m_ok;
111 }
112
113 void wxMemoryDCImpl::DoSelect( const wxBitmap& bitmap )
114 {
115 // select old bitmap out of the device context
116 if ( m_oldBitmap )
117 {
118 ::SelectObject(GetHdc(), (HBITMAP) m_oldBitmap);
119 if ( m_selectedBitmap.Ok() )
120 {
121 #ifdef __WXDEBUG__
122 m_selectedBitmap.SetSelectedInto(NULL);
123 #endif
124 m_selectedBitmap = wxNullBitmap;
125 }
126 }
127
128 // check for whether the bitmap is already selected into a device context
129 wxASSERT_MSG( !bitmap.GetSelectedInto() ||
130 (bitmap.GetSelectedInto() == GetOwner()),
131 wxT("Bitmap is selected in another wxMemoryDC, delete the first wxMemoryDC or use SelectObject(NULL)") );
132
133 m_selectedBitmap = bitmap;
134 WXHBITMAP hBmp = m_selectedBitmap.GetHBITMAP();
135 if ( !hBmp )
136 return;
137
138 #ifdef __WXDEBUG__
139 m_selectedBitmap.SetSelectedInto(GetOwner());
140 #endif
141 hBmp = (WXHBITMAP)::SelectObject(GetHdc(), (HBITMAP)hBmp);
142
143 if ( !hBmp )
144 {
145 wxLogLastError(wxT("SelectObject(memDC, bitmap)"));
146
147 wxFAIL_MSG(wxT("Couldn't select a bitmap into wxMemoryDC"));
148 }
149 else if ( !m_oldBitmap )
150 {
151 m_oldBitmap = hBmp;
152 }
153 }
154
155 void wxMemoryDCImpl::DoGetSize(int *width, int *height) const
156 {
157 if ( m_selectedBitmap.Ok() )
158 {
159 *width = m_selectedBitmap.GetWidth();
160 *height = m_selectedBitmap.GetHeight();
161 }
162 else
163 {
164 *width = 0;
165 *height = 0;
166 }
167 }
168
169 // the rest of this file deals with drawing rectangles workaround, disabled by
170 // default
171
172 #define wxUSE_MEMORY_DC_DRAW_RECTANGLE 0
173
174 #if wxUSE_MEMORY_DC_DRAW_RECTANGLE
175
176 // For some reason, drawing a rectangle on a memory DC has problems.
177 // Use this substitute if we can.
178 static void wxDrawRectangle(wxDC& dc, wxCoord x, wxCoord y, wxCoord width, wxCoord height)
179 {
180 wxBrush brush(dc.GetBrush());
181 wxPen pen(dc.GetPen());
182 if (brush.Ok() && brush.GetStyle() != wxTRANSPARENT)
183 {
184 HBRUSH hBrush = (HBRUSH) brush.GetResourceHandle() ;
185 if (hBrush)
186 {
187 RECT rect;
188 rect.left = x; rect.top = y;
189 rect.right = x + width - 1;
190 rect.bottom = y + height - 1;
191 ::FillRect((HDC) dc.GetHDC(), &rect, hBrush);
192 }
193 }
194 width --; height --;
195 if (pen.Ok() && pen.GetStyle() != wxTRANSPARENT)
196 {
197 dc.DrawLine(x, y, x + width, y);
198 dc.DrawLine(x, y, x, y + height);
199 dc.DrawLine(x, y+height, x+width, y + height);
200 dc.DrawLine(x+width, y+height, x+width, y);
201 }
202 }
203
204 #endif // wxUSE_MEMORY_DC_DRAW_RECTANGLE
205
206 void wxMemoryDCImpl::DoDrawRectangle(wxCoord x, wxCoord y, wxCoord width, wxCoord height)
207 {
208 // Set this to 1 to work around an apparent video driver bug
209 // (visible with e.g. 70x70 rectangle on a memory DC; see Drawing sample)
210 #if wxUSE_MEMORY_DC_DRAW_RECTANGLE
211 if (m_brush.Ok() && m_pen.Ok() &&
212 (m_brush.GetStyle() == wxSOLID || m_brush.GetStyle() == wxTRANSPARENT) &&
213 (m_pen.GetStyle() == wxSOLID || m_pen.GetStyle() == wxTRANSPARENT) &&
214 (GetLogicalFunction() == wxCOPY))
215 {
216 wxDrawRectangle(* this, x, y, width, height);
217 }
218 else
219 #endif // wxUSE_MEMORY_DC_DRAW_RECTANGLE
220 {
221 wxMSWDCImpl::DoDrawRectangle(x, y, width, height);
222 }
223 }