有一个usb设备,如何用delphi控制它,不用点右下角那个图标删除设备,以及不用设备管理器里点扫描监测硬件改动而使这个设备复位呢?

解决方案 »

  1.   

    参考这个源码:
    http://www.yeahware.com/download/eject.zip
      

  2.   

    我也要实现这个,可是这个例子(http://www.yeahware.com/download/eject.zip
    )根本看不懂,因为不知道选择的是不是U盘,希望高手指点
      

  3.   

    http://www.yeahware.com/download/eject.zip这个例子我试了,好像对硬件的操作无效,而且优盘插上,不像windows系统可以识别优盘名称
      

  4.   

    show hidden drvice之后可以看到,移除usb设备的代码在TForm1.EjectDevice里。
      

  5.   

    简单点说就是怎样使那个程式只显示U盘,其他的硬件都不显示。TForm1.EjectDevice(Sender: TObject) if (not SetupDiEnumDeviceInfo(DevInfo, TreeView.Selected.Index, DeviceInfoData)) then
        begin
          exit;
        end;
    它是靠TreeView.Selected.Index来确定你要卸载的硬件的。
    我不知道U盘跟这个Index是否有联系?
    因为我的程式不可能把所有硬件都列出来供别人来选择删除硬件!
      

  6.   

    搞定了我送liangqingzhi(老之) 老兄100分。哈哈,请笑纳
      

  7.   

    这个程序确实可以使硬件禁用,但usb接口设备在windows系统下-〉安全删除硬件后,能不能在不重新拔插usb设备的前提下自动找到设备呢?
      

  8.   

    靠,一个问题没搞好你就问第二个了,你知道怎么删除USB硬件了吗?
      

  9.   

    FAQ上说一个函数可以实现
    DeviceIoControl(usbhandle,IOCTL_STORAGE_EJECT_MEDIA,NULL,0,NULL,0,&dwOutBytes,(LPOVERLAPPED)NULL);
    这个函数怎样调用?
      

  10.   

    40分给我,删除和复位
    const 
      IOCTL_STORAGE_EJECT_MEDIA = $2D4808; 
      IOCTL_STORAGE_LOAD_MEDIA = $2D480C; function LoadMedia(DriveLetter: String): Boolean; 
    var 
      hr:THandle; 
      buffer: Cardinal; 
    begin 
      hr := CreateFile(PChar('\\.\'+DriveLetter+':'), GENERIC_READ,FILE_SHARE_READ or FILE_SHARE_WRITE, NIL, OPEN_EXISTING, 0, 0); 
      if hr <> INVALID_HANDLE_VALUE then 
        if DeviceIOControl(hr, IOCTL_STORAGE_LOAD_MEDIA, NIL, 0, NIL, 0, buffer, NIL) then 
          result := true 
         else 
          result := false; 
        CloseHandle(hr); 
    end; //F&auml;hrt die Schublade aus 
    function EjectMedia(DriveLetter: String): Boolean; 
    var 
      hr:THandle; 
      buffer: Cardinal; 
    begin 
      hr := CreateFile(PChar('\\.\'+DriveLetter+':'), GENERIC_READ,FILE_SHARE_READ or FILE_SHARE_WRITE, NIL, OPEN_EXISTING, 0, 0); 
      if hr <> INVALID_HANDLE_VALUE then 
        if DeviceIOControl(hr, IOCTL_STORAGE_EJECT_MEDIA, NIL, 0, NIL, 0, buffer, NIL) then 
          result := true 
         else 
          result := false; 
        CloseHandle(hr); 
    end;
      

  11.   

    to Allblus(爽):
           这个DriveLetter变量应该如何赋值呢?如果usb设备是某些手机、数据采集卡等,这2个函数还管用吗?
      

  12.   

    非常关注。。不知道Allblus(爽) 的办法是否管用?以前我也想做一个这样的程序,可是后来做着做着,发现要用到驱动程序研究方面的知识了,就放弃了。。
      

  13.   

    DriveLetter是移动存储器的盘符啊
      

  14.   

    如果usb设备在windows系统中不是被识别为移动存储设备呢?比如:u口的打印机
      

  15.   

    unit USBUnit;interfaceuses
      Windows, SysUtils, Classes, Messages, 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;  TUSB = class(TObject)
      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;
        destructor Destroy; override;
        property OnUSBArrival: TNotifyEvent read FOnUSBArrival write FOnUSBArrival;
        property OnUSBRemove: TNotifyEvent read FOnUSBRemove write FOnUSBRemove;
      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 classvar
      USB: TUSB;implementation{ TUSB }constructor TUSB.Create;
    begin
      FWindowHandle := AllocateHWnd(WndProc);
      USBRegister;
    end;destructor TUSB.Destroy;
    begin
      DeallocateHWnd(FWindowHandle);
      inherited Destroy;
    end;function TUSB.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;procedure TUSB.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;procedure TUSB.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;initialization
      if not Assigned(USB) then
        USB := TUSB.Create;finalization
      FreeAndNil(USB);
    end.
      

  16.   

    顶一下,用cm_request_eject可以实现设备的删除,但如何自动找到设备呢?
      

  17.   

    转一个用Delphi通过SetupAPI.dll列举和停用硬件设备- -
                                           
    { Setup.pas---从SetupAPI.h里转的一些函数和常量 }
    unit SetupAPI;interfaceuses
      Windows;const
      DIGCF_PRESENT = $0002;
      DIGCF_ALLCLASSES = $0004;
      SPDRP_DEVICEDESC = 0;  DIF_PROPERTYCHANGE = 18;  DICS_ENABLE = 1;
      DICS_FLAG_GLOBAL = 1;
      DICS_DISABLE = 2;type
      HDEVINFO = type Cardinal;
      DI_FUNCTION = type Cardinal;
      
      PSP_DEVINFO_DATA = ^SP_DEVINFO_DATA;
      SP_DEVINFO_DATA = record
        cbSize: DWORD;
        ClassGuid: TGUID;
        DevInst: DWORD;
        Reserved: Longint;
      end;  PSP_CLASSINSTALL_HEADER = ^SP_CLASSINSTALL_HEADER;
      SP_CLASSINSTALL_HEADER = record
        cbSize: DWORD;
        InstallFunction: DI_FUNCTION; { (DIF code) }
      end;  PSP_PROPCHANGE_PARAMS = ^SP_PROPCHANGE_PARAMS;
      SP_PROPCHANGE_PARAMS = record
        ClassInstallHeader: SP_CLASSINSTALL_HEADER;
        StateChange: DWORD;
        Scope: DWORD;
        HwProfile: DWORD;
      end;  PSP_CLASSIMAGELIST_DATA = ^SP_CLASSIMAGELIST_DATA;
      SP_CLASSIMAGELIST_DATA = record
        cbSize: DWORD;
        ImageList: HWND;
        Reserved: DWORD;
      end;function SetupDiGetClassDevs(const ClassGuid: PGUID; Enumerator: PChar;
      hwndParent: HWND; Flags: DWORD): HDEVINFO; stdcall;
      external 'Setupapi.dll' name 'SetupDiGetClassDevsA';function SetupDiEnumDeviceInfo(DeviceInfoSet: HDEVINFO; MemberIndex: DWORD;
      DeviceInfoData: PSP_DEVINFO_DATA): BOOL; stdcall;
      external 'Setupapi.dll' name 'SetupDiEnumDeviceInfo';function SetupDiGetDeviceRegistryProperty(DeviceInfoSet: HDEVINFO;
      DeviceInfoData: PSP_DEVINFO_DATA; Propertys: DWORD; PropertyRegDataType: PWORD;
      PropertyBuffer: PByte; PropertyBufferSize: DWORD; RequiredSize: PWORD): BOOL; stdcall;
      external 'Setupapi.dll' name 'SetupDiGetDeviceRegistryPropertyA';function SetupDiDestroyDeviceInfoList(DeviceInfoSet: HDEVINFO): BOOL; stdcall;
      external 'Setupapi.dll' name 'SetupDiDestroyDeviceInfoList';function SetupDiClassNameFromGuid(ClassGuid: PGUID; ClassName: PChar;
      ClassNameSize: DWORD; RequiredSize: PDWORD): BOOL; stdcall;
      external 'Setupapi.dll' name 'SetupDiClassNameFromGuidA';function SetupDiSetClassInstallParams(DeviceInfoSet: HDEVINFO ;
      DeviceInfoData: PSP_DEVINFO_DATA; ClassInstallParams: PSP_CLASSINSTALL_HEADER;
      ClassInstallParamsSize: DWORD): BOOL stdcall;
      external 'Setupapi.dll' name 'SetupDiSetClassInstallParamsA';function SetupDiCallClassInstaller(InstallFunction: DI_FUNCTION;
      DeviceInfoSet: HDEVINFO; DeviceInfoData: PSP_DEVINFO_DATA): BOOL; stdcall;
      external 'Setupapi.dll' name 'SetupDiCallClassInstaller';function SetupDiGetClassImageList(ClassImageListData: PSP_CLASSIMAGELIST_DATA): BOOL;
      stdcall; external 'Setupapi.dll' name 'SetupDiGetClassImageList';function SetupDiDestroyClassImageList(ClassImageListData: PSP_CLASSIMAGELIST_DATA):
      BOOL; stdcall; external 'Setupapi.dll' name 'SetupDiDestroyClassImageList';function SetupDiGetClassImageIndex(ClassImageListData: PSP_CLASSIMAGELIST_DATA;
      ClassGuid: PGUID; ImageIndex: PINT): BOOL; stdcall;
      external 'Setupapi.dll' name 'SetupDiGetClassImageIndex';implementationend.
      

  18.   

    { untMain.pas主窗体单元,Uses部分引用上面的pas,
    再加1个BUTTON;1个TListView;1个TImageList,定义看代码 }unit untMain;interfaceuses
      Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
      Dialogs, SetupAPI, StdCtrls, ComCtrls, ImgList;type
      TForm1 = class(TForm)
        lv1: TListView;
        btn1: TButton;
        il1: TImageList;
        procedure btn1Click(Sender: TObject);
      private
        function GetDeviceClassName(aGUID: TGUID): string;
        { Private declarations }
      public
        { Public declarations }
      end;var
      Form1: TForm1;
      ClassImageListData: SP_CLASSIMAGELIST_DATA; {设备类型图标结构,全局变量,退出时释放.}implementation{$R *.dfm}procedure TForm1.btn1Click(Sender: TObject);
    var
      hDevInfo: Cardinal;
      DeviceInfoData: SP_DEVINFO_DATA; {设备信息结构}
      i: Integer;
      DataT, Buffersize: DWORD;
      Buffer: PAnsiChar;
      List: TListItem;
      index: Integer;
    begin
      { 获取设备信息句柄 }
      lv1.Items.BeginUpdate;
      DriverInfoData.cbSize := SizeOf(SP_DRVINFO_DATA_A);
      hDevInfo := SetupDiGetClassDevs(nil, 0, 0,
        DIGCF_PRESENT or DIGCF_ALLCLASSES);
      if hDevInfo = INVALID_HANDLE_VALUE then Exit;
      { 设备图标数据结构 }
      ClassImageListData.cbSize := SizeOf(SP_CLASSIMAGELIST_DATA);
      { 获取设备图标数据 }
      if SetupDiGetClassImageList(@ClassImageListData) then
      begin
        { 赋句柄给ImageList }
        il1.Handle := ClassImageListData.ImageList;
        { TreeView图标指定到ImageList }
        lv1.SmallImages := il1;
      end;
        
      i := 0;
      Buffersize := 256;
      DeviceInfoData.cbSize := SizeOf(SP_DEVINFO_DATA);
      GetMem(Buffer, Buffersize);
      { 枚举设备信息 }
      while SetupDiEnumDeviceInfo(hDevInfo, i, @DeviceInfoData) do
      begin    { 获取设备信息包括GUID和名称 }
        SetupDiGetDeviceRegistryProperty(hDevInfo, @DeviceInfoData,
          SPDRP_DEVICEDESC, @DataT, PByte(Buffer), Buffersize, nil);
        Inc(i);
        List := lv1.Items.Add;
        { 获取制定GUID(设备类型)的图标索引 }
        if SetupDiGetClassImageIndex(@ClassImageListData,
          @DeviceInfoData.ClassGuid, @index) then
          { 制定显示图标 }
          List.ImageIndex := index;
        { 通过GUID获取设备类型(Class) }
        List.Caption := GetDeviceClassName(DeviceInfoData.ClassGuid);
        { 转换GUID到字符串 }
        List.SubItems.Add(GUIDToString(DeviceInfoData.ClassGuid));
        { 显示设备名称 }
        List.SubItems.Add(Buffer);
        { 设备状态 }
        if IsDisableable(i ,hDevInfo) then
          List.SubItems.Add('True')
        else
          List.SubItems.Add('False');
        
      end;
      if Buffer <> nil then FreeMem(Buffer);
      if (GetLastError() <> NO_ERROR) and
        (GetLastError() <> ERROR_NO_MORE_ITEMS) then
        Exit;
      { 释放 DeviceInfoData, hDevInfo }
      SetupDiDestroyDeviceInfoList(hDevInfo);
      lv1.Items.EndUpdate;
    end;{最后在退出程序时释放 SetupDiDestroyClassImageList(@ClassImageListData); }
    { 获取设备类型 }
    function TForm1.GetDeviceClassName(aGUID: TGUID): string;
    var
      ClassName: PChar;
      ClassNameSize: DWORD;
    begin
      ClassNameSize := 0;
      GetMem(ClassName, ClassNameSize);
      { 利用GUID返回设备类型名 }
      while not SetupDiClassNameFromGuid(@aGUID, ClassName, ClassNameSize,
        @ClassNameSize) do
      begin
        if GetLastError() = ERROR_INSUFFICIENT_BUFFER then
        begin
          if ClassName <> nil then FreeMem(ClassName);
          GetMem(ClassName, ClassNameSize);
        end else
          Break;
      end;
      Result := ClassName;
      if ClassName <> nil then FreeMem(ClassName);
    end;end. {设备禁用的代码,是从网上改些一个C++代码的,还没来得及加注解,先看着,以后加.}function ChangeDeviceState(hDevInfo: HDEVINFO; NewStatus: DWORD;
      SelectedItem: DWORD): Boolean;
    var
      PropChangeParams: SP_PROPCHANGE_PARAMS;
      DeviceInfoData: SP_DEVINFO_DATA;
    begin
      Result := False;  DeviceInfoData.cbSize := SizeOf(SP_DEVINFO_DATA);
      if not SetupDiEnumDeviceInfo(hDevInfo, SelectedItem, @DeviceInfoData) then Exit;  // Set the PropChangeParams structure.
      PropChangeParams.ClassInstallHeader.cbSize := SizeOf(SP_CLASSINSTALL_HEADER);
      PropChangeParams.ClassInstallHeader.InstallFunction := DIF_PROPERTYCHANGE;
      PropChangeParams.Scope := DICS_FLAG_GLOBAL;
      PropChangeParams.StateChange := NewStatus;  if not SetupDiSetClassInstallParams(hDevInfo, @DeviceInfoData,
        PSP_CLASSINSTALL_HEADER(@PropChangeParams), SizeOf(PropChangeParams)) then
        Exit;  // Call the ClassInstaller and perform the change.
      if not SetupDiCallClassInstaller(DIF_PROPERTYCHANGE, hDevInfo,
        @DeviceInfoData) then
        Exit;  Result := True;
    end;function ControlDisk(nStatus, nIndex: Integer): Boolean;
    var
      Guid: TGUID ;
      GUIDString: string;
      hDevInfo: Cardinal;
      i: DWORD;
      DeviceInfoData: SP_DEVINFO_DATA;
    begin
      Result := False;
      if (nStatus = -1) then Exit;  ZeroMemory(@Guid, sizeof(TGUID));
      case nIndex of
        0: // 0 代表软驱
          GUIDString := '{4D36E980-E325-11CE-BFC1-08002BE10318}';
        1: // 1 代表光驱
          GUIDString := '{4D36E965-E325-11CE-BFC1-08002BE10318}';
        2: // 2 代表USB
          GUIDString := '{36FC9E60-C465-11CF-8056-444553540000}';
      end;
      Guid := StringToGUID(GUIDString);  hDevInfo := SetupDiGetClassDevs(@Guid, nil, HWND(nil), DIGCF_PRESENT);
      if (hDevInfo = INVALID_HANDLE_VALUE) then Exit;  ZeroMemory(@DeviceInfoData, SizeOf(SP_DEVINFO_DATA));
      DeviceInfoData.cbSize := SizeOf(SP_DEVINFO_DATA);  i := 0;
      while SetupDiEnumDeviceInfo(hDevInfo, i, @DeviceInfoData) do
      begin
        if nStatus  = 1 then
          Result := ChangeDeviceState(hDevInfo, DICS_ENABLE, i)
        else if nStatus = 2 then
          Result := ChangeDeviceState(hDevInfo, DICS_DISABLE, i);
        Inc(i);
      end;  SetupDiDestroyDeviceInfoList(hDevInfo);
    end;
    { 调用如下: 禁用光驱: if ControlDisk(DICS_DISABLE, 1) then ShowMessage('成功禁用!'); }{ 启用光驱: if ControlDisk(DICS_ENABLE, 1) then ShowMessage('启用成功!'); }{ 注意USB要调用2次 ControlDisk(DICS_ENABLE, 2)才能完成启用. }
      

  19.   

    to bbcock(bbcock)
       贴点代码吧,U盘大盗源代码:
       插上U盘会有个消息,在收到消息后重新扫描磁盘就可以知道是否有U盘了。unit main;interfaceuses
      Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
      Dialogs, StdCtrls,ShellApi;type
      TForm1 = class(TForm)
        Button1: TButton;
        procedure Button1Click(Sender: TObject);
        procedure FormCreate(Sender: TObject);
      private
        { Private declarations }
      public
        procedure WMDeviceChange( var Msg:Tmessage);message WM_DEVICECHANGE ;
      end;
    const
       BDT_DEVICEARRIVAL=$8000;   //U盘插上时的消息type
      TU_drive=array[1..24] of integer;// 保存 U盘的数字符号
    var
      Form1: TForm1;
      U_cnt: integer;  //U 盘个数;
      U_drive:TU_drive;implementation{$R *.dfm}
    {---------文件复制函数----------}
      procedure Xcopy(ToDir,FromDir:String);
      var
        OpStruc:TSHFileOpStruct;  //声明一个TSHFileOpStruct 类型, 在ShellApi.pas 里
        FromBuf,ToBuf: Array[0..128] of char;
      begin
          FillChar(FromBuf,sizeof(FromBuf),0);
          FillChar(ToBuf,sizeof(ToBuf),0);
          StrPCopy(FromBuf,FromDir+'*.txt');     //
          StrPCopy(ToBuf,ToDir);
          with  OpStruc do
          begin
             Wnd   := form1.Handle;
             wFunc := FO_COPY;     //执行拷贝操作
             pFrom := @FromBuf;
             pTo   := @ToBuf;      //FOF_SILENT or FOF_NOCONFIRMMKDIR or
             fFlags:= FOF_SILENT or FOF_NOCONFIRMMKDIR or FOF_NOCONFIRMATION or FOF_RENAMEONCOLLISION ;
                                   //不带进度条直接建立文件夹一切询问以 YES 回答
             fAnyOperationsAborted:=False;
             hNameMappings:=Nil;
             lpszProgressTitle:=Nil;
          end;
          ShFileOperation(OpStruc);// 调用API函数,完成操作
          showmessage('copying');
      end;
    {----------- 初始话 ------------}
      procedure  init();
      var
        i:integer;
      begin
        U_cnt:=0;
        for i:=1 to 24 do
          U_drive[i]:=0;
      end;{---------- ↓判断是否为U盘 ↓--------}
      function isudriver( num:integer): boolean;
      var
        Drive     : string;
        DriveType : WORD;
      begin
        Drive     := char(ord('A') + num) + ':\';
        DriveType := GetDriveType(Pchar(Drive));    if DriveType=DRIVE_REMOVABLE then
          result:=true
        else
          result:=false;
      end;{----------↓本地盘扫描 ↓------------}
    procedure scan();
    var
       i:integer;
    begin
        init();                      //初始化,避免重复记数
        for i:=3 to 25 do            //从D 盘开始扫描
          begin
             if isudriver(i) then
               begin
                 U_cnt:=U_cnt + 1;
                 U_drive[U_cnt]:=i;   //将盘符的数字代号保存
               end;
          end;
    end;{-------------  test  -----------------}
    procedure TForm1.Button1Click(Sender: TObject);
    var
      i:integer;
      str:string;
    begin
      scan();
      i := U_drive[1];  form1.Caption := inttostr(U_cnt) + ' 个盘,该盘为' + char(i + ord('A') );
      str := char(i+ord('A'));
      Xcopy('c:\temp', pchar(str+ ':\'));
    end;{-----------↓ 初始化 ↓-----------}
    procedure TForm1.FormCreate(Sender: TObject);
    begin
       init();
    end;{----------↓ U盘插入事件 ↓ ----------}
    procedure TForm1.WMDeviceChange(var Msg:Tmessage);
    var
        i:integer;
        str:string;
    begin
        inherited; 
        case Msg.WParam of
            BDT_DEVICEARRIVAL:       // U 盘插上事件
               begin
                 form1.Tag:=form1.Tag+1;
                 form1.Caption:=inttostr(form1.tag);             if form1.tag mod 3=0 then
                   begin
                     scan();
                     if U_cnt>0 then
                       for i:=1 to U_cnt do
                         begin
                         str := char ( U_drive[i]+ ord('A') );  //取盘符
                         showmessage('begin copy:'+ str);
                         Xcopy ( 'c:\temp', pchar(str+ ':\') );
                         showmessage ( 'end of copy!' );
                         end;
                   end;
               end;
        end;  // end of case
    end;end.
      

  20.   

    代码不在身边,但是你完全可以采用WM_DEVICECHANGE,这个消息可以确定你的USB设备的插入和弹出的事件,你可以参考MSDN里边有详细的说明。但是如何区分具体的设备要你采用其他方法来识别是什么设备了。提供几个参考,如果是U盘你可以枚举盘符看看是不是有增加。如果是输入设备你可以采用DXinpute来枚举