如何防止鼠标打开显示器?
How to prevent mouse from turning on monitor?
下面的代码可以成功锁定鼠标事件。这是我试图防止鼠标在关闭时打开显示器,但是当使用鼠标执行任何操作时显示器总是打开,例如:单击左键。
有解决办法吗?
type
TForm1 = class(TForm)
Button1: TButton;
Memo1: TMemo;
Button2: TButton;
procedure Button1Click(Sender: TObject);
procedure Button2Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
MouseHook: HHOOK;
implementation
{$R *.dfm}
function LowLevelMouseProc(nCode: Integer; WParam: WParam; LParam: LParam): LRESULT; stdcall;
begin
Result := 1{CallNextHookEx(MouseHook, nCode, WParam, LParam)};
case WParam of
WM_LBUTTONDOWN:
Form1.Memo1.Lines.Add('Mouse Left Button Down');
WM_LBUTTONUP:
Form1.Memo1.Lines.Add('Mouse Left Button Up');
WM_LBUTTONDBLCLK:
Form1.Memo1.Lines.Add('Mouse Left Button Double Click');
WM_RBUTTONDOWN:
Form1.Memo1.Lines.Add('Mouse Right Button Down');
WM_RBUTTONUP:
Form1.Memo1.Lines.Add('Mouse Right Button Up');
WM_RBUTTONDBLCLK:
Form1.Memo1.Lines.Add('Mouse Right Button Double Click');
WM_MBUTTONDOWN:
Form1.Memo1.Lines.Add('Mouse Middle Button Down');
WM_MBUTTONUP:
Form1.Memo1.Lines.Add('Mouse Middle Button Up');
WM_MBUTTONDBLCLK:
Form1.Memo1.Lines.Add('Mouse Middle Button Double Click');
WM_MOUSEMOVE:
Form1.Memo1.Lines.Add('Mouse Move');
WM_MOUSEWHEEL:
Form1.Memo1.Lines.Add('Mouse Wheel');
else
Form1.Memo1.Lines.Add('Unknown Event');
end;
end;
procedure TForm1.Button1Click(Sender: TObject);
const
MONITOR_ON = -1;
MONITOR_OFF = 2;
MONITOR_STANDBY = 1;
begin
MouseHook := SetWindowsHookEx(WH_MOUSE_LL, @LowLevelMouseProc, HInstance, 0);
SendMessage(Application.Handle, WM_SYSCOMMAND, SC_MONITORPOWER, MONITOR_OFF);
// SendMessage(Application.Handle, WM_SYSCOMMAND, SC_MONITORPOWER, MONITOR_ON);
end;
procedure TForm1.Button2Click(Sender: TObject);
begin
UnhookWindowsHookEx(MouseHook);
end;
编辑:
我只需要关闭显示器而不关闭系统(休眠或挂起)。并防止鼠标操作恢复它。
在分析和测试@AmigoJack 的建议后,似乎禁用设备(就像使用 Windows 设备管理器所做的那样)对我来说是一个可能的解决方案,即使某些设备无法禁用。我留下代码是为了帮助未来的读者解决同样的问题。
DeviceCtrl
unit DeviceCtrl;
interface
uses
Classes, SysUtils, Windows;
const
GUID_DEVCLASS_1394: TGUID = '{6BDD1FC1-810F-11D0-BEC7-08002BE2092F}';
GUID_DEVCLASS_ADAPTER: TGUID = '{4D36E964-E325-11CE-BFC1-08002BE10318}';
GUID_DEVCLASS_APMSUPPORT: TGUID = '{D45B1C18-C8FA-11D1-9F77-0000F805F530}';
GUID_DEVCLASS_BATTERY: TGUID = '{72631E54-78A4-11D0-BCF7-00AA00B7B32A}';
GUID_DEVCLASS_CDROM: TGUID = '{4D36E965-E325-11CE-BFC1-08002BE10318}';
GUID_DEVCLASS_COMPUTER: TGUID = '{4D36E966-E325-11CE-BFC1-08002BE10318}';
GUID_DEVCLASS_DECODER: TGUID = '{6BDD1FC2-810F-11D0-BEC7-08002BE2092F}';
GUID_DEVCLASS_DISKDRIVE: TGUID = '{4D36E967-E325-11CE-BFC1-08002BE10318}';
GUID_DEVCLASS_DISPLAY: TGUID = '{4D36E968-E325-11CE-BFC1-08002BE10318}';
GUID_DEVCLASS_FDC: TGUID = '{4D36E969-E325-11CE-BFC1-08002BE10318}';
GUID_DEVCLASS_FLOPPYDISK: TGUID = '{4D36E980-E325-11CE-BFC1-08002BE10318}';
GUID_DEVCLASS_GPS: TGUID = '{6BDD1FC3-810F-11D0-BEC7-08002BE2092F}';
GUID_DEVCLASS_HDC: TGUID = '{4D36E96A-E325-11CE-BFC1-08002BE10318}';
GUID_DEVCLASS_HIDCLASS: TGUID = '{745A17A0-74D3-11D0-B6FE-00A0C90F57DA}';
GUID_DEVCLASS_IMAGE: TGUID = '{6BDD1FC6-810F-11D0-BEC7-08002BE2092F}';
GUID_DEVCLASS_INFRARED: TGUID = '{6BDD1FC5-810F-11D0-BEC7-08002BE2092F}';
GUID_DEVCLASS_KEYBOARD: TGUID = '{4D36E96B-E325-11CE-BFC1-08002BE10318}';
GUID_DEVCLASS_LEGACYDRIVER: TGUID = '{8ECC055D-047F-11D1-A537-0000F8753ED1}';
GUID_DEVCLASS_MEDIA: TGUID = '{4D36E96C-E325-11CE-BFC1-08002BE10318}';
GUID_DEVCLASS_MEDIUM_CHANGER: TGUID = '{CE5939AE-EBDE-11D0-B181-0000F8753EC4}';
GUID_DEVCLASS_MODEM: TGUID = '{4D36E96D-E325-11CE-BFC1-08002BE10318}';
GUID_DEVCLASS_MONITOR: TGUID = '{4D36E96E-E325-11CE-BFC1-08002BE10318}';
GUID_DEVCLASS_MOUSE: TGUID = '{4D36E96F-E325-11CE-BFC1-08002BE10318}';
GUID_DEVCLASS_MTD: TGUID = '{4D36E970-E325-11CE-BFC1-08002BE10318}';
GUID_DEVCLASS_MULTIFUNCTION: TGUID = '{4D36E971-E325-11CE-BFC1-08002BE10318}';
GUID_DEVCLASS_MULTIPORTSERIAL: TGUID = '{50906CB8-BA12-11D1-BF5D-0000F805F530}';
GUID_DEVCLASS_NET: TGUID = '{4D36E972-E325-11CE-BFC1-08002BE10318}';
GUID_DEVCLASS_NETCLIENT: TGUID = '{4D36E973-E325-11CE-BFC1-08002BE10318}';
GUID_DEVCLASS_NETSERVICE: TGUID = '{4D36E974-E325-11CE-BFC1-08002BE10318}';
GUID_DEVCLASS_NETTRANS: TGUID = '{4D36E975-E325-11CE-BFC1-08002BE10318}';
GUID_DEVCLASS_NODRIVER: TGUID = '{4D36E976-E325-11CE-BFC1-08002BE10318}';
GUID_DEVCLASS_PCMCIA: TGUID = '{4D36E977-E325-11CE-BFC1-08002BE10318}';
GUID_DEVCLASS_PORTS: TGUID = '{4D36E978-E325-11CE-BFC1-08002BE10318}';
GUID_DEVCLASS_PRINTER: TGUID = '{4D36E979-E325-11CE-BFC1-08002BE10318}';
GUID_DEVCLASS_PRINTERUPGRADE: TGUID = '{4D36E97A-E325-11CE-BFC1-08002BE10318}';
GUID_DEVCLASS_SCSIADAPTER: TGUID = '{4D36E97B-E325-11CE-BFC1-08002BE10318}';
GUID_DEVCLASS_SMARTCARDREADER: TGUID = '{50DD5230-BA8A-11D1-BF5D-0000F805F530}';
GUID_DEVCLASS_SOUND: TGUID = '{4D36E97C-E325-11CE-BFC1-08002BE10318}';
GUID_DEVCLASS_SYSTEM: TGUID = '{4D36E97D-E325-11CE-BFC1-08002BE10318}';
GUID_DEVCLASS_TAPEDRIVE: TGUID = '{6D807884-7D21-11CF-801C-08002BE10318}';
GUID_DEVCLASS_UNKNOWN: TGUID = '{4D36E97E-E325-11CE-BFC1-08002BE10318}';
GUID_DEVCLASS_USB: TGUID = '{36FC9E60-C465-11CF-8056-444553540000}';
GUID_DEVCLASS_VOLUME: TGUID = '{71A27CDD-812A-11D0-BEC7-08002BE2092F}';
type
TDeviceControlResult = (DCROK, DCRErrEnumDevIceInfo, DCRErrSetClassInstallParams, DCRErrDIF_PROPERTYCHANGE);
function LoadDevices(GUID_DevClass: TGUID): TStringList;
function EnableDevice(SelectedItem: DWORD): TDeviceControlResult;
function DisableDevice(SelectedItem: DWORD): TDeviceControlResult;
implementation
const
DIF_PROPERTYCHANGE = [=10=]000012;
DICS_ENABLE = [=10=]000001;
DICS_DISABLE = [=10=]000002;
DICS_FLAG_GLOBAL = [=10=]000001;
DIGCF_PRESENT = [=10=]000002;
SPDRP_DEVICEDESC = [=10=]000000;
SPDRP_CLASS = [=10=]000007;
SPDRP_CLASSGUID = [=10=]000008;
SPDRP_FRIENDLYNAME = [=10=]00000C;
type
HDEVINFO = Pointer;
DI_FUNCTION = LongWord;
PSPClassInstallHeader = ^TSPClassInstallHeader;
SP_CLASSINSTALL_HEADER = packed record
cbSize: DWORD;
InstallFunction: DI_FUNCTION;
end;
TSPClassInstallHeader = SP_CLASSINSTALL_HEADER;
PSPPropChangeParams = ^TSPPropChangeParams;
SP_PROPCHANGE_PARAMS = packed record
ClassInstallHeader: TSPClassInstallHeader;
StateChange: DWORD;
Scope: DWORD;
HwProfile: DWORD;
end;
TSPPropChangeParams = SP_PROPCHANGE_PARAMS;
PSPDevInfoData = ^TSPDevInfoData;
SP_DEVINFO_DATA = packed record
cbSize: DWORD;
ClassGuid: TGUID;
DevInst: DWORD;
Reserved: ULONG_PTR;
end;
TSPDevInfoData = SP_DEVINFO_DATA;
TSetupDiEnumDeviceInfo = function(DeviceInfoSet: HDEVINFO; MemberIndex: DWORD; var DeviceInfoData: TSPDevInfoData): LongBool; stdcall;
TSetupDiSetClassInstallParamsA = function(DeviceInfoSet: HDEVINFO; DeviceInfoData: PSPDevInfoData; ClassInstallParams: PSPClassInstallHeader; ClassInstallParamsSize: DWORD): LongBool; stdcall;
TSetupDiSetClassInstallParamsW = function(DeviceInfoSet: HDEVINFO; DeviceInfoData: PSPDevInfoData; ClassInstallParams: PSPClassInstallHeader; ClassInstallParamsSize: DWORD): LongBool; stdcall;
TSetupDiSetClassInstallParams = TSetupDiSetClassInstallParamsA;
TSetupDiCallClassInstaller = function(InstallFunction: DI_FUNCTION; DeviceInfoSet: HDEVINFO; DeviceInfoData: PSPDevInfoData): LongBool; stdcall;
TSetupDiGetClassDevs = function(ClassGuid: PGUID; const Enumerator: PAnsiChar; hwndParent: HWND; Flags: DWORD): HDEVINFO; stdcall;
TSetupDiGetDeviceRegistryPropertyA = function(DeviceInfoSet: HDEVINFO; const DeviceInfoData: TSPDevInfoData; Property_: DWORD; var PropertyRegDataType: DWORD; PropertyBuffer: PBYTE; PropertyBufferSIze: DWORD; var RequiredSize: DWORD): BOOL; stdcall;
TSetupDiGetDeviceRegistryPropertyW = function(DeviceInfoSet: HDEVINFO; const DeviceInfoData: TSPDevInfoData; Property_: DWORD; var PropertyRegDataType: DWORD; PropertyBuffer: PBYTE; PropertyBufferSIze: DWORD; var RequiredSize: DWORD): BOOL; stdcall;
TSetupDiGetDeviceRegistryProperty = TSetupDiGetDeviceRegistryPropertyA;
var
DevInfo: hDevInfo;
SetupDiEnumDeviceInfo: TSetupDiEnumDeviceInfo;
SetupDiSetClassInstallParams: TSetupDiSetClassInstallParams;
SetupDiCallClassInstaller: TSetupDiCallClassInstaller;
SetupDiGetClassDevs: TSetupDiGetClassDevs;
SetupDiGetDeviceRegistryProperty: TSetupDiGetDeviceRegistryProperty;
var
SetupApiLoadCount: Integer = 0;
function LoadSetupApi: Boolean;
var
SetupApiLib: System.THandle;
begin
Result := True;
Inc(SetupApiLoadCount);
if SetupApiLoadCount > 1 then
Exit;
SetupApiLib := LoadLibrary('SetupApi.dll');
Result := SetupApiLib <> 0;
if Result then
begin
SetupDiEnumDeviceInfo := Windows.GetProcAddress(SetupApiLib, 'SetupDiEnumDeviceInfo');
SetupDiSetClassInstallParams := Windows.GetProcAddress(SetupApiLib, 'SetupDiSetClassInstallParamsA');
SetupDiCallClassInstaller := Windows.GetProcAddress(SetupApiLib, 'SetupDiCallClassInstaller');
SetupDiGetClassDevs := Windows.GetProcAddress(SetupApiLib, 'SetupDiGetClassDevsA');
SetupDiGetDeviceRegistryProperty := Windows.GetProcAddress(SetupApiLib, 'SetupDiGetDeviceRegistryPropertyA');
end;
end;
function StateChange(NewState, SelectedItem: DWORD; hDevInfo: hDevInfo): TDeviceControlResult;
var
PropChangeParams: TSPPropChangeParams;
DeviceInfoData: TSPDevInfoData;
begin
PropChangeParams.ClassInstallHeader.cbSize := SizeOf(TSPClassInstallHeader);
DeviceInfoData.cbSize := SizeOf(TSPDevInfoData);
if (not SetupDiEnumDeviceInfo(hDevInfo, SelectedItem, DeviceInfoData)) then
begin
Result := DCRErrEnumDevIceInfo;
Exit;
end;
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 := DCRErrSetClassInstallParams;
Exit;
end;
if (not SetupDiCallClassInstaller(DIF_PROPERTYCHANGE, hDevInfo, @DeviceInfoData)) then
begin
Result := DCRErrDIF_PROPERTYCHANGE;
Exit;
end;
Result := DCROK;
end;
function 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;
function 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 LoadDevices(GUID_DevClass: TGUID): TStringList;
var
DeviceInfoData: TSPDevInfoData;
I: DWORD;
pszText: PChar;
begin
if (not LoadSetupApi) then
begin
Result := nil;
Exit;
end;
DevInfo := nil;
DevInfo := SetupDiGetClassDevs(@GUID_DevClass, nil, 0, DIGCF_PRESENT);
if (DevInfo = Pointer(INVALID_HANDLE_VALUE)) then
begin
Result := nil;
Exit;
end;
Result := TStringList.Create;
DeviceInfoData.cbSize := SizeOf(TSPDevInfoData);
I := 0;
while SetupDiEnumDeviceInfo(DevInfo, I, DeviceInfoData) do
begin
GetMem(pszText, 256);
try
ConstructDeviceName(DevInfo, DeviceInfoData, pszText, DWORD(nil));
Result.AddObject(string(PAnsiChar(pszText)), Tobject(I));
finally
FreeMem(pszText);
end;
Inc(I);
end;
end;
function EnableDevice(SelectedItem: DWORD): TDeviceControlResult;
begin
Result := StateChange(DICS_ENABLE, SelectedItem, DevInfo);
end;
function DisableDevice(SelectedItem: DWORD): TDeviceControlResult;
begin
Result := StateChange(DICS_DISABLE, SelectedItem, DevInfo);
end;
end.
设备测试
program DeviceTest;
{$APPTYPE CONSOLE}
{$R *.res}
uses
Classes,
DeviceCtrl;
var
sl: TStringList;
I: Integer;
begin
sl := LoadDevices(GUID_DEVCLASS_MOUSE);
try
for I := 0 to sl.count - 1 do
begin
Writeln(I, ' : ', sl[I]);
if DisableDevice(I) = DCROK then
Writeln(sl[I], ' disabled');
if EnableDevice(I) = DCROK then
Writeln(sl[I], ' enabled');
end;
finally
sl.Free;
end;
Readln;
end.
- 要工作,需要以管理员身份执行此程序,并根据您的 Windows 系统编译为 32 位或 64 位。
- 参考文献:Enabling and disabling devices and Possibly you are hitting the problem of 32bit apps trying to setup 64 bit drivers
下面的代码可以成功锁定鼠标事件。这是我试图防止鼠标在关闭时打开显示器,但是当使用鼠标执行任何操作时显示器总是打开,例如:单击左键。
有解决办法吗?
type
TForm1 = class(TForm)
Button1: TButton;
Memo1: TMemo;
Button2: TButton;
procedure Button1Click(Sender: TObject);
procedure Button2Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
MouseHook: HHOOK;
implementation
{$R *.dfm}
function LowLevelMouseProc(nCode: Integer; WParam: WParam; LParam: LParam): LRESULT; stdcall;
begin
Result := 1{CallNextHookEx(MouseHook, nCode, WParam, LParam)};
case WParam of
WM_LBUTTONDOWN:
Form1.Memo1.Lines.Add('Mouse Left Button Down');
WM_LBUTTONUP:
Form1.Memo1.Lines.Add('Mouse Left Button Up');
WM_LBUTTONDBLCLK:
Form1.Memo1.Lines.Add('Mouse Left Button Double Click');
WM_RBUTTONDOWN:
Form1.Memo1.Lines.Add('Mouse Right Button Down');
WM_RBUTTONUP:
Form1.Memo1.Lines.Add('Mouse Right Button Up');
WM_RBUTTONDBLCLK:
Form1.Memo1.Lines.Add('Mouse Right Button Double Click');
WM_MBUTTONDOWN:
Form1.Memo1.Lines.Add('Mouse Middle Button Down');
WM_MBUTTONUP:
Form1.Memo1.Lines.Add('Mouse Middle Button Up');
WM_MBUTTONDBLCLK:
Form1.Memo1.Lines.Add('Mouse Middle Button Double Click');
WM_MOUSEMOVE:
Form1.Memo1.Lines.Add('Mouse Move');
WM_MOUSEWHEEL:
Form1.Memo1.Lines.Add('Mouse Wheel');
else
Form1.Memo1.Lines.Add('Unknown Event');
end;
end;
procedure TForm1.Button1Click(Sender: TObject);
const
MONITOR_ON = -1;
MONITOR_OFF = 2;
MONITOR_STANDBY = 1;
begin
MouseHook := SetWindowsHookEx(WH_MOUSE_LL, @LowLevelMouseProc, HInstance, 0);
SendMessage(Application.Handle, WM_SYSCOMMAND, SC_MONITORPOWER, MONITOR_OFF);
// SendMessage(Application.Handle, WM_SYSCOMMAND, SC_MONITORPOWER, MONITOR_ON);
end;
procedure TForm1.Button2Click(Sender: TObject);
begin
UnhookWindowsHookEx(MouseHook);
end;
编辑:
我只需要关闭显示器而不关闭系统(休眠或挂起)。并防止鼠标操作恢复它。
在分析和测试@AmigoJack 的建议后,似乎禁用设备(就像使用 Windows 设备管理器所做的那样)对我来说是一个可能的解决方案,即使某些设备无法禁用。我留下代码是为了帮助未来的读者解决同样的问题。
DeviceCtrl
unit DeviceCtrl;
interface
uses
Classes, SysUtils, Windows;
const
GUID_DEVCLASS_1394: TGUID = '{6BDD1FC1-810F-11D0-BEC7-08002BE2092F}';
GUID_DEVCLASS_ADAPTER: TGUID = '{4D36E964-E325-11CE-BFC1-08002BE10318}';
GUID_DEVCLASS_APMSUPPORT: TGUID = '{D45B1C18-C8FA-11D1-9F77-0000F805F530}';
GUID_DEVCLASS_BATTERY: TGUID = '{72631E54-78A4-11D0-BCF7-00AA00B7B32A}';
GUID_DEVCLASS_CDROM: TGUID = '{4D36E965-E325-11CE-BFC1-08002BE10318}';
GUID_DEVCLASS_COMPUTER: TGUID = '{4D36E966-E325-11CE-BFC1-08002BE10318}';
GUID_DEVCLASS_DECODER: TGUID = '{6BDD1FC2-810F-11D0-BEC7-08002BE2092F}';
GUID_DEVCLASS_DISKDRIVE: TGUID = '{4D36E967-E325-11CE-BFC1-08002BE10318}';
GUID_DEVCLASS_DISPLAY: TGUID = '{4D36E968-E325-11CE-BFC1-08002BE10318}';
GUID_DEVCLASS_FDC: TGUID = '{4D36E969-E325-11CE-BFC1-08002BE10318}';
GUID_DEVCLASS_FLOPPYDISK: TGUID = '{4D36E980-E325-11CE-BFC1-08002BE10318}';
GUID_DEVCLASS_GPS: TGUID = '{6BDD1FC3-810F-11D0-BEC7-08002BE2092F}';
GUID_DEVCLASS_HDC: TGUID = '{4D36E96A-E325-11CE-BFC1-08002BE10318}';
GUID_DEVCLASS_HIDCLASS: TGUID = '{745A17A0-74D3-11D0-B6FE-00A0C90F57DA}';
GUID_DEVCLASS_IMAGE: TGUID = '{6BDD1FC6-810F-11D0-BEC7-08002BE2092F}';
GUID_DEVCLASS_INFRARED: TGUID = '{6BDD1FC5-810F-11D0-BEC7-08002BE2092F}';
GUID_DEVCLASS_KEYBOARD: TGUID = '{4D36E96B-E325-11CE-BFC1-08002BE10318}';
GUID_DEVCLASS_LEGACYDRIVER: TGUID = '{8ECC055D-047F-11D1-A537-0000F8753ED1}';
GUID_DEVCLASS_MEDIA: TGUID = '{4D36E96C-E325-11CE-BFC1-08002BE10318}';
GUID_DEVCLASS_MEDIUM_CHANGER: TGUID = '{CE5939AE-EBDE-11D0-B181-0000F8753EC4}';
GUID_DEVCLASS_MODEM: TGUID = '{4D36E96D-E325-11CE-BFC1-08002BE10318}';
GUID_DEVCLASS_MONITOR: TGUID = '{4D36E96E-E325-11CE-BFC1-08002BE10318}';
GUID_DEVCLASS_MOUSE: TGUID = '{4D36E96F-E325-11CE-BFC1-08002BE10318}';
GUID_DEVCLASS_MTD: TGUID = '{4D36E970-E325-11CE-BFC1-08002BE10318}';
GUID_DEVCLASS_MULTIFUNCTION: TGUID = '{4D36E971-E325-11CE-BFC1-08002BE10318}';
GUID_DEVCLASS_MULTIPORTSERIAL: TGUID = '{50906CB8-BA12-11D1-BF5D-0000F805F530}';
GUID_DEVCLASS_NET: TGUID = '{4D36E972-E325-11CE-BFC1-08002BE10318}';
GUID_DEVCLASS_NETCLIENT: TGUID = '{4D36E973-E325-11CE-BFC1-08002BE10318}';
GUID_DEVCLASS_NETSERVICE: TGUID = '{4D36E974-E325-11CE-BFC1-08002BE10318}';
GUID_DEVCLASS_NETTRANS: TGUID = '{4D36E975-E325-11CE-BFC1-08002BE10318}';
GUID_DEVCLASS_NODRIVER: TGUID = '{4D36E976-E325-11CE-BFC1-08002BE10318}';
GUID_DEVCLASS_PCMCIA: TGUID = '{4D36E977-E325-11CE-BFC1-08002BE10318}';
GUID_DEVCLASS_PORTS: TGUID = '{4D36E978-E325-11CE-BFC1-08002BE10318}';
GUID_DEVCLASS_PRINTER: TGUID = '{4D36E979-E325-11CE-BFC1-08002BE10318}';
GUID_DEVCLASS_PRINTERUPGRADE: TGUID = '{4D36E97A-E325-11CE-BFC1-08002BE10318}';
GUID_DEVCLASS_SCSIADAPTER: TGUID = '{4D36E97B-E325-11CE-BFC1-08002BE10318}';
GUID_DEVCLASS_SMARTCARDREADER: TGUID = '{50DD5230-BA8A-11D1-BF5D-0000F805F530}';
GUID_DEVCLASS_SOUND: TGUID = '{4D36E97C-E325-11CE-BFC1-08002BE10318}';
GUID_DEVCLASS_SYSTEM: TGUID = '{4D36E97D-E325-11CE-BFC1-08002BE10318}';
GUID_DEVCLASS_TAPEDRIVE: TGUID = '{6D807884-7D21-11CF-801C-08002BE10318}';
GUID_DEVCLASS_UNKNOWN: TGUID = '{4D36E97E-E325-11CE-BFC1-08002BE10318}';
GUID_DEVCLASS_USB: TGUID = '{36FC9E60-C465-11CF-8056-444553540000}';
GUID_DEVCLASS_VOLUME: TGUID = '{71A27CDD-812A-11D0-BEC7-08002BE2092F}';
type
TDeviceControlResult = (DCROK, DCRErrEnumDevIceInfo, DCRErrSetClassInstallParams, DCRErrDIF_PROPERTYCHANGE);
function LoadDevices(GUID_DevClass: TGUID): TStringList;
function EnableDevice(SelectedItem: DWORD): TDeviceControlResult;
function DisableDevice(SelectedItem: DWORD): TDeviceControlResult;
implementation
const
DIF_PROPERTYCHANGE = [=10=]000012;
DICS_ENABLE = [=10=]000001;
DICS_DISABLE = [=10=]000002;
DICS_FLAG_GLOBAL = [=10=]000001;
DIGCF_PRESENT = [=10=]000002;
SPDRP_DEVICEDESC = [=10=]000000;
SPDRP_CLASS = [=10=]000007;
SPDRP_CLASSGUID = [=10=]000008;
SPDRP_FRIENDLYNAME = [=10=]00000C;
type
HDEVINFO = Pointer;
DI_FUNCTION = LongWord;
PSPClassInstallHeader = ^TSPClassInstallHeader;
SP_CLASSINSTALL_HEADER = packed record
cbSize: DWORD;
InstallFunction: DI_FUNCTION;
end;
TSPClassInstallHeader = SP_CLASSINSTALL_HEADER;
PSPPropChangeParams = ^TSPPropChangeParams;
SP_PROPCHANGE_PARAMS = packed record
ClassInstallHeader: TSPClassInstallHeader;
StateChange: DWORD;
Scope: DWORD;
HwProfile: DWORD;
end;
TSPPropChangeParams = SP_PROPCHANGE_PARAMS;
PSPDevInfoData = ^TSPDevInfoData;
SP_DEVINFO_DATA = packed record
cbSize: DWORD;
ClassGuid: TGUID;
DevInst: DWORD;
Reserved: ULONG_PTR;
end;
TSPDevInfoData = SP_DEVINFO_DATA;
TSetupDiEnumDeviceInfo = function(DeviceInfoSet: HDEVINFO; MemberIndex: DWORD; var DeviceInfoData: TSPDevInfoData): LongBool; stdcall;
TSetupDiSetClassInstallParamsA = function(DeviceInfoSet: HDEVINFO; DeviceInfoData: PSPDevInfoData; ClassInstallParams: PSPClassInstallHeader; ClassInstallParamsSize: DWORD): LongBool; stdcall;
TSetupDiSetClassInstallParamsW = function(DeviceInfoSet: HDEVINFO; DeviceInfoData: PSPDevInfoData; ClassInstallParams: PSPClassInstallHeader; ClassInstallParamsSize: DWORD): LongBool; stdcall;
TSetupDiSetClassInstallParams = TSetupDiSetClassInstallParamsA;
TSetupDiCallClassInstaller = function(InstallFunction: DI_FUNCTION; DeviceInfoSet: HDEVINFO; DeviceInfoData: PSPDevInfoData): LongBool; stdcall;
TSetupDiGetClassDevs = function(ClassGuid: PGUID; const Enumerator: PAnsiChar; hwndParent: HWND; Flags: DWORD): HDEVINFO; stdcall;
TSetupDiGetDeviceRegistryPropertyA = function(DeviceInfoSet: HDEVINFO; const DeviceInfoData: TSPDevInfoData; Property_: DWORD; var PropertyRegDataType: DWORD; PropertyBuffer: PBYTE; PropertyBufferSIze: DWORD; var RequiredSize: DWORD): BOOL; stdcall;
TSetupDiGetDeviceRegistryPropertyW = function(DeviceInfoSet: HDEVINFO; const DeviceInfoData: TSPDevInfoData; Property_: DWORD; var PropertyRegDataType: DWORD; PropertyBuffer: PBYTE; PropertyBufferSIze: DWORD; var RequiredSize: DWORD): BOOL; stdcall;
TSetupDiGetDeviceRegistryProperty = TSetupDiGetDeviceRegistryPropertyA;
var
DevInfo: hDevInfo;
SetupDiEnumDeviceInfo: TSetupDiEnumDeviceInfo;
SetupDiSetClassInstallParams: TSetupDiSetClassInstallParams;
SetupDiCallClassInstaller: TSetupDiCallClassInstaller;
SetupDiGetClassDevs: TSetupDiGetClassDevs;
SetupDiGetDeviceRegistryProperty: TSetupDiGetDeviceRegistryProperty;
var
SetupApiLoadCount: Integer = 0;
function LoadSetupApi: Boolean;
var
SetupApiLib: System.THandle;
begin
Result := True;
Inc(SetupApiLoadCount);
if SetupApiLoadCount > 1 then
Exit;
SetupApiLib := LoadLibrary('SetupApi.dll');
Result := SetupApiLib <> 0;
if Result then
begin
SetupDiEnumDeviceInfo := Windows.GetProcAddress(SetupApiLib, 'SetupDiEnumDeviceInfo');
SetupDiSetClassInstallParams := Windows.GetProcAddress(SetupApiLib, 'SetupDiSetClassInstallParamsA');
SetupDiCallClassInstaller := Windows.GetProcAddress(SetupApiLib, 'SetupDiCallClassInstaller');
SetupDiGetClassDevs := Windows.GetProcAddress(SetupApiLib, 'SetupDiGetClassDevsA');
SetupDiGetDeviceRegistryProperty := Windows.GetProcAddress(SetupApiLib, 'SetupDiGetDeviceRegistryPropertyA');
end;
end;
function StateChange(NewState, SelectedItem: DWORD; hDevInfo: hDevInfo): TDeviceControlResult;
var
PropChangeParams: TSPPropChangeParams;
DeviceInfoData: TSPDevInfoData;
begin
PropChangeParams.ClassInstallHeader.cbSize := SizeOf(TSPClassInstallHeader);
DeviceInfoData.cbSize := SizeOf(TSPDevInfoData);
if (not SetupDiEnumDeviceInfo(hDevInfo, SelectedItem, DeviceInfoData)) then
begin
Result := DCRErrEnumDevIceInfo;
Exit;
end;
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 := DCRErrSetClassInstallParams;
Exit;
end;
if (not SetupDiCallClassInstaller(DIF_PROPERTYCHANGE, hDevInfo, @DeviceInfoData)) then
begin
Result := DCRErrDIF_PROPERTYCHANGE;
Exit;
end;
Result := DCROK;
end;
function 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;
function 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 LoadDevices(GUID_DevClass: TGUID): TStringList;
var
DeviceInfoData: TSPDevInfoData;
I: DWORD;
pszText: PChar;
begin
if (not LoadSetupApi) then
begin
Result := nil;
Exit;
end;
DevInfo := nil;
DevInfo := SetupDiGetClassDevs(@GUID_DevClass, nil, 0, DIGCF_PRESENT);
if (DevInfo = Pointer(INVALID_HANDLE_VALUE)) then
begin
Result := nil;
Exit;
end;
Result := TStringList.Create;
DeviceInfoData.cbSize := SizeOf(TSPDevInfoData);
I := 0;
while SetupDiEnumDeviceInfo(DevInfo, I, DeviceInfoData) do
begin
GetMem(pszText, 256);
try
ConstructDeviceName(DevInfo, DeviceInfoData, pszText, DWORD(nil));
Result.AddObject(string(PAnsiChar(pszText)), Tobject(I));
finally
FreeMem(pszText);
end;
Inc(I);
end;
end;
function EnableDevice(SelectedItem: DWORD): TDeviceControlResult;
begin
Result := StateChange(DICS_ENABLE, SelectedItem, DevInfo);
end;
function DisableDevice(SelectedItem: DWORD): TDeviceControlResult;
begin
Result := StateChange(DICS_DISABLE, SelectedItem, DevInfo);
end;
end.
设备测试
program DeviceTest;
{$APPTYPE CONSOLE}
{$R *.res}
uses
Classes,
DeviceCtrl;
var
sl: TStringList;
I: Integer;
begin
sl := LoadDevices(GUID_DEVCLASS_MOUSE);
try
for I := 0 to sl.count - 1 do
begin
Writeln(I, ' : ', sl[I]);
if DisableDevice(I) = DCROK then
Writeln(sl[I], ' disabled');
if EnableDevice(I) = DCROK then
Writeln(sl[I], ' enabled');
end;
finally
sl.Free;
end;
Readln;
end.
- 要工作,需要以管理员身份执行此程序,并根据您的 Windows 系统编译为 32 位或 64 位。
- 参考文献:Enabling and disabling devices and Possibly you are hitting the problem of 32bit apps trying to setup 64 bit drivers