Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How does the Graphics CopyFromScreen method copy into a bitmap?

Tags:

c#

private void startBot_Click(object sender, EventArgs e)
{
        Bitmap bmpScreenshot = Screenshot();
        this.BackgroundImage = bmpScreenshot;
}

private Bitmap Screenshot()
{

    // This is where we will store a snapshot of the screen
    Bitmap bmpScreenshot = 
        new Bitmap(Screen.PrimaryScreen.Bounds.Width,Screen.PrimaryScreen.Bounds.Height);

    // Creates a graphic object so we can draw the screen in the bitmap (bmpScreenshot);
    Graphics g = Graphics.FromImage(bmpScreenshot);

    // Copy from screen into the bitmap we created
    g.CopyFromScreen(0, 0, 0, 0, Screen.PrimaryScreen.Bounds.Size);

    // Return the screenshot
    return bmpScreenshot;
}

I've been recently playing around with C# and I'm just following some tutorial, I just don't understand how if I was to erase Graphics g it wouldn't put the image as the background, but at no point does the code assign any relation between the variables, other than Graphics g = Graphics.FromImage(bmpScreenshot), then g is given some parameters, but then we return bmpScreenshot which just doesn't make any sense, I would expect g to be returned?

like image 283
Datsik Avatar asked Jul 01 '26 13:07

Datsik


1 Answers

Devices that can display graphics are virtualized in Windows. The concept is called a "device context" in the winapi, underlying representation is a "handle". The Graphics class wraps that handle, it does not itself store the pixels. Note the Graphics.GetHdc() method, a way to get to that handle.

The class otherwise just contains the drawing methods that produce graphics output on the device represented by that handle. Actual devices can be the screen, a printer, a metafile, a bitmap. With the big advantage in your own code that it can be used to produce output where ever you want it to go. So printing is just as easy as painting it to the screen or drawing to a bitmap that you store to a file.

So by calling Graphics.FromImage(), you associate the Graphics object to the bitmap. All of its draw methods actually set pixels in the bitmap. Like CopyFromScreen(), it simply copies pixels from the video adapter's frame buffer to the device context, in effect setting the pixels in the bitmap. So the expected return value of this code is the actual bitmap. The Graphics object should be disposed before that happens since it is no longer useful. Or in other words, the underlying handle needs to be released so the operating system de-allocates its own resources to represent the device context.

That's a bug in the code snippet. Repeated calls to this method can easily crash the program when Windows refuses to create more device contexts. And the garbage collector doesn't otherwise catch up fast enough. It should be written as:

  using (var g = Graphics.FromImage(bmpScreenshot)) {
      g.CopyFromScreen(0, 0, 0, 0, Screen.PrimaryScreen.Bounds.Size);
      return bmpScreenshot;
  }
like image 200
Hans Passant Avatar answered Jul 03 '26 03:07

Hans Passant



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!