2016-08-21 20 views
0

を隠された直後にコードを実行する方法。これは、デスクトップの一部をカバーしないように右、その前に私は、私のアプリのWindowを隠す:WPF - ウィンドウがIは、デスクトップのスクリーンショットを撮る私のアプリでは

MainWindow.Hide(); 
TakeScreenShot(); 

問題は時々ウィンドウが十分に速く隠されないということですので、私もそれのスクリーンショットを撮ることになりました。私はWindow.IsVisibleChangedイベントハンドラからスクリーンショットを撮ろうとしましたが、結果は同じです。もちろん

、私はThread.Sleepまたは類似を使用することができますが、私はよりよい解決策を探しています。

更新

私は、Aeroテーマに切り替えとデスクトップコンポジションを有効にし、現在の状況はさらに悪くなるしています。 Window.Hideを呼び出すとすぐに隠されるのではなく、ウィンドウが「フェードアウト」します。だから今私のアプリは常にフェージングウィンドウのスクリーンショットを取る...私はSetWindowPosまたはShowWindowでWINAPIをしようとすると、更新を掲載します。

アップデート2

  1. ShowWindowSetWindowPosWindow.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); 
} 

だから、フェードアウト効果の横に、問題が残っています。

+0

あなたは(.aspxのhttps://msdn.microsoft.com/en-us/library/system.windows.window.deactivated(V = vs.110))、単純な[OnDeactivated]を試してみましたか?または[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

Ok @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

関連する問題