MFC如何将二维码渲染到界面上

前言

之前的一个项目,涉及到C++界面包装ocx,当调用界面的一个方法时会弹窗二维码,二维码直接渲染到控件上(对话框)。使用的二维码库是qrencode,其中还遇到一个困难,C++界面缩放时,ocx界面不跟着缩放,那个问题解决很简单,只需要在Size事件中改变内部的ocx大小即可。下面不多说,进入界面如何渲染二维码。

实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
void QRCodeDialog::OnPaint()
{
CPaintDC dc(this); // device context for painting
COLORREF white = RGB(255,255,255);
COLORREF black = RGB(0,0,0);

// TODO: 在此处添加消息处理程序代码
// 不为绘图消息调用 CDialogEx::OnPaint()
// m_qrcode 为二维码信息,得到二维码引用
QRcode *qr=QRcode_encodeString(m_qrcode.c_str(),
1,
QR_ECLEVEL_L,
QR_MODE_8,
1);
//获取二维码宽度
const int qr_width = qr->width > 0 ? qr->width:1;
//内存画布
CDC MemDC;
MemDC.CreateCompatibleDC(NULL);
CBitmap MemBitmap;//定义一个位图对象
MemBitmap.CreateCompatibleBitmap(&dc,qr_width,qr_width);
//将位图选入到内存显示设备中
//只有选入了位图的内存显示设备才有地方绘图,画到指定的位图上
MemDC.SelectObject(&MemBitmap);


MemDC.FillSolidRect(0,0,qr_width,qr_width,RGB(255,255,255));



double scale = m_width/qr_width;
for(int y=0;y<qr_width;y++)
{
for(int x = 0;x<qr_width;x++)
{
unsigned char b = qr->data[y*qr_width+x];
if(b&0x01)
{
MemDC.SetPixel(x,y,black);
}else
{
MemDC.SetPixel(x,y,white);
}
}
}
dc.SetStretchBltMode(BLACKONWHITE);
//复制
int border_width = GetSystemMetrics(SM_CXDLGFRAME);
//这个比较重要,将内存设备画出来的二维码等比例复制到QRCodeDialog设备的画布中
// 如果直接画到QRCodeDialog设备中,会发现二维码很小,所以我们需要一个内存画布中转下
dc.StretchBlt(border_width*5/2,border_width*5/2,m_width,m_height,&MemDC,0,0,qr_width,qr_width,SRCCOPY);

//绘图完成后的清理
MemBitmap.DeleteObject();
MemDC.DeleteDC();

MemBitmap.DeleteObject();
MemDC.DeleteDC();

QRcode_free(qr);
}

结尾

因为二维码库生成的二维码图像很小,所以需要缩放下。具体思路:先在内存中画,画好之后再放大拷贝到Dialog中。这个文章参考QT如何使用qrencode,绘制出二维码,但是QT直接使用一个方法就可以放大绘制到Dialog中。不管用什么框架绘制,基本上思路都是差不多的。

评论