首页 文章

如何使窗口始终保持在.Net的顶部?

提问于
浏览
73

我有一个C#winforms应用程序在另一个程序中运行一个宏 . 另一个程序将不断弹出窗口,通常会让事情看起来,因为缺乏一个更好的词,疯狂 . 我想实现一个取消按钮来阻止进程运行,但我似乎无法让窗口保持在最顶层 . 我如何在C#中执行此操作?

编辑:我试过TopMost = true; ,但另一个程序不断在顶部弹出自己的窗口 . 有没有办法每隔n毫秒将窗口发送到顶部?

编辑:我解决这个问题的方法是添加一个系统托盘图标,通过双击取消该过程 . 系统托盘图标不会被遮盖 . 感谢所有回复的人 . 我读过有关为什么没有“超级顶级”窗口的文章......它在逻辑上不起作用 .

12 回答

  • 20

    您试图压制其他应用程序的可见性是什么?你有没有调查过其他方法来达到你想要的效果?请在您的用户遇到如您描述的流氓行为之前这样做:您尝试做的事情听起来更像是某些顽皮网站对浏览器窗口所做的事情......

    至少试着遵守Least Surprise的规则 . 用户希望能够确定大多数应用程序本身的z顺序 . 你不知道什么对他们来说最重要,所以如果你改变了什么,你应该专注于推动其他应用程序,而不是推广自己的应用程序 .

    这当然比较棘手,因为Windows没有特别复杂的窗口管理器 . 两种方法表明自己:

  • 30

    如果通过“疯狂”意味着每个窗口都不断地从另一个窗口窃取焦点,TopMost将无法解决问题 .

    相反,尝试:

    CalledForm.Owner = CallerForm;
    CalledForm.Show();
    

    这将显示“儿童”形式,而不会窃取焦点 . 即使父母被激活或专注,子表单也将保留在其父表单之上 . 如果您已在所有者表单中创建子表单的实例,则此代码仅适用 . 否则,您可能必须使用API设置所有者 .

  • 5

    将窗体的 .TopMost 属性设置为true .

    您可能不希望一直保持这种状态:在外部进程启动时设置它并在完成时将其放回原处 .

  • 140

    这是SetForegroundWindow的等价物:

    form.Activate();
    

    我看到人们在做奇怪的事情,比如:

    this.TopMost = true;
    this.Focus();
    this.BringToFront();
    this.TopMost = false;
    

    http://blog.jorgearimany.com/2010/10/win32-setforegroundwindow-equivalent-in.html

  • 4

    Form.TopMost 将起作用,除非其他程序正在创建最顶层的窗口 .

    无法创建另一个进程的新最顶层窗口未覆盖的窗口 . Raymond Chen explained为什么 .

  • 0

    我解决这个问题的方法是制作一个具有取消选项的系统托盘图标 .

  • 4

    以下代码使窗口始终保持在顶部并使其无框架 .

    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;
                }
            }
        }
    }
    
  • 6

    设置Form.TopMost

  • 5

    我知道这是旧的,但我没有看到这种反应 .

    在窗口(xaml)中添加:

    Deactivated="Window_Deactivated"
    

    在Window_Deactivated的代码中:

    private void Window_Deactivated(object sender, EventArgs e)
        {
            Window window = (Window)sender;
            window.Activate();
        }
    

    这将使您的窗口保持在最顶层 .

  • 3

    我有一个短暂的5分钟失误,我忘了像这样完整地指定表格:

    myformName.ActiveForm.TopMost = true;
    

    但我真正想要的就是这个!

    this.TopMost = true;
    
  • 3

    我正在寻找使我的WinForms应用程序“永远在顶部”,但设置“TopMost”对我没有任何作用 . 我知道这是可能的,因为WinAmp会这样做(以及许多其他应用程序) .

    我做的是打电话给“user32.dll” . 我对此没有任何疑虑,而且效果很好 . 无论如何,这是一个选择 .

    首先,导入以下命名空间:

    using System.Runtime.InteropServices;
    

    在类声明中添加一些变量:

    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);
    

    希望有所帮助 . Reference

  • 15

    为什么不将表单设为对话框:

    myForm.ShowDialog();
    

相关问题