EAN13条形码生成器(C++)

活动地址:毕业季·进击的技术er

夏日炎炎,热浪中我们迎来毕业季,这是告别,也是迈向新起点的开始,CSDN诚邀各毕业生/在校生/职场人讲述自己的毕业季故事,分享自己的经验,技术er的进击之路,等你来书写!你可以选择适合自己的对应身份从以下相关内容方向着笔,也可从自身经历出发,贴合活动主题参与投稿,文章题目自拟。

大家好,我是乘风偷月,下面给大家分享一份如何生成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;
}

职场人
目前为止毕业11年,当初学习的是信息与计算科学
一直从事本专业工作,目前从事的行业为交通行业,一开始的入门导师给了我很大的帮助,教会了我很多技术,例如,对接海康,大华的网络摄像机SDK,指导一些与视频相关的知识点,让我很快了解掌握了入门技巧等等技术。
从毕业生到职场IT人,最大的感受是面对每天不一样的工作内容,每次都是挑战和机遇伴成长。
我觉得毕业季职场新人参与工作,要看重行业的发展前景,女怕嫁错郎,男怕入错行,就是这个道理。
工作中,技术er需要不断感悟及回顾已做过的一些事情,这样把问题弄懂弄通弄透。从而,会发现不一样的印象。
你用过哪些开源项目让你忍不住分享给朋友?若依框架,JEECGBOOT,等等
工作中用技术做过的事,申请的项目专利有我的名字,哈哈
程序员三十五岁瓶颈,这并不影响一个老程序员继续发光发热,我已经超过35了,
路就在脚下,走稳每一步至关重要,一步一个脚印,创造美好生活,然后,贡献社会。

活动地址:毕业季·进击的技术er

  • 2
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

乘风偷月

如果觉得有用,请打赏一杯奶茶

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值