17

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

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

setParentWindow(myWindowHwnd, newParentHwnd);

そうすることで私の形はくっつきますが、見えなくなります。質問「Attach window ..」は、基本的に使用することにより、WPF ウィンドウのこの問題を解決します

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

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

別のコメントによると、Windows スタイルを変更する必要があります。

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

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

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

質問:

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

-- 所見(後ほど追加) --

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

ここですべてのウィンドウ スタイルを検索します。C# 構文は下部にあります。

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

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

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

メモ帳に接続された WinXP WinForm

4

2 に答える 2

14

これが実際の例です。ホスティング アプリは、空白のフォーム (ここには含まれていません) を持つ単純な 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();
    }
  }
}
于 2012-05-27T12:42:14.797 に答える