Hi there,

I just bumped across this website through google and found it very neat. I am self taught at Delphi, and know very little. I know there are quite a few ways to send the virtual keypresses, but I only know of one and I doubt I am using it properly.

procedure TForm1.Timer1Timer(Sender: TObject);
var
Int10: Integer;
begin
if Odd(GetAsyncKeyState(VK_F10)) then //Hotkey on F10.
  begin
    Inc(Int10);
    Timer2.Interval:=StrToInt(Edit1.Text);
  end;
if odd(Int10) then //If on
  begin
    Timer2.Enabled:=True; //Enables the keypress.
  end
else //If off
  begin
    Timer2.Enabled:=False;//Disables the keypress.
  end;
end;

procedure TForm1.Timer2Timer(Sender: TObject);
var
Window:hwnd;
begin
Window:=FindWindowA('notepad',nil); //Finds notepad.
if Window<>0 then
begin
keybd_event(Ord('B'), 0, 0, 0);
end;
end;

I found Delphi Tricks and there are a few ways of sending key presses, however I do not understand them. I only want Keydown in this application so it holds down B. I have tried googling and found some other examples, but I'm not sure if I am incorporating them in properly.

I appreciate your assistance!

Sincerely,
Ab.

Post Scriptum: I apologize if I was not being specific enough.

Recommended Answers

All 6 Replies

That timer event will not work like you expect. The Int10 is not guaranteed to have any specific value. While it may appear to work sometimes (just as a fluke of how the stack works), it will suddenly break and work differently.

In either case, you should not enable the timer in a timer event. Only disable.

The way to do it is:

procedure Form1.sendNsecondsWorthOfBtoNotepad( n: integer );
  // Add this procedure to the private, protected, or public part of your form class.
  begin
  timer1.interval := 100;    // one keypress every 1/10th second
  timer1.tag      := n /10;  // number of timeout events to process
  timer1.enabled  := TRUE
  end;

procedure Form1.Timer1Timer( sender: tObject );
  // This is the timeout event
  begin
  // Send the keystroke
  keybd_event(Ord('B'), 0, 0, 0);

  // One tenth second has passed
  timer1.tag := timer1.tag -100;

  // If time is up, stop sending keystrokes
  if timer1.tag = 0 then timer1.enabled := FALSE
  end;

procedure Form1.Button1Click( sender: tObject );
  // This procedure starts the process
  var ms: integer;
  begin
  // Convert the user's input if possible. (If not, complain.)
  try ms := strToInt( edit1.text )
  except
    showMessage( 'You must specify the number of milliseconds to send keystrokes' );
    edit1.setFocus;
    exit
    end;
  sendNsecondsWorthOfBtoNotepad( ms )
  end;

Hope this helps.

I'm still unsure of where to add the procedure even though it says:

//Add this procedure to the private, protected, or public part of your form class.

I tried to put it in a couple of different places (like under the public declarations), but it did not work (meaning I got an error). I know this is supposed to be obvious, but I unfortunately have little experience.

Make sure your form class looks something like this:

type
  TForm1 = class(TForm)
    ...
  public:
    { Public declarations }
    procedure sendNsecondsWorthOfBtoNotepad( n: integer );
  end;

...

implementation
{$R *.RES}

procedure Form1.sendNsecondsWorthOfBtoNotepad( n: integer );
  var ...
  begin
  ...
  end;

Hope this helps.

Thank you so much for replying, I really don't know how to thank you. The problem seemed to be solved, but another one came up! Here is your source:

[TEX]unit Unit1;

interface

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

type
TForm1 = class(TForm)
Timer1: TTimer;
Edit1: TEdit;
Button1: TButton;
procedure Timer1Timer(Sender: TObject);
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
procedure sendNsecondsWorthOfBtoNotepad( n: integer );
end;

var
Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.sendNsecondsWorthOfBtoNotepad(n: Integer);
begin
Timer1.Interval := 100;
Timer1.Tag := n /10;
Timer1.Enabled := True
end;

procedure TForm1.Timer1Timer(Sender: TObject);
begin
keybd_event(Ord('B'), 0, 0, 0);
Timer1.Tag := Timer1.Tag -100;
if Timer1.Tag = 0 then Timer1.Enabled := False
end;

procedure TForm1.Button1Click(Sender: TObject);
var ms: Integer;
begin
try ms := StrToInt(Edit1.Text)
except
ShowMessage( 'You must specify the number of milliseconds to send keystrokes' );
Edit1.SetFocus;
exit
end;
sendNsecondsWorthOfBtoNotepad(ms)
end;
end.[/TEX]

The line:
[TEX]Timer1.Tag := n /10;[/TEX]
gives me the following errors:

[Error] Unit1.pas(32): Incompatible types: 'Integer' and 'Extended'
[Fatal Error] Project1.dpr(5): Could not compile used unit 'Unit1.pas'

I'm trying to fix it, but I do not understand what "extended" means.

Oh, and I'm jealous of your skill in Delphi!!!!

Ab.

It comes with time.

Sorry, for the error. I accidentally mixed C and Pascal. The line should read Timer1.Tag := n div 10; The "extended" is the IEEE 80-bit Extended Precision floating point type. Pascal converts single, double, and real to extended when performing calculations.

The "extended" is the IEEE 80-bit Extended Precision floating point type. Pascal converts single, double, and real to extended when performing calculations.

Ohh, I never knew that until now (Cool tid-bit).

Thanks for solving my question! =]

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.