ページ 11

画像ファイルを描画したい

Posted: 2013年2月08日(金) 23:57
by shiro4ao
リモートにある画像をみれるフォトビューアみたいなソフトを作ろうとしています
TCPでのファイルの送信自体は流用したので上手く動いたのですが、
bmpファイルを受信側で読み込んで表示するのがうまくいきませんでした。

コード:

	// ビットマップをtemp2.bmpファイルからロード
	hBitmap = (HBITMAP)LoadImage( NULL, _T("temp2.bmp"), IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE );
	hDC = GetDC( hwnd );
	hCompatDC = CreateCompatibleDC( hDC );
	hPrevBitmap = (HBITMAP)SelectObject( hCompatDC, hBitmap );

コード:

	//WM_PAINTが来たら範囲を指定して描画してもらう	
	StretchBlt( hDC, 0,0,1280, 800, hCompatDC, 0, 0,1280,800, SRCCOPY );

上記のうち、「ビットマップをファイルからロード」の部分を受信スレッドで呼ぶと
表示できませんでした
試しに「ビットマップをファイルからロード」の部分をWM_CREATEで呼ぶと表示でき、
ウィンドウサイズを変えてもちゃんと描画できました

しかし、受信するたびにファイルを描画しないといけないのですが、
どのように変更すればいいでしょうか?

それとも根本的になにかおかしいのでしょうか?

Re: 画像ファイルを描画したい

Posted: 2013年2月09日(土) 00:57
by ISLe
スレッドとウィンドウメッセージキューは内部で結び付いているので、描画はウィンドウメッセージループのあるスレッドで行う必要があると思います。
受信スレッドからウィンドウに再描画を要求するユーザーメッセージを投げてウィンドウプロシージャで処理する形が良いのではないでしょうか。

あと、CreateCompatibleDCやSelectObjectは描画する都度行なうようにして、作りっぱなしは避けたほうが良いと思います。

Re: 画像ファイルを描画したい

Posted: 2013年2月09日(土) 15:24
by shiro4ao
ありがとうございます
データ受信スレッドからウィンドウメッセージWM_REFRESHを投げて
ウィンドウプロシージャ内でビットマップをロード、その他の準備をし
WM_PAINTが来たら描画させるようにしたら、画像が表示できました
ところが何もしていない(ウィンドウを動かさずサイズも変えない)のに
プロセッサがずーっと回り続けて居るようでした。
だいたい20%前後使用していました。

ウィンドウメッセージWM_REFRESHを投げた後、受信スレッドは終了しているので
ウィンドウプロシージャのあるメインスレッドがまわりっぱなしになるようなのですが
プロセッサが回り続けさせずに画像を表示させておく方法はありますか?

コード:

	// ビットマップをtemp2.bmpファイルからロードするウィンドウメッセージ
	case WM_REFRESH:
		{
			//  ビットマップをファイルからロードする
			hBitmap = (HBITMAP)LoadImage( NULL, _T("temp2.bmp"), IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE );
			hDC = GetDC( hwnd );
			hCompatDC = CreateCompatibleDC( hDC );
			hPrevBitmap = (HBITMAP)SelectObject( hCompatDC, hBitmap );
		}
		break;

コード:

	case WM_PAINT:
		// 描画させる
		StretchBlt( hDC, 0,0,1280, 800, hCompatDC, 0, 0,1280,800, SRCCOPY );
		break;

Re: 画像ファイルを描画したい

Posted: 2013年2月09日(土) 17:41
by ISLe
WM_PAINTメッセージでBeginPaint,EndPaintを使わないと無効領域がクリアされないので、WM_PAINTが連投されることになります。

描画にはBeginPaintが返すデバイスコンテキストを使ってください。
ルールに則れば、CreateCompatibleDC,SelectObjectしっぱなしは自ずとできないのです。

Re: 画像ファイルを描画したい

Posted: 2013年2月09日(土) 18:37
by shiro4ao

コード:

	case WM_PAINT:  // 再描画するタイミング
		hDC = BeginPaint(hWnd, &ps);
		StretchBlt( hDC, 0,0,1280, 800, hCompatDC, 0, 0,1280,800, SRCCOPY );
		EndPaint(hWnd, &ps);
		break;
BeginPaintとEndPaintのあいだに挿入するとプロセッサが落ち着きました
ありがとうございました。

一応、これで解決とさせていただきます。