问题描述
我有一些问题得到一个通知框在C#中正常运行。基本上我示出在屏幕上,这显示了几秒钟的消息的下右手侧的boarderless形式,然后消失。问题是,我需要它在其他窗口的顶部没有出现以往任何时候都能够窃取焦点。理想情况下,我希望它是纯粹的托管代码,虽然通过类似的例子我怀疑这将有可能寻找。
I'm having some issues getting a notification box to behave correctly in c#. Basically I'm showing a boarderless form in the lower right hand side of the screen, which displays a message for a few seconds and then disappears. The problem is that I need it to appear on top of other windows without it ever being able to steal focus. Ideally, I want it to be purely managed code, although looking through similar examples I doubt this will be possible.
目前,我阻止它偷焦点时的那一刻调用Form.Show()与控制装置:
At the moment I'm preventing it from stealing focus when calling Form.Show() with an override:
protected override bool ShowWithoutActivation // stops the window from stealing focus
{
get { return true; }
}
和再忽视的鼠标点击次数:
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 these in conjunction with TopMost = true (which I need), it gains focus anyway, and if all other windows are minimised, it also gains focus.
那么,有没有什么办法可以平掉防止从一个窗体曾经获得焦点(无论是通过鼠标点击,使用Alt-Tab等),同时仍然最顶端/秒的最顶端的形式?即使只给重点立刻回它偷走了它会工作窗口(虽然引进闪烁)。
So, is there any way to flat out prevent a form from ever gaining focus (whether via mouse click, alt-tab, etc), while still being the top most/second top most form? Even just giving focus immediately back to the window it stole it from would work (although introduce flickering).
任何建议,将不胜感激,我真的坚持这一。
Any suggestions would be greatly appreciated, I'm really stuck with this.
编辑:
好了,我终于得到这个利用工作:
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);
}
}
}
我也加Form.Hide()来GotFocus事件,这样即使它不以某种方式获得焦点,它只是关闭,并得到了用户的方式尽快解决。
I also added Form.Hide() to the GotFocus event so that even if it does somehow get focus, it simply closes and gets out of the users way asap.
另外,如果你想知道,这些常数所有窗口样式等可WINUSER.H可以发现,其在网上的如果你不能找到它。
Also, if anyone is wondering, the constants for all the window styles etc. can be found in WINUSER.H, its online at http://www.woodmann.com/fravia/sources/WINUSER.H if you can't find it.
不过,如果任何人都可以看到这样做的更优雅的方式,我们将不胜感激。
However, if anyone can see a more elegant way of doing this, it would be appreciated.
推荐答案
在WPF试试这个:
ShowActivated="False"
这篇关于通知窗口 - 从不断获取焦点防止窗口的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!