Simulate clicks/double clicks globally?

Hi,
How can I simulate single clicks and double clicks GLOBALLY(ie. anywhere in the screen)?
I want to do this only with the built-in components in Delphi.
(D2/Win95/Sample code expected)
yingkitAsked:
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.

WiseGuyCommented:
So you want to sent a windows message but not to a specific window handle?
0
yingkitAuthor Commented:
What I want is just to send single/double clicks to any specified x,y coordinates on the screen...
0
WiseGuyCommented:
You would have to find out the windows message that decodes this.

Say this message is <M>.
Then you call this windows api method:

PostMessage(HWND_BROADCAST,M,X,Y)

it might be the other way around for the X and Y coordinates

PostMessage(HWND_BROADCAST,M,Y,X)


See the Win32.hlp file in program files\common files\borland shared\mshelp
0
Cloud Class® Course: CompTIA Cloud+

The CompTIA Cloud+ Basic training course will teach you about cloud concepts and models, data storage, networking, and network infrastructure.

yingkitAuthor Commented:
Sample code?
0
WiseGuyCommented:
working on it.
 
0
yingkitAuthor Commented:
Thx
0
MadshiCommented:
Well, I see 3 possibilites:

(1) WiseGuy's suggestion.
(2) Use WindowFromPoint to get the window handle at the position, where you want to simulate the clicks. Then call PostMessage(window, WM_LBUTTONDOWN, ...) and PostMessage(window, WM_LBUTTONUP, ...).
(3) Use SetCursorPos. Then call Mouse_Event. This should work best. But the mouse is really moving to the simulated position.

Regards, Madshi.
0
WiseGuyCommented:
Well,

BroadCast doesn't work because the first window that accepts it takes the message from the queue. This window is hardly ever the one intended. The desktop is the most likely one.
So you would have to go with Madshi's option 2 or 3.

If I supply you with sample code, would you both consider that an answer
0
MadshiCommented:
Yes...   :-)   Post an answer...
0
WiseGuyCommented:
as soon as I got it working.

It turns out that only Mouse_Event works.
I call it, indirectly from a button.click.
This makes this click trigger all of the time.
I'm trying to solve this with a timer, so that the click event is finished before a new mouse event takes place.
0
men xinCEOCommented:
why dont you use mouse_event API?

to simulate single clicks :
mouse_event()
  mouse_event(MOUSEEVENTF_LEFTDOWN,x,y,0,0);
  mouse_event(MOUSEEVENTF_LEFTUP,x,y,0,0);

and double clicks is
  mouse_event(MOUSEEVENTF_LEFTDOWN,x,y,0,0);
  mouse_event(MOUSEEVENTF_LEFTUP,x,y,0,0);
  mouse_event(MOUSEEVENTF_LEFTDOWN,x,y,0,0);
  mouse_event(MOUSEEVENTF_LEFTUP,x,y,0,0);

(x,y) is your mousepoint!
0
WiseGuyCommented:
Solved it!
The timers where not needed, I accidently had a OnChange Eventhandler somewhere

It is quite an eleborate answer, that might pay itself in your grading Yingkit
I made the code in Delphi 5, so delphi 2 will complain about non-existing properties. I see NO reason why it would not work though.
Here it goes: (first form then unit)

object Form1: TForm1
  Left = 188
  Top = 107
  Width = 260
  Height = 252
  Caption = 'Form1'
  Color = clBtnFace
  Font.Charset = DEFAULT_CHARSET
  Font.Color = clWindowText
  Font.Height = -11
  Font.Name = 'MS Sans Serif'
  Font.Style = []
  OldCreateOrder = False
  OnDblClick = FormDblClick
  PixelsPerInch = 96
  TextHeight = 13
  object Label1: TLabel
    Left = 32
    Top = 40
    Width = 7
    Height = 13
    Caption = 'X'
  end
  object Label2: TLabel
    Left = 32
    Top = 96
    Width = 7
    Height = 13
    Caption = 'Y'
  end
  object lblWhereX: TLabel
    Left = 56
    Top = 40
    Width = 6
    Height = 13
    Caption = '?'
  end
  object lblWhereY: TLabel
    Left = 54
    Top = 96
    Width = 6
    Height = 13
    Caption = '?'
  end
  object edtX: TEdit
    Left = 32
    Top = 56
    Width = 121
    Height = 21
    TabOrder = 0
    Text = '369'
  end
  object edtY: TEdit
    Left = 32
    Top = 112
    Width = 121
    Height = 21
    TabOrder = 1
    Text = '220'
  end
  object btnClick: TButton
    Left = 8
    Top = 160
    Width = 75
    Height = 25
    Caption = 'Click'
    TabOrder = 2
    OnClick = btnClickClick
  end
  object btnDblClick: TButton
    Left = 104
    Top = 160
    Width = 75
    Height = 25
    Caption = 'DblClick'
    TabOrder = 3
    OnClick = btnDblClickClick
  end
  object RadioGroup1: TRadioGroup
    Left = 160
    Top = 32
    Width = 89
    Height = 105
    Caption = 'Mouse button'
    ItemIndex = 0
    Items.Strings = (
      'left'
      'right'
      'middle')
    TabOrder = 4
  end
  object Timer1: TTimer
    OnTimer = Timer1Timer
  end
end

unit ufMain;

interface

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

type
  TForm1 = class(TForm)
    edtX: TEdit;
    Label1: TLabel;
    Label2: TLabel;
    edtY: TEdit;
    btnClick: TButton;
    btnDblClick: TButton;
    RadioGroup1: TRadioGroup;
    Timer1: TTimer;
    lblWhereX: TLabel;
    lblWhereY: TLabel;
    procedure btnClickClick(Sender: TObject);
    procedure btnDblClickClick(Sender: TObject);
    procedure Timer1Timer(Sender: TObject);
    procedure FormDblClick(Sender: TObject);
  private
    { Private declarations }
    procedure WMLButtonDown(var Message: TWMLButtonDown); //message WM_LBUTTONDOWN;
  public
    { Public declarations }
    procedure SimulateDblClick(Msg : Cardinal; X, Y : Cardinal);
    procedure SimulateClick(Msg1, Msg2 : Cardinal; X, Y : Cardinal);
  end;

var
  Form1: TForm1;

implementation

{$R *.DFM}

procedure TForm1.btnClickClick(Sender: TObject);
var
  X,Y : Cardinal;
begin
  X := StrToInt(edtX.Text);
  Y := StrToInt(edtY.Text);
  case (self.RadioGroup1.ItemIndex) of
    -1: begin
      exit;
    end; {case-statement}
    0: begin
      // simulate left button click
      SimulateClick(MOUSEEVENTF_LEFTDOWN,MOUSEEVENTF_LEFTUP,X,Y);
    end; {case-statement}
    1: begin
      SimulateClick(MOUSEEVENTF_RIGHTDOWN,MOUSEEVENTF_RIGHTUP,X,Y);
    end; {case-statement}
    2: begin
      SimulateClick(MOUSEEVENTF_MIDDLEDOWN,MOUSEEVENTF_MIDDLEUP,X,Y);
    end; {case-statement}
  end; {case}
end;

procedure TForm1.btnDblClickClick(Sender: TObject);
var
  X,Y : Cardinal;
begin
  X := StrToInt(edtX.Text);
  Y := StrToInt(edtY.Text);
  case (self.RadioGroup1.ItemIndex) of
    -1: begin
      exit;
    end; {case-statement}
    0: begin
      // simulate left button click
      SimulateClick(MOUSEEVENTF_LEFTDOWN,MOUSEEVENTF_LEFTUP,X,Y);
      SimulateClick(MOUSEEVENTF_LEFTDOWN,MOUSEEVENTF_LEFTUP,X,Y);
    end; {case-statement}
    1: begin
      SimulateClick(MOUSEEVENTF_RIGHTDOWN,MOUSEEVENTF_RIGHTUP,X,Y);
      SimulateClick(MOUSEEVENTF_RIGHTDOWN,MOUSEEVENTF_RIGHTUP,X,Y);
    end; {case-statement}
    2: begin
      SimulateClick(MOUSEEVENTF_MIDDLEDOWN,MOUSEEVENTF_MIDDLEUP,X,Y);
      SimulateClick(MOUSEEVENTF_MIDDLEDOWN,MOUSEEVENTF_MIDDLEUP,X,Y);
    end; {case-statement}
  end; {case}
end;

procedure TForm1.SimulateClick(Msg1, Msg2: Cardinal; X, Y: Cardinal);
begin
  SetCursorPos(X,Y);
  mouse_event(MOUSEEVENTF_ABSOLUTE+Msg1,X,Y,0,0);
  mouse_event(MOUSEEVENTF_ABSOLUTE+Msg2,X,Y,0,0);
end;

procedure TForm1.SimulateDblClick(Msg: Cardinal; X, Y: Cardinal);
begin
  SetCursorPos(X,Y);
  mouse_event(MOUSEEVENTF_ABSOLUTE+Msg,X,Y,0,0);
end;

procedure TForm1.Timer1Timer(Sender: TObject);
var
  aPoint : TPoint;
begin
  GetCursorPos(aPoint);
  lblWhereX.Caption := IntToStr(aPoint.x);
  lblWhereY.Caption := IntToStr(aPoint.y);
end;

procedure TForm1.WMLButtonDown(var Message: TWMLButtonDown);
var
  aMes : TMessage;
begin
  Message.Result := 1;
  aMes := TMessage(Message);
end;

procedure TForm1.FormDblClick(Sender: TObject);
begin
  ShowMessage('DblClick');
end;

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
yingkitAuthor Commented:
EXCELLENT!
Thank you very much.
0
WiseGuyCommented:
yingkit,

what did you grade me?
0
yingkitAuthor Commented:
An "A" is given.
0
WiseGuyCommented:
Thanx,

I couldn't find what grade was given to me for what answer.


Yes, I already have answered more then one question

CU, Ramon
0
MadshiCommented:
WiseGuy, you can see that from the points you got. This q. was worth 40 points. If you got 4*40, you got an A grade. If you got 3*40 = B. 2*40 = C. 1*40 = D.
0
WiseGuyCommented:
I see,

I had noticed that I got more points than offered, but I thought it was related to the amount of experts participating in the discussion.

Thank you for salvaging me from my erronous way. :)
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.