2016-08-21 54 views
0

在我的應用程序中,我拍攝了桌面的屏幕截圖。之前正確的,我躲在我的應用程序的Window,所以它不會覆蓋桌面的一部分:WPF - 隱藏窗口後如何立即運行代碼

MainWindow.Hide(); 
TakeScreenShot(); 

的問題是,有時窗口沒有得到隱藏的速度不夠快,所以我最終採取它的屏幕截圖太。我試圖從Window.IsVisibleChanged事件處理程序中截取屏幕截圖,但結果相同。

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

更新

我剛切換到Aero主題並啓用桌面組合,而現在的情況更糟。現在窗口「淡出」,而不是在撥打Window.Hide時立即隱藏。所以,現在我的應用程序總是截屏的一個衰落窗口...我會嘗試與SetWindowPosShowWindow winapi,並會發布更新。

更新2

  1. ShowWindowSetWindowPos和得到相同的結果Window.HideWindow.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); 
} 

所以旁邊的淡出效果,問題依然存在。

+0

你試過簡單的[OnDeactivated](https://msdn.microsoft.com/en-us/library/system.windows.window.deactivated(v = vs.110).aspx)嗎?或[OnStateChanged](https://msdn.microsoft.com/en-us/library/system.windows.window.statechanged(v = vs.110).aspx)與過濾器檢查「最小化」狀態? – quetzalcoatl

+0

@quetzalcoatl:我試圖從Window.Deactivated事件處理程序中截取屏幕截圖。結果是一樣的。我沒有嘗試從StateChanged,因爲我不想最小化窗口。 – Bohoo

+0

@Bohoo你能告訴我你'TakeScreenShot'是怎麼樣的嗎? – Gopichandar

回答

0

您可以從您試圖複製的區域之外(當考慮子窗口恢復問題時)開始放置窗口。

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

感謝您的回答。把窗戶放在屏幕外是有效的,但是它是一種黑客......我不知道當我這樣做時究竟發生了什麼,以及後果如何。由於它是一個生產代碼,我寧願不使用它。你也可以看到我的問題更新。 – Bohoo

+0

好的@Bohoo。但我不明白你說的是什麼意思; 「當我這樣做時究竟發生了什麼,以及後果如何」。通過應用Top = Y_POSITION您只需將窗口移動到屏幕上的特定(Y_POSITION)位置。問候。 – Ilan

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

希望這會有所幫助。謝謝。

+0

感謝您的回答。由於涉及到動畫,我不想將窗口最小化。使用'DispatcherPriority.SystemIdle'本身並沒有幫助。你可以看到我的問題的更新。 – Bohoo