如何防止鼠标打开显示器?

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.