?
Solved

Screen Scraping with C#?

Posted on 2004-09-10
7
Medium Priority
?
732 Views
Last Modified: 2011-09-20
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
0
Comment
Question by:rmyhre
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 4
  • 2
7 Comments
 
LVL 4

Accepted Solution

by:
thedude112286 earned 2000 total points
ID: 12030163
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
 

Author Comment

by:rmyhre
ID: 12030252
Wow... a lot to disect there... thanks.

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

Any help?
0
 
LVL 4

Expert Comment

by:thedude112286
ID: 12034486
I'm going away for the weekend but I'll look into comparing the images when I get back.
0
VIDEO: THE CONCERTO CLOUD FOR HEALTHCARE

Modern healthcare requires a modern cloud. View this brief video to understand how the Concerto Cloud for Healthcare can help your organization.

 
LVL 4

Expert Comment

by:thedude112286
ID: 12039977
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
 
LVL 4

Expert Comment

by:thedude112286
ID: 12039980
Actually, I'm not sure about how == works on Bitmaps.  You may need to examine each bit to see if it is equal.
0
 

Author Comment

by:rmyhre
ID: 12044678
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

Featured Post

VIDEO: THE CONCERTO CLOUD FOR HEALTHCARE

Modern healthcare requires a modern cloud. View this brief video to understand how the Concerto Cloud for Healthcare can help your organization.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Extention Methods in C# 3.0 by Ivo Stoykov C# 3.0 offers extension methods. They allow extending existing classes without changing the class's source code or relying on inheritance. These are static methods invoked as instance method. This…
We all know that functional code is the leg that any good program stands on when it comes right down to it, however, if your program lacks a good user interface your product may not have the appeal needed to keep your customers happy. This issue can…
This tutorial will teach you the special effect of super speed similar to the fictional character Wally West aka "The Flash" After Shake : http://www.videocopilot.net/presets/after_shake/ All lightning effects with instructions : http://www.mediaf…
Sometimes it takes a new vantage point, apart from our everyday security practices, to truly see our Active Directory (AD) vulnerabilities. We get used to implementing the same techniques and checking the same areas for a breach. This pattern can re…
Suggested Courses

771 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question