画面サイズ変更処理
概要
今回は、前回作ったボロノイ図描画ソフトの改良
ウィンドウサイズの変更に合わせて描画領域を調整する処理を書きました
仕組み
Windowsで大量に描画するソフトを作る場合、ちらつき防止にバックバッファを使用します。
メモリ上に画面と同じサイズのキャンバスを用意して、そこに書き込み、最後にスタンプの様にベタッと貼り付けるという仕組みです。
こうすることで画面への描画回数が1回になり、画面のちらつきが無くなります。
また描画処理と画面更新処理が切り分けられるので、大きな負荷軽減にもなります。
今回はウィンドウサイズが変更されたときに、バックバッファの大きさを変更する処理を書いてみました。
デバイスコンテキストの概念
慣れないうちはデバイスコンテキストの概念がなかなか理解しにくいんですけど
簡単に説明するならデバイスコンテキスト=画家です
画家に”線を引け”と命令したら、”自分の持っているペン”で”自分が持っているキャンバス”に線を引きます
画面更新時に送られてくるデバイスコンテキストは、ウィンドウ画面をキャンバスとして持ってる特別な画家なのですね
バックバッファを作る場合は、画家とキャンバスの両方を作る必要があります
画面と互換性のあるデバイスコンテキストとビットマップを作るAPIがあるので、それを呼び出します。
CreateCompatibleDC
CreateCompatibleBitmap
の2つ
bool CChildView::InitMemoryDC()
{
RECT rc;
CDC* pDC = GetDC(); //ウィンドウのデバイスコンテキストを取得
// ウィンドウサイズを取得
GetWindowRect(&rc);
m_width = rc.right - rc.left + 1;
m_height = rc.bottom - rc.top + 1;
m_dc.CreateCompatibleDC(pDC);
m_Bitmap.CreateCompatibleBitmap(pDC, m_width, m_height);
m_dc.SelectObject(&m_Bitmap);
return true;
}
ChildViewクラスにキャンバス用の変数として
CDC m_dc;
CBitmap m_Bitmap;
を持たせてあります
SelectObjectが画家に画材を持たせるAPIになります。
今回はビットマップ(キャンバス)を持たせていますが
同じAPIでペンやブラシなども持たせることができます
サイズ変更のタイミング
ウィンドウサイズが変わったときにWM_SIZEメッセージが送られてきます
MFCの場合、OnSizeイベントハンドラで処理を実装します。
(クラスウィザード→WM_SIZEをダブルクリック)
しかしWM_SIZEメッセージはウィンドウサイズ変更中に何度も呼び出されるので
その度にビットマップを作り直すのは大きな負荷になります
そこでWM_SIZEメッセージが呼び出される度に、更新タイマーを500msにセットして、タイマーが0になったらビットマップを作り直すという工夫をしました。
ウィンドウサイズ変更中はタイマーが500msに固定され、マウスを離すとカウントダウンが始まり、カウントがゼロになったらメモリDCとBitmapが作り直されるという感じ
void CChildView::OnSize(UINT nType, int cx, int cy)
{
CWnd::OnSize(nType, cx, cy);
if (nType == SIZE_RESTORED) {
m_nResizeTimer = 500;
}
}
void CChildView::OnTimer(UINT_PTR nIDEvent)
{
Invalidate(0);
if (m_nResizeTimer > 0) {
m_nResizeTimer -= 100;
if (m_nResizeTimer <= 100) {
m_Bitmap.DeleteObject();
m_dc.DeleteDC();
m_bInitDC = false;
UpdateBitmap();
}
}
}
結果
ウィンドウサイズに合わせて描画領域が広がるようになりました
おわりに
プログラミング講座っぽく書いてみたけど全く需要が無いような気がしてきた
講座だったらもっといい記事がネットに広がってるし
そもそもMFC自体誰も使ってないような気がする
もっと簡単にこんな物作りました的な感じが良いかも・・・と迷走中
今回はプログラミングコードを表示するプラグインを使ってみたかったという事でノシ
最近のコメント