Solved

C# Windows Screen Capture

Posted on 2004-09-11
6
1,022 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
Networking for the Cloud Era

Join Microsoft and Riverbed for a discussion and demonstration of enhancements to SteelConnect:
-One-click orchestration and cloud connectivity in Azure environments
-Tight integration of SD-WAN and WAN optimization capabilities
-Scalability and resiliency equal to a data center

 
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

Free Tool: Postgres Monitoring System

A PHP and Perl based system to collect and display usage statistics from PostgreSQL databases.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

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…
Introduction Hi all and welcome to my first article on Experts Exchange. A while ago, someone asked me if i could do some tutorials on object oriented programming. I decided to do them on C#. Now you may ask me, why's that? Well, one of the re…
Microsoft Active Directory, the widely used IT infrastructure, is known for its high risk of credential theft. The best way to test your Active Directory’s vulnerabilities to pass-the-ticket, pass-the-hash, privilege escalation, and malware attacks …
Two types of users will appreciate AOMEI Backupper Pro: 1 - Those with PCIe drives (and haven't found cloning software that works on them). 2 - Those who want a fast clone of their boot drive (no re-boots needed) and it can clone your drive wh…

860 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