How can i spy when user press a key

My Delphi app sitting in trayicon and spy, when user clicks a key my Delphi app will be able to sore it in INI file

How is this possible?
traustiAsked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

HamidHossainCommented:
How you do it ...

please tell me how you put it in the tray  ?? ..
0
traustiAuthor Commented:
I use a component
0
traustiAuthor Commented:
I use a component to add it to the traybar
0
Cloud Class® Course: Microsoft Exchange Server

The MCTS: Microsoft Exchange Server 2010 certification validates your skills in supporting the maintenance and administration of the Exchange servers in an enterprise environment. Learn everything you need to know with this course.

MadshiCommented:
If you want to get this to work under NT, too, you'll need to use SetWindowsHookEx(WH_KEYBOARD, ...), but in your own little DLL.
If you need that only for win9x, there's a component on

www.torry.ru

if I remember right. Don't remember the name, though...

Regards, Madshi.
0
traustiAuthor Commented:
I think i need an complete example
0
edeyCommented:
I beliieve Madshi is thinking of the RxWindowHook component. Here is a possible solution:

unit Unit1;

interface

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

type
  TForm1 = class(TForm)
    RxWindowHook1: TRxWindowHook;
    procedure RxWindowHook1AfterMessage(Sender: TObject; var Msg: TMessage;
      var Handled: Boolean);
    procedure FormCreate(Sender: TObject);
    procedure FormClose(Sender: TObject; var Action: TCloseAction);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;
  f : file of cardinal;

implementation

{$R *.DFM}

procedure TForm1.RxWindowHook1AfterMessage(Sender: TObject;
  var Msg: TMessage; var Handled: Boolean);
begin
     if msg.msg = WM_KEYDOWN then
        write(f,msg.wparam,msg.lparam)//write the virtual key code, then the "key data" code
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
     assignFile(f,extractFilePath(application.exeName)+'keystrokes.bin');
     rewrite(f);
end;

procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
     closeFile(f);
end;

end.



Note: as masdhi pointed out, for a winNT solution you would have to use a system hook from a .dll.  Also note that I used a file of int instead of an .ini file as it seemed more appropriate here




GL
Mike
0
traustiAuthor Commented:
Where can i find this component -> RxWindowHook ?
0
edeyCommented:
Ah, I just checked & the RxWindowHook only hooks one window, for a system hook you would need the .dll, a little more complicated. I do have anexample though, not sure who wrote it (came from a deja news article) but here it goes:

:. Downloaded from http://inner-smile.com/
 
library Sendkey;
{This code taken with permission from "Delphi Developer's Guide"   by Xavier Pacheco and Steve Teixeira.}
uses
SysUtils, WinTypes, WinProcs, Messages, Classes, KeyDefs;
type
  { Error codes }
  TSendKeyError = (sk_None, sk_FailSetHook, sk_InvalidToken,
sk_UnknownError);
  { exceptions }
  ESendKeyError = class(Exception);
  ESetHookError = class(ESendKeyError);
  EInvalidToken = class(ESendKeyError);
  { a TList descendant that know how to dispose of its contents }   TMessageList = class(TList)
  public
    destructor Destroy; override;
  end;
destructor TMessageList.Destroy;
var
  i: longint;
begin
  { deallocate all the message records before discarding the list }   for i := 0 to Count - 1 do
    Dispose(PEventMsg(Items[i]));
  inherited Destroy;
end;
var
  { variables global to the DLL }
  MsgCount: word;
  MessageBuffer: TEventMsg;
  HookHandle: hHook;
  Playing: Boolean;
  MessageList: TMessageList;
  AltPressed, ControlPressed, ShiftPressed: Boolean;
  NextSpecialKey: TKeyString;
function MakeWord(L, H: Byte): Word;
{ macro creates a word from low and high bytes }
inline(
  $5A/            { pop dx }
  $58/            { pop ax }
  $8A/$E2);      { mov ah, dl }
procedure StopPlayback;
{ Unhook the hook, and clean up }
begin
  { if Hook is currently active, then unplug it }
  if Playing then
    UnhookWindowsHookEx(HookHandle);
  MessageList.Free;
  Playing := False;
end;
function Play(Code: integer; wParam: word; lParam: Longint): Longint; export;
{ This is the JournalPlayback callback function.  It is called by Windows } { when Windows polls for hardware events.  The code parameter indicates what }
{ to do. }
begin
  case Code of
    hc_Skip: begin
    { hc_Skip means to pull the next message out of our list. If we }     { are at the end of the list, it's okay to unhook the JournalPlayback }     { hook from here. }
      { increment message counter }
      inc(MsgCount);
      { check to see if all messages have been played }
      if MsgCount >= MessageList.Count then
        StopPlayback
      else
      { copy next message from list into buffer }
      MessageBuffer := TEventMsg(MessageList.Items[MsgCount]^);
      Result := 0;
    end;
    hc_GetNext: begin
    { hc_GetNext means to fill the wParam and lParam with the proper }     { values so that the message can be played back.  DO NOT unhook }     { hook from within here.  Return value indicates how much time until }     { Windows should playback message.  We'll return 0 so that it's }     { processed right away. }
      { move message in buffer to message queue }
      PEventMsg(lParam)^ := MessageBuffer;
      Result := 0  { process immediately }
    end
    else
      { if Code isn't hc_Skip or hc_GetNext, then call next hook in chain }       Result := CallNextHookEx(HookHandle, Code, wParam, lParam);   end;
end;
procedure StartPlayback;
{ Initializes globals and sets the hook }
begin
  { grab first message from list and place in buffer in case we }   { get a hc_GetNext before and hc_Skip }
  MessageBuffer := TEventMsg(MessageList.Items[0]^);
  { initialize message count and play indicator }
  MsgCount := 0;
  { initialize Alt, Control, and Shift key flags }
  AltPressed := False;
  ControlPressed := False;
  ShiftPressed := False;
  { set the hook! }
  HookHandle := SetWindowsHookEx(wh_JournalPlayback, Play, hInstance, 0);   if HookHandle = 0 then
    raise ESetHookError.Create('Couldn''t set hook')
  else
    Playing := True;
end;
procedure MakeMessage(vKey: byte; M: word);
{ procedure builds a TEventMsg record that emulates a keystroke and } { adds it to message list }
var
  E: PEventMsg;
begin
  New(E);                                { allocate a message record }
  with E^ do begin
    Message := M;                        { set message field }
    { high byte of ParamL is the vk code, low byte is the scan code }     ParamL := MakeWord(vKey, MapVirtualKey(vKey, 0));
    ParamH := 1;                          { repeat count is 1 }
    Time := GetTickCount;                { set time }
  end;
  MessageList.Add(E);
end;
procedure KeyDown(vKey: byte);
{ Generates KeyDownMessage }
begin
  { don't generate a "sys" key if the control key is pressed (Windows quirk) }
  if (AltPressed and (not ControlPressed) and (vKey in
[Ord('A')..Ord('Z')])) or
    (vKey = vk_Menu) then
    MakeMessage(vKey, wm_SysKeyDown)
  else
    MakeMessage(vKey, wm_KeyDown);
end;
procedure KeyUp(vKey: byte);
{ Generates KeyUp message }
begin
  { don't generate a "sys" key if the control key is pressed (Windows quirk) }
  if AltPressed and (not ControlPressed) and (vKey in [Ord('A')..Ord('Z')]) then
    MakeMessage(vKey, wm_SysKeyUp)
  else
    MakeMessage(vKey, wm_KeyUp);
end;
procedure SimKeyPresses(VKeyCode: Word);
{ This function simulates keypresses for the given key, taking into } { account the current state of Alt, Control, and Shift keys }
begin
  { press Alt key if flag has been set }
  if AltPressed then
    KeyDown(vk_Menu);
  { press Control key if flag has been set }
  if ControlPressed then
    KeyDown(vk_Control);
  { if shift is pressed, or shifted key and control is not pressed... }   if (((Hi(VKeyCode) and 1) <> 0) and (not ControlPressed)) or ShiftPressed then
    KeyDown(vk_Shift);    { ...press shift }
  KeyDown(Lo(VKeyCode));  { press key down }
  KeyUp(Lo(VKeyCode));    { release key }
  { if shift is pressed, or shifted key and control is not pressed... }   if (((Hi(VKeyCode) and 1) <> 0) and (not ControlPressed)) or ShiftPressed then
    KeyUp(vk_Shift);      { ...release shift }
  { if shift flag is set, reset flag }
  if ShiftPressed then begin
    ShiftPressed := False;
  end;
  { Release Control key if flag has been set, reset flag }
  if ControlPressed then begin
    KeyUp(vk_Control);
    ControlPressed := False;
  end;
  { Release Alt key if flag has been set, reset flag }
  if AltPressed then begin
    KeyUp(vk_Menu);
    AltPressed := False;
  end;
end;
procedure ProcessKey(S: String);
{ This function parses each character in the string to create the message list }
var
  KeyCode: word;
  Key: byte;
  index: integer;
  Token: TKeyString;
begin
  index := 1;
  repeat
    case S[index] of
      KeyGroupOpen : begin
      { It's the beginning of a special token! }
        Token := '';
        inc(index);
        while S[index] <> KeyGroupClose do begin
          { add to Token until the end token symbol is encountered }           Token := Token + S[index];
          inc(index);
          { check to make sure the token's not too long }
          if (Length(Token) = 7) and (S[index] <> KeyGroupClose) then             raise EInvalidToken.Create('No closing brace');
        end;
        { look for token in array, Key parameter will }
        { contain vk code if successful }
        if not FindKeyInArray(Token, Key) then
          raise EInvalidToken.Create('Invalid token');
        { simulate keypress sequence }
        SimKeyPresses(MakeWord(Key, 0));
      end;
      AltKey : begin
        { set Alt flag }
        AltPressed := True;
      end;
      ControlKey : begin
        { set Control flag }
        ControlPressed := True;
      end;
      ShiftKey : begin
        { set Shift flag }
        ShiftPressed := True;
      end;
      else begin
      { A normal character was pressed }
        { convert character into a word where the high byte contains }         { the shift state and the low byte contains the vk code }         KeyCode := vkKeyScan(MakeWord(Byte(S[index]), 0));
        { simulate keypress sequence }
        SimKeyPresses(KeyCode);
      end;
    end;
    inc(index);
  until index > Length(S);
end;
function SendKeys(S: String): TSendKeyError; export;
{ This is the one entry point.  Based on the string passed in the S  } { parameter, this function creates a list of keyup/keydown messages, } { sets a JournalPlayback hook, and replays the keystroke messages.  } var
  i: byte;
begin
  try
    Result := sk_None;                  { assume success }
    MessageList := TMessageList.Create;  { create list of messages }     ProcessKey(S);                      { create messages from string }
    StartPlayback;                      { set hook and play back messages }   except
    { if an exception occurs, return an error code, and clean up }     on E:ESendKeyError do begin
      MessageList.Free;
      if E is ESetHookError then
        Result := sk_FailSetHook
      else if E is EInvalidToken then
        Result := sk_InvalidToken;
    end
    else
      { Catch-all exception handler ensures than an exception }
      { doesn't walk up into application stack }
      Result := sk_UnknownError;
  end;
end;
exports
  SendKeys index 1;
begin
end
0

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
edeyCommented:
Oh, and the RX Component Collection is available here: http://www.rxlib.com/index.html


GL
Mike
0
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
Delphi

From novice to tech pro — start learning today.