最近在做一个和U盘有关的项目,有一个需求是要求显示插入的U盘的盘符,当然了,如果拔出U盘,也应该更新显示,就是显示U口上插入的全部移动设备的全部盘符。
其实就是重写
protected
override
void
WndProc(
ref
Message m)
方法,根据得到的系统消息来处理,但是如果要实时更新的话,最好加上定时查询U口设备,将查询结果更新,时间的间隔可以自己定义,根据项目情况吧。
下面是完整的代码,如果大家有什么好的建议,欢迎大家一起交流。
using
System;
using
System.Collections.Generic;
using
System.ComponentModel;
using
System.Data;
using
System.Drawing;
using
System.Text;
using
System.IO;
using
System.Windows.Forms;
using
System.Threading;
namespace
WindowsApp
{
public
partial
class
ComboBoxForm2 : Form
{
private
IList
<
string
>
diskList
=
new
List
<
string
>
();
delegate
void
SetTextCallback(
string
s);
delegate
void
ClearListBoxItem();
private
Thread thread
=
null
;
private
BackgroundWorker backgroundworker;
public
ComboBoxForm2()
{
InitializeComponent();
}
protected
override
void
WndProc(
ref
Message m)
{
object
ojb
=
new
object
();
try
{
//
WM_DEVICECHANGE,系统硬件改变发出的系统消息
if
(m.Msg
==
WndProMsgConst.WM_DEVICECHANGE)
{
switch
(m.WParam.ToInt32())
{
case
WndProMsgConst.WM_DEVICECHANGE:
break
;
//
DBT_DEVICEARRIVAL,设备检测结束,并且可以使用
case
WndProMsgConst.DBT_DEVICEARRIVAL:
scanUDisk();
listBox1.Items.Clear();
foreach
(
string
s
in
diskList)
{
listBox1.Items.Add(s);
}
break
;
//
DBT_DEVICEREMOVECOMPLETE,设备卸载或者拔出
case
WndProMsgConst.DBT_DEVICEREMOVECOMPLETE:
scanUDisk();
listBox1.Items.Clear();
foreach
(
string
s
in
diskList)
{
listBox1.Items.Add(s);
}
break
;
}
}
}
catch
(Exception ex)
{
MessageBox.Show(
"
当前盘不能正确识别,请重新尝试!
"
,
"
提示
"
, MessageBoxButtons.OK, MessageBoxIcon.Information);
}
base
.WndProc(
ref
m);
}
private
void
button1_Click(
object
sender, EventArgs e)
{
IList
<
string
>
diskList
=
new
List
<
string
>
();
diskList.Add(
"
k001
"
);
diskList.Add(
"
k002
"
);
diskList.Add(
"
k003
"
);
diskList.Add(
"
k004
"
);
comboBox1.DataSource
=
diskList;
}
///
<summary>
///
扫描U口设备
///
</summary>
///
<param name="obj"></param>
private
void
scanUDisk()
{
diskList.Clear();
DriveInfo[] drives
=
DriveInfo.GetDrives();
foreach
(DriveInfo drive
in
drives)
{
if
((drive.DriveType
==
DriveType.Removable)
&&
!
drive.Name.Substring(
0
,
1
).Equals(
"
A
"
))
{
try
{
diskList.Add(drive.Name);
}
catch
{
MessageBox.Show(
"
当前盘不能正确识别,请重新尝试!
"
,
"
提示
"
, MessageBoxButtons.OK, MessageBoxIcon.Information);
}
}
}
}
private
void
ComboBoxForm2_Load(
object
sender, EventArgs e)
{
System.Timers.Timer timer
=
new
System.Timers.Timer(
1000
);
timer.Enabled
=
true
;
timer.Elapsed
+=
new
System.Timers.ElapsedEventHandler(fi);
timer.AutoReset
=
true
;
}
private
void
ThreadProcSafe()
{
scanUDisk();
//
MessageBox.Show(diskList.Count.ToString());
foreach
(
string
s
in
diskList)
{
SetText(s);
}
}
public
void
SetText(
string
text)
{
if
(
this
.listBox1.InvokeRequired)
{
if
(listBox1.Items.Contains(text))
return
;
SetTextCallback d
=
new
SetTextCallback(SetText);
this
.Invoke(d,
new
object
[] { text });
}
else
{
if
(listBox1.Items.Contains(text))
return
;
this
.listBox1.Items.Add(text);
}
}
void
fi(
object
sender, System.Timers.ElapsedEventArgs e)
{
scanUDisk();
//
listBox1.Items.Clear();
foreach
(
string
s
in
diskList)
{
SetText(s);
}
}
}
///
<summary>
///
windows消息的常量
///
</summary>
class
WndProMsgConst
{
#region
WndProc常量
public
const
int
WM_DEVICECHANGE
=
0x219
;
public
const
int
DBT_DEVICEARRIVAL
=
0x8000
;
public
const
int
DBT_CONFIGCHANGECANCELED
=
0x0019
;
public
const
int
DBT_CONFIGCHANGED
=
0x0018
;
public
const
int
DBT_CUSTOMEVENT
=
0x8006
;
public
const
int
DBT_DEVICEQUERYREMOVE
=
0x8001
;
public
const
int
DBT_DEVICEQUERYREMOVEFAILED
=
0x8002
;
public
const
int
DBT_DEVICEREMOVECOMPLETE
=
0x8004
;
public
const
int
DBT_DEVICEREMOVEPENDING
=
0x8003
;
public
const
int
DBT_DEVICETYPESPECIFIC
=
0x8005
;
public
const
int
DBT_DEVNODES_CHANGED
=
0x0007
;
public
const
int
DBT_QUERYCHANGECONFIG
=
0x0017
;
public
const
int
DBT_USERDEFINED
=
0xFFFF
;
#endregion
}
}
设备的实时性还是差一点,还有啊,像这样的窗体有很多,我不能每个窗体都copy一遍这些代码吧,如何封装起来呢,控件的线程安全也是问题,还需要改进啊,谁有好的意见可以提出来。
msn:[email protected]
mail:[email protected]
简单封装了一下,封装类如下:
using
System;
using
System.Collections.Generic;
using
System.Text;
using
System.Windows.Forms;
using
System.Threading;
using
System.IO;
namespace
WindowsApp
{
class
Class1
{
private
IList
<
string
>
diskList
=
new
List
<
string
>
();
delegate
void
SetTextCallback(
string
s);
delegate
void
ClearListBoxItem();
private
ListBox _listbox;
private
Form _form;
private
Thread thread
=
null
;
//
private BackgroundWorker backgroundworker;
public
Class1()
{
System.Timers.Timer timer
=
new
System.Timers.Timer(
1000
);
timer.Enabled
=
true
;
timer.Elapsed
+=
new
System.Timers.ElapsedEventHandler(fi);
timer.AutoReset
=
true
;
}
public
void
filldata(Form form, Message m,ListBox listbox)
{
_listbox
=
listbox;
_form
=
form;
try
{
//
WM_DEVICECHANGE,系统硬件改变发出的系统消息
if
(m.Msg
==
WndProMsgConst.WM_DEVICECHANGE)
{
switch
(m.WParam.ToInt32())
{
case
WndProMsgConst.WM_DEVICECHANGE:
break
;
//
DBT_DEVICEARRIVAL,设备检测结束,并且可以使用
case
WndProMsgConst.DBT_DEVICEARRIVAL:
scanUDisk();
_listbox.Items.Clear();
foreach
(
string
s
in
diskList)
{
_listbox.Items.Add(s);
}
break
;
//
DBT_DEVICEREMOVECOMPLETE,设备卸载或者拔出
case
WndProMsgConst.DBT_DEVICEREMOVECOMPLETE:
scanUDisk();
_listbox.Items.Clear();
foreach
(
string
s
in
diskList)
{
_listbox.Items.Add(s);
}
break
;
}
}
}
catch
(Exception ex)
{
MessageBox.Show(
"
当前盘不能正确识别,请重新尝试!
"
,
"
提示
"
, MessageBoxButtons.OK, MessageBoxIcon.Information);
}
}
public
void
SetText(
string
text)
{
if
(
this
._listbox.InvokeRequired)
{
if
(_listbox.Items.Contains(text))
return
;
SetTextCallback d
=
new
SetTextCallback(SetText);
_form.Invoke(d,
new
object
[] { text });
}
else
{
if
(_listbox.Items.Contains(text))
return
;
this
._listbox.Items.Add(text);
}
}
void
fi(
object
sender, System.Timers.ElapsedEventArgs e)
{
scanUDisk();
//
listBox1.Items.Clear();
foreach
(
string
s
in
diskList)
{
SetText(s);
}
}
///
<summary>
///
扫描U口设备
///
</summary>
///
<param name="obj"></param>
private
void
scanUDisk()
{
diskList.Clear();
DriveInfo[] drives
=
DriveInfo.GetDrives();
foreach
(DriveInfo drive
in
drives)
{
if
((drive.DriveType
==
DriveType.Removable)
&&
!
drive.Name.Substring(
0
,
1
).Equals(
"
A
"
))
{
try
{
diskList.Add(drive.Name);
}
catch
{
MessageBox.Show(
"
当前盘不能正确识别,请重新尝试!
"
,
"
提示
"
, MessageBoxButtons.OK, MessageBoxIcon.Information);
}
}
}
}
}
///
<summary>
///
windows消息的常量
///
</summary>
class
WndProMsgConst
{
#region
WndProc常量
public
const
int
WM_DEVICECHANGE
=
0x219
;
public
const
int
DBT_DEVICEARRIVAL
=
0x8000
;
public
const
int
DBT_CONFIGCHANGECANCELED
=
0x0019
;
public
const
int
DBT_CONFIGCHANGED
=
0x0018
;
public
const
int
DBT_CUSTOMEVENT
=
0x8006
;
public
const
int
DBT_DEVICEQUERYREMOVE
=
0x8001
;
public
const
int
DBT_DEVICEQUERYREMOVEFAILED
=
0x8002
;
public
const
int
DBT_DEVICEREMOVECOMPLETE
=
0x8004
;
public
const
int
DBT_DEVICEREMOVEPENDING
=
0x8003
;
public
const
int
DBT_DEVICETYPESPECIFIC
=
0x8005
;
public
const
int
DBT_DEVNODES_CHANGED
=
0x0007
;
public
const
int
DBT_QUERYCHANGECONFIG
=
0x0017
;
public
const
int
DBT_USERDEFINED
=
0xFFFF
;
#endregion
}
}
使用方法如下:
using
System;
using
System.Collections.Generic;
using
System.ComponentModel;
using
System.Data;
using
System.Drawing;
using
System.Text;
using
System.IO;
using
System.Windows.Forms;
using
System.Threading;
namespace
WindowsApp
{
public
partial
class
ComboBoxForm2 : Form
{
public
ComboBoxForm2()
{
InitializeComponent();
}
protected
override
void
WndProc(
ref
Message m)
{
Class1 c
=
new
Class1();
c.filldata(
this
,m, listBox1);
base
.WndProc(
ref
m);
}
}
}