Ken Phipps wrote:
> I'm trying to create a simple component to draw rows/columns of 
> buttons. The first thing I'm trying to get done is the mouse event 
> handling. I was able to figure out how to catch the windows messages 
> and have them trigger published events from some examples I've found, 
> but I'm having a problem it. If you click very quickly in rapid 
> succession, the control seems to steal the mouse input for the entire 
> application. You can't even click on the form's close button as the 
> click gets taken.
> 
> In a test project, I notice that in a listbox that displays the 
> events when they are fired, when it shows a MouseUp event firing 
> without a corresponding MouseDown, that's when the control will begin 
> to steal all mouse input from that point onward. You have to kill the 
> app at that point. I read a post through a Google search about 
> problems like this happening with TGraphicControl descendants, so I 
> tried changing it to a TCustomPanel, but the problem is still there.

TGraphicControl already has mouse events. Are you sure the default 
handling isn't sufficient for your needs?

Remember that TGraphicControl doesn't have a handle of its own. It's 
just painted onto its parent. Any messages the control receives are 
second-hand -- messages that the windowed control decided to forward to 
the TGraphicControl.

When you click a control rapidly, you're creating double-clicks as well 
as clicks. The message sequence usually looks like this:

wm_LButtonDown
wm_LButtonUp
wm_LButtonDblClk
wm_LButtonUp

So that could explain your "up-with-down" phenomenon.

It's possible for a control to capture the mouse events, so they all go 
to that control instead of the control the mouse cursor is currently 
over. Capture is supposed to be terminated when the mouse gets clicked, 
though, so even if the first click of the close button doesn't work, the 
next should, unless the control is re-capturing the mouse each time. It 
shouldn't be doing that, though. I don't recall how capturing works in 
the VCL; search Controls.pas for "capture" and see what it turns up.

> procedure TMyButtonPanel.WM_LBUTTONDOWN(Var Msg: TWMLButtonDown);
> begin
>   if Assigned(FOnMouseDown) then FOnMouseDown(Self, mbLeft, 
> KeysToShiftState(Msg.Keys), Msg.XPos, Msg.YPos);
>   if Assigned(FOnMouseClick) then FOnMouseClick(Self, 0);

Merely depressing the mouse button does not usually count as a click. A 
click is a mouse down and a mouse up. If you're going to handling any 
kind of dragging, then you also need to pay attention to where the 
clicks occur; if the mouse up happens far enough away from the mouse 
down, then it's a drag and drop, not a click.

In these message handlers, you're not calling the inherited methods. 
You're omiting code that would normally run. That's a problem until you 
veryify that all the code is stuff you _intend_ to skip.

If you haven't already figured it out, writing a component will require 
reading a lot of the VCL source code, not only to see how descendants 
work, but to see how other unrelated controls respond to certain events 
or use features that you think you might need. Most of the Delphi 
documentation was not written with component developers as an audience.

-- 
Rob
_______________________________________________
Delphi mailing list -> [email protected]
http://www.elists.org/mailman/listinfo/delphi

Reply via email to