MFC VC++6.0 MFC XP
メインフレームからVIEWに再描画を指示したいのですが、よくわかりません。
さっき、bunさんから教えていただいたホームページをみて、実際、アクティブドキュメ
ントを介してUpdateAllViews() をつかうとできるのですが、このとき、関係のないドキ
ュメントクラスを使うのは、邪道のような気がしてしまいます。
コーディング1:うまくいきましたが・・・邪道?
void CMainFrame::OnMag2()
{
((MDIGetActive())->GetActiveDocument())->UpdateAllViews(NULL) ;
}
コーディング2:アクティブビューのInvalidate()をつかってみましたが、アクティ
ブビューは、更新されません。(たぶん、メッセージの送る場所がちがう?)
void CMainFrame::OnMag2()
{
((MDIGetActive())->GetActiveView())->Invalidate() ;
}
ドキュメントが変更されていないのに、どうして再描画が必要なんですか?
表示拡大倍率をメインフレームにくっついているダイアログバーにて、ユーザ入力して
もらって、それにしたがって、表示を変更するプログラムを作っています。
>ドキュメントが変更されていないのに、どうして再描画が必要なんですか?
ひょっとして、ダイアログバーから倍率変更のボタンが押されたとき、表示が更新される
ようにしたいとか?
>さっき、bunさんから教えていただいたホームページをみて、実際、アクティブドキュ
>ントを介してUpdateAllViews() をつかうとできるのですが、このとき、関係のない
>ドキュメントクラスを使うのは、邪道のような気がしてしまいます。
Document - Viewの関係で通すのなら、正しいのでは?
ドキュメントが変更されていないけど、倍率を変更するために表示を更新したいのです
よね。
ITOさんレスありがとうございます。
> ひょっとして、ダイアログバーから倍率変更のボタンが押されたとき、表示が更新さ
れるようにしたいとか?
そのとおりです。
> ドキュメントが変更されていないけど、倍率を変更するために表示を更新したいので
すよね。
そのとおりです。
そうですか、ドキュメントを変更しなくても、ドキュメントを通してもいいんです
か・・・
Viewを更新したいんならば、
> ((MDIGetActive())->GetActiveView())->Invalidate() ;
ではなく、
((MDIGetActive())->GetActiveView())->OnUpdate();
では?
ところで、そのダイアログバーのコマンドって、Viewクラスのメッセージで出来ない
んですか?メニューコマンドみたいに。
そうすればフレームからViewを検索するのはフレームワークがやってくれるから何も
考えることないのに。
ダイアログバーは詳しくないので、的外れなことを言っているかも知れません。
maruさん、レスありがとうございます。
ダイアログバーは、メニューと違いいろいろと制約があるみたいです。
実際、フレームでダイアログバーをクリエイトして、
ダイアログバーをVIEWに結び付けて、ダイアログバーに貼り付けている、ラジオボ
タン用ハンドルまでは、作れたんですが、実際、実行してみると、そのハンドルがよば
れませんでした。とりあえず、考え付いたのがいまの方法です。
ここにも関連したお話がのっていました。
http://www.ne.jp/asahi/hishidama/home/tech/vcpp/dlgbar.html
CView::OnUpdate()は、プロテクトメンバーなんですが・・・?
> CView::OnUpdate()は、プロテクトメンバーなんですが・・・?
おっとっと、プロテクトだったか。
強引にOnUpdateを呼び出すパブリック関数を作る手も有るが、設計として正しいか
否か...
ITOさんは
> Document - Viewの関係で通すのなら、正しいのでは?
> ドキュメントが変更されていないけど、倍率を変更するために表示を更新したいので
す
> よね。
と書いているが、Viewの表示方法を変更しようとしているのだから、
CDocment::UpdateAllViews()を使用するのは正しくはない気がする。
(そういう意味ではOnUpdateを使えといった私の考えも間違い。)
UpdateAllViewsでは対象以外のViewも更新されるてしまい、余分な処理が走る。
そのドキュメントに関係するViewは一つならいいけど、複数あったら...
従って、Viewを特定して関数を呼び出すほうが正しいと考える。
で、熱血さんがやるべきことは、
> ((MDIGetActive())->GetActiveView())->Invalidate() ;
のようにInvalidate()を直接呼び出すのではなく、CViewの派生クラスに倍率を変更する
関数を作成して、その関数を呼び出すことです。つまりメニューに対する処理と同じ様
にコマンドハンドラを作成してそれを呼び出すこと。メニューに対してはフレームワー
クがコマンドハンドラの呼び出しまでやってくれる。ダイアログバーはそこまで面倒を
見てくれないのなら、自分で対象Viewを探す。それだけのことではないのかな。
まじめにDoc-Viewの実装にするのであれば
倍率データはDocに持つべきでは?
そうすれば↓を行うのは当たり前
((MDIGetActive())->GetActiveDocument())->UpdateAllViews(NULL)
というか、Document側でUpdateAllViewsではないでしょうか?
CHogeDocument::Set倍率(double d)
{
mXXX = d;
UpdateAllViews(NULL);
}
基本的にウインドウメッセージに対応して呼び出される関数を
直に呼ぶのはどうかなと思います。
メソッド呼び出ししたいのであれば、それように関数を作成するのが
本当じゃないかと。
例えば、Viewクラスのメンバーに描画倍率を保持する変数を置いて
それをセットする関数を作成し、関数内で引き渡された倍率を設定後、
自分自身のInvalidateを呼び出すとか。
私個人としては表示倍率と言うのはドキュメントよりは
ビュウの持ち物なのではという気がするので書いたような実装を
思い浮かべます。
後は、メインフレームとビュウの結合を弱める為に
この辺実装をユーザー定義のウインドウメッセージで解決とかしてました。
これだとビュウクラスの型に左右されずに発行できるのでフレーム側の
実装時に派生されたビュウクラスの型を知っておく必要が有りません。
まあ、この辺は好みの問題もあると思いますけれど。
>Viewの表示方法を変更しようとしているのだから、
>CDocment::UpdateAllViews()を使用するのは正しくはない気がする。
確かにそうですね。
僕の場合、Viewの中にOnTimer()を入れてフラグチェックしていますね。
Viewが一つに固定されているのでよかったのですが、
今回の場合、Viewが複数あるのでどう対処するかですね。
そう考えると、PATIOさんのユーザーメッセージを送るのがいいと思いますね。
メッセージ送信なら、アクティブな状態のViewに届くはずですよね?
maruさん、焼肉定食さん、PATIOさん、ITOさん。
たいへん、貴重なご意見ありがとうございます。
焼肉定食さんのおっしゃっている
> ドキュメントで倍率変数を持つ
というのは、「VIEWどういう表示をしようがドキュメントには関係ない」という観
点から、すこし、違和感があります。でも、これが一番簡単かも・・
> 私個人としては表示倍率と言うのはドキュメントよりは
> ビュウの持ち物なのではという気がするので書いたような実装を
> 思い浮かべます。
わたしは、最近PATIOさんから、数々のアドバイスをいただいているので、かなり
考え方が、PATIOさんナイズしているのか、この部分は、まったくの同感です。
今回の場合は、maruさんがおっしゃってくださっている、
> CViewの派生クラスに倍率を変更する
> 関数を作成して、その関数を呼び出すことです。
という対処が今回は、簡単見たいですけれども、
PATIOさん、ITOさんのおっしゃっている
> ユーザーメッセージを送る
というのは、とても汎用的というか、オールマィティというか、たくさんのケースに通
用するものだと思います。両方試してみたいとおもいます。
みなさま、ありがとうございます。
void CMainFrame::OnMag2()
{
((MDIGetActive())->GetActiveView())->Invalidate() ;
((MDIGetActive())->GetActiveView())->UpdateWindow() ;
}
ではだめかな?