Does NotifyIcon have a MouseDown equivalent? - c#

I have a NotifyIcon in the system tray. How can I detect when the user has left-clicked down on it? I assumed the MouseDown event would be what I want to use but it only handles right click and middle-button click. For left-click, it only fires after the user has let go (as in they've just performed a normal click). Is there a way to get the MouseDown event only?

This is by design, the shell synthesizes the MouseDown message from the up event. You'll see why it works this way when you click and hold the button down and then start dragging. Note how the notification area overflow window pops up and lets you drag the icon into it to remove it from the visible area. It can't work both ways.
Technically you could hook the window owned by Explorer.exe to get a crack at the messages before Explorer does with SetWindowsHookEx(). That however requires a kind of DLL that you cannot write in C#, it needs to be injected into Explorer. Very destabilizing and hard to beat the competition that is trying to do the same thing. Also the kind of code that causes sleepless nights for the Microsoft appcompat team.

It appears that the underlying Win32 API Shell_NotifyIcon sends a WM_LBUTTONDOWN message when the user clicks the icon. According to MSDN anyway.
Examining the Windows Forms source code for NotifyIcon reveals standard mouse down event handling, so if the Win32 message was being sent at the "correct" time it would work as you want/expect.
I have to agree with a previous comment that NotifyIcon will be swallowing WM_LBUTTONDOWN since it needs to do mouse capture to allow the user to drag the icons about.
It's possible that this article about creating a tray icon for WPF will be useful since it shows how to use SetWindowsHookEx etc from C#.

Related

Capture moue movements on a WPF window drawn behind icons and dispose the handler on exit

I have a WPF window which I managed to draw behind desktop icons using the tutorial from here: Codeproject link.
Now I need two things.
First, because of the window position it doesn't capture any moue events which is good for my project. But I only need to make the window capture mouse movements, nothing else. In the tutorial I used it says to use WH_MOUSE_LL event. Please if anyone can show any light on this subject.
Secondly, after the window close event there is a static image of the window still showing on the background. May be this is because of the WorkerW handle which I produced through the previous code still there. How to dispose that in Window_closing event?

C# Suppressing mouse click for multiple mice

I have written an application that currently handles clicks from multiple mouse devices.
I used this project and modified to handle mouse clicks as apposed to keyboards.
This is working fine, however now I need to know if there is a way to suppress a click event if it has been handled by my app. The app is a quiz game so the idea is that the quiz master will have (and still be able to use) 1 mouse, and the other contestants will have their own mouse (as buzzers). So when they buzz in, I don't want the mouse click events to fire in the operating system (or at least this application).
The concept is the familiar override of void WndProc(ref Message message), and so I have tried not calling base.WndProc(ref Message) when I don't want the click events to fire, but this has not worked.
Can anybody point me in the right direction here?
Should I be going down the windows hook route? I have looked at this, but I can't seem to work out how I could hook to each mouse device individually.
Any help would be greatly appreciated.
Edit:
This is a Windows Form UI project, and not WPF. So the MultiPoint SDK from Microsoft won't work.
The solution to this lies within not WndProc, but PreFilterMessage(). By intercepting messages before they even reach the form, you can remove them from the message pump causing them to never reach the control that was clicked. This also works for child controls within the form.
I answered this and posted the full source in the following question:
C# Get Mouse handle (GetRawInputDeviceInfo)

Shockwave Flash Object doesn't support MouseWheel Event

I've a Windows Form Application that does a simple task : the user selects a video in the main form, and the application pops up a new form with a Shockwave Flash Object reproducing it.
What i would like to do now is to move in the Movie timeline when the user scrolls the mouse wheel. The problem is, the Flash object steals the focus from the form as soon as it pops up, and it doesn't support a mousewheel event.
Is there a way to do it, other than hooking the MouseWheel event and redirect it to the application when the popup has the focus?
The window displayed by Flash is owned by a different process. That makes messing with messages difficult, you'll at least need a low-level mouse hook to see the mouse message before it disappears into the other process.
The boilerplate code is available here. Beware that it has a bug that prevents it from working on .NET 4 and up, see this answer for the workaround.

Can I use window hooks in C# to determine if a window gains or loses focus?

I've written a c# application which automates an instance of IE. I'd like to know when internet explorer gains focus and when it looses focus.
From the SHDocVw.InternetExplorer object I can get it's HWND. From there how can I create a message hook to receive WM_KILLFOCUS and WM_FOCUS events (assuming those are the correct events to be listening for :))?
Thanks everyone!!
UPDATE: I found a way I could use to accomplish the above goal without using hooks (which I haven't quite figured out how to do in c# yet), using the .NET framework in this question.
The problem with this code
AutomationFocusChangedEventHandler focusHandler
= new AutomationFocusChangedEventHandler(OnFocusChanged);
Automation.AddAutomationFocusChangedEventHandler(focusHandler);
is that it is easy for a window to be the foreground window and that event won't fire when that window is switched to because it's waiting for a specific UI Element to be in focus. (To test this you can use a function that uses that code and prints a message everytime a new window is in focus, such as the MSDN sample TrackFocus, and then click on a webbrowser. When most webpages or a blank page is being displayed in the browser the event wont fire until the address bar or some other element is selected.) It could probably work if there was a way to modify so that it could throw the event if either no UI Element is in focus or every time an element lost focus (instead being thrown when it gains focused). Anyone have any ideas on how I could fix the above code to solve my problem?
Update 2: I just came across this (article claims you can only hook to mouse and keyboard from c#) as well which may mean I can't use hooks at all for what I'd like to do.
Detailed instructions on setting up a hook from C# are here: http://support.microsoft.com/kb/318804/en-us?fr=1

How do I prevent my custom tooltip code from drawing when that part of my window is obscured by an always-on-top window?

We have implemented some custom tooltip-drawing code that fires on Tick events of a timer. Whenever this event fires, we check to make sure our control is visible (this.Visible) and is the foreground window (GetForegroundWindow()).
The problem we are having involves "always on top" windows like Task Manager or Process Explorer (when the "always on top" option is enabled). Because these windows are always on top, sometimes our application is occluded/covered by such windows, but our tooltip still pops up and gets drawn on top of the top window.
I have tried to use the Form.TopMost property, but this is not acceptable because then, tooltips never appear if there is an "always on top" window anywhere. In this case, our application is even active, so we should be showing the tooltips.
How do I detect/determine whether there is an "always on top" window covering the area on my form where the mouse is hovering? I want to prevent the tooltip from showing "through" the window.
It sounds like you're polling the mouse position with a timer, and then displaying a tooltip. That's the wrong way to go. What you should do is detect mouse-move messages. If you get mouse-move events telling you that the mouse is in a certain region, then set a timer, and if the mouse hasn't left that region by the time the timer fires, display the tooltip. (Incidentally, that's how native Windows tooltips work. See TrackMouseEvent.)
That solves your problem with always-on-top windows automatically because if part of your window is obscured by an always-on-top window, your form simply won't receive mouse-move events for that region, so you don't need to check whether the mouse is really there.
If you're set on using your current technique, then you can use the WindowFromPoint API function to determine what window is visible at any given point on the screen. Use that to determine whether your window is on top at the place you plan to display the tooltip. (The .Net Framework API map says the .Net equivalent to that API function is Form.GetChildAtPoint, but that only gives children of a .Net form, whereas you need to consider all top-level windows, including non-.Net windows.)

Categories

Resources