簡體   English   中英

WPF - 如何在隱藏窗口后立即運行代碼

[英]WPF - How to run code immediately after a Window is hidden

在我的應用程序中,我截取了桌面的屏幕截圖。 在此之前,我隱藏了我的應用程序的Window ,因此它不會覆蓋桌面的一部分:

MainWindow.Hide();  
TakeScreenShot();

問題是有時窗口的隱藏速度不夠快,所以我也截取了它的屏幕截圖。 我曾嘗試從Window.IsVisibleChanged事件處理程序中截取屏幕截圖,但結果是一樣的。

當然,我可以使用Thread.Sleep或類似的,但我正在尋找更好的解決方案。

更新

我剛剛切換到Aero主題並啟用了桌面合成,現在情況更糟。 現在窗口“淡出”而不是在調用Window.Hide時立即隱藏。 所以現在我的應用程序總是截取一個漸隱窗口的屏幕截圖......我將嘗試使用SetWindowPosShowWindow winapi 並將發布更新。

更新 2

  1. ShowWindowSetWindowPos給出與Window.Hide相同的結果( Window.Hide使用ShowWindow(HWND, SW_HIDE) )。

  2. 為了在隱藏窗口時禁用淡出效果,我使用了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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM