環境:VC8 MFC(SDI) Win XP
お世話になります。
MFCドキュメント、ビューアーキテクチャーについて、教えて頂きたく思います
BOOL CxxxDoc::OnOpenDocument(LPCTSTR lpszPathName)から、ファイルを開き
データを読込み、加工して
CDocument::UpdateAllViews(NULL)で
ビュー画面へ表示へ表示はできるのですが、その後
異なるファイルを開いたとき、そのタイミングで、一旦それまでの、ビュー画像は
消去して(画面を単色で塗りつぶし)、新たに読込んだファイルを
表示したいのですが、どうも、うまくいきません
背景画面を消去するのに
afx_msg BOOL OnEraseBkgnd(CDC* pDC);
BOOL CxxxView::OnEraseBkgnd(CDC* pDC)
{
CRect rc;
GetClientRect(&rc);
pDC->FillSolidRect(&rc, RGB(0,0,0));
return TRUE;
}
と、追加し、これ自体は問題は無いのですが、呼び出すタイミングが、よくわかりません
void CxxxView::OnInitialUpdate()
{
// CScrollView::OnInitialUpdate();
CDC* pDC = this->GetDC();
OnEraseBkgnd(pDC);
CSize sizeTotal;
// TODO: このビューのサイズの合計を計算します。
sizeTotal.cx = sizeTotal.cy = 2000;
SetScrollSizes(MM_TEXT, sizeTotal);
}
このように、OnInitialUpdate()メッソッド内で呼ぶと、新規作成ボタンを、
押下した場合は、機能するのですが、ファイルを開く場面では、機能しません。
また、OnUpdateFileOpenイベントハンドラーを追加して、そのメッソッド内に、
CDC* pDC = this->GetDC();
OnEraseBkgnd(pDC);
を記述すると、ファイルを読込み、ビュー画面へ表示させるよう、実装しても
何も表示できません。
CxxxView::OnDraw()で呼んでも、スクロールビューなので、表示がおかしくなってしまい
ます。
どのタイミングで、呼び出したらいいか、ご教示願います。
MSDNによると
CDocument::UpdateAllViewsでCView::OnUpdateが呼ばれると書いてあるけど。
俺はドキュメントビューを使わないので知らない。
念のため
直接OnDraw();などはコールしてはいけないよ。
CWnd::InvalidateRectなどを使えば、後でOnDraw();が呼ばれる。
MFCは最近触ってませんが・・・
wclrp ( 'o')さんの指摘にあるように、OnDraw()やOnEraseBkgnd()は直接コールしてはダ
メです。
これ -> OnEraseBkgnd(pDC);
一般的な方法として、
1. OnOpenDocumentでファイルを読み込んだ後、InvalidateRect()を実行
2. OnEraseBkgnd, OnDrawが順番に実行されます。
#スクロールビューってpDCの原点が自動的に調整されてるはずでは?
wclrp ( 'o')さん、KJさんお世話になります。
OnDrawやOnEraseBkgndを、直接実行するのは、セオリー違反ということですね。
ご教授ありがとうございます。さて、
OnOpenDocument()メッソッド内でファイルを読んだ後、下記の通りInvalidateRectを
実行するのですが
OnEraseBkgndを、呼んでくれないようです、間違いがあれば、ご指摘お願いします。
BOOL CxxxDoc::OnOpenDocument(LPCTSTR lpszPathName)
{
if (!CDocument::OnOpenDocument(lpszPathName))
return FALSE;
// TODO: ここに特定な作成コードを追加してください。
if( m_curFcdata.ReadStream(lpszPathName) ) { // ファイル読込み
InvalidateRect(NULL, NULL, TRUE);
//UpdateWindow(FALSE);
CDocument::UpdateAllViews(NULL);
return TRUE;
}
return FALSE;
}
CxxxDocからInvalidateRect呼ぶと
CxxxDoc::InvalidateRectは無いので
::InvalidateRectを呼ぶわけだ。
そして::InvalidateRect(NULL,だから
どのウィンドウに対してInvalidateRectを行うか指定がないから失敗。
描画させたいウィンドウに対してInvalidateRectを行わないと意味ない。
CxxxDoc::UpdateAllViewsで
CxxxView::OnUpdateって呼ばれない?
当然CxxxView::OnUpdateが存在しないと呼ばれるわけないけど
その辺はよく知らない。
wclrp ( 'o')さん、いつもお世話になります。
Visual C++ 2005 シニア編という本に、ドキュメントとビューの詳しい、解説が掲載さ
れていました。
今回の場合ですと
void CFCView::OnInitialUpdate()
{
CSize sizeTotal;
// TODO: このビューのサイズの合計を計算します。
sizeTotal.cx = sizeTotal.cy = 2000;
SetScrollSizes(MM_TEXT, sizeTotal);
OnUpdate(NULL, 0, NULL); // これを追加
}
OnUpdate(NULL, 0, NULL);このように追加することで、
ファイルを開く度に、画像を消去し、新規画像を描画できました、ありがとうございました。
OnUpdate(NULL, 0, NULL);を追加するのではなく...
その箇所に基本クラスの
CScrollView::OnInitialUpdate();
を復活させるだけの話でわ?
CScrollView::OnInitialUpdate()はその中でOnUpdate()も
呼び出してくれるはず。
↑
MSDNのCView::OnUpdate()の解説に、
「OnInitialUpdate の既定の実装でも呼び出されます。」
とあります。
http://msdn.microsoft.com/ja-jp/library/w1z3te7e(VS.80).aspx
当初は ScrollView::OnInitialUpdate() があったはずだけど、
なぜか削除してしまっていますね。
特に明確な理由があって削除したのでなければ、
それを復活させるほうが妥当かと。