他プロセスのウィンドウの表示内容を取得したい

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
アバター
Cir
記事: 32
登録日時: 9年前
住所: 近畿地方

他プロセスのウィンドウの表示内容を取得したい

#1

投稿記事 by Cir » 9年前

いつもお世話になっております。

早速質問なのですが、件名のとおり、他プロセスのウィンドウの表示内容(クライアント領域、非クライアント領域の両方)を一定間隔(500msくらい)で取得し、自ウィンドウのクライアント領域に描画したいのです。

図で表すと
fig1.JPG
fig1.JPG (54.17 KiB) 閲覧数: 3142 回
このような感じです(AAA.exeのウィンドウにマインスイーパのウィンドウが描画されている)。

はじめは

コード:

HDC hdc_Target;
HWND hTargetWnd;

hdc_Target = GetWindowDC(hTargetWnd);

/*
BitBlt使ったりして自ウィンドウに他プロセスのウィンドウを描画
*/

ReleaseDC(hTargetWnd, hdc_Target);
対象のウィンドウ全体のデバイスコンテキストを取得し、BitBltを使用して自ウィンドウに描画していたのですが、この方法だと他のウィンドウが対象のウィンドウに覆いかぶさってしまうと、
fig2.JPG
fig2.JPG (52.2 KiB) 閲覧数: 3142 回
のように、覆いかぶさったウィンドウごと取得してしまうのです。また対象ウィンドウが最小化されていたり、画面外にはみ出していたりすると、その部分が黒くなっています。

PrintWindow関数を使ってもみたのですが、長時間にわたって連続で呼び出していると対象のウィンドウの表示内容が崩れしまい、この方法は使えませんでした。

何か良い方法などありますでしょうか?(説明べたで申し訳ありません…)

--------開発環境--------
・WindowsXP SP3
・VC++2008
・Win32APIを使用

アバター
Ciel
記事: 252
登録日時: 9年前

Re: 他プロセスのウィンドウの表示内容を取得したい

#2

投稿記事 by Ciel » 9年前

画面全体のデバイスコンテキストを取得していませんか?

対象のウィンドウのデバイスコンテキストを取得して描画したら、
ウィンドウが重なっていても、問題なく描画できましたよ。

下のコードは対象の座標部分(0,0)のウィンドウハンドルを取得して、
描画するものですけど、これでウィンドウが重なってもいけました。


コード:

static HDC hdc,targethdc;
	
PAINTSTRUCT ps;
	
POINT point={0,0};

case WM_PAINT:

			hdc=BeginPaint(hwnd,&ps);

			targethdc=GetWindowDC(WindowFromPoint(point));

			BitBlt(hdc,0,0,WIDTH,HEIGHT,targethdc,0,0,SRCCOPY);

			EndPaint(hwnd,&ps);
			return 0;
oui C'est la Vie♪

アバター
Ciel
記事: 252
登録日時: 9年前

Re: 他プロセスのウィンドウの表示内容を取得したい

#3

投稿記事 by Ciel » 9年前

画像はこれ。
copy.jpg
ウィンドウを3重に重ねてもいけました。
oui C'est la Vie♪

アバター
Cir
記事: 32
登録日時: 9年前
住所: 近畿地方

Re: 他プロセスのウィンドウの表示内容を取得したい

#4

投稿記事 by Cir » 9年前

早速のご回答ありがとうございます!

せっかくコードを提示していただいたのですが、私の環境ではウィンドウが覆いかぶさった状態のものが表示されてしまいました…。

このような感じです。
fig2_1.JPG
fig2_1.JPG (23.47 KiB) 閲覧数: 3091 回
スクリーン座標(0, 0)にあるVisual C++のデバイスコンテキストを500ms間隔で取得し、AAA.exe(自プロセス)のクライアントエリアに描画しているのですが、やはり覆いかぶさったウィンドウ(この画像の場合ではAAA.exeのウィンドウ)ごと表示されてしまいます。

コードは次のようにしました。

コード:

#define TIMER_ID		(100)

LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp)
{
	static HDC hdc, hdc_target;
	PAINTSTRUCT ps;
	POINT point = {0, 0};
	static int width, height;
 
	switch(msg)
	{
	//ウィンドウが作られた
	case WM_CREATE:
		//500ms毎にデバイスコンテキストを取得するためにタイマーを設定しておく
		SetTimer(hWnd, TIMER_ID, 500, NULL);
		
		break;

	//指定時間になった
	case WM_TIMER:
		
		InvalidateRect(hWnd, NULL, TRUE);
		
		break;

	//ウィンドウが壊される
	case WM_DESTROY:
		
		PostQuitMessage(0);
		
		break;

	//ウィンドウの大きさが変更された
	case WM_SIZE:
		//ウィンドウの大きさを取得しておく
		width = LOWORD(lp);
		height = HIWORD(lp);
		
		break;

	//描画
	case WM_PAINT:
		hdc = BeginPaint(hWnd, &ps);

		hdc_target = GetWindowDC(WindowFromPoint(point));
	 
		BitBlt(hdc, 0, 0, width, height, hdc_target, 0, 0, SRCCOPY);
	 
	//********(2011/2/7/18:00編集)ReleaseDCを忘れていたので追加*************************

		ReleaseDC(WindowFromPoint(point), hdc_target);

	//********編集ここまで**************************************************************************
		
		EndPaint(hWnd, &ps);

		break;

	//そのほか
	default:
		
		return DefWindowProc(hWnd, msg, wp, lp);
	}

	return 0;
}

これは、環境によって得られる結果が異なるのでしょうか?
最後に編集したユーザー Cir on 2011年2月07日(月) 18:02 [ 編集 1 回目 ]

ISLe
記事: 2646
登録日時: 9年前
連絡を取る:

Re: 他プロセスのウィンドウの表示内容を取得したい

#5

投稿記事 by ISLe » 9年前

Cir さんが書きました:これは、環境によって得られる結果が異なるのでしょうか?
Windows Vista以降はメインウインドウごとに描画バッファを持つようになったことが関係してるのではないでしょうか。

(追記)
Windows Vista以降はウインドウの見えない部分も描画されて保持されています。
XP以前はウインドウの見えないところは本当に描かれていない(上書きされて失われている)ので対象のアプリに再描画してもらう以外に取得する方法はありません。

アバター
Cir
記事: 32
登録日時: 9年前
住所: 近畿地方

Re: 他プロセスのウィンドウの表示内容を取得したい

#6

投稿記事 by Cir » 9年前

ISLe さんが書きました: (追記)
Windows Vista以降はウインドウの見えない部分も描画されて保持されています。
XP以前はウインドウの見えないところは本当に描かれていない(上書きされて失われている)ので対象のアプリに再描画してもらう以外に取得する方法はありません。
なるほど、そのような事情があったのですか…。
となると、ウィンドウの描画内容を取得するのは難しそうですね。

アバター
Cir
記事: 32
登録日時: 9年前
住所: 近畿地方

Re: 他プロセスのウィンドウの表示内容を取得したい

#7

投稿記事 by Cir » 9年前

解決方法が見つかりました!

対象のウィンドウをレイヤード ウィンドウにすることによって、たとえ他のウィンドウが覆いかぶさっていても問題なくウィンドウの表示内容を取得、描画することが出来ました!

ご回答してくださった皆様、本当にありがとうございました!

アバター
Ciel
記事: 252
登録日時: 9年前

Re: 他プロセスのウィンドウの表示内容を取得したい

#8

投稿記事 by Ciel » 9年前

それは知らなかった・・・。

難しそうですね。
アクティブにして取るとかしかなさそうですね。

追記:
そんな方法があったのか。参考になりました。。
oui C'est la Vie♪

ISLe
記事: 2646
登録日時: 9年前
連絡を取る:

Re: 他プロセスのウィンドウの表示内容を取得したい

#9

投稿記事 by ISLe » 9年前

レイヤードウインドウにするとブレンド処理用にバッファが用意されるのですね。
そんな副作用があったとは。
良いことを知りました。

閉鎖

“C言語何でも質問掲示板” へ戻る