Tuesday, November 11, 2008

Tutor.com Classroom How-To #7: screen-scraping an application via Win32 PrintWindow() API

These How-To tips are taken from The Tutor.com Classroom: Architecture and techniques using Silverlight, WPF, and the Microsoft .NET Framework.

You can check out the Silverlight Tutor.com Classroom in "practice" mode, although the real experience is with a live tutor on the other side!

In the WPF application, we make calls to the PrintWindow() Win32 API to gather screen contents. We then splice the return bitmap into a 4x4 grid and compare hashes of each of the slices with the previous slices’ hashes. If a slice has changed, we package up its bytes and ship it across the wire.

There are two key components to making this process of screen scrape, comparison, and messaging fast enough to run each second without overburdening the CPU. The first is that the entire process runs on a thread pool thread via a timer, which frees up the GUI. The second is that our Bitmap uses the Format32bppArgb pixel format, which uses more memory but optimizes performance of PrintWindow() calls.


[DllImport("user32.dll", SetLastError = true)]
static extern bool PrintWindow(IntPtr hwnd, IntPtr hDC, uint nFlags);

void processCapture()
{
using (Graphics g = Graphics.FromImage(captureBitmap))
{
//get window content
IntPtr hdc = g.GetHdc();
try
{
result = PrintWindow(m_Win32HostHandle, hdc);
}
finally
{
g.ReleaseHdc(hdc);
}

//process captureBitmap
...
}
}

No comments: