我需要我的窗口在另一个窗口的顶部。那"其他" window(应用程序)来自不同的开发人员。我没有源代码。我只能使用Spy ++获取有关它的信息。
我使用的是Windows 7。
我尝试了几件事,但他们没有用。
这是我到目前为止所尝试的:
1)Timer + BringWindowToTop
2)我改变了窗口的所有者
IntPtr handle = User32.FindWindow("Vega Prime", "Vega Prime");
NativeWindow win = new NativeWindow();
win.AssignHandle(handle);
ChildForm form = new ChildForm();
form.Show(win);
当我说这不起作用时,我的意思是:
1)起初一切都很好看:我的窗户在顶部
2)然后我点击我下面的窗口(Vega Prime)
3)我的窗口消失了
4)我点击我的窗口所在的位置然后重新出现(!!!!!!)
那是什么?怎么可能呢?更新:
我花了一些时间试图找到问题的解决方案。 这是我发现的:
TopMost window going behind non-TopMost fullscreen window sometimes
我很确定我的问题与"全屏问题"在Windows 7(有时,当不是最顶层的窗口变为全屏时,它会强制最顶层的窗口被隐藏)。这解释了上面描述的奇怪行为,对吧?
答案 0 :(得分:0)
我意识到这个例子似乎可以解决这个问题:
public partial class Form1 : Form
{
IntPtr hWndToStayOver = User32.FindWindow("Vega Prime", "Vega Prime");
private System.Windows.Forms.Timer timer1 = new System.Windows.Forms.Timer();
public Form1()
{
InitializeComponent();
this.Load += new EventHandler(this.Form1_Load);
this.FormClosing += new FormClosingEventHandler(Form1_FormClosing);
this.timer1.Tick += new System.EventHandler(this.timer1_Tick);
}
private void Form1_Load(object sender, EventArgs e)
{
timer1.Start(); // Routine starts now that I'm sure my Form exists
}
void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
timer1.Stop(); // Stop routine (my Form doesn't exist anymore)
}
private bool AmIAboveOtherWindow()
{
IntPtr tmpHwnd = User32.GetNextWindow(hWndToStayOver, User32.GetNextWindowCmd.GW_HWNDPREV);
while (tmpHwnd != (IntPtr)0)
{
if (tmpHwnd == this.Handle)
return true;
tmpHwnd = User32.GetNextWindow(tmpHwnd, User32.GetNextWindowCmd.GW_HWNDPREV);
}
return false;
}
private void timer1_Tick(object sender, EventArgs e)
{
timer1.Stop();
if (!AmIAboveOtherWindow()) // Check if I am behind the target window
{
User32.SetWindowPos(this.Handle, hWndToStayOver, 0, 0, 0, 0, // Move my Form behind the target
User32.SetWindowPosFlags.SWP_NOMOVE |
User32.SetWindowPosFlags.SWP_NOSIZE |
User32.SetWindowPosFlags.SWP_SHOWWINDOW |
User32.SetWindowPosFlags.SWP_NOACTIVATE |
User32.SetWindowPosFlags.SWP_ASYNCWINDOWPOS);
User32.SetWindowPos(hWndToStayOver, this.Handle, 0, 0, 0, 0, // Move target behind my Form
User32.SetWindowPosFlags.SWP_NOMOVE |
User32.SetWindowPosFlags.SWP_NOSIZE |
User32.SetWindowPosFlags.SWP_SHOWWINDOW |
User32.SetWindowPosFlags.SWP_NOACTIVATE |
User32.SetWindowPosFlags.SWP_ASYNCWINDOWPOS);
}
timer1.Start();
}
}
User32类
public class User32
{
[Flags]
public enum SetWindowPosFlags : uint
{
SWP_ASYNCWINDOWPOS = 0x4000,
SWP_DEFERERASE = 0x2000,
SWP_DRAWFRAME = 0x0020,
SWP_FRAMECHANGED = 0x0020,
SWP_HIDEWINDOW = 0x0080,
SWP_NOACTIVATE = 0x0010,
SWP_NOCOPYBITS = 0x0100,
SWP_NOMOVE = 0x0002,
SWP_NOOWNERZORDER = 0x0200,
SWP_NOREDRAW = 0x0008,
SWP_NOREPOSITION = 0x0200,
SWP_NOSENDCHANGING = 0x0400,
SWP_NOSIZE = 0x0001,
SWP_NOZORDER = 0x0004,
SWP_SHOWWINDOW = 0x0040,
}
public enum GetNextWindowCmd : uint
{
GW_HWNDNEXT = 2,
GW_HWNDPREV = 3,
}
[DllImport("user32.dll", SetLastError = true)]
public static extern bool SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter, int X, int Y, int cx, int cy, SetWindowPosFlags uFlags);
[DllImport("user32.dll", SetLastError = true)]
public static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
[DllImport("user32.dll", SetLastError = true, EntryPoint = "GetWindow")]
public static extern IntPtr GetNextWindow(IntPtr hWnd, GetNextWindowCmd uCmd);
}
显然,您必须在此代码中添加对目标句柄的一些检查:此示例仅在加载表单时存在目标窗口且在结束时未关闭时才有效
答案 1 :(得分:0)
确保将窗口的所有者设置为其他窗口。 这将确保您的窗口始终位于所有者之上。 Here了解如何导入appr。本机功能,只需更改“获取”功能即可。到'设置'无处不在。
然后你可以像这样调用它:
SetWindowLong(handle_of_owned_window, -8, handle_of_owner_window);
提示#1:通过Form.Owner属性设置所有权b / w 2表单实例很容易,但是您无法访问其中一个表单。
提示#2:为了访问窗口的句柄,首先需要至少显示一次。
答案 2 :(得分:0)
事实证明,“其他”应用程序(我试图与我的应用程序合并)正在使用全屏独占模式。这就解释了为什么我的最顶层窗口从视图中消失并且再也没有出现(除非我通过鼠标点击关闭全屏模式)。
有关全屏独占模式的详细信息,请访问:
https://docs.oracle.com/javase/tutorial/extra/fullscreen/exclusivemode.html
基本思想是全屏独占模式“允许程序员暂停窗口系统,以便可以直接在屏幕上完成绘图”。我认为这意味着在全屏独占模式期间(一些专家称之为“真正的全屏”)操作系统会忽略不同的窗口(以节省资源)。
在这种情况下唯一的解决方案是配置“其他”应用程序以禁用全屏模式。
在我的案例中它有所帮助 - 我研究了文档,并在配置文件中找到了将全屏模式设置为false的位置。