C# ComboBoxのWM_CHARをフックする

ドロップダウン型のコンボボックスはテキストを入力するためのエディット部を持っている。入力制限をかける等の処理を介入させるにはWM_CHARをフックしたいところだ。コンボボックスに対してはWM_CHARは発生しないので、このエディット部をサブクラス化する必要がある。ところが.Net Frameworkにはこのエディット部のハンドルを取得する機能が実装されていない。どうやらWinAPIを使うしかないようだ。
以下はWM_CHARをフックするための万能クラスだ。
コントロールがComboBoxの時はWinAPIのGetWindowでエディット部のハンドルを取得し、これをサブクラス化している。
尚、OnHandleDestroyedはハンドルが破棄された場合の連動、OnHandleCreatedはRecreateHandleでハンドルが再度作成された場合の対処だ。

class WmcharHook : NativeWindow {
  private const int WM_CHAR = 0x102;
  enum GetWindow_Cmd : uint {
    GW_HWNDFIRST = 0,
    GW_HWNDLAST = 1,
    GW_HWNDNEXT = 2,
    GW_HWNDPREV = 3,
    GW_OWNER = 4,
    GW_CHILD = 5,
    GW_ENABLEDPOPUP = 6
  }
  [DllImport("user32.dll", SetLastError = true)]
  static extern
         IntPtr GetWindow(IntPtr hWnd, GetWindow_Cmd uCmd);

  public WmcharHook(Control c) {
    IntPtr handle = c.Handle;
    if (c is ComboBox) {
      handle = GetWindow(c.Handle, GetWindow_Cmd.GW_CHILD);
    }
    AssignHandle(handle);
    c.HandleDestroyed += new EventHandler(OnHandleDestroyed);
    c.HandleCreated += new EventHandler(OnHandleCreated);
  }
  internal void OnHandleDestroyed(object sender, EventArgs e) {
    ReleaseHandle();
  }
  internal void OnHandleCreated(object sender, EventArgs e) {
    if (sender is Control) {
      AssignHandle(((Control)sender).Handle);
    }
  }
  protected override
       void WndProc(ref System.Windows.Forms.Message m) {
    switch (m.Msg) {
    case WM_CHAR:
      ///
      /// ここにフック処理をどうぞ
      ///
      break;
    }
    base.WndProc(ref m);
  }
}

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です