教えてください。MFCです。
View(正確にはListView)で持っている関数や値を
Docで使いたいのですがやり方はないでしょうか?
それらは本来Docが持つべきもので、その見せ方をViewに任せたんじゃないでしょか。
そこを何とか実現させてみたいのです。
今調べたところ以下のようなやり方がありました。
POSITION poz = GetFirstViewPosition();
C***List* pView = (C***List*)this->GetNextView(pos);
そしてリストコントロールを得ます
CListCtrl& listCtrl = pView->GetListCtrl();
ですがデバッグしてlistCtrlの中を見ても取得されていませんでした。
どうしたら正確に入ってくれるでしょうか?
Doc/View の設計理念に反することをしようとしている、つまり、
本来すべきでないことをしたがっているわけなのだ。
MFC の設計思想に反してまでやらなきゃならない何らかの根拠がある?
単なる技術的興味?
俺としては View が Doc を見に/書きに行くように直すほうを強く推奨する。
とりあえず、DOCに対しVIEWは複数の可能性があるので
>C***List* pView = (C***List*)this->GetNextView(pos);
このpViewが、目的のVIEWである保証はない。
よって、目的のVIEWであるか確認すること。
ネット上で「GetFirstViewPosition」を知ったのなら
一緒に目的のVIEWかどうかの調べ方がでているはず。
tetrapodさん
>単なる技術的興味?
はい
ryoさん
>ネット上で「GetFirstViewPosition」を知ったのなら
>一緒に目的のVIEWかどうかの調べ方がでているはず。
一応調べてみたところ以下のようなやり方がありました
void *p;
C***List* pListView;
POSITION pos = GetFirstViewPosition();
p = GetNextView(pos);
pListView = (C***List*)p;
CListCtrl& listCtrl = pListView->GetListCtrl();
前回より少々良くなりましたがデバッグで見たところ
pListViewの中身に違うViewクラスが入ってしまってるみたいです。
またunused=???とよくわからないこともかかれています。
どこかおかしいところがありましたら教えていただけないでしょうか?
補足します
今上記のコードに
void *p,*p2;
C***List* pListView;
POSITION pos = GetFirstViewPosition();
p = GetNextView(pos);
p2 = GetNextView(pos);
pListView = (C***List*)p2;
CListCtrl& listCtrl = pListView->GetListCtrl();
ともう一つViewを取得したところうまくC***Listクラスが入っていました
なぜなんでしょうか?ちなみに
p = GetNextView(pos);
にはTreeViewのクラスが入っていたようです
> DOCに対しVIEWは複数の可能性がある
このためです。
その Document に対する View が複数あり、2つ目の View が目的のものだったというこ
とでしょう。
ただし、常に必ず2つ目の View が目的のものだとは限りません。
>> 単なる技術的興味?
> はい
んー...僕だったら UpdateAllViews() 使って
「ListCtrl持ってる奴ぁ手ぇ挙げろー」
てやっちゃうかなー。
あんまりお勧めはしませんが、どうしてもやりたいなら、
Doc = Template->CreateNewDocument();
NewFrame = Template->CreateNewFrame(pDoc, NULL);
した後に、
while(1){
Frame = GetActiveFrame();
View = Frame->GetActiveView();
if( View->IsKindOf( RUNTIME_CLASS(「ビュークラス名」)){
Doc->SetYourFrmae( Frame); // Docにフレームポインタを設定
Doc->SetYourView( View); // Docにビューポインタを設定
break;
}
}
とかすれば、Viewだろうが、Frameだろうが
好きにできますよねぇ(笑)。
>一応調べてみたところ以下のようなやり方がありました
全然違う。
これじゃ、「なんのVIEWかわからないまま、気にせず型変換してる」だけ
で、色々書こうと思ったがほとんど答えがでてるのでいいや
しかし、
「TreeView」がいきなり出てきたな・・・
エクスプローラスタイルなんでしょうね、たぶん。
aetosさん
>ただし、常に必ず2つ目の View が目的のものだとは限りません。
これは困りましたね。あらかじめ2つ目のViewが目的のものとすることは出来るのでしょ
うか?
επιστημηさん
UpdateAllViews() を使ってView間を制御出来るみたいですね。
調べて使ってみます。
>これは困りましたね。あらかじめ2つ目のViewが目的のものとすることは出来るのでし
ょうか?
基本的に何番目のビューとか意識しないのがDoc-Viewの考え方です。
ドキュメントからビューに要求を出したいときは、
UpdateAllViews()で全てのビューに要求を一斉送信。
「ビューよお前に任せた」
「必要なデータは俺のところへ取りに来い!」
みたいな感じです。
ビューの側では、UpdateAllViews()の応答で OnUpdate()が呼ばれますので、
ビューが自分で判断して必要なら処理するだけです。
> UpdateAllViews() を使ってView間を制御出来るみたいですね。
てか、UpdateAllViewsの目的はその名のとおり、
「俺(Doc)の状態/値が変化した。
おまえら(AllViews)が俺の状態/値に依存する見てくれを持っているなら
俺の状態/値を反映(Update)せよ」です。
目的はそーなのですが、これを悪用(?)し、
「だれかいるぅ? いたらなんかしておくれー」と
Viewが何かをするきっかけを与えるだけにとどめるす。
で、
#define LISTCTRLくれ 100
class Doc : public CDocument {
CListCtrl* ctrl_;
public:
void setListCtrl(CListCtrl* p) { ctrl_ = p; }
private:
void ListCtrlがほしくなった() {
ctrl_ = 0;
UpdateAllViws(0,LISTCTRLくれ);
if ( ctrl_ != 0 ) {
ctrl_ を使う
}
}
};
class XXXView : public CXXXView {
void OnUpdate(CView*, LPARAM lHint, CObject*) {
if ( lHint == LISTCTRLくれ ) {
GetDocument()->setListCtrl(俺の持ってるCListCtrl);
}
}
};
とかなんとか。