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: dcmemory.cpp 42755 2006-10-30 19:41:46Z VZ $ 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 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// wxWin macros 38// ---------------------------------------------------------------------------- 39 40IMPLEMENT_DYNAMIC_CLASS(wxMemoryDC, wxDC) 41 42// ============================================================================ 43// implementation 44// ============================================================================ 45 46// ---------------------------------------------------------------------------- 47// wxMemoryDC 48// ---------------------------------------------------------------------------- 49 50wxMemoryDC::wxMemoryDC(wxDC *dc) 51{ 52 wxCHECK_RET( dc, _T("NULL dc in wxMemoryDC ctor") ); 53 54 CreateCompatible(dc); 55 56 Init(); 57} 58 59void wxMemoryDC::Init() 60{ 61 if ( m_ok ) 62 { 63 SetBrush(*wxWHITE_BRUSH); 64 SetPen(*wxBLACK_PEN); 65 66 // the background mode is only used for text background and is set in 67 // DrawText() to OPAQUE as required, otherwise always TRANSPARENT 68 ::SetBkMode( GetHdc(), TRANSPARENT ); 69 } 70} 71 72bool wxMemoryDC::CreateCompatible(wxDC *dc) 73{ 74 m_hDC = (WXHDC)::CreateCompatibleDC(dc ? GetHdcOf(*dc) : NULL); 75 76 // as we created the DC, we must delete it in the dtor 77 m_bOwnsDC = true; 78 79 m_ok = m_hDC != 0; 80 81 return m_ok; 82} 83 84void wxMemoryDC::DoSelect( const wxBitmap& bitmap) 85{ 86 // select old bitmap out of the device context 87 if ( m_oldBitmap ) 88 { 89 ::SelectObject(GetHdc(), (HBITMAP) m_oldBitmap); 90 if ( m_selectedBitmap.Ok() ) 91 { 92#ifdef __WXDEBUG__ 93 m_selectedBitmap.SetSelectedInto(NULL); 94#endif 95 m_selectedBitmap = wxNullBitmap; 96 } 97 } 98 99 // check for whether the bitmap is already selected into a device context 100 wxASSERT_MSG( !bitmap.GetSelectedInto() || 101 (bitmap.GetSelectedInto() == this), 102 wxT("Bitmap is selected in another wxMemoryDC, delete the first wxMemoryDC or use SelectObject(NULL)") ); 103 104 m_selectedBitmap = bitmap; 105 WXHBITMAP hBmp = m_selectedBitmap.GetHBITMAP(); 106 if ( !hBmp ) 107 return; 108 109#ifdef __WXDEBUG__ 110 m_selectedBitmap.SetSelectedInto(this); 111#endif 112 hBmp = (WXHBITMAP)::SelectObject(GetHdc(), (HBITMAP)hBmp); 113 114 if ( !hBmp ) 115 { 116 wxLogLastError(wxT("SelectObject(memDC, bitmap)")); 117 118 wxFAIL_MSG(wxT("Couldn't select a bitmap into wxMemoryDC")); 119 } 120 else if ( !m_oldBitmap ) 121 { 122 m_oldBitmap = hBmp; 123 } 124} 125 126void wxMemoryDC::DoGetSize(int *width, int *height) const 127{ 128 if ( m_selectedBitmap.Ok() ) 129 { 130 *width = m_selectedBitmap.GetWidth(); 131 *height = m_selectedBitmap.GetHeight(); 132 } 133 else 134 { 135 *width = 0; 136 *height = 0; 137 } 138} 139 140// the rest of this file deals with drawing rectangles workaround, disabled by 141// default 142 143#define wxUSE_MEMORY_DC_DRAW_RECTANGLE 0 144 145#if wxUSE_MEMORY_DC_DRAW_RECTANGLE 146 147// For some reason, drawing a rectangle on a memory DC has problems. 148// Use this substitute if we can. 149static void wxDrawRectangle(wxDC& dc, wxCoord x, wxCoord y, wxCoord width, wxCoord height) 150{ 151 wxBrush brush(dc.GetBrush()); 152 wxPen pen(dc.GetPen()); 153 if (brush.Ok() && brush.GetStyle() != wxTRANSPARENT) 154 { 155 HBRUSH hBrush = (HBRUSH) brush.GetResourceHandle() ; 156 if (hBrush) 157 { 158 RECT rect; 159 rect.left = x; rect.top = y; 160 rect.right = x + width - 1; 161 rect.bottom = y + height - 1; 162 ::FillRect((HDC) dc.GetHDC(), &rect, hBrush); 163 } 164 } 165 width --; height --; 166 if (pen.Ok() && pen.GetStyle() != wxTRANSPARENT) 167 { 168 dc.DrawLine(x, y, x + width, y); 169 dc.DrawLine(x, y, x, y + height); 170 dc.DrawLine(x, y+height, x+width, y + height); 171 dc.DrawLine(x+width, y+height, x+width, y); 172 } 173} 174 175#endif // wxUSE_MEMORY_DC_DRAW_RECTANGLE 176 177void wxMemoryDC::DoDrawRectangle(wxCoord x, wxCoord y, wxCoord width, wxCoord height) 178{ 179 // Set this to 1 to work around an apparent video driver bug 180 // (visible with e.g. 70x70 rectangle on a memory DC; see Drawing sample) 181#if wxUSE_MEMORY_DC_DRAW_RECTANGLE 182 if (m_brush.Ok() && m_pen.Ok() && 183 (m_brush.GetStyle() == wxSOLID || m_brush.GetStyle() == wxTRANSPARENT) && 184 (m_pen.GetStyle() == wxSOLID || m_pen.GetStyle() == wxTRANSPARENT) && 185 (GetLogicalFunction() == wxCOPY)) 186 { 187 wxDrawRectangle(* this, x, y, width, height); 188 } 189 else 190#endif // wxUSE_MEMORY_DC_DRAW_RECTANGLE 191 { 192 wxDC::DoDrawRectangle(x, y, width, height); 193 } 194} 195