>シャノンさん
いえいえ、まだまだ未熟者なので参考になります。
>PATIOさん
つまりそれってOnUpdateのところに記述しておいて、OnDraw
のところにはUpdateAllViews(this)を記述して、OnUpdate
イベントを起こすというのは、考え方としては間違いではない
と思っていいのでしょうか?といってもそのOnUpdateが呼ばれ
ないんですが・・・。
順番としては、こうなると思います。
1. pDoc->UpdateAllViews(this); を呼ぶ(保持データが変化した事を通知)
2. 全ビューの OnUpdate() が呼ばれる
3. OnUpdate() で、Invalidate() 等を呼び出し、
画面の更新を指示する。(表示内容が変化したことを通知)
3. OnDraw() が呼ばれる
なので、OnDraw()の中で1や3が起こりうる操作をするのは、
あまり良くないでしょう。
いえ、そもそもOnDrawというのはユーザーがデータを追加したときに呼ばれるのではなくて
画面を更新したいときに呼ばれるものなのでそこでUpdateAllViewsが呼ばれるはずはない
のです。
もし能動的に増やしたり、減らしたりしたいのであれば、
メニューでもこさえてそこを選択されたら増やすとか、
マウスの右クリックで増やすとか、そういうオペレーションを入れるべきです。
ようは、データの増やしたり、減らしたりする操作をOnDrawの中から起動しようというのが
間違いだと思います。
UpdateAllViewsは、ドキュメントが変更された時に、他のビューに表示を更新するように
通知するためのものです。
そのためドキュメントに対応するビューのうち、引数に指定していないビューのOnUpdate
が呼ばれます。
従って、UpdateAllViews(this); では、自身のOnUpdateは呼ばれません。
自身を含めたOnUpdateを呼びたいのであれば、引数にNULLを指定してください。
皆さんレスありがとうございます。
dairygoodsさん、PATIOさんがおっしゃるようにOnDrow内に書く
のは良くないというのは、私もなんとなくそんな気はします。
となると・・・
1.OnDrawでドキュメントにテキストを書いた→とりあえずOK
2.たくさん書いたからドキュメントの高さを増やしたい→どこで?
3.高さを増やしたからスクロール幅も増やしたい→どこで?
dairygoodsさんの言われるような、「順番」というのは、みなさん
どこで覚えてくるのでしょう。経験ですか?
(正直、まだデバッグ方法が良くわかっていないせいもあるが)
試しにREEさんのおっしゃるとおり、NULLを指定したら、確かに
OnUpdateイベントが起きました。
でも、これやっちゃだめなんですよねぇ。。。
>1.OnDrawでドキュメントにテキストを書いた→とりあえずOK
OnDrawは、ドキュメントの内容を表示するのが役割ですので、
ここで、ドキュメントの変更はしないで下さい。
>2.たくさん書いたからドキュメントの高さを増やしたい→どこで?
>3.高さを増やしたからスクロール幅も増やしたい→どこで?
ドキュメントの高さやスクロール幅を変えるのは、ドキュメントの変更をしたときです。
>試しにREEさんのおっしゃるとおり、NULLを指定したら、確かに
>OnUpdateイベントが起きました。
>でも、これやっちゃだめなんですよねぇ。。。
はい、やらないほうが良いです。
>REEさん
ますますわからなくなってきてしまいました。
何か私勘違いしてますか?
>OnDrawは、ドキュメントの内容を表示するのが役割ですので、
>ここで、ドキュメントの変更はしないで下さい。
いろんなサイト、参考書をみると全てOnDrawにTextOutを書いて
います。これってホントはやっちゃいけないんですか?
「内容を表示」するというのはどういう意味なのでしょう?
TextOutは「ドキュメントの変更」を指しているのですか?
>ドキュメントの高さやスクロール幅を変えるのは、ドキュメントの変更をしたときです。
私、ドキュメントの変更の意味がわかっていないみたいです。
正直 Document-View が何ぞや、あたりからはじめてもらうほうがよさげな気がします。
Scribble とか(Doc-View 入門的には良いけど他の部分が古杉ですが)
Document っつーのは単なるデータです。
HTML をご存知なら例えば <iostream> という文字列を考えましょう。
View っつーのはそれを表示する手段。
先ほどの Document に対して Text-View なるものを用意すると <iostream> と表示。
同じ Document を Html-View なるもので表示すると <iostream> と表示。
# 表示するように view を作る、ってこと。
TextOut は画面にデータを表示する関数です。
表示する際にどのような形式を用いるかを View は決めます。
OnDraw は「描画しなさい」って通知なので View は既存の Doc を自分の形式で表示します。
OnDraw の度に Doc の内容が変わるあるいは変えるっつーのは設計がヘン。
Doc の変更ってのは先の文字列が #include <iostream> に変わったとか。
すると表示されるべき幅が変わるはずです。
ScrollSize を変更する必要は、そんなときだけ生じるはず。
>>試しにREEさんのおっしゃるとおり、NULLを指定したら、確かに
>>OnUpdateイベントが起きました。
>>でも、これやっちゃだめなんですよねぇ。。。
>
> はい、やらないほうが良いです。
え? なんで? 他のViewまでre-drawしちゃうから?
「ドキュメントの変更」を描画領域の変更と置き換えて考えてみてください。
> え? なんで? 他のViewまでre-drawしちゃうから?
OnDraw でやってはダメなんだという話でしょう。
NULL だろうと this だろうと。
# 掲示板での説明では限界があると思いますので、参考書を紹介します。
# 回答者とわかさんの努力によって今回の問題が解決した後でも役に立つと思います。
# 『Inside Visual C++ version5―Microsoft Visual C++ Ver.5標準教科書』
http://www.amazon.co.jp/exec/obidos/ASIN/4756121748/qid=1108516441/ref=sr_8_xs_a
p_i1_xgl/249-2911650-4016320
>「ドキュメントの変更」を描画領域の変更と置き換えて考えてみてください。
いやこれは却って誤解を招きそうです。
描画領域の変更は、むしろビューの変更です。
描画内容の変更ならいいですが・・
>> はい、やらないほうが良いです。
>え? なんで? 他のViewまでre-drawしちゃうから?
これに関しては、たいちうさんのフォロー通りの意味です。
みなさん長い間お付き合いいただき、ありがとうございます。
私のためを思って、答えを自分で導き出せるように遠まわしに回答して
いただいたりしていただいたようですが、あまり時間もなくなってきて
しまったため、今回のところはもう降参です。
ズバリ教えてください。
1.デフォルトで表示したいテキストを書く場所(TextOut)
2.1に対してスクロール幅を計算および、設定する場所(SetScrollSizes)
3.ウィンドウのサイズを変更したときに2を再計算、再設定する場所
4.ResizeParentToFit(TRUE);を書く場所
私の回答は
1.OnDraw
2.OnInitialUpdateとOnUpdate
3.2と同様
4.OnUpdate
ですが、これではうまくいきませんでした。
どういう結果になるかというと、
1.垂直スクロールバーの計算はうまくいっているように
見えるが、ツマミを一番下までもってくると、最後の
行が表示されていない。
2.スクロールすると残像が残る。
3.一番下までスクロールしたあと、ウィンドウの位置を
変えると、一番上の行が表示される。(スクロールバー
のツマミは一番下にきたまま)
どうぞ宜しくお願いいたします。
>1.デフォルトで表示したいテキストを書く場所(TextOut)
>2.1に対してスクロール幅を計算および、設定する場所(SetScrollSizes)
>3.ウィンドウのサイズを変更したときに2を再計算、再設定する場所
>4.ResizeParentToFit(TRUE);を書く場所
>私の回答は
>1.OnDraw
これでOKです
>2.OnInitialUpdateとOnUpdate
これもOKでしょう
>3.2と同様
これは、一般的には不要ですが、
もし書くとしたら、WM_SIZEのハンドラであるOnSizeです。
>4.OnUpdate
これもOKですね
ちなみに、OnDrawで使っているNowTopって何のための変数ですか?
普通にスクロールすればいいのであれば、この様な変数は不要です。
高速化が必要な場合を除いてOnDrawでは現在のスクロール位置とは無関係に描画すればよ
いです。
> 私のためを思って、答えを自分で導き出せるように遠まわしに回答して
> いただいたりしていただいたようですが
というより、どこで躓いているか見えないので、
一般的な仕組みを理解してもらい、
間違いor勘違いを自力で見つけてもらうしかないのです。
> 2.1に対してスクロール幅を計算および、設定する場所(SetScrollSizes)
> 3.ウィンドウのサイズを変更したときに2を再計算、再設定する場所
この表現がちょっと気になります。
SetScrollSizes は、スクロール等考慮せず、
自分の描きたい絵が 何×何 ピクセルかを指定するだけです。
スクロールバーの設定は、MFCが勝手に計算してくれます。
画面サイズの変更によって、表示する内容が変化しないのであれば、
SetScrollSizes を呼び出す必要はありません。
そして、
OnDrawでは、たとえば、SetScrollSizes で 1000x1000 を指定したなら、
(0, 0) - (1000, 1000) の領域に好きなように描くだけです。
#印刷もする場合は、論理単位(mmなど)を使わないと
#画面と紙のサイズが合いませんが。
> 4.ResizeParentToFit(TRUE);を書く場所
ResizeParentToFit() は、ビュー自身のサイズにあわせて、
メインウィンドウのサイズを変更する機能です。
ウィンドウサイズは、大抵、ユーザーが自由に決めますし、
さらに、何か変更するたびにウィンドウサイズが変化しては、
使いづらいでしょう。
多分、呼び出し自体不要だと思います。
どうしても必要なら、OnInitialUpdateでしょう。