SDI工程切换视图问题

red-fly 2018-01-29 05:42:49
建立一个普通的SDI工程,参考网上的文章添加了另外一个视图B(原视图记为A),在CMainFrame::Create() 中调用如下的函数创建视图B:
/*
参考:
https://wenku.baidu.com/view/1109160002020740be1e9b29.html
http://blog.csdn.net/fengyanhui/article/details/5993104
*/
void CMainFrame::CreateMoreViews()
{
m_pViewList[0] = (CMyReportView*)GetActiveView();
CCreateContext context;
context.m_pNewViewClass = RUNTIME_CLASS(CSRView);
context.m_pCurrentDoc = m_pViewList[0]->GetDocument();
context.m_pNewDocTemplate = NULL;
context.m_pLastView = NULL;
context.m_pCurrentFrame = this;
m_pViewList[1] = (CMyReportView*)CreateView(&context);
m_pViewList[1]->OnInitialUpdate();
m_pViewList[1]->ShowWindow(SW_HIDE);
}

在类中定义CMyReportView m_pViewList[2]; 此函数视图A、B(CSRView)都是从CMyReportView(从CListView派生)派生出来的。
这个函数用来创建视图B。
两个视图A、B同时只显示一个,正常情况下显示A,通过菜单可以切换A、B的显示
m_pViewList中,下标0对应的是A视图,1对应的是B视图。
在程序启动后,默认显示的就是A视图,代码仅创建B,在上面的函数中,创建它之后进行隐藏。

切换两个视图的代码几乎一样,
切换显示A视图的代码:
void CMainFrame::OnShowAview()
{
m_pViewList[0]->ShowWindow(SW_SHOW);
m_pViewList[1]->ShowWindow(SW_HIDE);
SetActiveView(m_pViewList[0]);
RecalcLayout();
}


切换显示B视图的代码:
void CMainFrame::OnShowBview()
{
m_pViewList[0]->ShowWindow(SW_HIDE);
m_pViewList[1]->ShowWindow(SW_SHOW);
SetActiveView(m_pViewList[1]);
RecalcLayout();
}


对上面两个函数的调用,是通过两个菜单
程序启动之后,先切换到B,无反应,然后切换到A仍然是A视图这个正常,再切换到B时,才会有实际效果,即A被隐藏,B被显示出来了

不知道为什么第一次无效,有点奇怪
...全文
552 8 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
8 条回复
切换为时间正序
请发表友善的回复…
发表回复
red-fly 2018-02-08
  • 打赏
  • 举报
回复
不知道为什么,上次修改之后好好的,今天突然又出现了第一次切换不了的情况。看了几遍,确认这个位置的代码上次改了之后,后面虽然改了,但逻辑肯定没有变化,原来是两个函数分别写,现在采用了一个函数进行切换,然后由两个函数来调用它,如下
void CMainFrame::ShowBetterView(const int viewIndex)
{
	if (m_curViewIndex == viewIndex)
		return;
	m_pViewList[m_curViewIndex]->ShowWindow(SW_HIDE);
	m_curViewIndex = viewIndex;
	CMyReportView *pView = m_pViewList[m_curViewIndex];  // 两个view都是从我从CListView派生出来的CMyReportView派生出来的
	pView->ShowWindow(SW_SHOW);
	SetActiveView(pView);
	SetWindowLong(pView->m_hWnd, GWL_ID, AFX_IDW_PANE_FIRST);
	RecalcLayout();
}

void CMainFrame::OnShowAview()
{
    ShowBetterView(0);
}
void CMainFrame::OnShowBview()
{
    ShowBetterView(1);
}
以上代码只不过是把两个函数中的写到了一个,逻辑完全没有变化。 检查了几遍,也看不出问题。 由于后面加了一个SetWindowLong(),所以看起来是第一个虽然隐藏,但是没有把它的GWL_ID设置成其它的,所以可能会有影响,于是在CMyReportView的OnCreate()获了GWL_ID,结果两个view的值都是 AFX_IDW_PANE_FIRST! 然后对ShowBetterView()添加一行代码:
	...
	m_pViewList[m_curViewIndex]->ShowWindow(SW_HIDE);
	SetWindowLong(m_pViewList[m_curViewIndex]->m_hWnd, GWL_ID, AFX_IDW_PANE_FIRST + m_curViewIndex + 1);   // 这一行新添加的
	m_curViewIndex = viewIndex;
	...
添加之后,再测试,又恢复正常了。估计这次是真把问题解决了,如果以后没有再回贴,那应该就是没有再出现过这个情况了
red-fly 2018-02-01
  • 打赏
  • 举报
回复
引用 5 楼 schlafenhamster 的回复:
1 看看 m_pViewList[0] 在哪里创建 2 注意 例子 中 // Exchange view's window ID so RecalcLayout() works. SetWindowLong(pNewActiveView->m_hWnd, GWL_ID,AFX_IDW_PANE_FIRST); RecalcLayout();
问题已解决 1. 本来是在CMainFrame::OnCreate() 中调用CreateMoreViews(),但是此时获取GetActiveView()返回NULL,没办法给m_pViewList[0]附值,所以在OnCreate()的结尾向主窗口自己post了一个消息,在这个消息中调用CreateMoreViews()来创建视图B,此时m_pViewList[0]可以成功附值。这一项说明情况,和本次解决没有关系 2. 之前参考的两篇文章似乎没有上面的那一行,所以这次给的参考代码看得不够仔细,这次加上 SetWindowLong(pNewActiveView->m_hWnd, GWL_ID,AFX_IDW_PANE_FIRST); 一行后好了,修改的一个切换到B视图的代码如下:
void CMainFrame::OnShowBview()
{
	m_pViewList[0]->ShowWindow(SW_HIDE);
	m_pViewList[1]->ShowWindow(SW_SHOW);
	SetActiveView(m_pViewList[1]);
	SetWindowLong(m_pViewList[1]->m_hWnd, GWL_ID, AFX_IDW_PANE_FIRST);   // 这一行是参考新盒子添加的
	RecalcLayout();
}
worldy 2018-02-01
  • 打赏
  • 举报
回复
将当前视图隐藏 将pNewActiveView视图创建并显示出来,其父窗口指定为框架窗口 SetWindowLong(pNewActiveView->m_hWnd, GWL_ID,AFX_IDW_PANE_FIRST); 改变要显示视图的ID为AFX_IDW_PANE_FIRST; RecalcLayout();重新布局视图
schlafenhamster 2018-01-31
  • 打赏
  • 举报
回复
1 看看 m_pViewList[0] 在哪里创建 2 注意 例子 中 // Exchange view's window ID so RecalcLayout() works. SetWindowLong(pNewActiveView->m_hWnd, GWL_ID,AFX_IDW_PANE_FIRST); RecalcLayout();
red-fly 2018-01-31
  • 打赏
  • 举报
回复
引用 3 楼 schlafenhamster 的回复:
“先切换到B,无反应“ ,已经show B 了?
是的,你看我那个 OnShowBview() 函数,先隐藏前一个,再show第二个,然后激活
red-fly 2018-01-30
  • 打赏
  • 举报
回复
引用 1 楼 schlafenhamster 的回复:
参考

// CMainFrame message handlers
这和我参考的两个网址逻辑是一样的,都是设置新视图后把旧视图销毁。 而我的不能销毁它,只是隐藏,如果销毁了,则会很麻烦,所有显示的数据都没有了,这样还得保存要显示的数据,这很不好
schlafenhamster 2018-01-30
  • 打赏
  • 举报
回复
“先切换到B,无反应“ ,已经show B 了?
schlafenhamster 2018-01-29
  • 打赏
  • 举报
回复
参考

// CMainFrame message handlers
void CMainFrame::SwitchViews(int ID)
{
	CView* pOldActiveView = GetActiveView();
	CView* pNewActiveView;
	CCreateContext cc;
	cc.m_pCurrentDoc=pOldActiveView->GetDocument();
	CString title=cc.m_pCurrentDoc->GetPathName();;
// which one
	switch (ID)
	{
	case 1://
		pNewActiveView=(CView*) new CWinOh51View;
		title += " Binary View";
		break;
	case 2://
		pNewActiveView=(CView*) new CFormatView;
		title += " Formated View";
		break;
	case 3://
		pNewActiveView=(CView*) new CFlashView;
		title += " Flash View";
		break;
	case 4://
		pNewActiveView=(CView*) new CHexView;
		title += " Hex View";
		break;
	}
// Create new 
	pNewActiveView->Create(0,0,0,CFrameWnd::rectDefault,this,ID,&cc);	
	pNewActiveView->OnInitialUpdate();
	SetActiveView(pNewActiveView);
	pNewActiveView->ShowWindow(SW_SHOW);
// Exchange view's window ID so RecalcLayout() works.
	SetWindowLong(pNewActiveView->m_hWnd, GWL_ID,AFX_IDW_PANE_FIRST);
	RecalcLayout();
//If we use: delete pOldActiveView,
//we got : Warning: calling DestroyWindow in CWnd::~CWnd,
//OnDestroy or PostNcDestroy in derived class will not be called.
	pOldActiveView->DestroyWindow();
// new title
	SetWindowText(title);
}
//
void CMainFrame::OnSwitchViews() 
{
	// TODO: Add your command handler code here
	CView *pOldView=(CView *)GetActiveView();
//CHexView
	if(pOldView->IsKindOf(RUNTIME_CLASS(CWinOh51View)))
	{
		SwitchViews(2);//CFormatView
	}
	else if (pOldView->IsKindOf(RUNTIME_CLASS(CFormatView)))
	{
		SwitchViews(3);//CFlashView
	}
	else if (pOldView->IsKindOf(RUNTIME_CLASS(CFlashView)))
	{
		SwitchViews(4);//CHexView
	}
	else //(pOldView->IsKindOf(RUNTIME_CLASS(CHexView)))
	{
		SwitchViews(1);//CWinOh51View
	}
}

15,980

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC 界面
社区管理员
  • 界面
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧