功能导入:
最近在做一个串口调试工具,需求是:
1、打开串口软件时,获取所有的串口,并显示第一个串口号
2、在程序中没有点击打开串口按钮时(串口关闭状态),实时监控串口拔插,当有串口设备插入时,显示最新插入的那一个串口号,当有串口设备拔出时,显示第一个串口号
3、当程序中已经点击了打开串口按钮(串口打开状态),实时监控串口拔插,当有串口设备插入时,保持打开的串口号不变,当有串口设备拔出时,如果不是打开的串口,继续保持打开的串口号不变,如果拔出的串口时打开的串口号,初始化串口状态(设为串口关闭状态)
解决办法:
采用的方法是,在主窗口的From类下覆盖WndProc,程序示例如下
:
#region WndProc 重载WndProc,串口设备刷新方法
//事件代码
private const int WM_DEVICECHANGE = 0x219; //设备改变事件
private const int DBT_DEVICEARRIVAL = 0x8000; //检测到新设备
private const int DBT_DEVICEREMOVECOMPLETE = 0x8004; //移除设备
protected override void WndProc(ref Message m)
{
base.WndProc(ref m);//调用父类方法,以确保其他功能正常
switch (m.Msg)
{
case WM_DEVICECHANGE://设备改变事件
string[] ports = System.IO.Ports.SerialPort.GetPortNames();//重新获取串口
switch ((int)m.WParam)
{
case DBT_DEVICEARRIVAL://检测到新设备
//Debug.WriteLine("检测到新设备!!!!");
cbSerial.Items.Clear();//清除cbSerial里面的数据
cbSerial.Items.AddRange(ports);//给cbSerial添加数据
if (btnSwitch.Text == "关闭串口")//用户已经打开串口
{
//Debug.WriteLine("串口被占用,但检测到新设备");
cbSerial.SelectedIndex = cbSerial.Items.Count > 0 ? 0 : -1;//显示获取的第一个串口号
if (cbSerial.SelectedIndex >= 0)
{
//确保当前打开的串口不被改变
if (serialPort.PortName == cbSerial.SelectedItem.ToString())//之前打开的串口名与列表中的串口名相同
{
Debug.WriteLine("序号:" + cbSerial.SelectedIndex + " 设备名:" + cbSerial.SelectedItem);
}
else
{
for (int i = 0; i < cbSerial.Items.Count; i++)
{
cbSerial.SelectedIndex = i;
if (serialPort.PortName == cbSerial.SelectedItem.ToString())
{
Debug.WriteLine("序号:" + cbSerial.SelectedIndex + " 设备名:" + cbSerial.SelectedItem);
break;
}
}
}
}
}
else
{
Debug.WriteLine("串口未被占用,但检测到新设备");
cbSerial.SelectedIndex = cbSerial.Items.Count > 0 ? 0 : -1;//显示获取的第一个串口号
if (cbSerial.SelectedIndex >= 0)
{
for(int i=0;i<cbSerial.Items.Count;i++)
{
cbSerial.SelectedIndex = i;
Debug.WriteLine("序号:" + cbSerial.SelectedIndex + " 设备名:" + cbSerial.SelectedItem);
}
//cbSerial.SelectedIndex = 0;//显示最前面一个
}
}
break;
case DBT_DEVICEREMOVECOMPLETE://有设备移除
//Debug.WriteLine("有设备移除!!!!");
cbSerial.Items.Clear();//清除cbSerial里面的数据
cbSerial.Items.AddRange(ports);//给cbSerial添加数据
if (btnSwitch.Text == "关闭串口")//用户已经打开串口
{
//Debug.WriteLine("串口被占用,用但检测设备移除");
//serialPort.Dispose();//释放掉原先的串口资源
//用户打开过一个串口
cbSerial.SelectedIndex = cbSerial.Items.Count > 0 ? 0 : -1;//显示获取的第一个串口号
if (cbSerial.SelectedIndex >= 0)
{
//确保当前打开的串口不被改变
int temp_flag = 0;//标记串口状态 0:未检测到此串口 1:检测到此串口
for (int i = 0; i < cbSerial.Items.Count; i++)
{
cbSerial.SelectedIndex = i;
if (serialPort.PortName == cbSerial.SelectedItem.ToString())
{
Debug.WriteLine("序号:" + cbSerial.SelectedIndex + " 设备名:" + cbSerial.SelectedItem);
temp_flag = 1;
break;
}
}
if (temp_flag == 0)//执行初始化串口状态程序
{
//如果串口为打开状态,就先关闭一下来初始化串口
if (serialPort.IsOpen == true)
{
serialPort.Close();
}
//设置按钮内容为"打开串口"
btnSwitch.Text = "打开串口";
//恢复控件功能,设置必要控件为可用状态
SettingControls(1);
}
}
else
{
//如果串口为打开状态,就先关闭一下来初始化串口
if (serialPort.IsOpen == true)
{
serialPort.Close();
}
//设置按钮内容为"打开串口"
btnSwitch.Text = "打开串口";
//恢复控件功能,设置必要控件为可用状态
SettingControls(1);
}
}
else
{
//Debug.WriteLine("串口未被占用,用但检测设备移除");
cbSerial.SelectedIndex = cbSerial.Items.Count > 0 ? 0 : -1;//显示获取的第一个串口号
if (cbSerial.SelectedIndex >= 0)
{
for (int i = 0; i < cbSerial.Items.Count; i++)
{
cbSerial.SelectedIndex = i;
Debug.WriteLine("序号:" + cbSerial.SelectedIndex + " 设备名:" + cbSerial.SelectedItem);
}
cbSerial.SelectedIndex = 0;//显示最前面一个
}
}
break;
}
break;
}
}
#endregion