Einzelnen Beitrag anzeigen

Benutzerbild von KodeZwerg
KodeZwerg

Registriert seit: 1. Feb 2018
3.061 Beiträge
 
Delphi 10.3 Rio
 
#5

AW: Tastatur per Button sperren und wieder entsperren

  Alt 29. Jul 2020, 08:19
Guten Morgen,

nun eine unter Windows 10 getestete Variation, 32 sowie 64bit kompatibel.

4 Verschiedene Varianten stehen zur Auswahl, nur 3 sind per GUI testbar.
Assembler benötigt spezielle Rechte, die ich hier nicht verbaut habe.


Delphi-Quellcode:
unit Unit2;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants,
  System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls;

type
  TForm2 = class(TForm)
    GroupBox1: TGroupBox;
    RadioButton1: TRadioButton;
    RadioButton2: TRadioButton;
    GroupBox2: TGroupBox;
    Button1: TButton;
    GroupBox3: TGroupBox;
    CheckBox1: TCheckBox;
    GroupBox4: TGroupBox;
    RadioButton3: TRadioButton;
    RadioButton4: TRadioButton;
    Label1: TLabel;
    Edit1: TEdit;
    procedure FormCreate(Sender: TObject);
    procedure RadioButton1Click(Sender: TObject);
    procedure RadioButton2Click(Sender: TObject);
    procedure Button1Click(Sender: TObject);
    procedure RadioButton3Click(Sender: TObject);
    procedure RadioButton4Click(Sender: TObject);
  private
    // HOOK support start
    KBHook: HHOOK;
    function KBHookHandler(ACode: Integer; WParam: WParam; LParam: LParam): LResult; stdcall;
    function DisableKeyboard: Boolean; stdcall;
    // HOOK support end
  protected
    // delphi messages support
    procedure CMCHILDKEY(var Msg: TWMKey); message CM_CHILDKEY;
  public
  end;

var
  Form2: TForm2;

implementation

{$R *.dfm}

procedure TForm2.FormCreate(Sender: TObject);
begin
  // sicherstellen das es eine Null zur Initialisierung hat
  // (sollte eh der fall sein, aber man weiß ja nie)
  KBHook := 0;
end;

// Hook Handler
function TForm2.KBHookHandler(ACode: Integer; WParam: WParam; LParam: LParam): LResult; stdcall;
begin
  // ACode steht für einen Tastencode
  if ACode < 0 then
    // falls keine bekannte Taste gedrückt wurde, weiter "hooken"
    Result := CallNextHookEx(KBHook, ACode, WParam, LParam)
  else
    // sobald Result > 0 = werden Tasten unterdrückt
    Result := 1;
end;

// Hook Starter
function TForm2.DisableKeyboard: Boolean; stdcall;
begin
  // wenn noch kein hook vergeben wurde
  if KBHook = 0 then
    // einen neuen einrichten
    KBHook := SetWindowsHookEx(WH_KEYBOARD, @TForm2.KBHookHandler, HInstance, GetCurrentThreadId());
  // und als result auswerten
  Result := (KBHook <> 0);
end;

{ Hook Off }
procedure TForm2.RadioButton1Click(Sender: TObject);
begin
  // wenn ein hook gesetzt war
  if KBHook <> 0 then
    // geben wir ihn hier wieder frei
    UnhookWindowsHookEx(KBHook);
  // und stellen sicher das es ne null ist
  KBHook := 0;
  Edit1.SetFocus;
end;

{ Hook On }
procedure TForm2.RadioButton2Click(Sender: TObject);
begin
  DisableKeyboard;
  Edit1.SetFocus;
end;

{ BlockInput On/Off }
// vom blockinput rate ich dringend ab
// aber da es sowas gibt
// hier meine implementation
procedure TForm2.Button1Click(Sender: TObject);
  // meine Windows.pas besitzt bereits "BlockInput"
  // falls deins es nicht hat
  // hier ein helferlein um das nachzuholen
  function DllFunc(const dllName: string; const funcName: string; var p: pointer): Boolean;
  var
    lib: THandle;
  begin
    Result := False;
    p := nil;
    if (LoadLibrary(PChar(dllName)) = 0) then
      Exit;
    lib := GetModuleHandle(PChar(dllName));
    if (lib <> 0) then
      begin
        p := GetProcAddress(lib, PChar(funcName));
        if (p <> nil) then
          Result := True;
      end;
  end;

var
  BlockInput : function(Block: BOOL): BOOL; stdcall;
begin
  if DllFunc('USER32.DLL', 'BlockInput', @BlockInput) then
    begin
      // der input wird gepuffert und zurückgehalten
      BlockInput(Bool(True));
      Edit1.SetFocus;
      // hauptthread friert ein, sorry
      Sleep(5000);
      // der input wird freigelassen
      // was noch im puffer ist,
      // wird nun ausgeführt!!!
      BlockInput(Bool(False));
      Button1.SetFocus;
    end;
end;

{ Keyboard Message On/Off }
procedure TForm2.CMCHILDKEY(var Msg: TWMKey);
begin
  Edit1.SetFocus;
  if not CheckBox1.Checked then
    Msg.Result := 1;
end;

{ Assembler On }
procedure TForm2.RadioButton3Click(Sender: TObject);
asm
  in al,21h
  and al,11111101b
  out 21h,al
end;

{ Assembler Off }
procedure TForm2.RadioButton4Click(Sender: TObject);
asm
  in al,21h
  or al,00000010b
  out 21h,al
end;

end.
Im Anhang kompletter Quelltext zum Project sowie 64bit Kompilat zum sofort ausprobieren.
Falls sich das Project nicht kompilieren lässt bitte die "überflüssigen" Dateien per Hand selbst löschen, ich war gestern bissl faul
(.dpr, .pas, .dfm, .res behalten, den Rest löschen)

Anmerkung:
Es scheint das Windows keine globalen Hooks aus einem Programm heraus zulässt, wenn dies unbedingt erforderlich ist den Hook-Part eventuell als Library erstellen und über Dll mal testen, mir fehlte die Zeit dafür.

Ps: Kann sein das die Unit im Archiv minimal von der obigen gezeigten abweicht.

PPs: WM_KEYDOWN könnte vielleicht auch eine Message sein mit der man spielen könnte bzw. generell die Delphi eigenen KeyDown/KeyPress Events dazu "missbrauchen".


Viel Erfolg und Spaß damit.
(keine copryrights oder der gleichen, alles zur freien Verfügung)
Angehängte Dateien
Dateityp: 7z Keyboard_Disable.7z (859,0 KB, 2x aufgerufen)
Gruß vom KodeZwerg
  Mit Zitat antworten Zitat