none
複数のモニタディスプレイにまたがる領域の画面キャプチャを取得するには? RRS feed

  • 質問

  • 初めて投稿させて頂きます。

    今、Visual Studio 2005上でWin32APIを用いて画面キャプチャを定期的に取得するプログラムを作成しています。
    単一のモニタディスプレイからキャプチャするのであれば、BitBlt()により画像転送を行い、ウィンドウ上にStretchBlt()等を使って描画すればよいのですが、
    複数のモニタにまたがった矩形のキャプチャを手際よく取得する方法が分かりません。

    GetSystemMetrics()のパラメータにSM_XVIRTUALSCREEN, SM_YVIRTUALSCREENなどを与えてやることで、
    複数のモニタにまたがる仮想領域の始点と領域サイズを取得することはできるため、
    仮想領域上のキャプチャ領域の始点・終点を、その領域上のモニタ座標で表現すれば、モニタ単位でキャプチャできると考えたのですが、
    モニタの座標と仮想領域の座標を換算する手段が見当たらず、挫折してしまいました。

    もし首記の実装を経験された方がいらっしゃいましたら、ぜひ教えて頂けないでしょうか。

    2011年5月30日 8:48

回答

すべての返信

  • Multiple Display Monitors
    http://msdn.microsoft.com/en-us/library/dd145071(v=VS.85).aspx

    この辺使えばなんとかなるんじゃないでしょうか。

    2011年5月30日 13:13
  • 渋木様、ヒントをありがとうございます。
    ご提示頂いたサイトを追う限り、モニタ領域毎に画像転送を行うしかないのですね。

    ディスプレイモニタの個数・並び方と個々のモニタのサイズは、ユーザーさんの接続の仕方次第ゆえに、一定でないのが前提です。例えば、太字をプライマリモニタとして、

    monitor1 (1024x768) monitor2 (1024x768)
    monitor3 (1024x768) monitor4 (1024x768)

    もあり得ますし、

    monitor3 (1280x1024) monitor4 (1024x768)
    monitor1 (1024x768) monitor2(1280x1024)

    もあり得る状況です。そのために仮想空間上の任意のエリアをそのままビット転送してキャプチャ描画できないかと考えた次第です。

    理想は Cappuccino(http://tonton-soft.web.infoseek.co.jp/Software/Software.html#Cappuccino) のように、任意の矩形領域をキャプチャできるようにすることです。

    個々のモニタハンドルを考慮せずに考える手段はないのでしょうか。ご存知の方いらっしゃいましたら、ご教授頂けないでしょうか。

    2011年5月31日 0:27
  • その後調べを進めて、モニタ毎のキャプチャ領域の取得方法が分かりました。

    // 仮想空間におけるキャプチャ領域
    // (実際にはnx, ny, nWidth, nHeightにint値が入る)
    RECT rectEntireCapture = {nx, ny, nWidth, nHeight};
    
    // 仮想領域全域分取得
    HDC hdc = GetDC(NULL);
    EnumDisplayMonitors(hdc, NULL, EnumMonitorFunc, 0);
    ReleaseDC(NULL, hdc);
    
    // コールバック関数
    BOOL CALLBACK EnumMonitorFunc(HMONITOR hMonitor, HDC hdcMonitor, LPRECT lpRect, LPARAM dwData)
    {
    	// 個々のモニタ情報を取得
    	MONITORINFO mi;
    	mi.cbSize = sizeof(MONITORINFO);
    	GetMonitorInfo(hMonitor, &mi);
    
    	// キャプチャ領域を個々のモニタ毎に分割
    	RECT rectOverlap = {sizeof(RECT)};
    	if (IntersectRect(&rectOverlap, &(mi.rcMonitor), &rectEntireCapture))
    	{
    		// rectOverlapにモニタ毎のキャプチャ領域が取得される
    		・・・・・・
    	}
    	・・・・・・
    	return TRUE;
    }

    あとはモニタ毎にキャプチャしていくだけですので、スレッドとしては「解決」にしたいと思います。
    ありがとうございました。

    2011年5月31日 5:53