如何使一个窗口始终保持在.Net的顶部?
我有一个C#winforms应用程序在另一个程序中运行macros。 另一个程序会不断地popup窗口,通常会让事情变得很糟糕,因为缺less一个更好的单词,疯狂。 我想实现一个取消button,将停止运行的进程,但我似乎无法让窗口留在上面。 我如何在C#中做到这一点?
编辑:我已经尝试过TopMost = true; ,但另一个程序不断popup自己的窗口。 有没有办法把我的窗口每n毫秒发送到顶端?
编辑:我解决这个问题的方法是添加一个系统托盘图标,通过双击它来取消进程。 系统托盘图标没有被掩盖。 谢谢所有回复。 我读了关于为什么没有“超级顶部”窗口的文章…它在逻辑上不起作用。
Form.TopMost
将工作,除非其他程序正在创build最顶层的窗口。
没有办法创build一个没有被另一个进程的最上面的窗口覆盖的窗口。 Raymond Chen 解释了为什么。
如果通过“疯狂”,你的意思是每个窗口一直在偷窃对方的重点,TopMost不会解决问题。
相反,请尝试:
CalledForm.Owner = CallerForm; CalledForm.Show();
这将显示“孩子”的forms,而不是偷窃重点。 即使父母被激活或重点关注,子女表格也将保留在其父母之上。 如果您已经在所有者表单中创build了子表单的实例,则此代码只能轻松工作。 否则,您可能必须使用API来设置所有者。
设置Form.TopMost
我正在寻找使我的WinForms应用程序“总是在最前面”,但设置“TopMost”没有为我做任何事情。 我知道这是可能的,因为WinAmp这样做(以及许多其他应用程序)。
我所做的就是打电话给“user32.dll”。 我对此没有任何疑虑,而且效果很好。 无论如何,这是一个select。
首先,导入下面的命名空间:
using System.Runtime.InteropServices;
给你的类声明添加一些variables:
private static readonly IntPtr HWND_TOPMOST = new IntPtr(-1); private const UInt32 SWP_NOSIZE = 0x0001; private const UInt32 SWP_NOMOVE = 0x0002; private const UInt32 TOPMOST_FLAGS = SWP_NOMOVE | SWP_NOSIZE;
为user32.dll函数添加原型:
[DllImport("user32.dll")] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter, int X, int Y, int cx, int cy, uint uFlags);
然后在你的代码中(我在Form_Load()中添加了这个调用),添加调用:
SetWindowPos(this.Handle, HWND_TOPMOST, 0, 0, 0, 0, TOPMOST_FLAGS);
希望有所帮助。 参考
将窗体的.TopMost
属性设置为true。
您可能不想一直这样离开它:在外部进程启动时设置它,并在完成时将其放回。
我解决这个问题的方法是制作一个取消选项的系统托盘图标。
你试图压制可见性的其他应用程序是什么? 你有没有调查其他方式达到你想要的效果? 请在使用户接触到您所描述的stream氓行为之前这样做:您试图做的事情听起来像是某些顽皮的网站在浏览器窗口中所做的事情…
至less要设法坚持最小惊奇的规则。 用户希望能够确定大多数应用程序本身的z顺序。 你不知道什么对他们来说最重要,所以如果你改变什么,你应该把重点放在推动其他应用程序,而不是推动你自己。
这当然是棘手的,因为Windows没有一个特别复杂的窗口pipe理器。 两种方法表明:
- 枚举顶层窗口并检查它们属于哪个进程 , 如果是这样 ,则放弃它们的z顺序 。 (我不确定是否有这些WinAPI函数的框架方法。)
- 摆弄subprocess权限,以防止它访问桌面…但我不会尝试,直到其他方法失败,因为subprocess可能最终在僵尸状态,同时要求用户交互。
为什么不把你的表格作为一个对话框:
myForm.ShowDialog();
我有一个短暂的5分钟的失误,我忘记完整地指定这样的forms:
myformName.ActiveForm.TopMost = true;
但是我真的想要这个!
this.TopMost = true;
这里是SetForegroundWindow的等价物:
form.Activate();
我看到人们做怪事:
this.TopMost = true; this.Focus(); this.BringToFront(); this.TopMost = false;
http://blog.jorgearimany.com/2010/10/win32-setforegroundwindow-equivalent-in.html
下面的代码使窗口始终保持在最佳状态,并使其无框化。
using System; using System.Drawing; using System.Runtime.InteropServices; using System.Windows.Forms; namespace StayOnTop { public partial class Form1 : Form { private static readonly IntPtr HWND_TOPMOST = new IntPtr(-1); private const UInt32 SWP_NOSIZE = 0x0001; private const UInt32 SWP_NOMOVE = 0x0002; private const UInt32 TOPMOST_FLAGS = SWP_NOMOVE | SWP_NOSIZE; [DllImport("user32.dll")] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter, int X, int Y, int cx, int cy, uint uFlags); public Form1() { InitializeComponent(); FormBorderStyle = FormBorderStyle.None; TopMost = true; } private void Form1_Load(object sender, EventArgs e) { SetWindowPos(this.Handle, HWND_TOPMOST, 100, 100, 300, 300, TOPMOST_FLAGS); } protected override void WndProc(ref Message m) { const int RESIZE_HANDLE_SIZE = 10; switch (m.Msg) { case 0x0084/*NCHITTEST*/ : base.WndProc(ref m); if ((int)m.Result == 0x01/*HTCLIENT*/) { Point screenPoint = new Point(m.LParam.ToInt32()); Point clientPoint = this.PointToClient(screenPoint); if (clientPoint.Y <= RESIZE_HANDLE_SIZE) { if (clientPoint.X <= RESIZE_HANDLE_SIZE) m.Result = (IntPtr)13/*HTTOPLEFT*/ ; else if (clientPoint.X < (Size.Width - RESIZE_HANDLE_SIZE)) m.Result = (IntPtr)12/*HTTOP*/ ; else m.Result = (IntPtr)14/*HTTOPRIGHT*/ ; } else if (clientPoint.Y <= (Size.Height - RESIZE_HANDLE_SIZE)) { if (clientPoint.X <= RESIZE_HANDLE_SIZE) m.Result = (IntPtr)10/*HTLEFT*/ ; else if (clientPoint.X < (Size.Width - RESIZE_HANDLE_SIZE)) m.Result = (IntPtr)2/*HTCAPTION*/ ; else m.Result = (IntPtr)11/*HTRIGHT*/ ; } else { if (clientPoint.X <= RESIZE_HANDLE_SIZE) m.Result = (IntPtr)16/*HTBOTTOMLEFT*/ ; else if (clientPoint.X < (Size.Width - RESIZE_HANDLE_SIZE)) m.Result = (IntPtr)15/*HTBOTTOM*/ ; else m.Result = (IntPtr)17/*HTBOTTOMRIGHT*/ ; } } return; } base.WndProc(ref m); } protected override CreateParams CreateParams { get { CreateParams cp = base.CreateParams; cp.Style |= 0x20000; // <--- use 0x20000 return cp; } } } }