7

ホスティング フォームにフォーカスがある限り、ツール ウィンドウも同様に WinForms でツール ウィンドウを作成する方法はありますか? この例は、Paint.NET にあります。

フォーカスされたツール ウィンドウ

.Net 4.0 の下で、バックエンド アプリケーション言語として C# を使用しています。

4

4 に答える 4

2

古いバージョンの 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 に設定する必要はありません。また、Form2MDI 子フォームではありません。

于 2013-05-23T18:42:52.967 に答える
0

DevExpress リボンフォームを使用している場合は、下のリンクの解決策を使用してフォーカスの問題を解決してください。zip ファイルは、ソリューション自体ではなく、ソリューションへのコメントにあります。

http://www.devexpress.com/Support/Center/Question/Details/Q498321

于 2013-06-06T08:19:51.913 に答える