MFC对话框中使用GDI画二维码
在对话框中添加 WM_PAINT的相应消息,
具体函数实现,如下:
void CTaskRewardDlg::OnPaint()
{
CPaintDC dc(this); // device context for painting
// TODO: 在此处添加消息处理程序代码
if (m_bDataEncoded)
{
int nBmpWidth = pQR_Encode->m_nSymbleSize;
//获取控件的边界大小
CRect rect;
GetDlgItem(IDC_STATIC_QRCODE)->GetClientRect(&rect);
//定义并创建一个内存设备环境DC
CDC *pCurCDC = GetDlgItem(IDC_STATIC_QRCODE)->GetDC();
//CDC *pCurCDC = GetDC();
//创建兼容性的DC
CDC* pWorkDC = new CDC;
pWorkDC->CreateCompatibleDC(pCurCDC);
//pWorkDC->CreateCompatibleDC(NULL);
CBitmap workBitmap;
//workBitmap.CreateCompatibleBitmap(pWorkDC, nBmpWidth, nBmpWidth);
workBitmap.CreateCompatibleBitmap(pWorkDC, rect.Width(), rect.Height());
CBitmap* pOldBitmap = pWorkDC->SelectObject(&workBitmap);//将位图选入临时内存设备环境
// 背景全部画成白色
pWorkDC->PatBlt(0, 0, nBmpWidth, nBmpWidth, WHITENESS);
// 根据二维码内容绘制位图
for (int i = 0; i < pQR_Encode->m_nSymbleSize; ++i)
{
for (int j = 0; j < pQR_Encode->m_nSymbleSize; ++j)
{
if (pQR_Encode->m_byModuleData[i][j])
{
pWorkDC->SetPixel(i,j, RGB(0, 0, 0));
}
}
}
// 图片显示调用函数stretchBlt
//::StretchBlt(pCurCDC->GetSafeHdc(),335, 33, 150, 150, pWorkDC->GetSafeHdc(), 0, 0,nBmpWidth, nBmpWidth, SRCCOPY);
pCurCDC->StretchBlt(rect.left, rect.top, rect.Width(), rect.Height(), pWorkDC, 0, 0, nBmpWidth, nBmpWidth, SRCCOPY);
pWorkDC->SelectObject(pOldBitmap);
DeleteObject(pOldBitmap); //删除内存中的位图
pWorkDC->DeleteDC(); //删除CreateCompatibleDC得到的图片DC
delete pWorkDC;
ReleaseDC(pCurCDC); //释放获取的DC句柄
}
// 不为绘图消息调用 CIBADialog::OnPaint()
}
效果图:
说明:
1. 获取IDC_STATIC_QRCODE控件的矩形坐标,用这个坐标来指定新位图的宽和高、指定展示图片的位置,而不是用写死的坐标。一旦这个界面有所更改,代码层面就不需要重新指定坐标了。
//获取控件的边界大小
CRect rect;
GetDlgItem(IDC_STATIC_QRCODE)->GetClientRect(&rect);
2. 定义并创建一个内存设备环境DC 时,直接获取IDC_STATIC_QRCODE控件,使二维码直接显示在这个控件的区域内,而不需要自己去指定像素位置了。
如果直接改成
CDC *pCurCDC = GetDC();
//创建兼容性的DC
CDC* pWorkDC = new CDC;
pWorkDC->CreateCompatibleDC(NULL);
也是可以正常显示二维码的,只不过显示的位置就不在指定控件上了。
3. 如果代码前面获取的是IDC_STATIC_QRCODE控件范围内的DC,后面显示图片的代码
::StretchBlt(pCurCDC->GetSafeHdc(),335, 33, 150, 150, pWorkDC->GetSafeHdc(), 0, 0,nBmpWidth, nBmpWidth, SRCCOPY);
执行后,二维码在页面上显示不出来。
4. 二维码的生成,在C++中没有可以直接生成并显示二维码的API,只能自己一步步去实现。
这一步我是从网上下载了C源代码QR ENCODE,自己封装成了一个类来调用。
调用接口,输入二维码的字符串内容,可以生成一个内容为1或者0的二维数组。
得到这个数组后,先把DC的背景色画成白色,再循环遍历数组,如果数组中的内容为1,则在DC上画一个黑色的像素点,最终就在内存里画好了一个二维码。最后再把二维码位图显示在显卡上。