
ボールが右下に動いていくだけのプログラムです。
はじめはInvalidateRect(hWnd,NULL,.TRUE)を使っていたのですが画面がちらつくので
InvalidateRgnを使ってみました。そこで円の部分をリージョンで指定して背面消去したら
図1のようになってしまったので、
ペンの太さを考慮してなかったのが問題だと思って円の周辺に余裕を持ってリージョンを
設定して以下のようなプログラムになったのですが(スレッドの中身です)
図2のように進行方向の部分が欠けてしまいます。
その後余白の3の部分を7以上にしたら元の円のまま動きました。
ペンの太さは3なので十分だと思ったのですが6以下でなぜ欠けてしまうんでしょうか?
while(1){
hRgn = CreateEllipticRgn(x - hankei - 3, y - hankei - 3, x + hankei + 3, y + hankei + 3);
x = x + 4;
y = y + 2;
InvalidateRgn(hWnd,hRgn,TRUE);
Sleep(100);
}

No.1ベストアンサー
- 回答日時:
InvalidateRgnで無効にした領域だけを再描画するため 右下が欠けたようになるのだと思います
CreateEllipticRgnでリュージョンを生成するのを 描画側でやります
描画には FillRgnとFrameRgnで行い
描画位置更新イベント側では GetRgnBoxでリュージョンの矩形範囲を取得し
進行方向へ膨らませて InvalidateRectを実行して見ましょう
// 描画側
hRgn = CreateEllipticRgn(x - hankei, y - hankei, x + hankei, y + hankei);
HBRUSH hBrFrame = CreateSolidBrush(RGB(255,0,0));
// hBr: 塗りつぶしようのブラシは生成済みと仮定
FillRgn(hWnd, hRgn, hBr);
FrameRgn(hWnd, hRgn, hBrFrame, 3, 3);
DeleteObject(hBrFrame);
// 消去側
RECT r = {0};
if (hRgn) {
// 矩形範囲を取得
GetRgnBox(hRgn, &r);
// 再描画の増分を考慮
r.right += 4;
r.bottom += 2;
/*
左上に動かすなら left, topを更新
右上なら right,top
左下なら left,bottom
*/
InvalidateRect(hWnd, &r, TRUE);
// 使用済みなので リュージョンを破棄
if (DeleteObject(hRgn)) {
hRgn = NULL;
}
}
x += 4;
y += 2;
この回答への補足
回答ありがとうございます。
InvalidateRgnを使ったとき背面消去だけリージョンの範囲で行われて
描画は全範囲で行われるものと勘違いしていました。
消去も描画もリージョンの部分のみ行われていたから進行方向のはみだした
部分について描画されなかったんですね。
描画はペンとブラシでEllipse()を使っていたんですが、
FillRgnとFrameRgnでやるんですね。
これを使えばペンの太さとか気にせずに
描画した部分に対してぴったり無効化の範囲を指定できるって事でしょうか?
また更新部分のリージョンの指定で以下のようなものを考えてみたのですが
矩形の方が処理が早いとか何かメリットがあるんでしょうか?
それとも今回の質問の問題箇所がそれで解決されるので簡単にして書いただけですかね?
またいくつか質問になってしまいましたが、よろしくお願い致します。
hRgn1 = CreateEllipticRgn(x - hankei, y - hankei, x + hankei, y + hankei);
ボールの位置を変化させる(x,yを変化させる)
hRgn2 = CreateEllipticRgn(x - hankei, y - hankei, x + hankei, y + hankei);
CombineRgn(hRgn1, hRgn1, hRgn2, RGN_OR);
InvalidateRgn(hWnd, hRgn1, TRUE);
Sleep(50);
No.2
- 回答日時:
Ellipseでの描画は 指定された矩形範囲に内接する楕円を描画するのですが
内接するのはペンの中心です
// Pen,Brushは選択済みとします
Ellipse(hdc, 50, 50, 100, 100);
hRgn = CreateEllipseRgn(50,50,100,100);
InvalidateRgn(hWnd, hRgn, TRUE);
といったコード実行すると
Ellipseで描画した縁が消去されないと思います
FillRgn/FrameRgnを使えば 生成したリュージョン内での描画になるので上記のような問題は解決されるでしょう
再描画に関してですが WM_PAINTイベントの実装により変わってきますよ
BeginPaintを呼び出した際に 返される PAINTSTRUCT構造体psのrcPaintが無効にされた領域です
rcPaintだけを BitBltなどで転送する実装だと GetRgnBoxで取得できる領域と等価だとおもいます
無関係にクライアント領域を書き直す実装だと 無駄が多いようにおもいます
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
関連するカテゴリからQ&Aを探す
おすすめ情報
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
Minecraft 統合版(PC)の描画距...
-
VB.netでのライン描画方法がわ...
-
c++ ダブルバッファリング、以...
-
自分のクラスにイベントを入れ...
-
グラフの交点の求め方(Excel)
-
「アイテムは収集されました」...
-
エクセルで作った新しいウイン...
-
勝手にウィンドウが開いて止ま...
-
エクセルのコントロールツール...
-
メッセージボックスを大きくす...
-
コンテキスト依存とは?
-
D3DXCreateFontとID3DXFont::Dr...
-
他のウィンドウのボタンを自動...
-
閉図形の座標の配列が右回りか...
-
空のリストビューで1行おきに...
-
マインクラフト(pc版)で座標...
-
【VB2008】 マウス操作の一時的...
-
スピンボタンを右クリックして...
-
エクセルである行が急に消えて...
-
コントロールの書式設定で、“コ...
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
Minecraft 統合版(PC)の描画距...
-
[VB.net] DataGridViewの列ヘッ...
-
word
-
TextBoxに文字を書いても表示さ...
-
panelのスクロール表示について
-
google Colabでmatplotlibの描...
-
MFCでOnPaintのタイミング
-
CStaticコントロールの静的イメ...
-
VBAにGDI+を参照させる方法
-
Form1 Load で実行されない。
-
InvalidateRectの使い方について
-
CScrollViewの使用方法について
-
GDI+について
-
VC++プログラムをつかったBMP画...
-
ウインドウサイズを変更しても...
-
VB6,リストボックスの特定行の...
-
タブをオーナードローすると、...
-
ビットマップを表示させる(MFC)
-
UpdateData( FALSE); による文...
-
C++にて、塗りつぶされた円を描...
おすすめ情報