5

こんにちは、私は現在 Visual Studio 2010 を実行しており、32 ビット マシン上で 32 ビットで完全に動作するコンテキスト メニュー シェル拡張を使用しているため、すべてのメソッドが存在します。ATL プロジェクトです。32ビットではエラーも警告もありません。

これが問題です。Visual Studio で構成マネージャーに移動し、アクティブなソリューション プラットフォームを Win32 から x64 に切り替えてコンパイルしようとすると、「エラー C2259: 'ATL::CCOMObject : 抽象クラスをインスタンス化できません」というエラーが表示されます。

このまったく同じプロジェクトが 32 ビットでコンパイルおよび実行されるため、x64 でそのエラーがスローされるのはなぜですか?

アイデアや正しい方向へのポイントをいただければ幸いです。
必須で実装される主なメソッドは次のとおりです。

STDMETHODIMP Initialize(LPCITEMIDLIST, LPDATAOBJECT, HKEY);
STDMETHODIMP GetCommandString(UINT, UINT, UINT*, LPSTR, UINT);
STDMETHODIMP InvokeCommand(LPCMINVOKECOMMANDINFO);
STDMETHODIMP QueryContextMenu(HMENU, UINT, UINT, UINT, UINT);

コード スペースを節約するには Atl プロジェクトを作成します。初期項目が作成されたら、新しいクラス "TestingContextMenu" を追加します。残りのコードはこれを参照します。

stdafk.h

#include "resource.h"
#include <atlbase.h>
#include <atlcom.h>
#include <atlctl.h>
#include <shlobj.h>
#include <comdef.h>

#include <string>
#include <list>
typedef std::list< std::basic_string<TCHAR> > string_list;

TestingContextMenu.h 追加/変更された部分のみが含まれます

#include "stdafx.h"
using namespace std;
class ATL_NO_VTABLE CTestingContextMenu:
        public CComObjectRootEx<CComSingleThreadModel>,
    public CComCoClass<CTestingContextMenu, &CLSID_TestingContextMenu>,
    public IShellExtInit,
    public IContextMenu
    {
        // Comment out or remove IDispatch
BEGIN_COM_MAP(CMainMagnimbusContextMenu)
    //COM_INTERFACE_ENTRY(ITestingContextMenu)
    //COM_INTERFACE_ENTRY(IDispatch)
    COM_INTERFACE_ENTRY(IShellExtInit)
    COM_INTERFACE_ENTRY(IContextMenu)
END_COM_MAP()

protected:
    TCHAR m_szFile[MAX_PATH];
    list<string> Filenames;
    list<string> FilenamesCopier;
public:
    STDMETHODIMP Initialize(LPCITEMIDLIST, LPDATAOBJECT, HKEY);

    STDMETHODIMP GetCommandString(UINT, UINT, UINT*, LPSTR, UINT);
    STDMETHODIMP InvokeCommand(LPCMINVOKECOMMANDINFO);
    STDMETHODIMP QueryContextMenu(HMENU, UINT, UINT, UINT, UINT);
};  //There is other code within this but it is autogenerated

TestingContextMenu.cpp

#include "stdafx.h"
#include "TestingContextMenu"
#include <sstream>
using namespace std;
#pragma comment(lib, "comsuppw")

STDMETHODIMP CMainMagnimbusContextMenu::Initialize ( 
  LPCITEMIDLIST pidlFolder,
  LPDATAOBJECT pDataObj,
  HKEY hProgID )
  {
  FORMATETC fmt = { CF_HDROP, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL };
    STGMEDIUM stg = { TYMED_HGLOBAL };
    HDROP     hDrop;

    if ( FAILED( pDataObj->GetData ( &fmt, &stg ) ))
        return E_INVALIDARG;
    hDrop = (HDROP) GlobalLock ( stg.hGlobal );

    UINT uNumFiles = DragQueryFile ( hDrop, 0xFFFFFFFF, NULL, 0 );
   HRESULT hr = S_OK;

   if ( 0 == uNumFiles )
    {
       GlobalUnlock ( stg.hGlobal );
       ReleaseStgMedium ( &stg );
       return E_INVALIDARG;
    }

   UINT counter = 0;
    // Get the name of the every file and store it in our member variable m_szFile.
   for(counter = 0; counter < uNumFiles; counter++)
   {
        if ( 0 == DragQueryFile ( hDrop, counter, m_szFile, MAX_PATH ) )
        {   
            hr = E_INVALIDARG;
        }
        wchar_t* t = _wcsdup(m_szFile);
        char ch[260];
        char DefChar = ' ';
        WideCharToMultiByte(CP_ACP,0,t,-1, ch,260,&DefChar, NULL);
        string ss(ch);
        Filenames.push_back(ss);
        FilenamesCopier.push_back(ss);
   }

   GlobalUnlock ( stg.hGlobal );
   ReleaseStgMedium ( &stg );

   return hr;
}

残りの機能はリクエストに応じて利用できます。しかし、私は何か新しいことに気づきました。上記の関数とコードだけを実装し、構成マネージャーを x64 をビルドするように設定すると、初期エラーが発生します。これは、QueryContextMenu、GetCommandString、または呼び出しコマンドを実装しないことを意味します。このセットアップで発生する唯一のエラーは、実装されていないため、予想される私のオリジナルです。ただし、その構成マネージャーを Win32 に戻すと、3 つの未解決の外部エラーや、それに続く GetCommandString、InvokeCommand、および QueryContextMenu という名前の 3 つのエラーなど、予想されるエラーが発生します。実装されていない場合は再び予想されますが、x64 のコンパイラは、実装されたメソッドではなく、多くの人が想定する元のエラーのみを認識するのはなぜですか?

前の段落は、私が気づいたことです。3 つのメソッドはすべて正しく実装されており、Win32 では正しくコンパイルされますが、x64 ではコンパイルされません。

4

1 に答える 1

6

GetCommandStringパラメータがインターフェイス メソッドで定義されたものと一致しません。

君の

STDMETHODIMP GetCommandString(UINT, UINT, UINT*, LPSTR, UINT)

する必要があります

STDMETHODIMP GetCommandString(UINT_PTR, UINT, UINT*, LPSTR, UINT)

inWin32の不一致はそれほど重要ではなく (パラメーターの型は同じ型に解決されます)、inx64は重要になります。コンパイラのビルド出力は、欠落しているメソッド名を含め、これに関するヒントを提供するはずです。

于 2012-08-02T05:47:44.033 に答える