Solved

C# Windows Screen Capture

Posted on 2004-09-11
6
1,023 Views
Last Modified: 2009-12-16
Okay, here is the problem: I have managed to get a screen capture and turn it into a bitmap, using only one API call (I don't know if this is significant, but I know I started with about 10...).

My question, is how I can get rid of this BitBlt API call?


    [System.Runtime.InteropServices.DllImport("gdi32.dll")]
    private static extern int BitBlt(int srchDC, int srcX, int srcY, int srcW, int srcH, int desthDC, int destX, int destY, int op);
   
    private static System.Drawing.Bitmap CaptureScreen()
    {
      System.Drawing.Graphics displayGraphics = System.Drawing.Graphics.FromHwnd(IntPtr.Zero);
      using(displayGraphics)
      {
        System.Drawing.Rectangle screenBounds = System.Windows.Forms.Screen.PrimaryScreen.Bounds;
        System.Drawing.Bitmap bitmap = new System.Drawing.Bitmap(screenBounds.Width, screenBounds.Height, displayGraphics);
         
        IntPtr displayHdc = displayGraphics.GetHdc();
        try
        {
          System.Drawing.Graphics bitmapGraphics = System.Drawing.Graphics.FromImage(bitmap);
          using(bitmapGraphics)
          {
            IntPtr bitmapHdc = bitmapGraphics.GetHdc();
            try
            {
              const int SRCCOPY = 13369376;          
              BitBlt(bitmapHdc.ToInt32(), 0, 0, screenBounds.Width, screenBounds.Height, displayHdc.ToInt32(), 0, 0, SRCCOPY);

              return bitmap;
            }
            finally
            {
              bitmapGraphics.ReleaseHdc(bitmapHdc);
            }
          }
        }
        finally
        {
          displayGraphics.ReleaseHdc(displayHdc);
        }
      }
    }
0
Comment
Question by:eternal_21
[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
6 Comments
 
LVL 23

Expert Comment

by:rama_krishna580
ID: 12036786
Hi,

Tryout this...

Here's how to get the screen shot:

public virtual Image GetScreenShot()
{
     Graphics graphics =null;;
     Graphics graphics_new=null;
     try
    {
     graphics = this.CreateGraphics();
     Image screenShot_ = new Bitmap(this.ClientRectangle.Width, this.ClientRectangle.Height, graphics);
     graphics_new= Graphics.FromImage(screenShot_);
     IntPtr handle_1 = graphics.GetHdc();
     IntPtr handle_2 =graphics_new.GetHdc();
     BitBlt(handle_2, 0, 0, this.ClientRectangle.Width, this.ClientRectangle.Height, handle_1, 0, 0, 13369376);
     graphics.ReleaseHdc(handle_1);
     graphics_new.ReleaseHdc(handle_2);
     return screenShot_;
     }
     finally
     {
     if(null!=graphics) graphics.Dispose();
     if(null!=graphics_new) graphics_new.Dispose();
     }
}

Need this:
          [System.Runtime.InteropServices.DllImportAttribute("gdi32.dll")]
          private static extern bool BitBlt(
               IntPtr hdcDest,  
               int nXDest,  
               int nYDest,  
               int nWidth,  
               int nHeight,  
               IntPtr hdcSrc,
               int nXSrc,    
               int nYSrc,          
               System.Int32 dwRop  
               );


Once you have you image, save away...

R.K
0
 
LVL 10

Author Comment

by:eternal_21
ID: 12037220
Okay.... if you like, modify YOUR function so that it does not require the BitBlt call.... I am trying to avoid making API calls.
0
 
LVL 1

Expert Comment

by:roflkind
ID: 12042324
i think in this case it's not possible to make a function like that without a single API function
0
PeopleSoft Has Never Been Easier

PeopleSoft Adoption Made Smooth & Simple!

On-The-Job Training Is made Intuitive & Easy With WalkMe's On-Screen Guidance Tool.  Claim Your Free WalkMe Account Now

 
LVL 10

Author Comment

by:eternal_21
ID: 12044801
I though there might be some way (in unsafe code?) to copy data from one Graphics object to another.
0
 
LVL 10

Expert Comment

by:ptmcomp
ID: 12047514
This could also be a way: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/gdi/prntspol_6qpj.asp
(But it's also unmanaged code - but behind most of the .net framework calls are PInvoke calls. Unfortuanetly they're not all wrapped by the framework)
0
 
LVL 10

Accepted Solution

by:
ptmcomp earned 500 total points
ID: 12091215
           private void button1_Click(object sender, System.EventArgs e)
            {
                  Control control = this;

                  using (Graphics wndGraphics = control.CreateGraphics())
                  {
                        Size size = control.DisplayRectangle.Size;
                        Bitmap bitmap = new Bitmap(size.Width, size.Height, wndGraphics);
                        using (Graphics bmpGraphics = Graphics.FromImage(bitmap))
                        {
                              PaintRecursive(Point.Empty, control, bmpGraphics, size);
                        }
                        bitmap.Save(@"c:\test.bmp", ImageFormat.Bmp);
                  }
            }

            private void PaintRecursive(Point location, Control control, Graphics graphics, Size size)
            {
                  graphics.ResetTransform();
                  graphics.Transform = new Matrix(1,0,0,1,location.X, location.Y);

                  InvokePaintBackground(control, new PaintEventArgs(graphics, new Rectangle(Point.Empty, size)));
                  InvokePaint(control, new PaintEventArgs(graphics, new Rectangle(Point.Empty, size)));
                  foreach(Control innerControl in control.Controls)
                  {
                        Point innerLocation = new Point(location.X + innerControl.Left, location.Y + innerControl.Top);
                        PaintRecursive(innerLocation, innerControl, graphics, innerControl.ClientSize);
                  }
            }

But it doesn't paint the controls that are drawn by unmanaged code :o(
0

Featured Post

Independent Software Vendors: We Want Your Opinion

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

Question has a verified solution.

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

This article is for Object-Oriented Programming (OOP) beginners. An Interface contains declarations of events, indexers, methods and/or properties. Any class which implements the Interface should provide the concrete implementation for each Inter…
It was really hard time for me to get the understanding of Delegates in C#. I went through many websites and articles but I found them very clumsy. After going through those sites, I noted down the points in a easy way so here I am sharing that unde…
Finds all prime numbers in a range requested and places them in a public primes() array. I've demostrated a template size of 30 (2 * 3 * 5) but larger templates can be built such 210  (2 * 3 * 5 * 7) or 2310  (2 * 3 * 5 * 7 * 11). The larger templa…
In an interesting question (https://www.experts-exchange.com/questions/29008360/) here at Experts Exchange, a member asked how to split a single image into multiple images. The primary usage for this is to place many photographs on a flatbed scanner…

733 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