Prevent mouse events during wpf Window.OnActivate - c#

Is it possible to prevent mouse events when a window is activated?
For example, I have a C# window and I change the focus to something else such as a browser. When I reactivate the c# window by clicking on it, I don't want any mouse events to be executed. The first click on the window should just activate it. Mouse Events are only fired if the window is already activated.

An event will be fired then a user clicks on your wpf controll but why don't you just handle the event?
Subscribe to the event and prevent it to bubble up the visual tree:
private void Panel_KeyDown(object sender, KeyEventArgs e)
{
e.Handled = true;
}
Have a look at this link it describes the event bubble and tunneling in WPF.

Related

WPF Left click and drag

I've been trying to work with the mouse event handlers. Using MouseDown only seems to work with the right mouse button. And PreviewMouseLeftButton doesn't activate the MouseMove event until I release the left button.
So this code:
private void NewButton_MouseDown(object sender, MouseButtonEventArgs e)
{
var test = e.LeftButton;
var test2 = e.RightButton;
if (!bButtonIsDown)
{
bButtonIsDown = true;
Button mover = (Button)sender;
pntEnterPoint = e.GetPosition(this.cnvsLinkScreen);
cnvsLinkScreen.MouseMove += CnvsLinkScreen_MouseMove;
cnvsLinkScreen.MouseUp += CnvsLinkScreen_MouseUp;
spMover = (StackPanel)((Button)sender).Parent;
pntPreviousPoint.X = Canvas.GetLeft(spMover);
pntPreviousPoint.Y = Canvas.GetTop(spMover);
}
}
private void NewButton_MouseMove(object sender, MouseEventArgs e)
{
Button mover = (Button)sender;
StackPanel spMover = (StackPanel)((Button)sender).Parent;
base.OnMouseMove(e);
if (e.LeftButton == MouseButtonState.Pressed)
{
// Inititate the drag-and-drop operation.
FindChild<StackPanel>(cnvsLinkScreen, "CSVImport");
pntEnterPoint = e.GetPosition(this.cnvsLinkScreen);
Canvas.SetLeft(spMover, pntEnterPoint.X + 1);
Canvas.SetTop(spMover, pntEnterPoint.Y + 1);
}
}
Works but with right button only. When enabling the event handler with:
newButton.MouseDown += NewButton_MouseDown;
That event handler will not get touched with the left mouse button, which I think is odd.
I've done a good amount of reading out there and people refer to thePreviewMouseLeftButtonDown event handler but when I use that in place (same code) the cnvsLinkScreen.MouseMove += CnvsLinkScreen_MouseMove doesn't fire until I let go of the left mouse button (button up) then the StackPanel drags until I click and drop it.
I set breakpoints and see that the event handler is getting set, but it's just not working until after the left button is released. Clearly I'm missing something with the event handlers on this.
Why isn't the MouseDown event handler not even firing with a left mouse button down; only a right mouse button down?
This has to do with Routed Events. Unlike with normal events, a routed event can be marked as handled, after which no further handlers for that event will be called.
MouseDown and MouseMove are bubbling routed events, meaning they start at the deepest elements (the ones inside the button) and then "bubble" their way up, through their parents, toward the Window. Any parent can register a handler for these events and it will be called when the event reaches that parent's level. However if any child marks the event as handled, the event will never reach the parent and the parent's handler will never be called.
This is what's happening here. Button has a handler for MouseDown internally. When Button decides it has been clicked, it raises its own Click event and marks MouseDown as handled. Button also seems to handle MouseMove, but only while a click is in progress. This is why your event handlers don't get called during a left-click, because left-click triggers a "click" which ends up handling those events before they make it out of the Button.
PreviewMouseDown and PreviewMouseMove, on the other hand, are both tunneling routed events, meaning they start from the broadest parent (the Window) and work their way inwards toward the exact point of the cursor. Tunneling events happen before bubbling events; the mouse input first tunnels in toward the cursor, then bubbles back up.
If you attach event handlers to PreviewMouseDown and PreviewMouseMove instead of MouseDown and MouseMove, you will see all the mouse input you expect.
Funny side note: you can actually play the same trick on Button that Button is playing on you. If you mark PreviewMouseDown as handled before it gets inside the Button, then it will never raise its Click event.

How to allow button click events if window in the background

I have an application, ParentApp, which launches another application, ChildApp.
ParentApp displays a form while the ChildApp is running - just a kind of Childapp is currently running display with a Cancel button which kills ChildApp.
I want ParentApp to be unusable while ChildApp is running, so whenever someone clicks on ParentApp I want to bring the ChildApp to the foreground, which is fine.
So I've added this event handler to the ParentApp which responds to the Activated event of the form.
private void ParentAppForm_Activated(object sender, EventArgs e)
{
IntPtr childHwnd = _childApp.MainWindowHandle;
SetForegroundWindow(childHwnd );
}
(GotFocus didn't seem to work)
Unfortunately, if the user clicks the Cancel button on the ParentAppForm, the event handler for that button is never hit, because the Activated event fires first and sets the foreground window to another process.
Is there around this - to allow the button event to fire even though the application is not in the foreground?
As a quick workaround, you could check whether the mouse pointer in inside the area described by the Button.Bounds when the Form is activated.
You can translate the mouse pointer position to the Form.Bounds coordinates using PointToClient with the Cursor.Position coordinates.
Something like this:
private void ParentAppForm_Activated(object sender, EventArgs e)
{
if (this.button1.Bounds.Contains(this.PointToClient(Cursor.Position)))
ChildForm.Close(); //Or ChildApp.Kill()
else
ChildForm.BringToFront(); //Or SetForegroundWindow(ChildApp.Handle)
}

How to disable default PowerPoint event functionality of double click and right click?

In my PowerPoint Add-in using VSTO, I am implementing an Application-level Mouse Hook to capture mouse events like double click, right click, mouse over etc, by using MouseKeyboardActivityMonitor.dll downloaded from Codeplex. The reason I am doing this is because PowerPoint doesn't have mouse related events to listen to and the ones it gives are not fired in edit-mode of the PowerPoint.
In my Add-in when user clicks a chart a menu appears which allows the user to perform various functions on the chart. All is working fine. I have captured mouse events and a customized menu is shown but the problem arises when the menu is closed after performing some action the default menu of PowerPoint appears on the screen.
Example: When user double clicks on the chart, I show my form menu like this.
//Listening to the MouseDoubleClick event
MyMouseHookListener.MouseDoubleClick += MyMouseHookListener_MouseDoubleClick;
//MouseDoubleClickEvent
void MyMouseHookListener_MouseDoubleClick(object sender, System.Windows.Forms.MouseEventArgs e)
{
FormMenu.ShowDialog(); //Displaying menu
}
This works fine, but when the user closes the form the default double click menu of PowerPoint Charts appears. Same is the problem with other mouse events.
How can I disable PowerPoint's event menus?
Update:
There is a bool property named Cancel which is provided by PowerPoint's WindowBeforeDoubleClick and WindowBeforeRightClick events. Which if set to true cancels the default action that PowerPoint performs when an event is fired. How can i access this property in my MouseHook events?
There are several available events raised by the MouseKeyboardActivityMonitor. For a mouse down event you can choose to listen to either MouseDown or MouseDownExt. The latter supplies you with some extra options in the MouseEventExtArgs parameter, such as a Handled property. If you set this to true, the event will not propagate further.
When it comes to MouseDoubleClick event, there is no extended event available. I would therefore suggest that you implement the double click listener yourself by utilizing the MouseDownExt listener and counting the number of clicks that has occurred.
public void Initialize() {
// Initialize your listener and set up event listeners
MyMouseHookListener = new MouseHookListener(new AppHooker()) {Enabled = true};
MyMouseHookListener.MouseDownExt += MyMouseHookListenerOnMouseDownExt;
// UNDONE Delete when testing is done; included to show that the listener is never called
MyMouseHookListener.MouseDoubleClick += MyMouseHookListenerOnMouseDoubleClick;
}
private static void MyMouseHookListenerOnMouseDoubleClick(object sender, MouseEventArgs mouseEventArgs)
{
// NOTE: This listener should never be called
Debug.Print("Mouse double-click!");
}
private static void MyMouseHookListenerOnMouseDownExt(object sender, MouseEventExtArgs mouseEventExtArgs)
{
Debug.Print("Mouse down. Number of clicks: {0}", mouseEventExtArgs.Clicks);
if (mouseEventExtArgs.Clicks == 2)
{
// TODO Insert your double-click code here
mouseEventExtArgs.Handled = true;
}
}
To be exhaustive, you should perhaps also test whether it is the left or right button that has been clicked, which you can to by checking the MouseEventExtArgs.Button property. A right-double-click will now be counted as a double-click, however, this is as far as I know similar to the original MouseDoubleClick event.

C# Form not catching any mouse event

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

Explicitly Prevent ContextMenuStrip from Loading in C#

I have a requirement to hide the contextmenustrip when a particular flag is not set. As i don't think we can explicitly control the show/hide of the context menu strip, i decided to trap the right mouse button click on the control with which the contextmenustrip is associated. It is a UserControl, so i tried handling it's MouseClick event inside which i check if the flag is set and if the button is a right button. However to my amazement, the event doesn't get fired upon Mouse Right Click, but fires only for Left Click.
Is there any thing wrong with me or is there any workaround?
RIGHT CLICK IS GETTING DETECTED, Question TITLE and Description Changed
After Doing some more research, i got the rightclick to fire, when i Handled the Mouse_Down Event on the Control. However Am still clueless, as how to explicitly prevent the ContextMenuStrip From Loading. Another question being, why MouseClick didn't detect Right Button Click?
Current WorkAround
Registering the event handler
userControl1.Control1.MouseDown += new MouseEventHandler(Control1_MouseDown);
void Control1_MouseDown(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Right && flag == false)
{
userControl1.Control1.ContextMenuStrip = null;
}
else
{
userControl1.Control1.ContextMenuStrip = contextMenuStrip1;
}
}
this is the current workaround i'm doing.
But how can i change it in the Opening Event of the ContextMenuStrip
Your solution will fail anyway when the context menu is invoked with the context menu key (or what it's called) on the keyboard. You can use the Opening event to cancel the opening of a context menu.
There is a work around.
Lets say Menu Item A sets the flag that controls the context menu on control B.
In the click event for A, you set b.ContextMenu = nothing to switch it off, and set b.ContextMenu back to the context menu control to switch it back on.
In WinForms there's also the Click event - which does get fired for a right mouse click.
If you are using WPF you should have MouseRightButtonDown and MouseRightButtonUp events.
Check out the table on this MSDN page which lists which controls raise which click events. Significantly, Button, CheckBox, RichTextBox and RadioButton (and a few others) don't raise and event on right click.

Categories

Resources