重拾mfc

来源:互联网 发布:收藏宝贝店铺软件 编辑:程序博客网 时间:2024/04/28 06:03

系统保存了什么信息,你就能获取什么信息,在一个窗口的产生过程中,系统会保存它所属的进程,所属的窗

口,以及该窗口自身的信息,如ID,大小等。系统以一个句柄代表此窗口,于是程序就能以此句柄进行一系列

的操作。
MFC的窗口类不过是调用了attach把一个类关联到hwnd而已。但MFC的确是用程序生成代码的一个典型例子,继

承一个MFC类比自己去实现一个窗口类方便得多——写窗口过程函数(WndProc),创建窗口类(WNDCLASS),注

册窗口类(RegisterClass(&wc)),自己实现消息与消息处理函数的匹配——而MFC用几个宏搞定了这一切(或

许可以直接使用MFC的宏)。难能可贵的是,MFC没有扩展C++的内容,所有的功能都是用C++实现(虚函数、动

态绑定、函数重载)。
每个窗口都有一个窗口类,这是在创建时指定的,例如,在SDK中纯手工创建一个button时会为createwindow中

的lpWindowName参数赋值为"BUTTON",这是系统预定义的窗口类,而在mfc中,如果单纯是放一个button在对话

框上而不为其设置控件变量,它也是使用"BUTTON"作为窗口类,而这个窗口类必然有一个系统预定义的WndProc

。所以,让 一个按钮响应WM_MOUSEMOVE 消息,SDK手工编程中要自己重新为"BUTTON"实现一个WndProc

(SetWindowLong改变Button 控件的WndProc)或干脆重新写一个窗口类,而在mfc中,必然也是要换"BUTTON"

的WndProc。在MFC中这变得非常简单了。只要新建一个 基于 CButton 的类,然后在这个类中实WM_MOUSEMOVE

的消息响应函数,就行了。这么简单是因为 MFC 在底层 已经 替换 了 Button的原 WndProc。这分为两种情况

,如果是用代码创建的,它会在创建前挂一个WH_CBT钩子,在钩子回调里面直接把窗口回调换掉,然后卸载钩

子;如果资源里面的,那就是你说的DDX_CONTROL里面,在调用SubclassWindow的时刻把窗口回调换掉了。(别人说的)
那是否可以不为button指定变量而直接在对话框类中响应鼠标滑过button的事件呢?不行。想想消息是怎么派

分的吧——DispatchMessage(CONST MSG *lpmsg),这个函数只有一个消息结构体指针作为参数,而消息结构

体只有hwnd能够指明应该把这个消息送到哪个窗口的WndProc。而默认"BUTTON"的WndProc是不会再把消息与对

话框类建立联系的。当然,就算为button创建一个控制变量,最多也只是能把消息送到CWnd中处理(默认处理

)而已,不会与cdialog发生联系。具体说来是这样的(大致):

CWinThread::PumpMessage(){
GetMessage(&msgCur);

if ( !PreTranslateMessage(&msgCur) ) {

::TranslateMessage(&msgCur);

::DispatchMessage(&msgCur);

}

}=====>>
CWnd::AfxWndProc(hwnd...) {
 CWnd *pWnd = FromHandlePermanent(hWnd );    // pWnd指向一个CButton对象
 ...
 pWnd->WindowProc(nMsg, wParam, lParam);      // WindowProc是一个虚函数
} ======>>
CWnd::WindowProc() {
 if( OnWndMsg(nMsg, wParam, lParam, &lResult) )
  lResult = DefWindowProc(nMsg, wParam, lParam);
 return lResult;
} ======>>
CWnd::OnWndMsg(...) {
 // 在这里完成消息的处理,一般的windows消息先对比本类的消息映射,然后父类,而对于
 // WM_COMMAND和WM_NOTIFY则进行另外的路径
}

原创粉丝点击