首 页免费信息软件下载在线电视QQ空间克隆免费博客论 坛
您当前的位置:鸿飞官方免费资源网免费信息编程技术 → 文章内容 退出登录 用户管理
本类热门文章
相关文章
 
一步步教你如何编写Shell扩展
作者:鸿飞  来源:本站整理  发布时间:2007-11-22 22:00:48

减小字体 增大字体


修改上下文菜单 IContextMenu 有三个方法.
第一个是 QueryContextMenu(), 它让我们可以修改上下文菜单. 其原型为:

HRESULT IContextMenu::QueryContextMenu ( HMENU hmenu, UINT uMenuIndex, UINT uidFirstCmd, UINT uidLastCmd, UINT uFlags );


hmenu 上下文菜单句柄.
uMenuIndex 是我们应该添加菜单项的起始位置.
uidFirstCmduidLastCmd 是我们可以使用的菜单命令ID值的范围.
uFlags 标识了Explorer 调用QueryContextMenu()的原因,
这我以后会说到的.

而返回值根据你所查阅的文档的不同而不同.
Dino Esposito 的书中说返回值是你所添加的菜单项的个数.
而 VC6.0所带的MSDN 又说它是我们添加的最后一个菜单项的命令ID加上 1.
而最新的 MSDN 又说:
将返回值设为你为各菜单项分配的命令ID的最大差值,加上1.
例如, 假设 idCmdFirst 设为5,而你添加了三个菜单项 ,命令ID分别为 5, 7, 和 8.
这时返回值就应该是: MAKE_HRESULT(SEVERITY_SUCCESS, 0, 8 - 5 + 1).

我是一直按 Dino 的解释来做的, 而且工作得很好.
实际上, 他的方法与最新的 MSDN 是一致的, 只要你严格地使用 uidFirstCmd作为第一个菜单项的ID,再对接续的菜单项ID每次加1.

我们暂时的扩展仅加入一个菜单项,所以 QueryContextMenu() 非常简单:

HRESULT CSimpleShlExt::QueryContextMenu ( HMENU hmenu,UINT uMenuIndex, 
UINT uidFirstCmd, UINT uidLastCmd, UINT uFlags ) { // 如果标志包含 CMF_DEFAULTONLY 我们不作任何事情. if ( uFlags & CMF_DEFAULTONLY ) { return MAKE_HRESULT ( SEVERITY_SUCCESS, FACILITY_NULL, 0 ); } InsertMenu ( hmenu, uMenuIndex, MF_BYPOSITION, uidFirstCmd, _T("SimpleShlExt Test Item") ); return MAKE_HRESULT ( SEVERITY_SUCCESS, FACILITY_NULL, 1 ); }


首先我们检查 uFlags.
你可以在 MSDN中找到所有标志的解释, 但对于上下文菜单扩展而言, 只有一个值是重要的: CMF_DEFAULTONLY.
该标志告诉Shell命名空间扩展保留默认的菜单项,这时我们的Shell扩展就不应该加入任何定制的菜单项,这也是为什么此时我们要返回 0 的原因.
如果该标志没有被设置, 我们就可以修改菜单了 (使用 hmenu 句柄), 并返回 1 告诉Shell我们添加了一个菜单项.

在状态栏上显示提示帮助

下一个要被调用的IContextMenu 方法是 GetCommandString(). 如果用户是在浏览器窗口中右击文本文件,或选中一个文本文件后单击文件菜单时,状态栏会显示提示帮助.
我们的 GetCommandString() 函数将返回一个帮助字符串供浏览器显示.

GetCommandString() 的原型是:

HRESULT IContextMenu::GetCommandString ( UINT idCmd, UINT uFlags, UINT *pwReserved, LPSTR pszName, UINT cchMax );

idCmd 是一个以0为基数的计数器,标识了哪个菜单项被选择.
因为我们只有一个菜单项, 所以idCmd 总是0. 但如果我们添加了3个菜单项, idCmd 可能是 0, 1, 或 2.
uFlags 是另一组标志(我以后会讨论到的).
PwReserved 可以被忽略.
pszName 指向一个由Shell拥有的缓冲区,我们将把帮助字符串拷贝进该缓冲区.
cchMax 是该缓冲区的大小.
返回值是S_OKE_FAIL.

GetCommandString() 也可以被调用以获取菜单项的动作( "verb") .
verb 是个语言无关性字符串,它标识一个可以加于文件对象的操作。
ShellExecute()的文档中有详细的解释, 而有关verb的内容足以再写一篇文章, 简单的解释是:verb 可以直接列在注册表中(如 "open" 和 "print"等字符串), 也可以由上下文菜单扩展创建. 这样就可以通过调用ShellExecute()执行实现在Shell扩展中的代码.

不管怎样, 我说了这多只是为了解释清楚GetCommandString() 的作用.
如果 Explorer 要求一个帮助字符串,我们就提供给它. 如果 Explorer 要求一个verb, 我们就忽略它. 这就是 uFlags 参数的作用.
如果 uFlags 设置了GCS_HELPTEXT 位, 则 Explorer 是在要求帮助字符串. 而且如果 GCS_UNICODE 被设置, 我们就必须返回一个Unicode字符串.

我们的 GetCommandString() 如下:

#include "atlconv.h"
// 为使用 ATL 字符串转换宏而包含的头文件 
             
HRESULT CSimpleShlExt::GetCommandString( UINT idCmd, UINT uFlags,
UINT* pwReserved, LPSTR pszName, UINT cchMax ) { USES_CONVERSION; //检查 idCmd, 它必须是0,因为我们仅有一个添加的菜单项. if ( 0 != idCmd ) return E_INVALIDARG; // 如果 Explorer 要求帮助字符串,就将它拷贝到提供的缓冲区中. if ( uFlags & GCS_HELPTEXT ) { LPCTSTR szText = _T("This is the simple shell extension's help"); if ( uFlags & GCS_UNICODE ) { // 我们需要将 pszName 转化为一个 Unicode 字符串, 接着使用Unicode字符串拷贝 API. lstrcpynW ( (LPWSTR) pszName, T2CW(szText), cchMax ); } else { // 使用 ANSI 字符串拷贝API 来返回帮助字符串. lstrcpynA ( pszName, T2CA(szText), cchMax ); } return S_OK; } return E_INVALIDARG; }

这里没有什么特别的代码; 我用了硬编码的字符串并把它转换为相应的字符集.
如果你从未使用过ATL字符串转化宏,你一定要学一下,因为当你传递Unicode字符串到COM和OLE函数时,使用转化宏会很有帮助的.
我在上面的代码中使用了T2CW 和 T2CA 将TCHAR 字符串分别转化为Unicode 和 ANSI字符串.
函数开头处的USES_CONVERSION 宏其实声明了一个将被转化宏使用的局部变量.

要注意的一个问题是: lstrcpyn() 保证了目标字符串将以null为结束符.
这与C运行时(CRT)函 数strncpy()不同. 当要拷贝的源字符串的长度大于或等于cchMax 时 strncpy()不会添加一个 null 结束符.
我建议总使用lstrcpyn(), 这样你就不必在每一个strncpy()后加入检查保证字符 串以 null为结束符的代码.

执行用户的选择

IContextMenu 接口的最后一个方法是 InvokeCommand(). 当用户点击我们添加的菜单项时该方法将被调用. 其函数原型是:

上一页  [1] [2] [3] [4]  下一页

推荐:本站站长(鸿飞)原创软件免费赠送

温馨提示:如果发现资源地址无效时,请在下面的评论上留言,我会及时处理!谢谢!

[] [返回上一页] [打 印]
文章评论 (评论内容只代表网友观点,与本站立场无关!)

用户名: 查看更多评论

分 值:100分 85分 70分 55分 40分 25分 10分 0分

内 容:

         (注“”为必填内容。) 验证码: 验证码,看不清楚?请点击刷新验证码

关于本站 - 网站帮助 - 广告合作 - 下载声明 - 有情连接 - 网站地图 - 发布信息

Copyright © 2007-2008 鸿飞免费资源网:www.fei2yu.com. All Rights Reserved

站 长:鸿飞    Q Q:250118591    蜀ICP备07502538号