C++知识之如何利用双缓冲避免在HDC上画图时图像闪烁

最近在做项目时,需要实现在摄像机显示的图像上绘制指定的图案。就这样一个简单的功能花了三四天才彻底做出来,大部分时间都浪费在解决图像闪烁问题。于是整理了一下大概实现代码,用于记录成长过程和分享。

大概实现代码如下:

// 获取与窗口相关的HDC
HDC hdc = GetWindowDC(((HWND)m_hwnd));

/*如果直接在hdc上进行绘画时,很大概率上会发生视频录像中图像闪烁的问题。一开始我就是直接在此句柄上进行绘制,导致显示出来的数据一直在闪烁。*/

// 创建内存DC(创建一个与窗口矩形显示兼容的内存显示设备描述表)
HDC hMemDC = CreateCompatibleDC(hdc);

HDRAWDIB hdib =::DrawDibOpen();	
// 用完记得最后调用	::DrawDibClose(hdib);关闭

// 在hMemDC上画出需要的画面显示数据
int nRet=::DrawDibDraw(hdib,hMemDC,rc.left,rc.top,rc.right,rc.bottom,&(m_bmpInfo.bmiHeader),m_drawbuf,0,0,fixed_width,fixed_height,0);

// 这里的m_hwnd 窗口句柄,由上层传递
RECT rc;
GetClientRect(m_hwnd, &rc);
int nWidth = rc.right - rc.left;
int nHeight = rc.bottom - rc.top;

// 创建兼容性位图(用hdc创建一个与窗口矩形显示兼容的位图)
HBITMAP hMemBitmap = CreateCompatibleBitmap(hdc, nWidth , nHeight );

// 将位图hBitmap选入到内存显示设备的hMenDC中,只有选入了位图的内存显示设备才有地方绘图,画到指定的位图上
SelectObject(hMemDC, hMemBitmap);

// 进行绘图操作
// 设置输出方式(TRANSPARENT:使用透明的输出)
SetBkMode((hMemDC , TRANSPARENT);

// 计算字体高度与磅值
LOGFONT lFont;
memset(&lFont, 0, sizeof(LOGFONT));
// 设为16号字体
lFont.lfHeight = -MulDiv(16, GetDeviceCaps(hMemDC , LOGPIXELSY), 80);
lFont.lfWeight = FW_BOLD;

// 创建字体
HFONT hFont;
hFont = ::CreateFontIndirect(&lFont);
//选择字体
HGDIOBJ hOldFont = ::SelectObject(hMemDC , hFont);
// 设置颜色    这里设置为(0,0,0)黑色,其他颜色可自己指定
SetTextColor((hMemDC , RGB(0, 0, 0));

// 设置摄像机视频指定字符输出
std::string strText = “用于测试显示字符,图像是否闪烁”;
int nLen = (int)strText.size();
std::wstring wstr;
wstr.resize(nLen, L' ');
// CP_UTF8 utf_8显示
MultiByteToWideChar(CP_UTF8, 0, (LPCCH)strText.c_str(), nLen, (LPWSTR)wstr.c_str(), nLen);


// 确定文字绘制区域
RECT rcDraw = { 0 };
rcDraw.left = 0;		// 具体位置按自己实际需求进行填写
rcDraw.top = 0;
rcDraw.right = 200;
rcDraw.bottom = 150;
// 画指定数据 DT_LEFT左上角  DT_WORDBREAK超过指定宽度自动换行
DrawText(hMemDC, (LPCWSTR)wstr.c_str(), (int)strText.size(), &rcDraw, DT_LEFT | DT_WORDBREAK);

/// 最重要的一步
// 再将hMemDC画好的图案贴回到hdc上
BitBlt(hdc, rc.left, rc.top, rc.right, rc.bottom, hMemDC, 0, 0, SRCCOPY);

// 清空
::SelectObject(hMemDC, hOldFont);
::DeleteObject(hFont);
hFont = NULL;
hOldFont = NULL;

// 图已经画出来了.删除位图
::DeleteObject(hMemBitmap);
// 删掉内存hMemDC
DeleteDC(hMemDC);

::ReleaseDC(m_hwnd, hdc);

不同环境实现时的代码一般都有差别,以上代码仅供参考。

参考资料的链接
获取HDC方法
实现双缓存
BitBlt()双缓冲解决图象闪烁
BitBlt参数含义

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值