2016-05-25 94 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」,實際上你沒有這樣做,因爲Timer運行在不同的線程上。您可以改用DispatcherTimer。 – Clemens

回答

3

其實這是因爲你正在訪問不同的線程上的GUI。您可以包住初始呼叫是這樣的:

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

或者做後臺的所有處理線程的只是返回一個Frozen(線程安全)BitmapSource。你會徘徊需要不同地傳遞(int)((Grid)viewerImage.Parent).ActualWidth,因爲它也由UI線程擁有。

bs.Freeze(); 

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

非常感謝! –