使用soui4实现一个打印排版软件(七)UPCA码实现

在这里插入图片描述
以下是关于UPCA、UPCE、EAN8、EAN13等长短不一以及文本分开的码制条码的实现。
UPCA码
UPCA码绘制如下:

	//UPCA
	SStringW sstrContent = L"01234567891";
	if (sstrContent.GetLength() != 11 && sstrContent.GetLength() != 12)
	{
		//数据长度错误
	}
	//计算文本所占的大小
	SIZE szContent;
	pRT->MeasureText(sstrContent, sstrContent.GetLength(), &szContent);
	//将绘制条码的区域跟绘制文本的区域分开(此处只考虑文本在下方的情况,如有其他的需求可自己实现)
	CRect rcBar(rcWindow);
	rcBar.bottom = rcBar.bottom - szContent.cy;
	CRect rcText(rcWindow);
	rcText.top = rcBar.bottom;
	//如果是11位则需要自己计算校验码,如果是12位则需要验证一下校验码是否正确
	//校验码计算规则	
	//1 3 5 7 9 11位之和得出C1
	//2 4 6 8 10位之和乘以3得出C2
	//C1 + C2取个位得出CC
	//校验码为10 - CC如果结果为10则校验码为0
	SStringW sstr1 = sstrContent.GetAt(0);
	SStringW sstr2 = sstrContent.GetAt(1);
	SStringW sstr3 = sstrContent.GetAt(2);
	SStringW sstr4 = sstrContent.GetAt(3);
	SStringW sstr5 = sstrContent.GetAt(4);
	SStringW sstr6 = sstrContent.GetAt(5);
	SStringW sstr7 = sstrContent.GetAt(6);
	SStringW sstr8 = sstrContent.GetAt(7);
	SStringW sstr9 = sstrContent.GetAt(8);
	SStringW sstr10 = sstrContent.GetAt(9);
	SStringW sstr11 = sstrContent.GetAt(10);
	int nC1 = (std::stoi(sstr1.c_str()) + std::stoi(sstr3.c_str()) + std::stoi(sstr5.c_str()) + std::stoi(sstr7.c_str()) + std::stoi(sstr9.c_str()) + std::stoi(sstr11.c_str()));
	int nC2 = (std::stoi(sstr2.c_str()) + std::stoi(sstr4.c_str()) + std::stoi(sstr6.c_str()) + std::stoi(sstr8.c_str()) + std::stoi(sstr10.c_str())) * 3;
	int nCC = (nC1 + nC2) % 10;
	int nCheck = 10 - nCC;
	if (nCheck == 10) nCheck = 0;
	if (sstrContent.GetLength() == 12)
	{
		SStringW sstr12 = sstrContent.GetAt(11);
		int nContentCheck = std::stoi(sstr12.c_str());
		if (nContentCheck != nCheck)
		{
			//校验码错误
		}
	}
	SStringW sstrData = sstr1 + sstr2 + sstr3 + sstr4 + sstr5 + sstr6 + sstr7 + sstr8 + sstr9 + sstr10 + sstr11;
	std::string strContent = S_CW2A(sstrData);
	SStringW sstrCheck;
	sstrCheck.Format(L"%d", nCheck);

	struct zint_symbol* symbol;
	symbol = ZBarcode_Create();
	symbol->symbology = BARCODE_UPCA;
	symbol->input_mode = DATA_MODE; //编码格式
	int nRet = ZBarcode_Encode_and_Buffer_Vector(symbol, (unsigned char*)strContent.c_str(), strContent.size(), 0);
	if (nRet == 0)
	{
		ZBarcode_Print(symbol, 0);
		int nMinLen = 1000;
		int nMaxLen = 0;
		std::vector<CRect> vecLines;
		if (symbol->vector)
		{
			struct zint_vector_rect* rect = symbol->vector->rectangles;
			while (rect)
			{
				CRect rcTmp;
				rcTmp.left = rect->x;
				rcTmp.top = rect->y;
				rcTmp.right = rcTmp.left + rect->width;
				rcTmp.bottom = rcTmp.top + rect->height;
				vecLines.push_back(rcTmp);

				if (rect->height > nMaxLen) nMaxLen = rect->height;
				if (rect->height < nMinLen) nMinLen = rect->height;
				rect = rect->next;
			}
		}
		double nDrawUint = (double)rcWindow.Width() / symbol->width;
		double nUint = (double)symbol->bitmap_width / symbol->width;
		std::vector<CRect> vecDrawLines; 
		double dMinReal = 0.0;
		for (int i = 0; i < vecLines.size(); i++)
		{
			CRect rcTmp(vecLines[i]);
			rcTmp.left = rcTmp.left / nUint * nDrawUint;
			rcTmp.right = rcTmp.right / nUint * nDrawUint;
			if (rcTmp.Height() == nMaxLen)
			{
				rcTmp.bottom = rcTmp.top + rcWindow.Height();
				dMinReal = rcTmp.Height();
			}
			else
			{
				rcTmp.bottom = rcTmp.top + rcBar.Height() - szContent.cy;
				dMinReal = rcTmp.Height();
			}
			vecDrawLines.push_back(rcTmp);
		}
		//绘制条码
		for (int i = 0; i < vecDrawLines.size(); i++)
		{
			COLORREF clrFrgnd = GETCOLOR(L"RGB(0,0,0)");
			CAutoRefPtr<IBrush> brush, oldbrush;
			pRT->CreateSolidColorBrush(clrFrgnd, &brush);
			CRect rcBlack;
			rcBlack.left += vecDrawLines[i].left + rcBar.left;
			rcBlack.top += vecDrawLines[i].top + rcBar.top;
			rcBlack.right = rcBlack.left + vecDrawLines[i].Width();
			rcBlack.bottom = rcBlack.top + vecDrawLines[i].Height();

			pRT->SelectObject(brush, (IRenderObj**)&oldbrush);
			pRT->FillRectangle(&rcBlack);
			pRT->SelectObject(oldbrush, NULL);
		}
	}

在这里插入图片描述
以上即为UPCA码条码的绘制。
对于文本的绘制与CODE128码不同的是文本绘制需要分为4部分;第一部分是首位、第二部分为2-6位、第三部分为7-11位、第四部分为校验位。
第一部分的绘制区域为条码开始区域至第一个线条的位置,第二部分为第四个线条右侧至第15个线条的左侧,第三部分为第16个线条的右侧至第27个线条的左侧,第三部分为倒数第一个线条的右侧至条码区域的结束位置。

	CRect rcContentStart(rcText), rcContentLeft(rcText), rcContentRight(rcText), rcContentCheck(rcText);
	rcContentStart.right = rcContentStart.left + vecDrawLines[0].left - 5;
	rcContentCheck.left = rcText.left + vecDrawLines[vecDrawLines.size() - 1].right + 5;

	rcContentLeft.left = rcText.left + vecDrawLines[4].left;
	rcContentLeft.right = rcText.left + vecDrawLines[13].right;

	rcContentRight.left = rcText.left + vecDrawLines[16].left;
	rcContentRight.right = rcText.left + vecDrawLines[25].right;

	//绘制第一位
	pRT->DrawText(sstr1, -1, (LPRECT)rcContentStart, DT_RIGHT | DT_VCENTER | DT_SINGLELINE | DT_NOPREFIX);

	//绘制校验位
	pRT->DrawText(sstrCheck, -1, (LPRECT)rcContentCheck, DT_LEFT | DT_VCENTER | DT_SINGLELINE | DT_NOPREFIX);

	//绘制第二部分
	{
		SStringW sstrDrawContent = sstr2 + sstr3 + sstr4 + sstr5 + sstr6;
		pRT->DrawText(sstrDrawContent, -1, (LPRECT)rcContentLeft, DT_CENTER | DT_VCENTER | DT_SINGLELINE | DT_NOPREFIX);
	}
	
	//绘制第三部分
	{
		SStringW sstrDrawContent = sstr7 + sstr8 + sstr9 + sstr10 + sstr11;
		pRT->DrawText(sstrDrawContent, -1, (LPRECT)rcContentRight, DT_CENTER | DT_VCENTER | DT_SINGLELINE | DT_NOPREFIX);
	}

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值