如何使一个窗口始终保持在上面?

我有一个 C # winforms 应用程序,它在另一个程序中运行一个宏。另一个程序会不断弹出窗口,通常会让事情看起来很疯狂。我想实现一个取消按钮,将停止进程运行,但我似乎不能让窗口停留在顶部。我怎么用 C # 做这个?

编辑: 我试过 TopMost = true;,但是另一个程序总是在顶部弹出自己的窗口。有没有办法让我的窗口每 n 毫秒到达顶部?

编辑: 我解决这个问题的方法是添加一个系统托盘图标,通过双击它来取消进程。系统托盘图标不会被掩盖。感谢所有回应的人。我读了一篇关于为什么没有“超级顶级”窗口的文章... ... 从逻辑上讲,这是行不通的。

237184 次浏览

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

您可能不希望一直以这种方式保留它: 在外部进程启动时设置它,完成时将它放回原处。

除非另一个程序正在创建最上面的窗口,否则 Form.TopMost将工作。

无法创建不被另一个进程的新的最顶层窗口覆盖的窗口。为什么。

您试图抑制的另一个应用程序是什么?你有没有研究过其他方法来达到你想要的效果?在让你的用户遭受你所描述的这种流氓行为之前,请这样做: 你正在尝试做的事情听起来有点像某些顽皮的网站对浏览器窗口所做的事情..。

At least try to adhere to the rule of 意料之中. Users expect to be able to determine the z-order of most applications themselves. You don't know what is most important to them, so if you change anything, you should focus on pushing the other application behind everything rather than promoting your own.

这当然比较棘手,因为 Windows 没有一个特别复杂的窗口管理器:

  1. 枚举顶级窗口 并且检查“ href = “ http://msdn.microsoft.com/en-us/library/ms633522(VS. 85) .aspx”rel = “ nofollow noReferrer”> 它们的哪个进程 属于 ,< a href = “ http://msdn.microsoft.com/en-us/library/ms633545(VS. 85) . aspx”rel = “ nofollow noReferrer”> 如果是 z 顺序,则为 (我不确定如果是 有框架方法 这些 WinAPI 函数)
  2. 修改子进程权限以防止它访问桌面... ... 但我不会尝试这种方法,直到其他方法失败,因为子进程可能最终会处于僵尸状态,而需要用户交互。

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

如果你所说的“疯狂”是指每个窗口都从其他窗口窃取焦点,那么 TopMost 不会解决这个问题。

相反,尝试一下:

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

This will show the 'child' form without it stealing focus. The child form will also stay on top of its parent even if the parent is activated or focused. This code only works easily if you've created an instance of the child form from within the owner form. Otherwise, you might have to set the owner using the API.

为什么不把你的表单变成一个对话框:

myForm.ShowDialog();

我有一个短暂的5分钟的失误,我忘了指定的形式,完全像这样:

  myformName.ActiveForm.TopMost = true;

但我真正想要的是这个!

  this.TopMost = true;

我正在搜索使我的 WinForms 应用程序“总是在顶部”,但设置“最顶部”没有为我做任何事情。我知道这是可能的,因为 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);

希望能帮上忙 参考文献

以下是与 SetForeground 窗口等价的:

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

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

在窗口(xaml)中添加:

Deactivated="Window_Deactivated"

在 Window _ Deactive 后面的代码中:

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

这会让你的窗户保持在顶部。

基于 蛤蜊的回答,以及 Kevin Vuilleumier's关于其他标志负责的行为的评论,我做了这个切换,在 在上面不在上面之间切换按钮按下。

private void button1_Click(object sender, EventArgs e)
{
if (on)
{
button1.Text = "yes on top";
IntPtr HwndTopmost = new IntPtr(-1);
SetWindowPos(this.Handle, HwndTopmost, 0, 0, 0, 0, TopmostFlags);
on = false;
}
else
{
button1.Text = "not on top";
IntPtr HwndTopmost = new IntPtr(-2);
SetWindowPos(this.Handle, HwndTopmost, 0, 0, 0, 0, TopmostFlags);
on = true;
}
}

我做了些与众不同的事,我觉得这样更容易

因此,首先在表格载入

private void Form1_Load(object sender, EventArgs e)
{
this.Shown += new EventHandler(Form1_Shown);//let your form show up here
}


private void Form1_Shown(Object sender, EventArgs e)
{
Form1.ActiveForm.TopMost = true //and then do your TopMost logic
}