C# Form not catching any mouse event - c#

I have few controls (Label, Custom Textbox, Datagridview) docked on a form. When I tried to hook the MouseMove event to the individual controls, the event fires perfectly fine but when I tried to hook the event on the form itself, the mousemove event do not respond at all. What could be the possible cause of this?
Edit:
Here is the event hook from resources.cs
this.MouseMove += new System.Windows.Forms.MouseEventHandler(this.LogicSimulationViewerForm_MouseMove);
and here is the function handled on catching the event
private void LogicSimulationViewerForm_MouseMove(object sender, MouseEventArgs e)
{
//DOESN'T WORK!!!
}

Winforms events don't bubble up like in WPF or in Html. Therefore if the controls are docked on the form, the form doesn't expose any surface of it's own and it doesn't catch any mouse events. However 'under water', all windows messages (a mouse move is a windows message), do pass the form, so it is possible to catch that message.
edit
Tigran has linked to a good example for the use of IMessageFilter that makes creating another example a bit superfluous :)

The cause of this is that in difference of WPF in WindowsForms the event is "blocked" by the control that handled it (in WPF the event will be pushed to the parent up to the Visual Tree, or in opposite direction: from parent to child).
So to catch that event you need to process it on application level and do not subscribe to single control event.
For more detailed example how to handle it can look here:
How do I capture the mouse mouse move event in my winform application

Related

C# TreeView disable scrolling in UserControl [duplicate]

I have a little problem with winforms and mousewheel events.
I have a custom user control representing a slider. Now, I have a couple groups of sliders in which each group is wrapped inside a panel. All the groups are then wrapped in another panel (which has AutoScroll set to true) and this is wrapped in a form. The slider logic is implemented such that the mousewheel can be used to change its value. For this, the slider user control gets focus when the mouse is over the slider. However, when I scroll, also the AutoScroll parent panel scrolls with it.
I've already lost a lot of time on this issue. Anybody knows what is happening here and how I can solve it? I thought the event was bubbling to the parent panel but I don't find a Handled property on the event when handling it in the Slider control (as is possible with WPF).
many thanks
We implemented the Slider as a complete custom user control (inheriting the UserControl class) with own look-and-feel.
You might have noticed that a UserControl doesn't show the MouseWheel event in the Properties window. Hint of trouble there. The WM_MOUSEWHEEL message bubbles. If the control that has the focus doesn't handle it then Windows passes it on to its Parent. Repeatedly, until it finds a parent window that wants to handle it. The Panel in your case.
You'll need to invoke a bit of black magic in your slider control. The actual event args object that get passed to the MouseWheel event is not of the MouseEventArgs type as the event signature suggests, it is HandledMouseEventArgs. Which lets you stop the bubbling. Like this:
protected override void OnMouseWheel(MouseEventArgs e) {
base.OnMouseWheel(e);
// do the slider scrolling
//..
((HandledMouseEventArgs)e).Handled = true;
}
If you are creating event dynamically like
object.event += new EventHandler<EventArgs>(eventfunction);
try un-registering the event after the eventfunction is called like this
object.event -= new EventHandler<EventArgs>(eventfunction);

Form events not fired when other control is in place

I have an application that contains a form with multiple controls.
I have subscribed to the form mouse up event. However when I click on the form if thewre is an other control placed on the form the event is not fired.
So, I would like to capture an form event on the form (even when an control is in place). Is this possible?
Thanks in advance.
As far as i know windows forms doesn't implement the concept of event bubbling. So you should manually tweak controls to handle the event. You can do it manually looping through all controls, or you can create some kind of wrapper for your form/container to subscribe to the event automatically. You may check general implementation of this idea here. .

Receiving touch events outside of custom control

I am developing a custom user control in WPF and trying to receive all touch events OUTSIDE of my control (so I can implement "cancel touches", where the user cancels an action by tapping somewhere else). Is there any good way to do this? Obviously, if I use TouchDown or other events I will only get notified of touches inside my control.
I tried receiving PreviewTouchDown events from Application.Current.MainWindow, but besides the fact it feels kind of dirty it also doesn't work that well - as soon as I capture those events, the SurfaceListBox inside my custom control stops working (it does not recognize touches anymore).
Is there a good way to solve this? Receiving simply ALL touch events would be sufficient as well, I can then check if they are inside my control.
In WPF, events travel the tree of elements. Events starting with "Preview" are the ones that travel up to bottom, meaning from the parent to the elements it contains. In your case, TouchDown event will travel from the control in which it originates and then it will bubble up towards the parents. PreviewTouchDown will travel in the opposite direction: from the parent towards the control.
Your idea of handling PreviewTouchDown event in the Application.Current.MainWindow is a good one and should handle all PreviewTouchDown events, if this is what you want. But in your case, if you want to check if the event originates in your custom control, you should catch all the TouchDown events in your MainWindow and check their Source property, like this:
private void CommonClickHandler(object sender, RoutedEventArgs e)
{
FrameworkElement feSource = e.Source as FrameworkElement;
if(feSource.Name == "MyCustomControlName")
{
//cancel whatever you want to cancel
e.Handled=true;
}
}
Do not catch the PreviewTouchDown event as this one will first pop in the MainWindow and just later will go all the way to your control.
This msdn link should give you more information: http://msdn.microsoft.com/en-us/library/ms742806.aspx

How to prevent clicks from passing through a control to the one below it

I have a textbox in a groupbox, both with double click events. When I double click in the textbox both events are triggered.
How do I stop clicks in the textbox from passing through to the groupbox? I've tried putting "e.Handled = true;" at the end of the textbox_DoubleClick event but this makes no difference.
Because WPF uses a "tunneling / bubbling" model of event propagation, most events begin bubbling UP from the bottom of the visual tree. If you want to catch an event on the way down, there are Preview versions of the events that tunnel downwards. For example:
PreviewMouseDoubleClick
Set e.Handled = true in there.
In your GroupBox's DoubleClick event you could check the value of e.OriginalSource and if that value is not the GroupBox, ignore the event
private void TabItem_MouseDoubleClick(object sender, MouseButtonEventArgs e)
{
if (e.OriginalSource is GroupBox)
{
// Your code here
}
}
I believe ClickEvents are actually Direct Events, and not Tunneled/Bubbled events, so setting e.Handled in one won't cancel the other.
Per MSDN Site for MouseDoubleClick
Although this routed event seems to follow a bubbling route through an
element tree, it actually is a direct routed event that is raised
along the element tree by each UIElement.
you should handle e.Handled in the PreviewDoubleClick because tunneled events happens before bubbled up ones.
also why would you need to handle that event in both textbox and groupbox ? as it is getting fired in both because 2 separate events are getting fired.

C# WinForms dragging controls with mouse

I'm making a calendar From in C# using WinForms.
I've put it together using a two-dimensional array of Panels, and inside them I have a List<> of custom controls which represent appointments.
The user needs to be able to drag appointment controls from one Panel to another (from day to day).
The custom control has a MouseDown and MouseUp event, which passes a message up from the control to the Parent.Parent (custom control -> day panel -> calendar form) and calls public methods StartDragging() and StopDragging() respectively.
Inside these methods, I make a clone of the custom control and add it to the Form, and store it in a global variable in the form which is called DraggedControl.
The Form has an event handler for MouseMove which goes like this:
void Calendar_MouseMove(object sender, MouseEventArgs e)
{
if (DraggedControl == null)
return;
DraggedControl.Location = PointToClient(MousePosition);
Refresh();
}
There are two problems, however:
First of all, the custom control is under everything else. I can see it being added and removed on MouseDown and MouseUp, but it is being added at 0,0 under the panels and day Labels.
Secondly, it does not appear to be moving with the MouseMove at all. I have a feeling this might be because I am moving the mouse with the button pressed, and this would represent a drag action rather than a basic MouseMove.
If I remove the MouseUp code, the control does drag with the mouse, however as soon as the mouse enters the panels (which the control is, sadly, underneath), the drag action stops.
What would you suggest I do?
I suspect there is probably a better way to do what I am trying to do.
custom control is under everything
else
bring it on top:
DraggedControl.BringToFront();
it does not appear to be moving with
the MouseMove at all
Control, which handled MouseDown event, captures mouse input and receives all following MouseMove events until it releases mouse input on MouseUp event, that's why Calendar_MouseMove() is not called. Handle MouseMove event for the same control, which generated MouseDown event.

Categories

Resources