📄 painthelper.cpp
字号:
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
//
// Use of this sample source code is subject to the terms of the Microsoft
// license agreement under which you licensed this sample source code. If
// you did not accept the terms of the license agreement, you are not
// authorized to use this sample source code. For the terms of the license,
// please see the license agreement between you and Microsoft or, if applicable,
// see the LICENSE.RTF on your install media or the root of your tools installation.
// THE SAMPLE SOURCE CODE IS PROVIDED "AS IS", WITH NO WARRANTIES.
//
#include "PaintHelper.hpp"
#include "Common.hpp"
#define INVALID_BKMODE -1
//constants
const DWORD PaintHelper_t::CANVAS_CREATED = 0x00000001;
PaintHelper_t::PaintHelper_t(
)
{
ZeroMemory(&m_PaintStruct, sizeof(PAINTSTRUCT));
m_OldBitmap = NULL;
m_OldBkColor = CLR_INVALID;
m_OldBkMode = INVALID_BKMODE;
m_OldBrush = NULL;
m_OldFont = NULL;
m_OldPen = NULL;
m_OldTextColor = CLR_INVALID;
m_hwnd = NULL;
m_Flags = 0;
}
PaintHelper_t::~PaintHelper_t(
)
{
End();
}
HRESULT
PaintHelper_t::Attach(
HDC hdc
)
{
ASSERT(m_hdc == NULL);
if (!hdc)
{
return E_INVALIDARG;
}
m_hdc = hdc;
return S_OK;
}
HRESULT
PaintHelper_t::Begin(
HWND hwnd
)
{
ASSERT(m_hdc == NULL);
m_hwnd = hwnd;
m_hdc = BeginPaint(hwnd, &m_PaintStruct);
if (!m_hdc)
{
return CommonUtilities_t::GetErrorFromWin32();
}
m_OldTextColor = GetTextColor(m_PaintStruct.hdc);
return S_OK;
}
void
PaintHelper_t::End(
)
{
if (!m_hdc)
{
return;
}
if (m_OldBitmap)
{
SelectObject(m_hdc, m_OldBitmap);
m_OldBitmap = NULL;
}
if (m_OldBkColor != CLR_INVALID)
{
::SetBkColor(m_hdc, m_OldBkColor);
m_OldBkColor = CLR_INVALID;
}
if (m_OldBkMode != INVALID_BKMODE)
{
::SetBkMode(m_hdc, m_OldBkMode);
m_OldBkMode = INVALID_BKMODE;
}
if (m_OldBrush)
{
SelectObject(m_hdc, m_OldBrush);
m_OldBrush = NULL;
}
if (m_OldFont)
{
SelectObject(m_hdc, m_OldFont);
m_OldFont = NULL;
}
if (m_OldPen)
{
SelectObject(m_hdc, m_OldPen);
m_OldPen = NULL;
}
if (m_OldTextColor != CLR_INVALID)
{
::SetTextColor(m_PaintStruct.hdc, m_OldTextColor);
m_OldTextColor = CLR_INVALID;
}
if (m_PaintStruct.hdc)
{
EndPaint(m_hwnd, &m_PaintStruct);
ZeroMemory(&m_PaintStruct, sizeof(PAINTSTRUCT));
}
if (!(m_Flags & CANVAS_CREATED))
{
//release the device context since we do not own it
m_hdc.release();
}
if (m_Bitmap.valid())
{
SetRectEmpty(&m_PaintStruct.rcPaint);
m_Bitmap = NULL;
}
m_hdc = NULL;
m_Flags = 0;
}
HRESULT
PaintHelper_t::CreateCanvas(
HWND hwnd,
int Width,
int Height
)
{
ASSERT(m_hdc == NULL);
ce::auto_hdc Screen = GetDC(hwnd);
if (!Screen)
{
return CommonUtilities_t::GetErrorFromWin32(E_OUTOFMEMORY);
}
ce::auto_hdc OffScreen = CreateCompatibleDC(Screen);
if (!OffScreen)
{
return CommonUtilities_t::GetErrorFromWin32(E_OUTOFMEMORY);
}
m_Flags |= CANVAS_CREATED;
//create bitpmap only when requested
if ((Width > 0) && (Height > 0))
{
m_Bitmap = CreateCompatibleBitmap(Screen, Width, Height);
if (!m_Bitmap)
{
return CommonUtilities_t::GetErrorFromWin32(E_OUTOFMEMORY);
}
m_hdc = OffScreen.release();
SetBitmap(m_Bitmap);
SetRect(&m_PaintStruct.rcPaint, 0, 0, Width, Height);
}
else
{
m_hdc = OffScreen.release();
}
return S_OK;
}
HBITMAP
PaintHelper_t::SetBitmap(
HBITMAP bitmap
)
{
HBITMAP OldBitmap = NULL;
if (bitmap)
{
OldBitmap = (HBITMAP)SelectObject(m_hdc, bitmap);
if (m_OldBitmap == NULL)
{
m_OldBitmap = OldBitmap;
}
}
else if (m_OldBitmap)
{
//restore original bitmap
OldBitmap = (HBITMAP)SelectObject(m_hdc, m_OldBitmap);
m_OldBitmap = NULL;
}
return OldBitmap;
}
void
PaintHelper_t::SetBkColor(
COLORREF color
)
{
COLORREF OldColor = ::SetBkColor(m_hdc, color);
if (m_OldBkColor == CLR_INVALID)
{
m_OldBkColor = OldColor;
}
return;
}
void
PaintHelper_t::SetBkMode(
int BkMode
)
{
int OldMode = ::SetBkMode(m_hdc, BkMode);
if (m_OldBkMode == INVALID_BKMODE)
{
m_OldBkMode = OldMode;
}
return;
}
void
PaintHelper_t::SetBrush(
HBRUSH brush
)
{
if (brush)
{
HBRUSH OldBrush = (HBRUSH)SelectObject(m_hdc, brush);
if (m_OldBrush == NULL)
{
m_OldBrush = OldBrush;
}
}
else if (m_OldBrush)
{
//restore original brush
SelectObject(m_hdc, m_OldBrush);
m_OldBrush = NULL;
}
return;
}
void
PaintHelper_t::SetFont(
HFONT font
)
{
HFONT OldFont = (HFONT)SelectObject(m_hdc, font);
if (m_OldFont == NULL)
{
m_OldFont = OldFont;
}
return;
}
void
PaintHelper_t::SetPen(
HPEN Pen
)
{
if (Pen)
{
HPEN OldPen = (HPEN)SelectObject(m_hdc, Pen);
if (m_OldPen == NULL)
{
m_OldPen = OldPen;
}
}
else if (m_OldPen)
{
//restore original pen
SelectObject(m_hdc, m_OldPen);
m_OldPen = NULL;
}
return;
}
void
PaintHelper_t::SetTextColor(
COLORREF color
)
{
COLORREF OldColor = ::SetTextColor(m_hdc, color);
if (m_OldTextColor == CLR_INVALID)
{
m_OldTextColor = OldColor;
}
return;
}
PaintHelper_t&
PaintHelper_t::operator=(
PaintHelper_t& Source
)
{
BitBlt(
m_hdc,
Source.Rect().left,
Source.Rect().top,
RECTWIDTH(Source.Rect()),
RECTHEIGHT(Source.Rect()),
Source,
0,
0,
SRCCOPY
);
return *this;
}
PaintHelper_t::operator HDC(
)
{
return (HDC)m_hdc;
}
HRESULT
PaintHelper_t::DrawText(
const WCHAR* pText,
int TextLength,
const RECT* pRect,
DWORD StyleFlags
)
{
if (!::DrawText(
m_hdc,
pText,
TextLength,
(RECT*)pRect,
StyleFlags
))
{
return CommonUtilities_t::GetErrorFromWin32();
}
return S_OK;
}
HRESULT
PaintHelper_t::CalculateTextDimensions(
const WCHAR* pText,
int TextLength,
HFONT FontToBeUsed,
RECT* pRectangle,
UINT DrawTextFlags
)
{
if (!pText || !pRectangle)
{
return E_INVALIDARG;
}
HRESULT hr;
PaintHelper_t fake;
hr = fake.CreateCanvas(NULL);
if (FAILED(hr))
{
ASSERT(FALSE);
return hr;
}
fake.SetFont(FontToBeUsed);
hr = fake.DrawText(
pText,
TextLength,
pRectangle,
DrawTextFlags | DT_CALCRECT
);
return hr;
}
HRESULT
PaintHelper_t::TileBlt(
__in Bitmap_t* pBitmap3x3Tiles,
__in const RECT* pDestinationRect,
__in_opt const RECT* pSourceRect,
int cxLeft,
int cyTop,
int cxRight,
int cyBottom,
COLORREF TransparentColor
)
{
RECT SourceRect;
if (!pBitmap3x3Tiles || !pDestinationRect)
{
return E_INVALIDARG;
}
if (!pSourceRect)
{
SetRect(
&SourceRect,
0,
0,
pBitmap3x3Tiles->Width(),
pBitmap3x3Tiles->Height()
);
pSourceRect = &SourceRect;
}
struct Tile_t
{
bool m_ShouldBePainted;
RECT m_DestinationRect;
RECT m_SourceRect;
};
const Tile_t c_TilesToPaint[] =
{
{// Upper left corner
(cxLeft > 0 && cyTop > 0),
{pDestinationRect->left, pDestinationRect->top, cxLeft, cyTop},
{pSourceRect->left, pSourceRect->top, cxLeft, cyTop}
},
{// Upper right corner
(cxRight > 0 && cyTop > 0),
{pDestinationRect->right - cxRight, pDestinationRect->top, cxRight, cyTop},
{pSourceRect->right - cxRight, pSourceRect->top, cxRight, cyTop}
},
{// Lower left corner
(cxLeft > 0 && cyBottom > 0),
{pDestinationRect->left, pDestinationRect->bottom - cyBottom, cxLeft, cyBottom},
{pSourceRect->left, pSourceRect->bottom - cyBottom, cxLeft, cyBottom}
},
{// Lower right corner
(cxRight > 0 && cyBottom > 0),
{pDestinationRect->right - cxRight, pDestinationRect->bottom - cyBottom, cxRight, cyBottom},
{pSourceRect->right - cxRight, pSourceRect->bottom - cyBottom, cxRight, cyBottom}
},
// Blit the top and bottom using stretched blits in X
{// Top
(cyTop > 0),
{pDestinationRect->left + cxLeft, pDestinationRect->top, RECTWIDTH(*pDestinationRect) - (cxRight + cxLeft), cyTop},
{pSourceRect->left + cxLeft, pSourceRect->top, RECTWIDTH(*pSourceRect) - (cxRight + cxLeft), cyTop}
},
{// Bottom
(cyBottom > 0),
{pDestinationRect->left + cxLeft, pDestinationRect->bottom - cyBottom, RECTWIDTH(*pDestinationRect) - (cxRight + cxLeft), cyBottom},
{pSourceRect->left + cxLeft, pSourceRect->bottom - cyBottom, RECTWIDTH(*pSourceRect) - (cxRight + cxLeft), cyBottom}
},
// Blit the left and right using stretched blits in Y
{// Left
(cxLeft > 0),
{pDestinationRect->left, pDestinationRect->top + cyTop, cxLeft, RECTHEIGHT(*pDestinationRect) - (cyBottom + cyTop)},
{pSourceRect->left, pSourceRect->top + cyTop, cxLeft, RECTHEIGHT(*pSourceRect) - (cyBottom + cyTop)}
},
{// Right
(cxRight > 0),
{pDestinationRect->right - cxRight, pDestinationRect->top + cyTop, cxRight, RECTHEIGHT(*pDestinationRect) - (cyBottom + cyTop)},
{pSourceRect->right - cxRight, pSourceRect->top + cyTop, cxRight, RECTHEIGHT(*pSourceRect) - (cyBottom + cyTop)}
},
// Finally, blit the center, stretching in X and Y
{// Center
true,
{pDestinationRect->left + cxLeft,
pDestinationRect->top + cyTop,
RECTWIDTH(*pDestinationRect) - (cxRight + cxLeft),
RECTHEIGHT(*pDestinationRect) - (cyBottom + cyTop)
},
{pSourceRect->left + cxLeft,
pSourceRect->top + cyTop,
RECTWIDTH(*pSourceRect) - (cxRight + cxLeft),
RECTHEIGHT(*pSourceRect) - (cyBottom + cyTop)
}
},
};
for (int i = 0; i < _countof(c_TilesToPaint); i++)
{
if (c_TilesToPaint[i].m_ShouldBePainted)
{
if (CLR_INVALID != TransparentColor)
{
if (
!TransparentImage(
m_hdc,
c_TilesToPaint[i].m_DestinationRect.left,
c_TilesToPaint[i].m_DestinationRect.top,
c_TilesToPaint[i].m_DestinationRect.right,
c_TilesToPaint[i].m_DestinationRect.bottom,
*pBitmap3x3Tiles,
c_TilesToPaint[i].m_SourceRect.left,
c_TilesToPaint[i].m_SourceRect.top,
c_TilesToPaint[i].m_SourceRect.right,
c_TilesToPaint[i].m_SourceRect.bottom,
TransparentColor
)
)
{
return CommonUtilities_t::GetErrorFromWin32();
}
}
else
{
PaintHelper_t Source;
HRESULT hr = Source.CreateCanvas(NULL);
if (FAILED(hr))
{
return hr;
}
Source.SetBitmap(*pBitmap3x3Tiles);
if (
!StretchBlt(
m_hdc,
c_TilesToPaint[i].m_DestinationRect.left,
c_TilesToPaint[i].m_DestinationRect.top,
c_TilesToPaint[i].m_DestinationRect.right,
c_TilesToPaint[i].m_DestinationRect.bottom,
Source,
c_TilesToPaint[i].m_SourceRect.left,
c_TilesToPaint[i].m_SourceRect.top,
c_TilesToPaint[i].m_SourceRect.right,
c_TilesToPaint[i].m_SourceRect.bottom,
SRCCOPY
)
)
{
return CommonUtilities_t::GetErrorFromWin32();
}
}
}
}
return S_OK;
}
RECT&
PaintHelper_t::Rect(
)
{
return m_PaintStruct.rcPaint;
}
Bitmap_t::Bitmap_t(
)
{
m_IsAttached = false;
}
Bitmap_t::~Bitmap_t(
)
{
if (m_IsAttached)
{
//release the bitmap since we do not own it
m_Bitmap.release();
}
}
bool
Bitmap_t::operator!(
)
{
return !m_Bitmap;
}
Bitmap_t::operator HBITMAP(
)
{
return (HBITMAP)m_Bitmap;
}
HRESULT
Bitmap_t::Attach(
HBITMAP Bitmap
)
{
ASSERT(!m_Bitmap);
BITMAP bmpObject;
// Get the bitmap for its width and height
if (0 == GetObject(Bitmap, sizeof(bmpObject), &bmpObject))
{
return CommonUtilities_t::GetErrorFromWin32();
}
m_Width = bmpObject.bmWidth;
m_Height = bmpObject.bmHeight;
m_Bitmap = Bitmap;
m_IsAttached = true;
return S_OK;
}
HRESULT
Bitmap_t::LoadBitmap(
HINSTANCE Instance,
UINT ResourceId
)
{
ASSERT(!m_Bitmap);
m_Bitmap = ::LoadBitmap(
Instance,
MAKEINTRESOURCE(ResourceId)
);
if (!m_Bitmap)
{
return CommonUtilities_t::GetErrorFromWin32();
}
BITMAP bmpObject;
// Get the bitmap for its width and height
if (0 == GetObject((HBITMAP)m_Bitmap, sizeof(bmpObject), &bmpObject))
{
return CommonUtilities_t::GetErrorFromWin32();
}
m_Width = bmpObject.bmWidth;
m_Height = bmpObject.bmHeight;
return S_OK;
}
int
Bitmap_t::Height(
)
{
return m_Height;
}
int
Bitmap_t::Width(
)
{
return m_Width;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -