2

C# アプリケーションでカスタマイズ可能なファイル オープン ダイアログを使用しようとしていますが、共通項目ダイアログがカスタマイズ用の簡単な API を提供することがわかりました。ただし、COM Interop の魔法が必要です。COM に関しては完全な初心者なので、良い学習練習になると思います。今、私は次の問題で立ち往生しています:

相互運用アセンブリを生成するために、次の*.batファイルを作成しました。

set OUT_DIR=.\com_interop

if not exist %OUT_DIR% mkdir "%OUT_DIR%

call "C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\bin\vcvars32.bat"

set SDK_DIR="C:\Program Files\Microsoft SDKs\Windows\v7.1"
%SDK_DIR%\Bin\midl.exe /server none /client stub /out "%OUT_DIR%" /tlb ShObjIdl.tlb /x64  %SDK_DIR%\Include\ShObjIdl.idl

%SDK_DIR%\Bin\TlbImp.exe "%OUT_DIR%\ShObjIdl.tlb" /out:ComInterop.ShObj.dll /namespace:ComInterop.ShObj /machine:X64

move /Y ComInterop.ShObj.dll "%OUT_DIR%\ComInterop.ShObj.dll" 

すべての x64 関連のスイッチは、問題を解決するための (失敗した) 試みから来ており、それらが必要かどうかはわかりません。

問題は、midl.exeがハンドルを_RemotableHandle型に変換するシンボルを生成することです。メソッドの代わりに、以下Show(IntPtr)を生成しRemoteShow(_RemotableHandle)ます。

[Guid("D57C7288-D4AD-4768-BE02-9D969532D960")]
[InterfaceType(1)]
public interface IFileOpenDialog : IFileDialog
{
    void AddPlace(IShellItem psi, FDAP FDAP);
    void Advise(IFileDialogEvents pfde, out uint pdwCookie);
    void ClearClientData();
    void Close(int hr);
    void GetCurrentSelection(out IShellItem ppsi);
    void GetFileName(out string pszName);
    void GetFileTypeIndex(out uint piFileType);
    void GetFolder(out IShellItem ppsi);
    void GetOptions(out uint pfos);
    void GetResult(out IShellItem ppsi);
    void GetResults(out IShellItemArray ppenum);
    void GetSelectedItems(out IShellItemArray ppsai);
    void RemoteShow([ComAliasName("ComInterop.ShObj.wireHWND")] ref _RemotableHandle hwndOwner);  // <===== argument, why u no HWND?
    void SetClientGuid(ref Guid guid);
    void SetDefaultExtension(string pszDefaultExtension);
    void SetDefaultFolder(IShellItem psi);
    void SetFileName(string pszName);
    void SetFileNameLabel(string pszLabel);
    void SetFileTypeIndex(uint iFileType);
    void SetFileTypes(uint cFileTypes, ref _COMDLG_FILTERSPEC rgFilterSpec);
    void SetFilter(IShellItemFilter pFilter);
    void SetFolder(IShellItem psi);
    void SetOkButtonLabel(string pszText);
    void SetOptions(uint fos);
    void SetTitle(string pszTitle);
    void Unadvise(uint dwCookie);
}

通常のハンドルを使用するメソッドを生成することは可能ですか? そうでない場合RemoteShow、アプリケーションからどのように呼び出す必要がありますか? おまけの質問:なぜこのようになるのですか (COM に関して)?

他のスレッドで、次のコードに変換IntPtrする提案を見つけました:_RemotableHandle

    _RemotableHandle HWNDtoRemotableHandle(IntPtr handle)
    {
        return (_RemotableHandle)Marshal.PtrToStructure(handle, typeof(_RemotableHandle));
    }

しかし、それはAccessViolationエラーで失敗し、そのような変換はあまりクリーンなことではないと私は信じています。

4

0 に答える 0