2016-05-25 8 views
2

次のコードは、画面の一部のスナップショットを(マウス座標で)取得し、Imageコントロールに表示する必要があります。WPFでBitmapSourceを表示しない

public partial class MainWindow : Window 
{ 
    Timer timer = new Timer(100); 
    public MainWindow() 
    { 
     InitializeComponent(); 

     timer.Elapsed += Timer_Elapsed; 
     timer.Start(); 
    } 

    [System.Runtime.InteropServices.DllImport("gdi32.dll")] 
    public static extern bool DeleteObject(IntPtr hObject); 

    private void Timer_Elapsed(object sender, ElapsedEventArgs e) 
    { 
     viewerImage.Source = GetSnapAtMouseCoords((int)((Grid)viewerImage.Parent).ActualWidth, (int)((Grid)viewerImage.Parent).ActualHeight, System.Windows.Forms.Cursor.Position); 
    } 

    private BitmapSource GetSnapAtMouseCoords(int width, int height, System.Drawing.Point mousePosition) 
    { 
     IntPtr handle = IntPtr.Zero; 

     try 
     { 

      using (var screenBmp = new Bitmap(width, height, System.Drawing.Imaging.PixelFormat.Format32bppArgb)) 
      { 
       using (var bmpGraphics = Graphics.FromImage(screenBmp)) 
       { 
        bmpGraphics.CopyFromScreen(mousePosition.X, mousePosition.Y, 0, 0, screenBmp.Size); 

        handle = screenBmp.GetHbitmap(); 

        var bs = System.Windows.Interop.Imaging.CreateBitmapSourceFromHBitmap(
        handle, 
        IntPtr.Zero, 
        Int32Rect.Empty, 
        BitmapSizeOptions.FromEmptyOptions()); 

        return bs; 
       } 
      } 
     } 

     finally 
     { 
      DeleteObject(handle); 
     } 
    } 
} 

イメージソースをBitmapSourceに設定するまではすべて動作します。残念ながら、画像は決してスクリーン上にレンダリングされません。

私はGUIスレッド上にBitmapSourceを作成しているからかもしれないと思うかもしれません...しかし、私はそれほど確信していません。

ご意見やご提案は歓迎いたします。

+0

"GUIスレッドでBitmapSourceを作成しています"実際にはタイマーは別のスレッドで実行されるため、実際には実行していません。代わりにDispatcherTimerを使用することができます。 – Clemens

答えて

3

実際は、別のスレッドでGUIにアクセスしているからです。ただFrozen(スレッドセーフ)BitmapSourceを返すスレッド

Dispatcher.BeginInvoke(new Action(() => 
{ 
    viewerImage.Source = GetSnapAtMouseCoords(
     (int)((Grid)viewerImage.Parent).ActualWidth, 
     (int)((Grid)viewerImage.Parent).ActualHeight, 
     System.Windows.Forms.Cursor.Position); 
})); 

またはバックグラウンドですべての処理を行います。あなたは、このような最初の呼び出しをラップすることができます。 UIスレッドが所有しているので、(int)((Grid)viewerImage.Parent).ActualWidthを別の方法で渡す必要があります。

bs.Freeze(); 

Dispatcher.BeginInvoke(new Action(() => 
{ 
    viewerImage.Source = bs; 
})); 
+0

ありがとうございます! –

関連する問題