条码生成使用了开源库zint。该库实现了全部的常用码制。
在项目头文件中将库导入项目:
//zint
#include "../zint/include/backend/zint.h"
#ifdef _DEBUG
#pragma comment(lib, "../zint/lib/debug/zint.lib")
#else
#pragma comment(lib, "../zint/lib/release/zint.lib")
#endif
条码元素的移动、拉伸参考rect的实现,这里我们主要看看条码的绘制部分代码
#pragma once
#include "CEleBase.h"
class CEleBarcode : public CEleBase
{
DEF_SOBJECT(SWindow, L"ele_barcode")
public:
CEleBarcode();
~CEleBarcode();
public:
void OnPaint(IRenderTarget* pRT);
protected:
LRESULT OnCreate(LPVOID);
void OnLButtonDown(UINT nFlags, SOUI::CPoint point);
void OnLButtonUp(UINT nFlags, SOUI::CPoint point);
void OnMouseMove(UINT nFlags, SOUI::CPoint point);
void OnLButtonDblClk(UINT nFlags, SOUI::CPoint point);
void OnRButtonUp(UINT nFlags, CPoint point);
protected:
SOUI_MSG_MAP_BEGIN()
MSG_WM_CREATE(OnCreate)
MSG_WM_PAINT_EX(OnPaint)
MSG_WM_LBUTTONDOWN(OnLButtonDown)
MSG_WM_LBUTTONUP(OnLButtonUp)
MSG_WM_LBUTTONDBLCLK(OnLButtonDblClk)
MSG_WM_RBUTTONUP(OnRButtonUp)
MSG_WM_MOUSEMOVE(OnMouseMove)
SOUI_MSG_MAP_END()
private:
CPoint m_ptDown;
EcPosType m_curEcPosType;
};
#include "stdafx.h"
#include "CEleBarcode.h"
CEleBarcode::CEleBarcode()
{
//
}
CEleBarcode::~CEleBarcode()
{
//
}
void CEleBarcode::OnPaint(IRenderTarget* pRT)
{
SetMsgHandled(FALSE);
pRT->SetAntiAlias(TRUE);
CRect rcWindow = GetWindowRect();
SStringW sstrContent = L"0123456789";
//计算文本所占的大小
SIZE szContent;
pRT->MeasureText(sstrContent, sstrContent.GetLength(), &szContent);
//将绘制条码的区域跟绘制文本的区域分开(此处只考虑文本在下方的情况,如有其他的需求可自己实现)
CRect rcBar(rcWindow);
rcBar.bottom = rcBar.bottom - szContent.cy;
CRect rcText(rcWindow);
rcText.top = rcBar.bottom;
std::string strContent = S_CW2A(sstrContent);
struct zint_symbol* symbol;
symbol = ZBarcode_Create();
symbol->symbology = BARCODE_CODE128;
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);
std::vector<CRect> vecLines;
if (symbol->vector)
{
struct zint_vector_rect* rect = symbol->vector->rectangles;
while (rect)
{
CRect rcLine;
rcLine.left = rect->x;
rcLine.top = rect->y;
rcLine.right = rcLine.left + rect->width;
rcLine.bottom = rcLine.top + rect->height;
vecLines.push_back(rcLine);
rect = rect->next;
}
double nDrawUint = (double)rcBar.Width() / symbol->width;
double nUint = (double)symbol->bitmap_width / symbol->width;
CAutoRefPtr<IPathS> path;
GETRENDERFACTORY->CreatePath(&path);
for (int i = 0; i < vecLines.size(); i++)
{
CRect rcTmp(vecLines[i]);
rcTmp.left = rcTmp.left / nUint * nDrawUint;
rcTmp.right = rcTmp.right / nUint * nDrawUint;
rcTmp.bottom = rcTmp.top + rcBar.Height();
CRect rcBlack;
rcBlack.left += rcTmp.left + rcBar.left;
rcBlack.top += rcTmp.top + rcBar.top;
rcBlack.right = rcBlack.left + rcTmp.Width();
rcBlack.bottom = rcBlack.top + rcTmp.Height();
path->addRect(rcBlack);
}
COLORREF clrFrg = GETCOLOR(L"RGB(0,0,0)");
CAutoRefPtr<IBrush> brush, oldbrush;
pRT->CreateSolidColorBrush(clrFrg, &brush);
pRT->SelectObject(brush, (IRenderObj**)&oldbrush);
pRT->FillPath(path);
pRT->SelectObject(oldbrush, NULL);
//绘制文本
{
pRT->DrawText(sstrContent, -1, (LPRECT)rcText, DT_CENTER | DT_VCENTER | DT_SINGLELINE | DT_NOPREFIX);
}
}
}
//...
}
LRESULT CEleBarcode::OnCreate(LPVOID)
{
SetMsgHandled(FALSE);
//生成元素ID
std::string strUUID = CGlobalUnits::GetInstance()->GenerateUUID();
m_strUUID = strUUID;
return __super::OnCreate(NULL);
}
void CEleBarcode::OnLButtonDown(UINT nFlags, SOUI::CPoint point)
{
SetMsgHandled(FALSE);
SetCapture();
//...
}
void CEleBarcode::OnLButtonUp(UINT nFlags, SOUI::CPoint point)
{
SetMsgHandled(FALSE);
ReleaseCapture();
//...
}
void CEleBarcode::OnMouseMove(UINT nFlags, SOUI::CPoint point)
{
SetMsgHandled(FALSE);
//...
}
void CEleBarcode::OnLButtonDblClk(UINT nFlags, SOUI::CPoint point)
{
SetMsgHandled(FALSE);
}
void CEleBarcode::OnRButtonUp(UINT nFlags, CPoint point)
{
SetMsgHandled(FALSE);
}
控件使用:
先注册,再在容器中创建元素
m_theApp->RegisterWindowClass<CEleBarcode>();
CEleBarcode* pEle = (CEleBarcode*)SApplication::getSingleton().CreateWindowByName(L"ele_barcode");
SASSERT(pEle);
SApplication::getSingleton().SetSwndDefAttr(pEle);
this->InsertChild(pEle);
pEle->SSendMessage(WM_CREATE);
CPoint ptReal(point);
ptReal.x -= rcContainer.left;
ptReal.y -= rcContainer.top;
SStringT sstrRectPos;
sstrRectPos.Format(_T("%d,%d,@%d,@%d"), ptReal.x, ptReal.y, 100, 30);
pEle->SetAttribute(L"pos", sstrRectPos);
//将位置、长宽等信息转为毫米
CPoint ptRB(ptReal.x + 100, ptReal.y + 30);
pEle->m_ptLT = ptReal;
pEle->m_ptRB = ptRB;
以上就是条码控件的实现以及使用,此处只实现了CODE128码,其他码制的实现类似。需要注意的是这里文本跟条码的绘制是分开绘制的。如果是EAN8、EAN13、UPCA或者UPCE此类长短不一的线条还需要做特殊的处理。