やろうとしていることはなんら間違っていません。この方向で平気です。
コード:
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に渡して使えます。