procedure TForm1.TreeViewChange(Sender: TObject; Node: TTreeNode);
begin
with MainMenu, TreeView.Selected do
begin
// Clear the Menu Items.
Items[1][0].enabled := false;
Items[1][1].enabled := false;
Items[1][2].enabled := false;
if (IsDisabled(Index, DevInfo)) then
begin
Items[1][0].enabled := true
end else
begin
if (CheckStatus(Index, DevInfo, DN_DISABLEABLE)) then Items[1][1].enabled := true
end;
if (CheckStatus(Index, DevInfo, DN_REMOVABLE)) then
begin
Items[1][2].enabled := true;
end;
end;
end;
procedure TForm1.TreeViewDblClick(Sender: TObject);
begin
with TreeView.Selected do
begin
if (IsDisabled(Index, DevInfo)) then
begin
ChangeEnableDevice(Self);
end else
begin
if (CheckStatus(Index, DevInfo, DN_DISABLEABLE and DN_REMOVABLE)) then
begin
MessageBox(Handle, 'Device is disableable and ejectable. Please use MainMenu.', 'Change unknown', MB_OK);
end
else
begin
if (CheckStatus(Index, DevInfo, DN_DISABLEABLE)) then ChangeDisableDevice(Self);
if (CheckStatus(Index, DevInfo, DN_REMOVABLE)) then EjectDevice(Self);
end;
end;
end;
end;
procedure TForm1.ChangeEnableDevice(Sender: TObject);
begin
if (MessageBox(Handle, 'Enable this Device?', 'Change Device Status', MB_OKCANCEL) = IDOK) then
begin
if (StateChange(DICS_ENABLE, TreeView.Selected.Index, DevInfo)) then EnumAddDevices(ShowHidden, TreeView, DevInfo);
end;
end;
procedure TForm1.ChangeDisableDevice(Sender: TObject);
begin
if (MessageBox(Handle, 'Disable this Device?', 'Change Device Status', MB_OKCANCEL) = IDOK) then
begin
if (StateChange(DICS_DISABLE, TreeView.Selected.Index, DevInfo)) then EnumAddDevices(ShowHidden, TreeView, DevInfo);
end;
end;
procedure TForm1.EjectDevice(Sender: TObject);
var
DeviceInfoData: TSPDevInfoData;
Status, Problem: DWord;
VetoType: TPNPVetoType;
VetoName: array[0..256] of Char;
begin
if (MessageBox(Handle, 'Eject this Device?', 'Eject Device', MB_OKCANCEL) = IDOK) then
begin
DeviceInfoData.cbSize := SizeOf(TSPDevInfoData);
// Get a handle to the Selected Item.
if (not SetupDiEnumDeviceInfo(DevInfo, TreeView.Selected.Index, DeviceInfoData)) then
begin
exit;
end;
if (CM_Get_DevNode_Status(@Status, @Problem, DeviceInfoData.DevInst, 0) <> CR_SUCCESS) then
begin
exit;
end;
VetoName[0] := #0;
case CM_Request_Device_Eject(DeviceInfoData.DevInst, VetoType, @VetoName, SizeOf(VetoName), 0) of
CR_SUCCESS:
begin
EnumAddDevices(ShowHidden, TreeView, DevInfo);
end;
CR_REMOVE_VETOED:
begin
MessageBox(Handle, PChar('Failed to eject the Device (Veto: ' + VetoName + ')'), 'Vetoed', MB_OK);
end;
else
begin
MessageBox(Handle, PChar('Failed to eject the Device (' + SysErrorMessage(GetLastError) + ')'), 'Failure', MB_OK);
end;
end;
end;
end;
procedure TForm1.WMDeviceChange(var Msg: TMessage);
const
DBT_DEVNODES_CHANGED = $0007;
begin
case Msg.wParam of
DBT_DEVNODES_CHANGED:
begin
GetDevInfo;
EnumAddDevices(ShowHidden, TreeView, DevInfo);
end;
end;
end;
function TForm1.ConstructDeviceName(DeviceInfoSet: hDevInfo;
DeviceInfoData: TSPDevInfoData; Buffer: PChar; dwLength: DWord): Boolean;
const
UnknownDevice = '<Unknown Device>';
begin
if (not GetRegistryProperty(DeviceInfoSet, DeviceInfoData, SPDRP_FRIENDLYNAME, Buffer, dwLength)) then
begin
if (not GetRegistryProperty(DeviceInfoSet, DeviceInfoData, SPDRP_DEVICEDESC, Buffer, dwLength)) then
begin
if (not GetRegistryProperty(DeviceInfoSet, DeviceInfoData, SPDRP_CLASS, Buffer, dwLength)) then
begin
if (not GetRegistryProperty(DeviceInfoSet, DeviceInfoData, SPDRP_CLASSGUID, Buffer, dwLength)) then
begin
dwLength := DWord(SizeOf(UnknownDevice));
Buffer := Pointer(LocalAlloc(LPTR, Cardinal(dwLength)));
StrCopy(Buffer, UnknownDevice);
end;
end;
end;
end;
Result := true;
end;
function TForm1.IsClassHidden(ClassGuid: TGuid): Boolean;
var
bHidden: Boolean;
hKeyClass: HKey;
begin
bHidden := false;
hKeyClass := SetupDiOpenClassRegKey(@ClassGuid, KEY_READ);
if (hKeyClass <> 0) then
begin
bHidden := (RegQueryValueEx(hKeyClass, REGSTR_VAL_NODISPLAYCLASS, nil, nil, nil, nil) = ERROR_SUCCESS);
RegCloseKey(hKeyClass);
end;
Result := bHidden;
end;
function TForm1.EnumAddDevices(ShowHidden: Boolean; hwndTree: TTreeView; DevInfo: hDevInfo): Boolean;
var
i, Status, Problem: DWord;
pszText: PChar;
DeviceInfoData: TSPDevInfoData;
iImage: Integer;
begin
TTreeView(hWndTree).Items.BeginUpdate;
DeviceInfoData.cbSize := SizeOf(TSPDevInfoData);
// Clean off all the items in a TreeView.
TTreeView(hWndTree).Items.Clear;
i := 0;
// Enumerate though all the devices.
while SetupDiEnumDeviceInfo(DevInfo, i, DeviceInfoData) do
begin
inc(i);
// Should we display this device, or move onto the next one.
if (CM_Get_DevNode_Status(@Status, @Problem, DeviceInfoData.DevInst, 0) <> CR_SUCCESS) then
begin
break;
end;
if (not (ShowHidden or not(Boolean(Status and DN_NO_SHOW_IN_DM) or IsClassHidden(DeviceInfoData.ClassGuid)))) then
begin
break;
end;
GetMem(pszText, 256);
try
// Get a friendly name for the device.
ConstructDeviceName(DevInfo, DeviceInfoData, pszText, DWord(nil));
// Try to get an icon index for this device.
if (GetClassImageIndex(DeviceInfoData.ClassGuid, @iImage)) then
begin
with TTreeView(hWndTree).Items.AddObject(nil, pszText, nil) do
begin
TTreeView(hWndTree).Items[i-1].ImageIndex := iImage;
TTreeView(hWndTree).Items[i-1].SelectedIndex := iImage;
end;
if (Problem = CM_PROB_DISABLED) then // red (X)
begin
TTreeView(hWndTree).Items[i-1].OverlayIndex := IDI_DISABLED_OVL - IDI_CLASSICON_OVERLAYFIRST;
end else
begin
if (Boolean(Problem)) then // yellow (!)
begin
TTreeView(hWndTree).Items[i-1].OverlayIndex := IDI_PROBLEM_OVL - IDI_CLASSICON_OVERLAYFIRST;
end;
end;
if (Status and DN_NO_SHOW_IN_DM = DN_NO_SHOW_IN_DM) then // Greyed out
begin
TTreeView(hWndTree).Items[i-1].Cut := true;
end;
end;
finally
FreeMem(pszText);
end;
end;
TTreeView(hWndTree).Items.EndUpdate;
Result := true;
end;
procedure TForm1.GetDevInfo;
begin
if (assigned(DevInfo)) then
begin
SetupDiDestroyDeviceInfoList(DevInfo);
SetupDiDestroyClassImageList(ClassImageListData);
end;
// Get a handle to all devices in all classes present on system
DevInfo := SetupDiGetClassDevs(nil, nil, 0, DIGCF_PRESENT or DIGCF_ALLCLASSES);
if (DevInfo = Pointer(INVALID_HANDLE_VALUE)) then
begin
ShowMessage('GetClassDevs');
exit;
end;
// Get the Images for all classes, and bind to the TreeView
ClassImageListData.cbSize := SizeOf(TSPClassImageListData);
if (not SetupDiGetClassImageList(ClassImageListData)) then
begin
ShowMessage('GetClassImageList');
exit;
end;
ImageList.Handle := ClassImageListData.ImageList;
TreeView.Images := ImageList;
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
if (not LoadSetupAPI) then
begin
ShowMessage('Could not load SetupAPI.dll');
exit;
end;
DevInfo := nil;
ShowHidden := false;
GetDevInfo;
// Add the devices to the TreeView window.
EnumAddDevices(ShowHidden, TreeView, DevInfo);
end;
procedure TForm1.FormDestroy(Sender: TObject);
begin
SetupDiDestroyDeviceInfoList(DevInfo);
SetupDiDestroyClassImageList(ClassImageListData);
UnloadSetupApi;
end;
procedure TForm1.mExitClick(Sender: TObject);
begin
Close;
end;
procedure TForm1.mRefreshDisplayClick(Sender: TObject);
begin
EnumAddDevices(ShowHidden, TreeView, DevInfo);
end;
procedure TForm1.mShowHiddenDevicesClick(Sender: TObject);
begin
ShowHidden := not ShowHidden;
MainMenu.Items[2][2].Checked := ShowHidden;
EnumAddDevices(ShowHidden, TreeView, DevInfo);
end;
(*************************************************************
?2004 yeahware software development
http://www.yeahware.com
If this code works, it was written by Markus Fuchs.
If not, I don't know who wrote it. (Paul DiLascia)
Module : eject
Source File Name : ueject.pas
Description : Ejects Firewire/USB HDDs and USB sticks
Compiler : Delphi 5
Platforms : Windows 9x and NT platform
Created : 08.05.2004
Revisions : 19.08.2006 - Update device list with
every DBT_DEVNODES_CHANGED
*************************************************************)
function TForm1.CheckStatus(SelectedItem: DWord; hDevInfo: hDevInfo; StatusFlag: LongWord): Boolean;
var
DeviceInfoData: TSPDevInfoData;
Status, Problem: DWord;
begin
DeviceInfoData.cbSize := SizeOf(TSPDevInfoData);
// Get a handle to the Selected Item.
if (not SetupDiEnumDeviceInfo(hDevInfo, SelectedItem, DeviceInfoData)) then
begin
Result := false;
exit;
end;
if (CM_Get_DevNode_Status(@Status, @Problem, DeviceInfoData.DevInst, 0) <> CR_SUCCESS) then
begin
Result := false;
exit;
end;
Result := ((Status and StatusFlag = StatusFlag) and not (CM_PROB_HARDWARE_DISABLED = Problem));
end;
function TForm1.IsDisabled(SelectedItem: DWord; hDevInfo: hDevInfo): Boolean;
var
DeviceInfoData: TSPDevInfoData;
Status, Problem: DWord;
begin
DeviceInfoData.cbSize := SizeOf(TSPDevInfoData);
// Get a handle to the Selected Item.
if (not SetupDiEnumDeviceInfo(hDevInfo, SelectedItem, DeviceInfoData)) then
begin
Result := false;
exit;
end;
if (CM_Get_DevNode_Status(@Status, @Problem, DeviceInfoData.DevInst, 0) <> CR_SUCCESS) then
begin
Result := false;
exit;
end;
Result := ((Status and DN_HAS_PROBLEM = DN_HAS_PROBLEM) and (CM_PROB_DISABLED = Problem));
end;
function TForm1.StateChange(NewState: DWord; SelectedItem: DWord; hDevInfo: hDevInfo): Boolean;
var
PropChangeParams: TSPPropChangeParams;
DeviceInfoData: TSPDevInfoData;
begin
PropChangeParams.ClassInstallHeader.cbSize := SizeOf(TSPClassInstallHeader);
DeviceInfoData.cbSize := SizeOf(TSPDevInfoData);
// Get a handle to the Selected Item.
if (not SetupDiEnumDeviceInfo(hDevInfo, SelectedItem, DeviceInfoData)) then
begin
Result := false;
ShowMessage('EnumDeviceInfo');
exit;
end;
// Set the PropChangeParams structure.
PropChangeParams.ClassInstallHeader.InstallFunction := DIF_PROPERTYCHANGE;
PropChangeParams.Scope := DICS_FLAG_GLOBAL;
PropChangeParams.StateChange := NewState;
if (not SetupDiSetClassInstallParams(hDevInfo, @DeviceInfoData,
PSPClassInstallHeader(@PropChangeParams), SizeOf(PropChangeParams))) then
begin
Result := false;
ShowMessage('SetClassInstallParams');
exit;
end;
// Call the ClassInstaller and perform the change.
if (not SetupDiCallClassInstaller(DIF_PROPERTYCHANGE, hDevInfo, @DeviceInfoData)) then
begin
Result := false;
ShowMessage('SetClassInstallParams');
exit;
end;
Result := true;
end;
function TForm1.GetClassImageIndex(ClassGuid: TGuid; Index: PInt): Boolean;
begin
Result := SetupDiGetClassImageIndex(ClassImageListData, ClassGuid, Index^);
end;
function TForm1.GetRegistryProperty(PnPHandle: hDevInfo; DevData: TSPDevInfoData; Prop: DWord; Buffer: PChar; dwLength: DWord): Boolean;
var
aBuffer: array[0..256] of Char;
begin
dwLength := 0;
aBuffer[0] := #0;
SetupDiGetDeviceRegistryProperty(PnPHandle, DevData, Prop, Prop, PBYTE(@aBuffer[0]), SizeOf(aBuffer), dwLength);
StrCopy(Buffer, aBuffer);
Result := Buffer^ <> #0;
end;
//看哪个盘是U盘
procedure TForm1.Button1Click(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;
实现部分如下
procedure TForm1.WMDeviceChange(var Msg: TMessage);
var
myMsg : String;
begin
Case Msg.WParam of
32768:
begin
myMsg :='U盘插入';
MessageBox(0,'注意!U盘已插入!!!','AutoCopy Information',MB_ICONASTERISK and MB_ICONINFORMATION);
end;
32772:
begin
myMsg :='U盘拔出';
MessageBox(0,'注意!U盘已取走!!!','AutoCopy Information',MB_ICONASTERISK and MB_ICONINFORMATION);
end;
end;
end;