Winform 窗口有一个属性:TopMost,表示该窗体是否始终显示在此属性未设置为 true 的所有其他窗体之上;
我的理解就是,如果一个 Winform 项目有多个窗体,其中有一个窗体的 TopMost 属性设为 true 了,而其他窗体的 TopMost 未设置为 true,那么 TopMost 属性为 true 的窗体就会显示在其他窗体之上;
前几天项目上遇到一个问题:我明明设置了窗体的 TopMost 属性为 true,还是无法显示在最上层;
后来经过反复测试,发现一个情况:如果我只在窗体属性栏上设置 TopMost 为 true,窗体无法置顶显示:
如果没有把窗体属性栏上的 TopMost 设置为 true(默认为 false),而是在窗体的 Load 事件中用代码指定 TopMost=true,也无法置顶显示:
但是,当我同时在窗体属性栏上设置 TopMost 为 true,也在 load 事件里用代码指定 TopMost=true,就可以将窗体置顶显示。
但是,后来我再用这种方式置顶窗体,发现又不灵了。
在网上查了各种资料,我自己也测试了各种情况,最后发现,当我把窗体的 ShowInTaskbar 属性设置为 false,又可以置顶了。
也就是把 ShowInTaskbar 属性设置为 false,把 TopMost 属性设置为 true,也在 load 方法里用代码指定 TopMost=true,三个条件一起满足的情况下,窗体又可以置顶了。
在网上还查到另一种使用系统动态库的方法置顶窗体(不用把 ShowInTaskbar 属性设置为 false):
把窗体的 TopMost 属性设置为 true,同时在代码里加如下内容:
// 设置此窗体为活动窗体:
// 将创建指定窗口的线程带到前台并激活该窗口。键盘输入直接指向窗口,并为用户更改各种视觉提示。
// 系统为创建前台窗口的线程分配的优先级略高于其他线程。
[DllImport("user32.dll", EntryPoint = "SetForegroundWindow")]
public static extern bool SetForegroundWindow(IntPtr hWnd);
// 设置此窗体为活动窗体:
// 激活窗口。窗口必须附加到调用线程的消息队列。
[DllImport("user32.dll", EntryPoint = "SetActiveWindow")]
public static extern IntPtr SetActiveWindow(IntPtr hWnd);
// 设置窗体位置
[DllImport("user32.dll", CharSet = CharSet.Auto)]
private static extern int SetWindowPos(IntPtr hWnd, int hWndInsertAfter, int x, int y, int Width, int Height, int flags);
private void Form2_Load(object sender, EventArgs e)
{
// 设置窗体显示在最上层
SetWindowPos(this.Handle, -1, 0, 0, 0, 0, 0x0001 | 0x0002 | 0x0010 | 0x0080);
// 设置本窗体为活动窗体
SetActiveWindow(this.Handle);
SetForegroundWindow(this.Handle);
// 设置窗体置顶
this.TopMost = true;
}