Screen Scraping with C#?

Hi,

  I like to play Hearts on MSN Gaming Zone.  I would like to write a program that tracks the different cards that have been played for each round.  So, the question is how do I screen scrape a graphical window using C#?

The steps in my mind would consist of something like:

1) Get the device context of the foreign (Hearts) window
2) Capture the graphic bits in a well-defined, never changing location
3) Compare those graphics (the face of the card) with a library of 52 cards looking for a match

Can anyone help me with this?  Never mind if it is cheating or not, it is a way for me to learn more about graphics and programming.  I would consider giving more points if 500 is not enough for this challenge.

Thanks

Robert
rmyhreAsked:
Who is Participating?
 
thedude112286Connect With a Mentor Commented:
http://www.c-sharpcorner.com/Code/2003/Dec/ScreenCapture.asp was used extensively to develop this

using System;
using System.Drawing;
using System.Drawing.Imaging;
using System.Runtime.InteropServices;

class GDI32
{
      [DllImport("GDI32.dll")]
      public static extern bool BitBlt(int hdcDest,int nXDest,int nYDest,
                                       int nWidth,int nHeight,int hdcSrc,
                                       int nXSrc,int nYSrc,int dwRop);
      [DllImport("GDI32.dll")]
      public static extern int CreateCompatibleBitmap(int hdc,int nWidth,
                                                       int nHeight);
      [DllImport("GDI32.dll")]
      public static extern int CreateCompatibleDC(int hdc);
      [DllImport("GDI32.dll")]
      public static extern bool DeleteDC(int hdc);
      [DllImport("GDI32.dll")]
      public static extern bool DeleteObject(int hObject);
      [DllImport("GDI32.dll")]
      public static extern int GetDeviceCaps(int hdc,int nIndex);
      [DllImport("GDI32.dll")]
      public static extern int SelectObject(int hdc,int hgdiobj);
 

class User32
{
      [DllImport("User32.dll")]
      public static extern int FindWindow(string lpClassName, string lpWindowName);
      [DllImport("User32.dll")]
      public static extern int GetWindowDC(int hWnd);
      [DllImport("User32.dll")]
      public static extern int ReleaseDC(int hWnd,int hDC);
}
 

class Example
{
        string className, windowText;
      
        //the className parameter must be the name of the target window's class
        //and windowText must be the text of the target window - if you've never done
        //straight Win32 API programming and don't understand this concept, ask me
      public void CaptureScreen(string fileName,ImageFormat imageFormat, string className, string windowText)
      {
                  this.className = className;
                this.windowText = windowText;
                  int hdcSrc = User32.GetWindowDC(User32.FindWindow(className, windowText));
            int hdcDest = GDI32.CreateCompatibleDC(hdcSrc);
            int hBitmap = GDI32.CreateCompatibleBitmap(hdcSrc),
                                                                             GDI32.GetDeviceCaps(hdcSrc,8),
                                                                             GDI32.GetDeviceCaps(hdcSrc,10));
            GDI32.SelectObject(hdcDest,hBitmap);
            // set the nWidth, nHeight, nXSrc, and nYSrc parameters of BitBlt to whatever portion of the window you want
            GDI32.BitBlt(hdcDest,0,0,GDI32.GetDeviceCaps(hdcSrc,8),
                            GDI32.GetDeviceCaps(hdcSrc,10),
                            hdcSrc,0,0,0x00CC0020);
            Bitmap bitmap = GetManagedBitmap(hBitmap,fileName,imageFormat);
            Cleanup(hBitmap,hdcSrc,hdcDest);
            
                  //do whatever operations you want to do on bitmap
      }
      private void Cleanup(int hBitmap,int hdcSrc,int hdcDest)
      {
            User32.ReleaseDC(User32.FindWindow(className, windowText),hdcSrc);
            GDI32.DeleteDC(hdcDest);
            GDI32.DeleteObject(hBitmap);
      }      

      private Bitmap GetManagedBitmap(int hBitmap,string fileName,ImageFormat imageFormat)
      {
            Bitmap image =
            new Bitmap(Image.FromHbitmap(new IntPtr(hBitmap)),
                       Image.FromHbitmap(new IntPtr(hBitmap)).Width,
                       Image.FromHbitmap(new IntPtr(hBitmap)).Height);
            return image;
      }
}
0
 
rmyhreAuthor Commented:
Wow... a lot to disect there... thanks.

What I don't see is step 3... how to compare the two images?

Any help?
0
 
thedude112286Commented:
I'm going away for the weekend but I'll look into comparing the images when I get back.
0
Get expert help—faster!

Need expert help—fast? Use the Help Bell for personalized assistance getting answers to your important questions.

 
thedude112286Commented:
All I can think of is to try:

if ( screenBitmap == storedBitmap )
    //match

That should work fine as long as you get the EXACT same area of the window when you store the bitmap and when you get a bitmap to compare.
0
 
thedude112286Commented:
Actually, I'm not sure about how == works on Bitmaps.  You may need to examine each bit to see if it is equal.
0
 
rmyhreAuthor Commented:
I figured it out over the weekend.  Basically I dump the bitmap into a memory stream and then convert the memory stream into a byte array.  Finally, I just iterate through the array checking each value to ensure that they are the same in both the stored image and the scanned image.

Works pretty slick  :)
0
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

All Courses

From novice to tech pro — start learning today.