Recent

Author Topic: Intercepting keypress question.  (Read 17548 times)

wpflum

  • Sr. Member
  • ****
  • Posts: 287
Intercepting keypress question.
« on: September 14, 2010, 07:42:16 pm »
I'm using the formkeydown event  to validate input to the screen.  I can intercept the key press and determine if it's a valid press depending on where it is but I haven't been able to stop the actual key press from showing up on the screen if the entry is invalid either as a character or a Tab key.  Most of the examples I've seen set the Key variable to 0 to clear it but either I'm doing it wrong or I'm doing it at the right place since the key still shows up on the screen.  What am I missing??? 

garlar27

  • Hero Member
  • *****
  • Posts: 652
Re: Intercepting keypress question.
« Reply #1 on: September 14, 2010, 08:54:06 pm »
You should'nt have that problem!! I do that every day without problem.

The event you use is FormKeyDown or MyControlKeyDown?

If is FormKeyDown: Did you set the Form.KeyPreview to TRUE?

If you place a breakpoint in the line "Key := 0;" execution stops?

wpflum

  • Sr. Member
  • ****
  • Posts: 287
Re: Intercepting keypress question.
« Reply #2 on: September 14, 2010, 08:55:54 pm »
Oops   :-[

It appears I had a logic error upstream of the Key := 0  line which was skewing everything up. ::)

Just for a reference can anyone tell me a way to do a "if Key in ['0'..'9'] then " where the key isn't in the list?? I tried "if Key not in ['0'..'9'] then" but that doesn't work.

typo

  • Hero Member
  • *****
  • Posts: 3051
Re: Intercepting keypress question.
« Reply #3 on: September 14, 2010, 09:07:26 pm »
Code: [Select]
if not (key in ['0'..'9']) then something;

wpflum

  • Sr. Member
  • ****
  • Posts: 287
Re: Intercepting keypress question.
« Reply #4 on: September 14, 2010, 09:12:59 pm »
Duh  :o

I forgot about ()  :-[

garlar27

  • Hero Member
  • *****
  • Posts: 652
Re: Intercepting keypress question.
« Reply #5 on: September 14, 2010, 09:17:37 pm »
You mean:
Code: [Select]
if not (Key in ['0'..'9']) then // do your thingthis will work ONLY in a KeyPress Event.

KeyPress receives the param "var Key: Char"
KeyDown receives the param "var Key: Word"

The first one will work fine with the code above ...

KeyDown gives you the key's KEY_CODE. for instance on windows should be VK_1 or VK_NUMPAD1 and in linux i think is XK_1 or XK_NUMPAD1


fabienwang

  • Sr. Member
  • ****
  • Posts: 449
  • Lazarus is the best
    • My blog
Re: Intercepting keypress question.
« Reply #6 on: September 14, 2010, 09:22:22 pm »
oh about this subject, can you intercept keys while the Form is minimized or doesn't have the focus?
Cause i'm interested if Yes :D

Thanks
I'm using Arch Linux.
Known for: CPickSniff, OpenGrabby
Contributed to: LazPaint

garlar27

  • Hero Member
  • *****
  • Posts: 652
Re: Intercepting keypress question.
« Reply #7 on: September 14, 2010, 09:31:32 pm »
My guess is you won't be able to do that.

I know how to intercept the key pressed for the whole project, but I don't know how to do it at OS level...

typo

  • Hero Member
  • *****
  • Posts: 3051
Re: Intercepting keypress question.
« Reply #8 on: September 14, 2010, 09:34:06 pm »
Quote
can you intercept keys while the Form is minimized or doesn't have the focus?

At least on Windows you can make a Hook of the keyboard.

Code: [Select]
unit Unit1;

{$mode delphi}{$H+}

interface

uses
  Classes,SysUtils,FileUtil,LResources,Forms,Controls,Graphics,Dialogs,ExtCtrls,
  Windows;

type

  { TForm1 }

  TForm1 = class(TForm)
    Image1:TImage;
    procedure FormCreate(Sender:TObject);
    procedure FormDestroy(Sender:TObject);
  private
    { private declarations }
  public
    { public declarations }
  end;

var
  Form1: TForm1;
  KBHook: HHook; {this intercepts keyboard input}
  cx, cy : integer; {track battle ship's position}
  p :tpoint;

  {callback's declaration}
  function KeyboardHookProc(Code: Integer; WordParam: Word; LongParam: LongInt): LongInt; stdcall;

implementation

{$R *.lfm}

{
To install a hook, we call SetWindowsHookEx in the OnCreate event of a form.
}

procedure TForm1.FormCreate(Sender: TObject) ;
begin
 {Set the keyboard hook so we
 can intercept keyboard input}
 KBHook:=SetWindowsHookEx(WH_KEYBOARD,
           {callback —>} @KeyboardHookProc,
                          HInstance,
                          GetCurrentThreadId()) ;

 {place the battle ship in
 the middle of the screen}
 cx := Image1.ClientWidth div 2;
 cy := Image1.ClientHeight div 2;

 p.x := cx;
 p.y := cy;

 Image1.Canvas.PenPos := p;//Point(cx,cy) ;
end;

{
To free system resources associated with the hook, we must call the UnhookWindowsHookEx function in the OnDestroy event:
 }
procedure TForm1.FormDestroy(Sender: TObject) ;
begin
  {unhook the keyboard interception}
  UnHookWindowsHookEx(KBHook) ;
end;

{
The most important part of this project is the KeyboardHookProc callback procedure used to process keystrokes.
}
function KeyboardHookProc(Code: Integer; WordParam: Word; LongParam: LongInt) : LongInt;
begin
 case WordParam of
  vk_Space: {erase battle ship's path}
   begin
    with Form1.Image1.Canvas do
    begin
     Brush.Color := clWhite;
     Brush.Style := bsSolid;
     Fillrect(Form1.Image1.ClientRect) ;
    end;
   end;
  vk_Right: cx := cx+1;
  vk_Left: cx := cx-1;
  vk_Up: cy := cy-1;
  vk_Down: cy := cy+1;
 end; {case}

 If cx < 2 then cx := Form1.Image1.ClientWidth-2;
 If cx > Form1.Image1.ClientWidth -2 then cx := 2;
 If cy < 2 then cy := Form1.Image1.ClientHeight -2 ;
 If cy > Form1.Image1.ClientHeight-2 then cy := 2;

 with Form1.Image1.Canvas do
 begin
  Pen.Color := clRed;
  Brush.Color := clYellow;
  TextOut(0,0,Format('%d, %d',[cx,cy])) ;
  Rectangle(cx-2, cy-2, cx+2,cy+2) ;
 end;

 Result:=0;
 {To prevent Windows from passing the keystrokes
 to the target window, the Result value must
 be a nonzero value.}
end;


end.           

wpflum

  • Sr. Member
  • ****
  • Posts: 287
Re: Intercepting keypress question.
« Reply #9 on: September 14, 2010, 09:34:58 pm »
You mean:
Code: [Select]
if not (Key in ['0'..'9']) then // do your thingthis will work ONLY in a KeyPress Event.

KeyPress receives the param "var Key: Char"
KeyDown receives the param "var Key: Word"

The first one will work fine with the code above ...

KeyDown gives you the key's KEY_CODE. for instance on windows should be VK_1 or VK_NUMPAD1 and in linux i think is XK_1 or XK_NUMPAD1



Found that out the hard way so I just added a MyKey variable as a character and did a MyKey := chr(Key)  to fix it  :)

So the actual code should have been

if not (MyKey in ['0'..'9']) then ......

Didn't think to include that part.

One further question since you seem knowledgeable in the ways of win vs lin, I'm using the VK_ keywords with LCLTYPE in the uses clause in a Linux environment.  Will this work across on a Windows system??  I'm writing this in Linux but will final compile on a Windows box and have tried small bits of the code and had it work but I wanted to make sure I shouldn't be doing it differently to keep compatibility.

garlar27

  • Hero Member
  • *****
  • Posts: 652
Re: Intercepting keypress question.
« Reply #10 on: September 14, 2010, 09:50:16 pm »
WHAT A QUESTION!!!

I work smoothly on linux and windows with the lcltype and I Hope not to have problems with that. So far I don't have problems. It's all I can say about it.

The constants for Virtual Key Codes for windows (VK_key) are defined in a unit different of LCLType the same with the linux X Key Codes (XK_key). LCLType AFAIK was made for LazMouseAndkeyInput component and it's cross platform.

garlar27

  • Hero Member
  • *****
  • Posts: 652
Re: Intercepting keypress question.
« Reply #11 on: September 14, 2010, 10:23:42 pm »
I wish that key code's constants declared in LCLType would have a different name like LK_NUMPAD1 or FPK_NUMPAD1 to avoid confussion. Furthermore I think it would be good to define those constant this way instead:
Code: [Select]
{$IFDEF WINDOWS}
   LK_NUMPAD1 = VK_NUMPAD1;
{$ELSE}
   {$IFDEF LINUX}
      LK_NUMPAD1 = XK_NUMPAD1;
   {$ENDIF}
{$ENDIF}

But that's the way it is. :-\

wpflum

  • Sr. Member
  • ****
  • Posts: 287
Re: Intercepting keypress question.
« Reply #12 on: September 15, 2010, 12:08:44 am »
WHAT A QUESTION!!!

I work smoothly on linux and windows with the lcltype and I Hope not to have problems with that. So far I don't have problems. It's all I can say about it.

The constants for Virtual Key Codes for windows (VK_key) are defined in a unit different of LCLType the same with the linux X Key Codes (XK_key). LCLType AFAIK was made for LazMouseAndkeyInput component and it's cross platform.

?????   :-\

Didn't mean to put you on the spot  :-[

I just thought that since you at least knew there was a difference in Linux vs windows names you might be a bit more versed in cross platform than me  %)

I did manage to drop the latest version of the code onto a virtual XP box with Lazarus on it before I left for the day and it compiled and ran more or less like the Linux version.  I say more or less since I still have an ongoing problem with either the color pallet or a variable relating to it causing me to have a white screen background but I figured I'd tweak that out when I'm more or less finished on the linux side.  I'd like to say as generic as possible so I wont have to do many/any windows/linux defs.

garlar27

  • Hero Member
  • *****
  • Posts: 652
Re: Intercepting keypress question.
« Reply #13 on: September 15, 2010, 12:56:04 pm »
LCLType is fine. I use it every day on linux, and even more during testings because I've made an automatic tester which generates keystrokes from a script to reproduce user keypress events as if there where a real user working on the PC.

 

TinyPortal © 2005-2018