我用mfc做的一个sdi程序,想实现的功能是把视图分为2部分,左边是一排按钮。点击其中一个右边出现相应的页面。
现在我已经用CSPlietWnd分割视图成功了。添加了一个class CLeftView : public CFormView。代码如下:
BOOL CMainFrame::OnCreateClient(LPCREATESTRUCT lpcs, CCreateContext *pContext)
{
CRect rect;
GetClientRect(rect);
if (!m_wndSplitter.CreateStatic(this,1,2))
return FALSE;
if (!m_wndSplitter.CreateView(0,0,RUNTIME_CLASS(CLeftView),CSize(rect.Width()/4,100),pContext))
return FALSE;
if (!m_wndSplitter.CreateView(0,1,RUNTIME_CLASS(CMy8View),CSize(100,100),pContext))
return FALSE;
return TRUE; }
class CMy8View : public CFormView从向导里直接生成的视图类。
我询问过应该怎么做,大家说是查一个SwitchViewInSplitter 函数。我已经查到了,这个函数的功能应该是切换视图吧。但是我不知道该怎么使用它,是放到CMainFrame里吗?而且我左边有4个按钮,是不是得定义4个视图类啊,上面的代码也需要改动一下呢?请大家指教,谢谢
现在我已经用CSPlietWnd分割视图成功了。添加了一个class CLeftView : public CFormView。代码如下:
BOOL CMainFrame::OnCreateClient(LPCREATESTRUCT lpcs, CCreateContext *pContext)
{
CRect rect;
GetClientRect(rect);
if (!m_wndSplitter.CreateStatic(this,1,2))
return FALSE;
if (!m_wndSplitter.CreateView(0,0,RUNTIME_CLASS(CLeftView),CSize(rect.Width()/4,100),pContext))
return FALSE;
if (!m_wndSplitter.CreateView(0,1,RUNTIME_CLASS(CMy8View),CSize(100,100),pContext))
return FALSE;
return TRUE; }
class CMy8View : public CFormView从向导里直接生成的视图类。
我询问过应该怎么做,大家说是查一个SwitchViewInSplitter 函数。我已经查到了,这个函数的功能应该是切换视图吧。但是我不知道该怎么使用它,是放到CMainFrame里吗?而且我左边有4个按钮,是不是得定义4个视图类啊,上面的代码也需要改动一下呢?请大家指教,谢谢
解决方案 »
- 收藏 不显示删除回复显示所有回复显示星级回复显示得分回复 急!用installshield developer 8.0制作的安装程序为何运行时需要输入密码呢?
- 要想拦截其他进程的消息必须要注入进程吗
- 窗口焦点问题
- 有做过类似QQ或MSN等聊天工具的兄弟请进
- 帮忙看这些宏定义是什么意思。。谢谢
- 如何定时触发一个事件啊??
- 屏幕取词的一些问题
- 熟悉VFW的进来,如何控制视频预览的大小(在线等)
- 心情不好,散分,还有http://expert.csdn.net/Expert/topic/2313/2313811.xml?temp=.2412073
- 常常看到报纸、杂志这个认证,哪个认证的,谁知道为什么要认证?搞vc也要认证么?
- 你们猜猜有没有这个可能性
- 完成端口模型疑问?
//网上摘抄的一段代码,可以参考一下
void SwitchViewInSplitter( CSplitterWnd * pSplitter, int row, int col, CRuntimeClass * pViewClass )
{
///////////////////////////////////////////////////////////
// Replace the current view in the splitter pSplitter
// at pane (row, col) by a new view of class pViewClass
ASSERT_VALID( pSplitter );
ASSERT( pViewClass != NULL ); ASSERT( pViewClass->IsDerivedFrom( RUNTIME_CLASS( CView ) ) ); // 1 - Find the view to be replaced
CWnd *pPaneWnd = pSplitter->GetPane( row, col );
if( !pPaneWnd->IsKindOf( RUNTIME_CLASS( CView ) ) )
{
TRACE2( "Unable to switch: pane (%d,%d) is not a view\n", row, col );
return;
} CView* pCurrentView = static_cast<CView*>( pPaneWnd );
ASSERT_VALID( pCurrentView );
ASSERT_KINDOF( CView, pCurrentView ); if( pCurrentView->IsKindOf( pViewClass ) )
{
// No need to switch for same view class
return;
} // 2 - Store current view position and activation state
CRect rcView;
pCurrentView->GetWindowRect( &rcView ); CView* pActiveView = pSplitter->GetParentFrame()->GetActiveView();
BOOL bSaveActive = ( pActiveView == NULL ) || ( pActiveView == pCurrentView ); // 3 - Find the associated document
CDocument* pDoc = pCurrentView->GetDocument();
ASSERT_VALID( pDoc ); // 4 - Make sure the document won't self-destruct
// when current view is destroyed
BOOL bSaveAutoDelete = pDoc->m_bAutoDelete;
pDoc->m_bAutoDelete = FALSE; // 5 - Destroy the current view
pCurrentView->DestroyWindow(); // 6 - Restore document to initial state
pDoc->m_bAutoDelete = bSaveAutoDelete; // 7 - Initialize creation context used by CreateView()
CCreateContext context;
context.m_pNewDocTemplate = NULL;
context.m_pLastView = NULL;
context.m_pCurrentFrame = NULL; context.m_pNewViewClass = pViewClass;
context.m_pCurrentDoc = pDoc; // 8 - Create the new view
pSplitter->CreateView( row, col, pViewClass,
rcView.Size(), &context ); CView* pNewView = static_cast<CView*>( pSplitter->GetPane( row, col ) );
ASSERT_VALID( pNewView );
ASSERT_KINDOF( CView, pNewView ); // 9 - Position the new view like the old one and
// activate it if needed
pSplitter->ScreenToClient( &rcView );
pNewView->MoveWindow( &rcView, TRUE );
if( bSaveActive )
{
pSplitter->GetParentFrame()->SetActiveView( pNewView );
} // 10 - Send WM_INITIALUPDATE to the view
pNewView->GetParentFrame()->InitialUpdateFrame( pDoc, TRUE );
}
当然得4个视图类,视图相同的话就没有必要切换了。
接着该怎么办呢?我想是不是为左边的一排按钮中每一个按钮都增添一个点击事件啊。在点击事件函数中使用这个SwitchViewInSplitter函数呢?
不过我不太明白这个函数应该怎么用,请大家指教
红色字体是被切换的类名。
void CLeftView::OnXl()
{
SwitchViewInSplitter( &m_wndSplitter_v, 0, 1, RUNTIME_CLASS( CPage2 ) );
}
可是编译有错误;
error C2065: 'SwitchViewInSplitter' : undeclared identifier
F:\8\LeftView.cpp(68) : error C2065: 'm_wndSplitter_v' : undeclared identifier
我把SwitchViewInSplitter'定义到CMainFrame里。在CLeftView的.cpp的文件里也加上了#include "MainFrm.h"了啊。为什么还会说'SwitchViewInSplitter' : undeclared identifier???
2.常规做法,leftview发消息给frame,frame去切换子view。
你的意思是不是并不在按钮事件中调用SwitchViewInSplitter函数。而只是在这个按钮事件里发一个消息给frame,让frame去处理切换子view。
//我觉得你的按钮函数还是放在Mainfrm中比较好。
void CMainfrm::OnXl()
{
SwitchViewInSplitter( &m_wndSplitter, 0, 1, RUNTIME_CLASS( CMy8View) );
}
//我想知道你CPage2是不是一个视图类呢?还是CMy8View里面的一个Tab控件。
//你可以把几个Cpage做成基于CFormView的基类,然后在使用上面的函数切换就可以了。
//如果你是CTabCtrl,就不需要要用切换视图来达到你需要的效果,直接切换就可以了。
m_wndSplitter
m_wndSplitter是怎么定义的啊?
是怎么做到的呢?一般直接就到Cleftview类里了啊,这个按钮是放在Cleftview视图类的啊
BOOL CMainFrame::OnCreateClient(LPCREATESTRUCT lpcs, CCreateContext *pContext)
{
CRect rect;
GetClientRect(rect);
if (!m_wndSplitter.CreateStatic(this,1,2))
//
//就是你在MainFrm.h里面定义的啊
}
//在你这个按钮上面点击右键,然后选择添加添加事件处理程序,在弹出对话框中选择类列表为CMainFrm就可 以了,(2003)如果你是VC6,点击右键以后选择class Wizard,在弹出对话框中的类名种选择CMainframe,选择BN_CLICKED然后点Edit Code就可以了。
//不知上面的方法是否可行,你可以这样实现
//按钮函数还是在Cleftview中。
void CLeftView::OnXl()
{
CMainFrame *pMainFrame=(CMainFrame *)AfxGetApp()->m_pMainWnd;
pMainFrame->SwitchView(1);
}
//在你CMainFrame中定义一个函数:
//mainfrm.h
void SwitchToView(int view);
//mainfrm.cpp
void CMainFrame::SwitchToView(int view)
{
switch(view)
{
case 1: // CPage1
{
SwitchViewInSplitter(&m_wndSplitter,0,1, RUNTIME_CLASS( CPage1) );
break;
}
case 2://CPage2
{
SwitchViewInSplitter(&m_wndSplitter,0,1, RUNTIME_CLASS( CPage2) );
break;
}
//.......
//基本上这样就可以咯。
这样可以得到视图的指针,然后就可以通信了。
CMainFrame* pmainframe=(CMainFrame*)this->GetParent();
Cpage1 *p1 =(cpage1)pmainframe->m_wndspitter.GetPane(0,1);
编译错误如下:
error C2440: 'type cast' : cannot convert from 'class CWnd *' to 'class Cpage1'
No constructor could take the source type, or constructor overload resolution was ambiguous
为什么呢,哪里有错了。
p1->OnBrowse();//
可我发现这个函数是一个afx_msg void OnBrowse();
编译就有问题了 error C2248: 'OnBrowse' : cannot access protected member declared in class 'CMy8View'
这该怎么办?
这个函数代码:
void CMy8View::OnBrowse()
{
CFileDialog fileDlg(TRUE);
if(IDOK == fileDlg.DoModal())
{
GetDlgItem(IDSRCDIR)->SetWindowText(fileDlg.GetPathName());
}
CString dstSrc;
dstSrc = fileDlg.GetPathName();
}
我就想获得这个值dstSrc
//{{AFX_MSG(CMyView)
afx_msg void OnBrowse();
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
编译后有2错误了:
Page2.obj : error LNK2001: unresolved external symbol "public: void __thiscall CMyView::OnBrowse(void)" (?OnBrowse@CMyView@@QAEXXZ)
Debug/8.exe : fatal error LNK1120: 1 unresolved externals
Error executing link.exe.
{...
public:
//{{AFX_MSG(CMy8View)
afx_msg void OnBrowse();
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
};
void CMyView::OnBrowse()
{
CFileDialog fileDlg(TRUE);
if(IDOK == fileDlg.DoModal())
{
GetDlgItem(IDSRCDIR)->SetWindowText(fileDlg.GetPathName());
}
CString dstSrc;
dstSrc = fileDlg.GetPathName();
}
class CPage2 : public CFormView
{
protected:
CPage2(); // protected constructor used by dynamic creation
DECLARE_DYNCREATE(CPage2)// Form Data
public:
//{{AFX_DATA(CPage2)
enum { IDD = IDD_FORM3 };
CWebBrowser2 m_htmlShow;
//}}AFX_DATA// Attributes
public:// Operations
public:
BOOL PreTranslateMessage(MSG *pMsg);
CString ResourceToURL(LPCTSTR lpszURL);
void OnInitialUpdate();// Overrides
// ClassWizard generated virtual function overrides
//{{AFX_VIRTUAL(CPage2)
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
//}}AFX_VIRTUAL// Implementation
protected:
virtual ~CPage2();
#ifdef _DEBUG
virtual void AssertValid() const;
virtual void Dump(CDumpContext& dc) const;
#endif // Generated message map functions
//{{AFX_MSG(CPage2)
afx_msg void OnTj();
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
};
void CPage2::OnTj()
{
CMainFrame* pmainframe=(CMainFrame*)this->GetParent();
CMyView *p1 =(CMyView *)pmainframe->m_wndSplitter.GetPane(0,1);
p1->OnBrowse();//
}