WPF - 如何在隐藏Window后立即运行代码

时间:2016-08-21 20:54:32

标签: c# wpf windows winapi window

在我的应用程序中,我会截取桌面的截图。在此之前,我隐藏了我的应用程序的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

  3. 像这样:

    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);
    }  
    

    除了淡出效果,问题仍然存在。

2 个答案:

答案 0 :(得分:0)

您可以从您尝试复制的区域之外的窗口开始(当考虑子窗口恢复问题时)。

<li>Last</li>

答案 1 :(得分:0)

在隐藏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);
        }
    }

希望这会有所帮助。感谢。