windows程序设计POPPAD3的关键难点详解(一)
2015-11-08 18:59
183 查看
windows程序设计中POPPAD3也是一个非常麻烦的程序,其中让人不好理解的地方很多。所以也做一下详解,不过只是就一些难点做详解,那些基本的东西不做解释,另外如果篇幅过长,可能会为篇或做续。另外本文看着长,但是语言很简练,读起来应该非常容易,所以不要看着长就害怕不读了,长的文章不一定难读,短的文章也不一定好读,还要看语言简练不简练,废话多不多。好了,讲正事:
case WM_INITMENUPOPUP:
switch (lParam)
{case 1:
EnableMenuItem ((HMENU) wParam, IDM_EDIT_UNDO,SendMessage (hwndEdit, EM_CANUNDO, 0, 0L) ?MF_ENABLED : MF_GRAYED) ;
首先看WM_INITMENUPOPUP,在原文的菜单那一章里对它有这样一段:
当Windows准备显示一个弹出式菜单时,它给窗口消息处理程序发送一个WM_INITMENUPOPUP消息,参数如下:
wParam: 弹出式菜单句柄
LOWORD (lParam):弹出式菜单索引
HIWORD (lParam): 系统菜单为1,其它为0
何为弹出式菜单呢:也在原文的菜单那一章里:
窗口的菜单列紧接在标题列的下方显示,这个菜单列有时被称为「主菜单」或「顶层菜单」。列在顶层菜单的项目通常是下拉式菜单,也叫做「弹出式菜单」或「子菜单」。您也可以定义多重嵌套的弹出式菜单,也就是说,在弹出式菜单上的项目可以存取另一个弹出式菜单。有时弹出式菜单上的项目呼叫对话框以获得更多的信息(对话框在下一章介绍)。在标题列的最左端,很多父窗口都显示程序的小图标,这个图标可以启动系统菜单。它实际上是另一个弹出式菜单。
您还可以在没有顶层菜单列的情况下使用菜单,也就是说,您可以使弹出式菜单出现在屏幕顶层的任何位置。一种方法是使用鼠标右键来启动弹出式菜单
以上是原文中找出的两段,也就是说,弹出式菜单既包含这样的:
![](https://img-blog.csdn.net/20151111014920729?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center)
也包括这样的:
![](https://img-blog.csdn.net/20151111013829581?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center)
还包括这样的:
![](https://img-blog.csdn.net/20151111012736654?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center)
再继续看菜单那一章,有这么一段话:
窗口消息处理程序的工作包括启用和无效化「Edit」菜单中的选项,这项工作在处理WM_INITMENUPOPUP时完成。首先,程序检查是否要显示「Edit」弹出式菜单。因为菜单里「Edit」的位置索引(「File」从0开始)是1,因此如果即将显示「Edit」弹出式菜单,那么lParam应该等于1。
注意,最后那句:因为菜单里「Edit」的位置索引(「File」从0开始)是1,因此如果即将显示「Edit」弹出式菜单,那么lParam应该等于1,也就是说下面的弹出式菜单的位置索引从左到右依次是:0,1,2,3,4
![](https://img-blog.csdn.net/20151111015135836?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center)
好了,这下就可以明白了这段代码了,首先当你点一个弹出式菜单时,就是上图中的从File到Help的那五个选项,会产生case WM_INITMENUPOPUP:,然后通过switch (lParam)来确定是选了上图中的那一个弹出式菜单,上面的那五个弹出式菜单的位置索引依次为0、1、2、4、5,也就是说他们的lParam依次为0、1、2、4、5,当case
1:时,就是说点了它们中的Edit那个弹出式菜单。
再来看EnableMenuItem
((HMENU) wParam, IDM_EDIT_UNDO,SendMessage (hwndEdit, EM_CANUNDO, 0, 0L) ?MF_ENABLED : MF_GRAYED) ;这一句,显然SendMessage (hwndEdit, EM_CANUNDO, 0, 0L) ?MF_ENABLED : MF_GRAYED是一个参数,SendMessage向编辑窗口发送一个EM_CANUNDO,然后编辑窗口的窗口处理程序将检测编辑窗口撤消缓冲区是否为空,通常控件把最后一次在控件的编辑操作保存在一个撤消缓冲区,如果缓冲区非空则返回TRUE表示上次操作可以撤消,否则返回FALSE,也就是说编辑窗口有一个撤消缓冲区,只要你在编辑区里运行操作,就会把你的操作保存在那个撤消缓冲区,再有操作,新的操作会覆盖上一次操作,但只要你有操作,这个撤消缓冲区就不会为空,这时SendMessage
(hwndEdit, EM_CANUNDO, 0, 0L) 返回TRUE,但是没有操作,这个撤消缓冲区就为空,此时SendMessage (hwndEdit, EM_CANUNDO, 0, 0L) 返回FALSE,当SendMessage
(hwndEdit, EM_CANUNDO, 0, 0L) 返回TRUE,则SendMessage (hwndEdit, EM_CANUNDO, 0, 0L) ?MF_ENABLED : MF_GRAYED为MF_ENABLED,相反则为 MF_GRAYED。
这时的EnableMenuItem,看看它的定义:
BOOL
EnableMenuItem(
HMENU hMenu, // handle to menu
UINT uIDEnableItem, // menu item to enable, disable, or gray
UINT wEnable // menu item flags
);
其中第一个参数为菜单句柄。第二个参数为欲允许或禁止的一个菜单条目的标识符。如果在wEnable参数中设置了MF_BYCOMMAND标志,这个参数就代表欲改变菜单条目的命令ID。如设置的是MF_BYPOSITION,则这个参数代表菜单条目在菜单中的位置(第一个条目肯定是零),第三个参数wEnable
,参考ModifyMenu函数中的菜单常数标志定义表,其中列出了允许使用的所有常数。对于这个函数,只能指定下述常数:MF_BYCOMMAND,MF_BYPOSITION,MF_ENABLED,MF_DISABLED以及MF_GRAYED。
所以EnableMenuItem
((HMENU) wParam, IDM_EDIT_UNDO,SendMessage (hwndEdit, EM_CANUNDO, 0, 0L) ?MF_ENABLED : MF_GRAYED) ;就是给一个ID为IDM_EDIT_UNDO的菜单项发送一个MF_ENABLED
或是MF_GRAYED,至于是哪个要看SendMessage的返回值。当发送MF_ENABLED时,菜单有效,相发送MF_GRAYED时,菜单项无效。
但这里你可能要问(HMENU)
wParam,为什么这个wParam前面要加个(HMENU) ,这个问题嘛,我觉的可能是为了把wParam转换为类型吧,毕竟EnableMenuItem第一个参数要的是菜单句柄,但wParam前面说了也是弹出式菜单句柄,这个嘛,我做了实验把那个(HMENU)
去掉,也能运行,但是两个警告,说是类型不对,所以我觉的可能是WM_INITMENUPOPUP带的wParam参数,虽然也是菜单的句柄,但它应该不是HMENU型,而EnableMenuItem的第一个参数不仅要求是菜单的句柄还要求为HMENU型,所以要转换为HMENU型。
还有下面的EnableMenuItem
((HMENU) wParam, IDM_EDIT_PASTE,IsClipboardFormatAvailable (CF_TEXT) ?MF_ENABLED : MF_GRAYED) ;情况差不多,就不细讲了,本文只是就一些难点讲讲,不是每一个地方都讲,这里只说说IsClipboardFormatAvailable(CF_TEXT)判断剪贴板上的数据,如果当前剪切板包含的是以NULL结尾的ASCII字符的文本格式,则该函数返回值为true,否则为false。剩下的你自己也就应该知道了。
好了,看来要分章节了,后面还要很多要说的,拜拜
case WM_INITMENUPOPUP:
switch (lParam)
{case 1:
EnableMenuItem ((HMENU) wParam, IDM_EDIT_UNDO,SendMessage (hwndEdit, EM_CANUNDO, 0, 0L) ?MF_ENABLED : MF_GRAYED) ;
首先看WM_INITMENUPOPUP,在原文的菜单那一章里对它有这样一段:
当Windows准备显示一个弹出式菜单时,它给窗口消息处理程序发送一个WM_INITMENUPOPUP消息,参数如下:
wParam: 弹出式菜单句柄
LOWORD (lParam):弹出式菜单索引
HIWORD (lParam): 系统菜单为1,其它为0
何为弹出式菜单呢:也在原文的菜单那一章里:
窗口的菜单列紧接在标题列的下方显示,这个菜单列有时被称为「主菜单」或「顶层菜单」。列在顶层菜单的项目通常是下拉式菜单,也叫做「弹出式菜单」或「子菜单」。您也可以定义多重嵌套的弹出式菜单,也就是说,在弹出式菜单上的项目可以存取另一个弹出式菜单。有时弹出式菜单上的项目呼叫对话框以获得更多的信息(对话框在下一章介绍)。在标题列的最左端,很多父窗口都显示程序的小图标,这个图标可以启动系统菜单。它实际上是另一个弹出式菜单。
您还可以在没有顶层菜单列的情况下使用菜单,也就是说,您可以使弹出式菜单出现在屏幕顶层的任何位置。一种方法是使用鼠标右键来启动弹出式菜单
以上是原文中找出的两段,也就是说,弹出式菜单既包含这样的:
也包括这样的:
还包括这样的:
再继续看菜单那一章,有这么一段话:
窗口消息处理程序的工作包括启用和无效化「Edit」菜单中的选项,这项工作在处理WM_INITMENUPOPUP时完成。首先,程序检查是否要显示「Edit」弹出式菜单。因为菜单里「Edit」的位置索引(「File」从0开始)是1,因此如果即将显示「Edit」弹出式菜单,那么lParam应该等于1。
注意,最后那句:因为菜单里「Edit」的位置索引(「File」从0开始)是1,因此如果即将显示「Edit」弹出式菜单,那么lParam应该等于1,也就是说下面的弹出式菜单的位置索引从左到右依次是:0,1,2,3,4
好了,这下就可以明白了这段代码了,首先当你点一个弹出式菜单时,就是上图中的从File到Help的那五个选项,会产生case WM_INITMENUPOPUP:,然后通过switch (lParam)来确定是选了上图中的那一个弹出式菜单,上面的那五个弹出式菜单的位置索引依次为0、1、2、4、5,也就是说他们的lParam依次为0、1、2、4、5,当case
1:时,就是说点了它们中的Edit那个弹出式菜单。
再来看EnableMenuItem
((HMENU) wParam, IDM_EDIT_UNDO,SendMessage (hwndEdit, EM_CANUNDO, 0, 0L) ?MF_ENABLED : MF_GRAYED) ;这一句,显然SendMessage (hwndEdit, EM_CANUNDO, 0, 0L) ?MF_ENABLED : MF_GRAYED是一个参数,SendMessage向编辑窗口发送一个EM_CANUNDO,然后编辑窗口的窗口处理程序将检测编辑窗口撤消缓冲区是否为空,通常控件把最后一次在控件的编辑操作保存在一个撤消缓冲区,如果缓冲区非空则返回TRUE表示上次操作可以撤消,否则返回FALSE,也就是说编辑窗口有一个撤消缓冲区,只要你在编辑区里运行操作,就会把你的操作保存在那个撤消缓冲区,再有操作,新的操作会覆盖上一次操作,但只要你有操作,这个撤消缓冲区就不会为空,这时SendMessage
(hwndEdit, EM_CANUNDO, 0, 0L) 返回TRUE,但是没有操作,这个撤消缓冲区就为空,此时SendMessage (hwndEdit, EM_CANUNDO, 0, 0L) 返回FALSE,当SendMessage
(hwndEdit, EM_CANUNDO, 0, 0L) 返回TRUE,则SendMessage (hwndEdit, EM_CANUNDO, 0, 0L) ?MF_ENABLED : MF_GRAYED为MF_ENABLED,相反则为 MF_GRAYED。
这时的EnableMenuItem,看看它的定义:
BOOL
EnableMenuItem(
HMENU hMenu, // handle to menu
UINT uIDEnableItem, // menu item to enable, disable, or gray
UINT wEnable // menu item flags
);
其中第一个参数为菜单句柄。第二个参数为欲允许或禁止的一个菜单条目的标识符。如果在wEnable参数中设置了MF_BYCOMMAND标志,这个参数就代表欲改变菜单条目的命令ID。如设置的是MF_BYPOSITION,则这个参数代表菜单条目在菜单中的位置(第一个条目肯定是零),第三个参数wEnable
,参考ModifyMenu函数中的菜单常数标志定义表,其中列出了允许使用的所有常数。对于这个函数,只能指定下述常数:MF_BYCOMMAND,MF_BYPOSITION,MF_ENABLED,MF_DISABLED以及MF_GRAYED。
所以EnableMenuItem
((HMENU) wParam, IDM_EDIT_UNDO,SendMessage (hwndEdit, EM_CANUNDO, 0, 0L) ?MF_ENABLED : MF_GRAYED) ;就是给一个ID为IDM_EDIT_UNDO的菜单项发送一个MF_ENABLED
或是MF_GRAYED,至于是哪个要看SendMessage的返回值。当发送MF_ENABLED时,菜单有效,相发送MF_GRAYED时,菜单项无效。
但这里你可能要问(HMENU)
wParam,为什么这个wParam前面要加个(HMENU) ,这个问题嘛,我觉的可能是为了把wParam转换为类型吧,毕竟EnableMenuItem第一个参数要的是菜单句柄,但wParam前面说了也是弹出式菜单句柄,这个嘛,我做了实验把那个(HMENU)
去掉,也能运行,但是两个警告,说是类型不对,所以我觉的可能是WM_INITMENUPOPUP带的wParam参数,虽然也是菜单的句柄,但它应该不是HMENU型,而EnableMenuItem的第一个参数不仅要求是菜单的句柄还要求为HMENU型,所以要转换为HMENU型。
还有下面的EnableMenuItem
((HMENU) wParam, IDM_EDIT_PASTE,IsClipboardFormatAvailable (CF_TEXT) ?MF_ENABLED : MF_GRAYED) ;情况差不多,就不细讲了,本文只是就一些难点讲讲,不是每一个地方都讲,这里只说说IsClipboardFormatAvailable(CF_TEXT)判断剪贴板上的数据,如果当前剪切板包含的是以NULL结尾的ASCII字符的文本格式,则该函数返回值为true,否则为false。剩下的你自己也就应该知道了。
好了,看来要分章节了,后面还要很多要说的,拜拜
相关文章推荐
- android 代码实现控件之间的间距
- 如何重装TCP/IP协议
- [Android]在代码里运行另一个程序的方法
- Windows 8 官方高清壁纸欣赏与下载
- 谁是桌面王者?Win PK Linux三大镇山之宝
- 对《大家都在点赞 Windows Terminal,我决定给你泼一盆冷水》一文的商榷
- Windows Clang开发环境备忘
- 从Windows系统下访问Linux分区相关软件
- 肯特·贝克:改变人生的代码整理魔法
- 对《大家都在点赞 Windows Terminal,我决定给你泼一盆冷水》一文的商榷
- Windows下搭建本地SVN服务器
- Visual Studio 2012 示例代码浏览器 - 数以千计的开发示例近在手边,唾手可得
- Visual Studio 2012 示例代码浏览器 - 数以千计的开发示例近在手边,唾手可得
- Linux C函数参考手册(PDF版)
- 微软镜像下载
- windows server域用户提升到本地更高权限组中的方法
- 使用命令修改注册表键值及权限