Solved

MOUSECLICK outside the client area of my control - how ??

Posted on 1997-06-10
12
1,009 Views
Last Modified: 2010-05-18
I am writing delphi components. For some of them i would need the mouse click event in every mouse position - even when the mouse cursor is NOT over the client area of the control.

The events from TControl

(like  procedure WMLButtonDown(var Message: TWMLButtonDown); message
WM_LBUTTONDOWN;    procedure Click; override; ...)

are only triggered when the mouse is over the control. I am sure there is a possibility.
-------------
Once again my problem: Imagine a Combobox. The Combobox is closing the drop down list automatically when the user clicks the mouse SOMEWHERE on the screen. I have some components that look like combos (and should behave like them) but they are not derived from TCombobox. They for example open a TForm for the drop down list.

So - how can i close this TForm on any (somewhere on the screen) mouseclick ???
-----------

Thank you very much for your help

Bernhard Angerer
Technical University Vienna
angerer@eftuv1.tuwien.ac.at

 
0
Comment
Question by:angerer
12 Comments
 
LVL 5

Expert Comment

by:julio011597
Comment Utility
You may want to have a look at the mouse 'capture' method (or was it a property? cannot remember).

I've made use of it (a long ago:); it may do the job, but it's a bit tricky to make it work properly.

Rgds, julio
0
 
LVL 4

Expert Comment

by:erajoj
Comment Utility
There are something like 1001 different solutions to this problem.
Could you possibly be more specific?

/// John

0
 

Expert Comment

by:kangadru
Comment Utility
Depending on the level of control you need for the mouse you have a couple of options.  The Mouse Capture method mentioned is of course an option but is rather unstable when used on NT, I'm not entirely certain why either. The Next option is much more difficult but is also much more complete and is probably the more appropriate.  The trick is to use a Global Hook, see the article on "Hooks in Win32" on the MSDN site a www.microsoft.com/msdn or if you have access to MSDN or Technet CD's there.  Hooks are best implemented as DLL's and since you are designing as components, I would suggest that you use LoadLibrary instead of static linking the DLL so that you may choose to leave the DLL unloaded when in csDesign reducing the risk of bring down the IDE and the CompLib inadvertantly.  If this is the route you choose to go, let me suggest that you also invest in the Delphi 3 upgrade as it's Interface implementation and improved header files will ease the conversion of the C code the MS samples are done in.  If I can find the code I will follow this up with the Code I wrote to do X-Mouse Focus follows mouse on NT before they added ActiveWindowTracking to the shell, (or more specifically, documented it :-))Andy
0
 
LVL 2

Expert Comment

by:icampbe1
Comment Utility
Hi there angerer,

I believe what you want is to process the 'WM_NCLButtonDown'  or  LButtonUp or R button up/down  etc etc....

These messages (WM_NC...) are sent in response to a mouse button in the NON-Client area.  You can do the standard window processing for them.

I'm sure this is what you want.  If not, I'll be more specific.

0
 
LVL 1

Author Comment

by:angerer
Comment Utility
Edited text of question
0
 
LVL 1

Author Comment

by:angerer
Comment Utility
Dear icampbel !

I think you understood me right. I tried it - but it did not work. (?)
I  think that this msg goes to the form in which my control is liying in. But i want my control to react on this.

Once again my problem: Imagine a Combobox. The Combobox is closing the drop down list automatically when the user clicks the mouse SOMEWHERE on the screen. I have some components that look like combos (and should behave like them) but they are not derived from TCombobox. They for example open a TForm for the drop down list.

So - how can i close this TForm on any (somewhere on the screen) mouseclick ???

Thank you very much (for your effort)

DI Bernhard Angerer
angerer@eftuv1.tuwien.ac.at

0
IT, Stop Being Called Into Every Meeting

Highfive is so simple that setting up every meeting room takes just minutes and every employee will be able to start or join a call from any room with ease. Never be called into a meeting just to get it started again. This is how video conferencing should work!

 
LVL 2

Expert Comment

by:icampbe1
Comment Utility
OK, I think I understand.  You want to detect a click 'Anywhere' on the screen.  You might have to subclass the WndProc routine of your application to catch the clicks.  Im sure you are familliar with this process.  You replace the Application's WndProc with one of your own. (GetWindowLong/SetWindowLong etc).  If the message is not interresting to you, you call the original routine.  In most cases, you call the original routine anyhow.  I can clarify further if you need more help.

Ian C.


0
 
LVL 2

Expert Comment

by:icampbe1
Comment Utility
I just read your earlier comment again.  What you can do is use my original solution, but have the form pass the click on the the control that it contains.  In fact, if you process the HitTest message (NCHITTEST I think), you can make the control believe that the mouse was clicked inside its own area.  I believe that you only want to inform the control of the click though, not of the exact click location.  OK?

Ian C.

0
 
LVL 1

Author Comment

by:angerer
Comment Utility
Dear icampbel !

I am sorry but i could not reach a solution with your information.

In the mean time i found a component that is managing exactly my problem. If you are interested you can find it on the delphi super page under the section freeware (file: selcombo.zip).

Thank you very much

DI Bernhard Angerer
angerer@eftuv1.tuwien.ac.at

PS: Your secound answer is - i think - a possibility but the component should manage this problem by itself.
0
 
LVL 12

Expert Comment

by:andrewjb
Comment Utility
Use MouseCapture to grab control over the mouse while you're displaying the combo box etc. This will deliver clicks to you if they hit anywhere on your application ( or anywhere on the screen if you are using Windows 3.1 ). Don't forget to release capture when the window has been removed.

You'll probably also need to watch for the exit event for the control, so you can spot if the user clicks on another application.

I wouldn't advise messing around with hooking into the record/playback events that windows offers. They really aren't designed for this at all. It isn't 'correct' windows programming for this problem.

In addition, you really don't want to be stealing the mouse do you, from everything else that is running. That's the whole point of windows - that you can ( attempt! ) to do more than one thing at once.

I'm sure we can come up with a complete solution if you actually post ( or e-mail ) some real code to us / me.


AJB


0
 

Accepted Solution

by:
iainmagee earned 100 total points
Comment Utility
Hi,

I've been doing a similar thing recently only with a popup menu based on a TListbox.

If I've read your question correctly the same principles should apply. What you need to do is trap the CM_CANCELMODE message in your component. This is generated when the user clicks anywhere else - including on the desktop or another application - provided your dropdown has the focus at the time.

In the handler make sure you ensure that you only process messages that don't originate from you own component! Your handler will look something like this:

procedure TNewComp.CMCANCELMODE(var Message: TCMCancelMode);
begin
  if Message.Sender <> Self then
    // Code to close or hide the dropdown window
end;

You may find that you will also need to trap the WM_KILLFOCUS message in order to get the desired effect. If you do this and you are actually destroying the dropdown window - make sure you don't free it twice - ie from the Cancelmode message and from the killfocus message.

Hope this sets you on the right track, need any more info please drop me a line at iainmagee@enterprise.net

Iain.
0
 
LVL 1

Author Comment

by:angerer
Comment Utility
thank you very much - this is excactaly the solution i was lookong for
0

Featured Post

Highfive Gives IT Their Time Back

Highfive is so simple that setting up every meeting room takes just minutes and every employee will be able to start or join a call from any room with ease. Never be called into a meeting just to get it started again. This is how video conferencing should work!

Join & Write a Comment

This article explains how to create forms/units independent of other forms/units object names in a delphi project. Have you ever created a form for user input in a Delphi project and then had the need to have that same form in a other Delphi proj…
Introduction The parallel port is a very commonly known port, it was widely used to connect a printer to the PC, if you look at the back of your computer, for those who don't have newer computers, there will be a port with 25 pins and a small print…
Polish reports in Access so they look terrific. Take yourself to another level. Equations, Back Color, Alternate Back Color. Write easy VBA Code. Tighten space to use less pages. Launch report from a menu, considering criteria only when it is filled…
This video shows how to remove a single email address from the Outlook 2010 Auto Suggestion memory. NOTE: For Outlook 2016 and 2013 perform the exact same steps. Open a new email: Click the New email button in Outlook. Start typing the address: …

763 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

13 Experts available now in Live!

Get 1:1 Help Now