矿泉水敷脸有什么作用| 巴扎是什么意思| 喝酒眼睛红是什么原因| 送枕头代表什么意思| 男人要吃什么才能壮阳| 公关是什么工作| 尿液少是什么原因| 如何看五行缺什么| 吃什么食物下奶快而且奶多| 龚自珍是什么朝代的| 潜血十一是什么意思| 南昌有什么好吃的| 什么叫慢性萎缩性胃炎| 小孩睡觉磨牙是什么原因| 女性白带发黄是什么原因| 为什么明星整牙那么快| 彩超无回声是什么意思| 金字旁的字有什么| 宝批龙是什么意思| 尐是什么意思| other是什么品牌| 香茅是什么| 什么不见| 碰到蛇是什么征兆| 木耳炒什么好吃| 99年属什么| 上大厕拉出血是什么原因| 金光是什么生肖| 为什么养鱼养单不养双| 天地始交是什么意思| 震颤是什么症状| 蛋皮痒痒是什么病| 肝左叶囊肿是什么意思| 腰果不能和什么一起吃| 心驰神往是什么意思| 手肘黑是什么原因| 四风指什么| 双手麻木是什么原因| 梦见好多蛇是什么预兆| 2025年是什么命| 左手小手指麻木是什么原因引起的| 梦见做手术是什么意思| 吃什么容易长肉| 绿色大便是什么原因| 月经老提前是什么原因| 碳酸氢钠有什么作用| 葡萄籽什么牌子效果好| 紫米和黑米有什么区别| 腰间盘突出挂什么科室| 征信对个人有什么影响| 银饰发黑是什么原因| 什么的头发| 海马炖什么好小孩长高| 梦见喝水是什么意思| 面部提升紧致做什么效果最好| 大腿痛挂什么科| 什么油炒菜好吃又健康| 脂肪肝吃什么水果好| 84年是什么命| 中国中铁是做什么的| 国树是什么树| 晚上咳嗽是什么原因| 44岁月经量少是什么原因| 疖肿是什么样子的图片| 中性粒细胞百分比低是什么原因| 舌苔有裂纹是什么原因| 樱桃不能和什么一起吃| crp高是什么原因| 反流性食管炎吃什么药好| 属鼠的是什么命| 小孩呕吐是什么原因引起的| 高考450分能上什么学校| 水中毒是什么| 麦粒肿挂什么科| 财神叫什么名字| 油价什么时候上涨| 出汗多是什么原因| 为什么喝牛奶会拉肚子| 老实人为什么总被欺负| 为的笔顺是什么| 胎儿没有胎心是什么原因| 一劳永逸什么意思| 牛的尾巴有什么作用| 寸金难买寸光阴什么意思| 蛞蝓是什么| 什么才叫幸福| 电器发生火灾用什么灭火器| 三月三是什么星座| 什么花好看| 亚麻酸是什么东西| 屈原为什么投江| dbp是什么意思| ace是什么| 肩膀骨头响是什么原因| 体内湿气重是什么原因造成的| 不见棺材不落泪是什么生肖| 脂肪肝吃什么药效果好| 三个十念什么| 炸酱面的酱是什么酱| 籍贯一般填什么| 猜忌是什么意思| 牙齿出血是什么病征兆| 纤维瘤挂什么科| 1月25号是什么星座| 北上广是什么意思| 白细胞十一是什么意思| 龙眼什么时候成熟| 紫苏叶有什么作用| 经常嗓子疼是什么原因| 什么是耳石症| 双花是什么中药| 长期喝山楂水有什么好处和坏处| 老年人腿浮肿是什么原因引起的| 男人喝藏红花有什么好处| 211是什么学校| 党工委书记是什么级别| 中药为什么那么苦| 乙肝核心抗体阳性是什么意思| 虎鼠不结亲是什么意思| 熬夜后吃什么恢复元气| 肛裂擦什么药膏| 嗓子疼可以吃什么水果| 刘德华属什么生肖| 儿童心肌酶高有什么症状| 腰椎退行性变是什么病| 老虎头是什么牌子衣服| 肝部有阴影一般都是什么病| 小孩咳嗽吃什么药好| 帕金森病是什么症状| 铖字五行属什么| 黄芪什么季节喝最好| 尿道口痛什么原因| 右束支传导阻滞是什么意思| 皮肤暗黄是什么原因造成的| lot是什么| 女同什么意思| 心什么肉什么| 感冒发烧挂什么科| 北京为什么是首都| 跳蚤什么样| 胸口疼痛吃什么药| M3什么意思| 蛊惑什么意思| 喝牛奶放屁多是什么原因| 洁白丸治什么类型胃病| 什么的老虎| 处理是什么意思| 血小板减少是什么原因造成的| 血糖高有什么危害| 亨特综合症是什么病| 脑梗死吃什么药| 孕妇喝什么汤| 鸡血藤手镯有什么功效| 肝内多发钙化灶是什么意思| 艾灸为什么不能天天灸| 芦荟有什么功效| 新生的什么| 什么情况下要打破伤风针| 赵子龙属什么生肖| 巨蟹座与什么星座最配| 姨妈安全期是什么时候| 白色虫子是什么虫图片| 讲师是什么职称| 吃什么水果祛斑最快| 挪威用什么货币| 易蒙停是什么药| 龟苓膏不能和什么一起吃| 胶原蛋白有什么作用| 肾结石少吃什么食物| 喉咙痒咳嗽吃什么药好| 肠胃炎吃什么药| 吃什么治白头发| 调和油是什么油| 小孩老咳嗽是什么原因| 梦见自己杀人了是什么意思| xanax是什么药| 祈福是什么意思| 六块钱的麻辣烫是什么意思| 孕吐 吃什么| 吃冰糖有什么好处和坏处| 上火为什么会牙疼| 备考是什么意思| 眼睛胀痛什么原因| 饺子什么馅好吃| 舌吻是什么感觉| pao2是什么意思| 人心果什么时候成熟| 爱因斯坦发明了什么| 金钱能买来什么但买不来什么| 什么属相不适合养鱼| 有点想吐是什么原因| 什么虫子有毒| 冠状动脉ct检查什么| 犹太人为什么不受欢迎| 莫名其妙什么意思| 上岸了是什么意思| 雨落心尘是什么意思| 4月19是什么星座| 括约肌是什么| 高粱是什么粮食| 喜欢穿黑色衣服的女人是什么性格| 月经不调有什么症状| 胎盘位于后壁是什么意思| 姜维属什么生肖| 饭圈是什么意思| 倒模是什么意思| 馐什么意思| 什么原因造成耳鸣| 脸颊两边长痘痘是什么原因引起的| 3岁小孩不会说话是什么原因| 宝宝为什么吐奶| 生理反应是什么意思| 梦见大水牛是什么兆头| 乳酸脱氢酶高是什么原因| 电商属于什么行业| 尺寸是什么意思| 筋膜炎是什么症状| 大人吃什么排黄疸快| 什么是血铅| 118号是什么星座| 吃了虾不能吃什么| 考级有什么用| 膈应什么意思| pab是什么意思| 官鬼是什么意思| 痰有腥臭味是什么原因| 梦见弟弟是什么意思| 天然是什么意思| 高铁上不能带什么东西| 杜牧号什么| ep是什么| 蜱虫最怕什么药| 人为什么怕蛇| 梦房子倒塌什么预兆| 厉兵秣马什么意思| 什么头什么面| 心火旺吃什么中药| 普洱茶属于什么茶类| 重庆为什么叫重庆| 开柙出虎是什么意思| 月经不规律是什么原因| 心脏在什么位置图片| 太平天国失败的根本原因是什么| 一剪梅是什么意思| 吃是什么意思| 怀孕16周要做什么检查| 蝴蝶兰什么时候开花| 肚脐是什么穴位| 脱节是什么意思| 喝酒之前吃什么保护胃| 阴茎勃起不硬吃什么| 齐耳短发适合什么脸型| 中国第一长洞是什么| 鲜章是什么意思| 梦见和老公吵架是什么预兆| 女装大佬什么意思| 儿茶酚胺是什么| 阑珊处是什么意思| 贵州有什么美食| 喉咙痛去药店买什么药| 鼻鼽病是什么意思| 狗狗呕吐吃什么药| 马蜂窝治什么病最好| mini是什么车| 百度跳转到内容

《中华人民共和国监察法(草案)》(摘要)-政策解读-时政频道-中工网

本页使用了标题或全文手工转换
维基百科,自由的百科全书
百度 技术的辐射是一方面,人才的培养是影响更深远的部分,我们正在向浙江大学申请,争取早日开设康复医学系,专门培养康复人才。

微软基础类库(英语:Microsoft Foundation Classes,简称MFC)是一个微软公司提供的类库(class libraries),以C++类的形式封装了Windows API,并且包含一个(也是微软产品的唯一一个)应用程序框架,以减少应用程序开发人员的工作量。其中包含的类包含大量Windows句柄封装类和很多Windows的内置控件和组件的封装类。

特性

[编辑]

Visual C++包含MFC应用程序向导,可用于兼容MFC的应用程序[1]。在ATL程序中也可以手动添加MFC支持[2]。在向导中有各种选项以定制生成的程序的功能,例如界面风格、语种、数据库开发支持、打印支持、自动化支持、ActiveX支持、网络支持、基于HTML的帮助文档支持等等。

COM开发方面,相对于ATL来说,MFC的组件比较大,代码不够短小精悍,但是支持的功能也比较多,例如有对ActiveX Document的封装类[3]

在界面开发方面,MFC提供对消息循环的封装,使用消息映射来避免虚函数的开销。MFC也提供常用Windows通用控件的封装类。

MFC扩展DLL的接口使得MFC程序可以直接调用MFC扩展DLL中的MFC类。MFC也支持在标准DLL中被使用。

发展

[编辑]

MFC是在1992年随微软的Microsoft C/C++ 7.0编译器发布的,用于面向16位Windows的软件开发。起初,MFC是作为一个应用程序框架开发的,所以定名为Application Framework eXtensions(AFX)。[4]

随着.NET框架的发布,曾经一度被微软重点推荐的MFC被Visual Basic .NETC#Windows Forms抢走了不少市场份额,但是MFC继续在非托管软件开发中占据重要地位。在托管开发方面,MFC中也包括对Windows Forms和托管/非托管互操作的封装。微软在Windows VistaWindows 7发布之后在MFC中增加了对新的Windows API支持[5][6]

MFC的优点

[编辑]

MFC的主要优点是可以用面向对象的方法来调用Windows API,以及能够更加便捷地开发应用程序。MFC将很多应用程序开发中常用的功能自动化,并且提供了文档框架视图结构和活动文档这样的便于自定义的应用程序框架。同时,在Visual C++内部也内置了很多对MFC的例如类向导这样的支持以减少软件开发的时间,使用类向导可以快速生成Hello World程序。

MFC的缺点

[编辑]

虽然MFC的源代码对用户是完全开放的,但是MFC的一些封装过程过于复杂,以致于新用户很难迅速掌握MFC的应用程序框架,以及在调试中定位问题的位置。同时,很多MFC对象不是线程安全的,致使在跨线程访问MFC对象时需要编写额外的代码。另外,MFC的很多类依赖于应用程序向导生成的代码,使得在使用Visual C++中其他类型的应用程序向导生成的工程中添加MFC支持的难度大大增加。

第三方支持

[编辑]

很多商用类库在MFC的基础上进一步实现了皮肤、渐变风格、多顶层窗口程序、属性列表等较受欢迎的功能;同时,在C++在线社区中,很大一部分开放的源代码也是基于MFC的。

版本

[编辑]
产品 程序库 版本 发布日期
名称 版本
Microsoft C/C++ 7.0 mafxcw.lib MFC 1.0 1992
Microsoft Visual C++ 1.0 Visual C++ 1.0 mfc200.dll MFC 2.0
Visual C++ 1.5 mfc250.dll MFC 2.5
Visual C++ 1.51 mfc250.dll MFC 2.51
Visual C++ 1.52c mfc250.dll MFC 2.5 ( Windows 3.x 的最后发展平台 )
Microsoft Visual C++ 2.0 Visual C++ 2.0 mfc30.dll MFC 3.0
Visual C++ 2.1 mfc30.dll MFC 3.1
Visual C++ 2.2 mfc30.dll MFC 3.2
Microsoft Visual C++ 4.0 Visual C++ 4.0 mfc40.dll MFC 4.0 (mfc40.dll 包含于 Windows 95) 1995年8月
Visual C++ 4.1 mfc40.dll MFC 4.1
Visual C++ 4.2 mfc42.dll MFC 4.2 (mfc42.dll 包含于 Windows 98 初版) 1998年3月
内含于 Visual C++ 3.0 mfc42.dll MFC 4.2
Microsoft Visual C++ 5.0 Visual C++ 5.0 mfc42.dll MFC 4.21, 是 MFC 4.2 的主要更新
Microsoft Visual C++ 6.0 Visual C++ 6.0 mfc42.dll MFC 6.0 1998年
内含于 Visual C++ 4.0 mfcce400.dll MFC 6.0
Microsoft Visual C++ .NET 2002 Visual C++ .NET 2002 (Visual C++ 7.0) mfc70.dll MFC 7.0 2025-08-05
Microsoft Visual C++ .NET 2003 Visual C++ .NET 2003 (Visual C++ 7.1) mfc71.dll MFC 7.1 2025-08-05
Visual C++ .NET 2003 + MS11-025 (KB2465373)[7] MFC 7.10.6119.0 2025-08-05
Microsoft Visual C++ 2005 Visual C++ 2005 (Visual C++ 8.0) mfc80.dll 8.0.50727.42 2025-08-05
Visual C++ 2005 SP1 8.0.50727.762 2025-08-05
Visual C++ 2005 SP1 + MS09-035 (KB973544)[8][9] 8.0.50727.4053 2025-08-05
Visual C++ 2005 SP1 + MS11-025 (KB2467175)[7] 8.0.50727.5592 2025-08-05
Visual C++ 2005 SP1 + MS11-025 (KB2538242)[7][10] 8.0.50727.6195 (包含于 redist 8.0.61000/8.0.61001[11]) 2025-08-05
Microsoft Visual C++ 2008 Visual C++ 2008 (Visual C++ 9.0) mfc90.dll 9.0.21022.8 2025-08-05
Visual C++ 2008 + MS09-035 (KB973551)[8][9] 9.0.21022.218 2025-08-05
Visual C++ 2008 含Feature Pack 9.0.30411 2025-08-05
Visual C++ 2008 SP1 9.0.30729.1 2025-08-05
Visual C++ 2008 SP1 + MS09-035 (KB973552)[8][9] 9.0.30729.4148 2025-08-05
Visual C++ 2008 SP1 + MS11-025 (KB2467174)[7] 9.0.30729.5570 2025-08-05
Visual C++ 2008 SP1 + MS11-025 (KB2538243)[7] 9.0.30729.6161 (安装程序版本 9.0.30729.5677) 2025-08-05
Microsoft Visual C++ 2010 Visual C++ 2010 (Visual C++ 10.0) mfc100.dll 10.0.30319.1 2025-08-05[12]
Visual C++ 2010 + MS11-025 (KB2467173)[7] 10.0.30319.415 2025-08-05
Visual C++ 2010 SP1 10.0.40219.1 2025-08-05
Visual C++ 2010 SP1 + MS11-025 (KB2565063)[7] 10.0.40219.325 2025-08-05
Microsoft Visual C++ 2012 Visual C++ 2012 (Visual C++ 11.0) mfc110.dll 11.0.50727.1 2025-08-05
Visual C++ 2012 Update 1 11.0.51106.1 2025-08-05
Visual C++ 2012 Update 3 11.0.60610.1 2025-08-05
Visual C++ 2012 Update 4 11.0.61030.0 2025-08-05
Microsoft Visual C++ 2013 Visual C++ 2013 (Visual C++ 12.0) mfc120.dll 12.0.21005.1 2025-08-05
Visual C++ 2013 Update 2 12.0.30501.0 2025-08-05
Visual C++ 2013 Update 5 + KB3138367 12.0.40649.5 2016年2月?
Visual C++ 2013 Update 5 + KB3179560 12.0.40660.0 2025-08-05[13]
Visual C++ 2013 Update 5 + KB4032938 12.0.40664.0 2025-08-05[14]
Microsoft Visual C++ 2015 Visual C++ 2015 (Visual C++ 14.0) mfc140.dll 14.0.23026.0 2025-08-05
Visual C++ 2015 Update 1 14.0.23506.0 2025-08-05[15]
Visual C++ 2015 Update 2 14.0.23918.0 2025-08-05[16]
Visual C++ 2015 Update 3 14.0.24210.0 2025-08-05[17]
Visual C++ 2015 Update 3 14.0.24212.0 2025-08-05
Visual C++ 2015 Update 3 + KB3165756 14.0.24215.1 2025-08-05[18]
Microsoft Visual C++ 2017 Visual C++ 15.0 mfc140.dll 14.10.25008.0 2025-08-05
Visual C++ 15.1? 14.10.25017.0 2025-08-05?
Visual C++ 15.2 14.11.25325.0 2025-08-05
Visual C++ 15.4 14.12.25810.0 2025-08-05
Visual C++ 15.6 14.13.26020.0 2025-08-05
Visual C++ 15.7 14.14.26405.0 2025-08-05
Visual C++ 15.7.3? 14.14.26429.4 2025-08-05
Visual C++ 15.8 14.15.26706.0 2025-08-05
Visual C++ 15.9 14.16.27012.6 2025-08-05
Visual C++ 15.9.5 14.16.27024.1 2025-08-05
Visual C++ 15.9.6 14.16.27026.1 2025-08-05
Visual C++ 15.9.9 14.16.27027.1 2025-08-05
Visual C++ 15.9.15 14.16.27033.0 2025-08-05
Microsoft Visual C++ 2019 Visual C++ 16.0.0 mfc140.dll 14.20.27508.1 2025-08-05?
Visual C++ 16.1.0 14.21.27702.2 2025-08-05
Visual C++ 16.2.0 14.22.27821.0 2025-08-05
Visual C++ 16.3.0 14.23.27820.0 2025-08-05
Visual C++ 16.4.0 14.24.28127.4 2025-08-05
Visual C++ 16.5.0 14.25.28508.3 2025-08-05
Visual C++ 16.6.0 14.26.28720.3 2025-08-05
Visual C++ 16.6.3 14.26.28808.1 2025-08-05
Visual C++ 16.7.0 14.27.29016.0 2025-08-05
Visual C++ 16.7.5 14.27.29112.0 2025-08-05
Visual C++ 16.8.0 14.28.29325.2 2025-08-05
Visual C++ 16.8.2 14.28.29334.0 2025-08-05
Visual C++ 16.9.0 14.28.29910.0 2025-08-05
Visual C++ 16.9.2 14.28.29913.0 2025-08-05
Visual C++ 16.9.4 14.28.29914.0 2025-08-05
Visual C++ 16.10.0 14.29.30037.0 2025-08-05
Visual C++ 16.10.2 14.29.30038.0 2025-08-05
Visual C++ 16.10.4 14.29.30040.0 2025-08-05
Visual C++ 16.11.0 14.29.30133.0 2025-08-05
Visual C++ 16.11.4 14.29.30135.0 2025-08-05
Microsoft Visual C++ 2022 Visual C++ 17.0.0RC mfc140.dll 14.30.30704.0 2025-08-05
  • 1 Visual Studio速成版(Express)不包含MFC程序库。
  • 2 Feature Pack只用于英文版本的Visual Studio 2008。非英文版本的支持于将包含于Visual Studio 2008 Service Pack 1。

MFC的结构

[编辑]

作为一个应用程序的开发框架,必须满足各方面的功能需求。

应用程序启动

[编辑]

基于MFC开发的应用程序在启动时,Windows操作系统:

  1. 首先调用WinMain函数(位于appmodul.cpp中,封装到mfc80.dll(VS2005版)),WinMain函数内调用了AfxWinMain函数。
  2. AfxWinMain函数(位于WinMain.cpp中)调用了
    1. 该应用程序自定义的App类(这个类派生于CWinApp的,CWinApp又是派生于CWinThread,因此代表了应用程序的主线程)的InitInstance函数,该函数注册并创建窗口(通过AppUI2.cpp中的ProcessShellCommmand函数),然后ShowWindow、UpdateWindow;
    2. CWinThread的InitInstance函数;
    3. CWinThread的Run函数(位于thrdcore.cpp中)。该函数内部是Windows的消息循环。 当应用程序收到WM_QUIT消息后,CWinThread::Run函数返回,紧接着CWinThread::ExitInstance被调用,该函数可被覆盖。程序至此退出运行。 消息循环是一个for(;;)的死循环,该死循环内部包含了一个do...while的循环结构。while循环条件是调用PeekMessage函数的返回值,如果当前UI线程消息队列为空就返回到外层的死循环;while循环体内做两件事:
      1. PumpMessage()。实际调用AfxInternalPumpMessage函数实现其功能:GetMessage()、AfxPreTranslateMessage()、TranslateMessage()、DispatchMessage().即:从UI线程消息队列移除一条消息、遍历该消息的CWnd类直到该窗口的各级别父窗口的CWnd类以提供预处理该消息的机会、如果该消息是按键消息则翻译为WM_CHAR消息、把该消息给相应的窗口函数。
      2. IsIdleMessage():实际调用了AfxInternalIsIdleMessage函数,对于WM_PAINT、WM_SYSTIMER、以及光标位置没有变化的WM_MOUSEMOVE或WM_NCMOUSEMOVE,为Idle Message。
    4. 各个窗口函数(WndProc)内部首先获取对应当前窗口句柄的CWnd类的指针,然后调用AfxCallWndProc函数。

应用程序结束

[编辑]
  • 如果是点击了IDOK按钮,默认是调用OnOK(),然后是OnDestory(),最后是PostNcDestroy()
  • 如果点击IDCANCEL按钮,默认调用OnCancel(),然后是OnDestory(),最后是PostNcDestroy()
  • 如果点击右上角的关闭按钮:先OnClose(),然后是OnCancel(),再然后是OnDestory() ,最后是PostNcDestroy()

消息循环与消息映射

[编辑]
MFC Class hierarchy for Windows message process flow

消息分类

[编辑]
分类 消息 映射宏 消息处理函数原型 注释
系统消息 标准Windows消息 MFC使用专用的相关的宏。如ON_WM_CREATE() MFC使用专用的消息处理成员函数 一般地由窗口对象来处理这类消息
命令消息 WM_COMMAND ON_COMMAND(id, memberFxn) void OnXXX () 通过标识符ID来区分来自哪个菜单项、工具栏按钮或者加速键等
ON_COMMAND_RANGE(id, idLast, memberFxn) void OnXXX (UINT id) 批量处理一定范围内的标示符ID
ON_UPDATE_COMMAND_UI(id, idLast, memberFxn) void OxXXX(CCmdUI* pCmdUI) 程序空闲时发的界面更新消息的宏
ON_UPDATE_COMMAND_UI_RANGE(id, idLast, memberFxn) void OxXXX(CCmdUI* pCmdUI)
ON_CONTROL(id, idLast, memberFxn) void OnXXX () 父窗口响应控件发送的消息
ON_CONTROL_RANGE(id, idLast, memberFxn) void OnXXX (UINT id)
ON_CONTROL_REFLECT(id, idLast, memberFxn) void OnXXX () 子控件响应父窗口反射回来的通知消息
通知消息WM_NOTIFY ON_NOTIFY(wNotifyCode,id,memberFxn) afx_msg void memberFxn(NMHDR * pNotifyStruct, LRESULT* result) wParam为控件ID,lParam指向NMHDR结构体,结构体的code域值为控件通知码用来表示控件上的动作,如NM_CLICK.一般地由父窗口对象来处理这类消息。
ON_NOTIFY_RANGE( wNotifyCode, id, idLast, memberFxn ) 可手工添加(class wizard不支持),处理控件id连续的一批控件的同一通知码消息。
ON_NOTIFY_EX 允许通知消息在多处被处理
ON_NOTIFY_EX_RANGE
ON_NOTIFY_REFLECT afx_msg void memberFxn(NMHDR * pNotifyStruct, LRESULT* result) 复杂子控件响应父窗口反射回来的通知消息
自定义消息 窗口类内部自定义消息WM_USER到WM_APP-1 ON_MESSAGE(消息名,memberFxn) afx_msg LRESULT OnMyMessageXXX(WPARAM wParam, LPARAM lParam) 示例
程序内部自定义消息WM_APP到0xBFFF ON_THREAD_MESSAGE(WM_THREADMSG,OnThreadMessage) afx_msg void OnThreadMessage(WPARAM wParam,LPARAM lParam); 示例
ON_REGISTERED_THREAD_MESSAGE afx_msg void OnMyRegisterdThreadMsg(WPARAM, LPARAM); RegisterWindowMessage()使用一个字符串来登记一个自定义的消息ID
应用程序之间自定义消息0xC000到0xFFFF ON_REGISTERED_MESSAGE LRESULT OnMyMessageXXX(WPARAM wParam, LPARAM lParam) RegisterWindowMessage()使用一个字符串来登记一个自定义的消息ID,便于跨进程应用

控件的通知消息与反射消息

[编辑]

窗体上的控件,应当向父窗体通报控件发生的各种事件,如被点击、绘制、内容改变等等,称为通知消息(notification message )。在 Windows 3.x的16位程序设计时代,控件向父窗体发送WM_COMMAND消息,由父窗体的代码负责实现这些事件。其中wParam的低16位是 control ID,高16位是notification code (例如BN_CLICKED);lParam是控件句柄。因此,再无可能传递其它信息给父窗体。为此,为传递具有特别内容的控件事件,Windows 3.x定义了一批特殊的通知消息(notification messages):

  • WM_PARENTNOTIFY:子窗口的某些重大事件发生时通知父窗口,包括创建、销毁、鼠标各键按下等事件
  • 子窗口的滚动情况的通知消息
    • WM_VSCROLL
    • WM_HSCROLL
  • 子窗口的绘制通知消息
    • WM_DRAWITEM,
    • WM_MEASUREITEM,
    • WM_COMPAREITEM,
    • WM_DELETEITEM,
    • WM_CHARTOITEM,
    • WM_VKEYTOITEM
    • WM_CTLCOLOR:设置按钮、编辑框、ListBox、Static、滚动条控件与MessageBox、DialogBox的前景色、背景色、背景模式、字体,并返回一把Brush,用于控件背景绘制。

早于4.0版本的MFC,在控件类提供了虚函数处理这些通知消息,这一办法已经被下述的“消息反射”取代(但仍然向后兼容继续支持)。

随着Windows 95开始了32位程序时代,伴之而来的是Win32 API 与 MFC 4.0。 Win32增加了很多复杂的控件,需要使用更多的通知消息传递很多复杂的数据给父窗体。Win32 API仅仅增加了一个消息WM_NOTIFY,就实现了这些功能。lParam参数开头是NMHDR数据结构,其后是与该通知类型相关的特定数据结构。

typedef struct tagNMHDR {
    HWND hwndFrom;
    UINT idFrom;
    UINT code;
} NMHDR;

CWnd::OnNotify函数处理通知消息。它的默认实现是检查消息映射表(message map)查找通知的处理器函数并调用。一般说来,不必覆盖OnNotify;而应该写一个处理器函数并增加为该窗口类的消息映射表条目。

 ON_NOTIFY(wNotifyCode, id, memberFxn)

成员函数应该写为:

 afx_msg void memberFxn(NMHDR* pNotifyStruct, LRESULT* result);

MFC 4.0提供了一种特性“消息反射”(message reflection),[19]允许控件通知消息既可以在父窗口中,也可以在控件中被处理。可以对控件创建一个派生的控件类,实现对从父窗口反射回来的指定类型消息的处理。消息反射是MFC而不是Win32的特性,因此父窗口的类必须是从CWnd派生,从而父窗口在CWnd::OnNotify函数中处理控件的WM_NOTIFY时,首先调用CWnd::ReflectLastMsg把消息反射回控件的CWnd::SendChildNotifyLastMsg函数去处理;ReflectLastMsg返回值就是在控件的消息映射中使用ON_NOTIFY_REFLECT_EX()声明的反射消息处理函数的返回值,可以通知父窗口该消息是否已经被控件处理。控件的CWnd::SendChildNotifyLastMsg函数,首先获得线程的最后一条message,然后调用发送窗口的虚函数OnChildNotify函数。在子窗口处理反射回来的控件消息,第一种方法是重载控件窗口的OnChildNotify虚函数;第二种办法是由CWnd::OnChildNotify默认处理去调用CWnd::ReflectChildNotify函数,进入控件子窗口的MFC消息映射的标准处理(子窗口处理的消息被译成WM_REFLECT_BASE+WM_NOTIFY消息)。对于WM_NOTIFY,仅当在控件的消息映射(message map)中,控件没有通过ON_NOTIFY_REFLECT()声明的反射消息处理函数,父窗口的相应的通知消息处理函数才会被调用(在父窗口消息映射中使用宏ON_NOTIFY声明)。控件中通过ON_NOTIFY_REFLECT_EX()声明的反射消息处理函数可以返回真或假,以决定父窗口是否继续处理该通知消息。WM_NOTIFY以外的其它通知消息,父窗口在第一时间有机会处理它,控件对它的处理排在第二位。反射消息处理函数通常使用特定的名字,对应的消息反射宏的名字是在消息名字加上前缀ON_,后缀_REFLECT。如WM_CTLCOLOR对应ON_WM_CTLCOLOR_REFLECT。但以下三种情况,反射消息处理函数可以随意自行起名,对应的消息反射宏的名字分别为:

  • WM_COMMAND使用ON_CONTROL_REFLECT
  • WM_NOTIFY使用ON_NOTIFY_REFLECT
  • ON_UPDATE_COMMAND_UI使用ON_UPDATE_COMMAND_UI_REFLECT

消息传递处理机制

[编辑]

MFC类体系中,Windows消息传递处理机制是基于CCmdTarget类及其派生类的静态成员函数GetThisMessageMap()内部定义的静态数据成员:

  • 成员类型为AFX_MSGMAP_ENTRY的数组_messageEntries。在类的实现文件中,在BEGIN_MESSAGE_MAP与END_MESSAGE_MAP之间的内容来初始化消息映射入口项数组。
  • 数据类型为AFX_MSGMAP的变量messageMap。该结构包含两项,分别是直接基类GetThisMessageMap函数指针与本类的_messageEntries数组首元素地址。

头文件的类定义中使用宏DECLARE_MESSAGE_MAP()来声明静态成员函数GetThisMessageMap与虚函数GetMessageMap

用户所写的类的Windows消息处理函数(例如OnCommand)必须转换为CCmdTarget::*的成员函数指针类型AFX_PMSG,保存在该类的_messageEntries数组中。

struct AFX_MSGMAP_ENTRY
{
	UINT nMessage;   // windows消息代号
	UINT nCode;      // WM_NOTIFY的控制代码
	UINT nID;        // WM_COMMAND下面的ID号,如果为其他的消息,则这个数字为0
	UINT nLastID;    //和前面的ID一起组成一个范围,用于发送一次消息,处理执行多次
	UINT nSig;       // 标志消息处理函数的类型
	AFX_PMSG pfn;    // 函数调用指针
};
typedef void (CCmdTarget::*AFX_PMSG)(void);

调用用户类中该消息处理函数时,根据该函数保存在_messageEntries中的signature(一个无符号整型表示的函数的形参类型列表与返回值类型),把类型为void (CCmdTarget::*AFX_PMSG)(void)的成员函数指针强制转为其它类型的CCmdTarget成员函数指针(例如void (AFX_MSG_CALL CWnd::*pfn_v_i_i)(int, int),目前在union MessageMapFunctions中列出了近百种CCmdTarget成员函数指针),然后调用转换后的成员函数指针。这是基于Visual C++编译器把单继承的成员函数指针编译为只保存了函数的内存起始地址,因此可以在同一个单继承类中把一种类型的成员函数指针强制转换为另一种成员函数指针,或者把单继承派生类的成员函数指针强制转换为基类成员函数指针。这是打破了C++标准的违例办法。例如,对于CWnd::OnCommand函数,转换过程是:

BOOL (CWnd::*)(WPARAM, LPARAM lParam) => void (CWnd::*)() => void (CCmdTarget::*)()

CString

[编辑]

CString是MFC中最常见的类之一,用于封装字符串数据结构。它只有一个数据成员m_pszData,其值为字符串的首地址,其数据类型为wchar_t*或char*。在CString的m_pszData的前面实际还分配了CSringData数据块,包含了管理数据:

IAtlStringMgr* pStringMgr; 
int nDataLength; 
int nAllocLength; 
int nRefs;

自底向上,CAtlStringMgr提供内存管理,CStringData提供共享管理,CString提供字符串操作。

CAtlStringMgr的一个成员是IAtlMemMgr接口,这是策略模式,可以引用某个内存管理类。CAtlStringMgr的另一个成员是CNilStringData。

因此,每次为CString动态分配地址空间,实际分配长度为:(nChars+1)*nCharSize+sizeof(CStringData)。通过 Attach 操作,将这个 CStringData* 与 CSimpleStringT::m_pszData 执行了关联。当执行CString的默认构造函数生成一个空串时,实际上都是构造一个CnilStringData对象。CNilStringData 派生自 CStringData,额外拥有一个 achNil 的数组成员,这个数组初始化为空字符串。通过这个 achNil,保证了一个经过调用默认构造函数初始化的 CString,其指向的真正的字符串是一个空串。

部分编译器对std::string放弃了写时复制(Copy On Write)机制。但是,CString一直采取这一机制。CSimpleStringT::Fork 函数就提供了这样一个操作,具体分为下面几步:

  1. 根据传入的一个长度分配一段新的空间;—— Allocate(nLength, ...)
  2. 把旧数据拷贝到新的空间里面;—— CopyChars(...)
  3. 旧数据块的引用技术减1; —— pOldData->Release()
  4. 把 m_pszData 和新的数据块关联起来。—— Attach(pNewData)

GetString方法返回的是只读的字符串地址;而GetBuffer方法返回的是可写的字符串地址(如果数据区是共享的,则写时复制),如果修改了字符串内容,这时需要调用ReleaseBuffer方法把新的字符串长度修改到元数据中(并在尾部增加2个0字节)。[20]

CString对象用作可变参数函数(如printf)的实参时,由于无法通过形参类型确定调用哪个CString的类型转换操作符函数,因此有必要显式指明要转换的类型。如果需要在函数的参数传递CString,由于CString使用了引用计数,因此函数参数传递一个CString对象是可行的;不需要修改其内容时,推荐使用const CString&。

支持MFC的DLL开发

[编辑]

使用Visual C++可以开发3种DLL:

  • 不使用MFC的DLL;
  • 使用MFC的规则的DLL:输出的函数不涉及MFC,因此可以被支持/不支持MFC的应用程序调用该DLL
    • 动态链接到MFC(Regular DLLs dynamically linked to MFC)。
    • 静态链接到MFC(Regular DLLs statically linked to MFC)
  • 使用MFC的扩展DLL(Extension DLLs),只能动态链接到MFC:输出的函数涉及MFC,也可以输出基于MFC的派生类。

由于DLL与调用它的应用程序都可以有自己的MFC全局数据与句柄映射(handle mapping),如果句柄值相同,则默认使用应用程序的映射到的资源。为了不互相干扰,允许DLL内部使用自己的资源,必须在DLL函数的入口处把资源模块句柄从默认的应用程序切换为该DLL。办法是:

  1. 在该DLL的每个输出的函数的最开始之处调用AFX_MANAGE_STATE(AfxGetStaticModuleState( ))[21]。函数AfxGetStaticModuleState的功能是在运行栈上创建一个AFX_MODULE_STATE类的实例,对其进行设置,函数返回值为AFX_MODULE_STATE的指针。AFX_MODULE_STATE类利用其构造函数和析构函数进行模块状态现场存储及恢复。
  2. 使用AfxGetResourceHandle();获取当前资源模块句柄。使用AfxSetResourceHandle(HINSTANCE xxx); 设置程序要使用的资源模块句柄。

常用头文件与库文件

[编辑]
  • STDAFX.H 加载其他MFC头文件。
  • AFXWIN.H 它和它加载的文件声明了所有的MFC类。其内包含AFX.H,后者包含了AFXVER_.H,后者又加载了AFXV_W32.H,后者又加载WINDOWS.H。
  • AFXEXT.H 使用工具栏、状态栏的程序必须加载这个文件
  • AFXDLGS.H 通用对话框(Common dialog)的MFC程序需要加载此文件。它内部包含COMMDLG.H
  • FXCMN.H 通用控件(common control)的MFC程序需要加载此文件。
  • AFXCOLL.H 使用MFC提供的容器都需要加载此文件。
  • AFXDLLX.H 凡使用MFC extension DLLs需要加载此文件。
  • AFXRES.H MFC程序的RC文件必须加载此文件。此文件中对于标准资源的ID都有默认值。它们定义于此文件中。

参考和引用

[编辑]
  1. ^ MFC应用程序向导. [2025-08-05]. (原始内容存档于2025-08-05). 
  2. ^ HOWTO:给ATL项目添加MFC支持. [2025-08-05]. (原始内容存档于2025-08-05). 
  3. ^ Recommendations for Choosing Between ATL and MFC页面存档备份,存于互联网档案馆(英文)
  4. ^ Upgrading Relational Databases with Objects, Robert Vermeulen著, 126页
  5. ^ MFC Updates for Vista Common Controls. [2025-08-05]. (原始内容存档于2025-08-05). 
  6. ^ Making your application sparkle with Windows 7. [2025-08-05]. (原始内容存档于2025-08-05). 
  7. ^ 7.0 7.1 7.2 7.3 7.4 7.5 7.6 MS11-025: Vulnerability in Microsoft Foundation Class (MFC) Library could allow remote code execution: April 12, 2011. Microsoft.com. [June 10, 2019]. (原始内容存档于2025-08-05). 
  8. ^ 8.0 8.1 8.2 Microsoft Security Bulletin MS09-035 - Moderate: Vulnerabilities in Visual Studio Active Template Library Could Allow Remote Code Execution (969706). Microsoft.com. [November 19, 2012]. (原始内容存档于2025-08-05). 
  9. ^ 9.0 9.1 9.2 Protect your computer from the Active Template Library (ATL) security vulnerability. [October 29, 2010]. (原始内容存档于October 26, 2010). 
  10. ^ Microsoft Visual Studio 2005 Service Pack 1 MFC Security Update. Microsoft.com. [November 19, 2012]. (原始内容存档于2025-08-05). 
  11. ^ Where can I download Visual C++ Redistributables?. [June 10, 2019]. (原始内容存档于2025-08-05). 
  12. ^ Visual C++ - Exploring New C++ and MFC Features in Visual Studio 2010. Msdn.microsoft.com. [November 19, 2012]. (原始内容存档于2025-08-05). 
  13. ^ Update for Visual C++ 2013 and Visual C++ Redistributable Package. Msdn.microsoft.com. [January 8, 2017]. (原始内容存档于2025-08-05). 
  14. ^ Update for Visual C++ 2013 Redistributable Package. [June 10, 2019]. 
  15. ^ Visual Studio 2015 Update 1. Msdn.microsoft.com. [June 12, 2016]. (原始内容存档于2025-08-05). 
  16. ^ Visual Studio 2015 Update 2. Msdn.microsoft.com. [June 12, 2016]. (原始内容存档于2025-08-05). 
  17. ^ Visual Studio 2015 Update 3. Msdn.microsoft.com. [June 28, 2016]. (原始内容存档于2025-08-05). 
  18. ^ Microsoft Visual Studio 2015 Update 3 (KB3165756). Msdn.microsoft.com. [August 28, 2016]. (原始内容存档于2025-08-05). 
  19. ^ MSDN TN062: Message Reflection for Windows Controls. [2025-08-05]. (原始内容存档于2025-08-05). 
  20. ^ 《CString 的部分实现剖析》
  21. ^ MSDN:Module States of a Regular DLL Dynamically Linked to MFC. [2025-08-05]. (原始内容存档于2025-08-05). 
天恩是什么意思 诸事顺遂是什么意思 牛字五行属什么 不加大念什么 青梅是什么水果
桃子不能和什么一起吃 肺部结节吃什么好 去医院检查艾滋病挂什么科 小便失禁是什么原因 头晕头重昏昏沉沉是什么原因
alike是什么意思 2015属什么生肖 阳历九月份是什么星座 马中赤兔人中吕布什么意思 全友床垫属于什么档次
子婴是秦始皇什么人 小孩记忆力差是什么原因 鸡为什么吃自己下的蛋 要注意什么 4.7号是什么星座
异性是什么意思wzqsfys.com 什么是血虚hcv9jop4ns4r.cn 惯犯是什么意思hcv9jop0ns0r.cn 杨梅和什么不能一起吃hcv9jop0ns3r.cn 葫芦炒什么好吃hcv7jop5ns6r.cn
后脑两侧痛是什么原因hcv9jop1ns7r.cn 隐翅虫皮炎用什么药hebeidezhi.com ins是什么社交软件hcv8jop4ns4r.cn 吃什么长卵泡hcv7jop9ns7r.cn 右眼老跳是什么原因hcv7jop5ns1r.cn
om是什么意思creativexi.com 猫咪呕吐吃什么药可以解决hcv9jop0ns0r.cn 草菅人命是什么意思hcv8jop6ns3r.cn 什么叫打卡hcv9jop4ns6r.cn 汇字五行属什么hcv8jop3ns9r.cn
湿气严重吃什么药好得快hcv9jop7ns3r.cn 思春是什么意思啊hcv7jop9ns6r.cn 晕车的读音是什么hcv7jop9ns0r.cn 夜尿多吃什么药效果好hcv8jop2ns1r.cn 凤梨跟菠萝有什么区别hcv9jop0ns9r.cn
百度