How to capture the screen and save it to the file.

Hello Everyone. I'm not a experienced developer and i have a problem.

I don't understand how to make screenshot and save it to the file.

[DllImport("/System/Library/Frameworks/ApplicationServices.framework/Versions/A/Frameworks/CoreGraphics.framework/CoreGraphics")]
private static extern IntPtr CGWindowListCreateImage(RectangleF screenBounds, CGWindowListOption windowOption, uint windowID, GWindowImageOption imageOption);

        partial void ButtonClicked (Foundation.NSObject sender) {

            IntPtr screenShot = CGWindowListCreateImage ((RectangleF)NSScreen.MainScreen.Frame, CGWindowListOption.IncludingWindow,
                0, CGWindowImageOption.Default);

            CGImage img = new CGImage(screenShot);
            NSBitmapImageRep imgRep = new NSBitmapImageRep(img);

            NSImage imgf = new NSImage(img, NSScreen.MainScreen.Frame.Size);   
        }

Not sure it's working properly. Can anyone help?

Answers

  • AliaksandrSheliutsinAliaksandrSheliutsin USMember
    edited May 2016

    Done! Was helped on stackoverflow, but there is a question: why we need NSAutoreleasePool?

    [DllImport("/System/Library/Frameworks/ApplicationServices.framework/Versions/A/Frameworks/CoreGraphics.framework/CoreGraphics")]
    private static extern IntPtr CGWindowListCreateImage(RectangleF screenBounds, CGWindowListOption windowOption, uint windowID, GWindowImageOption imageOption);
    
    partial void ButtonClicked (Foundation.NSObject sender) {
    
        using (var pool = new NSAutoreleasePool())
        {
            CGRect fullScreenBounds = NSScreen.MainScreen.Frame;
            IntPtr imageRef = CGWindowListCreateImage((RectangleF)fullScreenBounds, CGWindowListOption.All, 0, CGWindowImageOption.Default);
            var cgImage = new CGImage(imageRef);
            var filePath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Desktop), "StackOverflow.png");
            var fileURL = new NSUrl(filePath, false);
            var imageDestination = CGImageDestination.Create(fileURL, UTType.PNG, 1);
            imageDestination.AddImage(cgImage);
            imageDestination.Close();
        }
    }
    
  • ChrisHamonsChrisHamons Xamurai USForum Administrator, Xamarin Team Xamurai

    So the auto release pool is primarily just a way to scope the memory allocations if a bunch are created in a short period of time that you want cleaned up.

    If your application creates a lot of temporary autoreleased objects within the event loop, however, it may be beneficial to create “local” autorelease pools to help to minimize the peak memory footprint.

    https://developer.apple.com/library/mac/documentation/Cocoa/Reference/Foundation/Classes/NSAutoreleasePool_Class/

  • bogdanvi86bogdanvi86 Member

    Hi Chris,
    For the code above to work I had to use a CGRect instead of a RectangleF in the definition of CGWindowListCreateImage. Beside that, this does not seem to free the memory. I run this in a loop 40 times just to confirm and the memory usage is huge.
    Any suggestions as to how I can avoid this leak?

    Thanks.
    Bogdan

    PS: thanks for all useful answers you post in the forum!

  • ChrisHamonsChrisHamons Xamurai USForum Administrator, Xamarin Team Xamurai

    This thread was from 2016 and in Classic, not unified, so CGRect was RectangleF back then.

    You very likely need to CFRelease your handle from CGWindowListCreateImage when you are finished. When you manually bind APIs, it is your responsibility to handle memory management. C# knows nothing of the memory that was allocated on your behalf.

Sign In or Register to comment.