[英]WPF - How to run code immediately after a Window is hidden
在我的应用程序中,我截取了桌面的屏幕截图。 在此之前,我隐藏了我的应用程序的Window
,因此它不会覆盖桌面的一部分:
MainWindow.Hide();
TakeScreenShot();
问题是有时窗口的隐藏速度不够快,所以我也截取了它的屏幕截图。 我曾尝试从Window.IsVisibleChanged
事件处理程序中截取屏幕截图,但结果是一样的。
当然,我可以使用Thread.Sleep
或类似的,但我正在寻找更好的解决方案。
更新
我刚刚切换到Aero主题并启用了桌面合成,现在情况更糟。 现在窗口“淡出”而不是在调用Window.Hide
时立即隐藏。 所以现在我的应用程序总是截取一个渐隐窗口的屏幕截图......我将尝试使用SetWindowPos
或ShowWindow
winapi 并将发布更新。
更新 2
ShowWindow
和SetWindowPos
给出与Window.Hide
相同的结果( Window.Hide
使用ShowWindow(HWND, SW_HIDE)
)。
为了在隐藏窗口时禁用淡出效果,我使用了DwmSetWindowAttribute
。
像这样:
using System.Windows.Interop;
using System.Runtime.InteropServices;
[DllImport("dwmapi.dll")]
private static extern int DwmSetWindowAttribute(IntPtr hwnd, int attr, ref int attrValue, int attrSize);
private const int DWMWA_TRANSITIONS_FORCEDISABLED = 3;
并在Window.Loaded
事件处理程序中:
if (Environment.OSVersion.Version.Major >= 6) {
IntPtr WinHandle = new WindowInteropHelper(this).Handle;
int BOOL_TRUE = 1;
int HR = DwmSetWindowAttribute(WinHandle, DWMWA_TRANSITIONS_FORCEDISABLED, BOOL_TRUE, Marshal.SizeOf(BOOL_TRUE));
if (HR != 0)
Marshal.ThrowExceptionForHR(HR);
}
因此,除了淡出效果之外,问题仍然存在。
您可以先在要复制的区域外穿梭于窗口(考虑到子窗口还原问题)。
public partial class MainWindow : Window
{
private DispatcherOperation _action;
private int _width = 2000;
private int _height = 1000;
private double _top;
public MainWindow()
{
InitializeComponent();
Dispatcher.Hooks.OperationCompleted += HooksOnOperationCompleted;
}
private void HooksOnOperationCompleted(object sender, DispatcherHookEventArgs dispatcherHookEventArgs)
{
if(dispatcherHookEventArgs.Operation != _action) return;
_action.Task.ContinueWith((t) =>
{
Rectangle rect = new Rectangle(0, 0, _width, _height);
Bitmap bmp = new Bitmap(rect.Width, rect.Height, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
Graphics g = Graphics.FromImage(bmp);
g.CopyFromScreen(rect.Left, rect.Top, 0, 0, bmp.Size, CopyPixelOperation.SourceCopy);
bmp.Save("help" + DateTime.Now.Ticks + ".jpg", ImageFormat.Jpeg);
}).ContinueWith(t =>
{
Dispatcher.BeginInvoke((Action)(() =>
{
Top = _top;
}));
});
}
private void ButtonBase_OnClick(object sender, RoutedEventArgs e)
{
_top = Top;
_action = Dispatcher.BeginInvoke((Action) (() =>
{
Top = 10000;
}));
}
}
尝试最小化Window
然后再隐藏Window
并以最低优先级Asynchronously
运行它。 这样的事情。
private void Button_Click(object sender, RoutedEventArgs e)
{
//Minimize here before hiding. .
this.WindowState = WindowState.Minimized; //this is the key
this.Visibility = Visibility.Hidden;
this.Dispatcher.BeginInvoke(DispatcherPriority.SystemIdle, new Action(() =>
{
CaptureImage();
}));
}
private void CaptureImage()
{
System.Drawing.Rectangle bounds = new System.Drawing.Rectangle(0, 0, (int)System.Windows.SystemParameters.PrimaryScreenWidth, (int)System.Windows.SystemParameters.PrimaryScreenHeight);
using (Bitmap bitmap = new Bitmap(bounds.Width, bounds.Height))
{
using (Graphics g = Graphics.FromImage(bitmap))
{
g.CopyFromScreen(System.Drawing.Point.Empty, System.Drawing.Point.Empty, bounds.Size);
}
bitmap.Save("test.jpg", ImageFormat.Jpeg);
}
}
希望这可以帮助。 谢谢。
你可以使用这样的东西:
Visibility = Visibility.Collapsed;
Dispatcher.BeginInvoke(()=>{
Thread.Sleep(2000);
TakeScreenShot();
});
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.