WinformsはForm#HandleでふつうにHWNDが取り出せるので、CWnd::Attach
とCWnd::Detach
でMFCの部品をWindows.Forms.Formに貼り付けることができます。
C++/CLIを使うともっとスムーズにいくのかもしれませんが、なんかうまくいかなかったので次のようにしました。
手順
1. DLLを作る
MFCのDLLで、以下のような初期化と解放用の関数を作ります。
attach.cpp
/** WinFormsのhwndにattachし、newしたcwndを返す */
extern "C" __declspec(dllexport) CWnd* PASCAL attach(HWND hwnd) {
auto w = std::make_unique<CWnd>();
if (!w->Attach(hwnd)) { return nullptr; }
// ... wに好きな部品を置く ...
return w.release();
}
/** attachで作ったcwndをdetachとdeleteする */
extern "C" __declspec(dllexport) void PASCAL detach(Pair *p) {
auto w = std::unique_ptr<CWnd>(cwnd);
w->Detach();
}
2. ControlでHandleを渡して呼ぶ
作ったDLLの関数をコントロールで呼び出します。
SomeMFCControl.cs
public class GuestControl : Control
{
/// <summary>アタッチしたMFCのCWnd</summary>
private IntPtr CWnd { get; }
[DllImport("attach")]
private static extern IntPtr attach(IntPtr hwnd);
[DllImport("attach")]
private static extern void detach(IntPtr hwnd);
public GuestControl()
{
CWnd = attach(Handle);
}
protected override void Dispose(bool disposing)
{
if (disposing)
{
detach(CWnd);
}
base.Dispose(disposing);
}
}
あとはこのControlをフォームに貼り付ければ動きます。