他のViewへメッセージを送る方法は?

[戻る]
utm 2008/04/16(水) 15:43:28
環境 .NET2003 SDI/MFC

SDIテンプレート内でWindowsエクスプローラを選択しております。

左側ペインのTreeViewへローカルドライブ(C:)のディレクトリ一覧を
Itemとして設定しています(フォーカスはルート)。
右側ペインのListViewへは、TreeViewで選択されているルートにぶら下がる
ファイルやディレクトリをitemとして設定しております。

[行いたい事]
左側ペインのTreeViewのディレクトリItemを選択すると右側ペインのListViewの
一覧を更新したいと思っております。
また右側ペインのListViewの一覧にあるディレクトリItemを選択すると、
左側ペインのTreeViewのフォーカスを指定されたディレクトリに移動したい
と思っています。

[質問]
それぞれのViewから相手に対してSendMessageを送ってやれば良いのでは?
と思うのですが、直接相手側へ送る事が可能なのでしょうか?

親であるMainFormを経由する必要があるのであれば、それはどの様に記述
するべきなのでしょうか?

PATIO 2008/04/16(水) 17:02:05
SDIでドキュメント−ビュウ アーキテクチャに従うなら
ドキュメントのCDocument::UpdateAllViewsを呼ぶのが筋かと
思います。ただ、書かれている一文が理解できないので
外しているかもしれません。

「SDIテンプレート内でWindowsエクスプローラを選択しております。」

私が知っている範囲では、この文をきちんと説明できる内容が浮かびません。
この文章は何を意味しているのでしょう?
もしかして.NET 2003ではアプリケーションウィザードにそういう選択肢が
あるのでしょうか?
.NET 2003はあまり使い込んでいないのでわからないのですが。

utm 2008/04/16(水) 17:23:00
>もしかして.NET 2003ではアプリケーションウィザードにそういう選択肢が
>あるのでしょうか?
「プロジェクト形式:Windowsエクスプローラを選択」と訂正させて頂きます。

PATIO 2008/04/16(水) 17:39:28
>「プロジェクト形式:Windowsエクスプローラを選択」

うーむ、何処だか分からない。(^^;
これが直接関係無いとしたらの話ですが、

> SDIでドキュメント−ビュウ アーキテクチャに従うなら
> ドキュメントのCDocument::UpdateAllViewsを呼ぶのが筋かと
> 思います。

に関しては確認して見た方が良いと思います。

utm 2008/04/16(水) 18:04:22
PATIOさん、度々ありがとうございます。
>うーむ、何処だか分からない。(^^;
承知致しました。

今回私自身がSDIを使用するのが初めてで、
Document自体を把握しておりません。
# View(とCtrl)で可能かと思いましたので。

Documentに関する事をアホでも分かり易く
記載されているHP等は御座いませんでしょうか?

rin 2008/04/16(水) 18:06:10
VC2005なら
新規プロジェクトで
MFCアプリケーション→アプリケーションの種類
のときに
プロジェクト形式で選べます>「Windowsエクスプローラ」

デフォルトなら、左右2つのスプリッタウィンドウ(VIEW)のフレームと
CDocumentって構成になります

MainFrameまでさかのぼることなく、GetDocumentでドキュメントにアクセスし
そこでUpdateAllViews()すれば良いかと

たいちう 2008/04/16(水) 19:51:35
> Documentに関する事をアホでも分かり易く
> 記載されているHP等は御座いませんでしょうか?

自分にあった本を探せよ、とも思ったが気持ちはわかるので、
『MFC Document View』でググってみた。
http://mail2.nara-edu.ac.jp/~asait/visual_cpp/doc/document.htm
このようなサイトをいくつか見れば次に身に付けるべきものが判るかも。

もっとしっかり体系的にというなら、こんなの。
http://www.amazon.co.jp/dp/4756121748 : 『Inside Visual C++』

たいちう 2008/04/16(水) 20:14:02
ちょっと思いついたこと。

パワーポイントの資料を作りプロジェクタで会議の出席者に見せる。
↓
Documentを作りViewでユーザに見せる。

大きな違いはユーザがViewを通してDocumentの操作もできるところ。
出席者がプロジェクタ(に写ったイメージ)の間違いを指摘した場合、
プロジェクタではなく、パワーポイントの資料を修正します。

utmさんのケースでは、1つのパワーポイントのファイルを
複数のプロジェクタで表示しているようなもの。
本文と目次を写すプロジェクタがあるとしてください。

1つのプロジェクタを通して本文の変更をした後は、
もう1つのプロジェクタの内容(目次)も変わっている可能性があり、
更新する必要があります。
(パワーポイントとプロジェクタじゃなくてOHPの方が良かったかな)

このために用意されているのがCDocument::UpdateAllViews()で、
Documentと関連付けられている全てのViewを更新します。
本文は対処済みだったりして、本文以外のView、つまり目次だけを
更新したいときのために、この関数には1つめの引数があります。
本文のViewのポインタを入れて呼ぶことで
(通常は本文Viewの関数から呼ぶことを想定)、
呼び出し元のViewは更新されません。

utm 2008/04/17(木) 09:40:38
>rinさん
フォローありがとうございます。

>たいちうさん
>自分にあった本を探せよ…(略)
ごもっともです。

>ちょっと思いついたこと。
概略解説ありがとうございます。
┌───┬──────┐
|C:\   |ファイル一覧|
|├AAA |      |
|├BBB |      |
|└CCC |      |
└───┴──────┘
という表示イメージをDocumentでどの様に持てば良いか。
また、この情報がいくつもある場合はどの様に更新?
等々…。

んな面倒臭い事するなら、ダイアログイメージでデータ
を自身で管理して表示すれば良いのかな?って思っていました。

提示されたURL、ありがとうございました。

PATIO 2008/04/17(木) 11:32:06
> MFCアプリケーション→アプリケーションの種類のときに
> プロジェクト形式で選べます>「Windowsエクスプローラ」

指摘感謝します。
こんな所にあったのか。
見当違いのところを探してました。
この形式のビューがこんなに簡単に実装できるようになっていたとは
知りませんでした。前は自分でゴリゴリ書いてたのに。

と言うわけで、やはりCDocument::UpdateAllViewsでよさげですね。
あとはドキュメントにどういう形で実装するかですね。
これは考え方次第なのでやり様は色々有りそうです。

PATIO 2008/04/17(木) 11:39:08
ちなみにですが、ドキュメントに実装するのも
CDialogクラスの派生クラス上にデータ管理を実装するのも
基本的なスタンスは変わらないと思います。
CDialogでは表示するクラスとデータを管理するクラスが
同じだったと言うだけの事でCDocumentクラスにデータを
管理させて表示する時はドキュメントからデータを取り出して
表示するようにするだけの話なので。
うまく実装するとドキュメントクラスは一つだけで
複数のビューを作成し、同じドキュメントを色々な見せ方で
見せると言う実装がスマートにできると思います。


ドキュメントクラス内部でどのように実装するかは
実装する側に任されているので実装者の腕の見せ所では
ありますね。

maru 2008/04/17(木) 12:01:35
> こんな所にあったのか。
VC6からありましたよ。

>この形式のビューがこんなに簡単に実装できるようになっていたとは
> 知りませんでした。前は自分でゴリゴリ書いてたのに。
とは言っても、メインフレームにスプリッタウィンドを乗っけてその上に
ツリービューとリストビュー乗っけただけですよね。

一番最初に見たときはなるほどこうすればいいのかって思いましたが。

話は変わって、このスタイル(ツリービューとリストビュー)で構成される
ビューを必要とするドキュメントって、本質的にツリー構造となると思うん
だけど、ドキュメントにツリー構造を作って、さらにツリービューでツリー
構造を管理するってのはなんか無駄に思えてくる。
だから、ツリービューのツリーコントロール自身にデータを持たせたいなっ
て思うんだけど、皆さんはどうしています?
ケースバイケースでしょうけど。

PATIO 2008/04/17(木) 12:09:04
>> こんな所にあったのか。
> VC6からありましたよ。

がーん、ホントだ。
全然気がついて無かったです。
うわー。今まで全く使ってなかった。
まあ、アプリは作れてたので困ってはいませんでしたけど。
なんとなく、損をしていた感じです。
まあ、いっかぁ。

> とは言っても、メインフレームにスプリッタウィンドを乗っけてその上に
> ツリービューとリストビュー乗っけただけですよね。

ええ、ソースを直接弄ってやっていたと言うだけで基本は変わりません。
確か、どこぞの本に載っていたのでずっとそれでやってました。

PATIO 2008/04/17(木) 12:13:47
> 話は変わって、このスタイル(ツリービューとリストビュー)で構成される
> ビューを必要とするドキュメントって、本質的にツリー構造となると思うん
> だけど、ドキュメントにツリー構造を作って、さらにツリービューでツリー
> 構造を管理するってのはなんか無駄に思えてくる。
> だから、ツリービューのツリーコントロール自身にデータを持たせたいなっ
> て思うんだけど、皆さんはどうしています?
> ケースバイケースでしょうけど。

まあ、ツリー部分の量によるかなとも思いますけれど、
ツリービューでの表示は表現方法の一つと割り切って
データ管理とは別にしてますね。
データ管理部は実は他のアプリで同じデータを利用する時に
使いまわしたりしてますし。
これがツリービューに持たせてしまうとそういう使い方が
出来ないので。

たいちう 2008/04/17(木) 13:24:25
> がーん、ホントだ。
> 全然気がついて無かったです。

同意。

> ツリービューでの表示は表現方法の一つと割り切って
> データ管理とは別にしてますね。

同意。

この場合、データの多重化を嫌うよりは、
確実に同期させる仕組みを考えたほうが良いかと。
ツリービューの操作とドキュメントの操作を一対一で対応させるか、
一方から他方を(多分docからviewを)コピーするような。

bun 2008/04/17(木) 15:37:23
maruさん

> だから、ツリービューのツリーコントロール自身にデータを持たせたいなっ
> て思うんだけど、皆さんはどうしています?
読み方によって、回答が変わってしまいそうですが、
私なら、ツリーコントロール自身にデータを持たせるのは賛成です。
ただし、持たせるのは実体データではなく、参照データのみです。

参照データには、指し示す先の実体が必要なので、その実体データをドキュメン
トで扱う感じです。

(例) 住所録
住所録データの要素が以下のような設計だとして、
class CAdressBook
{
  CString m_Country;  // 都道府県
  CString m_City;     // 市区町村
  CString m_Name;     // 名前
};
ドキュメントには、このオブジェクトスの集まり(目的によって、リスト、配列、
マップを使い分ける)を扱います。

そして、ツリービューには、上記オブジェクトへの参照をもちます。
CTreeCtrl::SetItemData()にて設定
  都道府県 市区町村  名前
----------+---------+-----
- 東京都
    +      渋谷区    bun1
    +        :
+ 大阪府
    +      堺市      bun2
    +        :
- 愛知県
    +      名古屋市  bun3
    +        :

私が今までやってきた限りでは、これが一番分かりやすく無駄も少ない方法です。

もっとも、今回の場合、ドキュメントは不要という見方もできます。
通常、ドキュメントで扱うのは、ファイルに保存しない限り、揮発してしまう情
報だと思うからです。ディスク情報なら、揮発することはあり得ないですからね。

maru 2008/04/17(木) 16:50:20
utmさん

話がずれていって申し訳ありません。

> だから、ツリービューのツリーコントロール自身にデータを持たせたいなっ
> て思うんだけど、皆さんはどうしています?
自分で書いた内容だけど、実は自分でもツリーコントロール自身にデータを持
たせていません。
ドキュメントのツリー構造となる部分はコンポジットモデルで実現して、ツリ
ービューに表示するときに、その構造をたどってツリーコントロールに追加し
てます。さらにドキュメントのツリーのリーフとなるデータ(オブジェクト)
のポインタをツリーコントロールのアイテムにセット(これはbunさんと似た感
じ?)。
ただ、やはりデータ構造がダブっているような気がして、なんか気持ちが悪か
ったんですよ。
> ツリービューでの表示は表現方法の一つと割り切って
> データ管理とは別にしてますね。
と割り切ることですね。

で、utmさんの元に質問に対する私の回答。
(他の人と一緒ですけど)CDocument::UpdateAllViewsを使用すべきでしょう。
私の場合、クリックしたときの動作として、上に書いたツリーアイテムにセッ
トしたポインタをヒントデータとしてUpdateAllViewsを呼び出しています。


PATIOさん
> がーん、ホントだ。
> 全然気がついて無かったです。
情報の後出で済みません。

PATIO 2008/04/17(木) 17:31:37
> もっとも、今回の場合、ドキュメントは不要という見方もできます。
> 通常、ドキュメントで扱うのは、ファイルに保存しない限り、揮発してしまう情
> 報だと思うからです。ディスク情報なら、揮発することはあり得ないですからね。

これも一理あるんですが、CDocument::UpdateAllViewsを使ってコントロールする
と言う方法をとるならドキュメントクラスにデータ管理をさせた方がすっきりすると
思うのです。あれこれ考えずにドキュメントクラスに表示に必要な情報を要求する
と言う考え方です。
ドキュメントクラスの内部実装はどうにでも出来ますから
それこそ要求される度にディスクから取得しても実装はできると思います。
実際の話、ディスク上の状況が変わってしまった時にどう対応するかという
部分も絡む話なのでそれは設計次第かなと。
例えば、ユーザーに「最新の情報を表示」というコマンド明示的に与えて
それまでは最初に取得した情報をメモリ上に保持しておいて返却すると言うのも
有りかと思いますし。

この辺はそれこそ実装次第かなと。

utm 2008/04/17(木) 23:39:38
[[解決]]
皆さん、色々なご意見ありがとうございます。

管理と表示を別々ならば、皆さんがご教示して下さった
「CDocument::UpdateAllViews」を使用する理由は判りました。

今回はViewのみでは無く、Document/Viewの本来の姿で進めて
行こうかと思います。

また質問も出て来るやも知れませんので、その時も宜しくお願いします。

古いスレッドには追加発言できません。