tmori3y2のブログ

主にWindowsのプログラムなど

Microsoft All-In-One Code Frameworkのサンプルを元にMFCでC++/CLIを使用せずにWindows FormやWPFのUserControlを使用する

アンマネージアプリケーションと、マネージアプリケーションを組み合わせたシステムを開発していると、そろそろUIはMFCから脱却したいと思うが、規模が大きいと抵抗勢力も多く中々移行が進まない。

ならば、UserControlを新規にWindows FormやWPFで開発すれば、段階的に移行が進むのではと思う今日この頃。

しかし、MFCでのC++/CLIもそれなりにハードルがあるので、使わない方法がないかと色々リサーチをしてみた。

MFCC++/CLIを使用せずにWindows FormやWPFのUserControlを使用する方法のヒントはMicrosoft All-In-One Code Frameworkにあった。

blogs.msdn.com

Sample Browser for traditional desktopはこちらで入手ができる。

1code.codeplex.com

その中のCSActiveXとVBActiveXがそれだ。WPFの場合はWindows FormのUserControlでElementHostを使用することになる。

http://1code.codeplex.com/SourceControl/latest#Visual Studio 2008/CSActiveX/ReadMe.txt

http://1code.codeplex.com/SourceControl/latest#Visual Studio 2008/VBActiveX/ReadMe.txt

使い方はATLActiveXやMFCActiveXと同じ。

http://1code.codeplex.com/SourceControl/latest#Visual Studio 2008/ATLActiveX/ReadMe.txt

http://1code.codeplex.com/SourceControl/latest#Visual Studio 2008/MFCActiveX/ReadMe.txt

MFC Class WizardでProgIdを指定して、ラッパークラスを作成して使用する。

ただし、このサンプルは一部マネージCOMのデザインガイドラインに従っていない部分があるので修正が必要だ。

相互運用のための .NET 型の要件

クラス インターフェイスの概要

マネージCOMのデザインガイドラインを要約すると

  • Guidを割り当てる
  • ProgIdを割り当てる
  • デフォルトで自動生成されるクラスインターフェースの生成を抑制する
    • ClassInterface(ClassInterfaceType.None)でマークする
  • デフォルトコンストラクタを暗黙的/明示的に実装する
  • 明示的なインターフェースを実装する。
    • 明示的にDispIdを指定して値を変更しない。
    • 要件を満たす型以外は使用しない。
  • イベントソースを実装する。
    • 明示的にDispIdを指定して値を変更しない。
    • 要件を満たす型以外は使用しない。
  • COMに公開しない型はComVisible(false)でマークする。
    • COMクライアントで使用されてしまうと、デザイン変更上の制約となる。

CodeBaseオプションでアセンブリ登録を行った場合には、ProgId属性は無視されて、NamespaceName.ClassNameが設定されるので、名前空間の階層が深くならないようにする配慮が必要である。

COM相互運用の基本的な話やWindows Form ControlのActiveX化の話は、.NET and COM: The Complete Interoperability Guideに詳しいので参考にすると良い。

ActiveX用のレジストリエントリは、この本やATL/MFCActiveXなども参考に微修正すると良い。

なお、インプロセスの side-by-side 実行により、CLR2のランタイムがロードされているアンマネージアプリケーションでも、CLR4のランタイムを使用したUserControlを使用することが出来るのが非常に嬉しいが、一方で アプリケーションの起動時間に書かれているように、コールドスタートの問題があるので注意が必要である。

しかし、相互運用に関しては情報が少ないですね。

経験者の方のコメント等をどしどし募集中。先生教えてください!!