⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 comboboxbase.cs

📁 c#编写的仿OUTLOOK工具条的Winform菜单
💻 CS
📖 第 1 页 / 共 2 页
字号:
using System;
using System.Collections;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Windows.Forms;
using System.Diagnostics;
using System.Security;
using System.Runtime.InteropServices;


using UtilityLibrary.General;
using UtilityLibrary.Win32;


namespace UtilityLibrary.WinControls
{

	#region Helper Classes
	internal class EditCtrlHook : System.Windows.Forms.NativeWindow
	{
		
		#region Class Variables
		ComboBoxBase comboBox = null;
		bool ignoreNextPaintMessage = false;
		#endregion
		
		#region Constructors
		public EditCtrlHook(ComboBoxBase cb)
		{
			comboBox = cb;
		}
		#endregion

		#region Overrides
		protected override  void WndProc(ref Message m)
		{
			Msg currentMessage = (Msg)m.Msg;
						
			switch(m.Msg)
			{
				case ((int)Msg.WM_PAINT):
					if ( ignoreNextPaintMessage )
					{
						ignoreNextPaintMessage = false;
						return;
					}
					if ( comboBox.forceUpdate &&  comboBox.DroppedDown == false )
					{
						comboBox.forceUpdate = false;
						comboBox.ForceUpdate();
					}

					if ( comboBox.Enabled == false ) 
					{
						// Let the edit control do its thing first
						base.WndProc(ref m);
						// This is going to generate another paint message
						// ignore it
						ignoreNextPaintMessage = true;
						DrawDisableState();
						return;
					}

					break;
				case ((int)Msg.WM_MOUSEMOVE):
					RequestMouseLeaveMessage(m.HWnd); 
					if ( comboBox.highlighted == false)
					{
						using (Graphics g = Graphics.FromHwnd(comboBox.Handle))
						{
							comboBox.DrawComboBoxBorder(g, ColorUtil.VSNetBorderColor);
							comboBox.DrawComboBoxArrowSelected(g, false);
						}
					}
					break;
				case ((int)Msg.WM_MOUSELEAVE):
					if ( comboBox.highlighted == true && !comboBox.ContainsFocus)
					{
						using (Graphics g = Graphics.FromHwnd(comboBox.Handle))
						{
							comboBox.DrawComboBoxBorder(g, SystemColors.Window);
							comboBox.DrawComboBoxArrowNormal(g, false);
						}
					}
					break;
				default:
					break;
			}

			base.WndProc(ref m);
		
		}

		#endregion

		#region Implementation
		void RequestMouseLeaveMessage(IntPtr hWnd)
		{
			// Crea the structure needed for WindowsAPI call
			Win32.TRACKMOUSEEVENTS tme = new Win32.TRACKMOUSEEVENTS();

			// Fill in the structure
			tme.cbSize = 16;									
			tme.dwFlags = (uint)Win32.TrackerEventFlags.TME_LEAVE;
			tme.hWnd = hWnd;								
			tme.dwHoverTime = 0;								

			// Request that a message gets sent when mouse leaves this window
			WindowsAPI.TrackMouseEvent(ref tme);
		}

		void DrawDisableState()
		{
			// we are just going to fill the edit area
			// with a white background, the combobox 
			// already does the hard part
			using (Graphics g = Graphics.FromHwnd(Handle))
			{
				RECT rc = new RECT();
				WindowsAPI.GetClientRect(Handle, ref rc);
				Rectangle clientSize = new Rectangle(rc.left, rc.top, rc.right-rc.left, rc.bottom-rc.top);
				g.FillRectangle(Brushes.White, clientSize);

				// Draw text
				STRINGBUFFER buffer;
				WindowsAPI.GetWindowText(Handle, out buffer, 512);
				using ( Brush b = new SolidBrush(SystemColors.ControlDark) )
				{
					string text = buffer.szText;
					Size textSize = TextUtil.GetTextSize(g, text, SystemInformation.MenuFont);
					Point pt = new Point(rc.left, rc.top + ( rc.bottom-textSize.Height )/2);
					g.DrawString(text, comboBox.Font, b, pt);
				}
			}
		}

		#endregion

	}

	#endregion

	/// <summary>
	/// Summary description for ComboBoxBase.
	/// </summary>
	[ToolboxItem(false)]
	public class ComboBoxBase : System.Windows.Forms.ComboBox
	{
		#region Class Variables
		private IntPtr mouseHookHandle = IntPtr.Zero;
		private GCHandle mouseProcHandle;
		private bool toolBarUse = false;
		private bool hooked = false;
		public const int ARROW_WIDTH = 12;
		private EditCtrlHook editHook = null;
		internal bool forceUpdate = false;
		internal bool highlighted = false;
		bool fireOnSelectedIndexChanged = true;
		#endregion
		
		#region Constructors
		// I wanted to make this constructor either protected
		// or internal so that the ComboBoxBase could not be used
		// as a stand alone class, however the IDE designer complains about it
		// if the constructors are not public
		public ComboBoxBase(bool toolBarUse)
		{
			// Flag to indicate that combo box will be used
			// in a toolbar --which means we will use some window hooks
			// to reset the focus of the combobox--
			this.toolBarUse = toolBarUse;
			DrawMode = DrawMode.OwnerDrawFixed;
			SetStyle(ControlStyles.AllPaintingInWmPaint|ControlStyles.UserPaint|ControlStyles.DoubleBuffer, true);
			// Use Menu font so that the combobox uses the same font as the toolbar buttons
			Font = SystemInformation.MenuFont;
			// When use in a toolbar we don't need tab stop
			TabStop = false;
         }

		// I wanted to make this constructor either protected
		// or internal so that the ComboBoxBase could not be used
		// as a stand alone class, however the IDE designer complains about it
		// if the constructors are not public
		public ComboBoxBase()
		{
			DrawMode = DrawMode.OwnerDrawFixed;
			SetStyle(ControlStyles.AllPaintingInWmPaint
				|ControlStyles.UserPaint|ControlStyles.Opaque|ControlStyles.DoubleBuffer, true);
		}

		#endregion

		#region Overrides
		protected override void OnPaint(PaintEventArgs pe)
		{
			// This on paint is only going to happen for the combobox if 
			// the combobox has been set the style to do all painting
			// in the OnPaint event
			base.OnPaint(pe);
			if ( DropDownStyle == ComboBoxStyle.DropDown )
			{
				// We will handle the painting from WM_PAINT
				return;
			}

			if (Enabled == false)
			{
				DrawDisableState();
				return;
			}
			
			PaintComboBoxBackground(pe.Graphics, SystemColors.Window);
			Rectangle rc = ClientRectangle;
			if ( SelectedIndex == -1 ) 
			{
				if ( Items.Count > 0 )
				{
					// Select first item as the current item
					fireOnSelectedIndexChanged  = false;
					SelectedIndex = 0;
				}
			}
			
			DrawComboBoxItemEx( pe.Graphics, rc, SelectedIndex, false, true);
			if ( !ContainsFocus )
			{
				DrawComboBoxBorder(pe.Graphics, SystemColors.Window);
				DrawComboBoxArrowNormal(pe.Graphics, true);
			}
			else
			{
				DrawComboBoxBorder(pe.Graphics, ColorUtil.VSNetBorderColor);
			}
		}

		protected override void OnHandleCreated(EventArgs e)
		{
			base.OnHandleCreated(e);
			// Hook the edit control
			if ( DropDownStyle == ComboBoxStyle.DropDown )
			{
				IntPtr hEditControl = WindowsAPI.GetDlgItem(Handle, 0x3E9);
				Debug.Assert(hEditControl != IntPtr.Zero, "Fail to get ComboBox's Edit Control Handle...");
				editHook = new EditCtrlHook(this);
				editHook.AssignHandle(hEditControl);
			}
		}

		protected override void OnDrawItem(DrawItemEventArgs e)
		{
			// Draw bitmap strech to the size of the size of the combobox
			Graphics g = e.Graphics;
			Rectangle bounds = e.Bounds;
			bool selected = (e.State & DrawItemState.Selected) > 0;
			bool editSel = (e.State & DrawItemState.ComboBoxEdit ) > 0;
			if ( e.Index != -1 )
				DrawComboBoxItem(g, bounds, e.Index, selected, editSel);
		}

		protected override void WndProc(ref Message m)
		{
			bool doPainting =  false;
			switch(m.Msg)
			{
				case (int)Msg.WM_PAINT:
					doPainting = true;
					break;
				default:
					break;
			}

			base.WndProc(ref m);
			
			// Now let's do our own painting
			// we have to do it after the combox
			// does its own painting so that we can 
			// let the edit control in the combobox
			// take care of the text
			if ( doPainting )
				ForcePaint(ref m);
		}

		protected override void OnMouseEnter(EventArgs e)
		{
			base.OnMouseEnter(e);
			Graphics g = CreateGraphics();
			DrawComboBoxBorder(g,ColorUtil.VSNetBorderColor);
			DrawComboBoxArrowSelected(g, false);
			g.Dispose();
		}

		protected override void OnMouseLeave(EventArgs e)
		{
			base.OnMouseLeave(e);
			if ( !ContainsFocus )
			{
				Graphics g = CreateGraphics();
				DrawComboBoxBorder(g, SystemColors.Window);
				DrawComboBoxArrowNormal(g, false);
				g.Dispose();
			}
		}
	
		protected override void OnLostFocus(EventArgs e)
		{
			base.OnLostFocus(e);
			Graphics g = CreateGraphics();
			DrawComboBoxBorder(g, SystemColors.Window);
			DrawComboBoxArrowNormal(g, false);
			g.Dispose();
			if ( toolBarUse && hooked)
			{
				hooked = false;
				EndHook();
			}
		}

		protected override void OnGotFocus(EventArgs e)
		{
			base.OnGotFocus(e);
			Graphics g = CreateGraphics();
			DrawComboBoxBorder(g, ColorUtil.VSNetBorderColor);
			DrawComboBoxArrowSelected(g, false);
			g.Dispose();
			if ( toolBarUse && !hooked)
			{
				hooked = true;
				StartHook();
			}
		}

		protected override void OnSelectedIndexChanged(EventArgs e)
		{
			if ( fireOnSelectedIndexChanged )
			{

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -