如何获取U盘插入的事件和盘符?关键是盘符的获取
有些U盘 如装有U3 等U盘辅助工具的, 会产生一个虚拟盘,造成混乱.

解决方案 »

  1.   

    可监控,用文件夹监控代码可以,主要函数:SHChangeNotifyRegisterunit unit1;interfaceuses
      Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
      Dialogs, StdCtrls, shlobj, Activex, ComCtrls, ExtCtrls;const
      SHCNE_RENAMEITEM = $1;
      SHCNE_CREATE = $2;
      SHCNE_DELETE = $4;
      SHCNE_MKDIR = $8;
      SHCNE_RMDIR = $10;
      SHCNE_MEDIAINSERTED = $20;
      SHCNE_MEDIAREMOVED = $40;
      SHCNE_DRIVEREMOVED = $80;
      SHCNE_DRIVEADD = $100;
      SHCNE_NETSHARE = $200;
      SHCNE_NETUNSHARE = $400;
      SHCNE_ATTRIBUTES = $800;
      SHCNE_UPDATEDIR = $1000;
      SHCNE_UPDATEITEM = $2000;
      SHCNE_SERVERDISCONNECT = $4000;
      SHCNE_UPDATEIMAGE = $8000;
      SHCNE_DRIVEADDGUI = $10000;
      SHCNE_RENAMEFOLDER = $20000;
      SHCNE_FREESPACE = $40000;
      SHCNE_ASSOCCHANGED = $8000000;
      SHCNE_DISKEVENTS = $2381F;
      SHCNE_GLOBALEVENTS = $C0581E0;
      SHCNE_ALLEVENTS = $7FFFFFFF;
      SHCNE_INTERRUPT = $80000000;
      SHCNF_IDLIST = 0;
     // LPITEMIDLIST
      SHCNF_PATHA = $1;
     // path name
      SHCNF_PRINTERA = $2;
     // printer friendly name
      SHCNF_DWORD = $3;
     // DWORD
      SHCNF_PATHW = $5;
     // path name
      SHCNF_PRINTERW = $6;
     // printer friendly name
      SHCNF_TYPE = $FF;
      SHCNF_FLUSH = $1000;
      SHCNF_FLUSHNOWAIT = $2000;
      SHCNF_PATH = SHCNF_PATHW;
      SHCNF_PRINTER = SHCNF_PRINTERW;
      WM_SHNOTIFY = $401;
      NOERROR = 0;type
      TForm1 = class(TForm)
        Button1: TButton;
        Memo1: TMemo;
        procedure FormClose(Sender: TObject; var Action: TCloseAction);
        procedure Button1Click(Sender: TObject);
      private
        procedure WMShellReg(var Message: TMessage); message WM_SHNOTIFY;
      public
       { Public declarations }
      end;type
      PSHNOTIFYSTRUCT = ^SHNOTIFYSTRUCT;
      SHNOTIFYSTRUCT = record
        dwItem1: PItemIDList;
        dwItem2: PItemIDList;
      end;type PSHFileInfoByte = ^SHFileInfoByte;
      _SHFileInfoByte = record
        hIcon: Integer;
        iIcon: Integer;
        dwAttributes: Integer;
        szDisplayName: array[0..259] of char;
        szTypeName: array[0..79] of char;
      end;  SHFileInfoByte = _SHFileInfoByte;
    type PIDLSTRUCT = ^IDLSTRUCT;
      _IDLSTRUCT = record
        pidl: PItemIDList;
        bWatchSubFolders: Integer;
      end;
      IDLSTRUCT = _IDLSTRUCT;function SHNotify_Register(hWnd: Integer): Bool;
    function SHNotify_UnRegister: Bool;
    function SHEventName(strPath1, strPath2: string; lParam: Integer): string;function SHChangeNotifyDeregister(hNotify: integer): integer; stdcall; external 'Shell32.dll' index 4;
    function SHChangeNotifyRegister(hWnd, uFlags, dwEventID, uMSG, cItems: LongWord; lpps: PIDLSTRUCT): integer; stdcall; external 'Shell32.dll' index 2;
    function SHGetFileInfoPidl(pidl: PItemIDList;
      dwFileAttributes: Integer;
      psfib: PSHFILEINFOBYTE;
      cbFileInfo: Integer;
      uFlags: Integer): Integer; stdcall;
    external 'Shell32.dll' name 'SHGetFileInfoA';
    var
      Form1: TForm1;
      m_hSHNotify: Integer;
      m_pidlDesktop: PItemIDList;implementation{uses
     Graphics;
    }
    {$R *.dfm}function SHEventName(strPath1, strPath2: string; lParam: Integer): string;
    var
      sEvent: string;
    begin
      case lParam of //根据参数设置提示消息
        SHCNE_RENAMEITEM: sEvent := '重命名文件' + strPath1 + '为' + strpath2;
        SHCNE_CREATE: sEvent := '建立文件 文件名:' + strPath1;
        SHCNE_DELETE: sEvent := '删除文件 文件名:' + strPath1;
        SHCNE_MKDIR: sEvent := '新建目录 目录名:' + strPath1;
        SHCNE_RMDIR: sEvent := '删除目录 目录名:' + strPath1;
        SHCNE_MEDIAINSERTED: sEvent := strPath1 + '中插入可移动存储介质';
        SHCNE_MEDIAREMOVED: sEvent := strPath1 + '中移去可移动存储介质' + strPath1 + ' ' + strpath2;
        SHCNE_DRIVEREMOVED: sEvent := '移去驱动器' + strPath1;
        SHCNE_DRIVEADD: sEvent := '添加驱动器' + strPath1;
        SHCNE_NETSHARE: sEvent := '改变目录' + strPath1 + '的共享属性';
        SHCNE_ATTRIBUTES: sEvent := '改变文件目录属性 文件名' + strPath1;
        SHCNE_UPDATEDIR: sEvent := '更新目录' + strPath1;
        SHCNE_UPDATEITEM: sEvent := '更新文件 文件名:' + strPath1;
        SHCNE_SERVERDISCONNECT: sEvent := '断开与服务器的连接' + strPath1 + ' ' + strpath2;
        SHCNE_UPDATEIMAGE: sEvent := 'SHCNE_UPDATEIMAGE';
        SHCNE_DRIVEADDGUI: sEvent := 'SHCNE_DRIVEADDGUI';
        SHCNE_RENAMEFOLDER: sEvent := '重命名文件夹' + strPath1 + '为' + strpath2;
        SHCNE_FREESPACE: sEvent := '磁盘空间大小改变';
        SHCNE_ASSOCCHANGED: sEvent := '改变文件关联';
      else
        sEvent := '未知操作' + IntToStr(lParam);
      end;
      Result := sEvent;
    end;function SHNotify_Register(hWnd: Integer): Bool;
    var
      ps: IDLSTRUCT;
    begin
    {$R-}
      Result := False;
      if m_hSHNotify = 0 then
      begin
     //获取桌面文件夹的Pidl
        if SHGetSpecialFolderLocation(0, CSIDL_DESKTOP, m_pidlDesktop) <> NOERROR then
        begin
          form1.close;
        end;
        if Boolean(m_pidlDesktop) then
        begin
          ps.bWatchSubFolders := 1;
          ps.pidl := m_pidlDesktop;
       // 利用SHChangeNotifyRegister函数注册系统消息处理
          m_hSHNotify := SHChangeNotifyRegister(hWnd, (SHCNF_TYPE or SHCNF_IDLIST),
            (SHCNE_ALLEVENTS or SHCNE_INTERRUPT),
            WM_SHNOTIFY, 1, @ps);
          Result := Boolean(m_hSHNotify); //mmmmmmmm
        end
        else
       // 如果出现错误就使用 CoTaskMemFree函数来释放句柄
          CoTaskMemFree(m_pidlDesktop);
      end;
    {$R+ }
    end;function SHNotify_UnRegister: Bool;
    begin
      Result := False;
      if Boolean(m_hSHNotify) then
      begin
       //取消系统消息监视,同时释放桌面的Pidl
        if Boolean(SHChangeNotifyDeregister(m_hSHNotify)) then
        begin
    {$R-}
          m_hSHNotify := 0;
          CoTaskMemFree(m_pidlDesktop);
          Result := True;
    {$R-}
        end;
      end;
    end;procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
    begin
      if Boolean(m_pidlDesktop) then
        SHNotify_Unregister;
    end;procedure TForm1.Button1Click(Sender: TObject);
    begin
      m_hSHNotify := 0;
      if SHNotify_Register(self.Handle) then
      begin //注册Shell监视
        ShowMessage('Shell监视程序成功注册');
        Button1.Enabled := False;
      end
      else
        ShowMessage('Shell监视程序注册失败');
    end;procedure TForm1.WMShellReg(var Message: TMessage);
    var
      strPath1, strPath2: string;
      charPath: array[0..259] of char;
      pidlItem: PSHNOTIFYSTRUCT;
    begin
      pidlItem := PSHNOTIFYSTRUCT(Message.wParam);
      //获得系统消息相关得路径
      SHGetPathFromIDList(pidlItem.dwItem1, charPath);
      strPath1 := charPath;
      SHGetPathFromIDList(pidlItem.dwItem2, charPath);
      strPath2 := charPath;
      Memo1.Lines.Add(SHEvEntName(strPath1, strPath2, Message.lParam) + chr(13) + chr(10));
    end;end.
      

  2.   

      unit   Unit1;   
       
      interface   
       uses   
          Windows,   Messages,   SysUtils,   Variants,   Classes,   Graphics,   Controls,   Forms,   
          Dialogs,   AppEvnts,   ExtCtrls,   StdCtrls;   
        
      type   
          TForm1   =   class(TForm)   
              Label1:   TLabel;   
          private   
              {   Private   declarations   }   
              procedure WMDeviceChange(var Msg:TMessage);message WM_DEVICECHANGE;  
          public   
              {   Public   declarations   }   
          end;   
        
      var   
          Form1:   TForm1;   
        
      implementation   
        
      {$R   *.dfm}   
        
    procedure TForm1.WMDeviceChange(var Msg:TMessage);
    var
     myMsg: String;
    begin
      Case Msg.WParam of
      32768:
      begin
         myMsg := 'U盘插入';
         lbl1.Caption := myMsg;
      end;
      32772:
      begin
         myMsg := 'U盘拔出';
         lbl1.Caption := myMsg;
      end;
      end;
    end;
      

  3.   

    上面是优盘插入、拔出的消息
    这个是获取优盘盘符的代码
    procedure TForm1.FormCreate(Sender: TObject); 
    var 
        buf:array [0..MAX_PATH-1] of char; 
        m_Result:Integer; 
        i:Integer; 
        str_temp:string; 
    begin 
      m_Result:=GetLogicalDriveStrings(MAX_PATH,buf); 
      for i:=0 to (m_Result div 4) do 
      begin 
            str_temp:=string(buf[i*4]+buf[i*4+1]+buf[i*4+2]); 
             if getdrivetype(pchar(str_temp)) = DRIVE_REMOVABLE  then 
             begin 
                showmessage(str_temp+’盘为U盘’); 
                ListBox1.Items.Add(str_temp); 
            end; 
      end; 
      

  4.   

    unit USBCheck;interfaceuses
      Windows, Messages, SysUtils, Classes, Forms;type
      PDevBroadcastHdr = ^DEV_BROADCAST_HDR;
      DEV_BROADCAST_HDR = packed record
        dbch_size: DWORD;
        dbch_devicetype: DWORD;
        dbch_reserved: DWORD;
      end;  PDevBroadcastDeviceInterface = ^DEV_BROADCAST_DEVICEINTERFACE;
      DEV_BROADCAST_DEVICEINTERFACE = record
        dbcc_size: DWORD;
        dbcc_devicetype: DWORD;
        dbcc_reserved: DWORD;
        dbcc_classguid: TGUID;
        dbcc_name: short;
      end;const
      GUID_DEVINTERFACE_USB_DEVICE: TGUID   =   '{A5DCBF10-6530-11D2-901F-00C04FB951ED}';
      DBT_DEVICEARRIVAL                     =   $8000;                     //   system   detected   a   new   device
      DBT_DEVICEREMOVECOMPLETE              =   $8004;                     //   device   is   gone
      DBT_DEVTYP_DEVICEINTERFACE            =   $00000005;             //   device   interface   class
        
    type
      TComponentUSB = class(TComponent)
      private
        FWindowHandle: HWND;
        FOnUSBArrival: TNotifyEvent;
        FOnUSBRemove: TNotifyEvent;
        procedure WndProc(var Msg: TMessage);
        function USBRegister: Boolean;
      protected
        procedure WMDeviceChange(var Msg: TMessage); dynamic;
      public
        constructor Create(AOwner: TComponent); override;
        destructor Destroy; override;
      published
        property OnUSBArrival: TNotifyEvent read FOnUSBArrival write FOnUSBArrival;
        property OnUSBRemove: TNotifyEvent read FOnUSBRemove write FOnUSBRemove;
      end;procedure Register;implementationprocedure Register;
    begin
      RegisterComponents('GrayStorm', [TComponentUSB]);
    end;constructor TComponentUSB.Create(AOwner: TComponent);
    begin
      inherited Create(AOwner);
      FWindowHandle := AllocateHWnd(WndProc);
      USBRegister;
    end;destructor TComponentUSB.Destroy;
    begin
      DeallocateHWnd(FWindowHandle);
      inherited Destroy;
    end;procedure TComponentUSB.WndProc(var Msg: TMessage);
    begin
      if (Msg.Msg = WM_DEVICECHANGE) then
      begin
        try
          WMDeviceChange(Msg);
        except
          Application.HandleException(Self);
        end;
      end
      else Msg.Result := DefWindowProc(FWindowHandle, Msg.Msg, Msg.wParam, Msg.lParam);
    end;procedure TComponentUSB.WMDeviceChange(var Msg: TMessage);
    var
      devType: Integer;
      Datos: PDevBroadcastHdr;
    begin
      if (Msg.wParam = DBT_DEVICEARRIVAL) or (Msg.wParam = DBT_DEVICEREMOVECOMPLETE)   then
      begin
        Datos := PDevBroadcastHdr(Msg.lParam);
        devType := Datos^.dbch_devicetype;
        if devType = DBT_DEVTYP_DEVICEINTERFACE then
        begin   //   USB   Device
          if Msg.wParam = DBT_DEVICEARRIVAL then
          begin
            if Assigned(FOnUSBArrival) then
              FOnUSBArrival(Self);
          end
          else begin
              if Assigned(FOnUSBRemove) then
                FOnUSBRemove(Self);
          end;
        end;
      end;
    end;function TComponentUSB.USBRegister: Boolean;
    var
      dbi: DEV_BROADCAST_DEVICEINTERFACE;
      Size: Integer;
      r: Pointer;
    begin
      Result := False;
      Size := SizeOf(DEV_BROADCAST_DEVICEINTERFACE);
      ZeroMemory(@dbi, Size);
      dbi.dbcc_size := Size;
      dbi.dbcc_devicetype := DBT_DEVTYP_DEVICEINTERFACE;
      dbi.dbcc_reserved := 0;
      dbi.dbcc_classguid := GUID_DEVINTERFACE_USB_DEVICE;
      dbi.dbcc_name := 0;  r := RegisterDeviceNotification(FWindowHandle, @dbi, DEVICE_NOTIFY_WINDOW_HANDLE);
      if Assigned(r) then Result := true;
    end;
        
    end.这个挺好用的。嘿嘿
      

  5.   

    //声明:
    GetDriveType(
      lpRootPathName: PChar {磁盘根目录}
    ): UINT;//返回值:
    DRIVE_UNKNOWN     = 0; {未知}
    DRIVE_NO_ROOT_DIR = 1; {可移动磁盘}
    DRIVE_REMOVABLE   = 2; {软盘}
    DRIVE_FIXED       = 3; {本地硬盘}
    DRIVE_REMOTE      = 4; {网络磁盘}
    DRIVE_CDROM       = 5; {CD-ROM}
    DRIVE_RAMDISK     = 6; {RAM 磁盘}
    下面是从1-26个字母作为盘符,检测是否存在,然后你可以再判断返回值是否是可移动磁盘用来获得盘符!var
      Drives: DWord;
      i: Integer;
      c: Cardinal;
      s:string;
    begin
      Drives := GetLogicalDrives;
      Memo1.Clear;
      for i := 0 to 25 do {检测26个字母共盘符}
        if LongBool(Drives and ($0001 shl i)) = True then
          c := GetDriveType(Char(Ord('A')+i));
          if IntToStr(c)=1 then  //如果是1,则是移动磁盘!
          Memo1.Lines.Add(Char(Ord('A')+i) + ':\');
    end;U盘就是可移动磁盘了。。返回1