大家好,我是乘风偷月,下面给大家分享一份如何生成EAN-13条形码的内容,直接拷贝内容应该可以跑起来。希望大家会喜欢
先上效果图
EAN-13介绍:European Article Number (欧洲物品编码的缩写),其中共计13位代码的EAN-13是比较通用的一般终端产品的条形码协议和标准,主要应用于超级市场和其它零售业,因此这种是我们比较常见的,随便拿起身边的一个从超市买来的商品都可以从包装上看得到。
链接:EAN-13_百度百科
在项目中,需要根据文本内容生成条码,打印出来贴到商品上面,这里主要用到EAN-13,在市面上有一些第三方库可以使用,例如ZXing,但是这篇文章将根据百度百科的算法去实现逻辑,并显示出来。
如图所示
根据字符类型,得到前置码:
计算校验符:
以上这些理论的东西可以参考百度百科的详细说明,下面将根据这些理论编写代码。
直接上代码(WIN32 应用程序)
ean13util.h 文件
/*
========================================================================
File name: ean13util.h
Module:
Author: 中唐工作室(zt)18824182332
Create Time: 2016/12/12 10:41:00
Modify By:
Modify Date:
========================================================================
*/
#pragma once
#include "stdafx.h"
class Ean13Util
{
public:
Ean13Util();
Ean13Util(LPCTSTR pStrEan);
void SetBarCode(LPCTSTR pStrEan);
static TCHAR CalSNVerify(LPCTSTR sz);
CString ConverCode(LPCTSTR pStrEan);
~Ean13Util(void);
void DrawBarCode(HDC* pDC, RECT rect);
protected:
CString m_cEanCode;
CString m_cBitCode;
};
ean13util.cpp
/*
========================================================================
File name: ean13util.cpp
Module:
Author: 中唐工作室(zt)18824182332
Create Time: 2016/12/12 10:41:00
Modify By:
Modify Date:
========================================================================
*/
#include "StdAfx.h"
#include "ean13util.h"
#include <assert.h>
// 将12位EAN转换为01条码代码
CString Ean13Util::ConverCode(LPCTSTR pStrEan)
{
// 拿到前置码
LPCTSTR pStrFont = DICTIONTABLE[pStrEan[0] - _T('0')][0];
CString strCode;
for (int i = 0; i < 12; i++)
{
strCode += DICTIONTABLE[pStrEan[i + 1] - _T('0')][pStrFont[i] - _T('A') + 1];
}
return CString(_T("101")) + strCode.Left(strCode.GetLength() / 2)
+ _T("01010") + strCode.Right(strCode.GetLength() / 2) + _T("101");
}
Ean13Util::Ean13Util()
{
}
Ean13Util::Ean13Util(LPCTSTR pStrEan)
{
SetBarCode(pStrEan);
}
Ean13Util::~Ean13Util(void)
{
}
void Ean13Util::SetBarCode(LPCTSTR pStrEan)
{
CString strCode = pStrEan;
if (strCode.GetLength() == 12)
{
strCode += CalSNVerify(strCode);
}
if (strCode.GetLength() != 13)
{
assert(FALSE);
throw - 1;
return;
}
m_cEanCode = strCode;
m_cBitCode = ConverCode(strCode);
}
// 计算EAN-13校验位,生成方法为:
// 前12位的偶数位(索引从1开始)之和*3 - 奇数位和
// 最后返回最接近且大于等于当前数的10倍数与当前值的差值
TCHAR Ean13Util::CalSNVerify(LPCTSTR pStrEan)
{
if (_tcslen(pStrEan) != 12)
{
return _T('0');
}
INT iSum = 0;
for (int i = 0; i < 6; i++)
{
iSum += pStrEan[i * 2] - _T('0');
iSum += (pStrEan[i * 2 + 1] - _T('0')) * 3;
}
return (iSum % 10 == 0) ? _T('0') : 10 - iSum % 10 + _T('0');
}
void Ean13Util::DrawBarCode(HDC* pDC, RECT pRect)
{
if (m_cBitCode.GetLength() == 0)
{
return;
}
// 计算单个模组宽度
INT iWidth = (pRect.right - pRect.left) / (m_cBitCode.GetLength() + 11 * 2);
//设定文字大小和颜色
LOGFONT logfont; //改变输出字体
ZeroMemory(&logfont, sizeof(LOGFONT));
logfont.lfCharSet = ANSI_CHARSET;
logfont.lfHeight = iWidth * 9; //设置字体的大小
logfont.lfEscapement = 0;
logfont.lfOrientation = 0;
logfont.lfWidth = 5.5 * iWidth;
logfont.lfWeight = FW_NORMAL;
logfont.lfItalic = FALSE;
logfont.lfUnderline = FALSE;
logfont.lfOutPrecision = OUT_DEFAULT_PRECIS;
logfont.lfClipPrecision = CLIP_DEFAULT_PRECIS;
logfont.lfQuality = DEFAULT_QUALITY;
logfont.lfPitchAndFamily = (DEFAULT_PITCH | FF_SWISS);
lstrcpy(logfont.lfFaceName, _T("Arial"));
HFONT hFont = CreateFontIndirect(&logfont);
HBRUSH hBrushBlack = CreateSolidBrush(RGB(0, 0, 0));
HBRUSH hOldBrush2 = (HBRUSH)SelectObject(*pDC, hBrushBlack);
for (int i = 0; i < m_cBitCode.GetLength(); i++)
{
RECT rtCur = pRect;
rtCur.left += (11 + i) * iWidth;
rtCur.right = rtCur.left + iWidth;
rtCur.bottom -= 7 * iWidth;
if (m_cBitCode[i] == _T('1'))
{
Rectangle(*pDC, rtCur.left, rtCur.top, rtCur.right, rtCur.bottom);//绘制黑色条形
}
}
SelectObject(*pDC, hOldBrush2);
DeleteObject(hBrushBlack);
HBRUSH hBrushWhile = CreateSolidBrush(RGB(255, 255, 255));
INT iOldMode = SetBkMode(*pDC, TRANSPARENT);
HFONT* pOldFnt = (HFONT*)SelectObject(*pDC, hFont);
RECT rtText = pRect;//文本绘制区域
rtText.top = pRect.bottom - 10 * iWidth;
rtText.right = pRect.left + 11 * iWidth;
//Rectangle(*pDC, rtText.left, rtText.top, rtText.right, rtText.bottom);
DrawText(*pDC, m_cEanCode, 1, &rtText, DT_SINGLELINE | DT_CENTER | DT_VCENTER);
rtText.left = pRect.left + 14 * iWidth;
rtText.right = pRect.left + 57 * iWidth;
FillRect(*pDC, &rtText, hBrushWhile);
DrawText(*pDC, m_cEanCode.Mid(1, 6), -1, &rtText, DT_SINGLELINE | DT_CENTER | DT_VCENTER);
rtText.left = pRect.left + 60 * iWidth;
rtText.right = pRect.left + 103 * iWidth;
FillRect(*pDC, &rtText, hBrushWhile);
DrawText(*pDC, m_cEanCode.Right(6), -1, &rtText, DT_SINGLELINE | DT_CENTER | DT_VCENTER);
DeleteObject(hBrushWhile);
SetBkMode(*pDC, iOldMode);
SelectObject(*pDC, pOldFnt);
}
stdafx.h 文件
// stdafx.h : 标准系统包含文件的包含文件,
// 或是经常使用但不常更改的
// 特定于项目的包含文件
//
#pragma once
#include "targetver.h"
#define WIN32_LEAN_AND_MEAN // 从 Windows 头文件中排除极少使用的信息
// Windows 头文件:
#include <windows.h>
// C 运行时头文件
#include <stdlib.h>
#include <malloc.h>
#include <memory.h>
#include <tchar.h>
#define _ATL_CSTRING_EXPLICIT_CONSTRUCTORS // 某些 CString 构造函数将是显式的
#include <atlbase.h>
#include <atlstr.h>
// TODO: 在此处引用程序需要的其他头文件
const static LPCTSTR DICTIONTABLE[][4] =
{
// TYPE 'A' 'B' 'C'
{ _T("AAAAAACCCCCC"), _T("0001101"), _T("0100111"), _T("1110010") }, // 0
{ _T("AABABBCCCCCC"), _T("0011001"), _T("0110011"), _T("1100110") }, // 1
{ _T("AABBABCCCCCC"), _T("0010011"), _T("0011011"), _T("1101100") }, // 2
{ _T("AABBBACCCCCC"), _T("0111101"), _T("0100001"), _T("1000010") }, // 3
{ _T("ABAABBCCCCCC"), _T("0100011"), _T("0011101"), _T("1011100") }, // 4
{ _T("ABBAABCCCCCC"), _T("0110001"), _T("0111001"), _T("1001110") }, // 5
{ _T("ABBBAACCCCCC"), _T("0101111"), _T("0000101"), _T("1010000") }, // 6
{ _T("ABABABCCCCCC"), _T("0111011"), _T("0010001"), _T("1000100") }, // 7
{ _T("ABABBACCCCCC"), _T("0110111"), _T("0001001"), _T("1001000") }, // 8
{ _T("ABBABACCCCCC"), _T("0001011"), _T("0010111"), _T("1110100") }, // 9
};
Resource.h 文件
//{{NO_DEPENDENCIES}}
// Microsoft Visual C++ 生成的包含文件。
// 供 Ean813Win.rc 使用
//
#define IDC_MYICON 2
#define IDD_EAN813WIN_DIALOG 102
#define IDS_APP_TITLE 103
#define IDD_ABOUTBOX 103
#define IDM_ABOUT 104
#define IDM_EXIT 105
#define IDI_EAN813WIN 107
#define IDI_SMALL 108
#define IDC_EAN813WIN 109
#define IDB_BUTTON_EAN813 111
#define IDR_MAINFRAME 128
#define IDM_EAN813 32771
#define IDC_STATIC -1
#define IDC_RADBTN_EAN13 50001
#define IDC_RADBTN_EAN8 50002
#define IDE_EDIT_ZOOM 50003
// Next default values for new objects
//
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NO_MFC 1
#define _APS_NEXT_RESOURCE_VALUE 130
#define _APS_NEXT_COMMAND_VALUE 32772
#define _APS_NEXT_CONTROL_VALUE 1000
#define _APS_NEXT_SYMED_VALUE 110
#endif
#endif
测试调用:
// Ean813Win.cpp : 定义应用程序的入口点。
//
#include "stdafx.h"
#include "Ean813Win.h"
#include "ean13util.h"
#include "ean8util.h"
#define MAX_LOADSTRING 100
// 全局变量:
HINSTANCE hInst; // 当前实例
TCHAR szTitle[MAX_LOADSTRING]; // 标题栏文本
TCHAR szWindowClass[MAX_LOADSTRING]; // 主窗口类名
HWND hInputNum; //输入编辑框
HWND Ean813Button; //Ean813按钮
HWND hInputZoom; //放大编辑框
int m_izoom; //模宽
Ean13Util ean13Build = Ean13Util();
// 此代码模块中包含的函数的前向声明:
ATOM MyRegisterClass(HINSTANCE hInstance);
BOOL InitInstance(HINSTANCE, int);
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
INT_PTR CALLBACK About(HWND, UINT, WPARAM, LPARAM);
int APIENTRY _tWinMain(_In_ HINSTANCE hInstance,
_In_opt_ HINSTANCE hPrevInstance,
_In_ LPTSTR lpCmdLine,
_In_ int nCmdShow)
{
UNREFERENCED_PARAMETER(hPrevInstance);
UNREFERENCED_PARAMETER(lpCmdLine);
// TODO: 在此放置代码。
MSG msg;
HACCEL hAccelTable;
// 初始化全局字符串
LoadString(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);
LoadString(hInstance, IDC_EAN813WIN, szWindowClass, MAX_LOADSTRING);
MyRegisterClass(hInstance);
// 执行应用程序初始化:
if (!InitInstance(hInstance, nCmdShow))
{
return FALSE;
}
hAccelTable = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDC_EAN813WIN));
// 主消息循环:
while (GetMessage(&msg, NULL, 0, 0))
{
if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
return (int)msg.wParam;
}
//
// 函数: MyRegisterClass()
//
// 目的: 注册窗口类。
//
ATOM MyRegisterClass(HINSTANCE hInstance)
{
WNDCLASSEX wcex;
wcex.cbSize = sizeof(WNDCLASSEX);
wcex.style = CS_HREDRAW | CS_VREDRAW;
wcex.lpfnWndProc = WndProc;
wcex.cbClsExtra = 0;
wcex.cbWndExtra = 0;
wcex.hInstance = hInstance;
wcex.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_EAN813WIN));
wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
wcex.lpszMenuName = MAKEINTRESOURCE(IDC_EAN813WIN);
wcex.lpszClassName = szWindowClass;
wcex.hIconSm = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL));
return RegisterClassEx(&wcex);
}
//
// 函数: InitInstance(HINSTANCE, int)
//
// 目的: 保存实例句柄并创建主窗口
//
// 注释:
//
// 在此函数中,我们在全局变量中保存实例句柄并
// 创建和显示主程序窗口。
//
BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{
HWND hWnd;
hInst = hInstance; // 将实例句柄存储在全局变量中
hWnd = CreateWindow(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT, 600, 400, NULL, NULL, hInstance, NULL);
if (!hWnd)
{
return FALSE;
}
ShowWindow(hWnd, nCmdShow);
UpdateWindow(hWnd);
return TRUE;
}
//
// 函数: WndProc(HWND, UINT, WPARAM, LPARAM)
//
// 目的: 处理主窗口的消息。
//
// WM_COMMAND - 处理应用程序菜单
// WM_PAINT - 绘制主窗口
// WM_DESTROY - 发送退出消息并返回
//
//
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
int wmId, wmEvent;
PAINTSTRUCT ps;
HDC hdc;
static int cxClient, cyClient;
RECT rect;
switch (message)
{
case WM_SIZE:
cxClient = LOWORD(lParam);
cyClient = HIWORD(lParam);
return 0;
case WM_COMMAND:
wmId = LOWORD(wParam);
wmEvent = HIWORD(wParam);
// 分析菜单选择:
switch (wmId)
{
case IDM_ABOUT:
DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About);
break;
case IDM_EXIT:
DestroyWindow(hWnd);
break;
case IDB_BUTTON_EAN813:
//TODO
{
TCHAR buf[256];
SendMessage(hInputNum, WM_GETTEXT, sizeof(buf) / sizeof(TCHAR), (LPARAM)(void*)buf);
if (AtlStrLen(buf) != 12 && AtlStrLen(buf) != 13)
{
MessageBox(hWnd, _T("数字长度为12或者13位"), _T("提示"), 0);
return 0;
}
ean13Build.SetBarCode(buf);
TCHAR buf2[256];
SendMessage(hInputZoom, WM_GETTEXT, sizeof(buf2) / sizeof(TCHAR), (LPARAM)(void*)buf2);
m_izoom = atoi((char*)buf2) < 1 ? 1 : atoi((char*)buf2);
rect.left = 0;
rect.top = 0;
rect.right = cxClient;
rect.bottom = cyClient;
InvalidateRect(hWnd, &rect, true);//擦除上次绘制的内容
}
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
break;
case WM_CREATE:
//添加编辑框
hInputNum = CreateWindow(_T("edit"), NULL,
WS_CHILD | WS_VISIBLE | WS_BORDER,
10, 20, 200, 30,
hWnd, NULL, NULL, NULL);
//添加编辑框
hInputZoom = CreateWindow(_T("edit"), NULL,
WS_CHILD | WS_VISIBLE | WS_BORDER,
380, 20, 40, 30,
hWnd, (HMENU)IDE_EDIT_ZOOM, NULL, NULL);
m_izoom = 5;
SetDlgItemText(hWnd, IDE_EDIT_ZOOM, _T("5"));//设置默认值5
// 添加按钮
Ean813Button = CreateWindow(TEXT("button"), TEXT("EAN13"),
WS_CHILD | WS_VISIBLE,
460, 20, 75, 30,
hWnd, (HMENU)IDB_BUTTON_EAN813,
((LPCREATESTRUCT)lParam)->hInstance, NULL);
break;
case WM_PAINT:
hdc = BeginPaint(hWnd, &ps);
// TODO
//绘制区域,根据缩放倍数进行计算调整
rect.left = cxClient / 2 - m_izoom * 50;
rect.top = cyClient / 2 - m_izoom * 20;
rect.right = cxClient / 2 + m_izoom * 50;
rect.bottom = cyClient / 2 + m_izoom * 20;
ean13Build.DrawBarCode(&hdc, rect);
EndPaint(hWnd, &ps);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}
// “关于”框的消息处理程序。
INT_PTR CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
UNREFERENCED_PARAMETER(lParam);
switch (message)
{
case WM_INITDIALOG:
return (INT_PTR)TRUE;
case WM_COMMAND:
if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL)
{
EndDialog(hDlg, LOWORD(wParam));
return (INT_PTR)TRUE;
}
break;
}
return (INT_PTR)FALSE;
}