我创建了一个使用WPF的窗口,我希望我的窗口始终显示在顶部,所以我只是为它创建一个线程:
System.Threading.Tasks.Task.Factory.StartNew(() =>
{
for (;;)
{
System.Threading.Thread.Sleep(3000);
this.Dispatcher.BeginInvoke(new Action(() =>
{
this.Activate();
this.Topmost = true;
}));
}
});
}
这将确保我的窗口每隔3秒就会显示一次。
当我在Visual Studio 2015下打开它时,一切正常,即使我打开“开始”菜单,它也会关闭开始菜单并将窗口置于顶部。但是当我不使用时Visual Studio打开应用程序(只需双击打开应用程序),当我打开开始菜单时,窗口只是闪烁,不显示在顶部。我想念的是什么?我如何让它像在Visual Studio 2015下打开应用程序一样工作(我在Win10上测试过)?
答案 0 :(得分:1)
编辑:我在某种程度上错过了标题中涉及的内容。我后来提出的观点是" 不要这样做"仍然是正确的。它可能会给您的应用程序用户带来问题。
如果你真的需要,this answer可能是你正在寻找的那个。它讨论了如何在所有事物前面保持一个窗口。它仍然是一种解决方法(就像你问题的大多数答案一样)。
旧答案
我理解您的问题:您希望您的窗口保持在所有其他窗口之上。类似的功能可以在Ubuntu和适用于Window的Google Play音乐桌面应用程序中找到(见下文)。
要完成此操作,您只需向Topmost="True"
添加Window
,如下所示(查看最后一个属性)。
<Window xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
Topmost="True">
</Window>
除非您的实际问题&#34;是两个窗口设置了该属性后会发生什么?&#34;然后我建议阅读this article(评论中引用的同一篇文章)。它陈述如下:
&#34;如何创建一个从未被任何其他窗口覆盖的窗口,甚至是其他最顶层的窗口?&#34;
想象一下,如果这是可能的,并想象两个程序是否做到了这一点。 程序A创建一个窗口,超级最顶层的窗口#34;程序也是如此 B.现在用户拖动两个窗口使它们重叠。什么 发生?你已经创造了一个逻辑上的不可能性。其中的一个 两个窗户必须在另一个之上,与想象中的相矛盾 &#34;超最上面的&#34;特征
如果您的功能真的如此,我建议:不要这样做。所有其他解决方案都是一种解决方法,可能会给您的应用程序的消费者带来问题。
答案 1 :(得分:0)
我会用互操作来做这件事。
public class Interop
{
[DllImport("user32.dll")]
public static extern bool SetForegroundWindow(IntPtr hWnd);
[DllImport("user32.dll")]
public static extern bool ShowWindow(IntPtr hwind, int cmd);
[DllImport("user32.dll")]
public static extern IntPtr GetForegroundWindow();
public static IntPtr GetWindowHandle(Window window)
{
return new WindowInteropHelper(window).Handle;
}
}
然后使用计时器:
private void Tick(object state)
{
this.Dispatcher.Invoke(() =>
{
IntPtr window = Interop.GetWindowHandle(this);
IntPtr focused = Interop.GetForegroundWindow();
if (window != focused)
{
Interop.SetForegroundWindow(window);
// Command 5 for show
Interop.ShowWindow(window, 5);
}
});
}
关于startmenu的部分问题,只需添加组策略即可。
或者你可以与'FindWindowEx'进行互操作以找到开始按钮并禁用它。
答案 2 :(得分:0)
我同意Jonas的回答,但会修改它以使用事件而不是计时器。
/// Get the topmost window handle
[System.Runtime.InteropServices.DllImport("user32.dll")]
private static extern IntPtr GetForegroundWindow();
/// Trigger event when topmost window changed
[System.Runtime.InteropServices.DllImport("user32.dll")]
private static extern IntPtr SetWinEventHook(uint eventMin, uint eventMax, IntPtr hmodWinEventProc, TopmostWindowChangedDelegate lpfnWinEventProc, uint idProcess, uint idThread, uint dwFlags);
/// Set the topmost window
[DllImport("user32.dll")]
private static extern bool SetForegroundWindow(IntPtr hWnd);
/// Show a window
[DllImport("user32.dll")]
private static extern bool ShowWindow(IntPtr hwind, int cmd);
// Constant variables for topmost window changed event
private const uint WINEVENT_OUTOFCONTEXT = 0;
private const uint EVENT_SYSTEM_FOREGROUND = 3;
/// Keep track of the last topmost window with a name
private static IntPtr topWinHandle { get; set; }
/// Implementation of topmost window changed delegate
private TopmostWindowChangedDelegate TopmostWindowChanged { get; set; }
然后在您的一个启动方法中设置处理程序
// Set topmost window changed event handler
TopmostWindowChanged = new TopmostWindowChangedDelegate(WinEventProc);
// Set event hook for topmost window changed
IntPtr hook = SetWinEventHook(EVENT_SYSTEM_FOREGROUND, EVENT_SYSTEM_FOREGROUND, IntPtr.Zero, TopmostWindowChanged, 0, 0, WINEVENT_OUTOFCONTEXT);
然后当其他最顶层的更改
时,将窗口移到最顶层 /// Make sure this window stays on top
public void WinEventProc(IntPtr hWinEventHook, uint eventType, IntPtr hwnd, int idObject, int idChild, uint dwEventThread, uint dwmsEventTime)
{
// Get current window name from handle
IntPtr handle = GetForegroundWindow();
if(handle != YOUR_WINDOW'S_HANDLE)
{
// Move your window back to the top
SetForegroundWindow(YOUR_WINDOW'S_HANDLE);
ShowWindow(YOUR_WINDOW'S_HANDLE, 5);
}
}