当前位置:首页 » 服务存储 » mfc绘画板虚函数存储
扩展阅读
webinf下怎么引入js 2023-08-31 21:54:13
堡垒机怎么打开web 2023-08-31 21:54:11

mfc绘画板虚函数存储

发布时间: 2023-03-23 12:38:47

‘壹’ 关于MFC中的虚函数的问题

/*
可是在MFC中,只看到在不停地在最底层的子类中override虚函数,如CmyXXX等,却没见着有父类对象的指针向子类对象的转换,相对而言,如果仅仅是为能获得 可以通过子类来访问父类的函数和变量 能力的话,通过继承的机制就完全能办到,塌让不用涉判芹及到虚函数了。
*/

你搞团冲局错了,用虚函数是为了从父类访问子类的函数。

比如你自己定义的一个对话框类,override了几个函数,如OnCreate(), 没用虚函数,就不会调用你的OnCreate(),而调用父类的OnCreate()了。
底层通过一个父类的指针来访问你派生的类。

‘贰’ MFC中的InitInstance()函数应该怎样理解

MFC
中扮镇InitInstance()是应用初始化函数。
1.函厅隐粗数原型:
CWinApp::InitInstance
virtual
BOOL
InitInstance(
);
2.返回值:
如果初始化成功,则返回非零值;否则返回0。
InitInstance函数的返回值为BOOL类型,所谓的BOOL(布尔)类型,在C语言中就是int,携饥它实际就是一个宏定义:
typedef
int
BOOL
通常我们使用BOOL类型来决定“是”以及“否”,“是”就是TRUE,“否”就是FALSE。TRUE和FALSE的值就是1和0,它们也是通过宏来直接定义的常量。
3.深入理解:
MFC对WindowsAPI进行了封装。在用向导编译成的二进时代码,MFC编译器链接器把源文件编译成PE文件格式存储在磁盘上。程序执行的时候,从PE文件头开始执行,在进入Winmain函数之前,进行一系列的必备的初始化。
MFC对这一系列的过程进行了封装。提供给编程人员的第一个裸露程序入口就是CWinApp的InitInstance(),其实程序的入口依然是WinMain()函数。大家都知道,每个程序都有拥有一个进程,每个进程至少有一个线程就是主线程。CWinThread类是MFC用来封装线程的,这个主线程就是在WinMain函数中创建的,包括UI线程和工作者线程。因此每个MFC程序至少使用一个CWinThread派生类。被MFC程序员熟知的CWinApp应用类就从这里派生。
InitInstance是CWinThread的一个虚函数,InitInstance就是“初始化实例”的意思,可见,它是在实例创建时首先被调用的。应用程序总要重载这个虚函数,进行系统设置,创建运行环境。例如,主窗口一定要在InitInstance()中创建,因为该函数退出后就进入该线程的消息循环。
MFC执行流程:
_tWinMain(WinMain的别名,用define替换的)->AfxWinMain->初始化线程,调用InitInstance初始化窗口,调用Run函数进入消息循环。

‘叁’ mfc增加虚函数的作用

虚函数的作用是团段世,父类声明了一个塌肢函数,燃瞎允许子类选择修改或者沿用父类原有的函数。
但如果父类声明了一个纯虚函数,那么编译器就会强制子类实现它,否则编译不通过。

‘肆’ MFC 为什么在VS2005环境下我没找到OnCreateClient()这个虚函数的

OnCreateClient()函拦早数是在OnCreate执行时被框架调用的,函数原型是:
virtual BOOL OnCreateClient(
LPCREATESTRUCT lpcs,
CCreateContext* pContext
);
这个函数是封装在CFrameWnd类中的.在头文件afxwin.h定义,你这个头拦慎文件在#pragma once后应该另简衡雀起一行写#include "afxwin.h"

这个函数一般不调用,函数作用是根据pContext提供的信息创建一个CView对象.
以下是MSDN的资料:
Remarks
Never call this function.

The default implementation of this function creates a CView object from the information provided in pContext, if possible.

‘伍’ mfc为什么许多重写的虚函数内部还是要调用基类的虚函数啊

MFC给销扮御你改写的基类虚函数本身就是已经有一定功能的函数了,而改写不是为了彻底亏岩改变它的方法,而是在此虚函数上增加或自定义一些做法,如果不掉用基类的话缺蠢,那么很多MFC默默帮你做的事情可能就被打断了

‘陆’ MFC中OnDraw和OnPaint的区别

(一) OnPaint 和 OnDraw

(1)OnPaint是WM_PAINT消息的消息处理函数,在OnPaint中调用OnDraw,一般来码前说,用户自己的绘图代码应放在OnDraw中。

(2)OnPaint()是CWnd的类成员,负责响应WM_PAINT消息。OnDraw()是CVIEW的成员函数,没有响应消息的功能.

(3)当视图变得无效时(包括大小的改变,移动,被遮盖等等),Windows发送WM_PAINT消息。该视图的OnPaint 处理函数通过创建CPaintDC类的DC对象来响应该消息并调用视图的OnDraw成员函数.OnPaint最后也要调用OnDraw,因此一般在OnDraw函数中进行绘制。

(4)The WM_PAINT message is sent when function is called.

(5)在OnPaint中,将调用BeginPaint,用来获得客户区的显示设备环境,并以此调用GDI函数执行绘图操作。在绘图操作完成后,将调用EndPaint以释放显示设备环境。而OnDraw在BeginPaint与EndPaint间被调用。

(二) MFC结构

(1)在MFC结构里OnPaint是CWnd的成员函数. OnDraw是CView的成员函数.

(2)OnPaint()调用OnDraw(),OnPrint也会调用OnDraw(),所以OnDraw()是显示和打印的共同操作。

(3)OnPaint是WM_PAINT消息引发的重绘消息处理函数,在OnPaint中会调用OnDraw来进行绘图。

1. OnPaint中首先构造一个CPaintDC类得实例,然后以这个实例为参数来调用虚函数OnPrepareDC来进行一些绘制前的一些处理,比设置映射模式,最后调用OnDraw。

2. OnDraw和OnPrepareDC不是消息处理函数。所以在不是因为重绘消息所引发的OnPaint导致OnDraw被调用时,比如在OnLButtonDown等消息处理函数中绘图时,要先自己调用OnPrepareDC。

(4)至于CPaintDC和CClientDC根本是两回事情:

1. CPaintDC是一个设备环境类,在OnPaint中作为参数传递给OnPrepareDC来作设备环境的设置。

2. 真正和CClientDC具有可比性的是CWindowDC,他们一个是描述客户区域,一个是描述整个屏幕。 如果是对CVIEW或从CVIEW类派生的窗口绘迟祥清图时应该用OnDraw。

(三) OnDraw()和OnPaint()区别

1. 首先:我们先要明确CView类派生自CWnd类。而OnPaint()是CWnd的类成员,同时负责响应WM_PAINT消息。OnDraw()是CVIEW的成员函数,并且没有响应消息的功能。这就是为什么你用VC生成的程序代码时,在视图类只有OnDraw没有OnPaint的原因。而在基于对话框的程序中,只有OnPaint。

2. 其次:要想在屏幕上绘图或显示图形,首先需要建立设备环境DC。其实DC是一个数据结构,它包含输出设备(不单指你的纯屏显示器,还包括打印机之类的输出设备)的绘图属性的描述。MFC提供了CPaintDC类和CWindwoDC类来实时的响应,而CPaintDC支持重画。当视图变得无效时(包括大小的改变,移动,被遮盖等等),Windows 将 WM_PAINT 消息发送给它。该视图的OnPaint 处理函数通过创建 CPaintDC 类的DC对象来响应该消息并调用视图的 OnDraw 成员函宴孝数。通常我们不必编写重写的 OnPaint 处理成员函数。

///CView默认的标准的重画函数
voidCView::OnPaint()//见VIEWCORE.CPP
{
CPaintDCdc(this);
OnPrepareDC(&dc);
OnDraw(&dc);//调用了OnDraw
}
///CView默认的标准的OnPrint函数
voidCView::OnPrint(CDC*pDC,CPrintInfo*)
{
ASSERT_VALID(pDC);
OnDraw(pDC);//CallDraw
}

既然OnPaint最后也要调用OnDraw,因此我们一般会在OnDraw函数中进行绘制。下面是一个典型的程序。

///视图中的绘图代码首先检索指向文档的指针,然后通过DC进行绘图调用。
voidCMyView::OnDraw(CDC*pDC)
{
CMyDoc*pDoc=GetDocument();
CStrings=pDoc->GetData();
GetClientRect(&rect);//ReturnsaCStringCRectrect;
pDC->SetTextAlign(TA_BASELINE|TA_CENTER);
pDC->TextOut(rect.right/2,rect.bottom/2,s,s.GetLength());
}

3.最后:现在大家明白这哥俩之间的关系了吧。因此我们一般用OnPaint维护窗口的客户区(例如我们的窗口客户区加一个背景图片),用OnDraw维护视图的客户区(例如我们通过鼠标在视图中画图)。当然你也可以不按照上面规律来,只要达到目的并且没有问题,怎么干都成。

4. 补充:我们还可以利用Invalidate(),ValidateRgn(),ValidateRect()函数强制的重画窗口,具体的请参考MSDN的CWnd::Invalidate.

5. OnDraw中可以绘制用户区域。OnPaint中只是当窗口无效时重绘不会保留CClientDC绘制的内容。

(四)、这两个函数有区别也有联系:

1、区别:OnDraw是一个纯虚函数,定义为virtual void OnDraw( CDC* pDC ) = 0;而OnPaint是一个消息响应函数,它响应了WM_PANIT消息,也是是窗口重绘消息。

2、联系:我们一般在视类中作图的时候,往往不直接响应WM_PANIT消息,而是重载OnDraw纯虚函数,这是因为在CVIEW类中的WM_PANIT消息响应函数中调用了OnDraw函数。如果在我们自己定义的类CMYVIEW中响应了WM_PAINT消息,不显式地调用OnDraw函数的话,是不会在窗口重绘的时候调用OnDraw函数的(显式调用必须自己准备设备环境( CDC *pDC=GetDC(); OnDraw(pDC); ).)。

3、应用程序中几乎所有的绘图都在视图的 OnDraw 成员函数中发生,必须在视图类中重写该成员函数。(鼠标绘图是个特例,这在通过视图解释用户输入中讨论。)

4、OnDraw 重写: 通过调用您提供的文档成员函数获取数据。 通过调用框架传递给 OnDraw 的设备上下文对象的成员函数来显示数据。 当文档的数据以某种方式更改后,必须重绘视图以反映该更改。默认的 OnUpdate 实现使视图的整个工作区无效。当视图变得无效时,Windows 将 WM_PAINT 消息发送给它。该视图的 OnPaint 处理函数通过创建 CPaintDC 类的设备上下文对象来响应该消息并调用视图的 OnDraw 成员函数。

5、想象一下,窗口显示的内容和打印的内容是差不多的,所以,一般情况下,统一由OnDraw来画。窗口前景需要刷新时,系统会会调用到OnPaint,而OnPaint一般情况下是对DC作一些初始化操作后,调用OnDraw()。

6、OnEraseBkGnd(),是窗口背景需要刷新时由系统调用的。明显的一个例子是设置窗口的背景颜色(你可以把这放在OnPaint中去做,但是会使产生闪烁的现象)。至于怎么界定背景和前景,那要具体问题具体分析了,一般情况下,你还是很容易区别的吧。

(五)

OnPaint()用来响应WM_PAINT消息,视类的OnPaint()内部根据是打印还是屏幕绘制分别以不同的参数调用OnDraw()虚函数。所以在OnDraw()里你可以区别对待打印和屏幕绘制。 其实,MFC在进行打印前后还做了很多工作,调用了很多虚函数,比如OnPreparePrint()等。

对于OnDraw():This method is called by the framework to render an image of the document. The framework calls this method to perform screen display, printing, and print preview, and it passes a different device context in each case. There is no default implementation.

‘柒’ mfc类向导中为何找不到我要重写的虚函数

类向导只是提供了一些常用的会被重写的虚函数,如果所有的虚函数都列出来的话,要去遍历该类的整个继承,太多又麻烦锋扰也没有必要。
直接把虚函数拷贝到自己的类银中旦里面重培段新实现就行了。类向导一般用得少,都是自己加。

‘捌’ 谁帮忙介绍一下mfc里OnDrawItem这个函数以及其参数谢谢了。

afx_msgvoidOnDrawItem(intnIDCtl,);
Parameters
nIDCtl
存储发送WM_DRAWITEM 消息的控件ID,如果是菜单发送的,nIDCtl 的值为0。
lpDrawItemStruct
一个指向DRAWITEMSTRUCT 结构体的指针,该结构体保存有关要被绘制的项目与绘制所需要的类型等星系。
Remarks
当自绘按钮(owner-draw button),下拉列表框(combo box),列表框(list box)视觉属性,或者菜单发生变化时,框架为他们的owner调用该函数。
DRAWITEMSTRUCT结构的itemAction 成员定义了要进行的绘制操作行为。该值确定了所需的绘制动作。
在处理完此消息之前,应用程序应当确保由DRAWITEMSTRUCT 结构的成员hDC 标识的设备上下文还原到默认状态。
如果上面结构的成员hwndItem 指向CButton,CMenu,CListBox或者CComboBox 对象,那么就调用相应类的DrawItem 虚函数。重载相应类的DrawItem 成员函数来绘制各个项。
OnDrawItem()这个函数是自已去绘画一个控件,根据你想要的形状,图案.它是建立一个控件的外表而用到的

可以这样理解,OnDrawItem是画窗口中的子控件的,因为它的入口参数LPDRAWITEMSTRUCT带入不同子控件的相关参数,而且,你得把字控件设置成“自画”类型,才会调用到OnDrawItem,顺便说一下自画,不是所有设置成自画类型的控件都会调用父窗口的OnDrawItem,例如ListBox的自画,你就必须重载CListBox的DrawItem方法和MeasureItem方法才可以,但象菜单,按钮等的自画则会调用OnDrawItem。OnPaint和OnDrawItem不在一个范畴内,他是WM_PAINT的响应函数,凡是基于CWnd的类都有OnPaint事件发生,就是说凡是窗口都有WM_PAINT事件发生。

‘玖’ MFC的CWinApp的构造函数是怎么调用虚函数InitInstance()的

谁告诉你App类的构造函数会调用InitInstance了?这个说法是不对的。
MFC框架,有一个APPMODUL模式,每次运行找_tWinMain函数,这个函数调用MFC的全局函数AfxWinMain,在这个函数中创建肆搭App类并调用InitInstance入口虚函数,完成初始化。
构造函数和裂樱拿入颂橡口函数没有调用关系。

‘拾’ 关于MFC里面的afxwinmain()函数具体实现

深入浅早庆灶出MFC中应该讲的很清楚,不过我看过了陆扮好几年了,你肯定会了,我是最近看的这本书,里面是这样说的,也算是我自己的理解哈!
首先,MFC程序先执行到TheApp实例化对象也就是通过这句CTestApp the App来实例化对象的
然后,调用CTestApp构造函数分配内存空间

然后,就调用了AfxWinMain函数(这个是MFC/SRC下的源码,安装软件后电脑上会有,跟踪也会跟踪的到)
然后,AfxWinMain指向AfxWinInit()函数
然后差好,AfxWinMain执行InitApplication,这个地方InitApplication是虚函数,调用的是CWinApp::InitApplication
然后,AfxWinMain指向InitInstance,在这里面调用了CTestFrameWnd的构造函数,产生了主窗口
然后,显示窗口,更新窗口发送标准消息WM_PAINT
最后回到AfxWinMain,执行run函数,进入消息循环