MFC是怎样封装API函数的
请用浅显易懂的方式说下MFC是怎样封装窗口和消息的。多一些注释,附图就更好了。拈花小仙 发表于 2013-11-28 02:29 static/image/common/back.gif
想通过学习MFC,做了实例,了解SDK中到底有多少库函数,看他们是怎么应用的,也有助于SDK编程吧?我不懂, ...
认真看windows程序设计5,认真看这一本书抵得上其它的10本书。用SDK写界面不难,你觉得难的话,去看MFC肯定觉得更难。只要看明白了,一般的小问题就能自己解决了,至于示例,相信此书上的实例你还有很多没搞明白,不然怎么会觉得SDK写很难呢?
MFC写小程序开发速度不一定比得上SDK,灵活性显然更差。 http://pan.baidu.com/share/link?shareid=1898614691&uk=1513950714 深入浅出mfc
建议看下这本书吧,是讲mfc的经典。
http://pan.baidu.com/share/link?shareid=1918448307&uk=1513950714windows程序设计
如果看不懂建议先看windows程序设计。 窗口的封装
mfc底层有个窗口基类叫CWnd, 前台见到的窗口都是继承与他, 这个类的模型简单点可以如下表示
class CWnd
{
public
BOOL CreateEx(......); //具体参数参考windowsapi CreateEX
void ShowWindows(int sw_cmdLine); //具体参考CWnd::ShowWindows
void UpdateWindows(); //更新窗口
private:
HWndm_hWnd; //窗口句柄
}
所以这类更像是一个带有窗口句柄的管理类.
特别注意!!! 哪怕内部m_hwnd的窗口销毁了。 该类对象还是存在的.
窗口消息处理
简单的windows消息是如下伪代码表示
while(&msg)
{
case WM_KEYDOWN:
dosomething;
case WM_CREATE
dosomethin;
......
}
但是如果mfc也类似写的话。那么Cwnd类要写一堆的虚函数,来对应每个消息的处理。
这个显然不科学。所以mfc有自己的一套消息机制,
原理: mfc会在启动之后,在进程中建立类名和句柄的映射关系,假如前台在a界面上点击了左键
那么会发送消息体, 里面句柄是a的句柄, 这个时候mfc会根据句柄找到消息a的类, 然后在a.h和a.cpp中
查看
DECLARE_MESSAGE_MAP()段
和
BEGIN_MESSAGE_MAP(CADlg, CDialogEx)
END_MESSAGE_MAP()
段
是否有该消息的处理时间,如果有,则按事件处理,否则按默认的处理.
- -~ 都是大神.我楼上的太猛了....我还么入门呢!~:shock: 风のQ 发表于 2013-11-22 09:06 static/image/common/back.gif
窗口的封装
mfc底层有个窗口基类叫CWnd, 前台见到的窗口都是继承与他, 这个类的模型简单点可以如下表示
...
呵呵,对于MFC刚产生时期的电脑来说,速度非常慢,所以将消息处理实现为虚函数会导致处理速度严重下降。但是,现在计算机速度快了,经得起这一点的性能损耗,所以反而显得MFC的做法不合时宜了。
诸如:
DECLARE_MESSAGE_MAP()段
和
BEGIN_MESSAGE_MAP(CADlg, CDialogEx)
END_MESSAGE_MAP()
这些宏,是非常招人讨厌的。因为这不是C++语言,利用宏来搞一套自己的语言有意思么?有意思的话还不如不用C++来完成那个这个任务,刚崔换种语言不是更好么? 仰望天上的光 发表于 2013-11-22 21:12 static/image/common/back.gif
呵呵,对于MFC刚产生时期的电脑来说,速度非常慢,所以将消息处理实现为虚函数会导致处理速度严重下降。但 ...
也许有这些原因在里面, 到那时不得不说,他的这套框架式属于扩展性较好的,假如后期新增了windows消息,他不用改动这套框架,假如是每个消息对应虚函数。则需要新增消息应对函数,这在代码后期维护上还是有点麻烦的。 风のQ 发表于 2013-11-22 21:52 static/image/common/back.gif
也许有这些原因在里面, 到那时不得不说,他的这套框架式属于扩展性较好的,假如后期新增了windows消息, ...
不用改?不增加windows消息,MFC只要处理任何消息都要改。比如在
BEGIN_MESSAGE_MAP(CADlg, CDialogEx)
END_MESSAGE_MAP()之间写一堆的Onxxx这些就是对程序的修改,只不过是利用宏的特性使得这些修改看起来很小而已。
事实上,MFC废弃C++的虚拟函数表不用,自己在很多类里添加消息转发功能(其实就是添加static 元素取代原来的C++虚函数表),并以几个宏维护这些功能,这本身就像是在自己创建一个新的语言。既然要花如此大的代价来实现这样的功能,只能说明,C++语言不适合MFC的这种框架。 去看windowsAPI接口,函数,编程实例,其实就是把API封装进类里面 把鼠标移到代码上按F12多看看是怎么封装的 我有一个分析MFC的源码的教程然后自己实现的教程 你加我发给你 本帖最后由 拈花小仙 于 2013-11-26 13:13 编辑
杞人 发表于 2013-11-23 21:23 static/image/common/back.gif
我有一个分析MFC的源码的教程然后自己实现的教程 你加我发给你
加QQ吗?小金鱼的我看过,看不懂 windows 程序设计 仰望天上的光 发表于 2013-11-22 23:48 static/image/common/back.gif
不用改?不增加windows消息,MFC只要处理任何消息都要改。比如在
BEGIN_MESSAGE_MAP(CADlg, CDialogEx)
...
你这样说也对。只能说我们能看到的问题,微软肯定也能看到,但是到了vs2010还是那套框架。总归是有他的道理的。也许我还认识不到位吧。。。 没加好友权限。不好意思了。 你对类和类的三态熟悉程度怎么样?
我觉得mfc已经是对类的三态运用的很经典的例子了。
要熟悉mfc先从学习类和类的三态开始, 在这之后你再去看一些大神的教学讲解视频比较好. 风のQ 发表于 2013-11-26 08:47 static/image/common/back.gif
你对类和类的三态熟悉程度怎么样?
我觉得mfc已经是对类的三态运用的很经典的例子了。
封装 继承 多态吗?还是不懂怎么封装的 拈花小仙 发表于 2013-11-26 13:14 static/image/common/back.gif
封装 继承 多态吗?还是不懂怎么封装的
额。所有想到出来的dlg或者view或者啥的都是继承自CWnd的,CWnd只是放了接口供你实现自己的事情而已,
要不你在把问题具体点。。。是指窗口类的内部结构,比如成员变量或函数什么的? 还是一个窗口的初始化过程?。。。 风のQ 发表于 2013-11-26 13:50 static/image/common/back.gif
额。所有想到出来的dlg或者view或者啥的都是继承自CWnd的,CWnd只是放了接口供你实现自己的事情而已,
要 ...
嗯嗯,想知道内部怎么初始化的,消息怎么映射的,最好把主要代码拿出来,多一些注释 拈花小仙 发表于 2013-11-26 13:52 static/image/common/back.gif
嗯嗯,想知道内部怎么初始化的,消息怎么映射的,最好把主要代码拿出来,多一些注释
// 类声明, 自建一个窗口类并让这个窗口显示.
class CMyFrame : public CWnd
{
DECLARE_DYNAMIC(CMyFrame )
public:
CMyFrame ();
virtual ~CMyFrame ();
protected:
DECLARE_MESSAGE_MAP()
afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);
private:
//此处放一些自己要在窗口上放的元素, 比如button声明的
};
int CMyFrame ::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
//下面是根据继承原理, 构造子类前,先构造父类
if (CWnd::OnCreate(lpCreateStruct) == -1)
return -1;
//此处是自己创建的窗口的私有元素的初始化
//TODO
return 0;
}
//调用生成代码。在App实例类中进行
CMyFrame * pFrame = new CMyFrame ();
// 上句生成自己的窗口对象(严格说是管理类), 此时对象中的m_hwnd句柄为空,但是可以初始化自己的变量
也就是调用类中的Create函数
pFrame->CreateEx(0,
_T("CFRAME"),
_T("Test"),
WS_POPUPWINDOW | WS_MAXIMIZEBOX | WS_MINIMIZEBOX | WS_THICKFRAME ,
0,0,100,100,NULL,NULL
);
//上句开始做初始化过程.CreateEx为子类CWnd拥有, 所以开始调用CWnd的CreateEx函数
//一下代码在Wincore.cpp中。c++目录下自己找找
BOOL CWnd::CreateEx(DWORD dwExStyle, LPCTSTR lpszClassName,LPCTSTR lpszWindowName, DWORD dwStyle,
int x, int y, int nWidth, int nHeight,
HWND hWndParent, HMENU nIDorHMenu, LPVOID lpParam)
{
ASSERT(lpszClassName == NULL || AfxIsValidString(lpszClassName) ||
AfxIsValidAtom(lpszClassName));
ENSURE_ARG(lpszWindowName == NULL || AfxIsValidString(lpszWindowName));
// allow modification of several common create parameters
CREATESTRUCT cs;
cs.dwExStyle = dwExStyle;
cs.lpszClass = lpszClassName;
cs.lpszName = lpszWindowName;
cs.style = dwStyle;
cs.x = x;
cs.y = y;
cs.cx = nWidth;
cs.cy = nHeight;
cs.hwndParent = hWndParent;
cs.hMenu = nIDorHMenu;
cs.hInstance = AfxGetInstanceHandle();
cs.lpCreateParams = lpParam;
if (!PreCreateWindow(cs)) //注意这个函数,就是我们可以实现的虚函数,可以干一些创建之前要干的事情,比如自己注册窗口.
{
PostNcDestroy();
return FALSE;
}
AfxHookWindowCreate(this);
HWND hWnd = ::AfxCtxCreateWindowEx(cs.dwExStyle, cs.lpszClass, //此处创建窗口.
cs.lpszName, cs.style, cs.x, cs.y, cs.cx, cs.cy,
cs.hwndParent, cs.hMenu, cs.hInstance, cs.lpCreateParams);、
。。。略。
}
pFrame->ShowWindow(SW_SHOW); //显示自己的窗口
pFrame->UpdateWindow(); //更新自己的窗口.
页:
[1]
2