さらにしつこく複数ウィンドウのキャプチャ。
これまで複数ウィンドウのキャプチャ画像を作るのに個別のウィンドウ画像を地道に合成していた。が、そんな面倒なことをしなくとも WindowIDの配列を渡すだけで1枚の画像にまとめてくれる関数が用意されていたのに気がついた。早速試してみる。
ソース:FullScreenSample-18.zip
コードは自前合成に比べるとずいぶんと簡潔になる。ポイントだけ抜き出してみる。
CGWindowID *windowIDs = calloc([list count], sizeof(CGWindowID));
int i=0;
for (Window* w in list) {
windowIDs[i++] = [w windowID];
}
CFArrayRef windowIDsArray = CFArrayCreate(kCFAllocatorDefault, (const void**)windowIDs, [list count], NULL);
free(windowIDs);
CGImageRef cgimage = CGWindowListCreateImageFromArray(CGRectNull, windowIDsArray, kCGWindowImageDefault);
画像に含めたい WindowIDの配列をCGWindowListCreateImageFromArray( )の第二引数へ CFArrayRef 型で渡してやる。この配列にはCFNumberRef や NSNumberでラッピングせず、 CGWindowID(uint32_tで定義)のまま入れなければならないので注意が必要。上記コードは ADCのサンプルコード(SonOfGrab)より一部拝借した。ついでにコメントも転記しておく。
// CGWindowListCreateImageFromArray expect a CFArray of *CGWindowID*, not CGWindowID wrapped in a CF/NSNumber
// Hence we typecast our array above (to avoid the compiler warning) and use NULL CFArray callbacks
// (because CGWindowID isn't a CF type) to avoid retain/release.
なお引き渡した WindowID順にウィンドウが並べられて画像が作成されるので、この順序を並び替えると画面で見えていたのとは違った任意の順序で合成画像を作ることができる。下記は画面で見えていたのとは逆順にした例。