Invalidate

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
研修生

Invalidate

#1

投稿記事 by 研修生 » 16年前

MFCのVC++6.0で開発しています。
ダイアログ内をリサイズしてコントロールなど再配置するというプログラムを作っています。
コントロールを移動させInvalidateで再描画する。

普段ならこれでいいのですがダイアログ内の一部コントロールにおいて再描画したくないものもあるので
全体を再描画するのはまずいです。部分的に排除した画面全体を再描画する方法か
1つのコントロールだけにおいて再描画する方法を教えて下さい。

バグ

Re:Invalidate

#2

投稿記事 by バグ » 16年前

逆に質問で申し訳ないのですが、やりたい事は『再描画したくない』のですか?『表示したくない』のですか?
質問を読んでも、いまいち、やりたい事が伝わってこないものでして…ピンとこないんですよね。

研修生

Re:Invalidate

#3

投稿記事 by 研修生 » 16年前

ダイアログ上にリストビュー1個とボタン2個があってサイズに合わせてコントロール配置するのですが
画面全体を再描画してしまうとリストビューのところがちかちかするんですよね。
必要なのはボタン2個の再描画なんです。ダイアログ内のリストビュー以外の箇所の再描画か
もしくはボタンの移動した箇所の再描画がしたいです。

質問の答えとしてはリストビューの所の再描画をしたくない でしょうか

バグ

Re:Invalidate

#4

投稿記事 by バグ » 16年前

そういうことでしたか。
それでしたら、InvalidateRect関数を使って、再描画したいエリアだけを指定して再描画してやればいいと思います。

研修生

Re:Invalidate

#5

投稿記事 by 研修生 » 16年前

それもやったんですが私の考え方がおかしいのかもしれません。例えばOKボタンのメンバ変数をm_OKとします。
OnSize関数内で
SetWindowPosで移動させ
CRect rect;
m_OK.GetClientRect(&rect);//領域確保
InvalidateRect(&rect, TRUE);

としても全く変化がなくリサイズするとコマ送りようにOKボタンの残像が・・
どこがおかしいのでしょうか

バグ

Re:Invalidate

#6

投稿記事 by バグ » 16年前

それでは…

CRect rect;
m_OK.GetClientRect(&rect);

/* この位置でrectの中身を書き換えて座標を移動させる*/

m_OK.MoveWindow(&rect, TRUE);


これではどうでしょうか?
CButtonクラスのMoveWindow関数を使用して移動させ、第2引数をTRUEにする事で、m_OKを再描画させています。

研修生

Re:Invalidate

#7

投稿記事 by 研修生 » 16年前

書き忘れてしまいました・・
MoveWindowは使わないように言われています。
MoveWindowでのやり方はできているんですが用意している関数の方を使うよういわれています

バグ

Re:Invalidate

#8

投稿記事 by バグ » 16年前

あ、それから追記ですが…

残像が残るのは移動させた後の領域を再描画しているからでしょう。
「移動させる前」と「移動させた後」の領域で重なっていない部分が再描画されずに残っているのが原因です。
ですから、研修生さんの方法でやりたいのならば、「移動させる前」と「移動させた後」の両方の領域を再描画させる必要があります。


>>m_OK.GetClientRect(&rect);//領域確保
>>InvalidateRect(&rect, TRUE);

それから、この書き方では、m_OKのクライアント領域を取得しているのに、そのまま親オブジェクト(今回の場合はダイアログクラスでしょうか?)のInvalidateRect関数の引数へ使用しています。これはマズイのではないでしょうか?

この方法でやりたいのならば…


CRect rect;
m_OK.GetClientRect(&rect); // OKボタンのクライアント座標を取得
m_OK.ClientToScreen(&rect); // クライアント座標をスクリーン座標に変換
this->ScreenToClient(&rect); // OKボタンのスクリーン座標をダイアログのクライアント座標へ変換
this->InvalidateRect(&rect); // 指定領域を再描画


こんな感じでしょうか?

バグ

Re:Invalidate

#9

投稿記事 by バグ » 16年前

>>MoveWindowでのやり方はできているんですが用意している関数の方を使うよういわれています

用意している関数というのは、何のことでしょうか?

研修生

Re:Invalidate

#10

投稿記事 by 研修生 » 16年前

社員みんなで1つの製品を作ってますがその中で社員が使いやすいようにと独自に用意した
関数です。その関数内にSetWindowPosがありました。

バグ

Re:Invalidate

#11

投稿記事 by バグ » 16年前

これまでの話を総括すると、その関数は単純に座標を移動させるだけで再描画はしてくれないという解釈でよろしいですか?

バグ

Re:Invalidate

#12

投稿記事 by バグ » 16年前

MoveWindowが使えれば楽なんですが、事情があるなら仕方ないですね。
ちょっと、汚いソースになってしまいましたが…こんな感じかな?
同じ様な処理をいている個所を関数化すればスッキリするかもしれませんね。

// 移動前の座標を保持する
CRect rect1;
m_OK.GetWindowRect(&rect1); // OKボタンのスクリーン座標を取得
this->ScreenToClient(&rect1); // OKボタンのスクリーン座標をダイアログのクライアント座標へ変換

// 移動後の座標を保持する
CRect rect2;

/* ここで移動処理を行う */

m_OK.GetWindowRect(&rect2); // OKボタンのスクリーン座標を取得
this->ScreenToClient(&rect2); // OKボタンのスクリーン座標をダイアログのクライアント座標へ変換

// 再描画を行う
this->InvalidateRect(&rect1); // 移動前の領域を再描画する
this->InvalidateRect(&rect2); // 移動後の領域を再描画する

研修生

Re:Invalidate

#13

投稿記事 by 研修生 » 16年前

なるほど、原因はわかりました。まだ曖昧な理解ですがここからは自分で考える所だと思いますので
頑張ってみます。ありがとうございました。

閉鎖

“C言語何でも質問掲示板” へ戻る