2009-11-15 11 views
3

Avec Windows Presentation Foundation, si j'ai un HWND, comment puis-je capturer sa fenêtre en tant qu'image que je peux manipuler et afficher?Capture d'une fenêtre avec WPF

+0

que voulez-vous dire? un HWND d'une autre fenêtre, non WPF? –

+0

En effet, le HWND d'une fenêtre arbitraire. – directedition

Répondre

8

Vous pouvez:

  1. CreateBitmap() pour créer un hBitmap
  2. Appel GetDC() sur les hWnd
  3. BitBlt() le contenu du hBitmap
  4. ReleaseDC()
  5. Appel Imaging.CreateBitmapSourceFromHBitmap() pour créer une gestion BitmapSource
  6. DeleteObject() sur la hBitmap
  7. Utilisez le BitmapSource si besoin

étapes 1 à 4 et 6 utilisent l'API Win32 (GDI pour être précis), les étapes 5 et 7 sont effectuées en utilisant WPF

+0

Merci! J'ai tout configuré et compilé sans problème. Je suis toujours sûr de savoir comment appliquer le BitmapSource à mon directedition

+0

Dans le code: Image.Source = myImageSource. En XAML:

+0

C'est 'DeleteObject()' http://msdn.microsoft.com/en-us/library/dd183539(VS.85).aspx pas la version – Ciantic

7

Bien que ci-dessus réponse est grande, cela aurait sauvé une tonne de temps trop:

section Utilisation:

using System; 
using System.Windows; 
using System.Windows.Interop; 
using System.Runtime.InteropServices; 
using System.Windows.Media.Imaging; 

code:

/// <summary> 
/// Captures screenshot using WINAPI. 
/// </summary> 
static public class CaptureScreenshot 
{ 
    /// <summary> 
    /// Capture the screenshot. 
    /// <param name="area">Area of screenshot.</param> 
    /// <returns>Bitmap source that can be used e.g. as background.</returns> 
    /// </summary> 
    public static BitmapSource Capture(Rect area) 
    { 
     IntPtr screenDC = GetDC(IntPtr.Zero); 
     IntPtr memDC = CreateCompatibleDC(screenDC); 
     IntPtr hBitmap = CreateCompatibleBitmap(screenDC, (int)SystemParameters.VirtualScreenWidth, (int)SystemParameters.VirtualScreenHeight); 
     SelectObject(memDC, hBitmap); // Select bitmap from compatible bitmap to memDC 

     // TODO: BitBlt may fail horribly 
     BitBlt(memDC, 0, 0, (int)area.Width, (int)area.Height, screenDC, (int)area.X, (int)area.Y, TernaryRasterOperations.SRCCOPY); 
     BitmapSource bsource = Imaging.CreateBitmapSourceFromHBitmap(hBitmap, IntPtr.Zero, Int32Rect.Empty, BitmapSizeOptions.FromEmptyOptions()); 

     DeleteObject(hBitmap); 
     ReleaseDC(IntPtr.Zero, screenDC); 
     ReleaseDC(IntPtr.Zero, memDC); 
     return bsource; 
    } 

    #region WINAPI DLL Imports 

    [DllImport("gdi32.dll", ExactSpelling = true, PreserveSig = true, SetLastError = true)] 
    static extern IntPtr SelectObject(IntPtr hdc, IntPtr hgdiobj); 

    [DllImport("gdi32.dll")] 
    private static extern IntPtr CreateCompatibleBitmap(IntPtr hdc, int nWidth, int nHeight); 

    [DllImport("gdi32.dll", SetLastError = true)] 
    private static extern IntPtr CreateCompatibleDC(IntPtr hdc); 

    [DllImport("gdi32.dll")] 
    private static extern bool DeleteObject(IntPtr hObject); 

    [DllImport("gdi32.dll")] 
    private static extern IntPtr CreateBitmap(int nWidth, int nHeight, uint cPlanes, uint cBitsPerPel, IntPtr lpvBits); 

    [DllImport("user32.dll")] 
    private static extern IntPtr GetDC(IntPtr hWnd); 

    [DllImport("user32.dll")] 
    private static extern int ReleaseDC(IntPtr hWnd, IntPtr hDC); 

    private enum TernaryRasterOperations : uint 
    { 
     /// <summary>dest = source</summary> 
     SRCCOPY = 0x00CC0020, 
     /// <summary>dest = source OR dest</summary> 
     SRCPAINT = 0x00EE0086, 
     /// <summary>dest = source AND dest</summary> 
     SRCAND = 0x008800C6, 
     /// <summary>dest = source XOR dest</summary> 
     SRCINVERT = 0x00660046, 
     /// <summary>dest = source AND (NOT dest)</summary> 
     SRCERASE = 0x00440328, 
     /// <summary>dest = (NOT source)</summary> 
     NOTSRCCOPY = 0x00330008, 
     /// <summary>dest = (NOT src) AND (NOT dest)</summary> 
     NOTSRCERASE = 0x001100A6, 
     /// <summary>dest = (source AND pattern)</summary> 
     MERGECOPY = 0x00C000CA, 
     /// <summary>dest = (NOT source) OR dest</summary> 
     MERGEPAINT = 0x00BB0226, 
     /// <summary>dest = pattern</summary> 
     PATCOPY = 0x00F00021, 
     /// <summary>dest = DPSnoo</summary> 
     PATPAINT = 0x00FB0A09, 
     /// <summary>dest = pattern XOR dest</summary> 
     PATINVERT = 0x005A0049, 
     /// <summary>dest = (NOT dest)</summary> 
     DSTINVERT = 0x00550009, 
     /// <summary>dest = BLACK</summary> 
     BLACKNESS = 0x00000042, 
     /// <summary>dest = WHITE</summary> 
     WHITENESS = 0x00FF0062 
    } 

    [DllImport("gdi32.dll")] 
    private static extern bool BitBlt(IntPtr hdc, int nXDest, int nYDest, int nWidth, int nHeight, IntPtr hdcSrc, int nXSrc, int nYSrc, TernaryRasterOperations dwRop); 

    #endregion 
} 

Notez que cela prend capture d'écran de la zone donnée dans l'écran et non de la fenêtre. Cela fonctionne pour mes fins, vous devez probablement le modifier pour le vôtre :)

+0

Merci. J'ai fait quelque chose de très similaire. Je cacherais() toutes les fenêtres que je ne veux pas, je ferai un screencap celui que je fais, et restituerais les autres après. – directedition