📄 colorpicker.cs
字号:
using System;
using System.Collections;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Windows.Forms;
using System.Reflection;
using System.Resources;
using System.Diagnostics;
using UtilityLibrary.General;
using UtilityLibrary.WinControls;
using UtilityLibrary.Win32;
namespace UtilityLibrary.WinControls
{
#region Helper Classes
public class NewColorArgs : EventArgs
{
#region Class Variables
Color newColor;
#endregion
#region Class Variables
public NewColorArgs(Color newColor)
{
this.newColor = newColor;
}
#endregion
#region Properties
public Color NewColor
{
get { return newColor;}
}
#endregion
}
[ToolboxItem(false)]
internal class ArrowButton : System.Windows.Forms.Button
{
#region Class Variables
ColorPicker colorPicker = null;
DrawState drawState = DrawState.Normal;
#endregion
#region Constructor
public ArrowButton()
{
}
public ArrowButton(ColorPicker colorPicker)
{
SetStyle(ControlStyles.AllPaintingInWmPaint|ControlStyles.UserPaint|ControlStyles.Opaque, true);
this.colorPicker = colorPicker;
TabStop = false;
}
#endregion
#region Overrides
protected override void OnPaint(PaintEventArgs pe)
{
base.OnPaint(pe);
Graphics g = pe.Graphics;
DrawArrowState(g, drawState);
}
protected override void OnMouseDown(MouseEventArgs e)
{
base.OnMouseDown(e);
if ( colorPicker != null )
colorPicker.DrawState = DrawState.Pressed;
}
protected override void OnGotFocus(EventArgs e)
{
base.OnGotFocus(e);
}
protected override void OnMouseEnter(EventArgs e)
{
base.OnMouseEnter(e);
if ( colorPicker != null )
colorPicker.DrawState = DrawState.Hot;
}
protected override void OnMouseLeave(EventArgs e)
{
base.OnMouseLeave(e);
if ( colorPicker == null ) return;
Point mousePos = Control.MousePosition;
if ( !colorPicker.ClientRectangle.Contains(colorPicker.PointToClient(mousePos))
&& !colorPicker.colorTextBox.ContainsFocus )
{
colorPicker.DrawState = DrawState.Normal;
}
}
protected override void WndProc(ref Message m)
{
Msg currentMessage = (Msg)m.Msg;
switch(m.Msg)
{
// The NET MouseEnter Mouse Leave mechanism seems to fall
// apart when I use PeekMessage function in the ColorPickerDropDown class
// use the Windows API to keep it working
case ((int)Msg.WM_MOUSEMOVE):
if ( colorPicker != null )
{
RequestMouseLeaveMessage(m.HWnd);
colorPicker.DrawState = DrawState.Hot;
}
break;
case ((int)Msg.WM_MOUSELEAVE):
Point mousePos = Control.MousePosition;
if ( colorPicker != null && !colorPicker.ClientRectangle.Contains(colorPicker.PointToClient(mousePos))
&& !colorPicker.colorTextBox.ContainsFocus )
{
colorPicker.DrawState = DrawState.Normal;
}
break;
default:
break;
}
base.WndProc(ref m);
}
#endregion
#region Properties
internal DrawState DrawState
{
set
{
if ( drawState != value )
{
drawState = value;
Invalidate();
}
}
get { return drawState; }
}
#endregion
#region Implementation
void DrawArrowState(Graphics g, DrawState state)
{
if ( colorPicker == null ) return;
if ( state == DrawState.Pressed && colorPicker.colorDropDown.Visible == false )
state = DrawState.Hot;
DrawBackground(g, state);
Rectangle rc = ClientRectangle;
SizeF sizeF = Image.PhysicalDimension;
int imageWidth = (int)sizeF.Width;
int imageHeight = (int)sizeF.Height;
// We are assuming that the button image is smaller than
// the button itself
if ( imageWidth > rc.Width || imageHeight > rc.Height)
{
Debug.WriteLine("Image dimensions need to be smaller that button's dimension...");
return;
}
// Image only drawing
int x = (Width - imageWidth)/2;
int y = (Height - imageHeight)/2;
DrawImage(g, state, Image, x, y);
}
void DrawBackground(Graphics g, DrawState state)
{
Rectangle rc = ClientRectangle;
// Draw background
if ( state == DrawState.Normal || state == DrawState.Disable )
{
g.FillRectangle(new SolidBrush(SystemColors.Control), rc);
// Draw border rectangle
g.DrawRectangle(Pens.White, rc.Left, rc.Top, rc.Width-1, rc.Height-1);
}
else if ( state == DrawState.Hot || state == DrawState.Pressed )
{
// Erase whatever that was there before
if ( state == DrawState.Hot )
g.FillRectangle(new SolidBrush(ColorUtil.VSNetSelectionColor), rc);
else
g.FillRectangle(new SolidBrush(ColorUtil.VSNetPressedColor), rc);
// Draw border rectangle
g.DrawRectangle(SystemPens.Highlight, rc.Left, rc.Top, rc.Width-1, rc.Height-1);
}
}
void DrawImage(Graphics g, DrawState state, Image image, int x, int y)
{
SizeF sizeF = Image.PhysicalDimension;
int imageWidth = (int)sizeF.Width;
int imageHeight = (int)sizeF.Height;
if ( state == DrawState.Disable )
ControlPaint.DrawImageDisabled(g, Image, x, y, SystemColors.Control);
else
g.DrawImage(Image, x, y, imageWidth, imageHeight);
}
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);
}
#endregion
}
internal class ColorPickerEditCtrlHook : System.Windows.Forms.NativeWindow
{
#region Class Variables
ColorPicker colorPicker;
bool ignoreNextPaintMessage = false;
#endregion
#region Constructors
public ColorPickerEditCtrlHook(ColorPicker colorPicker)
{
this.colorPicker = colorPicker;
}
#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 ( colorPicker.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;
default:
break;
}
base.WndProc(ref m);
}
#endregion
#region Implementation
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, colorPicker.Font, b, pt);
}
}
}
#endregion
}
#endregion
/// <summary>
/// Summary description for ColorPicker.
/// </summary>
[ToolboxItem(false)]
public class ColorPicker : System.Windows.Forms.UserControl
{
#region Class Variables
internal System.Windows.Forms.TextBox colorTextBox;
internal ArrowButton arrowButton;
internal ColorPickerDropDown colorDropDown;
const int COLOR_PANEL_WIDTH = 20;
const int ARROW_BUTTON_WIDTH = 15;
int TEXTBOX_HEIGHT = -1;
const int MARGIN = 8;
ResourceManager rm = null;
Color currentColor = Color.White;
public delegate void NewColorEventHandler(object sender, NewColorArgs e);
public event NewColorEventHandler NewColor;
internal DrawState drawState = DrawState.Normal;
internal DrawState previousState = DrawState.Normal;
Rectangle displayColorRect;
ColorPickerEditCtrlHook editHook = null;
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.Container components = null;
#endregion
#region Constructors
public ColorPicker()
{
Assembly thisAssembly = Assembly.GetAssembly(Type.GetType("UtilityLibrary.WinControls.ColorPicker"));
rm = new ResourceManager("UtilityLibrary.Resources.ImagesColorPicker", thisAssembly);
// This call is required by the Windows.Forms Form Designer.
InitializeComponent();
}
/// <summary>
/// Clean up any resources being used.
/// </summary>
protected override void Dispose( bool disposing )
{
if( disposing )
{
if(components != null)
{
components.Dispose();
}
}
base.Dispose( disposing );
}
#endregion
#region Overrides
protected override void OnPaint(PaintEventArgs pe)
{
base.OnPaint(pe);
DrawColorPickerState();
}
protected override void OnHandleCreated(EventArgs e)
{
base.OnHandleCreated(e);
// Hook the edit control
editHook = new ColorPickerEditCtrlHook(this);
editHook.AssignHandle(colorTextBox.Handle);
}
protected override void OnEnabledChanged(EventArgs e)
{
if ( Enabled == true )
drawState = DrawState.Normal;
else
drawState = DrawState.Disable;
base.OnEnabledChanged(e);
}
protected override void OnMouseEnter(EventArgs e)
{
base.OnMouseEnter(e);
DrawState = DrawState.Hot;
}
protected override void OnMouseLeave(EventArgs e)
{
base.OnMouseLeave(e);
Point mousePos = Control.MousePosition;
if ( !ClientRectangle.Contains(PointToClient(mousePos))
&& !colorTextBox.ContainsFocus )
{
DrawState = DrawState.Normal;
Debug.WriteLine("ON MOUSE LEAVE NORMAL PAINTING...");
}
}
protected override void OnGotFocus(EventArgs e)
{
base.OnGotFocus(e);
DrawState = DrawState.Hot;
}
protected override void OnLostFocus(EventArgs e)
{
base.OnLostFocus(e);
Point mousePos = Control.MousePosition;
if ( !ClientRectangle.Contains(PointToClient(mousePos)) )
DrawState = DrawState.Normal;
}
protected override void OnResize(EventArgs e)
{
base.OnResize(e);
if ( TEXTBOX_HEIGHT == -1 )
{
TEXTBOX_HEIGHT = colorTextBox.Height;
}
if ( Height != TEXTBOX_HEIGHT + MARGIN )
{
Height = TEXTBOX_HEIGHT + MARGIN;
return;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -