## 小白学习Winform 遇到的问题总结*
需求:
公司需要做一个血压体重一体机,功能就是可以配置血压器、体重器、读卡器等参数,实现刷卡自动测量体重血压等数据,这对于一个没有接触过winform的小白而言还是很有难度的
设计思路:
1、创建两个窗体,A和B,A窗体负责配置仪器信息,B窗体负责测量数据进行展示
2、创建了四个类 :
(1)ReadCardInfo(负责读取患者信息,页面展示);
(2)WeightMachine(连接体重仪,读取串口数据);
(3)BloodPressure(连接血压器,读取高低压、心率数据)
(4)ScanerCode(扫码盒子,患者可以通过二维码直接进行扫码测量)
3、创建两个线程ReadThread、MeasureThread 分别进行读卡和测量操作
遇到的问题总结以及解决方法:
1、最大化窗口并且去除边框
//设置窗体位于左上角
this.StartPosition = 0;
//去除窗体边框
this.FormBorderStyle = FormBorderStyle.None;
//窗体最大化
this.WindowState = System.Windows.Forms.FormWindowState.Maximized;
2、取消跨线程检查,否则在给控件赋值的时候会报错
//取消跨线程检查
Control.CheckForIllegalCrossThreadCalls = false;
3、窗体加载和label控件赋值的时候会闪烁,可能是由于窗体添加背景图片引起的
//减少闪烁
SetStyle(ControlStyles.UserPaint, true);
SetStyle(ControlStyles.AllPaintingInWmPaint, true); // 禁止擦除背景.
SetStyle(ControlStyles.OptimizedDoubleBuffer, true);//双通道渲染
this.UpdateStyles();
总结分享:
第一次做winform项目,比较差劲,但是还是有很多收获的;接下来分享代码给大家,希望大家能够对大家有帮助
(1)读卡类ReadCardInfo
#region 描述
/
///作者:XXXX
///时间:XXX
///描述:读卡操作
/
#endregion
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace AppWithoutBlutdruckAndWeight
{
public class ReadCardInfo
{
//读卡器类型,1是明华,2德卡D3 默认是德卡
public string ReadCardType = "2";
//寻卡
[DllImport("lib\\dcrf32.dll", EntryPoint = "dc_card")]
public static extern Int16 dc_card(Int16 icdev, int mode, ref long Snr);
//打开设备
[DllImport("lib\\dcrf32.dll", EntryPoint = "dc_init")]
public static extern Int16 dc_init(int port, int baud);
//读取数据 从卡中读数据
[DllImport("lib\\dcrf32.dll")]
public static extern Int16 dc_read(Int16 icdev, int adr, [MarshalAs(UnmanagedType.LPArray)] byte[] sdata);
//断开设备
[DllImport("lib\\mwrf32.dll", EntryPoint = "rf_exit")]
public static extern Int16 rf_exit(Int16 icdev);
//读取数据
[DllImport("lib\\mwrf32.dll")]
public static extern Int16 rf_read(Int16 icdev, int adr, [MarshalAs(UnmanagedType.LPArray)] byte[] sdata);
[DllImport("lib\\dcrf32.dll", EntryPoint = "dc_load_key_hex")]
public static extern Int16 dc_load_key_hex(Int16 icdev, int mode, int secnr, string keybuff);
//验证某一扇区密码
[DllImport("lib\\dcrf32.dll")]
public static extern Int16 dc_authentication(Int16 icdev, int _Mode, int _SecNr);
//中止对该卡操作
[DllImport("lib\\dcrf32.dll", EntryPoint = "dc_halt")]
public static extern Int16 dc_halt(Int16 icdev);
//断开设备
[DllImport("lib\\dcrf32.dll", EntryPoint = "dc_exit")]
public static extern Int16 dc_exit(Int16 icdev);
//连接设备
[DllImport("lib\\mwrf32.dll", EntryPoint = "rf_init")]
public static extern Int16 rf_init(int port, int baud);
//寻卡
[DllImport("lib\\mwrf32.dll", EntryPoint = "rf_card")]
public static extern Int16 rf_card(Int16 icdev, int mode, ref long Snr);
//中止对该卡操作
[DllImport("lib\\mwrf32.dll", EntryPoint = "rf_halt")]
public static extern Int16 rf_halt(Int16 icdev);
//蜂鸣器
[DllImport("lib\\dcrf32.dll", EntryPoint = "dc_beep")]
public static extern Int16 dc_beep(Int16 icdev, int version);
//蜂鸣器
[DllImport("lib\\mwrf32.dll", EntryPoint = "rf_beep")]
public static extern Int16 rf_beep(Int16 icdev, int version);
public string readCard()
{
string cardNo = "";
//寻卡 成功/失败
Int16 icdev = OpenCard();
if (icdev < 0) return string.Empty;
//验证
bool success = VerifyPassword(icdev, 1, 0);
if (!success) return string.Empty;
//读卡
cardNo = ReadCard(icdev, 1, 0).Replace("\0", "").Trim();
return cardNo;
}
public Int16 OpenCard()
{
if (!string.IsNullOrEmpty(ReadCardType) && ReadCardType == "2")
{
Int16 icdev = dc_init(100, 9600);
if (icdev < 0)
{
return icdev;
}
long cardNo = 0;
int result = dc_card((Int16)icdev, 1, ref cardNo);
if (result == 0)
{
return icdev;
}
else
{
// 寻卡失败
dc_halt((Int16)icdev);
dc_exit(icdev); //关闭设备
return -1;
}
}
else
{
// 打开设备
Int16 icdev = rf_init(0, 9600);
if (icdev < 0)
{
return icdev;
}
// 寻卡
long icCardNo = 0;
int result = rf_card((Int16)icdev, 1, ref icCardNo);
if (result == 0)
{
// 寻卡成功 卡号为icCardNo
return icdev;
}
else
{
// 寻卡失败
rf_halt((Int16)icdev);
rf_exit(icdev); //关闭设备
return -1;
}
}
}
private bool VerifyPassword(Int16 icdev, int sector, int block)
{
int ints = dc_load_key_hex(icdev, 0, sector, "FFFFFFFFFFFF");
if (ints != 0) return false;
// 验证密码
int result = dc_authentication(icdev, 0, sector);
if (result != 0)
{
dc_halt((Int16)icdev);
dc_exit(icdev); //关闭设备
return false;
}
return true;
}
private string ReadCard(Int16 icdev, int sector, int block)
{
int address = sector * 4 + block;
byte[] temp1 = new byte[64 * 8];
//德卡
if (!string.IsNullOrEmpty(ReadCardType) && ReadCardType == "2")
{
int result = dc_read(icdev, address, temp1);
if (result == 0)
{
dc_beep(icdev, 5);//提示音
return Encoding.Default.GetString(temp1);
}
else
{
dc_beep(icdev, 20);//提示音
return "";
}
}
else//明华
{
int result = rf_read(icdev, address, temp1);
if (result == 0)
{
rf_beep(icdev, 5);//提示音
return Encoding.Default.GetString(temp1);
}
else
{
rf_beep(icdev, 20);//提示音
return "";
}
}
}
}
}
(2)体重测量 WeightMachine
#region 描述
/
///作者:XXXX
///时间:XXXX
///描述:连接串口读取体重数据
/
#endregion
using System;
using System.Collections.Generic;
using System.IO.Ports;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace AppWithoutBlutdruckAndWeight
{
public class WeightMachine
{
/// <summary>
/// 串口对象
/// </summary>
private SerialPort serialPort = new SerialPort();
/// <summary>
/// 体重数据
/// </summary>
private string result = "0";
/// <summary>
/// 体重器类型
/// </summary>
public string WeightType = string.Empty;
/// <summary>
/// 计时器,一分钟未读出数据,停止读取
/// </summary>
public int CountTime = 0;
public string ReadMessage(string baudrate,string Name)
{
try
{
WeightType = Name;
if (!serialPort.IsOpen)
{
string[] portName = SerialPort.GetPortNames();
serialPort.PortName = portName[0]; //端口名称
serialPort.BaudRate = Convert.ToInt32(baudrate); // 波特率4800
serialPort.DataBits = 8; // 每个字节的标准数据位长度。
serialPort.StopBits = StopBits.One; //停止一位
serialPort.Parity = Parity.None; //偶校验
//serialPort.ReadTimeout = 500; //接收延时ms
//serialPort.DataReceived += new SerialDataReceivedEventHandler(DataReceivedHandler);
serialPort.Open();
}
if (serialPort.IsOpen)
{
CountTime = 0;
while (true)
{
Thread.Sleep(1000);
CountTime++;
byte[] readData = new byte[2048]; //获取接收缓冲区中数据的字节数。
serialPort.Read(readData, 0, readData.Length);//从SerialPort 输入缓冲区中读取。
string temp = Encoding.Default.GetString(readData);
result = ParsingDataByType(temp.Trim());
if (!string.IsNullOrEmpty(result) && result != "0")
{
break;
}
if (CountTime > 120)
{
result = "-1";
break;
}
serialPort.DiscardInBuffer();
serialPort.DiscardOutBuffer();
}
serialPort.Close();
}
return result;
}
catch (Exception ex)
{
//MessageBox.Show("“" + ex.Message + "”设置硬件功能不可用!", "提示", MessageBoxButtons.OK, MessageBoxIcon.Warning);
return "";
}
}
public void CloseWeight() => serialPort.Close();
#region 解析体重数据
/// <summary>
/// 解析数据
/// </summary>
private string ParsingDataByType(string data)
{
string weightresult = "";
switch (WeightType)
{
case "上海志荣轮椅体重秤":
string[] weight = data.Trim('=').Split('=');
if (weight.Length > 3 && (weight[0].Trim() == weight[1].Trim() && weight[1].Trim() == weight[2].Trim()))
{
char[] c = weight[0].Trim().ToCharArray();
Array.Reverse(c);
weightresult = Convert.ToInt32(new string(c)).ToString();
}
break;
case "电子多功能秤seca685":
break;
}
return weightresult;
}
#endregion
}
}
3、读取血压 BloodPressure
#region 描述
/
///作者:XXXX
///时间:XXXX
///描述:连接串口读取血压、心率
/
#endregion
using System;
using System.Collections.Generic;
using System.IO.Ports;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Timers;
using System.Windows.Forms;
namespace AppWithoutBlutdruckAndWeight
{
public class BloodPressure
{
/// <summary>
/// 血压器类型
/// </summary>
public string BloodPreType = string.Empty;
SerialPort comm = new SerialPort();
public BloodPressure()
{
}
/// <summary>
/// 读取数据
/// </summary>
/// <returns></returns>
public string ReadMessage(string baudrate,string Name)
{
BloodPreType = Name;
try
{
string result = string.Empty;
string[] portName = SerialPort.GetPortNames();
comm.PortName = portName[0]; //端口名称
comm.BaudRate = Convert.ToInt32(baudrate);
comm.Parity = System.IO.Ports.Parity.None;
comm.DataBits = 8;
comm.StopBits = System.IO.Ports.StopBits.One;
comm.Handshake = System.IO.Ports.Handshake.None;
comm.ReadTimeout = 90000;
Thread.Sleep(1000);
//接收缓冲区大小
comm.Open();
//读取并解析数据
return ParsingDataByType();
}
catch (Exception ex)
{
return "-1";
}
finally
{
comm.Close();
}
}
/// <summary>
/// 关闭串口
/// </summary>
public void CloseBlood() => comm.Close();
#region 解析血压、心率数据
/// <summary>
/// 解析数据
/// </summary>
private string ParsingDataByType()
{
string bloodResult = "";
string result = "";
switch (BloodPreType)
{
case "健太郎血压仪9020(RVIII)":
break;
case "RBP-9000c和RBP-9001台式血压计":
int count = 0;
string subStr = "";
while (true)
{
byte[] buf = new byte[1];
comm.Read(buf, 0, 1);
string str = Convert.ToString(buf[0], 10);
result += str;
//前24位信息组成 前导码、设备版本、数据长度、类型标识、类型子码、用户标识、测量时间
if (result.Length > 24)
{
subStr += str;
if (subStr.Length >= 3)
{
subStr = subStr.TrimStart('0');
bloodResult += subStr + "|";
count++;
subStr = "";
}
if (count >= 3) break;
}
}
bloodResult = bloodResult.Trim('|');
break;
}
return bloodResult;
}
#endregion
}
}
(4)扫码盒子的代码我就不贴了,网上自行搜索,或者留言给我