forked from chrisguo/beijing_fushengji
-
Notifications
You must be signed in to change notification settings - Fork 1
/
BitmapPicture.cpp
executable file
·184 lines (148 loc) · 5.71 KB
/
BitmapPicture.cpp
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
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
// BitmapPicture.cpp : implementation file
//
// Copyright (c) 1997 Chris Maunder ([email protected])
// Written 1 December, 1997
#include "stdafx.h"
#include "BitmapPicture.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
// if UPDATE_ENTIRE_CLIENT_AREA is not defined then only the update region of
// the bitmap is updated. Otherwise, on each update, the whole client area of
// the bitmap is drawn. UPDATE_ENTIRE_CLIENT_AREA is slower, but distortion
// of the picture may occur if it is not defined.
#define UPDATE_ENTIRE_CLIENT_AREA
/////////////////////////////////////////////////////////////////////////////
// CBitmapPicture
CBitmapPicture::CBitmapPicture()
{
m_hBitmap = NULL;
m_nResourceID = -1;
m_strResourceName.Empty();
}
CBitmapPicture::~CBitmapPicture()
{
if (m_hBitmap) ::DeleteObject(m_hBitmap);
}
BEGIN_MESSAGE_MAP(CBitmapPicture, CStatic)
//{{AFX_MSG_MAP(CBitmapPicture)
ON_WM_ERASEBKGND()
ON_WM_DRAWITEM_REFLECT()
ON_WM_SYSCOLORCHANGE()
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CBitmapPicture message handlers
BOOL CBitmapPicture::SetBitmap(HBITMAP hBitmap)
{
::DeleteObject(m_hBitmap);
m_hBitmap = hBitmap;
return ::GetObject(m_hBitmap, sizeof(BITMAP), &m_bmInfo);
}
BOOL CBitmapPicture::SetBitmap(UINT nIDResource)
{
m_nResourceID = nIDResource;
m_strResourceName.Empty();
HBITMAP hBmp = (HBITMAP)::LoadImage(AfxGetInstanceHandle(),
MAKEINTRESOURCE(nIDResource),
IMAGE_BITMAP,
0,0,
LR_LOADMAP3DCOLORS);
if (!hBmp) return FALSE;
return CBitmapPicture::SetBitmap(hBmp);
}
BOOL CBitmapPicture::SetBitmap(LPCTSTR lpszResourceName)
{
m_nResourceID = -1;
m_strResourceName = lpszResourceName;
HBITMAP hBmp = (HBITMAP)::LoadImage(AfxGetInstanceHandle(),
lpszResourceName,
IMAGE_BITMAP,
0,0,
LR_LOADMAP3DCOLORS);
if (!hBmp) return FALSE;
return CBitmapPicture::SetBitmap(hBmp);
}
// Suggested by Pål K. Used to reload the bitmap on system colour changes.
BOOL CBitmapPicture::ReloadBitmap()
{
if (m_nResourceID > 0)
return SetBitmap(m_nResourceID);
else if (!m_strResourceName.IsEmpty())
return SetBitmap(m_strResourceName);
else // if SetBitmap(HBITMAP hBitmap) was used directly then we can't reload.
return FALSE;
}
void CBitmapPicture::PreSubclassWindow()
{
CStatic::PreSubclassWindow();
ModifyStyle(0, SS_OWNERDRAW);
}
BOOL CBitmapPicture::OnEraseBkgnd(CDC* pDC)
{
CRect rect;
GetClientRect(rect);
// If no bitmap selected, simply erase the background as per normal and return
if (!m_hBitmap)
{
CBrush backBrush(::GetSysColor(COLOR_3DFACE)); // (this is meant for dialogs)
CBrush* pOldBrush = pDC->SelectObject(&backBrush);
pDC->PatBlt(rect.left, rect.top, rect.Width(), rect.Height(), PATCOPY);
pDC->SelectObject(pOldBrush);
return TRUE;
}
// We have a bitmap - draw it.
// Create compatible memory DC using the controls DC
CDC dcMem;
VERIFY( dcMem.CreateCompatibleDC(pDC));
// Select bitmap into memory DC.
HBITMAP* pBmpOld = (HBITMAP*) ::SelectObject(dcMem.m_hDC, m_hBitmap);
pDC->SetStretchBltMode(COLORONCOLOR);
// StretchBlt bitmap onto static's client area
#ifdef UPDATE_ENTIRE_CLIENT_AREA
pDC->StretchBlt(rect.left, rect.top, rect.Width(), rect.Height(),
&dcMem, 0, 0, m_bmInfo.bmWidth-1, m_bmInfo.bmHeight-1,
SRCCOPY);
#else
CRect TargetRect; // Region on screen to be updated
pDC->GetClipBox(&TargetRect);
TargetRect.IntersectRect(TargetRect, rect);
CRect SrcRect; // Region from bitmap to be painted
SrcRect.left = MulDiv(TargetRect.left, m_bmInfo.bmWidth, rect.Width());
SrcRect.top = MulDiv(TargetRect.top, m_bmInfo.bmHeight, rect.Height());
SrcRect.right = MulDiv(TargetRect.right, m_bmInfo.bmWidth, rect.Width());
SrcRect.bottom = MulDiv(TargetRect.bottom, m_bmInfo.bmHeight, rect.Height());
pDC->StretchBlt(TargetRect.left, TargetRect.top, TargetRect.Width(), TargetRect.Height(),
&dcMem,
SrcRect.left, SrcRect.top, SrcRect.Width(), SrcRect.Height(),
SRCCOPY);
#endif
::SelectObject(dcMem.m_hDC, pBmpOld);
return TRUE;
}
void CBitmapPicture::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct)
{
ASSERT(lpDrawItemStruct != NULL);
CString str;
GetWindowText(str);
if (!str.GetLength()) return;
CDC* pDC = CDC::FromHandle(lpDrawItemStruct->hDC);
CRect rect = lpDrawItemStruct->rcItem;
DWORD dwStyle = GetStyle();
int nFormat = DT_NOPREFIX | DT_NOCLIP | DT_WORDBREAK | DT_SINGLELINE;
if (dwStyle & SS_CENTERIMAGE) nFormat |= DT_VCENTER;
if (dwStyle & SS_CENTER) nFormat |= DT_CENTER;
else if (dwStyle & SS_RIGHT) nFormat |= DT_RIGHT;
else nFormat |= DT_LEFT;
int nOldMode = pDC->SetBkMode(TRANSPARENT);
pDC->DrawText(str, rect, nFormat);
pDC->SetBkMode(nOldMode);
}
// Suggested by Pål K. Tønder.
void CBitmapPicture::OnSysColorChange()
{
CStatic::OnSysColorChange();
ReloadBitmap();
}