繁体   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