teratail header banner
teratail header banner
質問するログイン新規登録

回答編集履歴

1

SetParent関数の使用を廃止し、NativeWindowを使って解決するように修正

2019/12/25 04:54

投稿

Masahiro-Ito
Masahiro-Ito

スコア24

answer CHANGED
@@ -1,69 +1,51 @@
1
- Excelの前面に表示したいフォームのオーナーの親をExcelにすることで解決しました。
1
+ Excelの前面に表示したいフォームのオーナーをExcelのハンドルを割り当てたNativeWindowにすることで解決しました。
2
- 自身のオーナーの親をExcelアプリケーションにすることでフォームは常にExcelの前面に表示されます。
2
+ 自身のオーナーをExcelのハドルを割り当てたNativeWindowにすることでフォームは常にExcelの前面に表示されます。
3
- フォームの親を設定するためにSetParent関数を使用します。Excelの前面に表示したいフォームの親をExcelアプリケーションにしてもExcelの前面に表示されるのですが、そのフォームはExcelのメインウインドウの中に表示される(MDIの子フォームのように表示される)ので、自身ではなく自身のオーナーの親をExcelアプリケーションにします。
4
3
 
5
- 以下のサンプルコードは、Form1の親をExcelアプリケション、Form2のオーナーをForm1にするものです。
4
+ 以下のサンプルコードは、前面に表示したいフォのオーナーをExcelのハンドルを割り当てたNativeWindowにするものです。
6
5
 
7
6
  こんな風に表示されるようになります。
8
- Excelをクリックしても、Form2は前面表示されたままです。
7
+ Excelをクリックしても、Formは前面表示されたままです。
9
- ![イメージ説明](0294c6adb26449eabea8101217f05cb0.png)
8
+ ![イメージ説明](c545c2b86fe1d1ac5f9e1b2674b6f203.png)
10
9
 
11
-
12
10
  ```C#
13
11
  public partial class Form1 : Form
14
12
  {
15
13
 
16
- /// <summary>
17
- /// Changes the parent window of the specified child window.
18
- /// </summary>
19
- /// <param name="hWndChild">A handle to the child window.</param>
20
- /// <param name="hWndNewParent">A handle to the new parent window.</param>
21
- /// <returns>If the function succeeds, the return value is a handle to the previous parent window.</returns>
22
- [System.Runtime.InteropServices.DllImport("user32.dll")]
23
- static extern IntPtr SetParent(IntPtr hWndChild, IntPtr hWndNewParent);
24
-
25
- private void Form1_Shown(object sender, EventArgs e)
14
+ private void Form1_Load(object sender, EventArgs e)
26
15
  {
27
16
 
28
- var frm = (Form)sender;
29
-
30
- // Formを非表示にする
31
- frm.Visible = false;
32
-
33
17
  // Excel生成
34
18
  var app = new Microsoft.Office.Interop.Excel.Application
35
19
  {
36
20
  Visible = true
37
21
  };
38
22
 
39
- // FormExcelにす
23
+ // NativeWindowにExcelアプリケーションハンドル割り当て
24
+ var nw = new NativeWindow();
40
- SetParent(frm.Handle, (IntPtr)app.Hwnd);
25
+ nw.AssignHandle((IntPtr)app.Hwnd);
41
26
 
42
- // Form1をオーナーにしてForm2を開く
27
+ // ハンドルが割り当てられたNativeWindowをオーナーにしてFormを開く
28
+ // ここで生成するForm は自作ユーザーフォームでも可
43
- var form2 = new Form2();
29
+ var form = new Form();
44
- form2.Show(frm);
30
+ form.Show(nw);
45
31
 
32
+ // 前面に表示したフォームが閉じられた時に自身を閉じるイベントハンドラ
33
+ form.FormClosed += this.Form_FormClosed;
34
+
46
35
  }
47
36
 
37
+ private void Form_FormClosed(object sender, FormClosedEventArgs e)
38
+ {
39
+ this.Close();
48
- }
40
+ }
49
41
 
50
- public partial class Form2 : Form
51
- {
52
-
53
- private void Form2_FormClosed(object sender, FormClosedEventArgs e)
42
+ private void Form1_Shown(object sender, EventArgs e)
54
43
  {
55
44
 
56
- // Formを閉じる
57
- void closeForm(Form form)
45
+ ((Form)sender).Visible = false;
58
- {
59
- form.Close();
60
- }
61
46
 
62
- // 自身のオーナーフォームを非同期で閉じる
63
- var frm = (Form)sender;
64
- frm.Owner.BeginInvoke(new Action<Form>(closeForm), new Form[] { frm.Owner });
65
-
66
47
  }
67
48
 
68
49
  }
50
+
69
51
  ```