在SDI或MDI中获得类指针 rstudio mdi sdi
为方便说明,现假设已用Application Wizard生成一个SDI应用程序Test,包含如一几个类:CTestApp,CTestDoc,CTestView,CMainFrm.
1.从视图类获得文档类的指针
在视图类中需要引用文档类的地方之前,使用以下语句:
CTextDoc *pDoc=(CTestDoc*)GetDocument();
以后便可使用pDoc指针访问文档类。
此处的强制类型转换在Test应用程序中并不必需,因为该程序中只有一个视图类,并且在Initstance()中用SDI文档模板进行了装配,你可以在Test.cpp中的Initstance()方法中看到以下语句:
CSingleDocTemplate *pDocTemplate;
pDocTemplate=new CSingleDocTemplate(IDR_MAINFRAME,RUNTIME_CLASS(CTestDoc),RUNTIME_CLASS(CMainFrame),RUNTIME_CLASS(CTestView));
AddDocTemplate(pDocTemplate);
以及TestView.h中的线上定义:
inline CTestDoc* CTestView::GetDocument()
{ return (CTestDoc*)m_pDocument;}
简而言之,就是说CTestView的GetDocument()函数自然而然地认为CTestDoc是与它“相配”的。
2.从文档类取得视图类的指针
CDocument类提供了两个函数用于视图类的定位:GetFirstViewPosition()和GetNextView(),具体语法如下:
virtual POSITION GetFirstViewPosition() const;
virtual CView* GetNextView(POSITION& rPosition) const;
注意:GetNextView()括号中的参数用的是引用方式,因此执行后值可能改变。
GetFirstViewPosition()用于返回第一个视图位置(返回的并非视图类指针,而是一个POSITION类型值), GetNextView()有两个功能:返回下一个视图类的指针以及用引用调动的方式来改变传入的POSITION类型参数的值。很明显,在Test程序中,只有一个视图类,因此只需将这两个函数调用一次即可得到CTestView的指针如下(需定义一个POSITION结构变量来辅助操作):
CTestView* pTestView;
POSITION pos=GetFirstViewPosition();
pTestView=GetNextView(pos);
这样,便可到了CTestView类的指针pTestView.执行完成几句后,变量pos=NULL,这是因为没有下一个视图类.
但是之几条语句太简单,不具有太强的通用性和安全特征;当象前面说的那样,当要在多个视图为中返回某个指定类的指针时,我们需要遍历所有视图类,直到找到指定类为止。判断一个类指针指向的是否某个类的实例时,可用IsKindOf()成员函数时行检查,如:
pView->IsKindOf(RUNTIME_CLASS(CTestView));
即可检查pView所指是否是CTestView类。
有了以上基础,我们已经可以从文档类取得任何类的指针。为了方便,我们将其作为一个文档类的成员函数,它有一个参数,表示要获得哪个类的指针。实现如下:
CView* CTestDoc::GetVieww(CRuntimeClass* pClass)
{
CView* pView;
POSITION pos=GetFirstViewPosition();
while(pos!=NULL)
{
pView=GetNextView(pos);
if(pView->IsKindOf(pClass))
break;
}
if(!pView->IsKindOf(pClass))
return NULL;
return pView;
}
其中用了两次视图类的成员函数IsKindOf()来判断,是因为退出while循环有三种可能:
1.pos为NULL,即已经不存在下一个视图类供操作;
2.pView已符合要求。
3.1和2同是满足。这是因为GetNextView()的功能是将当前视图指针改变成一个视图的位置同时返回当前视图指针,因此pos是pView的下一个视图类的POSITION,完全有可能既是pos==NULL又是pView符合需要。当所需的视图是最后一个视图是最后一个视图类时就如引。因此需采用两次判断。
使用该函数应遵循如下格式(以取得CTestView指针为例):
CTestView* pTestView=(CTestView*)GetView(RUNTIME_CLASS(CTestView));
RUNTIME_CLASS是一个宏,可以简单地理解它的作用:将类的名字转化为CRuntimeClass为指针。
至于强制类型转换也是为了安全特性考虑的,因为从同一个基类之间的指针类型是互相兼容的。这种强制类型转换也许并不必要,但能避免一些可能出现的麻烦。
字串8
3.从一个视图类取得另一视图类的指针
综合1和2,很容易得出视图类之间互相获得指针的方法:就是用文档类作中转,先用1的方法得到文档类的指针,再用2的方法,以文档类的视图定位函数取得另一个视图类。同样,可以实现成一个函数:
(假设要从CTestAView中取得指向其它视图类的指针)
CView* CTestAView::GetView(CRuntimeClass* pClass)
{ CTestDoc* pDoc=(CTestDoc*)GetDocument();
CView* pView;
POSITION pos=pDoc->GetFirstViewPosition();
while(pos!=NULL)
{
pView=pDoc->GetNextView(pos);
if(pView->IsKindOf(pClass))
break;
}
if(!pView->IsKindOf(pClass))字串3
return NULL;
return pView;}
这个函数和2中的GetView()相比,一是多了第一句以取得文档类指针,二是在GetFirstViewPosition()和GetNextView()前加上了文档类指针,以表示它们是文档类成员函数。
有了此函数;当要从CTestAView中取得CTestBView的指针时,只需如下:
CTestBView* pTestbView=(CTestView*)GetView(RUNTIME_CLASS(CTestBView));字串9
4.从主帧窗口类获得视图类指针字串8
对本文所举的Test这各SDI程序来说,这是简单的,只需用CFrameWnd类的GetActiveView()成员函数即可。格式如下:
CFrameWnd::GetActiveView()
但将此函数应用在MDI应用的CMDIFrameWnd为中时,并不象所想的那样获得当前活动子窗口的视图类,而是返回NULL,这是一个要领性问题。在 MDI程序中,CMDIFrameWnd没有和任何视图类发生关系,也就是说没有视图类直接属于它,只有子帧窗口类CMDIChildWnd才是所有子窗口视图类的父窗口。而子帧窗口的父窗口才是CFrameWnd。因此,在MDI程序中获得活动视图类的正确方法应为:先获得活动子帧窗口,再从活动子帧窗口中获得活动视图类。
CMDIChildWnd* pChild=(CMDIChildWnd*)GetActiveFrame(); //获得活动子帧窗口
//或:CMDIChildWnd* pChild=MDIGetActive();;
CMyView* pView=(CMyView*)pChild->GetActiveView();//获得活动子帧窗口的活动视图
5.从视图类中获得主帧窗口类指针:
用函数:CWnd::GetParentFrame()或AfxGetMainWnd();
可达到目的。GetParentFrame()的工作原理是在父窗口链中搜索,直到找到CFrameWnd或其派生类为止,并返回其指针。用法在InfoViewer中有详细介绍。
6.在任何类中获得应用程序类
用MFC全局函数AfxGetApp()可做到。
7.从应用程序类中获得主帧窗口类
CWinThread类有一个数据成员叫m_pMainWnd,由于CWinApp类由CWinThread派生而来,我们的应用程序为又由 CWinApp派生而来,所以我们的CTestApp类也有一个m_pMainWnd成员,它所指南的即是CMainFrame类。(需进行合适的强制类型转换)。
注意以下两点:1.在类A中获得类B的指针时,类A应包含类B的头文件。2.在适当的时候要进行强制类型转换,并要注意括号的括法。特别是由于派生类和父类指针类型兼容,使明确区分各个类变得十分重要,所以在拿不准的时候,最好加上强制类型转换。
1)在View中获得Doc指针 CYouSDIDoc *pDoc=GetDocument();一个视只能有一个文档。 2)在App中获得MainFrame指针 CWinApp中的m_pMainWnd变量就是MainFrame的指针,或者通过以下获得之。 CMainFrame *pMain =(CMainFrame *)AfxGetMainWnd(); 3)在View中获得MainFrame指针 CMainFrame *pMain=(CmaimFrame *)AfxGetApp()->m_pMainWnd; 4) 获得View(已建立)指针方式1:
CMainFrame* pFrame = (CMainFrame*)AfxGetMainWnd(); CYourDocument* yDoc = pFrame->GetActiveDocument(); CYourView* yView = pFrame->GetActiveView();方式2:
CMainFrame *pMain=(CmaimFrame *)AfxGetApp()->m_pMainWnd; CyouView *pView=(CyouView *)pMain->GetActiveView(); 5)获得当前文档指针 CDocument * pCurrentDoc =(CFrameWnd *)m_pMainWnd->GetActiveDocument(); 6)获得状态栏与工具栏指针获得状态栏指针:
CStatusBar * pStatusBar=(CStatusBar *)AfxGetMainWnd()->GetDescendantWindow(AFX_IDW_STATUS_BAR);获得工具栏指针: CToolBar * pToolBar=(CtoolBar *)AfxGetMainWnd()->GetDescendantWindow(AFX_IDW_TOOLBAR); 7)如果框架中加入工具栏和状态栏变量还可以这样 获得状态栏指针: (CMainFrame *)GetParent()->m_wndStatusBar; 获得工具栏指针:
(CMainFrame *)GetParent()->m_wndToolBar; 8)在Mainframe获得菜单指针 CMenu *pMenu=m_pMainWnd->GetMenu(); 9)在任何类中获得应用程序类 用MFC全局函数AfxGetApp()获得。
更多阅读
从来就没有什么救世主——传统出版必须在坚守与变革中前行 世上从来没有救世主
2014年北京国际图书博览会开卷社长论坛演讲从来就没有什么救世主——传统出版必须在坚守与变革中前行(以清华为例)2014.08在新技术快速发展的形势下,传统出版面临着史无前例的挑战与压力。然而,事物总是辨证的。看电影,虽然手机携
SCL-90在心理健康研究中应用的争议 研究生心理健康
(边俊士 井西学 庄 娜) http://www.100md.com 2008年2月1日 《中国健康心理学杂志》【摘要】 目的 分析SCL-90量表在心理健康研究中的应用争议。方法 搜集相关文献,采用内容分析法对相关研究的对象、方法和结果进行综述。结果 SCL
数学论文:浅谈反思在初中数学教学中的重要性
数学论文: 浅谈反思在初中数学教学中的重要性反思既是一种思想,更是一种技术。教学反思对教师的成长极为重要。只有对教学反思有明晰而正确的认识,才能在情感上真正接受反思思想,从而激发反思的内在动力,进而产生具体的反思行为。而数
行政指导在工商执法办案中使用的思考 - - 中国红盾论坛 - |工商论 工商执法办案心得体会
行政指导在工商执法办案中使用的思考近几年来,各级工商机关已不同程度地运用行政指导方式,创造性地解决了监管实践中的一些问题。重庆市工商行政管理局于2009年4月13日出台《重庆市工商行政管理局关于在执法办案工作中开展行政指导的
在EXCEL2007或2010图中添加标准差 excel怎么添加标准差
Excel2007或2010在功能上较2003版本强大许多,但是一些功能键的位置和操作方法发生了一些改变,下面就通过简单的例子介绍一下,如何在Excel 2007或 2010中添加误差线的具体步骤。1、在Excel中输入X,Y和相应的误差值,并对X,Y做图。2、点击