views:

162

answers:

1

I'm new to using WPF and GDI, and I'm having trouble displaying an image. My eventual goal is to build something expose-like. So far, I gray-out the screens, gather all the active HWNDs, and capture the screens of all the windows. For now, I have a single Image element that I try to set the source for, but nothing ever shows up.

foreach (IntPtr hwnd in hwndlist)
{
    IntPtr windowhdc = GetDC((IntPtr) hwnd);
    IntPtr bmap = CreateBitmap(400, 400, 1, 32, null);
    IntPtr bitmaphdc = GetDC(bmap);
    BitBlt(bitmaphdc, 0, 0, System.Convert.ToInt32(this.Width), System.Convert.ToInt32(this.Height), windowhdc, 0, 0, TernaryRasterOperations.SRCCOPY);
    ReleaseDC(hwnd, windowhdc);
    BitmapSource bmapSource = System.Windows.Interop.Imaging.CreateBitmapSourceFromHBitmap(bmap, IntPtr.Zero, Int32Rect.Empty, System.Windows.Media.Imaging.BitmapSizeOptions.FromEmptyOptions());
    image1.Source = bmapSource;
    image1.BeginInit();
}

The complete code is here:
http://pastebin.com/m70af590 - code
http://pastebin.com/m38966750 - xaml

I know the way I have it now doesn't make much sense for what I'm trying to do (running the loop and just writing to the same Image over and over), but I'm hoping to have something on that Image by the end.

I've tried hard coding the HWND of a visible window, and it still won't work.

Thanks for any help!

+1  A: 

I think working with a Memory DC will solve your problem. To do this, first import:

[DllImport("gdi32.dll", EntryPoint = "CreateCompatibleDC")]
public static extern IntPtr CreateCompatibleDC(IntPtr hdc);

[DllImport("gdi32.dll", EntryPoint = "SelectObject")]
public static extern IntPtr SelectObject(IntPtr hdc, IntPtr bmp);

[DllImport("gdi32.dll",EntryPoint="DeleteDC")]
public static extern IntPtr DeleteDC(IntPtr hDc);

And instead of this:

IntPtr bitmaphdc = GetDC(bmap);
BitBlt(bitmaphdc, 0, 0, System.Convert.ToInt32(this.Width), System.Convert.ToInt32(this.Height), windowhdc, 0, 0, TernaryRasterOperations.SRCCOPY);

Do this:

IntPtr memdc = CreateCompatibleDC(windowhdc);
SelectObject(memdc, bmap);

BitBlt(memdc, 0, 0, System.Convert.ToInt32(this.Width), System.Convert.ToInt32(this.Height), windowhdc, 0, 0, TernaryRasterOperations.SRCCOPY);

Don't forget to delete the Memort DC later:

DeleteDC(memdc);

And BTW, you don't need image1.BeginInit();.

Also to check, you do not need to enumerate all windows. Use GetDesktopWindow method from user32.dll instead.

Yogesh