MFC对话框中使用GDI画二维码

时间:2024-03-21 22:17:46

在对话框中添加 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()
}

效果图:

MFC对话框中使用GDI画二维码

 

说明:

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上画一个黑色的像素点,最终就在内存里画好了一个二维码。最后再把二维码位图显示在显卡上。