kkAyatakaのメモ帳。

誰かの役に立つかもしれない備忘録。

WPFでWindow MessageのHook

Windows Forms同じくオーバーライドかなぁと思っていたら全然違いました。

using System.Windows.Interop;

var wnd = new Window();
wnd.Show();

// Show()の後で無いと取れません。
var handle = new WindowInteropHelper(wnd).Handle;
var src = HwndSource.FromHwnd(handle);
src.AddHook(MessageHook);

private IntPtr MessageHook(IntPtr hwnd, int msg, IntPtr wp, IntPtr lp, ref bool handle)
{
  return IntPtr.Zero;
}

特にコンストラクタ時点でハンドルが取れません。Window Messageのハンドリング用にウィンドウを作ったりする場合は(Hot Keyとかね)コンストラクタ内でShow()を呼び出しておけばよい感じ。

Messageハンドリング専用の場合、いろいろと設定して、表示されないように細工が必要でしょう。

private class MsgWnd : Window
{
  public MsgWnd()
  {
    this.Top = -100000;
    this.Left = -100000;
    this.Width = 0;
    this.Height = 0;
    this.WindowStyle = WindowStyle.None;
    this.AllowsTransparency = true;
    this.Background = Brushes.Transparent;

    this.ShowInTaskbar = false;
    this.ShowActivated = false;

    this.SourceInitialized += MsgWnd_SourceInitialized;
    this.Show();
  }

  public IntPtr Handle
  {
    get
    {
      if (handle == IntPtr.Zero)
      {
        handle = new WindowInteropHelper(this).Handle;
      }
      return handle;
    }
  }
  private IntPtr handle;
  
  private void MsgWnd_SourceInitialized(object sender, EventArgs e)
  {
    try
    {
      HwndSource src = HwndSource.FromHwnd(Handle);
      src.AddHook(MessageHook);
    }
    catch (Exception ex)
    {
      Console.WriteLine(ex.Message);
    }
  }

  private IntPtr MessageHook(IntPtr hwnd, int msg, IntPtr wp, IntPtr lp, ref bool handle)
  {
    return IntPtr.Zero;
  }
}