VBComboBox の全ソースです。

ReadOnly のときのコンテキストメニューをなんとかしたいところですが、自前で実装するのはイヤなので、何か方法を見つけたら対応することにします。

 using System;
 using System.ComponentModel;
 using System.Diagnostics;
 using System.Drawing;
 using System.Windows.Forms;
 using System.Runtime.InteropServices; 
 
 namespace VB6Control
 {
     public class VBComboBox : ComboBox 
     {
 
         private int m_NewIndex = -1;
         private bool m_ReadOnly = false;
 
         private Color m_ForeColor = Color.Empty;
         private Color m_DefaultForeColor = SystemColors.WindowText;
 
         private IntPtr m_EditBoxHandle = IntPtr.Zero;
         private IntPtr m_ListBoxBoxHandle = IntPtr.Zero;
         private EditBoxWindow m_EditBoxWindow = null;
         private ListBoxWindow m_ListBoxWindow = null;
 
         public event EventHandler ReadOnlyChanged;
 
         // Window メッセージ
 
         const int
         WM_ENABLE = 0x000A,
         WM_NCDESTROY = 0x0082,
         WM_VSCROLL = 0x0115,
 
         // キーボードメッセージ
         WM_KEYFIRST = 0x0100,
         WM_KEYDOWN = 0x0100,
         WM_KEYUP = 0x0101,
         WM_CHAR = 0x0102,
         WM_DEADCHAR = 0x0103,
         WM_CTLCOLOR = 0x0019,
         WM_SYSKEYDOWN = 0x0104,
         WM_SYSKEYUP = 0x0105,
         WM_SYSCHAR = 0x0106,
         WM_SYSDEADCHAR = 0x0107,
         WM_KEYLAST = 0x0108,
             
         // マウスメッセージ
 
         WM_MOUSEFIRST = 0x0200,
         WM_MOUSEMOVE = 0x0200,
         WM_LBUTTONDOWN = 0x0201,
         WM_LBUTTONUP = 0x0202,
         WM_LBUTTONDBLCLK = 0x0203,
         WM_RBUTTONDOWN = 0x0204,
         WM_RBUTTONUP = 0x0205,
         WM_RBUTTONDBLCLK = 0x0206,
         WM_MBUTTONDOWN = 0x0207,
         WM_MBUTTONUP = 0x0208,
         WM_MBUTTONDBLCLK = 0x0209,
         WM_XBUTTONDOWN = 0x020B,
         WM_XBUTTONUP = 0x020C,
         WM_XBUTTONDBLCLK = 0x020D,
         WM_MOUSEWHEEL = 0x020A,
         WM_MOUSELAST = 0x020A,
 
         // 非クライアント領域への Mouse メッセージ
 
         WM_NCMOUSEMOVE = 0x00A0,
         WM_NCMOUSELEAVE = 0x02A2,
         WM_NCLBUTTONDOWN = 0x00A1,
         WM_NCLBUTTONUP = 0x00A2,
         WM_NCLBUTTONDBLCLK = 0x00A3,
         WM_NCRBUTTONDOWN = 0x00A4,
         WM_NCRBUTTONUP = 0x00A5,
         WM_NCRBUTTONDBLCLK = 0x00A6,
         WM_NCMBUTTONDOWN = 0x00A7,
         WM_NCMBUTTONUP = 0x00A8,
         WM_NCMBUTTONDBLCLK = 0x00A9,
         WM_NCXBUTTONDOWN = 0x00AB,
         WM_NCXBUTTONUP = 0x00AC,
         WM_NCXBUTTONDBLCLK = 0x00AD,
 
         // ComboBox メッセージ
 
         CB_ADDSTRING = 0x0143,
         CB_DELETESTRING = 0x0144,
         CB_INSERTSTRING = 0x014A,
         CB_RESETCONTENT = 0x014B,
 
         // ListBox メッセージ
 
         LB_ERR = -1,
         LB_SETCURSEL = 0x0186,
         LB_GETCURSEL = 0x0188,
         LB_GETTOPINDEX = 0x018E,
         LB_SETTOPINDEX = 0x0197;
 
         [StructLayout(LayoutKind.Sequential)]
         private class ComboBoxInfo
         {
             public int Size;
             public Rectangle RectItem;
             public Rectangle RectButton;
             public int ButtonState;
             public IntPtr ComboBoxHandle;
             public IntPtr EditBoxHandle;
             public IntPtr ListBoxHandle;
             public ComboBoxInfo()
             {
                 this.Size = Marshal.SizeOf(this);
             }
         }
 
         [DllImport("user32")]
         private static extern bool GetComboBoxInfo(HandleRef hwndCombo, ComboBoxInfo cbinfo);
 
         [DllImport("user32", CharSet = CharSet.Auto)]
         private extern static IntPtr SendMessage(IntPtr hwnd, int wMsg, IntPtr wParam, IntPtr lParam);
 
         [DllImport("user32.dll")]
         private static extern bool GetClientRect(HandleRef hwnd, ref Rectangle lpRect);
 
         public VBComboBox()
         {
             base.BackColor = SystemColors.Window;
         }
 
         [DefaultValue(typeof(Color), "Window")] 
         public override Color BackColor
         {
             get { return base.BackColor; }
             set { base.BackColor = value; }
         }
 
         [DllImport("user32")]
         private static extern bool EnableWindow(IntPtr hWnd, bool fEnable);
 
         protected override void OnHandleCreated(EventArgs e)
         {
             base.OnHandleCreated(e);
 
             HandleRef hr = new HandleRef(this, this.Handle);
             ComboBoxInfo ci = new ComboBoxInfo();
 
             if (GetComboBoxInfo(hr, ci))
             {
                 m_EditBoxHandle = ci.EditBoxHandle;
                 m_ListBoxBoxHandle = ci.ListBoxHandle;
             }
             else
             {
                 m_EditBoxHandle = IntPtr.Zero;
                 m_ListBoxBoxHandle = IntPtr.Zero;
             }
 
             AssignChildWindows();
             EnableWindow(this.Handle, true);
             OnEnabledChanged(EventArgs.Empty);  
         }
 
         private IntPtr EditBoxHandle
         {
             get { return m_EditBoxHandle; }
         }
 
         private IntPtr ListBoxHandle
         {
             get { return m_ListBoxBoxHandle; }
         }
 
         [Browsable(false)]
         [EditorBrowsable(EditorBrowsableState.Always)]
         [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
         public int TopIndex
         {
             get { return (int)SendMessage(ListBoxHandle, LB_GETTOPINDEX, IntPtr.Zero, IntPtr.Zero); }
             set { SendMessage(ListBoxHandle, LB_SETTOPINDEX, (IntPtr)value, IntPtr.Zero); }
         }
 
         [Browsable(false)]
         [EditorBrowsable(EditorBrowsableState.Always)]
         [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
         public int NewIndex
         {
             get { return m_NewIndex; }
         }
 
         public event EventHandler Scroll;
 
         protected virtual void OnScroll(EventArgs e)
         {
             if (Scroll != null) Scroll(this, e);
         }
 
         private void AssignChildWindows()
         {
             if (EditBoxHandle != IntPtr.Zero)
             {
                 m_EditBoxWindow = new EditBoxWindow(this);
             }
             if (ListBoxHandle != IntPtr.Zero)
             {
                 m_ListBoxWindow = new ListBoxWindow(this);
             }
         }
 
         private void ReleaseChildWindows()
         {
             if (m_EditBoxWindow != null)
             {
                 m_EditBoxWindow.ReleaseHandle();
                 m_EditBoxWindow = null;
             }
             if (m_ListBoxWindow != null)
             {
                 m_ListBoxWindow.ReleaseHandle();
                 m_ListBoxWindow = null;
             }
         }
 
         private void DecidesColor()
         {
             if (base.IsHandleCreated)
                 EnableWindow(base.Handle, m_Enabled);
 
             if (m_Enabled)
                 if (m_ForeColor.IsEmpty)
                     base.ForeColor = m_DefaultForeColor;
                 else
                     base.ForeColor = m_ForeColor;
             else
                 base.ForeColor = SystemColors.GrayText;
         }
 
         [DefaultValue(typeof(Color), "WindowText")]
         public new Color ForeColor
         {
             get
             {
                 if (m_ForeColor.IsEmpty)
                     return m_DefaultForeColor;
                 else
                     return m_ForeColor;
             }
             set
             {
                 if (m_ForeColor != value)
                 {
                     m_ForeColor = value;
                     DecidesColor();
                     OnForeColorChanged(EventArgs.Empty);
                 }
             }
         }
 
         public new event EventHandler ForeColorChanged;
 
         protected new virtual void OnForeColorChanged(EventArgs e)
         {
             if (ForeColorChanged != null) ForeColorChanged(this, e);
         }
 
         protected override void OnEnabledChanged(EventArgs e)
         {
             base.OnEnabledChanged(e);
             DecidesColor();
         }
 
         [Browsable(true)]
         [EditorBrowsable(EditorBrowsableState.Always)]
         [DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
         public virtual bool ReadOnly
         {
             get { return m_ReadOnly; }
             set 
             {
                 if (m_ReadOnly != value)
                 {
                     m_ReadOnly = value;
                     OnReadOnlyChanged(EventArgs.Empty);
                 }
             }
         }
 
         protected virtual void OnReadOnlyChanged(EventArgs e)
         {
             if (ReadOnlyChanged != null) ReadOnlyChanged(this, e);
         }
 
         public override string Text
         {
             get { return base.Text; }
             set
             {
                 bool readOnly = m_ReadOnly;
                 m_ReadOnly = false;
                 base.Text = value;
                 m_ReadOnly = readOnly;
             }
         }
 
         public override int SelectedIndex
         {
             get { return base.SelectedIndex; }
             set
             {
                 bool readOnly = m_ReadOnly;
                 m_ReadOnly = false;
                 base.SelectedIndex = value;
                 m_ReadOnly = readOnly;
             }
         }
 
         private static int HIWORD(int n)
         {
             return (n >> 16) & 0xffff;
         }
 
         private static int HIWORD(IntPtr n)
         {
             return HIWORD(unchecked((int)(long)n));
         }
 
         private static int LOWORD(int n)
         {
             return n & 0xffff;
         }
 
         private static int LOWORD(IntPtr n)
         {
             return LOWORD(unchecked((int)(long)n));
         }
 
         [DebuggerStepThrough]
         protected override void WndProc(ref Message m)
         {
             switch (m.Msg)
             {
                 case CB_ADDSTRING:
                     // 追加されたときは戻り値が NewIndex 
                     base.WndProc(ref m);
                     m_NewIndex = m.Result.ToInt32();
                     break;
 
                 case CB_INSERTSTRING:
                     // 挿入されたときは WParam が NewIndex 
                     base.WndProc(ref m);
                     m_NewIndex = m.WParam.ToInt32();
                     break;
 
                 case CB_DELETESTRING:
                 case CB_RESETCONTENT:
                     // 削除、クリアされたときは -1 に戻します
                     base.WndProc(ref m);
                     m_NewIndex = -1;
                     break;
 
                 // 子ウインドウをリリース
                 case WM_NCDESTROY:
                     base.WndProc(ref m);
                     ReleaseChildWindows();
                     break;
 
                 // Enable = false のメッセージは握りつぶす
                 case WM_ENABLE:
                     if (m.WParam != IntPtr.Zero) base.WndProc(ref m);
                     break;
 
                 default:
                     base.WndProc(ref m);
                     break;
             }
         }
 
         private class ListBoxWindow : NativeWindow
         {
             private VBComboBox m_Owner;
 
             public ListBoxWindow(VBComboBox owner)
             {
                 m_Owner = owner;
                 this.AssignHandle(owner.ListBoxHandle);
             }
 
             private bool IsIgnoreMessage(Message m)
             {
                 if (m.Msg >= WM_KEYFIRST && m.Msg <= WM_KEYLAST)
                 {
                     if (m.Msg == WM_KEYDOWN && (Keys)m.WParam == Keys.F4) return false;
 
                     return true;
                 }
 
                 if (m.Msg >= WM_MOUSEFIRST && m.Msg <= WM_MOUSELAST)
                 {
                     Rectangle clientRect = new Rectangle();
                     if (GetClientRect(new HandleRef(this, this.Handle), ref clientRect))
                     {
                         int x = LOWORD(m.LParam);
                         int y = HIWORD(m.LParam);
                        if (!clientRect.Contains(x, y)) return false;
                     }
                     return true;
                 }
                 return false;
             }
 
             protected override void WndProc(ref Message m)
             {
                 switch (m.Msg)
                 {
                     case WM_VSCROLL:
                         base.WndProc(ref m);
                         m_Owner.OnScroll(EventArgs.Empty);
                         break;
 
                     default:
                         if (m_Owner.ReadOnly && IsIgnoreMessage(m)) break;
                         base.WndProc(ref m);
                         break;
                 }
             }
         }
 
         private class EditBoxWindow : NativeWindow
         {
             VBComboBox m_Owner;
 
             public EditBoxWindow(VBComboBox owner)
             {
                 m_Owner = owner;
                 this.AssignHandle(owner.EditBoxHandle);
             }
 
             protected override void WndProc(ref Message m)
             {
                 const int CTRL_C = 0x03; // CTRL + C
                 const int
                 WM_CHAR = 0x0102,
                 WM_CUT = 0x0300,
                 //WM_COPY = 0x0301,     WM_COPY は許可
                 WM_PASTE = 0x0302,
                 WM_CLEAR = 0x0303,
                 WM_UNDO = 0x0304,
                 WM_SETTEXT = 0x000C;
 
                 switch (m.Msg)
                 {
                     case WM_CHAR:
                         if ((!m_Owner.ReadOnly) || (m.WParam == (IntPtr)CTRL_C)) base.WndProc(ref m);
                         break;
 
                     case WM_CUT:
                     case WM_PASTE:
                     case WM_CLEAR:
                     case WM_UNDO:
                     case WM_SETTEXT:
                         if (!m_Owner.ReadOnly) base.WndProc(ref m);
                         break;
 
                     default:
                         base.WndProc(ref m);
                         break;
                 }
             }
         }
     }
 }



トップ   編集 凍結 差分 バックアップ 添付 複製 名前変更 リロード   新規 一覧 単語検索 最終更新   最終更新のRSS
Last-modified: 2013-03-15 (金) 12:34:34 (1616d)