MFC体系结构
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了MFC体系结构相关的知识,希望对你有一定的参考价值。
一、CWndThread类
1.CWndThread类其实就是一个线程封装类,他有两种模式
a.工作者线程,他没有消息循环, 用来做耗时计算,
线程函数 UINT _cdecl MyThreadProc(LPVOID param);
启动线程
AfxBeginThread(线程的入口函数,如果函数参数, 优先级 = 0,栈大小=0,
创建后的状态(挂起或者创建就运行)默认是运行,安全性默认NULL.)
b.UI界面线程,CWinThread派生类,他有Windows消息循环
他的使用发送和工作者则不一样, 他是要你自定义一个类,这个类是继承自
CWinThread。 把这个派生类坐位你 AfxBeginThread 第一个参数。
c.用户界面线程主要是为了消息循环, 这样才能和用户交互,接收鼠标键盘消息.
2.CWinThread 主要方法 派生自线程类的UI界面线程使用
a.virtual BOOL InitInstance(); 程序实例对象初始化 返回真就执行消息循环
b.virtual int ExitInstance(); 退出应用程序实例
c.virtual int Run() 执行消息循环
d.BOOL CreateThread 使用成员方法启动线程,和AfxBeginThread效果一样,按需要使用.
e.DWORD SuspendThread()暂停 DWORD ResumeThread() 恢复
f.int GetThreadPriority() 获取优先级 BOOL SetThreadPriority(int o)设置优先级
g.virtual BOOL IsldleMessage(MSG* pMsg)判断消息是否是空闲消息 WM_TIME也会被当成空闲消息
h.virtual BOOL Onldle(LONg lCount) 处理空闲消息
i.BOOL PreTranslateMessage(MSG* pMsg) 截获消息, 返回TRUE告诉消息循环,这个消息我已经处理了
j.BOOL ProcessMessageFilter(int code,LPMSG lpMsg) 处理消息过滤,针对一个消息数组,
比如要用户输入一个东西,如果他不输入, 我们就过滤鼠标消息, 他就不能移动鼠标了
k.KRESULT ProcessWndProcException(CException*e,const MSG* pMsg);处理函数没有捕获线程或者命令函数抛出的异常
二、CWinApp类和CWinAppEx类
1.CWinApp类继承自 CWinThread 他其实还就是以现场类 他实现了一些方法
a.CWinApp* AFXAPI AfxGetApp(), LPCTSTR AFXAPI AfxGetAppNAme();
b.HINSTANCE AFXAPI AfxGetInstanceHandle() 调用Win32Api要求你传递一个Instance句柄
在16位Windows下 这个句柄非常有用,但是到了32位 意义不大.
c.void AFXAPI AfxSetResourceHandle(HINSTANCE hInstanceResource)
在开发大型国际应用的时候,字符串资源单独放一个动态库里面,通过切换动态库的方法
就可以加载不同字符串,实现多语言的版本.
2.CWinAppEx 是CWinApp的扩展
a.CWinApp类是支持注册表和INI文件读写配置文件
b.CWinAppEx 只能使用注册表了
c.CWinApp void SetRegistryKey(LPCTSTR lpszKey) 设置注册表的key
如果是NULL,那么他就是从INI文件进行读取
d.CWinAppEx 你就必须知道这个key, 如果你不想存取注册表,
就重写 相关的函数就行了.
3.CWinApp文档集合框架
a.AddDocTemplate 是一个列表 应用程序支持文档类型的集合
有多个Template就可以支持多个不同的视图 或者扩展文件
b.GetFirstDocTemplatePosition GetNextDocTemplate 遍历文档模板集合
c.OpenDocumentFile 打开
d.LoadStdProfileSettings 载入了框架窗口用户设置的配置,比如一开始是最大化的
下次打开的时候还是最大化的. 里面会创建主窗口
e.AddToRecentFileList 打开视图的历史
f.RegisterShellFileTypes 注册外壳文件的类型,扩展名文件和你关联,Windows扩展名的文件图标和应用程序相管理的
如果双击这文件,Windows会找到这个程序把他打开, 实现双击打开
g.UnregisterShellFileTypes
注意如果你添加多个文档模板的时候,你选中新建会弹出一个窗口
让用户选择默认新建哪一个类型文档,作为新的模板,这个窗口很难看,
也很讨厌, 如果要改变这个东西,你把OnFileNew里面的这个
CDocManager::OnFileNew() 把这个进行重载, 改变他的行为,
也就是你点击新建的时候,这个函数会检测你Add的文档, 他会遍历DocTemplate
如果类别数量大于1个的时候,就会弹出这个窗口,参考OnFileNew里的函数,把有用的函数拷贝出来即可
三、窗口知识
1.Win32创建一个窗口是最基本的知识,所以就不见了
2.基本的窗口风格
a.重叠窗口(WS_OVERLAPPED)
通常用于简历应用程序主窗口,事实上有时候就叫做主窗口,或框架窗口
b.弹出窗口(WS_POPUP)
通常以对话框和消息框的形式与用户对话
c.子窗口(WS_CHILD)
通常用在View中,比如文本编辑器中文本显示,也用在空间中,比如对话框
的按钮,子窗口也称为"控件"窗口
d.第一种和第二种不能组合,其他的任何风格都可以组合上面的风格
3.三种截获窗口消息的方法
作用:比如Win32按钮很难看,想给他加个图片
想改变这个窗口的行为,就要拦截他的消息,从他本身的窗口
过程把消息截过来,在他的WM_PAINT消息中,绘制一个好看的图片.
a.超类化,替换窗口类的窗口过程,替换没有窗口的窗口类的
窗口过程是纯粹的超类化,如果利用已有窗口找到窗口类替换类
的窗口过程称为全局子类化,
替换系统窗口类的窗口过程之前必须先反注册一下窗口类
b.子类化
替换已有窗口的窗口过程(MFC中只使用这种方式)
c.消息钩子
利用Windows消息钩子截获窗口消息,进来使用前两种方式
来截获窗口消息
d.尽量不使用,防止被杀毒软件防火墙杀死进程.带来不必要的麻烦
e.超类化子类化功能不必消息钩子逊色,消息钩子的好处是拦截另外一个应用
程序的消息的时候就比较方便了,可以全局的拦截应用程序的消息循环.
但是会很消耗系统资源.
f.MFC中其实提供了类型消息钩子的机制,
CWinThread里就有一个消息拦截的APIPreTranslateMessage。可以把他理解成消息钩子.
f.别的进程里的消息结果,仍然可以用超类化或者全局子类化类结果都可以的.
如果你某些特殊的控件行为要特别定制的时候,就可以用子类化.
否则就用PreTranslateMessage进行处理,在WM_PAINT替换按钮风格.
四、CWnd类
1.AfxRegisterClass() AfxRegisterWndClass 注册新窗口类
2.AfxGetMainWnd() 获取当前应用主窗口
3.创建和使用窗口
a.Create CreateEx 创建窗口
b.CreateControl 创建控件
c.FromHandle()通过窗口句柄拿到对应的CWnd对象
e.FromHandlePermanent 通过窗口句柄拿到对应的CWnd 内部会创建临时的窗口变量
用完就自动销毁了.
f.Attach()创建CWnd类或派生类对象,绑定参数的窗口句柄
g.Detach()解除CWnd类或派生类绑定的这个窗口句柄 这个CWnd类的HWND句柄就接触绑定了.
h.ExecuteDlginit()执行对话框的初始化
i.PreCreateWindow()调用CreateWindow之前他会先调用PerCreateWindow
重载了之后在这之前改变窗口的风格,经常用在主框架窗口是否包含最小化按钮这些风格等等.
甚至可以把窗口类都换掉,类名啊什么的.
4. 子类化支持(本质就是替换已有窗口的窗口过程的方法)
子类化主要是用在从CWnd派生的空间中
a.SubClasswindow SubclassDlgItem UnsubClassWindow 反子类化
如果说界面中的很多按钮,让他们换成一种风格,那工作量是很庞大的,
SubClassWindow让人头晕,建议使用超类化来完成这些工作.
或者在APIPreTranslateMessage截获消息的地方
子类化其实也是经常要用的一个技巧,很多时候对Win32的控件加以改变
这样就能做成一自定义的控件.自定义控件就是子类化的方式.
本质上就是一个替换消息映射。
b.PreSubclassWindow 类似 PreCreateWindow
c.GetSafeHwnd()
e.GetStyle GetStyleEx ModifyStyle ModifyStyleEx
f.GetOwner SetOwer
以上是关于MFC体系结构的主要内容,如果未能解决你的问题,请参考以下文章