上一版本链接:https://blog.csdn.net/u012156872/article/details/103755254,测试过程中发现存在问题,于是进行了功能补充。
源码实现(CSWMemDC.h):
#pragma once
namespace sw {
class CMemDC : public CDC
{
public:
CMemDC(CDC& dc, CWnd* pWnd, BOOL bAutoDraw = TRUE) :
m_dc(dc), m_bMemDC(FALSE), m_hBufferedPaint(NULL), m_hOldBmp(NULL), m_hBmp(NULL), m_pWnd(pWnd), m_bAutoDraw(bAutoDraw)
{
ASSERT_VALID(pWnd);
pWnd->GetClientRect(m_rect);
m_rect.right += pWnd->GetScrollPos(SB_HORZ);
m_rect.bottom += pWnd->GetScrollPos(SB_VERT);
HDC hdcPaint = NULL;
m_hBufferedPaint = NULL;// BeginBufferedPaint(dc.GetSafeHdc(), m_rect, BPBF_TOPDOWNDIB, NULL, &hdcPaint);
if (m_hBufferedPaint != NULL && hdcPaint != NULL)
{
m_bMemDC = TRUE;
this->Attach(hdcPaint);
}
else
{
if (this->CreateCompatibleDC(&m_dc))
{
m_bMemDC = TRUE;
BITMAPINFO bi;
bi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
bi.bmiHeader.biBitCount = 32;
bi.bmiHeader.biHeight = m_rect.Height();
bi.bmiHeader.biWidth = m_rect.Width();
bi.bmiHeader.biPlanes = 1;
bi.bmiHeader.biCompression = BI_RGB;
bi.bmiHeader.biXPelsPerMeter = 0;
bi.bmiHeader.biYPelsPerMeter = 0;
bi.bmiHeader.biClrUsed = 0;
bi.bmiHeader.biSizeImage = ((m_rect.Width() * 32 + 31) & (~31)) >> 3 * m_rect.Height();
PVOID pvBits = NULL;
m_hBmp = ::CreateDIBSection(NULL, &bi, DIB_RGB_COLORS, &pvBits, 0, 0);//创建32位位图
m_hOldBmp = (HBITMAP)this->SelectObject((HBITMAP)m_hBmp);
}
}
}
CMemDC(CDC& dc, const CRect& rect, BOOL bAutoDraw = TRUE) :
m_dc(dc), m_bMemDC(FALSE), m_hBufferedPaint(NULL), m_hOldBmp(NULL), m_rect(rect), m_hBmp(NULL), m_pWnd(NULL), m_bAutoDraw(bAutoDraw)
{
ASSERT(!m_rect.IsRectEmpty());
m_pWnd = dc.GetWindow();
HDC hdcPaint = NULL;
m_hBufferedPaint = NULL;// BeginBufferedPaint(dc.GetSafeHdc(), m_rect, BPBF_TOPDOWNDIB, NULL, &hdcPaint);
if (m_hBufferedPaint != NULL && hdcPaint != NULL)
{
m_bMemDC = TRUE;
this->Attach(hdcPaint);
}
else
{
if (this->CreateCompatibleDC(&m_dc))
{
m_bMemDC = TRUE;
BITMAPINFO bi;
bi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
bi.bmiHeader.biBitCount = 32;
bi.bmiHeader.biHeight = m_rect.Height();
bi.bmiHeader.biWidth = m_rect.Width();
bi.bmiHeader.biPlanes = 1;
bi.bmiHeader.biCompression = BI_RGB;
bi.bmiHeader.biXPelsPerMeter = 0;
bi.bmiHeader.biYPelsPerMeter = 0;
bi.bmiHeader.biClrUsed = 0;
bi.bmiHeader.biSizeImage = ((m_rect.Width() * 32 + 31) & (~31)) >> 3 * m_rect.Height();
PVOID pvBits = NULL;
m_hBmp = ::CreateDIBSection(NULL, &bi, DIB_RGB_COLORS, &pvBits, 0, 0);//创建32位位图
m_hOldBmp = (HBITMAP)this->SelectObject((HBITMAP)m_hBmp);
}
}
}
virtual ~CMemDC()
{
if (m_hBufferedPaint != NULL)
{
this->Detach();
EndBufferedPaint(m_hBufferedPaint, TRUE);
}
else if (m_bMemDC)
{
if (m_bAutoDraw)
{
DrawSufface(255);
}
this->SelectObject((HBITMAP)m_hOldBmp);
}
}
CMemDC* operator->()
{
return this;
}
operator CMemDC*()
{
return this;
}
CDC& GetDC() { return m_bMemDC ? *this : m_dc; }
BOOL IsMemDC() const { return m_bMemDC; }
BOOL IsVistaDC() const { return m_hBufferedPaint != NULL; }
void DrawSufface(BYTE byAlpha/* = 255*/)
{
CRect rcClip;
int nClipType = m_dc.GetClipBox(rcClip);
if (nClipType != NULLREGION)
{
if (nClipType != SIMPLEREGION)
{
rcClip = m_rect;
}
BLENDFUNCTION blend;
blend.AlphaFormat = AC_SRC_ALPHA;
blend.BlendFlags = 0;
blend.BlendOp = AC_SRC_OVER;
blend.SourceConstantAlpha = byAlpha;
::AlphaBlend(m_dc.GetSafeHdc(), rcClip.left, rcClip.top, rcClip.Width(), rcClip.Height(), m_hDC, rcClip.left, rcClip.top, rcClip.Width(), rcClip.Height(), blend);
//::BitBlt(m_dc.GetSafeHdc(), rcClip.left, rcClip.top, rcClip.Width(), rcClip.Height(), m_hDC, rcClip.left, rcClip.top, SRCCOPY);
//::UpdateLayeredWindow(m_pWnd->GetSafeHwnd(), m_dc.GetSafeHdc(), NULL, &CSize(rcClip.Width(), rcClip.Height()), m_hDC, &CPoint(rcClip.left, rcClip.top), 0, &blend, ULW_COLORKEY | ULW_ALPHA);
}
}
protected:
CDC& m_dc;
BOOL m_bMemDC;
HANDLE m_hBufferedPaint;
HBITMAP m_hBmp;
HBITMAP m_hOldBmp;
CRect m_rect;
CWnd* m_pWnd;
BOOL m_bAutoDraw;
};
}