Solved

C# Windows Screen Capture

Posted on 2004-09-11
6
1,012 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
Is Your Active Directory as Secure as You Think?

More than 75% of all records are compromised because of the loss or theft of a privileged credential. Experts have been exploring Active Directory infrastructure to identify key threats and establish best practices for keeping data safe. Attend this month’s webinar to learn more.

 
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

Is Your Active Directory as Secure as You Think?

More than 75% of all records are compromised because of the loss or theft of a privileged credential. Experts have been exploring Active Directory infrastructure to identify key threats and establish best practices for keeping data safe. Attend this month’s webinar to learn more.

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…
Introduction Although it is an old technology, serial ports are still being used by many hardware manufacturers. If you develop applications in C#, Microsoft .NET framework has SerialPort class to communicate with the serial ports.  I needed to…
You have products, that come in variants and want to set different prices for them? Watch this micro tutorial that describes how to configure prices for Magento super attributes. Assigning simple products to configurable: We assigned simple products…
With Secure Portal Encryption, the recipient is sent a link to their email address directing them to the email laundry delivery page. From there, the recipient will be required to enter a user name and password to enter the page. Once the recipient …

914 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

Need Help in Real-Time?

Connect with top rated Experts

13 Experts available now in Live!

Get 1:1 Help Now