-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathCMemDC.h
158 lines (139 loc) · 3.97 KB
/
CMemDC.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
#ifndef _MEMDC_H_
#define _MEMDC_H_
////////////////////////////////////////////////////////////////////////////////
// CMemDC - memory DC
//
// Author: Keith Rule
// Email: [email protected]
// Copyright 1996-2002, Keith Rule
//
// You may freely use or modify this code provided this
// copyright is included in all derived versions.
//
// History - 10/03/97 Fixed scrolling bug.
// Added print support. - KR
//
// 11/03/99 Fixed most common complaint. Added
// background color fill. - KR
//
// 11/03/99 Added support for mapping modes other than
// MM_TEXT as suggested by Lee Sang Hun. - KR
//
// 02/11/02 Added support for CScrollView as supplied
// by Gary Kirkham. - KR
//
// 04/19/06 Modified background fill to try and use
// correct background brush/color - AGB
//
// This class implements a memory device context which allows
// flicker free drawing.
////////////////////////////////////////////////////////////////////////////////
class CMemDC : public CDC
{
private:
BOOL m_bMemDC; // TRUE if not printing
CBitmap m_MemBitmap; // offscreen bitmap
CBitmap* m_pOldBitmap; // original bitmap
CDC* m_pDC; // saves CDC passed in constructor
CRect m_rect; // rectangle of drawing area
public:
// constructor sets up the memory DC
CMemDC(CDC* pDC, const CRect* pRect = NULL) : CDC()
{
// make sure the call provided a valid device context
ASSERT(pDC != NULL);
// save the original device context for later BitBlt()
m_pDC = pDC;
// check whether we're printing
m_bMemDC = !pDC->IsPrinting();
// get the output rectangle
if (pRect == NULL)
pDC->GetClipBox(&m_rect);
else
m_rect = *pRect;
if (m_bMemDC)
{
// do the memory DC stuff if not printing
// create a memory DC
CreateCompatibleDC(pDC);
// create new bitmap and save old bitmap
pDC->LPtoDP(&m_rect);
m_MemBitmap.CreateCompatibleBitmap(pDC, m_rect.Width(), m_rect.Height());
m_pOldBitmap = SelectObject(&m_MemBitmap);
SetMapMode(pDC->GetMapMode());
SetWindowExt(pDC->GetWindowExt());
SetViewportExt(pDC->GetViewportExt());
pDC->DPtoLP(&m_rect);
// set window origin
SetWindowOrg(m_rect.left, m_rect.top);
}
else
{
// make a copy of the relevant parts of the original DC for printing
m_bPrinting = pDC->m_bPrinting;
m_hDC = pDC->m_hDC;
m_hAttribDC = pDC->m_hAttribDC;
}
// fill background
CWnd* pWnd = pDC->GetWindow();
HWND hWnd = NULL;
if (pWnd != NULL)
{
hWnd = pWnd->m_hWnd;
if (hWnd != NULL)
{
#if _MSC_VER > 1200
if (GetClassLongPtr(hWnd, GCW_ATOM) == 32770)
#else
if (GetClassLong(hWnd, GCW_ATOM) == 32770)
#endif
{
// if window is a dialog box, use dialog background color
FillSolidRect(m_rect, GetSysColor(COLOR_BTNFACE));
}
else
{
// try to get background brush for window class
#if _MSC_VER > 1200
ULONG_PTR ulpBrush = GetClassLongPtr(hWnd, GCLP_HBRBACKGROUND);
#else
ULONG_PTR ulpBrush = GetClassLong(hWnd, GCL_HBRBACKGROUND);
#endif
if (ulpBrush)
{
// fill with class background brush
FillRect(m_rect, CBrush::FromHandle((HBRUSH)ulpBrush));
}
else
hWnd = NULL;
}
}
}
if (hWnd == NULL)
FillSolidRect(m_rect, pDC->GetBkColor());
}
// destructor copies the contents of the memory DC to the original DC
~CMemDC()
{
if (m_bMemDC)
{
// copy the offscreen bitmap onto the screen
m_pDC->BitBlt(m_rect.left, m_rect.top, m_rect.Width(), m_rect.Height(),
this, m_rect.left, m_rect.top, SRCCOPY);
// restore the original bitmap
m_pDC->SelectObject(m_pOldBitmap);
}
else
{
// all we need to do is replace the DC with an illegal value,
// this keeps us from accidently deleting the handles associated
// with the CDC that was passed to the constructor
m_hDC = m_hAttribDC = NULL;
}
}
// allow usage as a pointer
CMemDC* operator->() { return this; }
// allow usage as a pointer
operator CMemDC*() { return this; }
};
#endif //#ifndef _MEMDC_H_