[英]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.