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.
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.
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
Regards,
Hypoviax
How about this:
procedure TForm1.AppDeactivate(Sende r: TObject);
begin
if ((GetAsyncKeyState(VK_LBUT TON) and 1) = 1) then
ShowMessage('Form deactivated with left mouse button');
end;
then, in the FormCreate do this:
procedure TMainForm.FormCreate(Sende r: 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
procedure TForm1.AppDeactivate(Sende
begin
if ((GetAsyncKeyState(VK_LBUT
ShowMessage('Form deactivated with left mouse button');
end;
then, in the FormCreate do this:
procedure TMainForm.FormCreate(Sende
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;
procedure TForm1.FormClose(Sender: Tobject; var Action: TCloseAction);
begin
Application.OnDeactivate := nil;
end;
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(Send er: TObject);
procedure Button_StopJourClick(Sende r: 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.para mL)
+' and Y pos '+IntToStr(EventStrut.para mH));
if EventStrut.message = WM_LBUTTONDOWN then
Form1.ListBox1.Items.Add(' Left Mouse Down at X pos '+IntToStr(EventStrut.para mL)
+' and Y pos '+IntToStr(EventStrut.para mH));
if EventStrut.message = WM_RBUTTONDOWN then
Form1.ListBox1.Items.Add(' Right Mouse Down at X pos '+IntToStr(EventStrut.para mL)
+' and Y pos '+IntToStr(EventStrut.para mH));
if (EventStrut.message = WM_RBUTTONUP) then
Form1.ListBox1.Items.Add(' Right Mouse Up at X pos '+IntToStr(EventStrut.para mL)
+' and Y pos '+IntToStr(EventStrut.para mH));
end;
end;
procedure TForm1.Button_StartJourCli ck(Sender: TObject);
begin
if Track then
begin
ShowMessage('Mouse is already being Journaled, can not restart');
Exit;
end;
JHook := SetWindowsHookEx(WH_JOURNA LRECORD , @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_StopJourClic k(Sender: TObject);
begin
Track := False;
UnhookWindowsHookEx(JHook) ;
JHook := 0;
end;
procedure TForm1.ApplicationEvents1M essage(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_JOURNA LRECORD , @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.
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(Send
procedure Button_StopJourClick(Sende
procedure ApplicationEvents1Message(
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('
+' and Y pos '+IntToStr(EventStrut.para
if EventStrut.message = WM_LBUTTONDOWN then
Form1.ListBox1.Items.Add('
+' and Y pos '+IntToStr(EventStrut.para
if EventStrut.message = WM_RBUTTONDOWN then
Form1.ListBox1.Items.Add('
+' and Y pos '+IntToStr(EventStrut.para
if (EventStrut.message = WM_RBUTTONUP) then
Form1.ListBox1.Items.Add('
+' and Y pos '+IntToStr(EventStrut.para
end;
end;
procedure TForm1.Button_StartJourCli
begin
if Track then
begin
ShowMessage('Mouse is already being Journaled, can not restart');
Exit;
end;
JHook := SetWindowsHookEx(WH_JOURNA
{SetWindowsHookEx starts the Hook}
if JHook > 0 then
begin
Track := True;
end else
ShowMessage('No Journal Hook availible');
end;
procedure TForm1.Button_StopJourClic
begin
Track := False;
UnhookWindowsHookEx(JHook)
JHook := 0;
end;
procedure TForm1.ApplicationEvents1M
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_JOURNA
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.
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).
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_LBUT TON) and 1) = 1) then
begin
if (mouse.CursorPos.x<form1.L eft) or (mouse.CursorPos.x>form1.l eft+form1. Width) or (mouse.CursorPos.y<form1.T op) or (mouse.CursorPos.y>form1.T op+form1.H eight) then
memo1.lines.add('Left button has been clicked at: ' + inttostr(mouse.cursorpos.x )+',' + inttostr(mouse.cursorpos.y ) );
end;
Best Regards,
Hypoviax
if ((GetAsyncKeyState(VK_LBUT
begin
if (mouse.CursorPos.x<form1.L
memo1.lines.add('Left button has been clicked at: ' + inttostr(mouse.cursorpos.x
end;
Best Regards,
Hypoviax
Actually, let me just fix up those conditions, it doesnt quite work yet.
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
>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(Send er: TObject);
procedure Button_StopJourClick(Sende r: 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.para mL)
+' and Y pos '+IntToStr(EventStrut.para mH));
if EventStrut.message = WM_LBUTTONDOWN then
Form1.ListBox1.Items.Add(' Left Mouse Down at X pos '+IntToStr(EventStrut.para mL)
+' and Y pos '+IntToStr(EventStrut.para mH));
if EventStrut.message = WM_RBUTTONDOWN then
Form1.ListBox1.Items.Add(' Right Mouse Down at X pos '+IntToStr(EventStrut.para mL)
+' and Y pos '+IntToStr(EventStrut.para mH));
if (EventStrut.message = WM_RBUTTONUP) then
Form1.ListBox1.Items.Add(' Right Mouse Up at X pos '+IntToStr(EventStrut.para mL)
+' and Y pos '+IntToStr(EventStrut.para mH));
if (Eventstrut.message= WM_KEYDOWN ) then
Form1.ListBox1.Items.Add(' Keyboard pressed '+IntToStr(EventStrut.para mL)
+' and Y pos '+IntToStr(EventStrut.para mH)+' NEW SET '+inttostr(eventstrut.time ));
end;
end;
procedure TForm1.Button_StartJourCli ck(Sender: TObject);
begin
if Track then
begin
ShowMessage('Mouse is already being Journaled, can not restart');
Exit;
end;
// or 0
JHook := SetWindowsHookEx(WH_JOURNA LRECORD , @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_StopJourClic k(Sender: TObject);
begin
Track := False;
UnhookWindowsHookEx(JHook) ;
JHook := 0;
end;
procedure TForm1.ApplicationEvents1M essage(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_JOURNA LRECORD , @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.
- 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(Send
procedure Button_StopJourClick(Sende
procedure ApplicationEvents1Message(
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('
+' and Y pos '+IntToStr(EventStrut.para
if EventStrut.message = WM_LBUTTONDOWN then
Form1.ListBox1.Items.Add('
+' and Y pos '+IntToStr(EventStrut.para
if EventStrut.message = WM_RBUTTONDOWN then
Form1.ListBox1.Items.Add('
+' and Y pos '+IntToStr(EventStrut.para
if (EventStrut.message = WM_RBUTTONUP) then
Form1.ListBox1.Items.Add('
+' and Y pos '+IntToStr(EventStrut.para
if (Eventstrut.message= WM_KEYDOWN ) then
Form1.ListBox1.Items.Add('
+' and Y pos '+IntToStr(EventStrut.para
end;
end;
procedure TForm1.Button_StartJourCli
begin
if Track then
begin
ShowMessage('Mouse is already being Journaled, can not restart');
Exit;
end;
// or 0
JHook := SetWindowsHookEx(WH_JOURNA
{SetWindowsHookEx starts the Hook}
if JHook > 0 then
begin
Track := True;
end else
ShowMessage('No Journal Hook availible');
end;
procedure TForm1.Button_StopJourClic
begin
Track := False;
UnhookWindowsHookEx(JHook)
JHook := 0;
end;
procedure TForm1.ApplicationEvents1M
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_JOURNA
end;
procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
{make sure you UN hook it if the app closes}
UnhookWindowsHookEx(JHook)
end;
end.
ASKER
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? : )
ASKER
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
Regards,
Hypoviax
You could just accept mine but that wouldn't be fair ;)
Regards
Hypoviax
Regards
Hypoviax
ASKER
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
ASKER
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!
I deeply thank you for your great code too, man!
Thankyou very much, i am glad i could help.
Hypoviax
Hypoviax
ASKER
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
https://www.experts-exchange.com/questions/21136356/Is-it-possible-to-do-this-WITHOUT-a-database.html
Regards,
Hypoviax
ASKER
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.
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
Regards,
Hypoviax
ASKER
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?
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
nds1.dyndns.org
(I believe in hardcoding so pardon the spelling mistakes etc)
Regards,
Hypoviax
ASKER
Oh... Cool site too. It´s getting very good.
Who are you? Nam Hoang or Michael Langley?
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
Best regards,
Hypoviax
joelsilva :)
I am glad i could help , and thanks to Adding me in your friends list
I am glad i could help , and thanks to Adding me in your friends list
ASKER
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!!!
=======
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
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
Best Regards,
Hypoviax
Try this in a timer at about 10ms
if ((GetAsyncKeyState(VK_LBUT
begin
memo1.lines.add('Left button has been clicked at: ' + inttostr(mouse.cursorpos.x
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_LBUT
begin
memo1.lines.add('Left button has been clicked at: ' + inttostr(mouse.cursorpos.x
end;
end;
Note: to declare a global variable at it to the public or private sections up the top of the code
Regards,
Hypoviax