Notification Window – Preventing the window from ever getting focus
我在让通知框在 c# 中正常运行时遇到了一些问题。基本上,我在屏幕的右下角显示了一个无边界表格,它会显示一条消息几秒钟然后消失。问题是我需要它出现在其他窗口的顶部,而它却无法窃取焦点。理想情况下,我希望它是纯托管代码,尽管查看类似示例我怀疑这是否可能。
目前我正在阻止它在调用 Form.Show() 时窃取焦点:
1
2 3 4 |
protected override bool ShowWithoutActivation // stops the window from stealing focus
{ get { return true; } } |
然后忽略鼠标点击:
1
2 3 4 5 6 7 8 9 10 11 12 |
private const int WM_MOUSEACTIVATE = 0x0021; private const int MA_NOACTIVATEANDEAT = 0x0004; protected override void WndProc(ref Message m) |
但是我发现如果我将它们与 TopMost = true (我需要)结合使用,它无论如何都会获得焦点,如果所有其他窗口都被最小化,它也会获得焦点。
那么,有没有什么方法可以完全阻止表单获得焦点(无论是通过鼠标单击、alt-tab 等),同时仍然是最顶部/第二顶部的表单?即使只是将焦点立即返回到它从中窃取的窗口也可以工作(尽管会引入闪烁)。
任何建议将不胜感激,我真的坚持这一点。
编辑:
好的,所以我终于设法使用:
1
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 |
protected override bool ShowWithoutActivation // stops the window from stealing focus { get { return true; } } // and const int WS_EX_NOACTIVATE = 0x08000000; protected override CreateParams CreateParams // and [DllImport("user32.dll")] private const int WM_MOUSEACTIVATE = 0x0021; protected override void WndProc(ref Message m) if (m.LParam != IntPtr.Zero) } |
我还在 GotFocus 事件中添加了 Form.Hide() ,这样即使它确实以某种方式获得焦点,它也会尽快关闭并离开用户。
此外,如果有人想知道,所有窗口样式等的常量都可以在 WINUSER.H 中找到,如果可以的话,它的在线地址为 http://www.woodmann.com/fravia/sources/WINUSER.H没找到。
但是,如果有人能看到更优雅的方法,将不胜感激。
在 WPF 中试试这个:
1
|
ShowActivated="False"
|
您正在寻找的可能是 WS_EX_NOACTIVATE 扩展窗口样式。单击时不会激活具有此样式的窗口。例如,虚拟键盘窗口具有这种样式。
要将此样式应用于窗口,请覆盖 CreateParams 函数并更改 baseParams.ExStyle.
我不是在这里寻找积分,因为原始发帖人已经发布了一个对他们有用的解决方案,但我想分享我在这个问题上的经验。使用上面的解决方案(在问题的底部而不是在答案形式中)在使用
我想出了一个替代解决方案来防止表单被点击使用
注意:在这种状态下,您根本无法与表单进行交互,甚至尝试单击”X”按钮只会单击该位置的表单后面的任何内容,因此您需要使用代码来关闭表单:
1
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 |
public partial class Form1 : Form { private enum GWL : int { ExStyle = –20 } private enum WS_EX : int public enum LWA : int [DllImport("user32.dll")] [DllImport("user32.dll")] protected override bool ShowWithoutActivation const int WS_EX_NOACTIVATE = 0x08000000; protected override CreateParams CreateParams public Form1() private void Form1_Load(object sender, EventArgs e) this.ShowInTaskbar = false; // Allow the form to be clicked through so that the message never physically interferes with work being done on the computer SetWindowLong(this.Handle, (int)GWL.ExStyle, (int)WS_EX.Layered | (int)WS_EX.Transparent); // Set the opacity of the form byte nOpacity = 255; // 0 = invisible, 255 = solid, anything inbetween will show the form with transparency |
我还能够通过对上面的
注意:这也使表单无法单击,但行为不同,因为您实际上可以单击最小、最大和”X”按钮,但当您这样做时没有任何反应。当您位于表单边缘时,鼠标光标也会发生变化,好像要调整大小但它不允许调整大小:
1
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 |
public partial class Form1 : Form
{ protected override bool ShowWithoutActivation { get { return true; } } const int WS_EX_NOACTIVATE = 0x08000000; protected override CreateParams CreateParams [DllImport("user32.dll")] private const int WM_MOUSEACTIVATE = 0x0021; protected override void WndProc(ref Message m) if (m.LParam != IntPtr.Zero) } public Form1() private void Form1_Load(object sender, EventArgs e) this.ShowInTaskbar = false; |
原创文章,作者:ItWorker,如若转载,请注明出处:https://blog.ytso.com/269565.html