I have a large user drawn control that fills most of the screen area in an application.
I would like to simulate some "onMouseHover" behaviour, I cant really use the userControl event as the mouse is almost always on that control so it fires all of the time.
How can I detect the mouse "hovering" over part of my user drawn control?
(If it helps an image of the app can be found at : http://www.benbun.co.uk/st3/ayv the control is the large "year calendar")
You could handle MouseMove events instead of MouseHover. Then you could calculate based on the X,Y location of the mouse whether or not the cursor is in the part of your control you are interested in creating "hover" behavior for.
Related
On System.Windows.UIElement there is a CaptureMouse() and a paired ReleaseMouseCapture() method. In this WPF DragDrop sample they call CaptureMouse on MouseDown and release it on MouseUp. The documentation in MSDN is about as useless as it comes - "CaptureMouse -> Captures the mouse."
In my head before trying it I assumed that it somehow locked the mouse inside the UIElement bounds, but that's clearly not the case when I try it. From experimenting, it seems to have something to do with responding to events when the mouse is outside of the UIElement, but not wanting to be a cargo cult programmer I don't want to just use it because the example does, I'd like an authoritative description of what it means.
From Capture and Uncapture the Mouse on MSDN:
When an object captures the mouse, all mouse related events are treated as if the object with mouse capture perform the event, even if the mouse pointer is over another object.
Only the capturing control receives the mouse events until released.
Capturing the mouse is useful for dragging because all the dragging code can exist in the one control, rather than being spread over multiple controls.
When it has captured the mouse, a control will receive mouse events even if the mouse pointer is no longer within its bounding area.
Typically, it's used for:
Drag and drop
Buttons (to handle Mouse Up when you put the mouse down on the button and move the mouse before you release the button)
The Silverlight 2 documentation for it has a more verbose description, I don't know why it isn't a part of the 3.5 documentation page too:
When an object has captured the mouse, that object receives mouse input whether or not the mouse pointer is within its bounding area. The mouse is typically only captured during simulated drag operations.
...
It works the same with WPF, and so the reason it is used with DragDrop, is that is how the
it knows to report back to the control being dragged from when the mouse may be outside of that control. If you comment out the MyCanvas.Capture() and the Capture(Null) (which clears it) then you can no longer drop.
In WPF, I have a custom "toolbox" which consists of Label controls and some vector icons docked to the left of the screen.
In the center, I have a Canvas control which I eventually am going to need to serialize out the relative coordinates (for other platforms) for this "designer surface".
Basic question, I can drag/drop controls from this psuedo-control box onto a Canvas but I need to know how to place this WPF control properly in the canvas, under where the mouse pointer is, realtive to the Canvas and not the screen or main Window.
What are the functions that needed to be called so that I can ensure that if I drop a Button control at 10%, 20% of the canvas, I get an actual location back and the button drops where expected?
Mouse events provide a Point structure.
Converting of positions can be done by Control.PointToScreen and TargetControl.PointToClient.
The questions says it all.
How can I move a control, say a PictureBox between multiple panels, or betwween a panel and a flow layout panel.
I'm aware I can drag and drop controls between multiple panels and such, however this is does not make the control visually movable between the containers. The mouse only changes to a diferent cursor and after you drag to the other control and release the mouse button the control appears on the other container. I require the control to be visually movable.
Can someone provide a simple example, so I can extract the idea to apply to my situation.
NOTE: Runtime of course.
Assuming you need it runtime:
You can save the control as bitmap using Control.SaveToBitmap method
Create cursor from image.
Set the current cursor which we created from control.
Once drag and drop completed reset the cursor.
Let's take a simple example of dragging a button around.
Suppose you have two types of container controls:
1) an X-Y layout
2) a flow layout (assume left to right)
When you click to drag the button, record the x-offset and y-offset from the click to the top left corner of the control. As well, record the index of the control within the Controls collection.
As the mouse moves, first check if the mouse has changed container controls.
If so, then remove the button from its current parent and add it to the new parent.
If the button is added to a flow control, then you need to calculate the new index. To do this, calculate the distance from the mouse to the closest edge of a bounding box of all other controls. Then if the mouse is left of the center of that control, insert to that control's index minus 1, otherwise insert to the right of that control (index + 1).
If the button is added to an X-Y layout, then the index doesn't matter that much. You can simple just set the button's location relative to the mouse plus the x-offset, and y-offset.
As the mouse is dragging, you will need to force the controls to refresh. I think calling Invalidate() on the container control should be sufficient.
This should give you the basic idea that you could use to start coding something.
I'm looking for a way to check during a resizing event whether the control is currently being resized or whether it has reached its final size. (C# Windows Forms)
E.g. In Java with sliders, you can tell whether the user is currently sliding or whether they have released the mouse - this means that you can avoid expensive redraws or other calculations until the final value has been chosen.
Thanks in advance for any info.
The Form has a few events to help you with this
There's the ResizeBegin, Resize, and ResizeEnd Events. A combination of them should get you what you want.
Further notes:
When you click and drag the border of a window, the event sequence is ResizeBegin, repeated Resize for each move of the mouse, ResizeEnd. When you minimize, maximize or restore the window size, then Resize is called once for each of those. A ResizeBegin and ResizeEnd pair is also called for simply moving the window around as well by the title bar, though not when you programatically set the windows Location property.
I have a custom Canvas control (inherited from Canvas) overlaid over a large area of User Controls. The idea is to draw paths between user controls (i.e. connector lines).
To capture mouse movement, I call Mouse.Capture(theCanvas) on MouseDown. This works beautifully, but the user controls under the canvas obviously no longer receive mouse events. Mouse.DirectlyOver always shows the canvas, so I can't really fake it by peeking at the current position and seeing which user control it's over.
So, I still need the Canvas for drawing paths, but how can I solve this one of the following ways:
Peek under the Canvas and see what the topmost control is right under it?
Get this MouseDown -> Track MouseMoves -> MouseUp workflow to work on the canvas without mouse captures?
Any other ideas welcome...
I'd agree that those are your two options. If you want to only forward some clicks to your usercontrols, then go with option 1, and hit test the controls under the canvas.
If you need your usercontrols to behave as though there is nothing covering them (textboxes, buttons etc), then i'd recommend using the PreviewMouseMove event on the user control's parent, as this can pick up and optionally "handle" events before the controls get at the event, but it won't block the event if you don't set handled to true