.NETや.NetFrameworkのWindowsFormの話になります。
ComboBoxのカスタムコントロールでWndProcメソッドをオーバーライドさせても、WM_PASTEは届きません。ComboBoxの文字入力部分は、実際は内部にあるEditコントロールの子ウィンドウによって実装されているため、親のComboBoxのWndProcにはWM_PASTEが届かないということの様です。
実際に古くからこのことは話題になっていました。VBですが、次のサイト↓のQAが良く取り上げられています。
「コンボボックスの右クリックの貼り付けイベント取得について」(1) Insider.NET − @IT
「コンボボックスの右クリックの貼り付けイベント取得について」に関する質問と回答の一覧です。(1) Insider.NET − @IT
解決策としては、Edit部分のウィンドウハンドルに対してサブクラス化してWM_PASTEを捕捉するということになります。それでは実際にC#ではどのようにプログラムしたら良いかやってみたいと思います。
①新しいプロジェクトでWindowsフォームをを選び、Form1だけできた状態にします。
②ソリューションエクスプローラーのツリーのプロジェクトを右クリックし「追加」→「新しい項目」で「カスタムコントロール」を追加します。名前は「CustomComboBox.cs」にすることにします。
③今追加したカスタムコントロールをコードビューにして、次のコードの様にします。
using System;
using System.Runtime.InteropServices;
using System.Windows.Forms;
namespace CustomComboboxTest
{
public partial class CustomComboBox : ComboBox
{
public CustomComboBox()
{
InitializeComponent();
}
private EditBoxNativeWindow _editWnd;
protected override void OnHandleCreated(EventArgs e)
{
base.OnHandleCreated(e);
AttachEditControl();
}
private void AttachEditControl()
{
COMBOBOXINFO info = new COMBOBOXINFO();
info.cbSize = Marshal.SizeOf(info);
if (GetComboBoxInfo(this.Handle, ref info))
{
_editWnd = new EditBoxNativeWindow(info.hwndEdit, this);
}
}
// COMBOBOXINFO構造体とP/Invoke
[StructLayout(LayoutKind.Sequential)]
private struct COMBOBOXINFO
{
public int cbSize;
public RECT rcItem;
public RECT rcButton;
public int stateButton;
public IntPtr hwndCombo;
public IntPtr hwndEdit;
public IntPtr hwndList;
}
[StructLayout(LayoutKind.Sequential)]
private struct RECT
{
public int Left, Top, Right, Bottom;
}
[DllImport("user32.dll")]
private static extern bool GetComboBoxInfo(IntPtr hwndCombo, ref COMBOBOXINFO info);
private class EditBoxNativeWindow : NativeWindow
{
private ComboBox _owner;
public EditBoxNativeWindow(IntPtr handle, ComboBox owner)
{
_owner = owner;
AssignHandle(handle);
}
protected override void WndProc(ref Message m)
{
const int WM_PASTE = 0x0302;
if (m.Msg == WM_PASTE)
{
if (Clipboard.ContainsText())
{
string pasted = Clipboard.GetText();
MessageBox.Show("貼り付け文字: " + pasted);
}
}
base.WndProc(ref m);
}
}
}
}
④一旦ビルドし、カスタムコントロールを使えるようにします。
⑤Form1のデザインビューに今追加したComboBoxのカスタムコントロール「CustomComboBox」を追加します。
⑥実行してみてください。CustomComboBoxに文字列を貼付けするとWM_PASTEで捕捉されメッセージボックスが表示されるはずです。
コメント