I'm looking to intercept every mouse click in my WPF application. Seems this should be easy with the command routing mechanism, but sorry I'm not finding anything.
My application implements several security levels, and has the requirement to automatically revert to the most restrictive level if no one interacts with (clicks) the application in x minutes. My plan is to add a timer that expires after x minutes and adjusts the security level. Each mouse click into the application will reset the timer.
You can register a class handler:
public partial class App : Application
{
protected override void OnStartup(StartupEventArgs e)
{
EventManager.RegisterClassHandler(typeof(Window), Window.PreviewMouseDownEvent, new MouseButtonEventHandler(OnPreviewMouseDown));
base.OnStartup(e);
}
static void OnPreviewMouseDown(object sender, MouseButtonEventArgs e)
{
Trace.WriteLine("Clicked!!");
}
}
This will handle any PreviewMouseDown event on any Window created in the application.
<Window .... PreviewMouseDown="Window_PreviewMouseDown_1">
</Window>
This should work for you.
This fires even if other MouseDown events fire for components that it contains.
As per Clemens suggestion in the comments, PreviewMouseDown is a better choice than MouseDown, as that makes sure you can't stop the event bubbling from happening in a different event.
You have a few options:
Low level mouse hook:
http://filipandersson.multiply.com/journal/item/7?&show_interstitial=1&u=%2Fjournal%2Fitem
WPF Solution (I'd check to see if this does what you need first):
WPF. Catch last window click anywhere
Related
There is Activated event in a Window in WPF. What is the the closest match for Activated event for a page. I want to use an event that triggers every time a page is displayed.
How about using the IsVisibleChanged event.
In your window, either your base class definition that you use throughout your app, or just the one you are interested in. Add a call at the opening of it something like
public class MyBaseclassWindow : Window
{
public MyBaseclassWindow()
{
IsVisibleChanged += MyBaseclassWindow_IsVisibleChanged;
}
private void MyBaseclassWindow_IsVisibleChanged(object sender, DependencyPropertyChangedEventArgs e)
{
// e.NewValue will be TRUE when the visibility is coming back on
if ( !e.NewValue )
return;
// do whatever you want every time window becomes visible.
}
}
If this is something you want done throughout your system, then you can just use THIS window as your base window by always using it as forms are created.
There is the Loaded event which occurs when the element (Page) is laid out, rendered, and ready for interaction.
The Frame class, which I guess is used to host your pages, also has a ContentRendered event that you can handle.
I noticed strange behaviour of left-click event for NotifyIcon.
I have a code like this:
private void notifyIcon2_MouseClick(object sender, MouseEventArgs e)
{
if (e.Button == System.Windows.Forms.MouseButtons.Left)
{
Console.WriteLine("Hello!");
}
}
The problem is that upon clicking notifyicon in tray string "Hello" is not shown immediately, it takes about 0.5 seconds (half of a second) to react. That is why I can not add some sort of variable-counter for each click of the icon - it just reacts too slow to catch all clicks and increment my variable.
Is there any solution to the problem? I tried MouseClick, MouseDown, MouseUp and Click events, and all of them have such a slow reaction.
Thank you!
I think it is related to this little comment they make here (I know this is not this NotifyIcon).
Note that the LeftClickCommand fires after a short delay (as opposite to the DoubleClickCommand that fires immediately). This is because there is a time span between a first click and a second click for the OS to consider the mouse action a double-click. The NotifyIcon is smart enough to wait this period in order to make sure the LeftClickCommand is only fired if the user does not click a second time within that period.
I tried it and this delay is present on the Form itself as well. This is just how this event works.
Implementing a handler for the DoubleClick event was not a solution in my case where I wanted only the single click to open the NotifyIcon's popup.
I found the NoLeftClickDelay property in the code completion that makes things to work as wanted.
TaskbarIcon tbIcon = (TaskbarIcon)FindResource("MyNotifyIcon");
tbIcon.NoLeftClickDelay = true;
I am making an application for personal use where the stylus can be used to draw on the current screen but the normal use (with mouse) won't be interrupted.
Currently, I am trying to use WS_EX_TRANSPARENT to set the window to allow mouse events through, but it seems like that stylus events also get passed through without being captured.
Is there any other method I can use to pass through mouse/keyboard events while still allowing stylus events? Here is what my program looks like so far:
Disable the RealTimeStylus for WPF Applications on MSDN states:
[...] (WPF) has built in support for processing Windows 7 touch input [...] Windows 7 also provides multi-touch input as Win32 WM_TOUCH window messages. These two APIs are mutually exclusive on the same HWND.
This seems to imply that, for a given window, you can receive stylus events or touch events but not both. As you do want to handle the stylus events this means you don't need to bother filtering the touch events. That just leaves the mouse and keyboard.
At first I thought you might be able to use a custom window procedure (WndProc) and filter-out the mouse and keyboard messages. However, the WndProc (when used in WPF) is really just a notification mechanism and you can't block the received messages.
I found a Windows API called BlockInput that supposedly "Blocks keyboard and mouse input events from reaching applications". However from the docs this appears to be system-wide not app-specific so may not be any use to you.
The only other way I can think of is to use a low-level keyboard or mouse hook. This requires some P/Invoke but it's not too difficult. These hooks allow you to register callback functions that get called when keyboard and mouse events are raised. The advantage is that you can prevent those events from propagating and effectively "swallow" them, which sounds like what you need.
I don't really like posting an answer that basically says "do a search for ..." but the amount of code involved is non-trivial and has been posted in numerous places both on Stack Overflow and elsewhere, so: try doing a search for low level keyboard hook c# wpf and you should find some code that might help!
One thing you may have trouble with even if you go down this route is focus. As soon as your "invisible" topmost window gets a stylus message that it responds to, I'm presuming focus will switch to your WPF application, thus "stealing" focus from whatever application was being used prior. You might be able to use P/Invoke again to set the window style flags of your main window to prevent this (as per the accepted answer to this SO question).
ORIGINAL ANSWER
You can override the appropriate keyboard, mouse and touch Preview... event handler methods of the Window and mark them as handled. This has the effect of stopping child controls from receiving those events.
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
protected override void OnPreviewKeyDown(KeyEventArgs e)
{
e.Handled = true;
base.OnPreviewKeyDown(e);
}
protected override void OnPreviewMouseDown(MouseButtonEventArgs e)
{
e.Handled = true;
base.OnPreviewMouseDown(e);
}
protected override void OnPreviewMouseMove(MouseEventArgs e)
{
e.Handled = true;
base.OnPreviewMouseMove(e);
}
protected override void OnPreviewMouseWheel(MouseWheelEventArgs e)
{
e.Handled = true;
base.OnPreviewMouseWheel(e);
}
protected override void OnPreviewTouchDown(TouchEventArgs e)
{
e.Handled = true;
base.OnPreviewTouchDown(e);
}
protected override void OnPreviewTouchMove(TouchEventArgs e)
{
e.Handled = true;
base.OnPreviewTouchMove(e);
}
}
I've done the basic keyboard, mouse and touch events here. In a simple app test it seemed to do the trick and I assume it would still let stylus events through (I don't have a stylus I can test with).
You may have to experiment with which events need to be handled like this. I only did KeyDown for example, not KeyUp as I presume the latter is irrelevant without the former. I may also have implemented some that didn't need to be handled, and I'm not sure the calls to the base methods are needed either. As I say, experiment until you get something that works for you.
I was wonder how can I fire an event when the user double click on my webbrowser component. Since it has no such event how it could be possible...
Thanks in advance
Sounds like a WPF matter :-)
There you would go with an Behaviour attached to the browser. See this link for more information about this approach if you can alter your application (dependends on what you have done yet).
If you can't apply this solution, just bind a event handler to the click event and count click per time with respect to the mouse movement since the last click and if both conditions are true (two clicks in 0.2 secs, mouse hasn't moved more than 2px, for example) execute your double click code. The events you should use are previewMOUSEdown or MOUSEdown, not KEYdown.
// Call this where you want to create the event (let's say on the form load for example).
webBrowser1.DoubleClick += new EventHandler(webBrowser1_DoubleClick);
// This happens when the event is fired (so when you double click on the webbrowser control).
void webBrowser1_DoubleClick(object sender, EventArgs e)
{
// Code
}
Try this.
I don't know why you can't set this event via the designer :(, but this should work.
The thing is, I have 2 usercontrols, lets call them A and B. They both have MouseRightButtonDown and MouseRightButtonUp events and usercontrol A kinda overlaps B.
Now when I right mouse click on A, the mouse event on B does not fire. When I disable the mouseevents on usercontrol A, the mouseevents on usercontrol B fires.
But how can I get them both to fire simultaneously?
(hope I've explained it clearly)
a bit hacky but this would work, bind the event handler only to the control 1 and call the other event handler like this:
private void textBlock1_MouseRightButtonDown(object sender, MouseButtonEventArgs e)
{
Debug.WriteLine("textBlock1_MouseRightButtonDown");
textBlock2_MouseRightButtonDown(sender, e);
}
private void textBlock2_MouseRightButtonDown(object sender, MouseButtonEventArgs e)
{
Debug.WriteLine("textBlock2_MouseRightButtonDown");
}
personally I would not do this, I would do all my best to re-architect the logic and not have to call the other handler from one of the two controls, but without knowing more what your are doing, impossible to tell...
As we are talking about Silverlight here, I strongly suggest to look on how to work Routed Events, which is a mechanism which actually will help you to avoid event relaunching, as these are events that are traverse Visual Tree of your element, from top to bottom.
Definitely better then relaunching events.