web-dev-qa-db-ja.com

フォームウィンドウをC#の別のウィンドウにアタッチする

フォームを(別のプロセスの)別のウィンドウに添付したい。私はこれを使用してこれを試みます

_[DllImport("user32.dll", SetLastError = true)]
private static extern IntPtr SetParent(IntPtr hWndChild, IntPtr hWndNewParent);

setParentWindow(myWindowHwnd, newParentHwnd);
_

そうすることで私のフォームは添付されますが、見えません。質問 "ウィンドウをアタッチ.." 基本的にを使用してWPFウィンドウのこの問題を解決します

_HwndSourceParameters parameters = new HwndSourceParameters();
...
HwndSource src = new HwndSource(parameters);
_

これを自分のフォームに転送しようとしましたが、転送できません(たとえば、src.RootVisual = (Visual)window.Content;の処理方法?-> 完全なソース )。

別のコメント は、ウィンドウのスタイルを変更する必要があると言っています:

互換性の理由から、SetParentは、親が変更されているウィンドウのWS_CHILDまたはWS_POPUPウィンドウスタイルを変更しません。したがって、hWndNewParentがNULLの場合は、SetParentを呼び出した後、WS_CHILDビットもクリアし、WS_POPUPスタイルを設定する必要があります。逆に、hWndNewParentがNULLでなく、ウィンドウが以前はデスクトップの子であった場合は、SetParentを呼び出す前に、WS_POPUPスタイルをクリアし、WS_CHILDスタイルを設定する必要があります。

ここでは、対応するAPIがありません。C#から直接実行できますか、それとも別のDllImportを再度使用する必要がありますか?

善または悪-異なるプロセス間のSetParent()win32 API 異なるプロセスにウィンドウをアタッチしないようにアドバイスしますが、少なくとも試してみたいと思います。

質問:

フォームウィンドウを表示するにはどうすればよいですか? _WS_Child_を使用したアプローチが正しい場合、どのように設定しますか?または、 WPFアプローチ 方法ですが、Windowsフォームにどのように適用しますか?

-調査結果(後で追加)-

winAPIを使用して別のアプリケーションのWindowsスタイルを変更する C#/ PInvokeからスタイルを変更する方法を示します

すべてを検索 windows styles ここで、下部にC#構文があります。

-アランとの話し合いによる調査結果-

Win XPでクロスチェックするためにプログラムを実行しました(以下のAlanの回答とコメントを参照してください)。少なくとも今は何かが表示されています。Alanの例のように座標を追加したので、ウィンドウ左上隅近くの別のウィンドウ上を移動すると、メモ帳で光ります。メモ帳に入力されたテキストはオーバーレイとして表示されます。Win7(32)では、何も表示されません。

  1. ここで、これが安定した方法で記述でき、Win7にも表示されるかどうかを確認する必要があります。
  2. それでも、フォームのボタンをクリックできないので、解決する必要があります。

WinXP WinForm attached to notepad

16
Horst Walter

これが実際の例です。ホスティングアプリは、空白のフォーム(ここには含まれていません)を備えたシンプルなWinFormsアプリケーションですが、「ゲストアプリ」には、ゲストを変更した後にメッセージを表示するテストボタンなど、いくつかのコントロールを備えたメインフォーム(以下に含まれるコード)があります。フォームの親。

OPの質問にリンクされている通常の警告がこれにも当てはまります。

public partial class GuestForm: Form
{
  [DllImport("user32.dll")]
  public static extern int SetWindowLong(IntPtr hWnd, int nIndex, int dwNewLong);

  [DllImport("user32.dll")]
  public static extern int GetWindowLong(IntPtr hWnd, int nIndex);

  [DllImport("user32.dll", SetLastError = true)]
  private static extern IntPtr SetParent(IntPtr hWndChild, IntPtr hWndNewParent);

  public static int GWL_STYLE = -16;
  public static int WS_CHILD = 0x40000000; 

  public GuestForm()
  {
    InitializeComponent();
  }

  private void button1_Click(object sender, EventArgs e)
  {
    MessageBox.Show("done");
  }

  private void button2_Click(object sender, EventArgs e)
  {
    Process hostProcess = Process.GetProcessesByName("HostFormApp").FirstOrDefault();
    if (hostProcess != null)
    {
      Hide();
      FormBorderStyle = FormBorderStyle.None;
      SetBounds(0, 0, 0, 0, BoundsSpecified.Location);

      IntPtr hostHandle = hostProcess.MainWindowHandle;
      IntPtr guestHandle = this.Handle;
      SetWindowLong(guestHandle, GWL_STYLE, GetWindowLong(guestHandle, GWL_STYLE) | WS_CHILD);
      SetParent(guestHandle, hostHandle);

      Show();
    }
  }
}
14
Alan

@Horst Walterねえ、あなたが問題を修正したかどうかはわかりませんが、私はこれに対する解決策を見つけました。

私にとっての問題は、他のフォーム内に必要なメインフォームの透明性でした。

透明度を無効にするだけで機能するはずです。

3
Red Fane