Recent

Author Topic: Screenshots on Mac OX X 10.7 Lion  (Read 16985 times)

tristan_2468

  • New member
  • *
  • Posts: 7
Screenshots on Mac OX X 10.7 Lion
« on: May 17, 2012, 11:45:14 am »
Hi,

I have been using the following code to take screenshots of my app window for the last few years, with no problems. With Mac OS X 10.7 Lion however, the resulting image is all black.

procedure TfrmMain.CaptureScreenshot(var Image: TBitmap);
var
  BMP: TBitmap;
  ScreenDC: HDC;
begin
  BMP := TBitmap.Create;
  ScreenDC := GetDC(0);
  BMP.LoadFromDevice(ScreenDC);
  ReleaseDC(0, ScreenDC);

  Image.SetSize(Self.Width, Self.Height);

  Image.Canvas.CopyRect(Rect(0, 0, Self.Width - 1, Self.Height - 1), BMP.Canvas,
    Rect(Self.Left, Self.Top, Self.Left + Self.Width - 1, Self.Top + Self.Height - 1 + 22));

  BMP.Free;
end;


It is the example code from the Lazarus Wiki on taking screenshots.

I have reported in the bug here:
http://bugs.freepascal.org/view.php?id=21845

and it was mentioned that Apple broke this ability with 10.7, and that I can use LCL-CustomDrawn-Cocoa or a "new [method] which works only in 10.6+"

I was wondering if anyone had managed to get this to work and could provide me with some example code or pointers where to find the information for the technique.

I would prefer to keep my app compiled against the Carbon widgetset if I can.

Thank you,
Tristan

Shebuka

  • Sr. Member
  • ****
  • Posts: 427
Re: Screenshots on Mac OX X 10.7 Lion
« Reply #1 on: May 17, 2012, 12:14:39 pm »
I can confirm this (i'm using this for a while, but never noticed that on Lion it's not working...)

jwdietrich

  • Hero Member
  • *****
  • Posts: 1232
    • formatio reticularis
Re: Screenshots on Mac OX X 10.7 Lion
« Reply #2 on: May 17, 2012, 02:11:23 pm »
I think this is the result of rigid security measures that were introduced with Mac OS 10.7. Obviously, screen access has been blocked by Lion's sandboxing mechanism.
function GetRandomNumber: integer; // xkcd.com
begin
  GetRandomNumber := 4; // chosen by fair dice roll. Guaranteed to be random.
end;

http://www.formatio-reticularis.de

Lazarus 2.2.6 | FPC 3.2.2 | PPC, Intel, ARM | macOS, Windows, Linux

felipemdc

  • Administrator
  • Hero Member
  • *
  • Posts: 3538
Re: Screenshots on Mac OX X 10.7 Lion
« Reply #3 on: May 17, 2012, 03:59:14 pm »
I think this is the result of rigid security measures that were introduced with Mac OS 10.7. Obviously, screen access has been blocked by Lion's sandboxing mechanism.

Screen access is not blocked, they just changed the APIs which do it. The old way stopped working and the new one works only in 10.6 and this is the nasty part =(

Anyway, LCL-CustomDrawn-Cocoa shows how to use the new way.

tristan_2468

  • New member
  • *
  • Posts: 7
Re: Screenshots on Mac OX X 10.7 Lion
« Reply #4 on: May 17, 2012, 04:27:02 pm »
Anyway, LCL-CustomDrawn-Cocoa shows how to use the new way.

Could you please give me a link to a code example of capturing the screen?
Thanks,
Tristan

felipemdc

  • Administrator
  • Hero Member
  • *
  • Posts: 3538
Re: Screenshots on Mac OX X 10.7 Lion
« Reply #5 on: May 17, 2012, 04:55:58 pm »
Could you please give me a link to a code example of capturing the screen?

Just read the Lazarus source code, here:

http://svn.freepascal.org/cgi-bin/viewvc.cgi/trunk/lcl/interfaces/customdrawn/customdrawnlclintf_cocoa.inc?view=markup&root=lazarus

Line  164 function TCDWidgetSet.RawImage_FromDevice(out ARawImage: TRawImage; ADC: HDC; const ARect: TRect): Boolean;

There is a large comment right before this line which explains the process. After it there is the code of how to do it using CoreGraphic APIs

Patches for LCL-Carbon to implement this are welcome. It would need to detect the Mac OS X version and dynamically load the routine CGDisplayCreateImage. In Mac OS X <= 10.5 it should use the current method.
« Last Edit: May 17, 2012, 05:14:19 pm by felipemdc »

Shebuka

  • Sr. Member
  • ****
  • Posts: 427
Re: Screenshots on Mac OX X 10.7 Lion
« Reply #6 on: July 10, 2013, 10:08:40 am »
Resuming this old problem, was it patched?

I'm trying to implement this but having trouble with dynamically load the CGDisplayCreateImage routine...

Hansaplast

  • Hero Member
  • *****
  • Posts: 674
  • Tweaking4All.com
    • Tweaking4All
Re: Screenshots on Mac OX X 10.7 Lion
« Reply #7 on: July 15, 2013, 11:35:48 pm »
+1 here.
Only getting a black image :(

(looking into the suggested code from link now.)

Hansaplast

  • Hero Member
  • *****
  • Posts: 674
  • Tweaking4All.com
    • Tweaking4All
Re: Screenshots on Mac OX X 10.7 Lion
« Reply #8 on: October 03, 2013, 07:15:16 pm »
Does anybody know if there is an update on this situation?

BigChimp

  • Hero Member
  • *****
  • Posts: 5740
  • Add to the wiki - it's free ;)
    • FPCUp, PaperTiger scanning and other open source projects
Re: Screenshots on Mac OX X 10.7 Lion
« Reply #9 on: October 04, 2013, 09:43:03 am »
Well, nobody posted here, there's no link to a bug report, so my guess would be a resounding NO.
Want quicker answers to your questions? Read http://wiki.lazarus.freepascal.org/Lazarus_Faq#What_is_the_correct_way_to_ask_questions_in_the_forum.3F

Open source including papertiger OCR/PDF scanning:
https://bitbucket.org/reiniero

Lazarus trunk+FPC trunk x86, Windows x64 unless otherwise specified

Hansaplast

  • Hero Member
  • *****
  • Posts: 674
  • Tweaking4All.com
    • Tweaking4All
Re: Screenshots on Mac OX X 10.7 Lion
« Reply #10 on: October 04, 2013, 07:50:20 pm »
Thanks BigChimp.

I did search the forum and used Google for other sources: no progress.
The link to the bug is not showing any progress either.
I just wasn't sure if I overlooked something.

I haven't been able to get the suggested approach to work (my lack of knowledge I'm sure) either.

Thanks again though!  :)

Shebuka

  • Sr. Member
  • ****
  • Posts: 427
Re: Screenshots on Mac OX X 10.7 Lion
« Reply #11 on: April 17, 2014, 12:06:08 pm »
Now we finally target 10.6 as minimum OS version so here it is:

Code: [Select]
uses
  LCLIntf, GraphType, IntfGraphics, CGContext, CGImage, CGGeometry, CGDirectDisplay, CGBitmapContext, CGColorSpace,

procedure TGuiMgr.desktop_screen_grab_mnu_mnuClick(Sender: TObject);
var
  MyBitmap: TBitmap;
  //BMPHandle, BMPMaskHandle: HBITMAP;
  //ScreenDC: HDC;
  WrkJpg: TJpegImage;
  ReceiverDirPath, ScreenPathName: String;

  screenBitmapRawImage: TRawImage;
  monRect: TRect;
  screenBitmapWidth, screenBitmapHeight: Integer;
  screenBitmapContext: CGContextRef;
  screenshotImage: CGImageRef;
  lRect: CGRect;
  screenImage: TLazIntfImage;
  lScreenRawImage: TRawImage;
  lDataLength: SizeInt;
begin
  try 
      ReceiverDirPath := TrimFilename(GetUserDir + PathDelim + 'Downloads' + PathDelim + 'my_app_name');
      if not DirectoryExists(ReceiverDirPath) then
        ForceDirectories(ReceiverDirPath);

      ScreenPathName := ReceiverDirPath + PathDelim + 'Screen-' + UT_CondEventTime() + '[' + IntToStr(Random(899)+100) + '].jpg';    // UT_CondEventTime() returns string with current date

      Application.Minimize;
      Application.ProcessMessages;

      Sleep(32);

      monRect := Screen.WorkareaRect;
      screenBitmapWidth := monRect.Right;
      screenBitmapHeight := monRect.Bottom;

      screenBitmapRawImage.Init;
      screenBitmapRawImage.Description.Init_BPP32_A8R8G8B8_BIO_TTB(screenBitmapWidth, screenBitmapHeight);

      // Take the screenshot
      screenshotImage := CGDisplayCreateImage(CGMainDisplayID()); // Requires 10.6+

      // Draw it to our screen bitmap
      lRect := CGRectMake(0, 0, screenBitmapWidth, screenBitmapHeight);

      screenBitmapRawImage.CreateData(True);
      screenBitmapContext := CGBitmapContextCreate(screenBitmapRawImage.Data,
                                                   screenBitmapWidth,
                                                   screenBitmapHeight,
                                                   8,
                                                   ScreenBitmapWidth * 4,
                                                   CGColorSpaceCreateDeviceRGB(),
                                                   kCGImageAlphaNoneSkipFirst//,kCGImageAlphaPremultipliedFirst
                                                   );
      screenImage := TLazIntfImage.Create(screenBitmapRawImage, True);

      CGContextDrawImage(screenBitmapContext, lRect, screenshotImage);

      // Now copy the data
      screenImage.GetRawImage(lScreenRawImage, False);
      lDataLength := Min(Int64(lScreenRawImage.DataSize), Int64(screenBitmapRawImage.DataSize));
      System.Move(lScreenRawImage.Data^, screenBitmapRawImage.Data^, lDataLength);

      MyBitmap := TBitmap.Create;
      MyBitmap.LoadFromRawImage(screenBitmapRawImage, true);

      Application.Restore;
      Application.BringToFront;

      // Per avere un elenco dei vari formati disponibili (png, bmp, xmp, ecc.):
      // http://wiki.lazarus.freepascal.org/Developing_with_Graphics#Image_formats
      WrkJpg := TJpegImage.Create;
      try
        WrkJpg.CompressionQuality := 80;
        WrkJpg.Assign(MyBitmap);
        WrkJpg.SaveToFile(Utf8ToSys(ScreenPathName));
      finally
        FreeAndNil(WrkJpg);
      end;

      FreeAndNil(MyBitmap);
      //FreeAndNil(screenImage);              //This is commented for a reason, don't uncomment it
      //FreeAndNil(screenBitmapContext);      //This is commented for a reason, don't uncomment it
      //FreeAndNil(screenBitmapRawImage);     //This is commented for a reason, don't uncomment it
      //FreeAndNil(screenshotImage);          //This is commented for a reason, don't uncomment it
  except
    on e: Exception do
      SendLogMsg('TGuiMgr.desktop_screen_grab_mnu_mnuClick => raised: ' + e.Message, LOG_ERROR, LOG_CTX_GUI);
  end;
end;

Comments and suggestions with improvements are welcome :)
« Last Edit: April 17, 2014, 12:10:42 pm by Shebuka »

skalogryz

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 2770
    • havefunsoft.com
Re: Screenshots on Mac OX X 10.7 Lion
« Reply #12 on: April 17, 2014, 12:53:32 pm »
sleep(32)?

Shebuka

  • Sr. Member
  • ****
  • Posts: 427
Re: Screenshots on Mac OX X 10.7 Lion
« Reply #13 on: April 17, 2014, 12:57:12 pm »
sleep(32)?
It's time for minimize animation to execute, without it, depending on machine load, i get at random screenshots with application in foreground.

taazz

  • Hero Member
  • *****
  • Posts: 5368
Re: Screenshots on Mac OX X 10.7 Lion
« Reply #14 on: April 17, 2014, 12:59:50 pm »
isn't this the opposite of what the OP wanted ee he wants a screen shot of his application not the desktop.
Good judgement is the result of experience … Experience is the result of bad judgement.

OS : Windows 7 64 bit
Laz: Lazarus 1.4.4 FPC 2.6.4 i386-win32-win32/win64

 

TinyPortal © 2005-2018