题
我怎么可以把我的WPF应用以前的桌面上?到目前为止,我已经试过:
SwitchToThisWindow(new WindowInteropHelper(Application.Current.MainWindow).Handle, true);
SetWindowPos(new WindowInteropHelper(Application.Current.MainWindow).Handle, IntPtr.Zero, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
SetForegroundWindow(new WindowInteropHelper(Application.Current.MainWindow).Handle);
它们都不是在做的工作(Marshal.GetLastWin32Error()
是说这些行动成功完成,并且P/调用的属性,对每个定义没有 SetLastError=true
).
如果我创建一个新的空白WPF应用程序,并呼叫 SwitchToThisWindow
有计时器,它工作正按预期,所以我不知道为什么它不工作在我原来的情况。
编辑:我这样做是与一个全球性的热键。
解决方案 11
嗯,我想出了一个围绕工作。我打电话是从一个键盘钩用于实现一个热键。呼叫工作预计如果我把它变成一个BackgroundWorker有一个暂停。这是一个临时搭配,但是我不知道为什么它不工作的原本。
void hotkey_execute()
{
IntPtr handle = new WindowInteropHelper(Application.Current.MainWindow).Handle;
BackgroundWorker bg = new BackgroundWorker();
bg.DoWork += new DoWorkEventHandler(delegate
{
Thread.Sleep(10);
SwitchToThisWindow(handle, true);
});
bg.RunWorkerAsync();
}
其他提示
myWindow.Activate();
试图把窗的前景并激活它。
这应该做到,除非我误会了,你要总是在顶的行为。在这种情况下你想要的:
myWindow.TopMost = true;
我已经找到一个解决方案带来的窗口,但它的行为作为一个正常的窗口:
if (!Window.IsVisible)
{
Window.Show();
}
if (Window.WindowState == WindowState.Minimized)
{
Window.WindowState = WindowState.Normal;
}
Window.Activate();
Window.Topmost = true; // important
Window.Topmost = false; // important
Window.Focus(); // important
如果你需要的窗口,可以在前面第一次载荷,那么你应该使用如下:
private void Window_ContentRendered(object sender, EventArgs e)
{
this.Topmost = false;
}
private void Window_Initialized(object sender, EventArgs e)
{
this.Topmost = true;
}
让这个快速的复制到一个-
使用此类' DoOnProcess
法移动过程的主要窗口前景(但不是偷的重点从其他windows)
public class MoveToForeground
{
[DllImportAttribute("User32.dll")]
private static extern int FindWindow(String ClassName, String WindowName);
const int SWP_NOMOVE = 0x0002;
const int SWP_NOSIZE = 0x0001;
const int SWP_SHOWWINDOW = 0x0040;
const int SWP_NOACTIVATE = 0x0010;
[DllImport("user32.dll", EntryPoint = "SetWindowPos")]
public static extern IntPtr SetWindowPos(IntPtr hWnd, int hWndInsertAfter, int x, int Y, int cx, int cy, int wFlags);
public static void DoOnProcess(string processName)
{
var allProcs = Process.GetProcessesByName(processName);
if (allProcs.Length > 0)
{
Process proc = allProcs[0];
int hWnd = FindWindow(null, proc.MainWindowTitle.ToString());
// Change behavior by settings the wFlags params. See http://msdn.microsoft.com/en-us/library/ms633545(VS.85).aspx
SetWindowPos(new IntPtr(hWnd), 0, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_SHOWWINDOW | SWP_NOACTIVATE);
}
}
}
禾田
我知道这问题是相当古老,但我刚刚遇到这种精确的方案,并想分享的解决方案,我已经实现。
正如在评论这一页,几个提议的解决办法不工作上的XP,我需要支持在我的情况。虽然我同意的情绪通过@马修*泽维尔,一般来说,这是一个糟糕的UX实践中,有的时间里,它完全是一个plausable UX。
该解决方案带来WPF窗口的顶实际上是向我提供的同样的代码,我在使用提供全球的热键。 一个博客的条约瑟夫*库尼 包含一个 链接到他的代码样本 包含的原始代码。
我清理和修改的代码一点,并实现它作为一个扩展的方法系统。窗户。窗口。我已经测试了这个XP32位和windows7资64位,这两者正常工作。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Interop;
using System.Runtime.InteropServices;
namespace System.Windows
{
public static class SystemWindows
{
#region Constants
const UInt32 SWP_NOSIZE = 0x0001;
const UInt32 SWP_NOMOVE = 0x0002;
const UInt32 SWP_SHOWWINDOW = 0x0040;
#endregion
/// <summary>
/// Activate a window from anywhere by attaching to the foreground window
/// </summary>
public static void GlobalActivate(this Window w)
{
//Get the process ID for this window's thread
var interopHelper = new WindowInteropHelper(w);
var thisWindowThreadId = GetWindowThreadProcessId(interopHelper.Handle, IntPtr.Zero);
//Get the process ID for the foreground window's thread
var currentForegroundWindow = GetForegroundWindow();
var currentForegroundWindowThreadId = GetWindowThreadProcessId(currentForegroundWindow, IntPtr.Zero);
//Attach this window's thread to the current window's thread
AttachThreadInput(currentForegroundWindowThreadId, thisWindowThreadId, true);
//Set the window position
SetWindowPos(interopHelper.Handle, new IntPtr(0), 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE | SWP_SHOWWINDOW);
//Detach this window's thread from the current window's thread
AttachThreadInput(currentForegroundWindowThreadId, thisWindowThreadId, false);
//Show and activate the window
if (w.WindowState == WindowState.Minimized) w.WindowState = WindowState.Normal;
w.Show();
w.Activate();
}
#region Imports
[DllImport("user32.dll")]
private static extern IntPtr GetForegroundWindow();
[DllImport("user32.dll")]
private static extern uint GetWindowThreadProcessId(IntPtr hWnd, IntPtr ProcessId);
[DllImport("user32.dll")]
private static extern bool AttachThreadInput(uint idAttach, uint idAttachTo, bool fAttach);
[DllImport("user32.dll")]
public static extern bool SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter, int X, int Y, int cx, int cy, uint uFlags);
#endregion
}
}
我希望这个代码可以帮助别人谁会遇到这个问题。
如果用户相互作用的另一个应用程序,它不可能把你的前面。作为一般规则,这一过程只能期望来设置的前景的窗口,如果这一进程已经是前景的过程。(Microsoft文件的限制 SetForegroundWindow() MSDN项。) 这是因为:
- 用户"拥有"的前景。例如,这将是极为令人讨厌,如果另一个程序偷的前景,同时用户是打字、至少中断了她的工作流程,并有可能造成意想不到的后果,因为她键击意味着对于一个应用程序是错误解释的罪犯直到她注意的变化。
- 想象一下,每两个程序检查其窗口是前台并试图设置的前景,如果它不是。尽快为第二个程序是运行计算机是毫无用处的前景的反弹,两者之间,在每一个任务开关。
我已经有一个类似的问题与WPF应用程序得到援引,从一个接入的应用程序通过壳的对象。
我的解决方案为以下工作在XP和windows7资64与应用程序汇编,以x86目标。
我宁愿这样做,模拟一个alt-卡。
void Window_Loaded(object sender, RoutedEventArgs e)
{
// make sure the window is normal or maximised
// this was the core of the problem for me;
// even though the default was "Normal", starting it via shell minimised it
this.WindowState = WindowState.Normal;
// only required for some scenarios
this.Activate();
}
我知道这是迟到的答案,也许有帮助研究人员
if (!WindowName.IsVisible)
{
WindowName.Show();
WindowName.Activate();
}
为什么一些问题的答案,这个页面上是错误的!
任何答复使用的
window.Focus()
是错误的。- 为什么?如果通知消息就会弹出来,
window.Focus()
将抓住重点从任何用户打字的时候。这是疯狂的令人沮丧的最终用户,尤其是如果该弹出会发生相当频繁。
- 为什么?如果通知消息就会弹出来,
任何答复使用的
window.Activate()
是错误的。- 为什么?它会让任何父母windows可见。
- 任何答案,即省略了
window.ShowActivated = false
是错误的。- 为什么?它会抓住重点从另一个窗口的时的信息弹出,这是很烦人的!
- 任何解答不使用
Visibility.Visible
来隐藏或展示窗口是错误的。- 为什么?如果我们使用Citrix,如果窗口是没有崩溃的时候它是关闭的,它将留下一个奇怪的黑色的长方形保持在屏幕上。因此,我们不能使用
window.Show()
和window.Hide()
.
- 为什么?如果我们使用Citrix,如果窗口是没有崩溃的时候它是关闭的,它将留下一个奇怪的黑色的长方形保持在屏幕上。因此,我们不能使用
基本上:
- 窗不应该抓住的重点从任何其他的窗口,当它激活;
- 窗不应该激活其父母,当它被显示;
- 窗口应当与Citrix。
解决方案。
这个代码是100%的兼容Citrix(没有空白的领域的屏幕)。它是测试都正常WPF和DevExpress.
这个答案的目的是为任何使用的情况下,我们希望有一个小的通知的窗口,是始终在前面的其他窗口(如果用户选择在这个偏好)。
如果这个答复似乎更加复杂的其他人,这是因为它是强大的企业级别的代码。一些其他的答案在这页很简单,但实际上不工作。
XAML附着的财产
添加这一附属性的任何 UserControl
在窗口。所附财产将:
- 等到
Loaded
事件(否则它无法查找些树找到父母一窗口)。 - 添加一个事件处理程序,以确保该窗口可见或不可见。
在任何一点,可以设置窗口在前或者没有,通过翻转的价值附加的财产。
<UserControl x:Class="..."
...
attachedProperties:EnsureWindowInForeground.EnsureWindowInForeground=
"{Binding EnsureWindowInForeground, Mode=OneWay}">
C#-辅助方法
public static class HideAndShowWindowHelper
{
/// <summary>
/// Intent: Ensure that small notification window is on top of other windows.
/// </summary>
/// <param name="window"></param>
public static void ShiftWindowIntoForeground(Window window)
{
try
{
// Prevent the window from grabbing focus away from other windows the first time is created.
window.ShowActivated = false;
// Do not use .Show() and .Hide() - not compatible with Citrix!
if (window.Visibility != Visibility.Visible)
{
window.Visibility = Visibility.Visible;
}
// We can't allow the window to be maximized, as there is no de-maximize button!
if (window.WindowState == WindowState.Maximized)
{
window.WindowState = WindowState.Normal;
}
window.Topmost = true;
}
catch (Exception)
{
// Gulp. Avoids "Cannot set visibility while window is closing".
}
}
/// <summary>
/// Intent: Ensure that small notification window can be hidden by other windows.
/// </summary>
/// <param name="window"></param>
public static void ShiftWindowIntoBackground(Window window)
{
try
{
// Prevent the window from grabbing focus away from other windows the first time is created.
window.ShowActivated = false;
// Do not use .Show() and .Hide() - not compatible with Citrix!
if (window.Visibility != Visibility.Collapsed)
{
window.Visibility = Visibility.Collapsed;
}
// We can't allow the window to be maximized, as there is no de-maximize button!
if (window.WindowState == WindowState.Maximized)
{
window.WindowState = WindowState.Normal;
}
window.Topmost = false;
}
catch (Exception)
{
// Gulp. Avoids "Cannot set visibility while window is closing".
}
}
}
使用
在以使用此,需要创建的窗口,在你的视图模型:
private ToastView _toastViewWindow;
private void ShowWindow()
{
if (_toastViewWindow == null)
{
_toastViewWindow = new ToastView();
_dialogService.Show<ToastView>(this, this, _toastViewWindow, true);
}
ShiftWindowOntoScreenHelper.ShiftWindowOntoScreen(_toastViewWindow);
HideAndShowWindowHelper.ShiftWindowIntoForeground(_toastViewWindow);
}
private void HideWindow()
{
if (_toastViewWindow != null)
{
HideAndShowWindowHelper.ShiftWindowIntoBackground(_toastViewWindow);
}
}
额外的链接
有关如何确保通知的窗口总是转移到可见的屏幕,请参阅我的回答: WPF中,如何转变的一个窗口到屏幕上如果它是关闭的屏幕上?.
好吧,既然这是一个热门话题...这里是怎么对我的作品。我得到了错误的,如果我不这样做,因为激活()将错误了你,如果你看不见窗口。
键
<Window ....
Topmost="True"
....
ContentRendered="mainWindow_ContentRendered"> .... </Window>
代码隐藏:
private void mainWindow_ContentRendered(object sender, EventArgs e)
{
this.Topmost = false;
this.Activate();
_UsernameTextBox.Focus();
}
这是唯一的方式对我来说,获得窗口,以显示在上面。然后激活它所以你可以型的盒子,而不必设置的重点。控制。重点()不会的工作,除非该窗口活动();
以显示任何前打开的窗口,进口这些DLL:
public partial class Form1 : Form
{
[DllImportAttribute("User32.dll")]
private static extern int FindWindow(String ClassName, String WindowName);
[DllImportAttribute("User32.dll")]
private static extern int SetForegroundWindow(int hWnd);
在计划我们的搜索程序与规定的标题(编写的标题没有第一个字母(指数>0))
foreach (Process proc in Process.GetProcesses())
{
tx = proc.MainWindowTitle.ToString();
if (tx.IndexOf("Title of Your app WITHOUT FIRST LETTER") > 0)
{
tx = proc.MainWindowTitle;
hWnd = proc.Handle.ToInt32(); break;
}
}
hWnd = FindWindow(null, tx);
if (hWnd > 0)
{
SetForegroundWindow(hWnd);
}
问题可能是线呼叫你的代码从钩没有被初始化时,通过运行时所呼吁的运行时方法不起作用。
也许你可以尝试做一个调元帅你的代码,UI线呼叫你的代码,带来了窗的前景。
这些编码工作的现所有的时间。
在第一组活性事件处理程序键
Activated="Window_Activated"
添加下面的线到主窗口的构造模块:
public MainWindow()
{
InitializeComponent();
this.LocationChanged += (sender, e) => this.Window_Activated(sender, e);
}
和内部的活性事件处理程序复制这个代码:
private void Window_Activated(object sender, EventArgs e)
{
if (Application.Current.Windows.Count > 1)
{
foreach (Window win in Application.Current.Windows)
try
{
if (!win.Equals(this))
{
if (!win.IsVisible)
{
win.ShowDialog();
}
if (win.WindowState == WindowState.Minimized)
{
win.WindowState = WindowState.Normal;
}
win.Activate();
win.Topmost = true;
win.Topmost = false;
win.Focus();
}
}
catch { }
}
else
this.Focus();
}
这些步骤将工作现,并将带来前所有的其他窗口为他们的父母窗口。
如果你们试图隐藏的窗口,例如最小的窗口中,我们发现,使用
this.Hide();
会隐藏这是正确的,那么只需使用
this.Show();
然后会显示窗口的最上面的项目一次。
只是想增加另一个解决这个问题。这一执行工作的针对我的情况,在那里CaliBurn负责显示主要的窗口。
protected override void OnStartup(object sender, StartupEventArgs e)
{
DisplayRootViewFor<IMainWindowViewModel>();
Application.MainWindow.Topmost = true;
Application.MainWindow.Activate();
Application.MainWindow.Activated += OnMainWindowActivated;
}
private static void OnMainWindowActivated(object sender, EventArgs e)
{
var window = sender as Window;
if (window != null)
{
window.Activated -= OnMainWindowActivated;
window.Topmost = false;
window.Focus();
}
}
记住不要把代码显示窗口内PreviewMouseDoubleClick处理程序作为活性窗口,就会切换回来的窗口人的事件。只是把它放在MouseDoubleClick事件处理程序或停止冒泡通过设置e。处理真实的。
在我的情况下,我处理的PreviewMouseDoubleClick上的一个列表视图并不是设置的电子.处理=真的,那么它提出了MouseDoubleClick事件的巫婆坐焦点回到原来的窗口。
我建了一个扩展方法使用容易重复使用。
using System.Windows.Forms;
namespace YourNamespace{
public static class WindowsFormExtensions {
public static void PutOnTop(this Form form) {
form.Show();
form.Activate();
}// END PutOnTop()
}// END class
}// END namespace
呼叫在形成的构造
namespace YourNamespace{
public partial class FormName : Form {
public FormName(){
this.PutOnTop();
InitalizeComponents();
}// END Constructor
} // END Form
}// END namespace