29577
お世話になります。

以前、と規定のフォームの前面にProcess.Startで起動したプログラムが立ち上がるように  
したいという質問をしたのですが([C#
外部プログラムを起動させた際に、特定のフォームよりも前面に表示する方法](https://ja.stackoverflow.com/questions/9338/c-%E5%A4%96%E9%83%A8%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%A0%E3%82%92%E8%B5%B7%E5%8B%95%E3%81%95%E3%81%9B%E3%81%9F%E9%9A%9B%E3%81%AB-%E7%89%B9%E5%AE%9A%E3%81%AE%E3%83%95%E3%82%A9%E3%83%BC%E3%83%A0%E3%82%88%E3%82%8A%E3%82%82%E5%89%8D%E9%9D%A2%E3%81%AB%E8%A1%A8%E7%A4%BA%E3%81%99%E3%82%8B%E6%96%B9%E6%B3%95))、その方法について、少し問題があったので、今回、  
メインのフォームの中に、MDIのように外部プログラムを起動させられればと思い、  
新たに質問しました。

前回教えていただいた方法で、指定のフォームの前面にGoogleChromeを立ち上げたときですが、  
常に前面にするように指定したはずが、メインのフォームをアクティブにすると、背面に隠れて  
しまいました。

原因を調べてみると、このメインのフォームを起動する前に、通常の方法でChromeを一つ  
立ち上げた後、今回のプログラムを開き、二つ目のChromeをProcess.Startで  
立ち上げたところ、常に前面に表示されるという設定が効いていませんでした。  
ほかにChromeが開いていないときならば、  
このフォームから立ち上げたChromeは前面に来るのですが、どうやら多重起動するプログラムは  
既に立ち上がっている場合は設定の変更ができないようです。

また、WordやExcelなどはそもそもこの設定ができずに、呼び出したメインウインドウが  
アクティブになると、その背面に隠れてしまいます。

前置きが長くなりましたが、こういったことがあったため、MDIなどにすれば、間違いなく  
メインフォームの中に表示されるだろうと考えました。

フォームの中にフォームを表示するのは、フォームのTopLevelをfalseにすれば簡単に  
できますが、同じような結果になるようにProcess.Startで起動するプログラムを  
メインフォームの子供フォームのように入れることはできますでしょうか。

ご教授お願いいたします。

[![こんな例外が出ています](https://i.stack.imgur.com/RCP8F.jpg)](https://i.stack.imgur.com/RCP8F.jpg)
CC BY-SA 3.0
2016-10-15T02:40:24.363
29574
2016-10-17T00:01:49.947
2017-04-13T12:52:39.113
-1
9374
question
c# windows winforms
C# Process.Startで起動する外部プログラムを、特定のフォームの中に表示させるには？
[`SetParent`](https://msdn.microsoft.com/ja-
jp/library/cc411061.aspx)関数を使用するとウィンドウの親ウィンドウを変更することができます。

```

    [DllImport("user32.dll", SetLastError = true)]
    static extern IntPtr SetParent(IntPtr hWndChild, IntPtr hWndNewParent);
    
    [DllImport("user32.dll", SetLastError = true)]
    static extern bool SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter, int X, int Y, int cx, int cy, int  uFlags);
    
    const int ASYNCWINDOWPOS = 0x4000;
    
    var f = new Form();
    f.IsMdiContainer = true;
    f.Shown += (_, __) =>
    {
        var p = Process.Start("notepad");
        p.WaitForInputIdle();
    
        // 親ウィンドウを設定
        SetParent(p.MainWindowHandle, f.Handle);
    
        // ウィンドウを移動
        SetWindowPos(p.MainWindowHandle, IntPtr.Zero, 0, 0, 100, 100, ASYNCWINDOWPOS);
    };
    f.Show();
    
```

ただしMSDNにも明記されている通り、他プロセスのウィンドウと親子関係を設定するのは保証外の動作になります。
CC BY-SA 3.0
2016-10-15T03:42:21.233
29577
2016-10-15T03:42:21.233
5750
29574
answer