FROM : Andrew Farmer
DATE : Thu Jul 20 04:08:35 2006
On 19 Jul 06, at 14:31, Eric Summers wrote:
> I'm trying to figure out how programs like Apple's Grab screen capture
> application get an image of other application windows. I thought
> of using
> an AppleEvent to get the bounds of the windows then capturing the
> data using
> a big transparent window, but that wouldn't work if the window is
> hidden.
> Grab will get the image data even if the window is hidden. Anyone
> know how
> the Grab application works?
Yes!
http://www.objective-cocoa.org/forum/index.php?topic=1556.msg15898
The post is in French; here's a copy of the code and a translation of
the
comments, for the list archive and the non-Francophones in the crowd:
NSImage *GrabWindow(int wid)
{
// Get a context-ID
int cid = [NSApp contextID];
// Get the coordinates of the window
CGRect cgrect;
CGSGetWindowBounds(cid, wid, &cgrect);
// Transform CGRect to NSRect
NSRect nsrect;
nsrect.origin.x = cgrect.origin.x;
nsrect.origin.y = cgrect.origin.y;
nsrect.size.width = cgrect.size.width;
nsrect.size.height = cgrect.size.height;
// Create an NSImage
NSImage *img = [[NSImage alloc] initWithSize:nsrect.size];
// Write to the graphical context of the image
[img lockFocus];
// Get the grafport for the image
void *grafport = [[NSGraphicsContext currentContext] graphicsPort];
// Copy the contents of the window to the graphic context
cgrect.origin = CGPointZero;
CGContextCopyWindowCaptureContentsToRect(grafport, cgrect, cid,
wid, 0);
// Release the graphic context
[img unlockFocus];
// End of procedure: return the image
return [img autorelease];
}
Note that this invokes a couple of private functions:
OSStatus CGSGetWindowBounds(int cid, int wid, CGRect *ret);
void CGContextCopyWindowCaptureContentsToRect(void *grafport, CGRect
rect,
int cid, int wid, int zero);
No, I don't know what the last parameter is for. The only program I
know of
that uses CGCWCCTR - screencapture - always passes a constant zero
for the
last argument.
There's also another useful function that gets invoked in the
screencapture
tool:
OSStatus CGSFindWindowByGeometry(int cid, int zero, int one, int
zero_again,
CGPoint *screen_point, CGPoint *window_coords_out,
int *wid_out, int *cid_out);
This'll take a point in screen coordinates, specified by
screen_point, and
return the window ID of the frontmost window at that point (in
wid_out), the
WindowServer connection ID of that application (in cid_out), and the
transformed coordinates of that point within the window (in
window_coords_out).
There's actually no public *or* private API for the "click to select
a window"
interface that you get in screencapture; the tool just creates
translucent
overlay windows itself.
(Google actually isn't aware of any prior documentation for this
function.)
Oh, and remember that these are highly private interfaces. They will
probably
break on OS updates, particularly big ones. Don't complain to Apple
when they
do.
DATE : Thu Jul 20 04:08:35 2006
On 19 Jul 06, at 14:31, Eric Summers wrote:
> I'm trying to figure out how programs like Apple's Grab screen capture
> application get an image of other application windows. I thought
> of using
> an AppleEvent to get the bounds of the windows then capturing the
> data using
> a big transparent window, but that wouldn't work if the window is
> hidden.
> Grab will get the image data even if the window is hidden. Anyone
> know how
> the Grab application works?
Yes!
http://www.objective-cocoa.org/forum/index.php?topic=1556.msg15898
The post is in French; here's a copy of the code and a translation of
the
comments, for the list archive and the non-Francophones in the crowd:
NSImage *GrabWindow(int wid)
{
// Get a context-ID
int cid = [NSApp contextID];
// Get the coordinates of the window
CGRect cgrect;
CGSGetWindowBounds(cid, wid, &cgrect);
// Transform CGRect to NSRect
NSRect nsrect;
nsrect.origin.x = cgrect.origin.x;
nsrect.origin.y = cgrect.origin.y;
nsrect.size.width = cgrect.size.width;
nsrect.size.height = cgrect.size.height;
// Create an NSImage
NSImage *img = [[NSImage alloc] initWithSize:nsrect.size];
// Write to the graphical context of the image
[img lockFocus];
// Get the grafport for the image
void *grafport = [[NSGraphicsContext currentContext] graphicsPort];
// Copy the contents of the window to the graphic context
cgrect.origin = CGPointZero;
CGContextCopyWindowCaptureContentsToRect(grafport, cgrect, cid,
wid, 0);
// Release the graphic context
[img unlockFocus];
// End of procedure: return the image
return [img autorelease];
}
Note that this invokes a couple of private functions:
OSStatus CGSGetWindowBounds(int cid, int wid, CGRect *ret);
void CGContextCopyWindowCaptureContentsToRect(void *grafport, CGRect
rect,
int cid, int wid, int zero);
No, I don't know what the last parameter is for. The only program I
know of
that uses CGCWCCTR - screencapture - always passes a constant zero
for the
last argument.
There's also another useful function that gets invoked in the
screencapture
tool:
OSStatus CGSFindWindowByGeometry(int cid, int zero, int one, int
zero_again,
CGPoint *screen_point, CGPoint *window_coords_out,
int *wid_out, int *cid_out);
This'll take a point in screen coordinates, specified by
screen_point, and
return the window ID of the frontmost window at that point (in
wid_out), the
WindowServer connection ID of that application (in cid_out), and the
transformed coordinates of that point within the window (in
window_coords_out).
There's actually no public *or* private API for the "click to select
a window"
interface that you get in screencapture; the tool just creates
translucent
overlay windows itself.
(Google actually isn't aware of any prior documentation for this
function.)
Oh, and remember that these are highly private interfaces. They will
probably
break on OS updates, particularly big ones. Don't complain to Apple
when they
do.
| Related mails | Author | Date |
|---|---|---|
| Eric Summers | Jul 19, 23:31 | |
| Ryan Britton | Jul 20, 02:14 | |
| Eric Summers | Jul 20, 02:25 | |
| Ryan Britton | Jul 20, 02:30 | |
| Eric Summers | Jul 20, 03:57 | |
| Andrew Farmer | Jul 20, 04:08 | |
| John C. Randolph | Jul 20, 10:44 |






Cocoa mail archive

