导航
  • 主页
  • VC综合技术
  • 互联网技术
  • MFC AppLauncher
  • .NET 技术
  • 界面
  • 进程
  • 算法
  • 硬件/系统
  • 数据库
  • VC++技术资源

请教!如何替换CsplitterWnd中的某个View(快疯了,大侠快来救命)

isis 2004-04-06 07:19:17
CsplitterWnd中需要通过用户在运行期手动决定显示某个View
所有的View都是预先定义好了,保存在CsplitterWnd 中的
CPtrArray m_ptrarrayRCView数组中(其中任意的有多个CView的子类,比如CHtmlView)
用户需要调用CsplitterWnd 中自定义函数
ReplaceView(CRuntimeClass* pRCView),把从m_ptrarrayRCView取出的一个CView类型pRCView把原来的位于CsplitterWnd区域(0, 0)的哪个替换掉
请教大家如何做

我试图通过下面的代码来运行
BOOL Tab_SplitterWnd::ReplaceView(CRuntimeClass* pRCView)
{
CView* pOldView = GetParentFrame()->GetActiveView();
CView* pNewView = (CView*)pRCView;
::SetParent(pNewView->m_hWnd, GetParentFrame()->m_hWnd);
GetParentFrame()->SetActiveView(pNewView);
pNewView->ShowWindow(SW_SHOW);
pOldView->ShowWindow(SW_HIDE);
::SetWindowLong(pNewView->m_hWnd, GWL_ID, AFX_IDW_PANE_FIRST);
RecalcLayout();
return true;
}
但是不行
总是在SetActiveView中的ASSERT(IsChild(pViewNew));中出错
但是我设置了SetParent,不知道为什么

试图通过
BOOL Tab_SplitterWnd::ReplaceView(CRuntimeClass* pRCView)
{
CCreateContext context;
SIZE size;
CRect rect;

CView* pOldView = GetParentFrame()->GetActiveView();
CView* pNewView = (CView*)pRCView;
CDocument* pDoc = pOldView->GetDocument();

context.m_pNewViewClass = pRCView;
context.m_pCurrentDoc = pDoc;
context.m_pNewDocTemplate = pDoc->GetDocTemplate();
context.m_pLastView = NULL;
context.m_pCurrentFrame = GetParentFrame();

pOldView->GetClientRect( &rect );
size.cx = rect.right;
size.cy = rect.bottom;

CreateView( 0, 0, pRCView, size, &context);
GetParentFrame()->SetActiveView(pNewView);

RecalcLayout();
}
但是会出现
TRACE2("Error: CreateView - pane already exists for row %d, col %d.\n",
row, col);的Assertion错误
于是我在CreateView前面加入了pOldView ->DestoryWindow()
但是出现Violation Access错误

...全文
102 点赞 收藏 6
写回复
6 条回复
切换为时间正序
当前发帖距今超过3年,不再开放新的回复
发表回复
byf2002 2004-04-07
数据库开发之窗体编程

作者:李强



下载源代码


  在很多管理信息系统的窗体都有一些共同点:可以通过框架菜单打开各种类型的视图窗口,而这些视图窗口具有MDI的一些特点,可以在框架窗体中最小化最大化还原等,并且点击菜单只能产生一个窗口(象SDI)。这种形式的窗口设计给人与一种条理感。于是我用VC6.0尝试创建这种窗口,现将整个过程为大家写下来,这里应含有MFC的一些内幕技术。

  ㈠、新建AppWizad(exe)工程,名为mdisdi,基于MDI的文档视模式(其余默认)。

  ㈡、在CApp子类中添加如下代码:

  public:
  CMultiDocTemplate* pDoctemp1;
  CMultiDocTemplate* pDoctemp2;
  ㈢、修改InitInstance()中将如下代码:

  CMultiDocTemplate* pDocTemplate;
  pDocTemplate = new CMultiDocTemplate(
IDR_MDISDITYPE,
RUNTIME_CLASS(CMdisdiDoc),
RUNTIME_CLASS(CChildFrame), // custom MDI child frame
RUNTIME_CLASS(CMdisdiView));
AddDocTemplate(pDocTemplate);
  改为:

   //CMultiDocTemplate* pDocTemplate;//删除
pDoctemp1 = new CMultiDocTemplate(
IDR_MDISDITYPE,
RUNTIME_CLASS(CMdisdiDoc),
RUNTIME_CLASS(CChildFrame), // custom MDI child frame
RUNTIME_CLASS(CMdisdiView));
AddDocTemplate(pDoctemp1);
  ㈣、加入新类CDoc2,基类为CDocument(利用菜单Insert-New Class…让其自动生成即可);加入新框架类CChildFrame2,基类为CMDIChildWnd;
加入新视类,这里新加CView2基类为CFormView类(Insert-New Form…),注意在添加对话框中将Document选为CDoc2;

  ㈤同㈢将如下代码:

  CMultiDocTemplate* pNewDocTemplate = new CMultiDocTemplate(
IDR_VIEW2_TMPL,
RUNTIME_CLASS(CDoc2), // document class
RUNTIME_CLASS(CMDIChildWnd), // frame class
RUNTIME_CLASS(CView2)); // view class

AddDocTemplate(pNewDocTemplate);
改为:

  pDoctemp2 = new CMultiDocTemplate(
IDR_VIEW2_TMPL,
RUNTIME_CLASS(CDoc2), // document class
RUNTIME_CLASS(CChildFrame2), // frame class
RUNTIME_CLASS(CView2)); // view class
AddDocTemplate(pDoctemp2);
并在mdisdi.cpp头部添加:

#include "Doc2.h"
  ㈥、修改IDR_MAINFRAME菜单,新添一菜单“功能”,其子菜单为窗口1和窗口2.用ctrl+c复制,ctrl+v粘贴,产生二个新菜单IDR_MAINFRAME1和IDR_MAINFRAME2,再将其更名为IDR_MDISDITYPE,IDR_VIEW2_TMPL.

  ㈦、为IDR_MAINFRAME菜单新添菜单增加消息应射函数OnMenuitem32771()和OnMenuitem32772()

  ㈧、在MainFrm.h加入:

  #include "mdisdiDoc.h"
  #include "Doc2.h"
  并在类中添加:

public:
  CMdisdiDoc * pDoc1;
  CDoc2 * pDoc2;
  在MainFrm.cpp增加代码如下:

  void CMainFrame::OnMenuitem32771()
  {
  // TODO: Add your command handler code here
if(pDoc1==NULL)
{
CMdisdiApp * pmdisdiapp =(CMdisdiApp *)AfxGetApp();
pDoc1=(CMdisdiDoc *)
pmdisdiapp->pDoctemp1->OpenDocumentFile(NULL);
}
else
{
POSITION pos;
pos=pDoc1->GetFirstViewPosition();
CView * pView;
pView=pDoc1->GetNextView(pos);
pView->GetParentFrame()->ActivateFrame();
}
}

 void CMainFrame::OnMenuitem32772()
{
// TODO: Add your command handler code here
if(pDoc2==NULL)
{
CMdisdiApp * pmdisdiapp =(CMdisdiApp *)AfxGetApp();
pDoc2=(CDoc2 *)
pmdisdiapp->pDoctemp2->OpenDocumentFile(NULL);
}
else
{
POSITION pos;
pos=pDoc2->GetFirstViewPosition();
CView * pView;
pView=pDoc2->GetNextView(pos);
pView->GetParentFrame()->ActivateFrame();
}
}
  ㈨、在MainFrm.cpp添加如下代码:

 CMainFrame::CMainFrame()
{
// TODO: add member initialization code here
pDoc1=NULL;
pDoc2=NULL;
}
在ChildFrm.cpp中添加:

  #include "MainFrm.h"
  和如下代码:

 CChildFrame::~CChildFrame()
{
  CMainFrame * pmainwnd=
(CMainFrame *)AfxGetMainWnd();
  pmainwnd->pDoc1=NULL;
}
在ChildFrame2.cpp中添加:

  #include "MainFrm.h"
  和如下代码:

 CChildFrame2::~CChildFrame2()
{
  CMainFrame * pmainwnd=
(CMainFrame *)AfxGetMainWnd();
  pmainwnd->pDoc2=NULL;
}
最后将InitInstance()中如下几行注释掉:

  CCommandLineInfo cmdInfo;
  ParseCommandLine(cmdInfo);

  // Dispatch commands specified on the command line
  if (!ProcessShellCommand(cmdInfo))
  return FALSE;
作用是去掉新建选择视类对话框;

回复
byf2002 2004-04-07
如何切换视口而不破坏它们?

我创建了一个带有静态分隔区的sdi应用程序,左边显示工作区,右过显示左边选取的东西.我想达到的是如果在分隔区之间进行切换,而不覆盖或破坏原来的CView对象.
以下代码是你所想要的:
class CExSplitterWnd : public CSplitterWnd
{
// Construction
public:
CExSplitterWnd();
// Overrides
// ClassWizard generated virtual function overrides
//{{AFX_VIRTUAL(CExSplitterWnd)
//}}AFX_VIRTUAL
// Implementation
virtual ~CExSplitterWnd();
BOOL AttachView(CWnd* pView, int row, int col);
BOOL DetachView(int row, int col);
// Generated message map functions
//{{AFX_MSG(CExSplitterWnd)
// NOTE - the ClassWizard will add and remove member functions here.
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
};
CExSplitterWnd::CExSplitterWnd()
{
}
CExSplitterWnd::~CExSplitterWnd()
{
}
BOOL CExSplitterWnd::AttachView(CWnd* pView, int row, int col)
{
//Make sure the splitter window was created
if (!IsWindow(m_hWnd))
{
ASSERT(0);
TRACE(_T("Create the splitter window before attaching windows to panes"));
return (FALSE);
}
//Make sure the row and col indices are within bounds
if (row >= GetRowCount() || col >= GetColumnCount())
{
ASSERT(0);
return FALSE;
}
//Is the window to be attached a valid one
if (pView == NULL || (!IsWindow(pView->m_hWnd)))
{
ASSERT(0);
return FALSE;
}
pView->SetDlgCtrlID(IdFromRowCol(row, col));
pView->SetParent(this);
pView->ShowWindow(SW_SHOW);
pView->UpdateWindow();
return (TRUE);
}
BOOL CExSplitterWnd::DetachView(int row, int col)
{
//Make sure the splitter window was created
if (!IsWindow(m_hWnd))
{
ASSERT(0);
TRACE(_T("Create the splitter window before attaching windows to panes"));
return (FALSE);
}
//Make sure the row and col indices are
//within bounds
if (row >= GetRowCount() || col >= GetColumnCount())
{
ASSERT(0);
return FALSE;
}
CWnd* pWnd = GetPane(row, col);
if (pWnd == NULL || (!IsWindow(pWnd->m_hWnd)))
{
ASSERT(0);
return FALSE;
}
pWnd->ShowWindow(SW_HIDE);
pWnd->UpdateWindow();
//Set the parent window handle to NULL so that this child window is not
//destroyed when the parent (splitter) is destroyed
pWnd->SetParent(NULL);
return (TRUE);
}
回复
kongyunzhongque 2004-04-07
BOOL Tab_SplitterWnd::ReplaceView(CRuntimeClass* pRCView)
{
CView* pOldView = GetParentFrame()->GetActiveView();
SIZE size;
CRect rect;
pOldView->GetClientRect( &rect );
size.cx = rect.right;
size.cy = rect.bottom;

CDocument* pDoc = pOldView->GetDocument();

CCreateContext context;
context.m_pNewViewClass=pRCView;
context.m_pNewDocTemplate=NULL;
context.m_pCurrentFrame=NULL;
context.m_pLastView=GetPane(0,1);

DeleteView(0, 0);
CreateView( 0, 0, pRCView, size, &context);

GetParentFrame()->RecalcLayout();
RecalcLayout();
SetActivePane(0,0);
return true;
}
回复
isis 2004-04-07
up
回复
isis 2004-04-06
还是不行啊,错误始终存在SetActive***中
以前的错误是SetActiveView,现在是SetActivePane中的ASSERT_VALID(pFrameWnd)出错
顺便贴上改写的
BOOL Tab_SplitterWnd::ReplaceView(CRuntimeClass* pRCView)
{
CView* pOldView = GetParentFrame()->GetActiveView();
SIZE size;
CRect rect;
pOldView->GetClientRect( &rect );
size.cx = rect.right;
size.cy = rect.bottom;

CDocument* pDoc = pOldView->GetDocument();

CCreateContext context;
context.m_pNewViewClass = pRCView;
context.m_pNewDocTemplate = pDoc->GetDocTemplate();
context.m_pCurrentFrame = GetParentFrame();
context.m_pLastView = (CView*)pRCView;

DeleteView(0, 0);
CreateView( 0, 0, pRCView, size, &context);

CView *pviewNew = (CView*)GetPane(0,0);
GetParentFrame()->RecalcLayout();
RecalcLayout();
SetActivePane(0,0);
return true;
}
帮忙看看
回复
kongyunzhongque 2004-04-06
http://expert.csdn.net/Expert/topic/2926/2926832.xml?temp=9.286135E-02
回复
发动态
发帖子
VC/MFC
创建于2007-09-28

1.5w+

社区成员

VC/MFC相关问题讨论
申请成为版主
社区公告

        VC/MFC社区版块或许是CSDN最“古老”的版块了,记忆之中,与CSDN的年龄几乎差不多。随着时间的推移,MFC技术渐渐的偏离了开发主流,若干年之后的今天,当我们面对着微软的这个经典之笔,内心充满着敬意,那些曾经的记忆,可以说代表着二十年前曾经的辉煌……
        向经典致敬,或许是老一代程序员内心里面难以释怀的感受。互联网大行其道的今天,我们期待着MFC技术能够恢复其曾经的辉煌,或许这个期待会永远成为一种“梦想”,或许一切皆有可能……
        我们希望这个版块可以很好的适配Web时代,期待更好的互联网技术能够使得MFC技术框架得以重现活力,……