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