已阅读5页,还剩10页未读, 继续免费阅读
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
UNREFERENCED_PARAMETER的用处作用:告诉编译器,已经使用了该变量,不必检测警告!在VC编译器下,如果您用最高级别进行编译,编译器就会很苛刻地指出您的非常细小的警告。当你生命了一个变量,而没有使用时,编译器就会报警告:“warning C4100: : unreferenced formal parameter.”所以,为了让编译器不必检测你的警告,就使用UNREFERENCED_PARAMETER语句。比如:int SomeFunction(int arg1, int arg2) UNREFERENCED_PARAMETER(arg2) .我看到过一些 C+ 代码针对没有使用过的参数用 UNREFERENCED_PARAMETER,例如:int SomeFunction(int arg1, int arg2) UNREFERENCED_PARAMETER(arg2) .我还看到过这样的代码:int SomeFunction(int arg1, int /* arg2 */) .你能解释它们的差别吗?哪一种用法更好?Judy McGeough是啊!为什么呢?让我们从 UNREFERENCED_PARAMETER 开始吧。这个宏在 winnt.h 中定义如下:#define UNREFERENCED_PARAMETER(P) (P)换句话说 UNREFERENCED_PARAMETER 展开传递的参数或表达式。其目的是避免编译器关于未引用参数的警告。许多程序员,包括我在内,喜欢用最高级别的警告 Level 4(/W4)进行编译。Level 4 属于“能被安全忽略的事件”的范畴。虽然它们可能使你难堪,但很少破坏你的代码。例如,在你的程序中可能会有这样一些代码行:int x=1;但你从没用到过 x。也许这一行是你以前使用 x 时留下来的,只删除了使用它的代码,而忘了删除这个变量。Warning Level 4 能找到这些小麻烦。所以,为什么不让编译器帮助你完成可能是最高级别的专业化呢?用Level 4 编译是展示你工作态度的一种方式。如果你为公众使用者编写库,Level 4 则是社交礼节上需要的。你不想强迫你的开发人员使用低级选项清洁地编译他们的代码。问题是,Level 4 实在是太过于注意细节,在 Level 4 上,编译器连未引用参数这样无伤大雅的事情也要抱怨(当然,除非你真的有意使用这个参数,这时便相安无事)。假设你有一个函数带来两个参数,但你只使用其中一个:int SomeFunction(int arg1, int arg2) return arg1+5;使用 /W4,编译器抱怨:“warning C4100: arg2 : unreferenced formal parameter.”为了骗过编译器,你可以加上 UNREFERENCED_PARAMETER(arg2)。现在编译器在编译你的引用 arg2 的函数时便会住口。并且由于语句:arg2;实际上不做任何事情,编译器不会为之产生任何代码,所以在空间和性能上不会有任何损失。细心的人可能会问:既然你不使用 arg2,那当初为何要声明它呢?通常是因为你实现某个函数以满足某些API固有的署名需要,例如,MFC的 OnSize 处理例程的署名必须要像下面这样:void OnSize(UINT nType, int cx, int cy);这里 cx/cy 是窗口新的宽/高,nType 是一个类似 SIZE_MAXIMIZED 或 SIZE_RESTORED 这样的编码,表示窗口是否最大化或是常规大小。一般你不会在意 nType,只会关注 cx 和 xy。所以如果你想用 /W4,则必须使用 UNREFERENCED_PARAMETER(nType)。OnSize 只是上千个 MFC 和 Windows 函数之一。编写一个基于 Windows 的程序,几乎不可能不碰到未引用参数。说了这么多关于 UNREFERENCED_PARAMETER 内容。Judy 在她的问题中还提到了另一个 C+ 程序员常用的并且其作用与 UNREFERENCED_PARAMETER 相同的诀窍,那就是注释函数署名中的参数名:void CMyWnd:OnSize(UINT /* nType */, int cx, int cy)现在 nType 是未命名参数,其效果就像你敲入 OnSize(UINT, int cx, int cy)一样。那么现在的关键问题是:你应该使用哪种方法未命名参数,还是 UNREFERENCED_PARAMETER?大多数情况下,两者没什么区别,使用哪一个纯粹是风格问题。(你喜欢你的 java 咖啡是黑色还是奶油的颜色?)但我认为至少有一种情况必须使用 UNREFERENCED_PARAMETER。假设你决定窗口不允许最大化。那么你便禁用 Maximize 按钮,从系统菜单中删除,同时阻止每一个用户能够最大化窗口的操作。因为你是偏执狂(大多数好的程序员都是偏执狂),你添加一个 ASSERT (断言)以确保代码按照你的意图运行:void CMyWnd:OnSize(UINT nType, int cx, int cy) ASSERT(nType != SIZE_MAXIMIZE); . / use cx, cy质检团队竭尽所能以各种方式运行你的程序,ASSERT 从没有弹出过,于是你认为编译生成 Release 版本是安全的。但是此时 _DEBUG 定义没有了,ASSERT(nType != SIZE_MAXIMIZE)展开为 (void)0),并且 nType 一下子成了一个未引用参数!这样进入你干净的编译。你无法注释掉参数表中的 nType,因为你要在 ASSERT 中使用它。于是在这种情况下你唯一使用参数的地方是在 ASSERT 中或其它 _DEBUG 条件代码中只有 UNREFERENCED_PARAMETER 会保持编译器在 Debug 和 Release 生成模式下都没有问题。知道了吗?结束讨论之前,我想还有一个问题我没有提及,就是你可以象下面这样用 pragma 指令抑制单一的编译器警告:#pragma warning( disable : 4100 )4100 是未引用参数的出错代码。pragma 抑制其余文件/模块的该警告。用下面方法可以重新启用这个警告:#pragma warning( default : 4100 )不管怎样,较好的方法是在禁用特定的警告之前保存所有的警告状态,然后,等你做完之后再回到以前的配置。那样,你便回到的以前的状态,这个状态不一定是编译器的默认状态。所以你能象下面这样在代码的前后用 pragma 指令抑制单个函数的未引用参数警告:#pragma warning( push ) #pragma warning( disable : 4100 )void SomeFunction(.)#pragma warning( pop )当然,对于未引用参数而言,这种方法未免冗长,但对于其它类型的警告来说可能就不是这样了。库生成者都是用 #pragma warning 来阻塞警告,这样他们的代码可以用 /W4 进行清洁编译。MFC 中充满了这样的 pragmas 指令。还有好多的 #pragma warning 选项我没有在本文讨论。有关它们的信息请参考相关文档。我注意到一些应用程序,当右键单击其任务栏最小化按钮时,在弹出的上下文菜单中具备特殊的命令。例如,WinAmp(一个流行的媒体播放器)有一个附加的 “WinAmp”菜单项,其中是 WinAmp 特有的命令。我如何在程序的任务栏按钮中添加我自己的菜单项?Jirair Osygian我创建了一个简单的 MFC SDI 程序,该程序用表单视图(Form View)显示一个计数器。我想通过右键单击任务栏上程序的最小化按钮来控制启动/停止这个计数器。在表单视图上通过按钮控制的启动/停止功能运行正常,我也能将启动/停止命令加到系统菜单。但我单击加入的系统菜单时没反应。我如何处理这些定制的系统菜单消息?Monicque Sharman我两个问题一起回答,Jirair 问题的答案很简单:当你右键单击任务栏上应用程序的最小化按钮时,用户看到的菜单与用户单击左上角应用程序标题栏图标或按 Alt+Space 所看到的菜单一样。如 Figure 1 所示。这个菜单被称为系统菜单,其中包括命令如:还原、最小化、最大化和关闭等。Figure 1 系统菜单你可以调用 :GetSystemMenu 来获得此系统菜单,然后可以添加、删除或修改菜单项。你甚至可以通过关掉 WS_SYSMENU 窗口创建式样标志或 PreCreateWindow 虚函数来完全屏蔽掉这个系统菜单。但不论你做什么,当用户右键单击任务栏上应用程序的最小化按钮时,这个系统菜单还是会显示出来的。到了 Monicque 的问题:如果在系统菜单中添加自己的命令,MFC 是如何处理它们的呢?如果按常规来做 在某个地方写一个 ON_COMMAND 处理器并将它加到消息映射中,你会发现你的处理器不起作用,怎么会这样呢?那是因为 Windows 和 MFC 处理系统命令的方式与处理普通菜单命令的方式不一样。当用户调用窗体中的常规菜单命令或按钮时,Windows 向主窗口发送一个 WM_COMMAND 消息。如果你使用 MFC,那么其命令路由机制将捕获此消息并通过操作系统将它路由到该命令的 ON_COMMAND 命令处理器对象。(有关 MFC 命令处理机制的详细内容,参见我在 MSJ 1995年7月发表的文章:“Meandering Through the Maze of MFC Message and Command Routing”)。然而系统命令不属于 WM_COMMAND 消息范围。而属于另外一个叫做WM_SYSCOMMAND 的消息。不论命令ID是真正的系统命令如 SC_MINIMIZE 和 SC_CLOSE,还是你自己添加的其它命令ID都是如此。为了处理系统菜单命令,你必须处理显式处理 WM_SYSCOMMAND 并且要选择你自己的命令 IDs。这就需要你在主窗口消息映射中添加ON_WM_SYSCOMMAND,它有一个处理函数如下:CMainFrame:OnSysCommand(UINT nID, LPARAM lp) if (nID=ID_MY_COMMAND) . / 处理它 return 0; / 传递到基类:这一步很重要! return CFrameWnd:OnSysCommand(nID, lp);如果该命令不是你的,不要忘了将它传递到你的基类处理典型地,那就是 CFrameWnd 或 CMDIFrameWnd。否则,Windows 将无法得到此消息,并且会破坏内建的命令。在主框架中处理 WM_SYSCOMMAND 固然可以,但这样做感觉太业余。为什么要用特殊的机制来处理呢?就因为它们是系统菜单吗?如果你想在视图或文档对象中处理系统命令会怎样呢?有一个常见的命令放到了系统菜单中,它就是“关于”(ID_APP_ABOUT),大多数 MFC 程序都是在应用程序对象中处理 ID_APP_ABOUT:void CMyApp:OnAppAbout() static CAboutDialog dlg; dlg.DoModal(); MFC 一个真正很酷的特性是它的命令路由系统,它使得象 CMyApp 这样的非窗口对象也能处理菜单命令。许多程序员甚至都不了解怎么会有这样的例外。如果你已经在应用程序对象中处理 ID_APP_ABOUT,那把ID_APP_ABOUT 添加到系统菜单后,为什么还要去实现一套单独的机制?处理外加系统命令的比较好的,或者说更 MFC 的方法应该是通过常规的命令路由机制传递它们。然后按 MFC 常规方法编写 ON_COMMAND 处理例程来处理系统命令。你甚至可以用 ON_UPDATE_COMMAND_UI 来更新你的系统菜单项,例如禁用某个菜单项或在菜单项旁边显示一个检讫标志。Figure 2是我写的一个类,CSysCmdRouter,这个类将系统命令转成常规命令。为了使用这个类,你要做的只是在主框架中实例化 CSysCmdRouter,并从 OnCreate 中调用其 Init 方法即可:int CMainFrame:OnCreate(.) / 将我的菜单项添加到系统菜单 CMenu* pMenu = GetSystemMenu(FALSE); pMenu-AppendMenu(.ID_MYCMD1.); pMenu-AppendMenu(.ID_MYCMD2.); / 通过 MFC 路由系统命令 m_sysCmdHook.Init(this); return 0;一旦你调用 CSysCmdRouter:Init,你便可以按常规方式处理 ID_MYCMD1 和 ID_MYCMD2,为 MFC 命令路由机制中的任何对象编写 ON_COMMAND 处理例程视图,文档,框架,应用程序或通过改写 OnCmdMsg 添加的任何其它命令对象。CSysCmdRouter 还让你用 ON_UPDATE_COMMAND_UI 处理器更新系统菜单。唯一要注意的是确保命令IDs不要与其它菜单命令(除非他们确实代表相同的命令)或内建系统命令发生冲突,内建系统命令从 SC_SIZE = 0xF000 开始。Visual Studio .NET 指定的命令 IDs 从 0x8000 = 32768 开始,所以如果你让 Visual Studio 来指定 IDs,只要不超过 0xF000-0x8000 = 0x7000 个命令即可。也就是十进制的 28,762。如果你的应用程序有超过 28000 个命令,那么你需要咨询编程精神病专家。CSysCmdRouter 是如何实现其魔法的呢?简单:它使用我那个以前专栏中无处不在的 CSubclassWnd。CSubclassWnd 使你不用从其派生便能子类化 MFC 窗口对象。CSysCmdRouter 派生自 CSubclassWnd 并使用它子类化主框架。尤其是它截获发送到框架的 WM_SYSCOMMAND 消息。如果命令 ID 属于系统命令(大于 SC_SIZE = 0xF000),则 CSysCmdRouter 沿着 Windows 一路传递该消息;否则便吃掉 WM_SYSCOMMAND 并重新将它作为 WM_COMMAND 发送,于是 MFC 按照其常规路由过程,调用你的 ON_COMMAND 处理器。很聪明,是不是?那么 ON_UPDATE_COMMAND_UI 处理器呢?CSysCmdRouter 是如何让它处理系统菜单命令的呢?很简单。就在 Windows 显示菜单前,他向你的主窗口发送一个 WM_INITMENUPOPUP 消息。这是你更新菜单项的最佳时机启用或禁用它们,添加检讫标志等等。MFC 为每个菜单项创建一个 CCmdUI 对象并将它传递到你的消息映射中相应的 ON_UPDATE_COMMAND_UI 处理器。以它为参数的 MFC 函数是 CFrameWnd:OnInitMenuPopup,这个函数是这样的:void CFrameWnd:OnInitMenuPopup(CMenu* pMenu, UINT nIndex, BOOL bSysMenu) if (bSysMenu) return; / dont support system menu .MFC 初始化系统菜单时不做任何事情。为什么要去关心这种事呢?万一你要让 bSysMenu 为 FALSE,即使是系统菜单,那该怎么办?这恰恰是 CSysCmdRouter 做的事情。它截取 WM_INITMENUPOPUP 并清除 bSysMenu 标志,也就是 LPARAM 的 HIWORD:if (msg=WM_INITMENUPOPUP) lp = LOWORD(lp); / (set HIWORD = 0)现在,当 MFC 获得 WM_INITMENUPOPUP,它认为该菜单是常规菜单。只要你的命令 IDs 与真正的系统菜单不冲突,一切都运行得很好。如果你改写 OnInitMenuPopup,唯一丢失的东西是不能从主窗口菜单中区分系统菜单。嘿,你不能什么都想要!通过改写 CWnd:WindowProc,你总是能处理 WM_INITMENUPOPUP 的,或你想要区分,就比较 HMENUs。但你确实不用关心命令来自何处。Figure 3 任务栏菜单为了展示所有的实践,我写了一个小测试程序: TBMenu。如图 Figure 3 所示,当你右键单击任务栏上 TBMenu 的最小化按钮,便会显示出菜单。你可以看到在菜单底部有两个额外的命令。TBMenu 的 CMainFrame代码如Figure 4所示。便知道在 OnCreate 的什么地方添加命令并在 CMainFrame 的消息映射中用 ON_COMMAND 以及 ON_UPDATE_COMMAND_UI 处理器处理它们。TBMenu 在其应用程序类中处理 ID_APP_ABOUT(代码未列出)。CSysCmdRouter 使系统命令的工作机制类似其它
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 2025年联合投资合同范本
- 四川省成都市天立教育集团2024-2025学年高一上学期语文期中联考试卷(含答案)
- 2025年cap试题及答案
- 会计从业资格核心考点解析与2025年真题详解及答案
- 2025秋浙教版小学劳动技术二年级上册期末测试卷含答案
- 2025年特色手作材料批发合同
- (2025)时事政治试题库及答案
- 司磅工班组协作评优考核试卷含答案
- 重冶备料工安全教育知识考核试卷含答案
- 山西省山大附中2026届高二上生物期末学业水平测试试题含解析
- 光缆线路障碍点的定位
- 南瑞集团考试真题
- 智慧芽-医药行业:血栓领域抗血小板药物研究进展报告
- 小学数学结构化面试经典100题
- T、K、Y管节点焊缝超声波检验缺陷的判定
- ZJ70DB钻机绞车安装、操作及维护保养规程
- GB/T 34940.3-2017静态切换系统(STS)第3部分:确定性能的方法和试验要求
- GB/T 21198.5-2007贵金属合金首饰中贵金属含量的测定ICP光谱法第5部分:999‰银合金首饰银含量的测定差减法
- 现代优化算法-蚁群算法
- 课件现实与理想-西方古典绘画 课件高中美术人美版(2019)美术鉴赏
- 城镇污水处理厂污泥处理处置技术指南
评论
0/150
提交评论