Edited at

WPFアプリケーションでウィンドウプロシージャをフックする

More than 3 years have passed since last update.

WPFアプリケーションでウィンドウプロシージャをフックしたい場合、HwndSource.FromHwndメソッドを呼び出して、HwndSourceオブジェクトを取得し、そのオブジェクトに対してHwndSource.AddHookメソッドを呼び出すことで行います。


MSDN : HwndSource クラス (System.Windows.Interop)


以下のコードは、WPFでは通常取得できない、ALT+F4キーの押下を検知して無効化するサンプルです。

当たり前ですがフックをWindowの生成が終わった後でないとエラーになります。サンプルでは、MainWindowクラスのLoadedイベント内でフックを実行しています。


WindowHookSample.xaml


<Window x:Class="WindowHookSample.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">
<Grid>
<Button Name="CloseButton" Content="Close" VerticalAlignment="Center" HorizontalAlignment="Center" Width="100" Height="40" />
</Grid>
</Window>



WindowHookSample.xaml.cs


using System;
using System.Windows;
using System.Windows.Interop;

namespace WindowHookSample
{
/// <summary>
/// MainWindow.xaml の相互作用ロジック
/// </summary>
public partial class MainWindow : Window
{
private static readonly int WM_SYSKEYDOWN = 0x0104;
private static readonly int VK_F4 = 0x73;

/// <summary>
/// コンストラクタ
/// </summary>
public MainWindow()
{
InitializeComponent();

Loaded += (o, e) =>
{
var source = HwndSource.FromHwnd(new WindowInteropHelper(this).Handle);
source.AddHook(new HwndSourceHook(WndProc));
};

CloseButton.Click += (o, e) => { Close(); };
}

/// <summary>
/// ウィンドウプロシージャ
/// </summary>
/// <param name="hwnd">IntPtr : ウィンドウハンドル</param>
/// <param name="msg">int : メッセージ</param>
/// <param name="wParam">IntPtr : パラメータ</param>
/// <param name="lParam">IntPtr : パラメータ</param>
/// <param name="handled">ref book : ハンドルフラグ</param>
/// <returns>IntPtr</returns>
private static IntPtr WndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
{
// ALT+F4キーを無効化する
if ((msg == WM_SYSKEYDOWN) && (wParam.ToInt32() == VK_F4))
handled = true;
return IntPtr.Zero;
}
}
}