Solved

C# Windows Screen Capture

Posted on 2004-09-11
6
1,017 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
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
Problems using Powershell and Active Directory?

Managing Active Directory does not always have to be complicated.  If you are spending more time trying instead of doing, then it's time to look at something else. For nearly 20 years, AD admins around the world have used one tool for day-to-day AD management: Hyena. Discover why

 
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

Master Your Team's Linux and Cloud Stack

Come see why top tech companies like Mailchimp and Media Temple use Linux Academy to build their employee training programs.

Question has a verified solution.

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

Introduction This article series is supposed to shed some light on the use of IDisposable and objects that inherit from it. In essence, a more apt title for this article would be: using (IDisposable) {}. I’m just not sure how many people would ge…
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…
This Micro Tutorial demonstrates using Microsoft Excel pivot tables, how to reverse engineer competitors' marketing strategies through backlinks.
This video shows how to quickly and easily add an email signature for all users on Exchange 2016. The resulting signature is applied on a server level by Exchange Online. The email signature template has been downloaded from: www.mail-signatures…

773 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