I'm having trouble getting a notification window in order to behave correctly in C #. Basically I show a limitless form in the lower right of the screen that displays a message for a few seconds and then disappears. The problem is that I need it to appear on top of other windows, not being able to steal focus. Ideally, I want it to be purely managed code, although looking through similar examples, I doubt it will be possible.
At the moment, I'm stopping him from stealing focus when calling Form.Show () with an override:
protected override bool ShowWithoutActivation
and then ignoring mouse clicks with:
private const int WM_MOUSEACTIVATE = 0x0021; private const int MA_NOACTIVATEANDEAT = 0x0004; protected override void WndProc(ref Message m) { if (m.Msg == WM_MOUSEACTIVATE) { m.Result = (IntPtr)MA_NOACTIVATEANDEAT; return; } base.WndProc(ref m); }
However, I find that if I use them together with TopMost = true (what I need), it still gets focus, and if all other windows are minimized, it also gets focus.
So, is there any smoothing method so that the form never gains focus (be it with a mouse click, alt-tab, etc.), although it is still the top of the largest / second top? Even just by focusing on the window that he stole, it will work (although it introduces a flicker).
Any suggestions would be greatly appreciated, I am really stuck with this.
EDIT:
Ok, so I finally managed to get this working using:
protected override bool ShowWithoutActivation // stops the window from stealing focus { get { return true; } } // and const int WS_EX_NOACTIVATE = 0x08000000; const int WS_EX_TOPMOST = 0x00000008; protected override CreateParams CreateParams { get { CreateParams param = base.CreateParams; param.ExStyle |= WS_EX_TOPMOST; // make the form topmost param.ExStyle |= WS_EX_NOACTIVATE; // prevent the form from being activated return param; } } // and [DllImport("user32.dll")] private extern static IntPtr SetActiveWindow(IntPtr handle); private const int WM_ACTIVATE = 6; private const int WA_INACTIVE = 0; private const int WM_MOUSEACTIVATE = 0x0021; private const int MA_NOACTIVATEANDEAT = 0x0004; protected override void WndProc(ref Message m) { if (m.Msg == WM_MOUSEACTIVATE) { m.Result = (IntPtr)MA_NOACTIVATEANDEAT; // prevent the form from being clicked and gaining focus return; } if (m.Msg == WM_ACTIVATE) // if a message gets through to activate the form somehow { if (((int)m.WParam & 0xFFFF) != WA_INACTIVE) { if (m.LParam != IntPtr.Zero) { SetActiveWindow(m.LParam); } else { // Could not find sender, just in-activate it. SetActiveWindow(IntPtr.Zero); } } }
I also added Form.Hide () to the GotFocus event so that even if it was somehow focused, it just closes and leaves the user path as soon as possible.
Also, if someone is wondering, constants for all window styles, etc. can be found at WINUSER.H, its online at http://www.woodmann.com/fravia/sources/WINUSER.H if you cannot find it.
However, if someone can see a more elegant way to do this, it will be appreciated.