AS3 Movieclip not responding to Mouse_Wheel event - actionscript

I'm creating a container as a MovieClip and adding a mousewheel handler, then adding items to it like so:
container = new MovieClip();
addChild( container );
container.addEventListener( MouseEvent.MOUSE_WHEEL, HandleWheel );
container.addChild( item );
// etc. adding more items
However the mousewheel is only responding when the mouse is over one of the items, not over the visible areas of the container between the items. Is there any way to make it so the event is always triggered when the mouse is over the container, not just over its children?
I don't know if it's relevant, but the container has a mask set. I tried adding the listener to the mask and it didn't do anything, though.
If I set the opaqueBackground of the container to red, I can see the container bounds. I don't understand why the mouse wheel event isn't triggering when the mouse is within these bounds. If this is really not possible, is there another way to handle the situation without needing the container to respond directly to mouse events?
Thanks for any help.

"The opaque background region does not respond to mouse events."
From: http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/flash/display/DisplayObject.html#opaqueBackground

You may need to add a rectangle to the background to act like a bounding box. It can have its alpha set to 0%. The problem is that if the cursor is on a completely transparent area of the object, it will just not pass mouse events to it, as it shouldn't (otherwise we'd always be stuck with rectangular areas); in that case, adding the transparent backgrounds fixes it.

Related

Is there a workaround for something like "Form1.MousePreview:=true"?

I have two 100% overlapping panels with different contents on a form.
The first (static display of information) should be visible by default, but the other (user interaction) should replace it if the user moves the mouse near the two - and if the mouse moves away, it should switch back.
Something like this:
if (*the mouse is near*) then
begin
Panel1.Hide;
Panel2.Show;
end
else
begin
Panel2.Hide;
Panel1.Show;
end;
My problem is: where to capture mouse movement?
Each component has its own OnMouseMove handler - of course I could forward each of them to the forms handler, but I'd rather have something a bit more elegant (and easier to maintain).
The perfect solution would be something like Form1.MousePreview := true;.
Another solution would be assigning a generic handler that translates coordinates and calls the forms handler; The assigning could be done in FormCreate.
But that's not as easy as it seems, because one TImage already has its own mouse event handlers.
I have tried OnMouseEnter and OnMouseLeave of the two panels but it didn't work; #1 disappeared, but #2 did not appear. I guess that's because if the mouse leaves Panel2, it should disappear - but it also leaves it if it enters a button on it.
That's why I'd like to use a coordinate based approach to make the check more reliable.
Maybe the two panel method is completely wrong?
Update: Yes, it is, as Remy said.
I am now using a TJVPageList because a TPageControl has visual tabs.
The OnMouseEnter handler of the PageList sets one page, the OnMouseLeave sets the other; But once the mouse moves over the PageList, both pages start flickering.
I have tried adding the event handlers to each page, too, but that made no difference.
Should I check all OnMouseEnter / Leave events to filter out the PageList, the two pages and all components sitting on the pages?
Another update: I am using a TPageControl now, but the behaviour is similar.
It doesn't flicker, but if I move the mouse ontop the TPageControl, no TTabSheet is displayed at all.
Only if I press down the left mousebutton, the UI sheet is displayed. The other sheet is displayed normally if I move away the mouse. (The TJVPageList displays the UI page if I press the left mousebutton, too.)
I have used the mouse event handlers (enter/leave) of the TPageControl and both TTabSheets.
Update 3:
Done it.
The static Panel / TabSheet / JvStandardPage (#1) must not trigger the OnMouseLeave handler.
What you describe might be better served using a single TPageControl instead of two TPanel controls. Use the TPageControl's own OnMouseEnter/Leave events (or intercept the CM_MOUSEENTER/LEAVE messages) to switch the TPageControl.ActivePage as needed.

How to get the control under the mouse cursor in onMouseDown event?

I have a TGridLayout filled with some images in a Firemonkey HD Application. In the gridLayout's onMouseDown event I want to get the image object on which the user has clicked, but I have only mouse coordinates.
Implementing onMouseDown event for every image is not an option, because if an image is removed from the gridlayout an empty space remains. In this case I also want to know if the user has clicked in this empty area.
Is there a some kind of "getChildAtPos" or "FindVCLWindow" analog in Firemonkey?
Thanks!
TForm.ObjectAtPoint should do the trick.
FindVCLWindow does what you need. You need to specify the point at which the control is, in your case it's mouse position.

Check out whether or not Focus Rect is required (Delphi)

Imagine that we have a form with two buttons on it. I run the application and I click on the first button. nothing happens and no focus rectangle is displayed. But when I press a key, it shows a focus rect on the button and even if I click on the second one, it moves the focus rect to it. So it doesn't display the focus rect unless I press a key. I'm creating my own component and I need to know whether or not I should display the focus rect to draw it.
How do I know it?
I think it's not meant to display the focus rectangle by default, that's until a keyboard accelerator is used. Read UI State on MSDN, that suggests WM_QUERYUISTATE should be used to determine if keyboard accelerators or focus indicators should be drawn or not.

Avoid painting over nested controls

I am writing a toolbar-style control and use the ThemeServices unit to paint the background required by the toolbar. Like so:
ThemeServices.DrawElement(Canvas.Handle,
ThemeServices.GetElementDetails(trRebarRoot), ARect);
I then drop child controls onto the toolbar and voila - instant toolbar. Except that every now and again I notice that the nested (child) controls don't repaint as well. So my control paints its background and the child controls disappear until you move the mouse over them.
Some of the edit controls show their client area (no border) and some of them are just gone altogether.
This happens mostly when I place a window from another application over the toolbar and move it away.
I keep thinking this has to be very easy to cure, that perhaps I'm somehow preventing the paint message from reaching the child controls, or missing an override but I have been unable to figure it out.
For this to work properly so you do not end up over-painting the child controls from the WM_NCPaint, you can use the Window's GDI Region functions to create a clipping region which excludes the areas you do not want to paint.
You can do this by creating a Region using the CreateRectRgn (or similar) function with the size of your background.
Select this region in to the DC you are using via the SelectClipRgn function.
Next, loop through the top level child windows on your toolbar / panel and calling ExcludeClipRect with the appropriate coords for each child.
Finally when you paint, only the area's that have not been excluded will be painted.
Also be aware you might need to clear up your region (best check the GDI help).
That's normal for a canvas to have to repaint when covered by another windows control.
You should draw your tool bar in the OnPaint event of the container control.
OK, I found the problem myself. I was drawing the background in WM_NCPAINT because it is a gradiated background that cannot really be drawn bit by bit. I didn't realize that WM_NCPAINT is often called without the client controls being repainted. So I still paint the background in WM_NCPAINT but also in WM_PAINT. The latter is already clipped to exclude the border and to get the former to clip the client area, I called ExcludeClipRect.
This works like a treat.

How to make control invisible but responsive to mouse events?

I want to create a control (derived from TCustomControl) that is invisible but reacts to normal events (I want to use it to show a hint when moving the mouse over a custom element). I thought overriding the paint method and leaving it empty would do the job but unfortunately a rectangle is drawn where the component is.
How can I make the control completely invisible?
You can inherit from TGraphicControl instead of from TCustomControl, and leave the paint handler empty. Nothing will be drawn.
If you need a windowed control, then you should make sure that it has no border and uses the parent background. See this question for info on how to do that. You may need to override CreateParams() as well, to remove the border style bits.
If the control is not visible then process click messages in the parent, do a simple test for those being in the control's rectangle and use PostMessage to forward the message to the control. Such code may be more readable than empty paint handlers.
Bri

Resources