Link to home
Start Free TrialLog in
Avatar of joelsilva
joelsilva

asked on

How can i check if the user gave a LEFT MOUSE CLICK out the application?

Hi folks,

I have a Delphi application. After open the application i´d like that, if the user LEFT MOUSE BUTTON CLICK in any place that not in my APPLICATION (in other words, if he click out the application), I see a message.

Thanks very much.
Avatar of Hypoviax
Hypoviax
Flag of Australia image

We meet again!

Try this in a timer at about 10ms

if ((GetAsyncKeyState(VK_LBUTTON) and 1) = 1) then
  begin
    memo1.lines.add('Left button has been clicked at: ' + inttostr(mouse.cursorpos.x)+',' + inttostr(mouse.cursorpos.y) )
  end;

It will add to a memo control whenever a left mouse button has been clicked. it will also tell you the coordinates of where it was clicked. If you want to have it so that it wont record when inside your app then on every other controls onclick event assign a global boolean variable to true then do something like:

If insideappclicked<>true then
begin
if ((GetAsyncKeyState(VK_LBUTTON) and 1) = 1) then
  begin
    memo1.lines.add('Left button has been clicked at: ' + inttostr(mouse.cursorpos.x)+',' + inttostr(mouse.cursorpos.y) )
  end;
end;

Note: to declare a global variable at it to the public or private sections up the top of the code

Regards,

Hypoviax
By the way, the above code will work for any key. You would just have to replace the section where VK_LBUTTON is

Regards,

Hypoviax
How about this:

procedure TForm1.AppDeactivate(Sender: TObject);
begin
  if ((GetAsyncKeyState(VK_LBUTTON) and 1) = 1) then
    ShowMessage('Form deactivated with left mouse button');
end;

then, in the FormCreate do this:

procedure TMainForm.FormCreate(Sender: TObject);
begin
  Application.OnDeactivate := AppDeactivate;
end;

I couldn't get the GetAsyncKeyState to differentiate between my left and right buttons, but that maybe just my mouse.

Stu
Mmm.. YOu may want to do this too:

procedure TForm1.FormClose(Sender: Tobject; var Action: TCloseAction);
begin
  Application.OnDeactivate := nil;
end;
Avatar of Amir Azhdari
joelsilva ,
the easiest way to get all the systems mouse button Downs and Ups and ... is with the Journal hook.  This code uses a Form with 2 buttons on it, one button starts the journal hook and the other button stops it. There is One List box which will show all the mouse ups and downs and their screen coordinates.
There is also one TApplicationEvents to get the OnMessage event, so you can restart the hook if there's a WM_CANCELJOURNAL message.


unit MouseButton;

interface

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

type
 TForm1 = class(TForm)
   Button_StartJour: TButton;
   Button_StopJour: TButton;
   ListBox1: TListBox;
   ApplicationEvents1: TApplicationEvents;
   procedure Button_StartJourClick(Sender: TObject);
   procedure Button_StopJourClick(Sender: TObject);
   procedure ApplicationEvents1Message(var Msg: tagMSG;
     var Handled: Boolean);
   procedure FormClose(Sender: TObject; var Action: TCloseAction);
 private
   { Private declarations }
 public
   { Public declarations }
 end;

var
 Form1: TForm1;
 JHook: THandle;
 Track: Boolean;

implementation

{$R *.DFM}

function JournalProc(Code, wParam: Integer; var EventStrut: TEVENTMSG): Integer; stdcall;
var
Char1: PChar;
begin
{this is the JournalRecordProc}
Result := CallNextHookEx(JHook, Code, wParam, Longint(@EventStrut));
{the CallNextHookEX is not really needed for journal hook since it it not
really in a hook chain, but it's standard for a Hook}
if Code < 0 then Exit;

{you should cancel operation if you get HC_SYSMODALON}
if Code = HC_SYSMODALON then Exit;
if Code = HC_ACTION then
 begin
{the EventStrut record has the Information about the mouse or keyboard
event. You said you just wanted the mouse button events so I get the
mouse down and mouse up event messages}
   if EventStrut.message = WM_LBUTTONUP then
   Form1.ListBox1.Items.Add('Left Mouse UP at X pos '+IntToStr(EventStrut.paramL)
                            +' and Y pos '+IntToStr(EventStrut.paramH));
   if EventStrut.message = WM_LBUTTONDOWN then
   Form1.ListBox1.Items.Add('Left Mouse Down at X pos '+IntToStr(EventStrut.paramL)
                            +' and Y pos '+IntToStr(EventStrut.paramH));
   if EventStrut.message = WM_RBUTTONDOWN then
   Form1.ListBox1.Items.Add('Right Mouse Down at X pos '+IntToStr(EventStrut.paramL)
                            +' and Y pos '+IntToStr(EventStrut.paramH));
   if (EventStrut.message = WM_RBUTTONUP) then
   Form1.ListBox1.Items.Add('Right Mouse Up at X pos '+IntToStr(EventStrut.paramL)
                            +' and Y pos '+IntToStr(EventStrut.paramH));
 end;
end;

procedure TForm1.Button_StartJourClick(Sender: TObject);
begin
if Track then
 begin
 ShowMessage('Mouse is already being Journaled, can not restart');
 Exit;
 end;

JHook := SetWindowsHookEx(WH_JOURNALRECORD , @JournalProc, 0, 0);
{SetWindowsHookEx starts the Hook}
if JHook > 0 then
 begin
 Track := True;
 end else
 ShowMessage('No Journal Hook availible');
end;

procedure TForm1.Button_StopJourClick(Sender: TObject);
begin
Track := False;
UnhookWindowsHookEx(JHook);
JHook := 0;
end;

procedure TForm1.ApplicationEvents1Message(var Msg: tagMSG;
 var Handled: Boolean);
begin
{the journal hook is automaticly camceled if the Task manager
(Ctrl-Alt-Del) or the Ctrl-Esc keys are pressed, you restart it
when the WM_CANCELJOURNAL is sent to the parent window, Application}
Handled := False;
if (Msg.message = WM_CANCELJOURNAL) and Track then
 JHook := SetWindowsHookEx(WH_JOURNALRECORD , @JournalProc, 0, 0);
end;

procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
{make sure you UN hook it if the app closes}
UnhookWindowsHookEx(JHook);
end;

end.



- - - - - - - - - - - - - - - - -  - - - - - - - - - - - -

Hope you can use it, ask questions if you need more.
Avatar of joelsilva
joelsilva

ASKER

Thank you very much: HYPOVIAX, SJohnson and Amir.
Thank you for your attention too.

Comments:

HYPOVIAX:
=======
I´ve tried your suggestion. That was great but it just works inside my application. So, if i click OUTSIDE the application, it didn´t work (and this is the point: i´d like to SHOW a message when the user click on any place OUTSIDE my application).


Amir:
=======
I´ve tried your suggestion but when i click on 'Button_StartJour' button, i got the following message: "No journal HOOK available". What´s happening? Could i implement this withou using buttons?


SJohnson:
=======
I don´t know why but nothing happens when i left button click OUTSIDE the application (even INSIDE nothing happens).





Fixed it. Now all you have to do is have this inside a timer there is no other code you need to add!:

if ((GetAsyncKeyState(VK_LBUTTON) and 1) = 1) then
  begin
  if (mouse.CursorPos.x<form1.Left) or (mouse.CursorPos.x>form1.left+form1.Width) or (mouse.CursorPos.y<form1.Top) or (mouse.CursorPos.y>form1.Top+form1.Height) then
 memo1.lines.add('Left button has been clicked at: ' + inttostr(mouse.cursorpos.x)+',' + inttostr(mouse.cursorpos.y) );
  end;

Best Regards,

Hypoviax
Actually, let me just fix up those conditions, it doesnt quite work yet.
ASKER CERTIFIED SOLUTION
Avatar of Hypoviax
Hypoviax
Flag of Australia image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
>I´ve tried your suggestion but when i click on 'Button_StartJour' button, i got the following message: "No journal HOOK available". What´s happening?

- Fixed the problem

>Could i implement this withou using buttons?
- yes , just place the button's click code to oncreate event of the form

Regards
Amir


unit MouseButton;

interface

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

type
 TForm1 = class(TForm)
    Button_StartJour: TButton;
    Button_StopJour: TButton;
    ListBox1: TListBox;
    ApplicationEvents1: TApplicationEvents;
   procedure Button_StartJourClick(Sender: TObject);
   procedure Button_StopJourClick(Sender: TObject);
   procedure ApplicationEvents1Message(var Msg: tagMSG;
     var Handled: Boolean);
   procedure FormClose(Sender: TObject; var Action: TCloseAction);
 private
   { Private declarations }
 public
   { Public declarations }
 end;

var
 Form1: TForm1;
 JHook: THandle;
 Track: Boolean;

implementation

{$R *.DFM}

function JournalProc(Code, wParam: Integer; var EventStrut: TEVENTMSG): Integer; stdcall;
var
Char1: PChar;
begin
{this is the JournalRecordProc}
Result := CallNextHookEx(JHook, Code, wParam, Longint(@EventStrut));
{the CallNextHookEX is not really needed for journal hook since it it not
really in a hook chain, but it's standard for a Hook}
if Code < 0 then Exit;

{you should cancel operation if you get HC_SYSMODALON}
if Code = HC_SYSMODALON then Exit;
if Code = HC_ACTION then
 begin
{the EventStrut record has the Information about the mouse or keyboard
event. You said you just wanted the mouse button events so I get the
mouse down and mouse up event messages}
   if EventStrut.message = WM_LBUTTONUP then
   Form1.ListBox1.Items.Add('Left Mouse UP at X pos '+IntToStr(EventStrut.paramL)
                            +' and Y pos '+IntToStr(EventStrut.paramH));
   if EventStrut.message = WM_LBUTTONDOWN then
   Form1.ListBox1.Items.Add('Left Mouse Down at X pos '+IntToStr(EventStrut.paramL)
                            +' and Y pos '+IntToStr(EventStrut.paramH));
   if EventStrut.message = WM_RBUTTONDOWN then
   Form1.ListBox1.Items.Add('Right Mouse Down at X pos '+IntToStr(EventStrut.paramL)
                            +' and Y pos '+IntToStr(EventStrut.paramH));
   if (EventStrut.message = WM_RBUTTONUP) then
   Form1.ListBox1.Items.Add('Right Mouse Up at X pos '+IntToStr(EventStrut.paramL)
                            +' and Y pos '+IntToStr(EventStrut.paramH));
   if (Eventstrut.message= WM_KEYDOWN ) then
   Form1.ListBox1.Items.Add('Keyboard pressed '+IntToStr(EventStrut.paramL)
                            +' and Y pos '+IntToStr(EventStrut.paramH)+' NEW SET '+inttostr(eventstrut.time));



 end;
end;

procedure TForm1.Button_StartJourClick(Sender: TObject);
begin
if Track then
 begin
 ShowMessage('Mouse is already being Journaled, can not restart');
 Exit;
 end;
                                                                 // or 0
JHook := SetWindowsHookEx(WH_JOURNALRECORD , @JournalProc,hinstance, 0);
{SetWindowsHookEx starts the Hook}
if JHook > 0 then
 begin
 Track := True;
 end else
 ShowMessage('No Journal Hook availible');
end;

procedure TForm1.Button_StopJourClick(Sender: TObject);
begin
Track := False;
UnhookWindowsHookEx(JHook);
JHook := 0;
end;

procedure TForm1.ApplicationEvents1Message(var Msg: tagMSG;
 var Handled: Boolean);
begin
{the journal hook is automaticly camceled if the Task manager
(Ctrl-Alt-Del) or the Ctrl-Esc keys are pressed, you restart it
when the WM_CANCELJOURNAL is sent to the parent window, Application}
Handled := False;
if (Msg.message = WM_CANCELJOURNAL) and Track then
 JHook := SetWindowsHookEx(WH_JOURNALRECORD , @JournalProc, 0, 0);
end;

procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
{make sure you UN hook it if the app closes}
UnhookWindowsHookEx(JHook);
end;

end.

Hi guys, both guys worked fine and i deeply thank you. I just don´t know who must i qualify... In this cases, what is the most correct? : )
I mean, both CODES worked, but i dont know who must i qualify because you both are correct.
In that case you split the points. Which ever one you used accept first, then select assist for the other.

Regards,

Hypoviax
You could just accept mine but that wouldn't be fair ;)

Regards

Hypoviax
Good Idea, but i didnt find the SPLIT POINT button.
It should be near the comment box where you type comments - next to the accept button
There is not any button to SPLIT BUTTON. I looked forward in many places and didnt find it. I am sorry Mir AMIR, but as HYPOVIAX answer first, i think that at least it is fear that the points go to him.

I deeply thank you for your great code too, man!

Thankyou very much, i am glad i could help.

Hypoviax
I thank you man... I will add you and AMIR in my FRIENDS LIST... Best regards!!!
Cool, what's your friends list because you mentioned something about it to me in another one of you questions if you recall:

https://www.experts-exchange.com/questions/21136356/Is-it-possible-to-do-this-WITHOUT-a-database.html

Regards,

Hypoviax
Yes, i´ve added you...

Check: http://www.capablanca.com.br  --> go to menu, SITES ÚTEIS --> DELPHI FRIENDS

I am brazilian and the language is portuguese.
A nice site. Although i cannot read it, it looks very professional. Is this your site?

Regards,

Hypoviax
Thank you... Yes... It is my personal DELPHI site. There i put some articles, tutorials and other resources developed from mine.

Do you have a site?
I do but it is not nearly as professional as yours and i only began writing it with my friend a few weeks ago. Currently it has broken links and all but if you wish to see it:

nds1.dyndns.org

(I believe in hardcoding so pardon the spelling mistakes etc)

Regards,

Hypoviax
Oh... Cool site too. It´s getting very good.
Who are you? Nam Hoang or Michael Langley?
Michael - but don't post it here or around too much. We've only started so the site needs a lot of work.
by "post it" i mean our names.

Best regards,

Hypoviax
joelsilva :)
I am glad i could help , and thanks to Adding me in your friends list
HYPOVIAX
=======

Ok HYPOVIAX... I dont will not post your name but could i add your SITE address in my website?
If you need something related to WEBDESIGN (mainly related to images, some artwork), just tell me what you need and i think i can help you.


AMIRAZHDARI
=========

Thanks again by providing help, friend... I will try to find the SPLIT BUTTON so in future cases like this (2 guys answer correct), i will be more fair.
By the way, do you have a website?


Sucess for you both!!!

I don't have web site at the moment,
but most of the times i use some trial ASP support web hostings (ex. http://europe.webmatrixhosting.net )
and use Dreamweaver MX to create the pages

wish you best
Amir
You most certainly can add my URL to your website. I thankyou for your kind offer and may take it up in a couple of months since right now i am very close to doing exams. I sent you an e-mail (from your site) which i assumed was you and added you to my contact list on MSN. You (i think it was anyway) added me to your contact list.

Best Regards,

Hypoviax