Re: Taking screen shots
Re: Taking screen shots
- Subject: Re: Taking screen shots
- From: Kevin Meaney <email@hidden>
- Date: Wed, 18 Jun 2014 19:11:28 +0100
Since the SonOfGrab application works for grabbing the contents of my window, even when it is partially offscreen at the time of taking the screen grab I had a look at what it was doing differently.
Basically SonOfGrab was passing in CGRectNull into CGWindowListCreateImage instead of a defined rectangle. I was defining a rectangle because I wanted the content region of the window not the whole window. So instead I passed in CGRectNull and then afterwards crop the generated CGImageRef down to exclude the window title bar.
This now works as it should and as it does for SonOfGrab.
So now I'm going to ask about why drawing to the windows graphics context directly is not ok.
I'm not dealing with any views, just a window created programmatically with its one content view. The window cannot be
resized. In this situation I believe the issues around lock focus and the calling of draw rect within a view hierarchy may not apply. Are there other issues that will hurt me when drawing directly?
Kevin
On 18 Jun 2014, at 17:47, Kyle Sluder <email@hidden> wrote:
> On Wed, Jun 18, 2014, at 09:01 AM, Kevin Meaney wrote:
>> Drawing happens when I receive an xpc message containing a drawing
>> command. To do the drawing I get the NSGraphicsContext from which I pull
>> the graphicsPort which is a special kind of CGContext. I then use
>> CoreGraphics commands to do the drawing.
>
> You're still not being specific enough. Where is this code happening?
> Which context is it grabbing?
>
> If you want to draw to the screen, you send -setNeedsDisplay: to a view
> and wait for the window to come around and ask you to draw. That is the
> ONLY* way to draw to the screen in OS X.
>
> So this is OK:
>
> // xpc listener
> - (void)handleIncomingDrawCommand:(id)drawCommand {
> AppendDrawCommandToQueue(drawCommand);
> [_myView setNeedsDisplay:YES];
> }
>
> // view
> - (void)drawRect:(NSRect)dirtyRect {
> CGContextRef cgContext = [[NSGraphicsContext currentContext]
> graphicsPort];
> ApplyDrawCommandsFromQueue(cgContext);
> }
>
> This is NOT OK:
>
> - (void)handleIncomingDrawCommand:(id)drawCommand {
> CGContextRef cgContext = [[NSGraphicsContext currentContext]
> graphicsPort];
> ImmediatelyPerformDrawCommand(drawCommand, cgContext); // NO!
> }
>
> Depending on your application, your listener may need to maintain a
> partial or complete history of draw commands it has received so that it
> can draw them all anew in -drawRect:. If it's too expensive to redraw
> all your commands every time you get sent -drawRect:, you can maintain
> _your own_ offscreen buffer and just blit it to the screen in
> -drawRect:.
>
> // xpc listener
> NSBitmapImageRep *_offscreenBuffer;
> - (void)handleIncomingDrawCommand:(id)drawCommand {
> AppendDrawCommandToQueue(drawCommand); // in case we need to resize
> and redraw the _offscreenBuffer
> PerformQueuedDrawCommands(_offscreenBuffer);
> [_myView setNeedsDisplay:YES];
> }
>
> // view
> - (void)setFrameSize:(NSSize)newSize {
> ResizeBuffer(_offscreenBuffer, newSize);
> PerformQueuedDrawCommands(_offscreenBuffer);
> [super setFrameSize:newSize];
> }
>
> - (void)drawRect:(NSRect)dirtyRect {
> [_offscreenBuffer drawAtPoint:self.bounds.origin];
> }
>
> You can build a CGContextRef around an NSBitmapImageRep by using
> +[NSGraphicsContext graphicsContextWithBitmapImageRep:] and getting the
> result's graphicsPort.
>
> --Kyle Sluder
>
> * not really the only way, but the only supported way that works in all
> cases.
_______________________________________________
Cocoa-dev mailing list (email@hidden)
Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden