TECHNOLOGIES
FORUMS
JOBS
BOOKS
EVENTS
INTERVIEWS
Live
MORE
LEARN
Training
CAREER
MEMBERS
VIDEOS
NEWS
BLOGS
Sign Up
Login
No unread comment.
View All Comments
No unread message.
View All Messages
No unread notification.
View All Notifications
Answers
Post
An Article
A Blog
A News
A Video
An EBook
An Interview Question
Ask Question
Forums
Monthly Leaders
Forum guidelines
shintaerp
NA
1
0
How to trap all the WM_DEVICECHANGE messages
Sep 10 2004 3:45 AM
Since I am a new programmer, I know very few about Win32 API. In fact, I am writing something about detecting storage device attaching/detaching, and media insert/remove from the storage device. I've got two questions. 1) How can I trap all the WM_DEVICECHANGE messages, not just the default two (DBT_DEVICEARRIVAL and DBT_DEVICEREMOVECOMPLETE). 2) How can I detect media insert/remove from the storage device, such as: insert/remove CF card from a USB card reader? * I've tried to read the MSDN online to get some ideas, but I still don't understand. If I can, may I ask for a complete sample? Thanks, Thanks, Thanks a lot!!! ---Here is the class: using System; using System.Text; using System.Windows.Forms; using System.Runtime.InteropServices; namespace Staging { ///
/// Delegate used to implement the class events ///
public delegate void DeviceVolumeAction(int aMask); ///
/// Custom exception ///
public class DeviceVolumeMonitorException: ApplicationException { public DeviceVolumeMonitorException(string aMessage):base(aMessage) {} } internal class _DeviceVolumeMonitor: NativeWindow { ///
/// Private fields ///
DeviceVolumeMonitor fMonitor; #region API constants and structures ///
/// Constant defined for the WM_DEVICECHANGE message in WinUser.h ///
const int WM_DEVICECHANGE = 0x0219; ///
/// Constants and structs defined in DBT.h ///
public enum DeviceEvent:int { Arrival = 0x8000, //DBT_DEVICEARRIVAL QueryRemove = 0x8001, //DBT_DEVICEQUERYREMOVE QueryRemoveFailed = 0x8002, //DBT_DEVICEQUERYREMOVEFAILED RemovePending = 0x8003, //DBT_DEVICEREMOVEPENDING RemoveComplete = 0x8004, //DBT_DEVICEREMOVECOMPLETE Specific = 0x8005, //DBT_DEVICEREMOVECOMPLETE Custom = 0x8006 //DBT_CUSTOMEVENT } public enum DeviceType:int { OEM = 0x00000000, //DBT_DEVTYP_OEM DeviceNode = 0x00000001, //DBT_DEVTYP_DEVNODE Volume = 0x00000002, //DBT_DEVTYP_VOLUME Port = 0x00000003, //DBT_DEVTYP_PORT Net = 0x00000004 //DBT_DEVTYP_NET } public enum VolumeFlags:int { Media = 0x0001, //DBTF_MEDIA Net = 0x0002 //DBTF_NET } public struct BroadcastHeader //_DEV_BROADCAST_HDR { public int Size; //dbch_size public DeviceType Type; //dbch_devicetype private int Reserved; //dbch_reserved } public struct Volume //_DEV_BROADCAST_VOLUME { public int Size; //dbcv_size public DeviceType Type; //dbcv_devicetype private int Reserved; //dbcv_reserved public int Mask; //dbcv_unitmask public int Flags; //dbcv_flags } #endregion ///
/// Constructor ///
///
A DeviceVolumeMonitor instance that ownes the object ///
The Windows handle to be used public _DeviceVolumeMonitor(DeviceVolumeMonitor aMonitor) { fMonitor = aMonitor; } ///
/// WndProc method that traps all messages sent to the Handle ///
///
A Windows message protected override void WndProc(ref Message aMessage) { BroadcastHeader lBroadcastHeader; Volume lVolume; DeviceEvent lEvent; base.WndProc(ref aMessage); Console.WriteLine(""+aMessage.Msg); if(aMessage.Msg==WM_DEVICECHANGE && fMonitor.Enabled) { lEvent = (DeviceEvent)aMessage.WParam.ToInt32(); //Select needed event // if(lEvent == 18) // { //MessageBox.Show(""+aMessage.WParam.ToInt32()); // } if (lEvent==DeviceEvent.Arrival || lEvent==DeviceEvent.RemoveComplete) { lBroadcastHeader = (BroadcastHeader)Marshal.PtrToStructure(aMessage.LParam,typeof(BroadcastHeader)); //Select needed device type if(lBroadcastHeader.Type==DeviceType.Volume) { lVolume = (Volume)Marshal.PtrToStructure(aMessage.LParam,typeof(Volume)); if((lVolume.Flags & (int)VolumeFlags.Media)!=0) { fMonitor.TriggerEvents(lEvent==DeviceEvent.Arrival,lVolume.Mask); } } } } } } ///
/// DeviceVolumeMonitor class /// Derived from NativeWindow and implements IDisposable /// Built to monitor volume insertion and removal from devices which implement software ejection from removable media ///
public class DeviceVolumeMonitor: IDisposable { ///
/// Private fields ///
_DeviceVolumeMonitor fInternal; IntPtr fHandle; bool fDisposed; bool fEnabled; bool fAsync; IntPtr handleNotification; ///
/// Events /// These events are invoked on Volume insertion an removal ///
public event DeviceVolumeAction OnVolumeInserted; public event DeviceVolumeAction OnVolumeRemoved; ///
/// Enables or disables message trapping ///
public bool Enabled { get { return fEnabled; } set { if(!fEnabled && value) { if (fInternal.Handle==IntPtr.Zero) { fInternal.AssignHandle(fHandle); } fEnabled = true; } if(fEnabled && !value) { if(fInternal.Handle!=IntPtr.Zero) { fInternal.ReleaseHandle(); } fEnabled = false; } } } ///
/// Enables or disables asynchronous event calls ///
public bool AsynchronousEvents { get { return fAsync; } set { fAsync = value; } } ///
/// Constructor with no parameters /// This constructo can be used if the instance is created in a form. /// Caution: the form must already have an assigned Handle ///
public DeviceVolumeMonitor() { if (Form.ActiveForm!=null) { fHandle = Form.ActiveForm.Handle; } else { throw new DeviceVolumeMonitorException("There is no active form!"); } _DeviceVolumeMonitor.Volume lVolume = new Staging._DeviceVolumeMonitor.Volume(); lVolume.Size = Marshal.SizeOf(typeof(_DeviceVolumeMonitor.Volume)); lVolume.Type = _DeviceVolumeMonitor.DeviceType.Volume; lVolume.Flags = (int)_DeviceVolumeMonitor.VolumeFlags.Media; //lVolume.Mask // IntPtr tmpIntPtr = IntPtr.Zero; // Marshal.StructureToPtr(lVolume,tmpIntPtr,true); handleNotification = RegisterDeviceNotification(fHandle,ref lVolume,0x00000000); Initialize(); } [DllImport("User32", CharSet=CharSet.Auto)] private static extern IntPtr RegisterDeviceNotification(IntPtr hRecipient,ref _DeviceVolumeMonitor.Volume NotificationFilter,int Flags); [DllImport("User32", CharSet=CharSet.Auto)] private static extern bool UnregisterDeviceNotification(IntPtr Handle); ///
/// Preferred constructor, accepts a Window Handle as single parameter ///
///
Window handle to be captured public DeviceVolumeMonitor(IntPtr aHandle) { if (aHandle!=IntPtr.Zero) { fHandle = aHandle; } else { throw new DeviceVolumeMonitorException("Invalid handle!"); } Initialize(); } ///
/// Internal initialize method /// Sets all the private fields initial values and enables message trapping ///
private void Initialize() { fInternal = new _DeviceVolumeMonitor(this); fDisposed = false; fEnabled = false; fAsync = false; Enabled = true; } ///
/// Internal method used by _DeviceVolumeMonitor ///
///
Flag set if volume inserted ///
bit vector returned by the field dbcv_unitmask in the _DEV_BROADCAST_VOLUME structure internal void TriggerEvents(bool aInserted, int aMask) { if (AsynchronousEvents) { if(aInserted) { OnVolumeInserted.BeginInvoke(aMask,null,null); } else { OnVolumeRemoved.BeginInvoke(aMask,null,null); } } else { if(aInserted) { OnVolumeInserted(aMask); } else { OnVolumeRemoved(aMask); } } } ///
/// Platform invoke the API function QueryDosDevice /// Fills aPath with the device path mapped to a DOS drive letter or device name in aName /// Returns the device path count (NOTE: used to retrieve a single device path) ///
[DllImport("kernel32.dll", CharSet=CharSet.Auto)] private static extern int QueryDosDevice(string aName,[Out] StringBuilder aPath,int aCapacity); ///
/// Returns a comma delimited string with all the drive letters in the bit vector parameter ///
///
bit vector returned by the field dbcv_unitmask in the _DEV_BROADCAST_VOLUME structure ///
public string MaskToLogicalPaths(int aMask) { int lMask = aMask; int lValue = 0; StringBuilder lReturn = new StringBuilder(128); try { lReturn = new StringBuilder(128); if(aMask>0) { for (;lMask!=0;lMask>>=1) { if ((lMask & 1)!=0) { lReturn.Append((char)(65+lValue)); lReturn.Append(":,"); } lValue ++; } lReturn.Remove(lReturn.Length-1,1); } return lReturn.ToString(); } finally { lReturn = null; } } ///
/// Returns a comma delimited string with all the device paths in the bit vector parameter ///
///
bit vector returned by the field dbcv_unitmask in the _DEV_BROADCAST_VOLUME structure ///
public string MaskToDevicePaths(int aMask) { string[] lLogical = MaskToLogicalPaths(aMask).Split(Convert.ToChar(",")); StringBuilder lBuffer; StringBuilder lReturn; try { lBuffer = new StringBuilder(256); lReturn = new StringBuilder(256); foreach(string lPath in lLogical) { if (QueryDosDevice(lPath,lBuffer,lBuffer.Capacity)>0) { lReturn.Append(lBuffer.ToString()); lReturn.Append(","); } } lReturn.Remove(lReturn.Length-1,1); return lReturn.ToString(); } finally { lBuffer = null; lReturn = null; } } ///
/// IDisposable implementation acording to the preferred design pattern ///
public void Dispose() { Dispose(true); GC.SuppressFinalize(this); } protected virtual void Dispose(bool aDisposing) { if(!this.fDisposed) { if(fInternal.Handle!=IntPtr.Zero) { fInternal.ReleaseHandle(); fInternal = null; } } fDisposed = true; } ~DeviceVolumeMonitor() { UnregisterDeviceNotification(handleNotification); Dispose(false); } } }
Reply
Answers (
0
)
Image Class
DirectX