SDIのビューの切替

[戻る]
BOB 2002/03/14(木) 15:10:02
SDIでビューの切替を行っています。ON_CONTROL_RANGEでメッセージを受け取って画面の遷
移(ビューの切替)をしているのですが、メニューバーからメッセージをとばしたときは、
GetActiveViewでビューポインタを受け取れるのですが、ボタンコントロールを作成し、ボタン
からメッセージをとばして処理すると、GetActiveViewでビューポインタがNULLになってしま
します。ボタンにViewが移るとかあるのでしょうか?

よろしくお願いします。

Bun 2002/03/14(木) 15:47:30
ActiveなViewがないからでわ?

主要ソースをのせれば、(わし以外の)識者の方々が回答を
してくれるのでわ???

スプリッタでわないですよね?

BOB 2002/03/14(木) 16:57:09
ソースはこんな感じです。追加したところだけのせます。

-----****View.cpp---------------------------------------------
BEGIN_MESSAGE_MAP(CMainMenuView, CFormView)
ON_CONTROL_RANG(BN_CLICKED,IDC_MAIN1,IDC_MAIN2,CMainFrame::OnViewChange)
END_MESSAGE_MAP()


-----MainFrm.cpp-----------------------------------------------
BEGIN_MESSAGE_MAP(CMainFrame, CFrameWnd)
    ON_COMMAND_RANGE(ID_GAMEN1,ID_GAMEN3,OnViewChange)
    ON_UPDATE_COMMAND_UI_RANGE(IDD_ABOUTBOX,ID_GAMEN2,OnUpdateViews)
END_MESSAGE_MAP()

void CMainFrame::OnViewChange(UINT nCmdID)
{
    /* 同じ画面なら切替しない */
    if(nCmdID == m_nCurrView)
        return;

    /* 現在のビューを指すポインタの取得 */
    CView *pPrevView = GetActiveView();
    if( pPrevView == NULL ){
        MessageBox("GetActiveViewでNULLが返ってきました。");
        return;
    }
    /* 現在のビューのウィンドウIDの取得 */
    LONG nWindowID = ::GetWindowLong(pPrevView->m_hWnd,GWL_ID);
    /* 現在のビューのウィンドウIDの変更(ダミー) */
    ::SetWindowLong(pPrevView->m_hWnd,GWL_ID,nCmdID);

    /* 更新するビューのランタイムクラスの作成 */
    CRuntimeClass *pNewViewClass;

    switch(nCmdID){
        case ID_GAMEN1:
            pNewViewClass = RUNTIME_CLASS(CMainMenuView);
            break;
        case ID_MAIN1:
        case ID_GAMEN2:
            pNewViewClass = RUNTIME_CLASS(CIraiView);
            break;
        case ID_MAIN2:
        case ID_GAMEN3:
            pNewViewClass = RUNTIME_CLASS(CKekkaView);
            break;
        default:
            ASSERT(0);
            return;
    }

    /* 更新するビューに必要な情報を作成 */
    CCreateContext context;
    context.m_pNewViewClass = pNewViewClass;
    context.m_pCurrentDoc = GetActiveDocument();
    /* 新しいビューの作成 */
    CView *pNewView = (CView *)CreateView(&context);
    /* 作成成功 */
    if(pNewView != NULL){
        pNewView->ShowWindow(SW_SHOWDEFAULT);
        pNewView->OnInitialUpdate();
        SetActiveView(pNewView);
        RecalcLayout();
        /* 以前のビューを破棄 */
        pPrevView->DestroyWindow();
        m_nCurrView = nCmdID;
    }
    /* 作成失敗 */
    else{
        /* 元のビューウィンドウに戻す */
        TRACE("creation faiulre: new view\n");
        ::SetWindowLong(pPrevView->m_hWnd,GWL_ID,nWindowID);
    }
}

ID_GAMEN*というのがメニュー選択用のIDです。
ID_MAIN*というのがボタンのIDです。
どちらもOnViewChangeの処理にはくるのですが、ボタンだと
GetActiveViewでNULLが返ってきてしまいます。
メニュー選択では正常に動きます。
何故でしょうか?

Bun 2002/03/14(木) 18:45:04
>ON_CONTROL_RANG(BN_CLICKED,IDC_MAIN1,IDC_MAIN2,CMainFrame::OnViewChange)
                          ^^^^^^^^^^^^^^^^^^^^^^^^
自信ないのですが、こういう方法できるんでしたっけ? ↑↑↑

ON_CONTROL_RANG(BN_CLICKED,IDC_MAIN1,IDC_MAIN2, OnViewChangeMsgPost)
などとして、自クラスで処理するのはどーでしょ。
ただし処理自体はCMainFrameクラスにおこなわせる。

OnViewChangeMsgPost()から親のCMainFrameに対して ID_GAMEN* をPostする。

void C???View::OnViewChangeMsgPost(int nID)
{

  switch (nID) {
  case IDC_MAIN1:
    GetParent()->PostMessage(WM_COMMAND, MAKEWPARAM(IDC_GAMEN1, 0), 0);
    break;
  case IDC_MAIN2:
    GetParent()->PostMessage(WM_COMMAND, MAKEWPARAM(IDC_GAMEN2, 0), 0);        
    break;
  }

}

試していないので、はずしていたらゴメンナサイ。

BOB 2002/03/14(木) 18:54:01
[[解決]]
Bunさんありがとうございます。
うまく動いた感じです。もっとテストしてみます。
嬉しいです〜。

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