hur.cn - 华软网

 热门搜索

对话框中嵌入多视图的一种方法 (视图切换)(研究好久没有研究会)

  作者:未知    来源:网络    更新时间:2010/6/2
发现了一个教程,但是弄了半天都不知道为什么做错,大家帮忙一下,我发现我运行的时候有断言错误,在定义SwitchToView函数CView* pOldActiveView = (CView*)pFrame->GetActiveView();出错,还有一个是野指针的问题:OnInitDialog()函数
((CFrameWnd*)this)->SetActiveView(m_pView1);我就发现这个两个问题,不知道是我操作错了,还是什么,你们帮我看看,谢谢,原文如下:

在MFC的SDI和MDI文档结构中能很方便的嵌入多视图,而有时候则要在对话框中嵌入多视图,下面是方法。


1.插入三个对话框
ID分别为IDD_VIEW1_FORM,IDD_VIEW2_FORM,IDD_VIEW3_FORM,把三个对话框的属性Style设为Child,Border设为None,映射CView1,CView2,CView3分别对应三个对话框,CView1,CView2,CView3都派生自CFormView。
2.在对话框中加入三个成员变量:
CView1 *m_pView1;
CView2 *m_pView2;
CView3 *m_pView3;
3.映射对话框WM_INITDIALOG消息,在OnInitDialog()函数中加入创建视图窗口的代码.
(注意一定要用(CView*)把三个成员变量的类型转换成CView*类型,不然调用的就是CFormView::Create,但是CFromView的Create是protected类型,不能调用)
//create view1
m_pView1 = new CView1;
ASSERT(m_pView1 != NULL);

if (!((CView*)m_pView1)->Create(NULL, NULL, WS_CHILD,
   CRect(0, 0, 0, 0), this, NULL, NULL))
{
   AfxMessageBox(_T("Create view1 failed"));
   return TRUE;
}

m_pView1->ShowWindow(SW_HIDE);
m_pView1->OnInitialUpdate();
//create view2
m_pView2 = new CView2;
ASSERT(m_pView2 != NULL);

if (!((CView*)m_pView2)->Create(NULL, NULL, WS_CHILD,
   CRect(0, 0, 0, 0), this, NULL, NULL))
{
   AfxMessageBox(_T("Create view2 failed"));
   return TRUE; 
}

m_pView2->ShowWindow(SW_HIDE);
m_pView2->OnInitialUpdate();
//create view3
m_pView3 = new CView3;
ASSERT(m_pView3 != NULL);

if (!((CView*)m_pView3)->Create(NULL, NULL, WS_CHILD,
   CRect(0, 0, 0, 0), this, NULL, NULL))
{
   AfxMessageBox(_T("Create view3 failed"));
   return TRUE; 
}

m_pView3->ShowWindow(SW_HIDE);
m_pView3->OnInitialUpdate();

//move view in the dialog
CRect rect;
GetWindowRect(&rect);
ScreenToClient(rect);
rect.DeflateRect(200, 0, 0, 0);
m_pView1->MoveWindow(&rect);
m_pView2->MoveWindow(&rect);
m_pView3->MoveWindow(&rect);

((CFrameWnd*)this)->SetActiveView(m_pView1);
m_pView1->ShowWindow(SW_SHOW);
m_pView1->SetDlgCtrlID(AFX_IDW_PANE_FIRST); ...... 

在对话框中按顺序加入三个radio box,在第一个radio box中勾上group选项(三个radio box 靠左边放,注意不要被嵌入的视图覆盖住。

。在映射按钮消息函数中加入SwitchToView函数。(SwitchToView用来切换视图)
void Cxxxxx::OnRadio1()
{
SwitchToView(IDD_VIEW1_FORM);
}

void Cxxxxx::OnRadio2()
{
SwitchToView(IDD_VIEW2_FORM);
}

void Cxxxxx::OnRadio3()
{
SwitchToView(IDD_VIEW3_FORM);
}

SwitchToView的函数定义为:
void Cxxxxx::SwitchToView(UINT uViewID)
{
//the following statement is important!!!
CFrameWnd *pFrame = (CFrameWnd*)this;

//only for debug
ASSERT_VALID(pFrame);
CView *pNewActiveView = NULL;
CView* pOldActiveView = (CView*)pFrame->GetActiveView();

switch(uViewID)
{
case IDD_VIEW1_FORM: 
   pNewActiveView = m_pView1;
   break;
case IDD_VIEW2_FORM: 
   pNewActiveView = m_pView2;
   break;
case IDD_VIEW3_FORM: 
   pNewActiveView = m_pView3;
   break;
default:
   AfxMessageBox(_T("invalid view id"));
   return;
}

ASSERT(pOldActiveView!=NULL && pNewActiveView!=NULL);

if (pNewActiveView == pOldActiveView)
   return;

pNewActiveView->ShowWindow(SW_SHOW);
pOldActiveView->ShowWindow(SW_HIDE);
pFrame->SetActiveView(pNewActiveView);

if (pOldActiveView -> IsKindOf(RUNTIME_CLASS(CView1)))
   pOldActiveView -> SetDlgCtrlID(IDD_VIEW1_FORM);
else if(pOldActiveView -> IsKindOf(RUNTIME_CLASS(CView2)))
   pOldActiveView -> SetDlgCtrlID(IDD_VIEW2_FORM);
else if (pOldActiveView -> IsKindOf(RUNTIME_CLASS(CView3)))
   pOldActiveView -> SetDlgCtrlID(IDD_VIEW3_FORM);
//set the identity of current active view
pNewActiveView -> SetDlgCtrlID(AFX_IDW_PANE_FIRST);
}





---华软 网友回答---
对话框中可以很方便的嵌入frame,frame挂多个view也不难。
---华软网友回复---
引用 1 楼 jennyvenus 的回复:
对话框中可以很方便的嵌入frame,frame挂多个view也不难。
哦,大侠,那你给小弟弄个看看,我弄这个几天了都不知道什么的。
---华软网友回复---
CFrameWnd 和CDialog都是从Cwnd派生出来的
不能CFrameWnd *pFrame = (CFrameWnd*)this(this指针代表对话框)
因为他们属于不同的类,Cwnd* p=(Cwnd*) this;这样是可以的,因为CDialog是从
Cwnd中派生的!

编程的时候,不要人家怎么写,你也跟着怎么写,要理解人家的意图!

根据自己的需要去做!

其实你完全没必要做转换操作,直接保存一个CView * m_pNewActiveView
做全局变量,不就可以了吗?

---华软网友回复---
引用 3 楼 qimiao77 的回复:
CFrameWnd 和CDialog都是从Cwnd派生出来的
不能CFrameWnd *pFrame = (CFrameWnd*)this(this指针代表对话框)
因为他们属于不同的类,Cwnd* p=(Cwnd*) this;这样是可以的,因为CDialog是从
Cwnd中派生的!

编程的时候,不要人家怎么写,你也跟着怎么写,要理解人家的意图!

根据自己的需要去做!

……
CFrameWnd *pFrame = (CFrameWnd*)this  原文作者这样子做的意图是利用CFrameWnd类的GetActiveView()函数来获取当前活动窗口,用SetActiveView()激活新视图,应该是这样子吧……
---华软网友回复---
嗯 这个问题也困扰了很久
每次点击菜单栏中的选项都弹出一个对话框 感觉很挫。。
所以希望能直接在主对话框中根据不同的菜单显示不一样的视图。。。
---华软网友回复---
为啥一定要用视图呢,你直接在主对话框中显示不同的子窗口就好了。
---华软网友回复---
引用 2 楼 wei20041010 的回复:
引用 1 楼 jennyvenus 的回复:
对话框中可以很方便的嵌入frame,frame挂多个view也不难。
哦,大侠,那你给小弟弄个看看,我弄这个几天了都不知道什么的。


俺的程序从网上抄的,这样在dialog中挂了一个frame

C++">int
CCommonScriptDialog::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
if (CDialog::OnCreate(lpCreateStruct) == -1)
{
return -1;
}

// Because the CFRameWnd needs a window class, we will create
// a new one. I just copied the sample from MSDN Help.
// When using it in your project, you may keep CS_VREDRAW and
// CS_HREDRAW and then throw the other three parameters.
CString strMyClass = AfxRegisterWndClass( CS_VREDRAW |
CS_HREDRAW,
::LoadCursor( NULL, IDC_ARROW ),
( HBRUSH )::GetStockObject( WHITE_BRUSH ),
::LoadIcon( NULL, IDI_APPLICATION ) );

// Create the frame window with "this" as the parent
m_pFrame = new CCommonScriptFrame();
m_pFrame->SetID( IDR_TOOLBAR_COMMON_SCRIPT_CN, IDR_TOOLBAR_COMMON_SCRIPT_EN );

m_pFrame->Create( strMyClass, _T( "Common Script Tool View" ) , WS_CHILD,
CRect( 0, 0, 1, 1 ), this );
//m_pFrame->ShowWindow( SW_SHOW );
m_pFrame->MoveWindow( 0, 0, 300, 300 );

return 0;
}

---华软网友回复---
C++">int CConnectScheduleFrame::OnCreate(LPCREATESTRUCT lpCreateStruct) 
{
if (CDialogFrame::OnCreate(lpCreateStruct) == -1)
return -1;

// TODO: Add your specialized creation code here
CCreateContext ccc;
ccc.m_pNewViewClass   = RUNTIME_CLASS( CConnect_Spy_View );
ccc.m_pCurrentDoc     = NULL;
ccc.m_pNewDocTemplate = NULL;
ccc.m_pLastView       = NULL;
ccc.m_pCurrentFrame   = this;

// Because the CFRameWnd needs a window class, we will create
// a new one. I just copied the sample from MSDN Help.
// When using it in your project, you may keep CS_VREDRAW and
// CS_HREDRAW and then throw the other three parameters.
//CString strMyClass = AfxRegisterWndClass( CS_VREDRAW |
// CS_HREDRAW,
// ::LoadCursor( NULL, IDC_ARROW ),
// ( HBRUSH )::GetStockObject( WHITE_BRUSH ),
// ::LoadIcon( NULL, IDI_APPLICATION ) );

m_pView = ( CConnect_Spy_View * )( this->CreateView( &ccc ) );
::SendMessage( m_pView->GetSafeHwnd(), WM_INITIALUPDATE, 0, 0 );

this->SetActiveView( ( CView * )m_pView );
return 0;
}


这样又在frame中加载了一个view,这里是formview,这个view中你想加嵌套再加载一个frame也行,分隔成多个view也行,加载toolbar,状态条等都行。

---华软网友回复---
LZ说问题出在SwitchToView这个函数里,我是新手,不太懂原理,做的时候没用这个函数,把OnRadio()函数
void Cxxxxx::OnRadio1()
{
SwitchToView(IDD_VIEW1_FORM);
}

void Cxxxxx::OnRadio2()
{
SwitchToView(IDD_VIEW2_FORM);
}

void Cxxxxx::OnRadio3()
{
SwitchToView(IDD_VIEW3_FORM);
}

改成
void CXXX::OnRadio1() 
{
m_pView1->ShowWindow(SW_SHOW);
m_pView1->OnInitialUpdate();
}

void CXXX::OnRadio2() 
{
m_pView2->ShowWindow(SW_SHOW);
m_pView2->OnInitialUpdate();
}

void CXXX::OnRadio3() 
{
m_pView3->ShowWindow(SW_SHOW);
m_pView3->OnInitialUpdate();
}

程序就可以运行了。
---华软网友回复---
什么地方有这方面的书可以看,关于FORMVIEW对话框的这个,我也很乱
---华软网友回复---
m_pView1 = new CView1;这一句老出错:
error C2248: 'CView1::CView1' : cannot access protected member declared in class 'CView1'
        view1.h(20) : see declaration of 'CView1::CView1'
---华软网友回复---
对话框嵌入视图类并不难,关键代码只有几句(测试成功的,我经常用):
C++">	m_pView = new CMyView;
if (!m_pView->Create(NULL, NULL, AFX_WS_DEFAULT_VIEW, CRect(0,0,0,0), this, AFX_IDW_PANE_FIRST, NULL))
{
EndDialog(IDABORT);
}
CMyDoc* pDoc = new CMyDoc;//不需要DOC类,注释掉
pDoc->AddView(m_pView);//不需要DOC类,注释掉
m_pView->SendMessage(WM_INITIALUPDATE, 0, 0);
 

不要用SetActiveView(),因为是CFrameWnd的函数,用CDialog盗用这个函数,是会报错的。
切换时只需显示隐藏相应的对象就行了。

---华软网友回复---
另外要用new,必须把构造和析构函数放到public里
---华软网友回复---
http://www.vckbase.com/english/code/splitter/cxysplitter.shtml.htm      
华软声明:本内容来自网络,如有侵犯您版权请来信指出,本站立即删除。