我创建了一个ATL COM工程,然后创建了一个ATL Object的对象,Object选择的是Simple Object,在Attributes页面中的设置如下:
Threading Model:Apartment
Interface:Custom
Aggregation:No如下是接口定义:
class ATL_NO_VTABLE CFTProp : 
public CComObjectRootEx<CComSingleThreadModel>,
public CComCoClass<CFTProp, &CLSID_FTProp>,
// public IFTProp
    public IShellExtInit,
    public IShellPropSheetExt
{
public:
CFTProp()
{
}DECLARE_REGISTRY_RESOURCEID(IDR_FTPROP)
DECLARE_NOT_AGGREGATABLE(CFTProp)DECLARE_PROTECT_FINAL_CONSTRUCT()BEGIN_COM_MAP(CFTProp)
// COM_INTERFACE_ENTRY(IFTProp)
COM_INTERFACE_ENTRY(IShellExtInit)
COM_INTERFACE_ENTRY(IShellPropSheetExt)
END_COM_MAP()// IFTProp
public:
    // IShellExtInit
    STDMETHODIMP Initialize(LPCITEMIDLIST, LPDATAOBJECT, HKEY);    // IShellPropSheetExt
    STDMETHODIMP AddPages(LPFNADDPROPSHEETPAGE, LPARAM);
    STDMETHODIMP ReplacePage(UINT, LPFNADDPROPSHEETPAGE, LPARAM) { return E_NOTIMPL; }
};
上面的ATL 对象能正常运行。
我想在这个一个ATL COM工程中再创建一个ATL Object,所以按照上面的创建步骤再创建了一个,如下是接口:
class ATL_NO_VTABLE CFTComment : 
public CComObjectRootEx<CComSingleThreadModel>,
public CComCoClass<CFTComment, &CLSID_FTComment>,
// public IFTComment
public IShellExtInit, // 使用Shell接口的初始化;
public IContextMenu // 使用Shell中菜单接口;
{
public:
CFTComment()
{
}DECLARE_REGISTRY_RESOURCEID(IDR_FTCOMMENT)DECLARE_PROTECT_FINAL_CONSTRUCT()BEGIN_COM_MAP(CFTComment)
// COM_INTERFACE_ENTRY(IFTComment)
COM_INTERFACE_ENTRY(IShellExtInit) // IShellExtInit接口映射;
COM_INTERFACE_ENTRY(IContextMenu) // IContextMenu接口映射;
END_COM_MAP()// IFTComment
public:
STDMETHOD(Initialize)(LPCITEMIDLIST pidlFolder, LPDATAOBJECT pDataObj, HKEY hkeyProgID); // 接口初始化方法; STDMETHOD(QueryContextMenu)(HMENU hmenu, UINT indexMenu, UINT idCmdFirst, UINT idCmdLast, UINT uFlags);
STDMETHOD(GetCommandString)(UINT idCmd, UINT uFlags, UINT *pwReserved, LPSTR pszName, UINT cchMax);
STDMETHOD(InvokeCommand)(LPCMINVOKECOMMANDINFO pici);
};但是只有第一个创建的FTProp对象可以能正常运行,而第二个创建的则无法运行,是什么原因呢?如果我把第二创建的ATL对象FTComment放在另一个工程(ATL COM工程)中,就能正常运行,搞不懂是什么原因,是对象创建的时候“Attributes”的设置原因吗?如果是,我该怎么设置才能在一个工程中使用两个ATL Object对象呢?ATL ObjectATL COM

解决方案 »

  1.   

    首先,我想问一下你是怎么使用COM对象的,
    会不会是你没有指明正确的clsid呢?
      

  2.   

    主要是修改idl文件
    [
    object,
    uuid(xxxxxxx),
    ]
    interface IXXXX : IUnknown
    {
    }; 
    再加一份 你第二个的然后在你接口类的.h文件里面  class xxx:public xxx ,public IXXXX   增加一个你的新类。
      

  3.   

    CLSID没有问题,都是创建的自动生成的,另外这个两个ATL对象是用于shell的,调用是通过右键菜单和文件属性来调用的。如果将两个ATL对象分开到两个不同的ATL COM工程中运行是没有问题的,但是合在一起就有问题,就是第二个不能运行。下面的是我的idl文件内容import "oaidl.idl";
    import "ocidl.idl";
    [
    object,
    uuid(DB456395-46F3-47AE-8887-E76B1D4648C0),

    helpstring("IFTComment Interface"),
    pointer_default(unique)
    ]
    interface IFTComment : IUnknown
    {
    }; [
    object,
    uuid(D22F5D40-1DDD-48BA-A760-EE8F85F3AEF1),

    helpstring("IFTProp Interface"),
    pointer_default(unique)
    ]
    interface IFTProp : IUnknown
    {
    };
    [
    uuid(F6EAED7B-24B7-4BB6-9F26-5A9C918F4E2E),
    version(1.0),
    helpstring("FTManager 1.0 Type Library")
    ]
    library FTMANAGERLib
    {
    importlib("stdole32.tlb");
    importlib("stdole2.tlb"); [
    uuid(FFA53628-0D3B-43D5-AF64-1E1656B7EE24),
    helpstring("FTComment Class")
    ]
    coclass FTComment
    {
    [default] interface IFTComment;
    }; [
    uuid(BA056691-6D35-4666-A255-3C79CC110C61),
    helpstring("FTProp Class")
    ]
    coclass FTProp
    {
    [default] interface IFTProp;
    };
    };
      

  4.   

    在把两个注册文件加上:
    HKCR
    {
    FTManager.FTComment.1 = s 'FTComment Class'
    {
    CLSID = s '{FFA53628-0D3B-43D5-AF64-1E1656B7EE24}'
    }
    FTManager.FTComment = s 'FTComment Class'
    {
    CLSID = s '{FFA53628-0D3B-43D5-AF64-1E1656B7EE24}'
    CurVer = s 'FTManager.FTComment.1'
    }
    NoRemove CLSID
    {
    ForceRemove {FFA53628-0D3B-43D5-AF64-1E1656B7EE24} = s 'FTComment Class'
    {
    ProgID = s 'FTManager.FTComment.1'
    VersionIndependentProgID = s 'FTManager.FTComment'
    InprocServer32 = s '%MODULE%'
    {
    val ThreadingModel = s 'Apartment'
    }
    'TypeLib' = s '{F6EAED7B-24B7-4BB6-9F26-5A9C918F4E2E}'
    }
    }    NoRemove *
        {
    NoRemove shellex
    {
                NoRemove ContextMenuHandlers
    {
                    ForceRemove FTComment = s '{FFA53628-0D3B-43D5-AF64-1E1656B7EE24}'
    }
    }
        }}-------------------------------------------------------------------------HKCR
    {
    FTManager.FTProp.1 = s 'FTProp Class'
    {
    CLSID = s '{BA056691-6D35-4666-A255-3C79CC110C61}'
    }
    FTManager.FTProp = s 'FTProp Class'
    {
    CLSID = s '{BA056691-6D35-4666-A255-3C79CC110C61}'
    CurVer = s 'FTManager.FTProp.1'
    }
    NoRemove CLSID
    {
    ForceRemove {BA056691-6D35-4666-A255-3C79CC110C61} = s 'FTProp Class'
    {
    ProgID = s 'FTManager.FTProp.1'
    VersionIndependentProgID = s 'FTManager.FTProp'
    InprocServer32 = s '%MODULE%'
    {
    val ThreadingModel = s 'Apartment'
    }
    'TypeLib' = s '{F6EAED7B-24B7-4BB6-9F26-5A9C918F4E2E}'
    }
    }    NoRemove *
        {
            NoRemove shellex
            {
                NoRemove PropertySheetHandlers
                {
                    ForceRemove FTProp = s '{BA056691-6D35-4666-A255-3C79CC110C61}'
                }
            }
        }    NoRemove Directory
        {
            NoRemove shellex
            {
                NoRemove PropertySheetHandlers
                {
                    ForceRemove FTProp = s '{BA056691-6D35-4666-A255-3C79CC110C61}'
                }
            }
        }
    }
      

  5.   

    应该是 在你的一个 cpp 里,只注册了一个对象的工厂,可能表达不是很清楚,你去找找吧,
    你实现了两个 COM 对象,但是默认创建工程只登记了第一个,你要找到这里,加上第二个,
      

  6.   

    你说的是创建项目的cpp文件吗?
    是不是这个?#include "stdafx.h"
    #include "resource.h"
    #include <initguid.h>
    #include "FTManager.h"#include "FTManager_i.c"
    #include "FTProp.h"
    #include "FTComment.h"
    CComModule _Module;
    CADODatabase _adoConn;BEGIN_OBJECT_MAP(ObjectMap)
    OBJECT_ENTRY(CLSID_FTComment, CFTComment)
    OBJECT_ENTRY(CLSID_FTProp, CFTProp)
    END_OBJECT_MAP()
      

  7.   


    你说的是创建项目的cpp文件吗?
    是不是这个?#include "stdafx.h"
    #include "resource.h"
    #include <initguid.h>
    #include "FTManager.h"#include "FTManager_i.c"
    #include "FTProp.h"
    #include "FTComment.h"
    CComModule _Module;
    CADODatabase _adoConn;BEGIN_OBJECT_MAP(ObjectMap)
    OBJECT_ENTRY(CLSID_FTComment, CFTComment)
    OBJECT_ENTRY(CLSID_FTProp, CFTProp)
    END_OBJECT_MAP()
      

  8.   

    调试,第二个ATL对象是不执行的。
      

  9.   

    调试"创建出来没有",跟到 DllGetObject... 里,一看不就知道了,
      

  10.   

    没调试出来,这个是shell,第二个ATL对象只有在exploer中点击鼠标右键才能执行,断点设置在所有函数或过程的开始都没有断点提示,怎么去跟踪到你说的DllGetObject?之前没做过此类的shell程序,也只是在codeproject上看到Michel的系列文章才开始学着写的。
      

  11.   

    自己写个 测试程序 X ,CoCreateInstance(你那个 CLSID), 
    打开 COM 工程,调试对象设置为 X,在 DllGetClsidObject 处设断点,
    如果没到断点,说明,对象没注册成功,
    如果到了断点,就跟下去看,为啥功能没反应。也可以在代码里找,第一个有,第二个没有,的地方,
    问题在这里?你有两个 defaultcoclass FTComment
        {
            [default] interface IFTComment;
        };
     
        [
            uuid(BA056691-6D35-4666-A255-3C79CC110C61),
            helpstring("FTProp Class")
        ]
        coclass FTProp
        {
            [default] interface IFTProp;
        };
      

  12.   

    把[default]删除了现在一个都出不来了,呵呵。这个COM是由explorer调用的,不是自己程序调用哦。
      

  13.   

    如果在explorer中可以执行的话,第一步执行的是ATL的 Initialize 过程。
    但是现在无法执行。
      

  14.   


    如果在explorer中可以执行的话,第一步执行的是ATL的 Initialize 过程。
    但是现在无法执行。
      

  15.   

    我说错了,default 是设置 组件的默认接口,我以为是 设默认组件呢,(没有 设默认组件 这一说,怕误导,特别注明)