2023年2月

在我们以前的项目了,做摄像头的图片采集,我们一般还是需要做一个封装处理的,在较新版本的DevExpress控件里面,增加了一个CameraControl控件,可以直接调用摄像头显示的,因此也可以做头像采集等功能,本文介绍如何基于这个控件做相关的图像采集操作。

1、CameraControl控件介绍

该控件从15.1开始,就开始加入控件组了,控件的使用很简单,直接拖动到界面就可以在Winform界面上使用了。本案例基于16.1进行开发的,因此也都具有这些控件模块的。

例如我们直接把CameraControl控件拖动到界面上,然后运行界面就可以看到如下效果。

在摄像的界面上,有一个配置的选项,可以对摄像头的分辨率等参数进行设置处理。

同时在PictureEdit控件上,也可以开启摄像头采集功能,只需要在控件属性里设置一下即可:

运行界面得到效果如下所示。

这个采集图片的菜单项文字没有汉化,因此有点怪异,我们也可以通过使用其内置的对话框(
TakePictureDialog
)进行图片采集操作。

具体代码如下所示:

private void btnInternal_Click(objectsender, EventArgs e)
{
TakePictureDialog d
= newTakePictureDialog();if (d.ShowDialog() ==System.Windows.Forms.DialogResult.OK)
{
this.pictureEdit1.Image =d.Image;
}
}

调用得到的对话框是内置的,界面也是无法修改调整,包括文字内容。

2、自定义采集对话框

为了更好的实现对头像的采集操作,我们可以仿照这个对话框模块,做一个自定义的窗体,实现摄像头图像的采集操作,如下所示。

同时我们在对话框窗体里面设置一个Public的图像对象属性,如下所示

        /// <summary>
        ///采集图片/// </summary>
        public Image CameraImage { get; set; }

这样我们就方便设置和提取图像信息了。

捕获图像的代码就是从摄像控件里面获取一个快照就可以了,如下所示。

        private void btnCapture_Click(objectsender, EventArgs e)
{
this.CameraImage = this.cameraControl1.TakeSnapshot();this.pictureEdit1.Image = this.CameraImage;
}

然后在窗体退出的时候,记得释放摄像头的资源,否则第二次就提示占用,无法使用了。

        private void FrmCamera_FormClosing(objectsender, FormClosingEventArgs e)
{
this.cameraControl1.Dispose();
}

整个对话框的完整代码如下所示。

    public partial classFrmCamera : Form
{
/// <summary> ///采集图片/// </summary> public Image CameraImage { get; set; }publicFrmCamera()
{
InitializeComponent();
}
private void btnOK_Click(objectsender, EventArgs e)
{
this.DialogResult =System.Windows.Forms.DialogResult.OK;
}
private void btnCapture_Click(objectsender, EventArgs e)
{
this.CameraImage = this.cameraControl1.TakeSnapshot();this.pictureEdit1.Image = this.CameraImage;
}
private void FrmCamera_FormClosing(objectsender, FormClosingEventArgs e)
{
this.cameraControl1.Dispose();
}
}

最后运行可以得到界面如下所示。

这种处理方式比较好,我在该控件出来之前,在基础界面类库里面,使用肖像控件来处理摄像头图像采集的,如在我博客介绍《
Winform开发框架之肖像显示保存控件的实现
》所示。

例如在会员管理系统里面,就是利用肖像管理控件,通过之前的摄像头公用类库实现的图形采集操作的。

这里其实是利用一个摄像头类库来实现的,不过现在既然DevExpress本身就提供控件支持,那么我们也可以直接利用它了,这样更加方便,更少代码。

最近准备下PostgreSQL数据库开发的相关知识,本文把总结的PPT内容通过博客记录分享,本随笔的主要内容是介绍PostgreSQL数据库的基础信息,以及如何在我们的开发框架中使用PostgreSQL数据库,希望大家多多提意见。

1、PostgreSQL数据库介绍

PostgreSQL是以加州大学伯克利分校计算机系开发的 POSTGRES,现在已经更名为PostgreSQL。它具有很多不错的特点:

开源
:PostgreSQL 是一个自由的对象-关系数据库服务器(数据库管理系统),它在灵活的 BSD-风格许可证下发行。

兼容性好
:PostgreSQL 的特性覆盖了 SQL-2/SQL-92 和 SQL-3/SQL-99。

可靠性高
:PostgreSQL标榜自己是世界上最先进的开源数据库。可靠性是PostgreSQL的最高优先级。它以坚如磐石的品质和良好的工程化而闻名,支持高事务、任务关键型应用。

广泛采用
:自从MySQL被Oracle收购以后,PostgreSQL逐渐成为开源关系型数据库的首选,在功能上是全面超越MySQL的一个开源数据库。

良好支持
:PostgreSQL对接口的支持也是非常丰富的,几乎支持所有类型的数据库客户端接;最丰富的数据类型的支持,其中有些数据类型可以说连商 业数据库都不具备,比如IP类型和几何类型等;


2、安装数据库及管理工具

数据库安装
PostgreSQL数据库(https://www.postgresql.org/download/windows/)


数据库管理工具
Navicat for PostgreSQL (如V11.1)


数据库建模工具
PowerDesigner (如V16.5)

数据库操作:

1)安装PostgreSQL数据库
2)安装Navicat for PostgreSQL管理数据库工具


3)安装PowerDesigner建模工具

4)在PowerDesigner创建一个简单的表,获取表SQL,然后在Navicat 中执行脚本创建表,插入数据等。


3、PostgreSQL数据库语法

常规处理SQL,和其他数据库相同,如创建、删除表等常规操作。下面从网络上摘录一些关于PostgreSQL的常见操作。

1)表的定义:

1. 创建表:

CREATE TABLEproducts (
product_no
integer,
name
text,
price numeric
);

2. 删除表:

DROP TABLE products;

3. 创建带有缺省值的表:

CREATE TABLEproducts (
product_no
integer,
name
text,
price numeric
DEFAULT 9.99 --DEFAULT是关键字,其后的数值9.99是字段price的默认值。 );
CREATE TABLEproducts (
product_no SERIAL,
--SERIAL类型的字段表示该字段为自增字段,完全等同于Oracle中的Sequence。 name text,
price numeric
DEFAULT 9.99);

4. 约束:
检查约束是表中最为常见的约束类型,它允许你声明在某个字段里的数值必须满足一个布尔表达式。不仅如此,我们也可以声明表级别的检查约束。

CREATE TABLEproducts (
product_no
integer,
name
text,--price字段的值必须大于0,否则在插入或修改该字段值是,将引发违规错误。还需要说明的是,该检查约束--是匿名约束,即在表定义时没有显示命名该约束,这样PostgreSQL将会根据当前的表名、字段名和约束类型,--为该约束自动命名,如:products_price_check。 price numeric CHECK (price > 0)
);
CREATE TABLEproducts (
product_no
integer,
name
text,--该字段的检查约束被显式命名为positive_price。这样做的好处在于今后维护该约束时,可以根据该名进行直接操作。 price numeric CONSTRAINT positive_price CHECK (price > 0)
);

下面的约束是非空约束,即约束的字段不能插入空值,或者是将已有数据更新为空值。

CREATE TABLEproducts (
product_no
integer NOT NULL,
name
text NOT NULL,
price numeric
);


5. 主键和外键:
从技术上来讲,主键约束只是唯一约束和非空约束的组合。

CREATE TABLEproducts (
product_no
integer PRIMARY KEY, --字段product_no被定义为该表的唯一主键。 name text,
price numeric
);


和唯一性约束一样,主键可以同时作用于多个字段,形成联合主键:

CREATE TABLEexample (
a
integer,
b
integer,
c
integer,PRIMARY KEY(b, c)
);


外键约束声明一个字段(或者一组字段)的数值必须匹配另外一个表中某些行出现的数值。 我们把这个行为称做两个相关表之间的参考完整性。

CREATE TABLEorders (
order_id
integer PRIMARY KEY, --该表也可以有自己的主键。--该表的product_no字段为上面products表主键(product_no)的外键。 product_no integer REFERENCESproducts(product_no),
quantity
integer);

当多个表之间存在了主外键的参考性约束关系时,如果想删除被引用表(主键表)中的某行记录,由于该行记录的主键字段值可能正在被其引用表(外键表)中某条记录所关联,所以删除操作将会失败。如果想完成此操作,一个显而易见的方法是先删除引用表中和该记录关联的行,之后再删除被引用表中的该行记录。然而需要说明的是,PostgreSQL为我们提供了更为方便的方式完成此类操作。

CREATE TABLEproducts (
product_no
integer PRIMARY KEY,
name
text,
price numeric
);
CREATE TABLEorders (
order_id
integer PRIMARY KEY,
shipping_address
text);
 CREATE TABLEorder_items (
product_no
integer REFERENCES products ON DELETE RESTRICT, --限制选项 order_id integer REFERENCES orders ON DELETE CASCADE, --级联删除选项 quantity integer,PRIMARY KEY(product_no, order_id)
);

限制和级联删除是两种最常见的选项。RESTRICT 禁止删除被引用的行。 NO ACTION 的意思是如果在检查约束的时候,如果还存在任何引用行,则抛出错误; 如果你不声明任何东西,那么它就是缺省的行为。(这两个选择的实际区别是,NO ACTION 允许约束检查推迟到事务的晚些时候,而 RESTRICT 不行。) CASCADE声明在删除一个被引用的行的时候,引用它的行也会被自动删除掉。 在外键字段上的动作还有两个选项: SET NULL 和 SET DEFAULT。 这样会导致在被引用行删除的时候,引用它们的字段分别设置为空或者缺省值。 请注意这些选项并不能让你逃脱被观察和约束的境地。比如,如果一个动作声明 SET DEFAULT,但是缺省值并不能满足外键,那么动作就会失败。类似ON DELETE,还有ON UPDATE 选项,它是在被引用字段修改(更新)的时候调用的。可用的动作是一样的。

2)表的修改:
1. 增加字段:

ALTER TABLE products ADD COLUMN description text;

新增的字段对于表中已经存在的行而言最初将先填充所给出的缺省值(如果你没有声明DEFAULT子句,那么缺省是空值)。

在新增字段时,可以同时给该字段指定约束。

ALTER TABLE products ADD COLUMN description text CHECK(description <> '');


2. 删除字段:

ALTER TABLE products DROP COLUMN description;

如果该表为被引用表,该字段为被引用字段,那么上面的删除操作将会失败。如果要想在删除被引用字段的同时级联的删除其所有引用字段,可以采用下面的语法形式。

ALTER TABLE products DROP COLUMN description CASCADE;


3. 增加约束:

ALTER TABLE products ADD CHECK(name <> ''); --增加一个表级约束
ALTER TABLE products ADD CONSTRAINT same_name UNIQUE(product_no);--增加命名的唯一性约束。
ALTER TABLE products ADD FOREIGN KEY(pdt_grp_id) REFERENCES pdt_grps; --增加外键约束。
ALTER TABLE products ALTER COLUMN product_no SET NOT NULL; --增加一个非空约束。

4. 删除约束:

ALTER TABLE products DROP CONSTRAINT some_name;

对于显示命名的约束,可以根据其名称直接删除,对于隐式自动命名的约束,可以通过psql的\d tablename来获取该约束的名字。和删除字段一样,如果你想删除有着被依赖关系的约束,你需要用CASCADE。一个例子是某个外键约束依赖被引用字段上的唯一约束或者主键约束。

3)权限:
只有表的所有者才能修改或者删除表的权限。要赋予一个权限,我们使用GRANT命令,要撤销一个权限,使用REVOKE命令。
需要指出的是,PUBLIC是特殊"用户"可以用于将权限赋予系统中的每一个用户。在声明权限的位置写ALL则将所有的与该对象类型相关的权限都赋予出去。

GRANT UPDATE ON table_name TO user; --将表的更新权限赋予指定的user。
GRANT SELECT ON table_name TO GROUP group; --将表的select权限赋予指定的组。
REVOKE ALL ON table_name FROM PUBLIC; --将表的所有权限从Public撤销。

最初,只有对象所有者(或者超级用户)可以赋予或者撤销对象的权限。但是,我们可以赋予一个"with grant option"权限,这样就给接受权限的人以授予该权限给其它人的权限。如果授予选项后来被撤销,那么所有那些从这个接受者接受了权限的用户(直接或者通过级连的授权)都将失去该权限。

4、数据库语法差异部分

1)特殊字段对应关系(部分)

2)分页处理
MySQL分页常见写法

select * from persons  limit 0,10;

起点位置为0,查询10条记录。

兼容MySQL与postgreSQL的写法

select * from persons limit 10 offset 0

从起点0开始查询,返回10条记录

3)其他类型
Guid生成
(SQLServer 为newid() 函数)

PostgreSQL从9.1版本开始,执行下面可以创建guid的函数

CREATE EXTENSION IF NOT EXISTS "uuid-ossp";select uuid_generate_v4()

SQL限定符
Sqlserver为[],如Select [Name] from [User]
PostgreSQL为“”,如 Select “Name” from User


自增长标识
SQLserver为 identity(1,1)
PostgreSQL使用SERIAL代替
SERIAL 对象的是int4类型(默认),bigserial类型对应int8类型
一个serial类型创建的序列在其所属字段被删除时,该序列也将被自动删除

函数
string || string
'Post' || 'greSQL‘
lower(string)
lower('TOM')
upper(string)
upper('tom')
substring(string [from int] [for int])
substring('Thomas' from 2 for 3)
to_char(timestamp, text)
to_char(current_timestamp, 'HH12:MI:SS')
to_timestamp(text, text)
to_timestamp('2016-10-29 12:27:05', 'YYYY-MM-DD HH24:MI:SS')

...

current_date 今天的日期
current_time 现在的时间
current_timestamp 现在的日期和时间
Localtime 今日的时间
Localtimestamp日期和时间
now() 当前的日期和时间(等效于 current_timestamp)

序列操作函数
Nextval、currval、lastval、setval
其他函数
NULLIF :当且仅当value1和value2相等时,NULLIF才返回NULL。否则它返回value1。
GREATEST和LEAST :GREATEST和LEAST函数从一个任意的数字表达式列表里选取最大或者最小的数值。

系统信息函数
current_database()当前数据库的名字
current_schema()当前模式的名字
current_user目前执行环境下的用户名
version() PostgreSQL版本信息
……


5、在开发框架中使用PostgreSQL数据库

这个属于多数据库支持的其中一种,我在之前的随笔《
在数据库访问项目中使用微软企业库Enterprise Library,实现多种数据库的支持
》 有简单对多数据库的使用做了介绍,不过如果是基于多数据实现层的处理,那么则需要以框架的分层方式来实现,通过代码生成工具Databasse2Sharp的快速生成,整个开发工作变得更加高效和快速,而且各个分层的目录统一易懂。

我们以PostgreSQL数据库支持为例,在开发框架上支持这种开发,则具有以下特点:

1)框架底层采用了微软企业库Enterprise Library作为底层数据库访问模块
2)多数据库支持,统一采用企业库的数据库访问对象,操作一致
3)PostgreSQL开发和SQLServer开发过程相似
4)配置文件修改ComponentDbType为npgsql即可配置为PostgreSQL
5)数据库指向是在BaseBLL对象构建的时候实现切换

上面就是整个框架数据访问层的整体设计和继承关系,我们在实际开发的时候,我们可以利用代码生成工具Database2Sharp进行快速开发,可以实现生成框架底层和WInfrom界面或者Web界面等内容,从而可以实现快速整合即可。

我们在开发实现PostgreSQL数据层对象的时候,可以把其他数据库层(如SQLServer的),然后修改对应的数据访问层基类和命名空间即可构造成PostgreSQL层了。

在我们开发完软件后,除了极个别案例我们把整个目录复制给客户用外,我们一般都需要做成安装包,方便整个软件的部署操作,以安装包的部署操作可能简单的是复制文件,也可能包括一些注册表、数据库等额外的操作,不过安装包部署肯定是能够给客户提供专业、统一的软件安装体验,同时封装了很多细节方面的处理。在我们日常的基于.NET的开发中,VS2010之前我们还可以使用内置的安装包制作工具,自从VS2012、VS2013以后,微软把这个去掉,集成使用了InstallShield进行安装包的制作了,我自己在这方面也写了两篇随笔《
基于DevExpress的Winform程序安装包的制作
》、《
基于InstallShield2013LimitedEdition的安装包制作
》,不过基于InstallShield的制作虽然可以完成安装包的打包操作,不过也不见得是比较方便的打包工具,本篇介绍的Setup Factory是一个非常高效,功能强大的安装包制作工具,在独立于VS之外,我们可以用它作为我们常规.NET开发的安装包制作,简单易用。

1、Setup Factory介绍

Setup Factory 是一个强大的安装程序制作工具。提供了安装制作向导界面,即使你对安装制作不了解,也可以生成专业性质的安装程序。Setup Factory 的特性包括:工程向导、自定义对话框、主题/皮肤样式、运行时间模块、最小化支持、MD5编码序列号、250个功能函数的脚本编辑器、授权支持和其他特性等。

目前使用的版本是Setup Factory 9.5,不过各个版本之间差异并不大,这个软件在网上也很容易得到(即使是特别版本的,呵呵),因此较InstallShield更为方便获取到,在简单的对这款安装包制作工具的了解后,基本上常规的功能都非常方便设置处理,确实是比较易用的。软件的界面效果如下所示。

从软件的主要功能来讲,它的安装包制作,主要就是左边的任务栏的各个处理操作了,包括内容有:文件Files、设置Settings、屏幕Screens、动作Action、资源Resources、卸载UnInstall等操作。

2、软件安装包的制作

我们创建一个安装包,输入相关的公司、软件名称等,如下所示。

一步步后,我们需要指定指定具体的位置,以便加入所需要的文件,如下所示。

然后选择安装包的界面语言包,如下所示。

进一步的操作,就可以选择环境的安装包,例如.NET4,如果选择这个依赖环境,那么在安装的过程中会自动安装,好像说需要在SetUpFactory软件所在的目录中新建一下目录:
Dependencies\dotnet4 。
并且将 dotNetFx40_Full_x86_x64.exe放在其中。

接着需要设置一些安装包的操作,如是否包含卸载操作等等,如下界面所示。

最后,程序自动加入指定目录的问价,在主体界面中显示对应的文件,如下安装包制作视图所示,就是制作一个客户关系管理软件的安装包界面视图,包含所需要安装的文件、文件文档、程序依赖文件等。

在返回到主界面的安装包视图后,我们就是按照左边的任务工具栏的顺序,一步步的对安装包的参数进行设置即可。

包含的内容有:文件Files、设置Settings、屏幕Screens、动作Action、资源Resources、卸载UnInstall等操作。我们在加入文件后,对执行文件的相关参数进行设置处理,如下所示。

对执行文件的属性进行设置,根据情况设置相关的参数信息,如下界面所示。

然后接着对设置信息进行处理,如指定安装包软件的名称、公司信息、安装版权信息、安装路径等,如下界面所示。

安装包的屏幕显示,我们可以修改其中的图片,以及相关的提示信息、按钮信息等内容,如下界面所示。

在弹出的界面里面,我们可以通过Project内容选择符合安装包的制作主题,在右下角里面,我们还可以单击编辑按钮,对样式图片进行修改,选择符合自己项目的背景图片。

其他处理如动作Action、资源Resources等,我们根据情况进行设置即可,一般如果没有特殊,则不需要进行处理。

卸载的操作,我们可以修改其中的提示名称,将其修改为中文的提示信息,如下所示。

最后可以进行编译了,指定生成的目录和文件名称,编译就可以获得一个独立的安装包的。

编译过程就是把所需的文件一步步加入到一个安装包文件里面,如下是进度提示所示。

下面介绍的界面效果就是我完成后的安装包界面效果,包括了背景图片的修改,卸载信息的设置、安装包文件的信息等等,具体效果也可以下载我的客户关系管理软件进行了解。

http://www.iqidi.com/crm.htm

安装部署后,软件的快捷键在桌面上存在,并且可以看到【打开文件位置】的操作也可以了,这个在之前VS里面的安装包是没有的,呵呵,小细节。

安装文件是一个独立的文本文件,安装Setup Factory工具后,直接使用,也可以使用其他文本编辑工具维护和查看。

2、关于DevExpress相关DLL的依赖

在我们完成添加编译完成的系统所需相关DLL外,如果我们的UI依赖DevExpress,那么也需要引入对应的DevExpress相关DLL文件,我们可以一般可以拷贝到发布目录中,然后引入响应文件即可。

另外DevExpress还需要包含相关的中文化资源,可以通过包含文件夹所有文件的方式包含进来,如下所示。

完成后编译生成安装的执行文件即可。

以上就是我对一个完整的客户关系管理软件的安装包,在Setup Factory工具上的制作过程,基本上安装包制作起来还是比较方便快捷的,而且最后也就是一个文本文件的信息,独立,比较好管理。

对比InstallShield的笨重和麻烦,这个软件独立维护安装包也是非常方便的一件事情。

在我很早的WInform随笔《
WinForm界面开发之"SplashScreen控件"
》有介绍如何使用闪屏的处理操作,不过那种是普通WInform和DevExpress都适用的方案,如果是基于DevExpress,那么可以使用更简便的方式,就是本文介绍的在DevExpress程序中使用SplashScreenManager控件实现启动闪屏和等待信息窗口,这个SplashScreenManager很好的封装了日常WInform程序中用到的启动闪屏窗口和在耗时操作中进行等待提示的信息窗口,合理使用可以增加程序界面的友好交换。

1、SplashScreenManager控件的使用

这个控件一般人很少注意到,毕竟不是很常用,我们可以通过在控件工具箱里面进行搜索,找到后拖动到WInform窗口即可,如下界面所示。

然后在SplashScreenMananger控件的右上角上单击三角符号,利用连接按钮添加两个窗口,一个是启动界面的闪屏窗口,一个是等待界面窗口。

最后得到两个新建的界面,稍作调整就可以使用在程序中了。

2、SplashScreenManager控件的调用

上面我们通过控件手工添加的方式增加了两个界面窗体,如果需要在程序中使用,那么需要进行一定的代码调用处理。

例如我们在程序启动的时候,程序入口的代码修改如下。

其中启动闪屏窗口的代码就是

 //显示闪屏窗体
SplashScreenManager.ShowForm(typeof(FrmSplashScreen));
Thread.Sleep(
3000);

在主程序窗体中,我们加载完毕界面后,我们需要手工关闭闪屏窗体的显示,代码如下所示。

而在界面中,如果我们需要显示等待窗口,如在耗时的数据获取和更新操作上,我们可以提示用户等待一下,那么这个时候就应该做等待信息窗口的显示了,如下界面效果所示。

为了实现上面的操作,我们可以对这个窗口的调用做一些简单的初始化和封装处理,如下代码所示。

privateSplashScreenManager _loadForm;/// <summary>
///等待窗体管理对象/// </summary>
protectedSplashScreenManager LoadForm
{
get{if(_loadForm == null)
{
this._loadForm = new SplashScreenManager(this, typeof(FrmWaitForm), true, true);this._loadForm.ClosingDelay = 0;
}
return_loadForm;
}
}
/// <summary> ///显示等待窗体/// </summary> public voidShowMessage()
{
bool flag = !this.LoadForm.IsSplashFormVisible;if(flag)
{
this.LoadForm.ShowWaitForm();
}
}
/// <summary> ///关闭等待窗体/// </summary> public voidHideMessage()
{
bool isSplashFormVisible = this.LoadForm.IsSplashFormVisible;if(isSplashFormVisible)
{
this.LoadForm.CloseWaitForm();
}
}

最后在数据更新的时候,我们调用上面的函数

这样就实现了两种界面效果的处理了:启动闪屏显示、数据操作的等待信息,这两个控件还可以在中间过程中调用更多的事件函数处理,如SendCommand等,从而实现更进一步的信息显示。

在很多业务系统里面,越来越多涉及到条形码、二维码的应用了,不管在Web界面还是WInform界面都需要处理很多物料相关的操作,甚至很多企业为了减少录入错误操作,为每个设备进行条形码、二维码的标签,直接在流程中进行扫描处理,仅仅在界面勾选一些处理选项即可,极大提高工作效率,降低出错的几率。本篇随笔介绍如何在基于WInform的DevExpress程序中对条形码、二维码的处理,包括界面展示,报表打印等常规的处理。

1、DevExpress的条形码操作及报表打印

在15.1以上的DevEpxress版本中,增加了BarCodeControl控件,该控件包含了条形码、二维码等的展示和处理,支持很多种编码。

在工具箱里面,我们可以找到这个控件,添加到界面后,设置属性就可以显示如下的效果。

对于条形码的控件显示,需要设置对应的编码,以及显示内容等信息。

设置正确的格式显示,才能显示出条形码的内容,否则会处理得不到显示的内容。

为了方便界面的处理,动态增加对应的条形码控件展示,我们独立出一个条形码控件,如下所示。

为了方便展示,我们在界面上添加一个FlowLayoutPanel流布局控件,用来动态添加条码内容的容器,界面代码如下所示。

运行Demo程序,可以得到下面的测试界面效果。

对于条形码的打印操作,我们可以基于XtraReport的报表模板对内容进行展示的,因此需要设计一个报表的界面,如下所示是设计好的报表界面。

这个报表界面就是添加一个空白报表,然后加入对应的标签和二维码报表控件,和操作WInform界面一样,排版后就可以了。

然后增加对应的数据源信息,以及设定绑定控件的字段名称即可。

最后绑定报表数据源,并打印报表的界面代码如下所示。

得到界面效果如下所示。

2、二维码控件的处理

上面介绍的是条形码操作,其中BarCodeControl很有迷惑性,其实它也可以作为二维码的空间处理的,这是后来才发现,哈哈。

其实Github上也有很多开源的二维码控件,可以生成图片进行展示的。

如下界面所示,我们可以看到,这个二维码也是即看即所得的效果,设置界面后,马上可以看到效果的。

使用内置控件,我们在后台代码赋值的时候,只需要设置它的内容即可,如下所示。

//使用内置控件
var url = this.txtContent.Text.Trim();this.barCodeControl1.Text = url;

如果使用第三方二维码控件,如ThoughtWorks.QRCode(https://github.com/aaronogan/QR.NET),则创建的代码如下所示。

最后得到两组界面的对比,如下所示。