Visit our Sponsor   Visit our Sponsor
delphi3000.com - the free delphi knowledge platform
delphi3000.com - the free delphi knowledge platform
500 Users Online NOW
Have a look at your member-status

connecting people's knowledge


  - Recent ArticlesRSS feed for Recent Articles on delphi3000.com
  - List of All Articles
  - Top Viewed Articles
  - Articles (+Attachem.)
  - Articles Of Interest
  - Categories
  - Top Uploader
  - Search
  - Index

  - My Home
  - Submit an Article
  - My Articles
  - My Personal Data
  - My Bookmarks
  - Activities
  - Login/Logout

  - Sign Up
  - Why Sign Up
  - Newsletter

  - Press
  - Advertise

  - Contact
  - Feedback





Community
Borland
ClubeDelphi
Dr. Bob
UK-BUG
Delphi Meetings
Planeta Delphi



Loremo - the 1.5 liter car coming in 2009




Startblatt.de






Share this article with friendsShare this article with friends
Rate this articleRate this article - to keep the quality of delphi3000.com !
Comment this article or read through previous comments (32)


Keyboard wide system hookFormat this article printer-friendly!Bookmark function is only available for registered users!
Capturing keys in all Windows
Product:
Delphi 3.x (or higher)
Category:
Win API
Skill Level:
Scoring:
Last Update:
11/15/2004
Search Keys:
delphi delphi3000 article borland vcl code-snippet keyboard key all hook system
Times Scored:
34
Visits:
22796
Uploader: Radikal Q3
Company: Q3
Reference: http://www.q3.nu/trucomania
 
Question/Problem/Abstract:
Capturing keys in all Windows
Answer:



A lot of people ask me about the possibility that our application Delphi captures the user's keystrokes, although the user doesn't make them our active application being.  
Of course... the first thing that we make is to give a turn for the event OnKeyPress of the form, and of course, without obtaining positive results, even putting the property KeyPreview from the form to true...  
This happens because our application will only receive messages of the keystrokes when is it who has the focus.
The following step to solve this question is fighting with the keyboard hooks.  
A Hook it is not more than a mechanism that will allow us to spy the traffic of messages between Windows and the applications.  

To install a hook in our application is something relatively simple, but of course, if we install it in our application, we will only spy the messages that Windows sent to our application, so neither we will have solved the problem.  

Then... Which is the solution?. The solution is to install a Hook but at system level, that is to say, a hook that captures all the messages that circulate toward Windows.

Installing a hook at system level has a great added complication that is the fact that the function to the one that calls the hook it must be contained in a DLL, not in our Delphi application.  
This condition, will force us, in the first place to build us a DLL, and in second place to to build us some invention to communicate the DLL with our application.

In this trick you have an example of keyboard capture by means of a keyboard Hook to system level.  
The example consists of two projects, one for the DLL and another for the example application.  

The operation is the following one:  
  • We make DLL with two functions that we will export, one to install the hook and another for ununstall it.  
  • There is a third function that is the one that will execute the hook once installed (CallBack). In her, that will make it is to send the data of the message captured to our application.

    The DLL should know in all moment the handle of the receiver application, so we will make him to read it of a memory mapped file that we will create from the own application.  

    Well, let's go with the example:

    DLL that installs the Hook:

    Make the skeleton of a DLL (File - New - DLL)  
    Change the code of the project for this another:

    library Project1;

    {
    Demo de Hook de teclado a nivel de sistema, Radikal.
    Como lo que queremos es capturar las teclas pulsadas en cualquier parte
    de Windows, necesitamos instalar la funcion CallBack a la que llamará
    el Hook en una DLL, que es ésta misma.
    }

    uses Windows,
      Messages;

    const
    CM_MANDA_TECLA = WM_USER + $1000;

    var
    HookDeTeclado     : HHook;
    FicheroM    : THandle;
    PReceptor   : ^Integer;

    function CallBackDelHook( Code    : Integer;
                              wParam  : WPARAM;
                              lParam  : LPARAM
                              )       : LRESULT; stdcall;

    {Esta es la funcion CallBack a la cual llamará el hook.}
    {This is the CallBack function called by he Hook}
    begin
    {Si una tecla fue pulsada o liberada}
    {if a key was pressed/released}
    if code=HC_ACTION then
    begin
      {Miramos si existe el fichero}
      {if the mapfile exists}
      FicheroM:=OpenFileMapping(FILE_MAP_READ,False,'ElReceptor');
      {Si no existe, no enviamos nada a la aplicacion receptora}
      {If dont, send nothing to receiver application}
      if FicheroM<>0 then
      begin
        PReceptor:=MapViewOfFile(FicheroM,FILE_MAP_READ,0,0,0);
        PostMessage(PReceptor^,CM_MANDA_TECLA,wParam,lParam);
        UnmapViewOfFile(PReceptor);
        CloseHandle(FicheroM);
      end;
    end;
    {Llamamos al siguiente hook de teclado de la cadena}
    {call to next hook of the chain}
    Result := CallNextHookEx(HookDeTeclado, Code, wParam, lParam)
    end;

    procedure HookOn; stdcall;
    {Procedure que instala el hook}
    {procedure for install the hook}
    begin
      HookDeTeclado:=SetWindowsHookEx(WH_KEYBOARD, @CallBackDelHook, HInstance , 0);
    end;

    procedure HookOff;  stdcall;
    begin
    {procedure para desinstalar el hook}
    {procedure to uninstall the hook}
      UnhookWindowsHookEx(HookDeTeclado);
    end;

    exports
    {Exportamos las procedures...}
    {Export the procedures}
    HookOn,
    HookOff;

    begin
    end.

    Now record the project with the name: ' HookTeclado.dpr' and compile it (Project - Build All), and you will have generated the DLL of the project.

    Receiver application

  • Make a new empty application
  • Put a TMemo (Memo1) in the form
  • Change the form's unit code by this other:

    unit Unit1;

    interface

    uses
      Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
      StdCtrls;

    const
      NombreDLL       = 'HookTeclado.dll';
      CM_MANDA_TECLA  = WM_USER + $1000;


    type
      THookTeclado=procedure; stdcall;

    type
      TForm1 = class(TForm)
        Label1: TLabel;
        Memo1: TMemo;
        Button1: TButton;
        procedure FormCreate(Sender: TObject);
        procedure FormDestroy(Sender: TObject);
      private
        { Private declarations }
        FicheroM       : THandle;
        PReceptor      : ^Integer;
        HandleDLL      : THandle;
        HookOn,
        HookOff        : THookTeclado;

        procedure LlegaDelHook(var message: TMessage); message  CM_MANDA_TECLA;
      public
        { Public declarations }
      end;

    var
      Form1: TForm1;

    implementation

    {$R *.DFM}

    procedure TForm1.FormCreate(Sender: TObject);
    begin
      {No queremos que el Memo maneje el teclado...}
      {We dont want that the memo read the keyboard...}
      Memo1.ReadOnly:=TRUE;

      HandleDLL:=LoadLibrary( PChar(ExtractFilePath(Application.Exename)+
                                    NombreDLL ) );
      if HandleDLL = 0 then raise Exception.Create('No se pudo cargar la DLL');

      @HookOn :=GetProcAddress(HandleDLL, 'HookOn');
      @HookOff:=GetProcAddress(HandleDLL, 'HookOff');

      IF not assigned(HookOn) or
         not assigned(HookOff)  then
         raise Exception.Create('No se encontraron las funciones en la DLL'+#13+
                                'Cannot find the required DLL functions');

      {Creamos el fichero de memoria}
      FicheroM:=CreateFileMapping( $FFFFFFFF,
                                  nil,
                                  PAGE_READWRITE,
                                  0,
                                  SizeOf(Integer),
                                  'ElReceptor');

       {Si no se creó el fichero, error}
       if FicheroM=0 then
         raise Exception.Create( 'Error al crear el fichero'+
                                 '/Error while create file');

       {Direccionamos nuestra estructura al fichero de memoria}
       PReceptor:=MapViewOfFile(FicheroM,FILE_MAP_WRITE,0,0,0);

       {Escribimos datos en el fichero de memoria}
       PReceptor^:=Handle;
       HookOn;
    end;

    procedure TForm1.LlegaDelHook(var message: TMessage);
    var
       NombreTecla : array[0..100] of char;
       Accion      : string;
    begin
      {Traducimos de Virtual key Code a TEXTO}
      {Virtual key code to Key Name}
      GetKeyNameText(Message.LParam,@NombreTecla,100);

      {Miramos si la tecla fué pulsada, soltada o repetida}
      {Look if the key was pressed, released o re-pressed}
      if ((Message.lParam shr 31) and 1)=1
          then Accion:='Soltada' {Released}
      else
      if ((Message.lParam shr 30) and 1)=1
          then Accion:='Repetida' {repressed}
          else Accion:='Pulsada'; {pressed}

      Memo1.Lines.Append( Accion+
                          ' tecla: '+
                          String(NombreTecla) );
    end;

    procedure TForm1.FormDestroy(Sender: TObject);
    begin
    {Desactivamos el Hook}
    {Uninstall the Hook}
    if Assigned(HookOff) then HookOff;

    {Liberamos la DLL}
    {Free the DLL}
    if HandleDLL<>0 then
      FreeLibrary(HandleDLL);

    {Cerramos la vista del fichero y el fichero}
    {Close the memfile and the View}
    if FicheroM<>0 then
    begin
       UnmapViewOfFile(PReceptor);
       CloseHandle(FicheroM);
    end;

    end;

    end.

  • Record the project in the same directory of the project of the DLL and compile the application.

    If you have followed the steps until here, you will have in the directory of the two projects a DLL (HookTeclado.DLL) and the executable of the receiver application.  
    Execute it, and you will see in the Memo1 all the keys pressed in Windows.

    If you only wanted an example that works, it is not necessary that you continue reading. If you want to know a little more than like the invention works... so... here you have it, step to step:

    We go starting from the event OnCreate of the application:

    First, we put the Memo1 to readonly. Imagine for what reason, or better, it proves to not putting it, to see that it happens...:)

    procedure TForm1.FormCreate(Sender: TObject);
    begin
      {No queremos que el Memo maneje el teclado...}
      {We dont want that the memo read the keyboard...}
      Memo1.ReadOnly:=TRUE;

    Now we load the DLL that we will suppose that it will be in the same directory that our executable one. If there was some problem when loading it, we generate an exception, in such a way that the following code would not be executed.

      HandleDLL:=LoadLibrary( PChar(ExtractFilePath(Application.Exename)+
                                    NombreDLL ) );
      if HandleDLL = 0 then raise Exception.Create('No se pudo cargar la DLL');

  • Once loaded the DLL, we look for the two functions that they should be in it. If they are not... we generate an exception.

      @HookOn :=GetProcAddress(HandleDLL, 'HookOn');
      @HookOff:=GetProcAddress(HandleDLL, 'HookOff');

      IF not assigned(HookOn) or
         not assigned(HookOff)  then
         raise Exception.Create('No se encontraron las funciones en la DLL'+#13+
                                'Cannot find the required DLL functions');

  • Now, we make a memory mapped file, which will use to keep the handle of our form, the DLL will taste this way like who must send him the message with the key that has been pressed just  reading this file.

      {Creamos el fichero de memoria}
      FicheroM:=CreateFileMapping( $FFFFFFFF,
                                  nil,
                                  PAGE_READWRITE,
                                  0,
                                  SizeOf(Integer),
                                  'ElReceptor');

       {Si no se creó el fichero, error}
       if FicheroM=0 then
         raise Exception.Create( 'Error al crear el fichero'+
                                 '/Error while create file');

       {Direccionamos nuestra estructura al fichero de memoria}
       PReceptor:=MapViewOfFile(FicheroM,FILE_MAP_WRITE,0,0,0);

  • Once we have the memory mapped file, and a view pointing to it, we record the handle of the form in it, and we activate the Hook, calling to the procedure HookOn of the DLL:

       {Escribimos datos en el fichero de memoria}
       PReceptor^:=Handle;
       HookOn;
    end;

  • Well, now see that it happens in our DLL when calling to the function HookOn:

    procedure HookOn; stdcall;
    {Procedure que instala el hook}
    {procedure for install the hook}
    begin
      HookDeTeclado:=SetWindowsHookEx(WH_KEYBOARD, @CallBackDelHook, HInstance , 0);
    end;

    As you see, there is not more than a call to SetWindowsHookEx, to install a hook at system level (0 in the last parameter) that will execute the function CallBackDelHook with each message that it captures.

  • Let us see that it makes the function CallBackDelHook when it is executed by the hook:

    First, it checks that the function has been called by a new keyboard event, by means of the if code=HC_ACTION.

    function CallBackDelHook( Code    : Integer;
                              wParam  : WPARAM;
                              lParam  : LPARAM
                              )       : LRESULT; stdcall;

    {Esta es la funcion CallBack a la cual llamará el hook.}
    {This is the CallBack function called by he Hook}
    begin
    {Si una tecla fue pulsada o liberada}
    {if a key was pressed/released}
    if code=HC_ACTION then
    begin

    If it is this way, that is to say that is a new keyboard event that it is necessary to assist... the first thing that we should make is so to look for the handle from the application to which should send the message with the data of the pressed/released key, which have kept by heart in a file from the application, we try to open the file, and to read this handle, and if everything goes well, we send the message by means of a PostMessage:

      {Miramos si existe el fichero}
      {if the mapfile exists}
      FicheroM:=OpenFileMapping(FILE_MAP_READ,False,'ElReceptor');
      {Si no existe, no enviamos nada a la aplicacion receptora}
      {If dont, send nothing to receiver application}
      if FicheroM<>0 then
      begin
        PReceptor:=MapViewOfFile(FicheroM,FILE_MAP_READ,0,0,0);
        PostMessage(PReceptor^,CM_MANDA_TECLA,wParam,lParam);

    once sent the message, we free the file:

        UnmapViewOfFile(PReceptor);
        CloseHandle(FicheroM);
      end;
    end;

    later, should call to next hook:

    {Llamamos al siguiente hook de teclado de la cadena}
    {call to next hook of the chain}
    Result := CallNextHookEx(HookDeTeclado, Code, wParam, lParam)
    end;

    Well, do we have installed a hook that captures the keyboard events and does it forward them to our application... which the following step is?, of course... to make something to receive it...  
    We will have to capture user's message that we have been defined:

    const
    CM_MANDA_TECLA = WM_USER + $1000;

    that which we will get adding this line in the private part of the form:

    procedure LlegaDelHook(var message: TMessage); message  CM_MANDA_TECLA;

    and of course, the corresponding procedure in the implementation part:

    procedure TForm1.LlegaDelHook(var message: TMessage);
    var
       NombreTecla : array[0..100] of char;
       Accion      : string;
    begin
      {Traducimos de Virtual key Code a TEXTO}
      {Virtual key code to Key Name}
      GetKeyNameText(Message.LParam,@NombreTecla,100);

      {Miramos si la tecla fué pulsada, soltada o repetida}
      {Look if the key was pressed, released o re-pressed}
      if ((Message.lParam shr 31) and 1)=1
          then Accion:='Soltada' {Released}
      else
      if ((Message.lParam shr 30) and 1)=1
          then Accion:='Repetida' {repressed}
          else Accion:='Pulsada'; {pressed}

      Memo1.Lines.Append( Accion+
                          ' tecla: '+
                          String(NombreTecla) );
    end;

    In this example, I simply translate the data of the pressed/released key, translating it to its key name and adding it to the TMemo.  
    If you want more information on the parameters than the function will receive, revise the help file Win32.hlp looking for the topic ' KeyboardProc'.  
    There you will see the meaning of the parameters wParam and lParam that you will receive in the function.

    For I finish, we have left to undo this whole invention when we leave the application. The OnDestroy event of the application:

    First, uninstall the hook, calling to the HookOff function of the DLL. Care, is to use the if Assigned, because if there has been some problem when loading the DLL in the OnCreate... now we would try to execute something that was not initialized.

    procedure TForm1.FormDestroy(Sender: TObject);
    begin
    {Desactivamos el Hook}
    {Uninstall the Hook}
    if Assigned(HookOff) then HookOff;

    Now, free the DLL:

    {Liberamos la DLL}
    {Free the DLL}
    if HandleDLL<>0 then
      FreeLibrary(HandleDLL);

    And the file:

    {Cerramos la vista del fichero y el fichero}
    {Close the memfile and the View}
    if FicheroM<>0 then
    begin
       UnmapViewOfFile(PReceptor);
       CloseHandle(FicheroM);
    end;
    end;






  • Please rate this article!
    Skill level:
    BeginnerExpert

    Useful:
    No!Very!

    Overall rating:
    PoorExcellent



    Comments to this article
    Write a new comment
    Preventing key-strokes
        Tommy Andersen (Nov 15 2004 8:52PM)

    If you want to prevent a key-stroke or combination, define WH_KEYBOARD_LL = 13.

    Instead of calling SetWindowsHookEx with WH_KEYBOARD, call it with WH_KEYBOARD_LL .

    Whenever you encounter a key-stroke you don't want, just set the result to 1 instead of calling CallNextHookEx .

    Respond

    RE: Preventing key-strokes
    Tom B (Sep 28 2006 2:41AM)

    I've changed the dll to use WH_KEYBOARD_LL but what do you mean dont call CallNextHookEx?

    I assume you mean something like...

    if (lParam = key-I-want) then
    result = 1
    else
    result = CallNextHookEx....

    However i've no idea how to do this and everything i've tried has made my computer crash when the hook is done.

    Thanks for any help :)
    Respond

    MS Office
        Eddy Meb (Nov 29 2003 1:50PM)

    Hi,
    your code is good. but i noticed that i could not type to my MS Office apps when the hook is on. Other apps worked great. is there a way arround this. i know this problem is present bcos MS office is also doing a hook-like operations. Thanks for this great article anyway.

    Edwin
    Respond

    RE: MS Office
    Radikal Q3 (Jun 16 2005 7:26PM)

    The original posted had a bug.
    Now it's cirrected, and works with Office too
    Respond

    RE: RE: MS Office
    Jaydeep Bhatt (Aug 5 2005 1:53PM)

    I had long back downloaded the code and tried. I had done many modications.

    Can you please point, where was that bug ? so that I can find that in my modified Code and correct ?

    Thanks
    Respond

    RE: RE: RE: MS Office
    Radikal Q3 (Aug 5 2005 1:58PM)

    The bug was in the function CallBackDelHook
    and the manner in how call to next hook of the chain.
    Respond

    how can i disable alt+tab or ctrl+alt+del???
        jherbias (Jun 19 2003 6:10PM)

    hi your code works great, but i need disable some key combinations can you help me please??
    Respond

    Why not just make it possible to download the projects!?
        Steini Kallinn (Mar 17 2003 10:38PM)

    Great article!

    But wouldn't it make it a lot easyer to beginners like me, to see the code in actual project. Make the possibility to download the whole package in one zip file?
    Respond

    it does not reconize the CapsLock or Shift key state
        falll assd (Aug 2 2002 9:35PM)

    is there a way to make it reconize the CapsLock or Shift key state insted of just obtaining captial letters
    Respond

    Works great... need some help though
        David (Apr 6 2002 7:29AM)

    Has anyone modified this so that it traps words and specials rather than just individual letters. I have a support application that I am writing and I need to be able to get what the end user types in. I am not interested in the pressed and released, but want to get words or have the sample app post to the memo when a space or enter key is pressed.

    Thanks

    D
    Respond

    Work , not work !?
        Petko Mitko (Feb 7 2002 2:57PM)

    Your way to hook keyboard is good ...
    Work on Windows 98 / SE /ME / 2000 / XP - I have all Microsoft OS
    installed ...
    I write with your hook method great program , but ....

    But your hook work only with Windows GUI , when I try to use
    hook under GUI of DirectX or OpenGL Application - not work .

    Please if you have knowledge about other methoods to hook
    under DirectX or OpenGL then create new forum / link me / or send me
    e-mail ...

    my real e-mail :

      Delphibg@yahoo.com

    Thanks in advance.

    Respond

    Getmessage
        Arman Rad (Aug 17 2001 3:53PM)

    HOW CAN I USE GETMESSAGE FOR DESKTOP????

    Respond

    changing the ascii velue on the fly
        John Vascar (Jan 17 2001 2:17PM)

    Jaydeep you need to embed two DLL in one. one which recieve the ASCII velue and other which changes it on the fly. The second way you can do is write a file which reads input and output ascii velue.

    I think it helps.
    Respond

    RE: changing the ascii velue on the fly
    Jaydeep Bhatt (Sep 8 2001 9:44PM)

    Can anybody write a dll for me which will change the value of ascii chracter to other value ?? Please send me on jaydeepbhatt@hotmail.com
    Respond

    Keyboard Mapping
        Jaydeep Bhatt (Jan 15 2001 12:22AM)

    This program works fine. But how do I modify the ASCII value i.e how do I modify the windows' WM_CHAR message so that when the key is pressed, my desired ASCII value is send to the windows instead of the actual one.

    I wish to map the keyboard to make a local vernacular language program
    Respond

    RE: Keyboard Mapping
    John Vascar (Jan 17 2001 2:19PM)

    Jaydeep you need to embed two DLL in one. one which recieve the ASCII velue and other which changes it on the fly. The second way you can do is write a file which reads input and output ascii velue.

    I think it helps.

    Respond

    keyboard_hook
        normankrebs (Jan 9 2001 1:47PM)

    your article is great! it shows what i needed and the code worked at the first time i typed it in. i tryed out some similar components before - yours is the best!
    Respond

    The program refusese to catch the key strokes!
        Marian (Dec 27 2000 8:03AM)

    After I have copied the example DLL and pasted it into the DLL project
    and then done the same thing with the Monitoring program example
    (of course I had put the Memo1, even the label and the button) the DLL
    and the program compiled perfectly. The problem is that when I start the
    program it captures nothing, but does not raise ani of the exceptions
    that are set into the source.
    Is it possible to have problems with the compiler? I use Delphi4 on
    Win98_SE.
    Respond

    RE: The program refusese to catch the key strokes!
    Radikal Q3 (Dec 27 2000 9:23AM)

    The example works perfectly on Win98 SE ... I don't know what is your problem... sorry.


    Respond

    RE: RE: The program refusese to catch the key strokes!
    Klaus Petersen (Apr 23 2001 9:59AM)

    Did you remember to set the form's oncreate og ondestroy events?
    Respond

    Not working :-(
        Alien (Dec 27 2000 3:17AM)

    I tried this example but after I have done everything necessery according to the given instructions the program didn't want to capture the keys. The DLL file and the Monitoring program compiled without problems. When working the program do not raise exceptions. I am using Delphi4 an WIN98_SE.
    Is there any way to fix this problem?

    Respond

    RE: Not working :-(
    Dead Evil Boy (Feb 12 2001 2:19PM)

    Probably you didn't select FormCreate on OnCreate(Form1). If this is really your problem, don't forget to select FormDestroy on OnDestroy(Form1).

    Have Fun!
    Respond

    RE: RE: Not working :-(
    Dan (Jun 14 2001 6:06AM)

    Not working for me either.  I have set the events correctly.  When debugging from the dll, the hookon event it called, but the callback procedure is never triggered.  Im on Win 2k.
    I did change the code slightly to send the application handle in the hookon procedure rather than a memory mapped file, but this should not affect the call back procedure being triggered should it?
    Respond

    RE: RE: RE: Not working :-(
    Dan (Jun 17 2001 4:02PM)

    The hook seems to be only for the current application and not system wide, even though the correct values are entered for the setwindowhookex. Namely the last 0, meaning system wide. Im baffled as to why its not working for me...
    Respond

    RE: RE: RE: RE: Not working :-(
    Jim Burns (Jul 21 2002 6:05PM)

    But you can't pass in the windows handle as you've done, it will act like an application-wide hook just as you're suggesting, if it runs without exceptions at all.

    The original author uses a memory mapped file specifically because it's a way to communicate between processes.  The named mapping can be opened in any process, and the dll uses this mapping to obtain the handle of the window to send notifications to.  

    In your method, only the dll loaded into your main applications address space has this handle.

    You must understand, wacky as it might be, that this level of windows hook fires AFTER messages are sorted into the appropriate input queues.  This means that for this hook to work, your hook code is inserted into the process space of EVERY GUI application on the system.  

    The reason it appears to you as an application-wide hook is precisely because the dlls loaded into the process space of other GUI threads simply do not have value you store for the windows handle to notify on event.

    On a side note, you may fine using C++ easier for creating the dll since you can specify shared data sections which will be shared for all copies of the dll.  This will allow you to dispense with the memory-mapped file technique which is slightly more cumbersome.


    Jim Burns
    Technology Dynamics
    Pearland, TX
    Respond

    There is a way to return 1 time the keystroke?
        Fernando Ac (Sep 27 2000 4:09PM)

    Nice program . It work perfectly but it return 2 times the same character "Pulsada: tecla" and "Soltada: tecla" .. It be very very messed .
    There is a way to return just 1 time the keystroke?


    Respond

    RE: There is a way to return 1 time the keystroke?
    Radikal Q3 (Sep 29 2000 1:04PM)

    Hummm 'Pulsada' means 'Pressed' and 'Soltada' means released.
    The hook inform us in both cases: key pressed and key released.
    Simply... ignore one of the two events...
    Respond

    RE: RE: There is a way to return 1 time the keystroke?
    joemon sebastian (Dec 17 2000 11:45PM)

    Hi,
    How i can catch the left shift or rght shift key stroke from delphi?
    i have to execute some set of code even if the application window is not active.
    pls help me
    Thanks in advance

    RGDS,

    Respond

    RE: RE: There is a way to return 1 time the keystroke?
    Radikal Q3 (Feb 12 2004 5:34PM)

    The key go to the memo in 3 cases: when the key is pressed, when is released and when is repeated while still pressed...

    If you don't need any of these cases, symply... ignore it!

    This is the code of the original receiver demo application:


    procedure TForm1.LlegaDelHook(var message: TMessage);
    var
       NombreTecla : array[0..100] of char;
       Accion      : string;
    begin
      {Traducimos de Virtual key Code a TEXTO}
      {Virtual key code to Key Name}
      GetKeyNameText(Message.LParam,@NombreTecla,100);

      {Miramos si la tecla fué pulsada, soltada o repetida}
      {Look if the key was pressed, released o re-pressed}
      if ((Message.lParam shr 31) and 1)=1
          then Accion:='Soltada' {Released}
      else
      if ((Message.lParam shr 30) and 1)=1
          then Accion:='Repetida' {repressed}
          else Accion:='Pulsada'; {pressed}

      Memo1.Lines.Append( Accion+
                          ' tecla: '+
                          String(NombreTecla) );
    end;



    and this is the code that just use the event when the key is pressed:


    procedure TForm1.LlegaDelHook(var message: TMessage);
    var
       NombreTecla : array[0..100] of char;
       Accion      : string;
    begin
      {Traducimos de Virtual key Code a TEXTO}
      {Virtual key code to Key Name}
      GetKeyNameText(Message.LParam,@NombreTecla,100);

      if ( ((Message.lParam shr 31) and 1)=0 ) and ( ((Message.lParam shr 30) and 1)=0 )
          then Memo1.Lines.Append( String(NombreTecla) );

    end;
    Respond

    RE: There is a way to return 1 time the keystroke?
    Mark Bell (Oct 20 2000 3:16AM)

    I have the same problem, and I can't switch it off.

    Does anyone have the answer.

    Thanks

    Mark Bell
    Respond

    RE: There is a way to return 1 time the keystroke?
    Hook (Nov 8 2000 6:32AM)

    I think that the problem is that the event is intercepted of pulsing and of loosing the key. One of them should be rejected.
    Respond

    RE: There is a way to return 1 time the keystroke?
    Jose Luis Ramirez (Sep 28 2001 3:28AM)

    From the Win32 SDK Help file you can discover a lot about KeyboardProc, but to answer your question it's quite simple.

    Bit number 31 of the lParam parameter "Specifies the transition state. The value is 0 if the key is being pressed and 1 if it is being released".

    So all you have to do is an "and bitmask" of lParam with 40000000 (in hex) and then determine if the result is greater tan zero. If it is (the key is about to get released) you can discard the PostMessage(...) so there wont be multiple keystrokes printed in the form.


    Respond














     
    Sign up to consume product discounts for Bronze memberships !

    read more


      Visit our Sponsor

     

      Community Ad of
    Hans Gulö
     
       














     







         
      Copyright © 2000 - 2007 delphi3000.com - All rights reserved. Terms of use. || Privacy
    delphi3000.com is a service by bluestep.com IT-Services GmbH (Vienna)