回答編集履歴

1

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

2019/12/25 04:54

投稿

Masahiro-Ito
Masahiro-Ito

スコア24

test CHANGED
@@ -1,22 +1,18 @@
1
- Excelの前面に表示したいフォームのオーナーの親をExcelにすることで解決しました。
1
+ Excelの前面に表示したいフォームのオーナーをExcelのハンドルを割り当てたNativeWindowにすることで解決しました。
2
2
 
3
- 自身のオーナーの親をExcelアプリケーションにすることでフォームは常にExcelの前面に表示されます。
3
+ 自身のオーナーをExcelのハドルを割り当てたNativeWindowにすることでフォームは常にExcelの前面に表示されます。
4
-
5
- フォームの親を設定するためにSetParent関数を使用します。Excelの前面に表示したいフォームの親をExcelアプリケーションにしてもExcelの前面に表示されるのですが、そのフォームはExcelのメインウインドウの中に表示される(MDIの子フォームのように表示される)ので、自身ではなく自身のオーナーの親をExcelアプリケーションにします。
6
4
 
7
5
 
8
6
 
9
- 以下のサンプルコードは、Form1をExcelアプリケーショ、Form2のオーナーForm1にするものです。
7
+ 以下のサンプルコードは、前面に表示したいフォームオーナーをExcelのハドル割り当てたNativeWindowにするものです。
10
8
 
11
9
 
12
10
 
13
11
  こんな風に表示されるようになります。
14
12
 
15
- Excelをクリックしても、Form2は前面表示されたままです。
13
+ Excelをクリックしても、Formは前面表示されたままです。
16
14
 
17
- ![イメージ説明](0294c6adb26449eabea8101217f05cb0.png)
15
+ ![イメージ説明](c545c2b86fe1d1ac5f9e1b2674b6f203.png)
18
-
19
-
20
16
 
21
17
 
22
18
 
@@ -28,37 +24,9 @@
28
24
 
29
25
 
30
26
 
31
- /// <summary>
32
-
33
- /// Changes the parent window of the specified child window.
34
-
35
- /// </summary>
36
-
37
- /// <param name="hWndChild">A handle to the child window.</param>
38
-
39
- /// <param name="hWndNewParent">A handle to the new parent window.</param>
40
-
41
- /// <returns>If the function succeeds, the return value is a handle to the previous parent window.</returns>
42
-
43
- [System.Runtime.InteropServices.DllImport("user32.dll")]
44
-
45
- static extern IntPtr SetParent(IntPtr hWndChild, IntPtr hWndNewParent);
46
-
47
-
48
-
49
- private void Form1_Shown(object sender, EventArgs e)
27
+ private void Form1_Load(object sender, EventArgs e)
50
28
 
51
29
  {
52
-
53
-
54
-
55
- var frm = (Form)sender;
56
-
57
-
58
-
59
- // Formを非表示にする
60
-
61
- frm.Visible = false;
62
30
 
63
31
 
64
32
 
@@ -74,17 +42,51 @@
74
42
 
75
43
 
76
44
 
77
- // Formの親をExcelにす
45
+ // NativeWindowにExcelアプリケーションのハンドルを割り当て
78
46
 
47
+ var nw = new NativeWindow();
48
+
79
- SetParent(frm.Handle, (IntPtr)app.Hwnd);
49
+ nw.AssignHandle((IntPtr)app.Hwnd);
80
50
 
81
51
 
82
52
 
83
- // Form1をオーナーにしてForm2を開く
53
+ // ハンドルが割り当てられたNativeWindowをオーナーにしてFormを開く
84
54
 
85
- var form2 = new Form2();
55
+ // ここで生成するForm は自作ユーザーフォームでも可
86
56
 
57
+ var form = new Form();
58
+
87
- form2.Show(frm);
59
+ form.Show(nw);
60
+
61
+
62
+
63
+ // 前面に表示したフォームが閉じられた時に自身を閉じるイベントハンドラ
64
+
65
+ form.FormClosed += this.Form_FormClosed;
66
+
67
+
68
+
69
+ }
70
+
71
+
72
+
73
+ private void Form_FormClosed(object sender, FormClosedEventArgs e)
74
+
75
+ {
76
+
77
+ this.Close();
78
+
79
+ }
80
+
81
+
82
+
83
+ private void Form1_Shown(object sender, EventArgs e)
84
+
85
+ {
86
+
87
+
88
+
89
+ ((Form)sender).Visible = false;
88
90
 
89
91
 
90
92
 
@@ -96,42 +98,4 @@
96
98
 
97
99
 
98
100
 
99
- public partial class Form2 : Form
100
-
101
- {
102
-
103
-
104
-
105
- private void Form2_FormClosed(object sender, FormClosedEventArgs e)
106
-
107
- {
108
-
109
-
110
-
111
- // Formを閉じる
112
-
113
- void closeForm(Form form)
114
-
115
- {
116
-
117
- form.Close();
118
-
119
- }
120
-
121
-
122
-
123
- // 自身のオーナーフォームを非同期で閉じる
124
-
125
- var frm = (Form)sender;
126
-
127
- frm.Owner.BeginInvoke(new Action<Form>(closeForm), new Form[] { frm.Owner });
128
-
129
-
130
-
131
- }
132
-
133
-
134
-
135
- }
136
-
137
101
  ```