問題描述
我在讓通知框在 c# 中正確運行時遇到了一些問題.基本上我在屏幕的右下角顯示一個無邊框的表格,它顯示一條消息幾秒鐘然后消失.問題是我需要它出現在其他窗口的頂部而它永遠無法竊取焦點.理想情況下,我希望它是純托管代碼,盡管查看類似的示例我懷疑這是可能的.
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; }
}
然后忽略鼠標點擊:
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);
}
但是我發現如果我將這些與 TopMost = true(我需要)結合使用,它無論如何都會獲得焦點,如果所有其他窗口都最小化,它也會獲得焦點.
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);
}
}
}
我還在 GotFocus 事件中添加了 Form.Hide(),這樣即使它以某種方式獲得焦點,它也會關閉并盡快離開用戶.
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 中找到所有窗口樣式等的常量,其在線地址為 http://www.woodmann.com/fravia/sources/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 中試試這個:
In WPF try this:
ShowActivated="False"
這篇關于通知窗口 - 防止窗口獲得焦點的文章就介紹到這了,希望我們推薦的答案對大家有所幫助,也希望大家多多支持html5模板網!