看书上有一个SDI例子,是用来(静态)分割窗口的,并且可以使用菜单来切换两个视图(分别是CStringView显示字符串格式,CHexView显示相应的16进制)。切换视图的响应函数如下:enum EView{STRING = 1, HEX = 2};void CMainFrame::SwitchView(EView nView)
{
CView *pOldActiveView = GetActiveView();
CView *pNewActiveView = (CView*)GetDlgItem(nView); /*if (pNewActiveView == NULL)*/ {
switch(nView) {
case STRING:
pNewActiveView = (CView*)new CStringView();
break;
case HEX:
pNewActiveView = (CView*)new CHexView();
break;
}
} CCreateContext context;
context.m_pCurrentDoc = pOldActiveView->GetDocument(); pNewActiveView->Create(NULL, NULL, WS_BORDER, CFrameWnd::rectDefault, this, nView, &context); 
pNewActiveView->OnInitialUpdate(); SetActiveView(pNewActiveView);
pNewActiveView->ShowWindow(SW_SHOW);
pOldActiveView->ShowWindow(SW_HIDE);
pOldActiveView->SetDlgCtrlID(pOldActiveView->GetRuntimeClass() == RUNTIME_CLASS(CStringView) ? STRING : HEX);
pNewActiveView->SetDlgCtrlID(AFX_IDW_PANE_FIRST); RecalcLayout();}
结果发现:程序运行后,首次点击菜单来切换两个视图的时候,可以实现效果。可是当第三次点击菜单的时候,程序就死掉了。调试一下,发现在 pNewActiveView->Create(NULL, NULL, WS_BORDER, CFrameWnd::rectDefault, this, nView, &context); 这句出错,跟踪进去是有一步获得窗口句柄为空导致的结果。
回来我把程序中一句(就是用/* */注释掉的那句/*if (pNewActiveView == NULL)*/)注释后,就可以一直正常的切换。那就是说if里面的语句执行,影响了后面的Create()函数。可是我不知道为什么?请指教!谢谢!!!

解决方案 »

  1.   

    if 条件注释前出错,是因为 同一个View对象,在调用Create创建了窗口之后, 又被调用Create去创建窗口(切换时),这时Create函数出错。 if 条件注释后, 每次View对象重新创建,然后去Create窗口。 虽然不会出错,但带来的问题是,每切换一次就会创建一个新的,导致内存泄漏。修改如下:void CMainFrame::SwitchView(EView nView)
    {
        CView *pOldActiveView = GetActiveView();
        CView *pNewActiveView = (CView*)GetDlgItem(nView);    if (pNewActiveView == NULL) {
            switch(nView) {
            case STRING:
                pNewActiveView = (CView*)new CStringView();
                break;
            case HEX:
                pNewActiveView = (CView*)new CHexView();
                break;
            }
            CCreateContext context;
            context.m_pCurrentDoc = pOldActiveView->GetDocument();
            pNewActiveView->Create(NULL, NULL, WS_BORDER, CFrameWnd::rectDefault, this, nView, &context); 
            pNewActiveView->OnInitialUpdate();
        }    SetActiveView(pNewActiveView);
        pNewActiveView->ShowWindow(SW_SHOW);
        pOldActiveView->ShowWindow(SW_HIDE);
        pOldActiveView->SetDlgCtrlID(pOldActiveView->GetRuntimeClass() == RUNTIME_CLASS(CStringView) ? STRING : HEX);
        pNewActiveView->SetDlgCtrlID(AFX_IDW_PANE_FIRST);    RecalcLayout();}