ホスティング フォームにフォーカスがある限り、ツール ウィンドウも同様に WinForms でツール ウィンドウを作成する方法はありますか? この例は、Paint.NET にあります。
.Net 4.0 の下で、バックエンド アプリケーション言語として C# を使用しています。
古いバージョンの Paint.Net のソース コードは、openpdn Fork of Paint.NET 3.36.7で入手できます。
私はそのソース コードから彼らのメソッドを抽出して、私が集めることができる最も簡潔な動作例にしようとしました。
ピンヴォーク クラス:
internal static class Win32 {
public const int WM_ACTIVATE = 0x006;
public const int WM_ACTIVATEAPP = 0x01C;
public const int WM_NCACTIVATE = 0x086;
[DllImport("user32.dll", SetLastError = false)]
internal static extern IntPtr SendMessageW(IntPtr hWnd, uint msg,
IntPtr wParam, IntPtr lParam);
[DllImport("user32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
internal extern static bool PostMessageW(IntPtr handle, uint msg,
IntPtr wParam, IntPtr lParam);
}
ベースフォーム:
public partial class Form1 : Form {
public Form1() {
InitializeComponent();
}
private bool ignoreNcActivate = false;
protected override void WndProc(ref Message m) {
base.WndProc(ref m);
switch (m.Msg) {
case Win32.WM_NCACTIVATE:
if (m.WParam == IntPtr.Zero) {
if (ignoreNcActivate) {
ignoreNcActivate = false;
} else {
Win32.SendMessageW(this.Handle, Win32.WM_NCACTIVATE, new IntPtr(1), IntPtr.Zero);
}
}
break;
case Win32.WM_ACTIVATEAPP:
if (m.WParam == IntPtr.Zero) {
Win32.PostMessageW(this.Handle, Win32.WM_NCACTIVATE, IntPtr.Zero, IntPtr.Zero);
foreach (Form2 f in this.OwnedForms.OfType<Form2>()) {
f.ForceActiveBar = false;
Win32.PostMessageW(f.Handle, Win32.WM_NCACTIVATE, IntPtr.Zero, IntPtr.Zero);
}
ignoreNcActivate = true;
} else if (m.WParam == new IntPtr(1)) {
Win32.SendMessageW(this.Handle, Win32.WM_NCACTIVATE, new IntPtr(1), IntPtr.Zero);
foreach (Form2 f in this.OwnedForms.OfType<Form2>()) {
f.ForceActiveBar = true;
Win32.SendMessageW(f.Handle, Win32.WM_NCACTIVATE, new IntPtr(1), IntPtr.Zero);
}
}
break;
}
}
protected override void OnShown(EventArgs e) {
base.OnShown(e);
Form2 f = new Form2();
f.Show(this);
}
}
常にアクティブな Form2 (アプリがアクティブでない場合を除く):
public partial class Form2 : Form {
internal bool ForceActiveBar { get; set; }
public Form2() {
InitializeComponent();
this.ShowInTaskbar = false;
this.ForceActiveBar = true;
}
protected override void WndProc(ref Message m) {
base.WndProc(ref m);
if (m.Msg == Win32.WM_NCACTIVATE) {
if (this.ForceActiveBar && m.WParam == IntPtr.Zero) {
Win32.SendMessageW(this.Handle, Win32.WM_NCACTIVATE, new IntPtr(1), IntPtr.Zero);
}
}
}
}
Form2は、表示されるときにメイン フォームによって所有される必要があるため、TopMost を true に設定する必要はありません。また、Form2はMDI 子フォームではありません。
DevExpress リボンフォームを使用している場合は、下のリンクの解決策を使用してフォーカスの問題を解決してください。zip ファイルは、ソリューション自体ではなく、ソリューションへのコメントにあります。
http://www.devexpress.com/Support/Center/Question/Details/Q498321