ab.com コミュニティ

ActiveBasicを通したコミュニケーション
現在時刻 - 2024年4月28日(日) 07:32

全ての表示時間は UTC+09:00 です




新しいトピックを投稿する  トピックへ返信する  [ 5 件の記事 ] 
作成者 メッセージ
投稿記事Posted: 2005年12月24日(土) 07:56 
オフライン

登録日時: 2005年7月19日(火) 07:02
記事: 183
お住まい: 宮城県
いつもお世話になっております。連続投稿、失礼します。
最近BMPの扱い方を覚えてきたので、仮想画面作りに挑戦してます。
これを覚えれば再描画処理が楽になるはず!。
が、やっぱりGDIまわりは難しいです・・・。


さて。
メモリデバイスコンテキスト(hMemDC)と、それに付随するビットマップ(hBmp)を
グローバルで作っておいて、TextOut()、LineTo()などで文字/模様を描画するたびに
デバイスコンテキストをメモリデバイスコンテキストにコピーし、
WM_PAINTではひたすらメモリデバイスコンテキストから
デバイスコンテキストに画像貼り付けをするのみ、
とすれば再描画を気にせずに済むかと思ったのですが・・・上手くいかないです。

以下、ソースです。
ボタンが押されると「hoge」と文字を書き出します。
無効リージョンが発生したときに、それを再描画したいのですが・・・。
コード:
Dim hMemDC As DWord
Dim hBmp As DWord


Sub MainWnd_Create(ByRef CreateStruct As CREATESTRUCT)
	'メモリデバイスコンテキストのテスト
	Dim hDC As DWord
	Dim lpRect As RECT
	hDC = GetDC( hMainWnd )
	hMemDC = CreateCompatibleDC( hDC )
	GetClientRect( hMainWnd, lpRect )
	hBmp = CreateCompatibleBitmap( hDC, lpRect.right, lpRect.bottom )
	SelectObject( hMemDC, hBmp )
	BitBlt( hMemDC, 0, 0, lpRect.right, lpRect.bottom, hDC, lpRect.right, lpRect.bottom, SRCCOPY ) 
	ReleaseDC( hMainWnd, hDC )
End Sub

Sub MainWnd_Destroy()
	'メモリデバイスコンテキストの破棄
	DeleteDC( hMemDC )
	DeleteObject( hBmp )

	TestWnd_DestroyObjects()
	PostQuitMessage(0)
End Sub

Sub MainWnd_CommandButton2_Click()
	Dim hDC As DWord
	Dim lpRect As RECT
	Dim strBuf As String

	'文字を書き出す。
	strBuf = "hoge"
	hDC = GetDC( hMainWnd )
	TextOut( hDC, 32, 32, strBuf, Len(strBuf) )

	'BMPへコピー→メモリデバイスコンテキストへ選択。
	GetClientRect( hMainWnd, lpRect )
	hBmp = CreateCompatibleBitmap( hDC, lpRect.right, lpRect.bottom )
	DeleteObject( SelectObject( hMemDC, hBmp ) )
	BitBlt( hMemDC, 0, 0, lpRect.right, lpRect.bottom, hDC, lpRect.right, lpRect.bottom, SRCCOPY )'意味無いのかな?
	ReleaseDC( hMainWnd, hDC )
End Sub

Sub MainWnd_Paint(hDC As DWord)
	Dim lpPaint As PAINTSTRUCT
	Dim lpRect As RECT

	GetClientRect( hMainWnd, lpRect )

	hDC = BeginPaint( hMainWnd, lpPaint )
		'メモリデバイス~から貼り付ける。
		BitBlt( hDC, 0, 0, lpRect.right, lpRect.bottom, hMemDC, lpRect.right, lpRect.bottom, SRCCOPY ) 
	EndPaint( hMainWnd, lpPaint )
End Sub
【質問内容のまとめ】
1) 方向性はこれであっているのか? あっているならばどこが悪いのか。
2) それとも根本的にデバイスコンテキストの理解が間違っているのか。
以上です。
よろしくお願いします。


通報する
ページトップ
 記事の件名:
投稿記事Posted: 2005年12月24日(土) 10:36 
オフライン

登録日時: 2005年8月23日(火) 00:15
記事: 161
お住まい: 沖縄県
メモリーを使用する方法は、誰もが最初に思いつく方法ですよね!
今回のロジックは検証していませんが・・・BitBltの使い方に問題があるようです。
引用:
BitBlt( hMemDC, lpRect.left, lpRect.top, lpRect.right - lpRect.left, lpRect.bottom - lpRect.top, hDC, lpRect.right, lpRect.bottom, SRCCOPY )
最初に対象となる、ウィンドウと同じサイズのビットマップ(縦・横・色)を作成し、変化のあった部分のみデータを更新&再転送することで実現します。
コード:
Declare Function BitBlt Lib "gdi32" _
   (hdcDest As HDC, _   'コピー先長方形領域の左上隅の X 座標
    nXDest As Long, _   'コピー先長方形領域の左上隅の Y 座標
    nYDest As Long, _   'コピー先長方形領域の幅
    nWidth As Long, _   'コピー先長方形領域の高さ
    nHeight As Long, _
    hdcSrc As HDC, _
    nXSrc As Long, _    'コピー元長方形領域の左上隅の X 座標
    nYSrc As Long, _    'コピー元長方形領域の左上隅の Y 座標
    dwRop As DWord) As Long


通報する
ページトップ
投稿記事Posted: 2005年12月24日(土) 11:28 
オフライン

登録日時: 2005年5月31日(火) 17:59
記事: 899
お住まい: 東京都
やろうとしていることはなんら間違っていません。この方向で平気です。
コード:
Dim hMemDC As HDC
Dim hBmp As HBITMAP
Dim rcBmpSize As RECT
Declare Function SetRect Lib "User32" (
	ByRef rc As RECT, xLeft As Long, yTop As Long, xRight As Long, yBottom As Long) As Long
まずグローバル変数としてrcBmpSizeを増やしましたがこれは毎回GetClientRectを呼ばなくて済むようにするためです。
SetRect関数は後で使います。
コード:
Sub MainWnd_Create(ByRef cs As CREATESTRUCT)
	'メモリデバイスコンテキストのテスト
	Dim hDC As HDC
	hDC = GetDC(hMainWnd)
	hMemDC = CreateCompatibleDC(hDC)
	SetRect(rcBmpSize, 0, 0, cs.cx, cs.cy)
	With rcBmpSize
		hBmp = CreateCompatibleBitmap(hDC, .right, .bottom)
		SelectObject(hMemDC, hBmp)
		'BitBlt(hMemDC, 0, 0, .right, .bottom, hDC, .right, .bottom, SRCCOPY)
		FillRect(hMemDC, rcBmpSize, GetClassLong(hMainWnd, GCL_HBRBACKGROUND) As HBRUSH)
	End With
	ReleaseDC(hMainWnd, hDC)
End Sub
やっていることは変りません。
GetClientRectを呼ばずともCREATERECT型の引数でウィンドウの大きさは知ることができます。
SetRectは名前の通りRECTの各メンバを設定する関数です。
BitBltでhDCからhMemDCへコピーするとおもしろいことになります。
なぜならまだウィンドウに対してPaintイベントが発生していないので,
ウィンドウにはまだ何も書き込まれていないからです。
試しにFillRectの行をコメントアウトしてBitBltの行のコメントアウトを外して実行してみるとわかります。
そこでウィンドウの背景に使われるブラシハンドルをGetClassLongで取得して,
FillRectで直接hMemDCに書き込んでいます。
コード:
Sub MainWnd_Paint(hdc As HDC)
	BitBlt(hdc, 0, 0, rcBmpSize.right, rcBmpSize.bottom, hMemDC, 0, 0, SRCCOPY)
End Sub
Paintイベントの引数のHDCはBeginPaintを呼んで得たものなのでそのまま使えます。
なので自分でBeginPaintを呼んでも失敗します。
さらにhMemDCの後の2つの引数は左上の座標なので今回は0にする必要があります。
コード:
Sub MainWnd_CommandButton1_Click()
	Dim strBuf As String
	'文字を書き出す。
	strBuf = "hoge"
	TextOut(hMemDC, 32, 32, StrPtr(strBuf), Len(strBuf))
	InvalidateRect(hMainWnd, ByVal 0, TRUE)
End Sub
単純化して新しくビットマップを作るのをやめています。
さらにhMemDCもデバイスコンテキストへのハンドルですからTextOutに渡して使えます。


通報する
ページトップ
投稿記事Posted: 2005年12月24日(土) 17:43 
オフライン

登録日時: 2005年7月19日(火) 07:02
記事: 183
お住まい: 宮城県
≫イグトランスさん
ありがとうございます。

なるほど。
引用:
> Paintイベントの引数のHDCはBeginPaintを呼んで得たものなのでそのまま使えます。
> なので自分でBeginPaintを呼んでも失敗します。
> さらにhMemDCの後の2つの引数は左上の座標なので今回は0にする必要があります。
動作不良の原因はそこだったんですね。
RADでWM_PAINTを扱うのは初めてだったので、なんの疑問も無くBeginPaint()を呼んでました。
そのうえ何故かBeginPaint()自体は成功してる(返り値がNULLじゃなかった)んですよね~。^^;
ついでにその後のBitBlt()も関数は成功している・・・いったいどこに描き込んでいるのやら^^;
(ABの環境はVer.3.13)
このエラーは指摘されなかったらまず気づけなかったと思います。
助かりました。
ちなみに後ろ2つの引数はボケてました(汗)。当然0,0ですよね。
引用:
> BitBltでhDCからhMemDCへコピーするとおもしろいことになります。
たしかに面白いことになりました(笑)。
カメレオンか己はw

すばやい回答をありがとうございました。
無事に動作しました。




≫マティさん
一応、GetClientRect()ではleftメンバとtopメンバにゼロが代入されるので、問題ないはずです。
でもBitBlt()の引数自体が間違っていたわけですが(上記参照)。
引用:
メモリーを使用する方法は、誰もが最初に思いつく方法ですよね!
そうですよね♪なので覚えようと思いました。
でも「誰でも思いつく」故なのか過去ログにもさっぱり無いんですよね、仮想画面単体を扱った雛形が^^;


通報する
ページトップ
 記事の件名:
投稿記事Posted: 2005年12月24日(土) 19:57 
オフライン

登録日時: 2005年8月23日(火) 00:15
記事: 161
お住まい: 沖縄県
引用:
一応、GetClientRect()ではleftメンバとtopメンバにゼロが代入されるので、問題ないはずです。
でもBitBlt()の引数自体が間違っていたわけですが(上記参照)。
再描画処理をビットマップからの転送で行うようにプログラムを作成する時の注意事項に、画面全体の再描画以外(右端等の再描画等)を行うと描画が不正になる事があります。
(クリッピング等の処理を考慮する必要があるってことです。)

※上記は念のために投稿しました。

PS.
自分の初めて作成したウィンドウプログラムも同様に処理を行いました。
(直接ビットマップに描画したデータと、画面に描画したデータ同士をXORで画面に転送するとディスプレイドライバーの描画精度が分かります。これはこれで、面白いですよ)


通報する
ページトップ
期間内表示:  ソート  
新しいトピックを投稿する  トピックへ返信する  [ 5 件の記事 ] 

全ての表示時間は UTC+09:00 です


オンラインデータ

このフォーラムを閲覧中のユーザー: なし & ゲスト[10人]


トピック投稿:  可
返信投稿:  可
記事編集: 不可
記事削除: 不可
ファイル添付: 不可

検索:
ページ移動:  
Powered by phpBB® Forum Software © phpBB Limited
Japanese translation principally by ocean