winform打印机控制程序记录

news2024/11/26 13:51:36

1.Invoke 跨线程访问

有些回调函数不能直接访问控件的属性,这时就需要用到这个。
用法:

Invoke(new Action(() =>
	{
		//正常代码
		receiveCount++;
		tb_recvCount.Text = Convert.ToString(receiveCount);
	}));
                

2.控制打印机打印

2.1.绘制表格

准备一个 panel ,在里面放入 label ,将 label 的宽度设置为 1 或者 2 ,背景色改为黑色,就能得到一根直线,再放入几个 label 作为文本容器。
在这里插入图片描述

2.2.填充数据

使用 label ,给 label.Text 赋值即可。

2.3.开始打印

在页面中添加如下两个控件。
在这里插入图片描述
将 printPreviewDialog 的 Document 属性设置为 刚刚添加的 printDocument 。
在这里插入图片描述
在 printDocument 的 PrintPage 事件中绘制打印的内容。
在这里插入图片描述

	private void printDocument1_PrintPage(object sender, PrintPageEventArgs e)
        {
            //打印内容 为 局部的 this.panel1
            Bitmap _NewBitmap = new Bitmap(panel_label.Width, panel_label.Height);
            panel_label.DrawToBitmap(_NewBitmap, new Rectangle(0, 0, _NewBitmap.Width, _NewBitmap.Height));
            e.Graphics.DrawImage(_NewBitmap, 0, 0, _NewBitmap.Width, _NewBitmap.Height);
            Graphics g = e.Graphics;
            g.SmoothingMode = SmoothingMode.HighQuality;
            Pen pen01 = new Pen(Color.Black, 0.5f);
            //g.DrawLine(pen01, 5, 93, 233, 93);
        } 

3.威纶通触摸屏使用MQTT发送打印指令

  1. 触摸屏的MQTT发送的数据为 JSON 格式,带有 “d” 层和时间戳,值为数组格式,访问时应访问: json["d"]["SN"][0]
    在这里插入图片描述
  2. 触摸屏发送打印指令,使用位状态切换开关,操作模式为“设为ON”。这样点击打印按钮之后,直到 MQTT 发布完成, LB-20 都为 true ,如果设置为 “切换开关”,MQTT发送的时候 LB-20 很可能为 false ,这会有什么影响呢,请继续看。
    在这里插入图片描述
  3. 以下是发送的 MQTT 主题,发送模式为触发式,触发地址为第 2 点提到的 LB-20 。
    在这里插入图片描述
  4. 发送的信息有 LB-20 ,这就是第 2 点提到的会受到影响的地方,打印机控制程序通过判断 Print 的值是否为 true 来判断是否打印这条讯息,如果点击打印之后,发送过去的 Print 为 false 。打印机就不会打印 。
    在这里插入图片描述

4.打印机控制程序接收打印信息

4.1.使用 MQTT 客户端订阅讯息

获得触摸屏发送到 MQTT 服务器的讯息,解析讯息为 JSON 格式。

4.2.判断 Print 是否为 true

为 true 则将数据填充到表格,切换默认打印机,开始打印。
切换默认打印机的代码如下:

    class SetPrinter
    {
        [DllImport("winspool.drv")]
        public static extern bool SetDefaultPrinter(String Name); //调用win api将指定名称的打印机设置为默认打印机
    }

5.打印机配置

5.1. 配置特定机台对应特定的打印机

如下图,以主题来区分机台。
在这里插入图片描述

5.2. 获取打印机列表

在这里插入图片描述

        private void mbtn_getPrinterList_Click(object sender, EventArgs e)//获取打印机列表
        {
            cbb_printerList.Items.Clear();
            int i;
            using (PrintDocument pd = new PrintDocument())
            {
                for (i = 0; i < PrinterSettings.InstalledPrinters.Count; i++)  //开始遍历
                {
                    printers = PrinterSettings.InstalledPrinters[i];  //取得名称
                    cbb_printerList.Items.Add(printers);               //加入ComboBox
                    //if (pd.PrinterSettings.IsDefaultPrinter)                     //判断是否为默认打印机
                    //{
                    //    textBox_actPrinter.Text = pd.PrinterSettings.PrinterName;
                    //    cmbPrinterList.Text = pd.PrinterSettings.PrinterName;    //显示默认打印机名称
                    //}
                }
                if (cbb_printerList.Items != null)
                {
                    cbb_printerList.SelectedItem = cbb_printerList.Items[0];
                }
            }
        }

5.3.将配置写入配置文件。使用 ConfigHelper 类。

public class ConfigHelper
    {
        [DllImport("kernel32")]
        private static extern long GetPrivateProfileString(string section, string key, string def, StringBuilder retval, int size, string filepath);
        [DllImport("kernel32")]
        private static extern long WritePrivateProfileString(string section, string key, string val, string filepath);
        /// <summary>
        /// 读配置文件
        /// </summary>
        /// <param name="section">选择读取的部分</param>
        /// <param name="key">键</param>
        /// <param name="def">默认值</param>
        /// <param name="size"></param>
        /// <param name="filepath"></param>
        /// <returns></returns>
        public static String ReadIni(string section, string key, string def, int size, string filepath)
        {
            StringBuilder sb = new StringBuilder();
            GetPrivateProfileString(section, key, def, sb, size, filepath);
            return sb.ToString();
        }
        /// <summary>
        /// 写入数据到配置文件
        /// </summary>
        /// <param name="section"></param>
        /// <param name="key"></param>
        /// <param name="val"></param>
        /// <param name="filepath"></param>
        /// <returns></returns>
        public static long WriteIni(string section, string key, string val, string filepath)
        {
            return WritePrivateProfileString(section, key, val, filepath);
        }
        // 删除ini文件下所有段落
        public void ClearAllSection(string filepath)
        {
            WriteIni(null, null, null, filepath);
        }
        //删除ini文件下personal段落下的所有键
        public void ClearSection(string Section, string filepath)
        {
            WriteIni(Section, null, null, filepath);
        }
    }

用法:

		private void writeConfig()//配置写入
        {
            string path = Application.StartupPath + "/config.ini";
            ConfigHelper.WriteIni("part1", "Machine1_printer", tb_printer1.Text, path);
         }

效果:
在这里插入图片描述

5.4.读取配置文件到JSON,同时将数据写入控件

   private void readConfig(JObject configJson)//配置读取
   {
       string path = Application.StartupPath + "/config.ini";
       
       for(int i = 1; i <= 50; i++)
       {
           string key1=string.Empty, value1=string.Empty;
           //读取主题名
           string tb_topic = $"tb_topic{i}";
           Control[] tb_topics = Controls.Find(tb_topic, true);
           foreach (var tbt in tb_topics)
           {
               if(tbt.Name == tb_topic)
               {
                   tbt.Text = ConfigHelper.ReadIni("part2", $"Machine{i}_topic", "空数据", 1024, path);
                   key1 = tbt.Text;
               }
           }
           //读取打印机名
           string tb_printer = $"tb_printer{i}";
           Control[] tb_printers = Controls.Find(tb_printer, true);
           foreach (var tbp in tb_printers)
           {
               if (tbp.Name == tb_printer)
               {
                   tbp.Text = ConfigHelper.ReadIni("part1", $"Machine{i}_printer", "空数据", 1024, path);
                   value1 = tbp.Text;
               }
           }
           if(configJson.ContainsKey(key1) == false)
           {
               configJson.Add(key1, value1);
           }
       }
   }

6.打印记录

6.1.写入 .csv 文件

        public static void writeRecord(string line)
        {
            string path = Application.StartupPath + $"/PrintRecord/PrintRecord-{DateTime.Now.ToString("yyyy-MM")}.csv";
            //导出到文件的具体位置
            FileInfo fi = new FileInfo(path);
            if (!fi.Directory.Exists)	//如果文件不存在则创建文件
            {
                fi.Directory.Create();
            }
            FileStream fs = new FileStream(path, FileMode.Append, FileAccess.Write);
            StreamWriter sw = new StreamWriter(fs);
            sw.WriteLine(line);	//按行写入文件中
            sw.Close();
            fs.Close();
        }

6.2.从 .csv 文件读取

  1. 准备一个空 DataGridView ,不要添加列。
  2. 使用 LoadCSV 方法读取 .csv 文件,得到一个 DataTable 。
        public static DataTable LoadCSV(string data,string tableHead)
        {
            DataTable resultTable = new DataTable();//创建空DataTable

            //在下面写解析代码
            data = data.Replace("\r", string.Empty);//清除一些必须清理的东西
            string[] lines = data.Split(new char[1] { '\n' }, StringSplitOptions.RemoveEmptyEntries);//分离每一行,StringSplitOptions.RemoveEmptyEntries:返回值不包含空字符串
            string[] dataHeads = tableHead.Split(',');//获取表头
            foreach (string dataHead in dataHeads)
            {
                resultTable.Columns.Add(new DataColumn { ColumnName = dataHead });//把文件头中的元素加入dataTable的列中
            }
            foreach (string line in lines)//对每一行数据进行操作
            {
                if (string.IsNullOrEmpty(line)) continue;
                string[] items = line.Split(',');//以分号分离每一行数据

                这一块用于读取文件头
                //if (line == lines[0])//如果在读取文件头
                //{
                //    dataHead = new string[items.Length];
                //    dataHead = items;//将文件头数据赋值给dataHead
                //    foreach (string item in items)
                //    {
                //        resultTable.Columns.Add(new DataColumn { ColumnName = item });//把文件头中的元素加入dataTable的列中
                //    }
                //}
                //else//这一块用于读取数据并将数据写入表格
                {
                    DataRow row = resultTable.NewRow();//添加行进入dataTable
                    for (int i = 0; i < items.Length; i++)//向行中添加数据(除类名)
                    {
                        row[dataHeads[i]] = items[i];//dataHead[i]为文件头元素,item[i]为文件头元素对应值
                    }
                    resultTable.Rows.Add(row);//添加行进入dataTable
                }
            }


            return resultTable;
        }
  1. 将 DataGridView.DataSource 设置为这个 DataTable
string tableHead = "日期,时间,班次,机台编号,开机员";//设置表头,以‘,’分隔
string path = Application.StartupPath + "/PrintRecord/"+ cbb_printRecordList.Text;
Encoding encoding = Encoding.GetEncoding("UTF-8");//编码
string csv = File.ReadAllText(path, encoding);
dGV_printRecord.DataSource = UserClass1.LoadCSV(csv, tableHead);

效果:

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/746373.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Redis---缓存双写一致性

目录 一、什么是缓存双写一致性呢&#xff1f; 1.1 双检加锁机制 二、数据库和缓存一致性的更新策略 2.1、先更新数据库&#xff0c;后更新缓存 2.2 、先更新缓存&#xff0c;后更新数据库 2.3、先删除缓存&#xff0c;在更新数据库 延时双删的策略&#xff1a; 2.4.先更新数…

手把手一起完成Python上位机与下位机USB通信

前言 最近在使用Python设计上位机&#xff0c;下位机是ZYNQ7000&#xff0c;两者通过USB进行数据传输。该文章是USB通信过程的踩坑记录 一、安装所需库 首先&#xff0c;安装pyusb和libusb两个库&#xff0c;命令如下&#xff1a; pip install pyusbpip install libusb如图…

CUDA笔记2

1.硬件理解 1.1对应 1.2 不一定是同时执行 例如只有13个sm,每个sm有128个core,而我们创建了1百万个threads,就要同步执行 因此&#xff0c;我们倾向于在block的x维设置为32的倍数,防止浪费warp warp id打印 #include <stdio.h> #include <stdlib.h>#include &qu…

Acwing 849. Dijkstra求最短路 I

Acwing 849. Dijkstra求最短路 I 链接:849. Dijkstra求最短路 I - AcWing题库 /*题解:dijkstra算法模板对于单源最短路径dijkstra1.每次找到当前距离源最近的节点 作为确定距离的点2.通过这个点看能否让其他的节点来松弛其他点到源的距离重复12操作*/ #include<algorithm&g…

完美解决win10系统cmd命令无法使用ssh

最近我在远程访问服务器的时候&#xff0c;在winR运行cmd的时候&#xff0c;输入ssh来获得本地和服务器映射&#xff0c;无法实现。提示&#xff1a;’SSH’ 不是内部或外部命令&#xff0c;也不是可运行的程序 或批处理文件。 下面的方法可以完美解决这个问题&#xff1a; 目…

四大运营商的优缺点,你的选择是对的吗?

随着2022年中国广电获得基础运营商服务牌照&#xff0c;中国从三大运营商变成了四大运营商&#xff1a;中国移动&#xff0c;中国联通&#xff0c;中国电信&#xff0c;中国广电。这四大运营商到底都有什么优缺点呢&#xff1f;大家一直在用的运营商手机卡&#xff0c;大家了解…

REE刷TLB时会把安全的TLB刷掉吗

思考: REE刷TLB时会把安全的TLB刷掉吗? TEE刷TLB时能否刷安全的TLB?例如页表管理着的共享内存,它的翻译缓存到了TLB. 首先,纠正一下用词,这里的"刷",来自某些操作系统中的"flush",在TLB底层的操作指令中,是没有flush或clean的,关于TLB的操作指令…

基于linux下的高并发服务器开发(第一章)- 静态库的使用1.5

1、创建lesson05文件夹&#xff0c;mkdir lesson05,然后创建子文件夹calc和library 在calc文件夹下有文件add.c&#xff0c;div.c&#xff0c;mult.c &#xff0c; sub.c &#xff0c;head.h&#xff0c;main.c在library文件夹下有文件夹include&#xff0c;lib&#xff0c;sr…

目标跟踪基础:数据关联算法

本文来自公众号“AI大道理” —————— 数据关联是多目标跟踪任务中的关键步骤&#xff0c;其目的主要是为了进行帧与帧之间的多个目标的匹配。 1、数据关联 数据关联其实就是一个沿着时间轴&#xff0c;将来自同一个物体的不同时刻的信号串联起来的过程。 数据关联通常在…

探索基于300W-LP的3D人脸关键点检测

目录 前言一、&#xff13;D 关键点可视化二、使用步骤1.300W-LP转为YOLO数据格式2.修改数据入口3.开始训练 总结 前言 300WLP数据集提供来丰富的人脸线索&#xff0c;包括&#xff12;D或&#xff13;D的关键点信息&#xff0c;Head Angle和&#xff13;DMM的参数等&#xff…

【岗位】IT行业岗位知识图谱--大数据工程师、机器学习、嵌入式、架构师

目录 1. 大数据工程师技能图谱2. 机器学习技能图谱3. 架构师技能图谱4. 嵌入式开发必备技能5. 嵌入式体系结构 1. 大数据工程师技能图谱 2. 机器学习技能图谱 3. 架构师技能图谱 4. 嵌入式开发必备技能 5. 嵌入式体系结构 **点赞、关注、评论、收藏哦**

7.7.8clip/简单量化

一、 clip函数&#xff1a;限制一个array的上下界 给定一个范围[min, max]&#xff0c;数组中值不在这个范围内的&#xff0c;会被限定为这个范围的边界。如给定范围[0, 1]&#xff0c;数组中元素值小于0的&#xff0c;值会变为0&#xff0c;数组中元素值大于1的&#xff0c;要…

【云存储】主流分布式文件系统介绍

目录 1、引言 2、云存储与分布式文件系统 2.1、云存储 2.2、分布式文件系统 3、Google的三大云计算与云存储论文 3.1、The Google File System&#xff08;谷歌文件系统&#xff09; 3.2、MapReduce&#xff1a;Simplified Data Processing on Large Clusters&#xff0…

云原生之深入解析Kubernetes CNI插件的选型和应用场景

一、常见网络插件 在学习容器网络的时候&#xff0c;肯定都听说过 Docker 的 bridge 网络、Vethpair、VxLAN 等术语&#xff0c;从 Docker 到 Kubernetes 后&#xff0c;学习 Flannel、Calico 等主流网络插件&#xff0c;分别代表了 Overlay 和 Underlay 的两种网络传输模式&a…

【VirtualBox】安装 VirtualBox 提示 needsthe Microsoft Visual C++ 2019

概述 一个好的文章能够帮助开发者完成更便捷、更快速的开发。书山有路勤为径&#xff0c;学海无涯苦作舟。我是秋知叶i、期望每一个阅读了我的文章的开发者都能够有所成长。 一、开发环境 开发环境&#xff1a;windows10虚拟机&#xff1a;VirtualBox 7.0.8 二、报错 ubun…

多条件见多值查询的 Excel 公式和 python 函数

问题 Python草堂 群的一位群友问&#xff1a;excel 数据表&#xff0c;用 vlookup 函数怎样实现多条件查询多值&#xff0c;多值排到一行上。如下图所示&#xff1a; 左边是数据清单&#xff0c;希望根据两个条件&#xff1a;产品、日期&#xff0c;查询数量&#xff0c;列到…

Element-UI el-table属性row-class-name用法

文章目录 前言官方示例自定义条件样式设置背景颜色样式stripe属性 设置背景颜色样式设置字体颜色总结 前言 可以通过指定 Table 组件的 row-class-name 属性来为 Table 中的某一行添加 class&#xff0c;表明该行处于某种状态。 官方示例 代码如下&#xff1a; <el-table…

体验版小程序为何无法访问云端服务器后端接口(请求失败...(已完美解决附加图片))?

文章目录 前言解决方案一解决方案二第一步第二步 前言 体验版小程序访问不到后端&#xff0c;接口请求失败&#xff0c;这个及其头疼的今天这个坑被我踩到了&#xff0c;呜呜呜~ 今天再发体验版小程序时&#xff0c;在微信开发者工具上面是可以正常访问后端的&#xff0c;但是线…

【sql注入-堆叠注入】多语句执行、结合其他注入

目录 堆叠注入 一、语法介绍 二、漏洞示例 三、常见形式 网络安全O 堆叠注入 一、语法介绍&#xff1a; 版本&#xff1a; 可以影响几乎所有的关系型数据库 原理&#xff1a; 将多条语句堆叠在一起进行查询&#xff0c;且可以执行多条SQL语句 语句之间以分号(;)隔开&#…

人气爆棚!广西、湖南、山西等地领导莅临数据宝考察交流

摘要&#xff1a;近期&#xff0c;数据宝发展如火如荼&#xff0c;企业展厅“忙不停”&#xff0c;见证众多思想碰撞、交流提升&#xff0c;迎来了各省领导莅临参观指导。 01 数字广西集团、青秀区政府领导一行莅临数据宝上海分公司实地走访 近日&#xff0c;数字广西集团党…