无论是GDI、GDI+还是DirectDraw还是Direct2D,如果不注意细节的话,都非常容易闪屏。
C++// 错误的做法
void OnPaint()
{
using namespace Gdiplus;
CPaintDC dc(this);
Graphics graphics(dc);
Image myImage(L"img1.jpg");
REAL srcWidth = (REAL)myImage.GetWidth();
REAL srcHeight = (REAL)myImage.GetHeight();
RectF srcRect(0.0f, 0.0f, srcWidth, srcHeight);
Matrix myMatrix(1.0f, 0.0f, 0.0f, 1.0f, 200.0f, 20.0f);
BlurParams myBlurParams;
myBlurParams.expandEdge = TRUE;
myBlurParams.radius = 3;
Blur myBlur;
myBlur.SetParameters(&myBlurParams);
// Draw the image without the blur effect.
graphics.DrawImage(&myImage, 20.0, 20.0, srcWidth, srcHeight);
// Draw the image with the blur effect.
graphics.DrawImage(&myImage, &srcRect, &myMatrix, &myBlur, NULL, UnitPixel);
}
// 正确的做法
void OnPaint()
{
using namespace Gdiplus;
CPaintDC dc(this);
Graphics graphics(dc);
Image myImage(L"img1.jpg");
// 画出没有模糊效果的图片
graphics.DrawImage(&myImage, 20, 20);
static Bitmap *g_bmp = NULL;
if (g_bmp == NULL) { // 如果图片还没有被模糊处理过,那么就先处理它,否则直接显示
REAL srcWidth = (REAL)myImage.GetWidth();
REAL srcHeight = (REAL)myImage.GetHeight();
BlurParams myBlurParams;
myBlurParams.expandEdge = TRUE;
myBlurParams.radius = 3;
Blur myBlur;
myBlur.SetParameters(&myBlurParams);
g_bmp = ::new Bitmap(srcWidth, srcHeight, &graphics);
Graphics graphics2(g_bmp);
// 在内存位图上画出高斯模糊过的图片
graphics2.DrawImage(&myImage, NULL, NULL, &myBlur, NULL, UnitPixel);
}
// 画出已经处理过的图片
graphics.DrawImage(g_bmp, 500, 20);
}
OtherBOOL CChildView::OnEraseBkgnd(CDC* pDC)
{
// 抗闪烁 - 不自动清空背景,务必在OnPaint中清空背景,否则易出现显示不正确!
return TRUE;
// 默认 - 自动清空背景,但是在某些情况下可能会闪烁
//return CWnd::OnEraseBkgnd(pDC);
}
Otherstruct CFastDC : public CDC
{
CDC *m_phydc;
CBitmap m_bitmap;
CRect m_rc;
CFastDC() {
m_phydc = NULL;
}
CFastDC(CDC *phyDC, CRect rc, COLORREF cr = RGB(255, 255, 255)) {
m_phydc = NULL;
BeginFastDC(phyDC, rc, cr);
}
~CFastDC() {
if (m_phydc != NULL)
EndFastDC();
}
CDC *BeginFastDC(CDC *phyDC, CRect rc, COLORREF cr = RGB(255, 255, 255))
{
ASSERT(m_phydc == NULL);
m_phydc = phyDC;
m_rc = rc;
CreateCompatibleDC(phyDC); // 新建兼容DC
m_bitmap.CreateCompatibleBitmap(phyDC, m_rc.right-m_rc.left, m_rc.bottom-m_rc.top);
SelectObject(m_bitmap); // 新建承载图像的兼容位图并附着在兼容DC上
FillColor(cr);
return this;
}
void FillColor(COLORREF cr)
{
CRect rc2;
rc2.top = rc2.left = 0;
rc2.right = m_rc.right - m_rc.left;
rc2.bottom = m_rc.bottom - m_rc.top;
FillSolidRect(rc2, cr); // 填充背景
}
BOOL EndFastDC()
{
ASSERT(m_phydc != NULL);
return m_phydc->BitBlt(m_rc.left, m_rc.top,
m_rc.right-m_rc.left, m_rc.bottom-m_rc.top,
this, 0, 0, SRCCOPY);
}
};
Othervoid OnPaint() {
CRect rc;
GetClientRect(rc); // 获取窗口大小
CPaintDC dc(this); // 获取绘图DC
CFastDC memdc(&dc, rc, GetSysColor(COLOR_3DFACE)); // 新建一个指定背景色和大小的内存DC
// TODO: 使用memdc而不是dc作图
// ...
// 当CFastDC析构时,它会自动尝试将自己的图像映射到物理DC上
}
[修改于 10年2个月前 - 2015/07/18 19:34:16]
200字以内,仅用于支线交流,主线讨论请采用回复功能。