Archive for 5月 9th, 2012

  1. Hello, COM(#import) World!

    Posted on 5月 9th, 2012 by cx20

    COM(#import)

    COM(Component Object Model)はマイクロソフトの提唱するプログラム部品の仕様である。
    COM を用いて開発された部品であれば言語を問わず利用することができる。
    以下は Visual C++ のコンパイラ機能である #import ディレクティブを使用した COM クライアントの例となっている。

    ソースコード(事前バインディング)

    #import "shell32.dll"
    using namespace Shell32;
     
    int main( int argc, char* argv[] )
    {
        CoInitialize( NULL );
     
        IShellDispatchPtr pShell("Shell.Application");
        FolderPtr pFolder = NULL;
     
        _variant_t vRootFolder( ssfWINDOWS );
        pFolder = pShell->BrowseForFolder( 0, L"Hello, COM(#import) World!", 0, vRootFolder );
        if ( pFolder != NULL )
        {
            pFolder = NULL;
        }
        pShell = NULL;
     
        CoUninitialize();
     
        return 0;
    }

    #import ディレクティブにより、以下の2ファイル(「*.tlh(タイプライブラリヘッダ)」「*.tli(タイプライブラリ実装ファイル)」)が自動生成されタイプライブラリの情報が C++ ヘッダとして取り込まれる。

    ソースコード(タイプライブラリヘッダ)

    // #import "shell32.dll" にて自動生成された shell32.tlh より一部抜粋
     
    #include <comdef.h>
    namespace Shell32 {
     
    enum ShellSpecialFolderConstants;
    struct __declspec(uuid("bbcbde60-c3ff-11ce-8350-444553540000"))
    /* dual interface */ Folder;
    struct __declspec(uuid("d8f015c0-c278-11ce-a49e-444553540000"))
    /* dual interface */ IShellDispatch;
     
    _COM_SMARTPTR_TYPEDEF(Folder, __uuidof(Folder));
    _COM_SMARTPTR_TYPEDEF(IShellDispatch, __uuidof(IShellDispatch));
     
    enum __declspec(uuid("ca31ea20-48d0-11cf-8350-444553540000"))
    ShellSpecialFolderConstants
    {
        ssfWINDOWS = 36,
    };
     
    struct __declspec(uuid("d8f015c0-c278-11ce-a49e-444553540000"))
    IShellDispatch : IDispatch
    {
        // Wrapper methods for error-handling
        FolderPtr BrowseForFolder (
            long Hwnd,
            _bstr_t Title,
            long Options,
            const _variant_t & RootFolder = vtMissing );
     
        // Raw methods provided by interface
          virtual HRESULT __stdcall get_Application (
            /*[out,retval]*/ IDispatch * * ppid ) = 0;
          virtual HRESULT __stdcall get_Parent (
            /*[out,retval]*/ IDispatch * * ppid ) = 0;
          virtual HRESULT __stdcall raw_NameSpace (
            /*[in]*/ VARIANT vDir,
            /*[out,retval]*/ struct Folder * * ppsdf ) = 0;
          virtual HRESULT __stdcall raw_BrowseForFolder (
            /*[in]*/ long Hwnd,
            /*[in]*/ BSTR Title,
            /*[in]*/ long Options,
            /*[in]*/ VARIANT RootFolder,
            /*[out,retval]*/ struct Folder * * ppsdf ) = 0;
          virtual HRESULT __stdcall raw_Windows (
            /*[out,retval]*/ IDispatch * * ppid ) = 0;
          virtual HRESULT __stdcall raw_Open (
            /*[in]*/ VARIANT vDir ) = 0;
          virtual HRESULT __stdcall raw_Explore (
            /*[in]*/ VARIANT vDir ) = 0;
          virtual HRESULT __stdcall raw_MinimizeAll ( ) = 0;
          virtual HRESULT __stdcall raw_UndoMinimizeALL ( ) = 0;
          virtual HRESULT __stdcall raw_FileRun ( ) = 0;
          virtual HRESULT __stdcall raw_CascadeWindows ( ) = 0;
          virtual HRESULT __stdcall raw_TileVertically ( ) = 0;
          virtual HRESULT __stdcall raw_TileHorizontally ( ) = 0;
          virtual HRESULT __stdcall raw_ShutdownWindows ( ) = 0;
          virtual HRESULT __stdcall raw_Suspend ( ) = 0;
          virtual HRESULT __stdcall raw_EjectPC ( ) = 0;
          virtual HRESULT __stdcall raw_SetTime ( ) = 0;
          virtual HRESULT __stdcall raw_TrayProperties ( ) = 0;
          virtual HRESULT __stdcall raw_Help ( ) = 0;
          virtual HRESULT __stdcall raw_FindFiles ( ) = 0;
          virtual HRESULT __stdcall raw_FindComputer ( ) = 0;
          virtual HRESULT __stdcall raw_RefreshMenu ( ) = 0;
          virtual HRESULT __stdcall raw_ControlPanelItem (
            /*[in]*/ BSTR bstrDir ) = 0;
    };
     
    struct __declspec(uuid("bbcbde60-c3ff-11ce-8350-444553540000"))
    Folder : IDispatch
    {
        // Property data
        __declspec(property(get=GetTitle))
        _bstr_t Title;
     
        // Wrapper methods for error-handling
        _bstr_t GetTitle ( );
     
        // Raw methods provided by interface
          virtual HRESULT __stdcall get_Title (
            /*[out,retval]*/ BSTR * pbs ) = 0;
          virtual HRESULT __stdcall get_Application (
            /*[out,retval]*/ IDispatch * * ppid ) = 0;
          virtual HRESULT __stdcall get_Parent (
            /*[out,retval]*/ IDispatch * * ppid ) = 0;
          virtual HRESULT __stdcall get_ParentFolder (
            /*[out,retval]*/ struct Folder * * ppsf ) = 0;
          virtual HRESULT __stdcall raw_Items (
            /*[out,retval]*/ struct FolderItems * * ppid ) = 0;
          virtual HRESULT __stdcall raw_ParseName (
            /*[in]*/ BSTR bName,
            /*[out,retval]*/ struct FolderItem * * ppid ) = 0;
          virtual HRESULT __stdcall raw_NewFolder (
            /*[in]*/ BSTR bName,
            /*[in]*/ VARIANT vOptions = vtMissing ) = 0;
          virtual HRESULT __stdcall raw_MoveHere (
            /*[in]*/ VARIANT vItem,
            /*[in]*/ VARIANT vOptions = vtMissing ) = 0;
          virtual HRESULT __stdcall raw_CopyHere (
            /*[in]*/ VARIANT vItem,
            /*[in]*/ VARIANT vOptions = vtMissing ) = 0;
          virtual HRESULT __stdcall raw_GetDetailsOf (
            /*[in]*/ VARIANT vItem,
            /*[in]*/ int iColumn,
            /*[out,retval]*/ BSTR * pbs ) = 0;
    };
     
    // Wrapper method implementations
    #include "shell32.tli"
     
    } // namespace Shell32

    ソースコード(タイプライブラリ実装ファイル)

    // #import "shell32.dll" にて自動生成された shell32.tli より一部抜粋
     
    // interface IShellDispatch wrapper method implementations
    inline FolderPtr IShellDispatch::BrowseForFolder ( long Hwnd, _bstr_t Title, long Options, const _variant_t & RootFolder ) {
        struct Folder * _result = 0;
        HRESULT _hr = raw_BrowseForFolder(Hwnd, Title, Options, RootFolder, &_result);
        if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));
        return FolderPtr(_result, false);
    }
     
    // interface Folder wrapper method implementations
    inline _bstr_t Folder::GetTitle ( ) {
        BSTR _result = 0;
        HRESULT _hr = get_Title(&_result);
        if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));
        return _bstr_t(_result, false);
    }

    コンパイル方法(Visual C++)

    C:¥> cl hello.cpp

    実行結果

    +----------------------------------------+
    |Browse For Folder                    [X]|
    +----------------------------------------+
    | Hello, COM(#import) Wolrd!             |
    |                                        |
    | +------------------------------------+ |
    | |[Windows]                           | |
    | | +[addins]                          | |
    | | +[AppCompat]                       | |
    | | +[AppPatch]                        | |
    | | +[assembly]                        | |
    | |     :                              | |
    | |     :                              | |
    | |     :                              | |
    | +------------------------------------+ |
    | [Make New Folder]    [  OK  ] [Cancel] |
    +----------------------------------------+