这个问题一直困扰着我。
拿Shell Interface IContextMenu 来说,在VC6中COM映射宏是这么写的:
BEGIN_COM_MAP(CCountLines)
...
COM_INTERFACE_ENTRY(IContextMenu)
...
END_COM_MAP()COM类,或者叫ATL Object 类是这样继承的:
class ATL_NO_VTABLE CCountLines :
...
public IContextMenu在VC6中编译/连接都没有问题。
而在VC2003/2005中编译总会提示错误,错误定位在COM映射宏中的 COM_INTERFACE_ENTRY(IContextMenu)
提示信息为:
error C2787: 'IContextMenu' : no GUID has been associated with this object
error C2440: 'initializing' : cannot convert from 'DWORD_PTR' to 'const IID *'
error C2440: 'initializing' : cannot convert from 'ATL::_ATL_CREATORARGFUNC (__stdcall *)' to 'DWORD_PTR'我试过用其它映射宏来代替 COM_INTERFACE_ENTRY,比如:
COM_INTERFACE_ENTRY_IID()
这样,编译是通过了,可是程序没有效果,也就是说程序不会走到实现 IContextMenu 的接口函数中。这个问题对于很多 Shell Interface 都遇见过,比如还有 IShellExecuteHook。还有,VC2003/2005中的 实现COM 类接口的 Wizard 中,选择继承于 shell32.dll 中接口类时,怎么没有 IContextMenu 、IShellExecuteHook 这些类。如果能找到VC2003/2005正确的实现COM 类接口的 Wizard,看看VC是怎么自动生成代码的,也许以上问题就可以解决。
拿Shell Interface IContextMenu 来说,在VC6中COM映射宏是这么写的:
BEGIN_COM_MAP(CCountLines)
...
COM_INTERFACE_ENTRY(IContextMenu)
...
END_COM_MAP()COM类,或者叫ATL Object 类是这样继承的:
class ATL_NO_VTABLE CCountLines :
...
public IContextMenu在VC6中编译/连接都没有问题。
而在VC2003/2005中编译总会提示错误,错误定位在COM映射宏中的 COM_INTERFACE_ENTRY(IContextMenu)
提示信息为:
error C2787: 'IContextMenu' : no GUID has been associated with this object
error C2440: 'initializing' : cannot convert from 'DWORD_PTR' to 'const IID *'
error C2440: 'initializing' : cannot convert from 'ATL::_ATL_CREATORARGFUNC (__stdcall *)' to 'DWORD_PTR'我试过用其它映射宏来代替 COM_INTERFACE_ENTRY,比如:
COM_INTERFACE_ENTRY_IID()
这样,编译是通过了,可是程序没有效果,也就是说程序不会走到实现 IContextMenu 的接口函数中。这个问题对于很多 Shell Interface 都遇见过,比如还有 IShellExecuteHook。还有,VC2003/2005中的 实现COM 类接口的 Wizard 中,选择继承于 shell32.dll 中接口类时,怎么没有 IContextMenu 、IShellExecuteHook 这些类。如果能找到VC2003/2005正确的实现COM 类接口的 Wizard,看看VC是怎么自动生成代码的,也许以上问题就可以解决。
struct __declspec(uuid("000214e4-0000-0000-c000-000000000046"))
IContextMenu; _COM_SMARTPTR_TYPEDEF(IContextMenu, __uuidof(IContextMenu));
按照你的第2种方法,即自己定义接口的GUID,我在VC2005下调试通过了,这里还有些细节问题和你交流一下:
1、怎样找到Interface的GUID?
我在注册表 HKCR\Interface\ 下可以找到形式为
{aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee}的键,如果其下有默认项="Interface",则说明这个
键就是该Interface的GUID。
有没有其它方法?
(1) VC6\common\Tools 下有个OLE/COM Object Viewer 很方便,但在VC2005下就没找到这个工具(VC2003也有这个工具,我的VC2005是Team Edition,可能是我没有默认安装的原因)
(2) PlatformSDK\include\comdef.h 中应该也有GUID的定义吧?2、我的PlatformSDK\include 下没有comdef.h 文件,这也可能和我没有默认安装VC2005有关,在Microsoft的网站上有下载PlatformSDK的地址,那个上面应该包括comdef.h 吧?3、我按照你的第2种方法,调试通过了,但为什么还要#include Vc7\include 下的那个<comdef.h>,如果不 #include 的话,编译时会出错,其中有个错误叫:
error C2059: syntax error : '__uuidof'
我想是不是在 Vc7\include\comdef.h 中有符号__uuidof的定义。4、你提到的smart pointer是什么含义,可以在哪里查到资料?
就说这么多了,再次谢谢你的帮助,至少一直困扰着我的这个问题终于被你解决了。
IContextMenu、IShellExecuteHook、IShellExtInit 这些,而是一大堆 IShellDispatch。
我很想看看wizard是怎样生成代码的!
#include <initguid.h>
#include <shlobj.h>
1、VC2005中的 OLE/Obj Viewer 在Common7\Tools\Bin下而且默认没有集成在IDE中。
Platform SDK中的comdef.h中确实有Shell Extension Interface的GUID定义。
2、从微软网站上下了个Platform SDK for Windows Server 2003 R2,其中确实有comdef.h,在VC中重设一下include路径就可以了。
3、__uuidof并非是comdef.h或是其它文件中预定义的符号,它是C++ 运算符,在MSDN中可以查到。
另外,生成Shell Extension Implemented Class的Wizard方法还是没找到。
Over.