C#::ペースト禁止!

コントロールへの貼り付けを禁止する(メールアドレスの入力確認欄とか?)には、WM_PASTEを引っ掛けて何もしなければ良いです。つまり、

public class PasteDisabledTextBox : TextBox
{
  const int WM_PASTE = 0x0302;
  protected override void WndProc(ref Message m)
  {
    if (m.Msg != WM_PASTE) base.WndProc(ref m);
  }
}

こんなコントロールを使えばいいわけです。
これだけではアレなので、もう少し汎用的になるようにがんばってみようか。

public delegate bool WindowProc(ref Message m);

public static class WndProcOverrideExtension{
  //リストのprocを全部実行して戻り値をAND合成
  public static bool WndProcOverride(this IEnumerable<WindowProc> procs, ref Message m){
    bool res = true;
    foreach (var proc in procs){
      res &= proc(ref m);
    }
    return res;
  }
}

こんなふうにデリゲートを定義して、それを扱うための拡張メソッドを定義する。
実際に登録される関数として、たとえば次のようなものを用意して・・・

public static class StandardWndProcOverride{
  const int WM_PASTE = 0x0302;
  // ペーストを禁止します
  public static bool DisablePaste(ref Message m){
    return (m.Msg == WM_PASTE) ? false : true;
  }
}

最初のコントロールクラスを書き直すと、こんな感じ。

public class PasteDisabledTextBox : TextBox
  protected List<WindowProc> overrides = new List<WindowProc>();
  //コンストラクタ
  public PasteDisabledTextBox(){
    overrides.Add(StandardWndProcOverride.DisablePaste);
  }
  //ウィンドウプロシージャ
  protected override void WndProc(ref Message m){
    if (overrides.WndProcOverride(ref m)){
      base.WndProc(ref m);
    }
  }
}

ようは、base.WndProcを呼び出したくなくなるような処理をするときfalseを返す関数をリストに突っ込んで、WndProcではそのリストの中の関数を処理して、結果のANDがfalseでなければbase関数を呼ぶ、と。
あとは、DisablePasteみたいな関数を用途ごとに作って、コンストラクタあたりでリストにどんどん突っ込んでいけばいいわけですよ。デリゲートはクロージャなので大体の事はできるはず。何ならフック関数登録用のメソッドをクラスの外に公開してもいいね。

まぁ、今更ウィンドウメッセージをフックするとかあんまりやる機会ないんですけども、DirectShowあたりを使うときに地味に出てきたりする・・・。