[Okta Webinar] Learn how to a build a cloud-first strategyRegister Now

x
  • Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 190
  • Last Modified:

Need to hook left CTRL button only in my application.

Hello Guys,

I need code to hook all click on right CTRL button...
But I need to hook clicks only for my application.

Thanks,
Dan
0
DanDaemon
Asked:
DanDaemon
  • 7
  • 6
1 Solution
 
robert_marquardtCommented:
Now which one? Left or Right? :-)

Write a message handler for WM_KEYDOWN. There you get the full key information to check for left or right Ctrl key.
See the Win32 help for WM_KEYDOWN for details.
0
 
DanDaemonAuthor Commented:
Yes, sorry, LEFT!

Need good example on Delphi
0
 
Ferruccio AccalaiSenior developer, analyst and customer assistance Commented:
mmm...maybe something like this?

unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes,Forms,Dialogs;

type
  TForm1 = class(TForm)
    procedure FormCreate(Sender: TObject);
  private
    { Private declarations }
    procedure AppMessage(var Msg: TMsg; var Handled: Boolean);
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

uses Unit2;

{$R *.dfm}
procedure TForm1.FormCreate(Sender: TObject);

begin
  Application.OnMessage := AppMessage;

end;

procedure TForm1.AppMessage(var Msg: TMsg; var Handled: Boolean);
function HighOrderBitSet (theWord: Word): Boolean;
const
  HighOrderBit = 15;
type
  BitSet = set of 0..15;
begin
  HighOrderBitSet := (HighOrderBit in BitSet(theWord));
end;

begin
   if (Msg.Message = WM_KeyDown) then
   if (Msg.wParam = VK_Control) and
      (HighOrderBitSet(Word(GetKeyState(VK_LCONTROL)))) then
         begin
            showmessage('left ctrl pressed');
            Handled := True;
         end;
end;


end.
0
VIDEO: THE CONCERTO CLOUD FOR HEALTHCARE

Modern healthcare requires a modern cloud. View this brief video to understand how the Concerto Cloud for Healthcare can help your organization.

 
DanDaemonAuthor Commented:
Hello Ferruccio68,

Thanks, your function works properly.
I will increase points because understand that I need to detect also when it will be unpressed...

I.e. I need to detect when left CTRL will be pressed one time and unpressed back.
I.e. I need to detect two messages from system...

Can you modify your code?

Thanks,
Dan
0
 
Ferruccio AccalaiSenior developer, analyst and customer assistance Commented:
var
pressed: Boolean;
begin
   if (Msg.Message = WM_KeyDown) and
      (Msg.wParam = VK_Control) and
      (HighOrderBitSet(Word(GetKeyState(VK_LCONTROL)))) then
         begin
            showmessage('left ctrl pressed');
            Pressed := True;
            Handled := True;
         end
   else
   if (Msg.Message = WM_KeyUp) and
      Msg.wParam = VK_Control) and Pressed then
       begin
            showmessage('left ctrl unpressed');
            Pressed := False;
            Handled := True;
         end;
end;

Just from head (sorry, delphi not available at the moment)...
0
 
DanDaemonAuthor Commented:
Hello Ferruccio,

Your function does not work properly :(

Thanks,
Dan
0
 
DanDaemonAuthor Commented:
Hello Ferruccio,

I think I need to change first task, sorry but it is so.

I need a global hook for left ctrl button and this hook shold work so:

"user pressed left CTRL"______he still hold it____"user unpressed left CTRL"
__(software gets event)_______(no events)_______(software gets event)

I need to get two events:
1. Press left CTRL;
2. Unpress left CTRL (I should get this event only if CTRL was pressed and hooked by my software).

Sorry for changing :)

Thanks,
Dan.
0
 
Ferruccio AccalaiSenior developer, analyst and customer assistance Commented:
ok, so do this:

put a TTimer on a form with interval = 100

then paste this code in unit1

unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, ExtCtrls;

type
  TForm1 = class(TForm)
    Timer1: TTimer;
    procedure Timer1Timer(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;
  pressed: Boolean;
  Down, Up: Integer;
implementation

{$R *.dfm}
function lCtrlDown: Boolean;
var
  State: TKeyboardState;
begin
  GetKeyboardState(State);
  Result := ((State[VK_lCONTROL] and 128) <> 0);
end;

procedure TForm1.Timer1Timer(Sender: TObject);
begin
if lctrldown and not pressed then
   begin
      Pressed := True;
      Inc(Down);
   end else
      If not lctrldown and pressed then
         begin
            Pressed := False;
            inc(up);
         end;
caption := Format('Left Control Down: %d LeftControl Up: %d',[Down,up]);
end;

end.

F68 ;-)
0
 
DanDaemonAuthor Commented:
Hello Ferruccio68,

Any ideas about global hook?

Thanks, you code works perfect... But need to global hook.

Thanks,
Dan
0
 
Ferruccio AccalaiSenior developer, analyst and customer assistance Commented:
mmm...
Do you mean a Keyboard Hook using a dll or just trapping keyboard messages in your application?

As i can see the Timer solution is pretty simple and less coded.

Also note that the Pressed situation is a little bit hard to be checked in a WM_ message as it's considered as a repeteable key down-up....
0
 
DanDaemonAuthor Commented:
No, when my software is running I can hide it to system tray, but in this case main form is not active but I still need to hook left control button.

Your first example does not allow to hook this event when main form is not active...

Thanks,
Dan
0
 
Ferruccio AccalaiSenior developer, analyst and customer assistance Commented:
mmm....in this case you need a dll

well, this is the more simple method:
first you have to create your dll hook like this

library HandlerLib;

uses
  Windows;
var
pressed: Boolean;

function lCtrlDown: Boolean;
var
  State: TKeyboardState;
begin
  GetKeyboardState(State);
  Result := ((State[VK_lCONTROL] and 128) <> 0);
end;

procedure Handler( nCode : Integer;
                  wParam : WPARAM;
                  lParam : LPARAM); stdcall;
begin
 if lctrldown and not pressed then
   begin
      Pressed := True;
      MessageBox(0,'Left Control Pressed','Info',0); //here you can instead  store the value where you prefere and then read it  from your app
   end else
      If not lctrldown and pressed then
         begin
            Pressed := False;
            MessageBox(0,'Left Control Released','Info',0);
         end;
 CallNextHookEx( 0, nCode, wParam, lParam );
end;

exports Handler;

begin
end.

Now from your app

unit Unit2;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms;

type
  TForm1 = class(TForm)
    procedure FormCreate(Sender: TObject);
    procedure FormDestroy(Sender: TObject);


  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;
  hook : HHOOK;
  dll : HMODULE;

implementation

{$R *.dfm}


procedure TForm1.FormCreate(Sender: TObject);
begin
 dll:=LoadLibrary( 'HandlerLib' );
 hook:=SetWindowsHookEx( WH_KEYBOARD, GetProcAddress( dll, 'Handler' ), dll, 0 );
end;

procedure TForm1.FormDestroy(Sender: TObject);
begin
  UnhookWindowsHookEx( hook );
  FreeLibrary( dll );
end;
end.

what you can do is to create a dat (or ini) file on create and reset up and down values
then from dll just increment when needed these values in dat

from your for simply get the refreshed values from dat

hope this helps

0
 
DanDaemonAuthor Commented:
Thanks man! Works perfect!
0
 
Ferruccio AccalaiSenior developer, analyst and customer assistance Commented:
Glad to have helped you :)

F68 ;-)
0

Featured Post

Free Tool: Path Explorer

An intuitive utility to help find the CSS path to UI elements on a webpage. These paths are used frequently in a variety of front-end development and QA automation tasks.

One of a set of tools we're offering as a way of saying thank you for being a part of the community.

  • 7
  • 6
Tackle projects and never again get stuck behind a technical roadblock.
Join Now