自分の作成するアプリケーション上に別のアプリケーションを貼り付けたいということがたまにあります。
この記事では、MFCで作成したアプリケーション上に別のアプリケーションを貼り付ける方法について紹介します。
プロジェクトの作成
プロジェクトは何でもよいですが、ここでは簡単化のためダイアログベースで最小構成のプロジェクトを作成します。
画面上のコントロールは全て削除しておき、この画面上に別のアプリを貼り付けます。
画面に別アプリを貼り付ける
MFCの画面上に別アプリを貼り付ける場合、起動済みの別アプリのハンドルを取得してそのハンドルに対してウィンドウスタイルの変更と親ウィンドウの設定を行います。
まだ起動していないウィンドウのハンドルは取得できないため貼り付けることはできません
ここでは、貼り付ける側のアプリとして新規で開いたメモ帳を使用し、ウィンドウハンドルの取得は以下の記事のウィンドウ名(タイトルなし – メモ帳)のみ指定の方法を用います。
// 対象アプリのウィンドウハンドルを取得
HWND hWnd = ::FindWindow(nullptr, _T("タイトルなし - メモ帳"));
// ウィンドウハンドル取得に成功した場合
if (hWnd)
{
// 対象アプリのスタイルを取得
DWORD style = ::GetWindowLong(hWnd, GWL_STYLE);
// スタイルに「子要素」属性を追加
style |= WS_CHILD;
// スタイルから「枠線」属性を削除
style &= ~WS_BORDER;
// 対象アプリにスタイルを設定
::SetWindowLong(hWnd, GWL_STYLE, style);
// 対象アプリの親要素に自身を設定
::SetParent(hWnd, this->GetSafeHwnd());
// 自身のクライアント領域矩形
CRect rc;
// 自身のクライアント領域矩形を取得
this->GetClientRect(rc);
// 対象アプリを自身のクライアント領域いっぱいに設定
::MoveWindow(hWnd, rc.left, rc.top, rc.Width(), rc.Height(), TRUE);
}
処理の内容は全てコメントに記載した通りで、上記の処理を貼り付けたい画面のOnInitDialogにでも記載します。(実際は貼り付け処理を行いたい箇所に記載)
実行すると上記のように作成したMFCアプリの中にメモ帳が貼り付けられます。
貼り付けたアプリを元に戻す
別アプリを貼り付けたままアプリを終了すると貼り付けられたアプリはプロセスは生存するけど画面が表示できないといった問題が発生します。
そのため、貼り付け先のアプリが終了する際には貼り付けたアプリを元に戻す処理を行う必要があります。
貼り付けたアプリを元に戻す手順はアプリを貼り付ける手順の逆で、貼り付けたアプリの親ウィンドウをNULLに指定しウィンドウスタイルを元に戻すだけでよいです。
// ウィンドウハンドル取得済みの場合(メンバに保存していると想定)
if (hWnd)
{
// 対象アプリの親要素にNULLを設定
::SetParent(hWnd, NULL);
// 対象アプリのスタイルを取得
DWORD style = ::GetWindowLong(hWnd, GWL_STYLE);
// スタイルを元に戻す
style &= ~WS_CHILD;
style |= WS_BORDER;
// 対象アプリにスタイルを設定
::SetWindowLong(hWnd, GWL_STYLE, style);
}
上記の処理を貼り付けた画面のOnDestroyあたり(終了時処理関連)に記載することで、画面が閉じられる際に貼り付けたアプリが元の状態に戻ります。
終わりに
MFCアプリ上に別のアプリを貼り付ける方法について紹介しました。
業務アプリを開発しているとサードパーティ製のアプリを埋め込みたいという需要がたまにあるので、こういう方法もあるのだなと覚えておくと良いかと思います。
使用している関数は全てWin32の処理なので、C#など他の言語でも同じように貼り付けることもできるのでぜひ挑戦してみてください。
この記事について誤っている点・不明な点などありましたらコメントまでお願いします。
コメント