Commit a2a230ca 顾剑亮

upload

1 个父辈 c64e5714
正在显示 158 个修改的文件 包含 33 行增加13041 行删除
此文件类型无法预览
...@@ -3,9 +3,7 @@ Microsoft Visual Studio Solution File, Format Version 12.00 ...@@ -3,9 +3,7 @@ Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 16 # Visual Studio Version 16
VisualStudioVersion = 16.0.30523.141 VisualStudioVersion = 16.0.30523.141
MinimumVisualStudioVersion = 10.0.40219.1 MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FaceControl", "FaceControl\FaceControl.csproj", "{06F6C6E6-02F6-4134-945A-BE51BEEF58A4}" Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WindowsFormsApp1", "WindowsFormsApp1\WindowsFormsApp1.csproj", "{AD9F4ADD-A002-4CED-8FFF-BCE1B07538B0}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Test", "Test\Test.csproj", "{30CC76C8-F637-4323-BD65-EFE963DE17E8}"
EndProject EndProject
Global Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution GlobalSection(SolutionConfigurationPlatforms) = preSolution
...@@ -13,14 +11,10 @@ Global ...@@ -13,14 +11,10 @@ Global
Release|Any CPU = Release|Any CPU Release|Any CPU = Release|Any CPU
EndGlobalSection EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution GlobalSection(ProjectConfigurationPlatforms) = postSolution
{06F6C6E6-02F6-4134-945A-BE51BEEF58A4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {AD9F4ADD-A002-4CED-8FFF-BCE1B07538B0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{06F6C6E6-02F6-4134-945A-BE51BEEF58A4}.Debug|Any CPU.Build.0 = Debug|Any CPU {AD9F4ADD-A002-4CED-8FFF-BCE1B07538B0}.Debug|Any CPU.Build.0 = Debug|Any CPU
{06F6C6E6-02F6-4134-945A-BE51BEEF58A4}.Release|Any CPU.ActiveCfg = Release|Any CPU {AD9F4ADD-A002-4CED-8FFF-BCE1B07538B0}.Release|Any CPU.ActiveCfg = Release|Any CPU
{06F6C6E6-02F6-4134-945A-BE51BEEF58A4}.Release|Any CPU.Build.0 = Release|Any CPU {AD9F4ADD-A002-4CED-8FFF-BCE1B07538B0}.Release|Any CPU.Build.0 = Release|Any CPU
{30CC76C8-F637-4323-BD65-EFE963DE17E8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{30CC76C8-F637-4323-BD65-EFE963DE17E8}.Debug|Any CPU.Build.0 = Debug|Any CPU
{30CC76C8-F637-4323-BD65-EFE963DE17E8}.Release|Any CPU.ActiveCfg = Release|Any CPU
{30CC76C8-F637-4323-BD65-EFE963DE17E8}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection EndGlobalSection
GlobalSection(SolutionProperties) = preSolution GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE HideSolutionNode = FALSE
......
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
namespace FaceControl
{
public static class API
{
[DllImport("user32")]
public static extern int ReleaseCapture();
[DllImport("user32")]
public static extern int SendMessage(IntPtr hwnd, int wMsg, int wParam, int lParam);
[DllImport("user32")]
public extern static int GetCaretBlinkTime();
[DllImport("user32.dll")]
public extern static bool GetCursorPos(out Point pt);
[DllImport("gdi32.dll")]
public static extern bool BitBlt(IntPtr hdcDest, int xDest, int yDest, int wDest, int hDest, IntPtr hdcSource, int xSrc, int ySrc, CopyPixelOperation rop);
[DllImport("gdi32.dll")]
public static extern IntPtr DeleteDC(IntPtr hDc);
[DllImport("gdi32.dll")]
public static extern IntPtr DeleteObject(IntPtr hDc);
[DllImport("gdi32.dll")]
public static extern IntPtr CreateCompatibleBitmap(IntPtr hdc, int nWidth, int nHeight);
[DllImport("gdi32.dll")]
public static extern IntPtr CreateCompatibleDC(IntPtr hdc);
[DllImport("gdi32.dll")]
public static extern IntPtr SelectObject(IntPtr hdc, IntPtr bmp);
[DllImport("user32.dll")]
public static extern IntPtr GetDesktopWindow();
[DllImport("user32.dll")]
public static extern IntPtr GetWindowDC(IntPtr ptr);
[DllImport("user32.dll")]
public static extern bool PrintWindow(IntPtr hwnd, IntPtr hdcBlt, UInt32 nFlags);
[DllImport("user32.dll")]
public static extern bool ReleaseDC(IntPtr hWnd, IntPtr hDc);
public const int WM_SYSCOMMAND = 0x112;
public const int SC_MOVE = 0xF010;
public const int HTCAPTION = 0x2;
}
}
namespace FaceControl
{
partial class ControlBase
{
/// <summary>
/// 必需的设计器变量。
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// 清理所有正在使用的资源。
/// </summary>
/// <param name="disposing">如果应释放托管资源,为 true;否则为 false。</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region 组件设计器生成的代码
/// <summary>
/// 设计器支持所需的方法 - 不要修改
/// 使用代码编辑器修改此方法的内容。
/// </summary>
private void InitializeComponent()
{
this.SuspendLayout();
//
// ControlBase
//
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.None;
this.Name = "ControlBase";
this.Load += new System.EventHandler(this.ControlBase_Load);
this.Paint += new System.Windows.Forms.PaintEventHandler(this.ControlBase_Paint);
this.MouseDown += new System.Windows.Forms.MouseEventHandler(this.ControlBase_MouseDown);
this.MouseEnter += new System.EventHandler(this.ControlBase_MouseEnter);
this.MouseLeave += new System.EventHandler(this.ControlBase_MouseLeave);
this.Resize += new System.EventHandler(this.ControlBase_Resize);
this.ResumeLayout(false);
}
#endregion
}
}
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Drawing.Drawing2D;
namespace FaceControl
{
public partial class ControlBase : UserControl
{
private bool _inside = false;
private int _borderW = 2;
private HorizontalAlignment _textAlign = HorizontalAlignment.Center;
private Model.ButtonShape _shape = Model.ButtonShape.Rectangle;
internal Theme.IFaceTheme theme;
internal RectangleF borderRect;
internal Pen borderInsidePen;
internal Pen borderOutsidePen;
public ControlBase()
{
InitializeComponent();
AutoScaleMode = AutoScaleMode.None;
Margin = new Padding(3);
theme = new Theme.DarkTheme();
BackColor = theme.BACK_COLOR;
ForeColor = theme.FORE_COLOR;
}
//[Browsable(true), Category("属性已更改"), Description("在控件上更改Text属性的值时引发的事件")]
//public new event EventHandler TextChanged;
#region 属性
[Browsable(false)]
public new AutoScaleMode AutoScaleMode { set => base.AutoScaleMode = value; get => base.AutoScaleMode; }
[Browsable(false)]
public override bool AutoSize { get => base.AutoSize; set => base.AutoSize = value; }
[Browsable(false)]
public new AutoSizeMode AutoSizeMode { get => base.AutoSizeMode; set => base.AutoSizeMode = value; }
/// <summary>
/// 鼠标光标在控件里面
/// </summary>
[Browsable(false)]
public bool CursorInside
{
set
{
if (_inside != value)
{
if (Enabled)
{
_inside = value;
Refresh();
}
}
}
get
{
return _inside;
}
}
[Browsable(false)]
internal bool AllowHideDrop { set; get; } = true;
[Browsable(true), Category("外观"), Description("控件周围的边框大小"), DefaultValue(2)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
public int BorderWidth
{
set
{
if (value < 0)
_borderW = 0;
else
_borderW = value;
CalcSize();
Refresh();
}
get
{
return _borderW;
}
}
[Browsable(true), Category("外观"), Description("与控件关联的文本")]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
public override string Text
{
get => base.Text;
set
{
base.Text = value;
CalcSize();
Refresh();
//TextChanged?.Invoke(this, new EventArgs());
}
}
[Browsable(true), Category("外观"), Description("用于显示控件中文本的字体")]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
public override Font Font
{
get => base.Font;
set
{
base.Font = value;
CalcSize();
Refresh();
}
}
[Browsable(true), Category("行为"), Description("提示是否已启用该控件"), DefaultValue(true)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
public new bool Enabled
{
get => base.Enabled;
set
{
base.Enabled = value;
Refresh();
}
}
[Browsable(true), Category("外观"), Description("组件的背景色"), DefaultValue(null)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
public override Color BackColor
{
get => base.BackColor;
set
{
base.BackColor = value;
Refresh();
}
}
[Browsable(true), Category("外观"), Description("组件的前景色,用于显示文本"), DefaultValue(null)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
public override Color ForeColor
{
get => base.ForeColor;
set
{
base.ForeColor = value;
Refresh();
}
}
[Browsable(true), Category("外观"), Description("控件上显示的文本的对齐方式"), DefaultValue(HorizontalAlignment.Center)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
public HorizontalAlignment TextAlign
{
get => _textAlign;
set
{
_textAlign = value;
CalcSize();
Refresh();
}
}
[Browsable(true), Category("外观"), Description("控件的显示形状"), DefaultValue(Model.ButtonShape.Rectangle)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
public Model.ButtonShape FaceShape
{
get => _shape;
set
{
_shape = value;
CalcSize();
Refresh();
}
}
#endregion
public Bitmap ToImage()
{
IntPtr hSrce = API.GetWindowDC(Handle);
IntPtr hDest = API.CreateCompatibleDC(hSrce);
IntPtr hBmp = API.CreateCompatibleBitmap(hSrce, Width, Height);
IntPtr hOldBmp = API.SelectObject(hDest, hBmp);
if (API.BitBlt(hDest, 0, 0, Width, Height, hSrce, 0, 0, CopyPixelOperation.SourceCopy | CopyPixelOperation.CaptureBlt))
{
Bitmap bmp = Image.FromHbitmap(hBmp);
API.SelectObject(hDest, hOldBmp);
API.DeleteObject(hBmp);
API.DeleteDC(hDest);
API.ReleaseDC(Handle, hSrce);
return bmp;
}
return null;
}
protected virtual void CalcSize()
{
borderRect = new RectangleF(_borderW / 2f, _borderW / 2f, Width - _borderW - 1, Height - _borderW - 1);
borderInsidePen = new Pen(theme.BORDER_COLOR, _borderW);
borderOutsidePen = new Pen(theme.LOST_FOCUS_COLOR, _borderW);
}
protected virtual void DrawEnabled(Graphics g)
{
}
protected virtual void DrawDisabled(Graphics g)
{
}
internal virtual void HideDrop()
{
}
protected override void WndProc(ref Message m)
{
if (m.Msg == 0x0014) // 禁掉清除背景消息
return;
//System.Diagnostics.Debug.Print("Message: " + m.Msg);
base.WndProc(ref m);
}
private void ControlBase_Load(object sender, EventArgs e)
{
AutoScaleMode = AutoScaleMode.None;
theme = new Theme.DarkTheme();
CalcSize();
Refresh();
}
private void ControlBase_Resize(object sender, EventArgs e)
{
CalcSize();
Refresh();
}
private void ControlBase_Paint(object sender, PaintEventArgs e)
{
BufferedGraphicsContext current = BufferedGraphicsManager.Current;
BufferedGraphics bg = current.Allocate(e.Graphics, e.ClipRectangle);
Graphics g = bg.Graphics;
g.SmoothingMode = SmoothingMode.HighQuality;
g.CompositingQuality = CompositingQuality.HighQuality;
g.InterpolationMode = InterpolationMode.HighQualityBicubic;
g.Clear(theme.BACK_COLOR); //背景
if (Enabled)
DrawEnabled(g);
else
DrawDisabled(g);
bg.Render();
bg.Dispose();
}
private void ControlBase_MouseEnter(object sender, EventArgs e)
{
CursorInside = true;
}
private void ControlBase_MouseLeave(object sender, EventArgs e)
{
CursorInside = false;
}
private void ControlBase_MouseDown(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Left)
{
if (!AllowHideDrop) return;
if (TopLevelControl is FormBase @base)
@base.HideDrop(Handle);
}
}
}
}
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
</root>
\ No newline at end of file \ No newline at end of file
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Drawing.Drawing2D;
namespace FaceControl
{
public partial class PanelBase : Panel
{
private bool _inside = false;
private int _borderW = 2;
private HorizontalAlignment _textAlign = HorizontalAlignment.Center;
private Model.ButtonShape _shape = Model.ButtonShape.Rectangle;
private Font _font = new Font("宋体", 9f);
internal Theme.IFaceTheme theme;
internal RectangleF borderRect;
internal Pen borderInsidePen;
internal Pen borderOutsidePen;
public PanelBase()
{
InitializeComponent();
theme = new Theme.DarkTheme();
Resize += PanelBase_Resize;
Paint += PanelBase_Paint;
MouseDown += PanelBase_MouseDown;
MouseEnter += PanelBase_MouseEnter;
MouseLeave += PanelBase_MouseLeave;
theme = new Theme.DarkTheme();
BackColor = theme.BACK_COLOR;
ForeColor = theme.FORE_COLOR;
}
#region 属性
[Browsable(false)]
public override bool AutoSize { get => base.AutoSize; set => base.AutoSize = value; }
[Browsable(false)]
public new AutoSizeMode AutoSizeMode { get => base.AutoSizeMode; set => base.AutoSizeMode = value; }
[Browsable(false)]
public new BorderStyle BorderStyle { get => base.BorderStyle; set => base.BorderStyle = value; }
[Browsable(false)]
public override Font Font { get => base.Font; set => base.Font = value; }
/// <summary>
/// 鼠标光标在控件里面
/// </summary>
[Browsable(false)]
public bool CursorInside
{
set
{
if (_inside != value)
{
if (Enabled)
{
_inside = value;
Refresh();
}
}
}
get
{
return _inside;
}
}
[Browsable(true), Category("外观"), Description("控件周围的边框大小"), DefaultValue(2)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
public int BorderWidth
{
set
{
if (value < 0)
_borderW = 0;
else
_borderW = value;
CalcSize();
Refresh();
}
get
{
return _borderW;
}
}
[Browsable(true), Category("外观"), Description("与控件关联的文本")]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
public override string Text
{
get => base.Text;
set
{
base.Text = value;
CalcSize();
Refresh();
}
}
[Browsable(true), Category("外观"), Description("用于显示控件中文本的字体")]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
public Font TitleFont
{
get => _font;
set
{
_font = value;
CalcSize();
Refresh();
}
}
[Browsable(true), Category("行为"), Description("提示是否已启用该控件"), DefaultValue(true)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
public new bool Enabled
{
get => base.Enabled;
set
{
base.Enabled = value;
Refresh();
}
}
[Browsable(true), Category("外观"), Description("组件的背景色"), DefaultValue(null)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
public override Color BackColor
{
get => base.BackColor;
set
{
base.BackColor = value;
Refresh();
}
}
[Browsable(true), Category("外观"), Description("组件的前景色,用于显示文本"), DefaultValue(null)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
public override Color ForeColor
{
get => base.ForeColor;
set
{
base.ForeColor = value;
Refresh();
}
}
[Browsable(true), Category("外观"), Description("控件上显示的文本的对齐方式"), DefaultValue(HorizontalAlignment.Center)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
public HorizontalAlignment TextAlign
{
get => _textAlign;
set
{
_textAlign = value;
CalcSize();
Refresh();
}
}
[Browsable(true), Category("外观"), Description("控件的显示形状"), DefaultValue(Model.ButtonShape.Rectangle)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
public Model.ButtonShape FaceShape
{
get => _shape;
set
{
_shape = value;
CalcSize();
Refresh();
}
}
#endregion
public Bitmap ToImage()
{
IntPtr hSrce = API.GetWindowDC(Handle);
IntPtr hDest = API.CreateCompatibleDC(hSrce);
IntPtr hBmp = API.CreateCompatibleBitmap(hSrce, Width, Height);
IntPtr hOldBmp = API.SelectObject(hDest, hBmp);
if (API.BitBlt(hDest, 0, 0, Width, Height, hSrce, 0, 0, CopyPixelOperation.SourceCopy | CopyPixelOperation.CaptureBlt))
{
Bitmap bmp = Image.FromHbitmap(hBmp);
API.SelectObject(hDest, hOldBmp);
API.DeleteObject(hBmp);
API.DeleteDC(hDest);
API.ReleaseDC(Handle, hSrce);
return bmp;
}
return null;
}
protected virtual void CalcSize()
{
borderRect = new RectangleF(_borderW / 2f, _borderW / 2f, Width - _borderW - 1, Height - _borderW - 1);
borderInsidePen = new Pen(theme.BORDER_COLOR, _borderW);
borderOutsidePen = new Pen(theme.LOST_FOCUS_COLOR, _borderW);
}
protected virtual void DrawEnabled(Graphics g)
{
}
protected virtual void DrawDisabled(Graphics g)
{
}
protected override void WndProc(ref Message m)
{
if (m.Msg == 0x0014) // 禁掉清除背景消息
return;
base.WndProc(ref m);
}
//private void PanelBase_Load(object sender, EventArgs e)
//{
// theme = new Theme.DarkTheme();
// CalcSize();
// Refresh();
//}
private void PanelBase_Resize(object sender, EventArgs e)
{
CalcSize();
Refresh();
}
private void PanelBase_Paint(object sender, PaintEventArgs e)
{
BufferedGraphicsContext current = BufferedGraphicsManager.Current;
BufferedGraphics bg = current.Allocate(e.Graphics, e.ClipRectangle);
Graphics g = bg.Graphics;
g.SmoothingMode = SmoothingMode.HighQuality;
g.CompositingQuality = CompositingQuality.HighQuality;
g.InterpolationMode = InterpolationMode.HighQualityBicubic;
g.Clear(theme.BACK_COLOR); //背景
if (Enabled)
DrawEnabled(g);
else
DrawDisabled(g);
bg.Render();
bg.Dispose();
}
private void PanelBase_MouseDown(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Left)
{
if (TopLevelControl is FormBase @base)
{
@base.HideDrop(Handle);
}
}
}
private void PanelBase_MouseEnter(object sender, EventArgs e)
{
CursorInside = true;
}
private void PanelBase_MouseLeave(object sender, EventArgs e)
{
CursorInside = false;
}
}
}

namespace FaceControl
{
partial class FaceButton
{
/// <summary>
/// 必需的设计器变量。
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// 清理所有正在使用的资源。
/// </summary>
/// <param name="disposing">如果应释放托管资源,为 true;否则为 false。</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region 组件设计器生成的代码
/// <summary>
/// 设计器支持所需的方法 - 不要修改
/// 使用代码编辑器修改此方法的内容。
/// </summary>
private void InitializeComponent()
{
this.SuspendLayout();
//
// FaceButton
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.Name = "FaceButton";
this.Size = new System.Drawing.Size(85, 45);
this.MouseDown += new System.Windows.Forms.MouseEventHandler(this.FaceButton_MouseDown);
this.MouseMove += new System.Windows.Forms.MouseEventHandler(this.FaceButton_MouseMove);
this.MouseUp += new System.Windows.Forms.MouseEventHandler(this.FaceButton_MouseUp);
this.ResumeLayout(false);
}
#endregion
}
}
using System;
using System.ComponentModel;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Windows.Forms;
namespace FaceControl
{
[DefaultProperty("Text")]
[DefaultEvent("Click")]
public partial class FaceButton : ControlBase
{
private bool pressLock = false;
private bool mouseDown = false;
private bool borderOver = false;
private RectangleF imgRect = new RectangleF();
private RectangleF textRect = new RectangleF();
private GraphicsPath borderPath = new GraphicsPath();
private Bitmap _img = null;
private Size _imgSize = new Size();
private TextImageRelation _textImageRelation = TextImageRelation.Overlay;
private const int SPACE = 6; //图片与文字的间隔
public FaceButton()
{
InitializeComponent();
}
#region 事件
[Browsable(true), Category("操作"), Description("单击组件时发生")]
public new event EventHandler Click;
#endregion
#region 属性
[Browsable(true), Category("外观"), Description("控件上显示的图像"), DefaultValue(null)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
public Bitmap Image
{
get => _img;
set
{
_img = value;
if (_img == null)
ImageSize = new Size();
else
ImageSize = _img.Size;
CalcSize();
Refresh();
}
}
[Browsable(true), Category("外观"), Description("控件上显示的图像的大小")]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
public Size ImageSize
{
get => _imgSize;
set
{
_imgSize = value;
CalcSize();
Refresh();
}
}
[Browsable(true), Category("外观"), Description("按钮上图像与文本的相对位置"), DefaultValue(TextImageRelation.Overlay)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
public TextImageRelation TextImageRelation
{
get => _textImageRelation;
set
{
_textImageRelation = value;
CalcSize();
Refresh();
}
}
[Browsable(true), Category("外观"), Description("按下并锁住在按下弹起"), DefaultValue(false)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
public bool PressLock { set; get; }
#endregion
public void PressPush()
{
mouseDown = true;
pressLock = true;
Refresh();
}
public void PressPull()
{
mouseDown = false;
pressLock = false;
Refresh();
}
protected override void CalcSize()
{
base.CalcSize();
CalcTextLocation();
CalcShape();
}
protected override void DrawEnabled(Graphics g)
{
base.DrawEnabled(g);
//控件边框
if (CursorInside && borderOver)
{
if (mouseDown)
g.FillPath(new SolidBrush(theme.DOWN_COLOR), borderPath); //按下
else
g.FillPath(new SolidBrush(theme.OVER_COLOR), borderPath); //经过
if (BorderWidth > 0)
g.DrawPath(borderInsidePen, borderPath);
}
else
{
if (pressLock && mouseDown)
g.FillPath(new SolidBrush(theme.DOWN_COLOR), borderPath); //按下
else
g.FillPath(new SolidBrush(BackColor), borderPath);
if (BorderWidth > 0)
g.DrawPath(borderOutsidePen, borderPath);
}
//图标
if (_img != null)
g.DrawImage(_img, imgRect, new RectangleF(0, 0, _img.Width, _img.Height), GraphicsUnit.Pixel);
//文字
g.DrawString(Text, Font, new SolidBrush(ForeColor), textRect);
}
protected override void DrawDisabled(Graphics g)
{
base.DrawDisabled(g);
//控件边框
if (BorderWidth > 0)
g.DrawPath(borderOutsidePen, borderPath);
//图标
if (_img != null)
g.DrawImage(_img, imgRect, new RectangleF(0, 0, _img.Width, _img.Height), GraphicsUnit.Pixel);
//文字
g.DrawString(Text, Font, new SolidBrush(theme.LOST_FOCUS_COLOR), textRect);
}
private void CalcShape()
{
borderPath = new GraphicsPath();
float n;
switch (FaceShape)
{
case Model.ButtonShape.Rectangle:
borderPath.AddRectangle(borderRect);
break;
case Model.ButtonShape.RoundRectangle:
n = borderRect.Height / 8f;
borderPath.AddLine(borderRect.X + n, borderRect.Y, borderRect.Right - n, borderRect.Y);
borderPath.AddArc(borderRect.Right - n - n, borderRect.Y, n + n, n + n, 270, 90);
borderPath.AddLine(borderRect.Right, borderRect.Y + n, borderRect.Right, borderRect.Bottom - n);
borderPath.AddArc(borderRect.Right - n - n, borderRect.Bottom - n - n, n + n, n + n, 0, 90);
borderPath.AddLine(borderRect.Right - n, borderRect.Bottom, borderRect.X + n, borderRect.Bottom);
borderPath.AddArc(borderRect.X, borderRect.Bottom - n - n, n + n, n + n, 90, 90);
borderPath.AddLine(borderRect.X, borderRect.Bottom - n, borderRect.X, borderRect.Y + n);
borderPath.AddArc(borderRect.X, borderRect.Y, n + n, n + n, 180, 90);
break;
case Model.ButtonShape.Ellipse:
borderPath.AddEllipse(borderRect);
break;
case Model.ButtonShape.EllipseRectangle:
n = borderRect.Height / 2f;
borderPath.AddLine(borderRect.X + n, borderRect.Y, borderRect.Right - n, borderRect.Y);
borderPath.AddArc(borderRect.Right - n - n, borderRect.Y, n + n, n + n, 270, 180);
borderPath.AddLine(borderRect.Right - n, borderRect.Bottom, borderRect.X + n, borderRect.Bottom);
borderPath.AddArc(borderRect.X, borderRect.Y, n + n, n + n, 90, 180);
break;
case Model.ButtonShape.Circle:
if (borderRect.Width > borderRect.Height)
borderPath.AddEllipse((borderRect.Width - borderRect.Height) / 2f, borderRect.Y, borderRect.Height, borderRect.Height);
else
borderPath.AddEllipse(borderRect.X, (borderRect.Height - borderRect.Width) / 2f, borderRect.Width, borderRect.Width);
break;
}
}
private void CalcTextLocation()
{
if (string.IsNullOrEmpty(Text)) return;
Graphics g = CreateGraphics();
SizeF sf = g.MeasureString(Text, Font);
//imgRect = new RectangleF(0, 0, _imgSize.Width, _imgSize.Height);
//textRect = new RectangleF(0, 0, sf.Width, sf.Height);
//float x, y;
float imgX = 0, imgY = 0, textX = 0, textY = 0;
switch(TextImageRelation)
{
case TextImageRelation.Overlay:
imgY = (Height - _imgSize.Height) / 2f;
textY = (Height - sf.Height) / 2f;
switch (TextAlign)
{
case HorizontalAlignment.Left:
imgX = borderRect.X;
textX = borderRect.X;
break;
case HorizontalAlignment.Right:
imgX = borderRect.Right - _imgSize.Width;
textX = borderRect.Right - sf.Width;
break;
case HorizontalAlignment.Center:
imgX = borderRect.X + (borderRect.Width - _imgSize.Width) / 2f;
textX = borderRect.X + (borderRect.Width - sf.Width) / 2f;
break;
}
break;
case TextImageRelation.ImageAboveText:
imgY = (Height - _imgSize.Height - sf.Height - SPACE) / 2f;
textY = imgY + _imgSize.Height + SPACE;
switch (TextAlign)
{
case HorizontalAlignment.Left:
imgX = borderRect.X;
textX = borderRect.X;
break;
case HorizontalAlignment.Right:
imgX = borderRect.Right - _imgSize.Width;
textX = borderRect.Right - sf.Width;
break;
case HorizontalAlignment.Center:
imgX = borderRect.X + (borderRect.Width - _imgSize.Width) / 2f;
textX = borderRect.X + (borderRect.Width - sf.Width) / 2f;
break;
}
break;
case TextImageRelation.TextAboveImage:
textY = (Height - _imgSize.Height - sf.Height - SPACE) / 2f;
imgY = textY + sf.Height + SPACE;
switch (TextAlign)
{
case HorizontalAlignment.Left:
imgX = borderRect.X;
textX = borderRect.X;
break;
case HorizontalAlignment.Right:
imgX = borderRect.Right - _imgSize.Width;
textX = borderRect.Right - sf.Width;
break;
case HorizontalAlignment.Center:
imgX = borderRect.X + (borderRect.Width - _imgSize.Width) / 2f;
textX = borderRect.X + (borderRect.Width - sf.Width) / 2f;
break;
}
break;
case TextImageRelation.ImageBeforeText:
imgY = (Height - _imgSize.Height) / 2f;
textY = (Height - sf.Height) / 2f;
switch (TextAlign)
{
case HorizontalAlignment.Left:
imgX = borderRect.X;
textX = borderRect.X + _imgSize.Width + SPACE;
break;
case HorizontalAlignment.Right:
imgX = borderRect.Right - _imgSize.Width - sf.Width - SPACE;
textX = borderRect.Right - sf.Width;
break;
case HorizontalAlignment.Center:
imgX = borderRect.X + (borderRect.Width - _imgSize.Width - sf.Width - SPACE) / 2f;
textX = imgX + _imgSize.Width + SPACE;
break;
}
break;
case TextImageRelation.TextBeforeImage:
imgY = (Height - _imgSize.Height) / 2f;
textY = (Height - sf.Height) / 2f;
switch (TextAlign)
{
case HorizontalAlignment.Left:
textX = borderRect.X;
imgX = borderRect.X + sf.Width + SPACE;
break;
case HorizontalAlignment.Right:
textX = borderRect.Right - _imgSize.Width - sf.Width - SPACE;
imgX = borderRect.Right - _imgSize.Width;
break;
case HorizontalAlignment.Center:
textX = borderRect.X + (borderRect.Width - _imgSize.Width - sf.Width - SPACE) / 2f;
imgX = textX + sf.Width + SPACE;
break;
}
break;
}
imgRect = new RectangleF(imgX, imgY, _imgSize.Width, _imgSize.Height);
textRect = new RectangleF(textX, textY, sf.Width, sf.Height);
//switch (TextAlign)
//{
// case HorizontalAlignment.Left:
// x = BorderWidth;
// if (_img != null)
// {
// imgRect.X = x;
// x += _imgSize.Width + SPACE;
// }
// textRect.X = x;
// break;
// case HorizontalAlignment.Center:
// if (_img != null)
// {
// x = (Width - sf.Width - _imgSize.Width - SPACE) / 2f;
// imgRect.X = x;
// x += _imgSize.Width + SPACE;
// }
// else
// {
// x = (Width - sf.Width) / 2f;
// }
// textRect.X = x;
// break;
// case HorizontalAlignment.Right:
// x = Width - BorderWidth - sf.Width;
// textRect.X = x;
// if (_img != null)
// {
// x -= (SPACE + _imgSize.Width);
// imgRect.X = x;
// }
// break;
//}
}
private void FaceButton_MouseDown(object sender, MouseEventArgs e)
{
if (!Enabled) return;
if (e.Button == MouseButtons.Left)
{
mouseDown = true;
Refresh();
}
}
private void FaceButton_MouseUp(object sender, MouseEventArgs e)
{
if (!Enabled) return;
if (e.Button == MouseButtons.Left)
{
if (PressLock)
{
if (pressLock)
{
mouseDown = false;
pressLock = false;
}
else
{
pressLock = true;
}
}
else
{
mouseDown = false;
}
Refresh();
Click?.Invoke(this, new EventArgs());
}
}
private void FaceButton_MouseMove(object sender, MouseEventArgs e)
{
borderOver = borderPath.IsVisible(e.Location);
Refresh();
}
}
}
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
</root>
\ No newline at end of file \ No newline at end of file

namespace FaceControl
{
partial class FaceButtonGroup
{
/// <summary>
/// 必需的设计器变量。
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// 清理所有正在使用的资源。
/// </summary>
/// <param name="disposing">如果应释放托管资源,为 true;否则为 false。</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region 组件设计器生成的代码
/// <summary>
/// 设计器支持所需的方法 - 不要修改
/// 使用代码编辑器修改此方法的内容。
/// </summary>
private void InitializeComponent()
{
this.SuspendLayout();
//
// FaceButtonGroup
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.Name = "FaceButtonGroup";
this.Size = new System.Drawing.Size(85, 45);
this.MouseDown += new System.Windows.Forms.MouseEventHandler(this.FaceButtonGroup_MouseDown);
this.MouseMove += new System.Windows.Forms.MouseEventHandler(this.FaceButtonGroup_MouseMove);
this.MouseUp += new System.Windows.Forms.MouseEventHandler(this.FaceButtonGroup_MouseUp);
this.ResumeLayout(false);
}
#endregion
}
}
using System;
using System.ComponentModel;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Windows.Forms;
namespace FaceControl
{
[DefaultProperty("Text")]
[DefaultEvent("Click")]
public partial class FaceButtonGroup : ControlBase
{
private bool mouseDown = false;
private int buttonOverIndex = -1;
private RectangleF[] textRect;
private RectangleF[] buttonRect;
private GraphicsPath borderPath = new GraphicsPath();
public FaceButtonGroup()
{
InitializeComponent();
}
#region 事件
[Browsable(true), Category("操作"), Description("单击组件时发生")]
public new event EventHandler Click;
#endregion
#region 属性
[Browsable(false)]
public int SelectedIndex
{
get => buttonOverIndex;
set
{
if (value > -1 && value < buttonRect.Length)
{
buttonOverIndex = value;
Click?.Invoke(this, new EventArgs());
}
}
}
[Browsable(false)]
public string SelectedText
{
get
{
if (buttonOverIndex == -1) return "";
string[] s = Text.Split(',');
return s[buttonOverIndex];
}
}
#endregion
protected override void CalcSize()
{
base.CalcSize();
CalcTextLocation();
CalcShape();
}
protected override void DrawEnabled(Graphics g)
{
base.DrawEnabled(g);
//控件边框
if (CursorInside && buttonOverIndex > -1)
{
if (mouseDown)
g.FillRectangle(new SolidBrush(theme.DOWN_COLOR), buttonRect[buttonOverIndex]); //按下
else
g.FillRectangle(new SolidBrush(theme.OVER_COLOR), buttonRect[buttonOverIndex]); //经过
Region reg = new Region(new Rectangle(0, 0, Width, Height));
reg.Exclude(borderPath);
g.FillRegion(new SolidBrush(theme.BACK_COLOR), reg);
if (BorderWidth > 0)
g.DrawPath(borderInsidePen, borderPath);
}
else
{
buttonOverIndex = -1;
g.FillPath(new SolidBrush(BackColor), borderPath);
if (BorderWidth > 0)
g.DrawPath(borderOutsidePen, borderPath);
}
//文字
string[] s = Text.Split(',');
for (int i = 0; i < s.Length; i++)
g.DrawString(s[i], Font, new SolidBrush(ForeColor), textRect[i]);
}
protected override void DrawDisabled(Graphics g)
{
base.DrawDisabled(g);
//控件边框
if (BorderWidth > 0)
g.DrawPath(borderOutsidePen, borderPath);
//文字
string[] s = Text.Split(',');
for (int i = 0; i < s.Length; i++)
g.DrawString(s[i], Font, new SolidBrush(theme.LOST_FOCUS_COLOR), textRect[i]);
}
private void CalcShape()
{
borderPath = new GraphicsPath();
float n;
switch (FaceShape)
{
case Model.ButtonShape.Rectangle:
borderPath.AddRectangle(borderRect);
break;
case Model.ButtonShape.RoundRectangle:
n = borderRect.Height / 8f;
borderPath.AddLine(borderRect.X + n, borderRect.Y, borderRect.Right - n, borderRect.Y);
borderPath.AddArc(borderRect.Right - n - n, borderRect.Y, n + n, n + n, 270, 90);
borderPath.AddLine(borderRect.Right, borderRect.Y + n, borderRect.Right, borderRect.Bottom - n);
borderPath.AddArc(borderRect.Right - n - n, borderRect.Bottom - n - n, n + n, n + n, 0, 90);
borderPath.AddLine(borderRect.Right - n, borderRect.Bottom, borderRect.X + n, borderRect.Bottom);
borderPath.AddArc(borderRect.X, borderRect.Bottom - n - n, n + n, n + n, 90, 90);
borderPath.AddLine(borderRect.X, borderRect.Bottom - n, borderRect.X, borderRect.Y + n);
borderPath.AddArc(borderRect.X, borderRect.Y, n + n, n + n, 180, 90);
break;
case Model.ButtonShape.Ellipse:
borderPath.AddEllipse(borderRect);
break;
case Model.ButtonShape.EllipseRectangle:
n = borderRect.Height / 2f;
borderPath.AddLine(borderRect.X + n, borderRect.Y, borderRect.Right - n, borderRect.Y);
borderPath.AddArc(borderRect.Right - n - n, borderRect.Y, n + n, n + n, 270, 180);
borderPath.AddLine(borderRect.Right - n, borderRect.Bottom, borderRect.X + n, borderRect.Bottom);
borderPath.AddArc(borderRect.X, borderRect.Y, n + n, n + n, 90, 180);
break;
case Model.ButtonShape.Circle:
if (borderRect.Width > borderRect.Height)
borderPath.AddEllipse((borderRect.Width - borderRect.Height) / 2f, borderRect.Y, borderRect.Height, borderRect.Height);
else
borderPath.AddEllipse(borderRect.X, (borderRect.Height - borderRect.Width) / 2f, borderRect.Width, borderRect.Width);
break;
}
}
private void CalcTextLocation()
{
if (string.IsNullOrEmpty(Text)) return;
Graphics g = CreateGraphics();
string[] s = Text.Split(',');
buttonRect = new RectangleF[s.Length];
textRect = new RectangleF[s.Length];
float w = (Width - BorderWidth - BorderWidth) / (float)s.Length;
float h = Height - BorderWidth - BorderWidth;
for (int i = 0; i < s.Length; i++)
{
buttonRect[i] = new RectangleF(BorderWidth + w * i, BorderWidth, w, h);
SizeF sf = g.MeasureString(s[i], Font);
textRect[i] = new RectangleF(0, (h - sf.Height) / 2f, sf.Width, sf.Height);
switch (TextAlign)
{
case HorizontalAlignment.Left:
textRect[i].X = buttonRect[i].X;
break;
case HorizontalAlignment.Center:
textRect[i].X = buttonRect[i].X + (buttonRect[i].Width - sf.Width) / 2f;
break;
case HorizontalAlignment.Right:
textRect[i].X = buttonRect[i].X + buttonRect[i].Width - sf.Width;
break;
}
}
}
private void FaceButtonGroup_MouseDown(object sender, MouseEventArgs e)
{
if (!Enabled) return;
if (e.Button == MouseButtons.Left)
{
mouseDown = true;
Refresh();
}
}
private void FaceButtonGroup_MouseUp(object sender, MouseEventArgs e)
{
if (!Enabled) return;
if (e.Button == MouseButtons.Left)
{
mouseDown = false;
Refresh();
Click?.Invoke(this, new EventArgs());
}
}
private void FaceButtonGroup_MouseMove(object sender, MouseEventArgs e)
{
buttonOverIndex = -1;
for (int i = 0; i < buttonRect.Length; i++)
{
if (buttonRect[i].Contains(e.Location))
{
buttonOverIndex = i;
break;
}
}
Refresh();
}
}
}
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
</root>
\ No newline at end of file \ No newline at end of file

namespace FaceControl
{
partial class FaceCheck
{
/// <summary>
/// 必需的设计器变量。
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// 清理所有正在使用的资源。
/// </summary>
/// <param name="disposing">如果应释放托管资源,为 true;否则为 false。</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region 组件设计器生成的代码
/// <summary>
/// 设计器支持所需的方法 - 不要修改
/// 使用代码编辑器修改此方法的内容。
/// </summary>
private void InitializeComponent()
{
this.SuspendLayout();
//
// FaceCheck
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.Name = "FaceCheck";
this.Size = new System.Drawing.Size(85, 45);
this.MouseDown += new System.Windows.Forms.MouseEventHandler(this.FaceCheck_MouseDown);
this.MouseUp += new System.Windows.Forms.MouseEventHandler(this.FaceCheck_MouseUp);
this.ResumeLayout(false);
}
#endregion
}
}
using System;
using System.ComponentModel;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Windows.Forms;
namespace FaceControl
{
[DefaultProperty("Text")]
[DefaultEvent("CheckedChanged")]
public partial class FaceCheck : ControlBase
{
private bool mouseDown = false;
private RectangleF checkOutRect = new RectangleF();
private RectangleF checkInRect = new RectangleF();
private RectangleF textRect = new RectangleF();
private GraphicsPath borderPath = new GraphicsPath();
private bool _check = false;
private int _checkWidth = 18;
private const int SPACE = 6; //图片与文字的间隔
public FaceCheck()
{
InitializeComponent();
}
#region 事件
[Browsable(true), Category("杂项"), Description("当checked属性更改值时发生")]
public event EventHandler CheckedChanged;
#endregion
#region 属性
[Browsable(true), Category("外观"), Description("控件上矩形开关的宽度"), DefaultValue(18)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
public int CheckWidth
{
get => _checkWidth;
set
{
_checkWidth = value;
CalcSize();
Refresh();
}
}
[Browsable(true), Category(""), Description("单选按钮是否已选中"), DefaultValue(false)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
public bool Checked
{
set
{
if (_check != value)
{
_check = value;
CalcSize();
Refresh();
}
CheckedChanged?.Invoke(this, new EventArgs());
}
get
{
return _check;
}
}
#endregion
protected override void CalcSize()
{
base.CalcSize();
CalcTextLocation();
CalcShape();
}
protected override void DrawEnabled(Graphics g)
{
base.DrawEnabled(g);
//控件边框
if (CursorInside)
{
if (_check)
{
if (mouseDown)
g.FillRectangle(new SolidBrush(theme.DOWN_COLOR), checkOutRect);
else
g.FillRectangle(new SolidBrush(ForeColor), checkOutRect);
}
else
{
if (mouseDown)
g.FillRectangle(new SolidBrush(ForeColor), checkOutRect);
else
g.FillRectangle(new SolidBrush(theme.DOWN_COLOR), checkOutRect);
}
g.FillRectangle(new SolidBrush(theme.BACK_COLOR), checkInRect);
if (BorderWidth > 0)
g.DrawPath(borderInsidePen, borderPath);
}
else
{
g.FillPath(new SolidBrush(BackColor), borderPath);
if (_check)
{
g.FillRectangle(new SolidBrush(theme.DOWN_COLOR), checkOutRect);
}
else
{
g.FillRectangle(new SolidBrush(ForeColor), checkOutRect);
}
g.FillRectangle(new SolidBrush(theme.BACK_COLOR), checkInRect);
if (BorderWidth > 0)
g.DrawPath(borderOutsidePen, borderPath);
}
//开关圆点
//if (_check)
// g.FillRectangle(new SolidBrush(ForeColor), checkPoint);
if (_check)
{
g.DrawLine(new Pen(ForeColor, 2), checkInRect.X, checkInRect.Y + checkInRect.Height / 2f,
checkInRect.X + checkInRect.Width / 3f, checkInRect.Bottom);
g.DrawLine(new Pen(ForeColor, 2), checkInRect.X + checkInRect.Width / 3f, checkInRect.Bottom,
checkInRect.Right, checkInRect.Y);
}
//文字
g.DrawString(Text, Font, new SolidBrush(ForeColor), textRect);
}
protected override void DrawDisabled(Graphics g)
{
base.DrawDisabled(g);
//控件边框
g.FillRectangle(new SolidBrush(theme.OVER_COLOR), checkOutRect);
g.FillRectangle(new SolidBrush(theme.BACK_COLOR), checkInRect);
if (BorderWidth > 0)
g.DrawPath(borderOutsidePen, borderPath);
//开关圆点
if (_check)
{
//g.FillRectangle(new SolidBrush(theme.OVER_COLOR), checkPoint);
g.DrawLine(new Pen(theme.OVER_COLOR, 2), checkInRect.X, checkInRect.Y + checkInRect.Height / 2f,
checkInRect.X + checkInRect.Width / 3f, checkInRect.Bottom);
g.DrawLine(new Pen(theme.OVER_COLOR, 2), checkInRect.X + checkInRect.Width / 3f, checkInRect.Bottom,
checkInRect.Right, checkInRect.Y);
}
//文字
g.DrawString(Text, Font, new SolidBrush(theme.LOST_FOCUS_COLOR), textRect);
}
private void CalcShape()
{
borderPath = new GraphicsPath();
float n;
switch (FaceShape)
{
case Model.ButtonShape.Rectangle:
borderPath.AddRectangle(borderRect);
break;
case Model.ButtonShape.RoundRectangle:
n = borderRect.Height / 8f;
borderPath.AddLine(borderRect.X + n, borderRect.Y, borderRect.Right - n, borderRect.Y);
borderPath.AddArc(borderRect.Right - n - n, borderRect.Y, n + n, n + n, 270, 90);
borderPath.AddLine(borderRect.Right, borderRect.Y + n, borderRect.Right, borderRect.Bottom - n);
borderPath.AddArc(borderRect.Right - n - n, borderRect.Bottom - n - n, n + n, n + n, 0, 90);
borderPath.AddLine(borderRect.Right - n, borderRect.Bottom, borderRect.X + n, borderRect.Bottom);
borderPath.AddArc(borderRect.X, borderRect.Bottom - n - n, n + n, n + n, 90, 90);
borderPath.AddLine(borderRect.X, borderRect.Bottom - n, borderRect.X, borderRect.Y + n);
borderPath.AddArc(borderRect.X, borderRect.Y, n + n, n + n, 180, 90);
break;
case Model.ButtonShape.Ellipse:
borderPath.AddEllipse(borderRect);
break;
case Model.ButtonShape.EllipseRectangle:
n = borderRect.Height / 2f;
borderPath.AddLine(borderRect.X + n, borderRect.Y, borderRect.Right - n, borderRect.Y);
borderPath.AddArc(borderRect.Right - n - n, borderRect.Y, n + n, n + n, 270, 180);
borderPath.AddLine(borderRect.Right - n, borderRect.Bottom, borderRect.X + n, borderRect.Bottom);
borderPath.AddArc(borderRect.X, borderRect.Y, n + n, n + n, 90, 180);
break;
case Model.ButtonShape.Circle:
if (borderRect.Width > borderRect.Height)
borderPath.AddEllipse((borderRect.Width - borderRect.Height) / 2f, borderRect.Y, borderRect.Height, borderRect.Height);
else
borderPath.AddEllipse(borderRect.X, (borderRect.Height - borderRect.Width) / 2f, borderRect.Width, borderRect.Width);
break;
}
}
private void CalcTextLocation()
{
if (string.IsNullOrEmpty(Text)) return;
Graphics g = CreateGraphics();
SizeF sf = g.MeasureString(Text, Font);
checkOutRect = new RectangleF(0, (Height - _checkWidth) / 2f, _checkWidth, _checkWidth);
textRect = new RectangleF(0, (Height - sf.Height) / 2f, sf.Width, sf.Height);
float x;
switch (TextAlign)
{
case HorizontalAlignment.Left:
x = BorderWidth;
checkOutRect.X = x;
x += _checkWidth + SPACE;
textRect.X = x;
break;
case HorizontalAlignment.Center:
x = (Width - sf.Width - _checkWidth - SPACE) / 2f;
checkOutRect.X = x;
x += _checkWidth + SPACE;
textRect.X = x;
break;
case HorizontalAlignment.Right:
x = Width - BorderWidth - sf.Width;
textRect.X = x;
x -= (SPACE + _checkWidth);
checkOutRect.X = x;
break;
}
float w = _checkWidth / 6f;
checkInRect = new RectangleF(checkOutRect.X + w, checkOutRect.Y + w, w * 4, w * 4);
//checkPoint = new RectangleF(checkOutRect.X + w * 2, checkOutRect.Y + w * 2, w * 2, w * 2);
}
private void FaceCheck_MouseDown(object sender, MouseEventArgs e)
{
if (!Enabled) return;
if (e.Button == MouseButtons.Left)
{
mouseDown = true;
_check = !_check;
Refresh();
}
}
private void FaceCheck_MouseUp(object sender, MouseEventArgs e)
{
if (!Enabled) return;
if (e.Button == MouseButtons.Left)
{
mouseDown = false;
Refresh();
CheckedChanged?.Invoke(this, new EventArgs());
}
}
}
}
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
</root>
\ No newline at end of file \ No newline at end of file

namespace FaceControl
{
partial class FaceCheckGroup
{
/// <summary>
/// 必需的设计器变量。
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// 清理所有正在使用的资源。
/// </summary>
/// <param name="disposing">如果应释放托管资源,为 true;否则为 false。</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region 组件设计器生成的代码
/// <summary>
/// 设计器支持所需的方法 - 不要修改
/// 使用代码编辑器修改此方法的内容。
/// </summary>
private void InitializeComponent()
{
this.SuspendLayout();
//
// FaceCheckGroup
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.Name = "FaceCheckGroup";
this.Size = new System.Drawing.Size(85, 45);
this.MouseDown += new System.Windows.Forms.MouseEventHandler(this.FaceRadioGroup_MouseDown);
this.MouseMove += new System.Windows.Forms.MouseEventHandler(this.FaceRadioGroup_MouseMove);
this.MouseUp += new System.Windows.Forms.MouseEventHandler(this.FaceRadioGroup_MouseUp);
this.ResumeLayout(false);
}
#endregion
}
}
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Windows.Forms;
namespace FaceControl
{
[DefaultProperty("SelectedIndex")]
[DefaultEvent("CheckedChanged")]
public partial class FaceCheckGroup : ControlBase
{
private int buttonOverIndex = -1;
private List<int> buttonDownIndex;
private RectangleF[] textRect;
private RectangleF[] buttonRect;
private GraphicsPath borderPath = new GraphicsPath();
public FaceCheckGroup()
{
InitializeComponent();
buttonDownIndex = new List<int>();
}
#region 事件
[Browsable(true), Category("杂项"), Description("当checked属性更改值时发生")]
public event EventHandler CheckedChanged;
#endregion
#region 属性
[Browsable(false)]
public int[] SelectedIndex { get { return buttonDownIndex.ToArray(); } }
[Browsable(false)]
public string[] SelectedText
{
get
{
string[] s = Text.Split(',');
string[] rtn = new string[buttonDownIndex.Count];
for (int i = 0; i < rtn.Length; i++)
rtn[i] = s[buttonDownIndex[i]];
return rtn;
}
}
#endregion
protected override void CalcSize()
{
base.CalcSize();
CalcTextLocation();
CalcShape();
}
protected override void DrawEnabled(Graphics g)
{
base.DrawEnabled(g);
//控件边框
if (CursorInside && buttonOverIndex > -1)
{
for (int i = 0; i < buttonDownIndex.Count; i++)
g.FillRectangle(new SolidBrush(theme.DOWN_COLOR), buttonRect[buttonDownIndex[i]]);
int index = buttonDownIndex.FindIndex(s => s == buttonOverIndex);
if (index == -1)
g.FillRectangle(new SolidBrush(theme.OVER_COLOR), buttonRect[buttonOverIndex]); //经过
Region reg = new Region(new Rectangle(0, 0, Width, Height));
reg.Exclude(borderPath);
g.FillRegion(new SolidBrush(theme.BACK_COLOR), reg);
if (BorderWidth > 0)
g.DrawPath(borderInsidePen, borderPath);
}
else
{
buttonOverIndex = -1;
g.FillPath(new SolidBrush(BackColor), borderPath);
for (int i = 0; i < buttonDownIndex.Count; i++)
g.FillRectangle(new SolidBrush(theme.DOWN_COLOR), buttonRect[buttonDownIndex[i]]);
Region reg = new Region(new Rectangle(0, 0, Width, Height));
reg.Exclude(borderPath);
g.FillRegion(new SolidBrush(theme.BACK_COLOR), reg);
if (BorderWidth > 0)
g.DrawPath(borderOutsidePen, borderPath);
}
//文字
string[] s = Text.Split(',');
for (int i = 0; i < s.Length; i++)
g.DrawString(s[i], Font, new SolidBrush(ForeColor), textRect[i]);
}
protected override void DrawDisabled(Graphics g)
{
base.DrawDisabled(g);
//控件边框
if (BorderWidth > 0)
g.DrawPath(borderOutsidePen, borderPath);
//文字
string[] s = Text.Split(',');
for (int i = 0; i < s.Length; i++)
g.DrawString(s[i], Font, new SolidBrush(theme.LOST_FOCUS_COLOR), textRect[i]);
}
private void CalcShape()
{
borderPath = new GraphicsPath();
float n;
switch (FaceShape)
{
case Model.ButtonShape.Rectangle:
borderPath.AddRectangle(borderRect);
break;
case Model.ButtonShape.RoundRectangle:
n = borderRect.Height / 8f;
borderPath.AddLine(borderRect.X + n, borderRect.Y, borderRect.Right - n, borderRect.Y);
borderPath.AddArc(borderRect.Right - n - n, borderRect.Y, n + n, n + n, 270, 90);
borderPath.AddLine(borderRect.Right, borderRect.Y + n, borderRect.Right, borderRect.Bottom - n);
borderPath.AddArc(borderRect.Right - n - n, borderRect.Bottom - n - n, n + n, n + n, 0, 90);
borderPath.AddLine(borderRect.Right - n, borderRect.Bottom, borderRect.X + n, borderRect.Bottom);
borderPath.AddArc(borderRect.X, borderRect.Bottom - n - n, n + n, n + n, 90, 90);
borderPath.AddLine(borderRect.X, borderRect.Bottom - n, borderRect.X, borderRect.Y + n);
borderPath.AddArc(borderRect.X, borderRect.Y, n + n, n + n, 180, 90);
break;
case Model.ButtonShape.Ellipse:
borderPath.AddEllipse(borderRect);
break;
case Model.ButtonShape.EllipseRectangle:
n = borderRect.Height / 2f;
borderPath.AddLine(borderRect.X + n, borderRect.Y, borderRect.Right - n, borderRect.Y);
borderPath.AddArc(borderRect.Right - n - n, borderRect.Y, n + n, n + n, 270, 180);
borderPath.AddLine(borderRect.Right - n, borderRect.Bottom, borderRect.X + n, borderRect.Bottom);
borderPath.AddArc(borderRect.X, borderRect.Y, n + n, n + n, 90, 180);
break;
case Model.ButtonShape.Circle:
if (borderRect.Width > borderRect.Height)
borderPath.AddEllipse((borderRect.Width - borderRect.Height) / 2f, borderRect.Y, borderRect.Height, borderRect.Height);
else
borderPath.AddEllipse(borderRect.X, (borderRect.Height - borderRect.Width) / 2f, borderRect.Width, borderRect.Width);
break;
}
}
private void CalcTextLocation()
{
if (string.IsNullOrEmpty(Text)) return;
Graphics g = CreateGraphics();
string[] s = Text.Split(',');
buttonRect = new RectangleF[s.Length];
textRect = new RectangleF[s.Length];
float w = (Width - BorderWidth - BorderWidth) / (float)s.Length;
float h = Height - BorderWidth - BorderWidth;
for (int i = 0; i < s.Length; i++)
{
buttonRect[i] = new RectangleF(BorderWidth + w * i, BorderWidth, w, h);
SizeF sf = g.MeasureString(s[i], Font);
textRect[i] = new RectangleF(0, (h - sf.Height) / 2f, sf.Width, sf.Height);
switch (TextAlign)
{
case HorizontalAlignment.Left:
textRect[i].X = buttonRect[i].X;
break;
case HorizontalAlignment.Center:
textRect[i].X = buttonRect[i].X + (buttonRect[i].Width - sf.Width) / 2f;
break;
case HorizontalAlignment.Right:
textRect[i].X = buttonRect[i].X + buttonRect[i].Width - sf.Width;
break;
}
}
}
private void FaceRadioGroup_MouseDown(object sender, MouseEventArgs e)
{
if (!Enabled) return;
if (e.Button == MouseButtons.Left)
{
int index = buttonDownIndex.FindIndex(s => s == buttonOverIndex);
if (index == -1)
buttonDownIndex.Add(buttonOverIndex);
else
buttonDownIndex.RemoveAt(index);
Refresh();
}
}
private void FaceRadioGroup_MouseUp(object sender, MouseEventArgs e)
{
if (!Enabled) return;
if (e.Button == MouseButtons.Left)
{
Refresh();
CheckedChanged?.Invoke(this, new EventArgs());
}
}
private void FaceRadioGroup_MouseMove(object sender, MouseEventArgs e)
{
buttonOverIndex = -1;
for (int i = 0; i < buttonRect.Length; i++)
{
if (buttonRect[i].Contains(e.Location))
{
buttonOverIndex = i;
break;
}
}
Refresh();
}
}
}
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
</root>
\ No newline at end of file \ No newline at end of file

namespace FaceControl
{
partial class FaceCombo
{
/// <summary>
/// 必需的设计器变量。
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// 清理所有正在使用的资源。
/// </summary>
/// <param name="disposing">如果应释放托管资源,为 true;否则为 false。</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region 组件设计器生成的代码
/// <summary>
/// 设计器支持所需的方法 - 不要修改
/// 使用代码编辑器修改此方法的内容。
/// </summary>
private void InitializeComponent()
{
this.SuspendLayout();
//
// FaceCombo
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.Name = "FaceCombo";
this.Size = new System.Drawing.Size(130, 45);
this.MouseDown += new System.Windows.Forms.MouseEventHandler(this.FaceText_MouseDown);
this.MouseMove += new System.Windows.Forms.MouseEventHandler(this.FaceText_MouseMove);
this.MouseUp += new System.Windows.Forms.MouseEventHandler(this.FaceText_MouseUp);
this.Resize += new System.EventHandler(this.FaceText_Resize);
this.ResumeLayout(false);
}
#endregion
}
}
using System;
using System.ComponentModel;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Windows.Forms;
namespace FaceControl
{
[DefaultProperty("Text")]
[DefaultEvent("SelectedIndexChanged")]
public partial class FaceCombo : ControlBase
{
private bool change = false;
private TextBox txt;
private bool mouseDown = false;
private bool buttonOver = false;
private bool borderOver = false;
private bool dropDown = false;
//private int dropHideTime = 0;
private GraphicsPath borderPath = new GraphicsPath();
private RectangleF buttonRect = new RectangleF();
private RectangleF textRect = new RectangleF();
private FaceList list = new FaceList();
private const int BTN_WIDTH = 30;
private readonly string[] BTN_TEXT = new string[] { "▼", "▲" };
public FaceCombo()
{
InitializeComponent();
list.Name = "itemList";
list.Visible = false;
list.AllowHideDrop = false;
list.TextAlign = HorizontalAlignment.Left;
list.SelectedIndexChanged += List_SelectedIndexChanged;
txt = new TextBox
{
BorderStyle = BorderStyle.None,
BackColor = BackColor,
ForeColor = ForeColor
};
txt.TextChanged += Txt_TextChanged;
txt.MouseEnter += Txt_MouseEnter;
txt.MouseLeave += Txt_MouseLeave;
Controls.Add(txt);
FaceText_Resize(null, EventArgs.Empty);
}
#region 事件
[Browsable(true), Category("属性已更改"), Description("在控件上更改Text属性的值时引发的事件")]
public new event EventHandler TextChanged;
[Browsable(true), Category("行为"), Description("属性值更改时发生")]
public event EventHandler SelectedIndexChanged;
#endregion
#region 属性
[Browsable(false)]
public int SelectedIndex
{
get => list.SelectedIndex;
set
{
change = true;
list.SelectedIndex = value;
change = false;
SelectedIndexChanged?.Invoke(this, new EventArgs());
}
}
[Browsable(false)]
public FaceList.Item Items
{
get
{
return list.Items;
}
}
[Browsable(false)]
public int ItemListHeight
{
get => list.Height;
set
{
list.Height = value;
}
}
[Browsable(false), Category(""), Description("选中的文本起始位置")]
public int SelectionStart { set => txt.SelectionStart = value; get => txt.SelectionStart; }
[Browsable(false), Category(""), Description("选中的文本长度")]
public int SelectionLength { set => txt.SelectionLength = value; get => txt.SelectionLength; }
[Browsable(false), Category(""), Description("选中的文本")]
public string SelectedText
{
set
{
list.SelectedText = value;
}
get
{
if (SelectedIndex == -1) return "";
return list.SelectedText;
}
}
[Browsable(true), Category("外观"), Description("与控件关联的文本")]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
public override string Text
{
get => txt.Text;
set
{
txt.Text = value;
}
}
[Browsable(true), Category("行为"), Description("控件中输入的最大字符数")]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
public int MaxLength { set => txt.MaxLength = value; get => txt.MaxLength; }
[Browsable(true), Category("行为"), Description("控制能否更改编辑控件中的文本"), DefaultValue(false)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
public bool ReadOnly { set => txt.ReadOnly = value; get => txt.ReadOnly; }
[Browsable(true), Category("外观"), Description("指示应该如何对齐编辑控件的文本"), DefaultValue(HorizontalAlignment.Left)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
public new HorizontalAlignment TextAlign { set => txt.TextAlign = value; get => txt.TextAlign; }
[Browsable(true), Category("外观"), Description("用于显示控件中文本的字体")]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
public override Font Font
{
get => base.Font;
set
{
base.Font = value;
FaceText_Resize(null, EventArgs.Empty);
}
}
#endregion
protected override void CalcSize()
{
base.CalcSize();
CalcTextLocation();
CalcShape();
}
protected override void DrawEnabled(Graphics g)
{
base.DrawEnabled(g);
//控件边框
if (CursorInside && borderOver)
{
if (mouseDown)
g.FillRectangle(new SolidBrush(theme.DOWN_COLOR), buttonRect); //按下
else if (buttonOver)
g.FillRectangle(new SolidBrush(theme.OVER_COLOR), buttonRect); //经过
Region reg = new Region(new Rectangle(0, 0, Width, Height));
reg.Exclude(borderPath);
g.FillRegion(new SolidBrush(theme.BACK_COLOR), reg);
if (BorderWidth > 0)
g.DrawPath(borderInsidePen, borderPath);
}
else
{
g.FillPath(new SolidBrush(BackColor), borderPath);
if (BorderWidth > 0)
g.DrawPath(borderOutsidePen, borderPath);
}
g.DrawString(dropDown ? BTN_TEXT[1] : BTN_TEXT[0], new Font("宋体", Font.Size), new SolidBrush(ForeColor), textRect);
}
protected override void DrawDisabled(Graphics g)
{
base.DrawDisabled(g);
//控件边框
if (BorderWidth > 0)
g.DrawPath(borderOutsidePen, borderPath);
g.DrawString(BTN_TEXT[0], new Font("宋体", Font.Size), new SolidBrush(theme.LOST_FOCUS_COLOR), textRect);
}
internal override void HideDrop()
{
base.HideDrop();
if (!dropDown) return;
HideDropDown();
}
private void CalcShape()
{
borderPath = new GraphicsPath();
float n;
switch (FaceShape)
{
case Model.ButtonShape.Rectangle:
borderPath.AddRectangle(borderRect);
break;
case Model.ButtonShape.RoundRectangle:
n = borderRect.Height / 8f;
borderPath.AddLine(borderRect.X + n, borderRect.Y, borderRect.Right - n, borderRect.Y);
borderPath.AddArc(borderRect.Right - n - n, borderRect.Y, n + n, n + n, 270, 90);
borderPath.AddLine(borderRect.Right, borderRect.Y + n, borderRect.Right, borderRect.Bottom - n);
borderPath.AddArc(borderRect.Right - n - n, borderRect.Bottom - n - n, n + n, n + n, 0, 90);
borderPath.AddLine(borderRect.Right - n, borderRect.Bottom, borderRect.X + n, borderRect.Bottom);
borderPath.AddArc(borderRect.X, borderRect.Bottom - n - n, n + n, n + n, 90, 90);
borderPath.AddLine(borderRect.X, borderRect.Bottom - n, borderRect.X, borderRect.Y + n);
borderPath.AddArc(borderRect.X, borderRect.Y, n + n, n + n, 180, 90);
break;
case Model.ButtonShape.Ellipse:
borderPath.AddEllipse(borderRect);
break;
case Model.ButtonShape.EllipseRectangle:
n = borderRect.Height / 2f;
borderPath.AddLine(borderRect.X + n, borderRect.Y, borderRect.Right - n, borderRect.Y);
borderPath.AddArc(borderRect.Right - n - n, borderRect.Y, n + n, n + n, 270, 180);
borderPath.AddLine(borderRect.Right - n, borderRect.Bottom, borderRect.X + n, borderRect.Bottom);
borderPath.AddArc(borderRect.X, borderRect.Y, n + n, n + n, 90, 180);
break;
case Model.ButtonShape.Circle:
if (borderRect.Width > borderRect.Height)
borderPath.AddEllipse((borderRect.Width - borderRect.Height) / 2f, borderRect.Y, borderRect.Height, borderRect.Height);
else
borderPath.AddEllipse(borderRect.X, (borderRect.Height - borderRect.Width) / 2f, borderRect.Width, borderRect.Width);
break;
}
}
private void CalcTextLocation()
{
buttonRect = new RectangleF(borderRect.Right - BTN_WIDTH, borderRect.Y, BTN_WIDTH, borderRect.Height);
Graphics g = CreateGraphics();
SizeF sf = g.MeasureString(dropDown ? BTN_TEXT[1] : BTN_TEXT[0], new Font("宋体", Font.Size));
textRect = new RectangleF(buttonRect.X + (buttonRect.Width - sf.Width) / 2f, buttonRect.Y + (buttonRect.Height - sf.Height) / 2f, sf.Width, sf.Height);
}
private void ShowDropDown()
{
dropDown = true;
Refresh();
Control ctl = TopLevelControl;
Point pt = PointToScreen(new Point(0, Height));
list.Location = ctl.PointToClient(pt);
list.Width = Width;
ctl.Controls.Add(list);
list.BringToFront();
list.Visible = true;
list.Focus();
}
private void HideDropDown()
{
dropDown = false;
Refresh();
Control ctl = list.Parent;
if (ctl == null) return;
ctl.Controls.Remove(list);
list.Visible = false;
}
private void Txt_TextChanged(object sender, EventArgs e)
{
TextChanged?.Invoke(this, new EventArgs());
}
private void Txt_MouseLeave(object sender, EventArgs e)
{
CursorInside = false;
borderOver = false;
Refresh();
}
private void Txt_MouseEnter(object sender, EventArgs e)
{
CursorInside = true;
borderOver = true;
Refresh();
}
private void FaceText_MouseDown(object sender, MouseEventArgs e)
{
if (!Enabled) return;
if (buttonOver && e.Button == MouseButtons.Left)
{
mouseDown = true;
if (dropDown)
HideDropDown();
else
ShowDropDown();
}
}
private void FaceText_MouseMove(object sender, MouseEventArgs e)
{
buttonOver = false;
if (buttonRect.Contains(e.Location))
buttonOver = true;
borderOver = borderPath.IsVisible(e.Location);
Refresh();
}
private void FaceText_MouseUp(object sender, MouseEventArgs e)
{
if (!Enabled) return;
if (e.Button == MouseButtons.Left)
{
mouseDown = false;
Refresh();
}
}
private void FaceText_Resize(object sender, EventArgs e)
{
txt.Left = BorderWidth + 3;
txt.Width = Width - BorderWidth - BorderWidth - BTN_WIDTH - 3 - 3;
txt.Top = BorderWidth + (Height - BorderWidth - BorderWidth - txt.Height) / 2;
}
private void List_SelectedIndexChanged(object sender, EventArgs e)
{
txt.Text = list.Items[list.SelectedIndex];
if (change) return;
SelectedIndex = list.SelectedIndex;
SelectedIndexChanged?.Invoke(this, new EventArgs());
HideDropDown();
}
}
}
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
</root>
\ No newline at end of file \ No newline at end of file

namespace FaceControl
{
partial class FaceImageShow
{
/// <summary>
/// 必需的设计器变量。
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// 清理所有正在使用的资源。
/// </summary>
/// <param name="disposing">如果应释放托管资源,为 true;否则为 false。</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region 组件设计器生成的代码
/// <summary>
/// 设计器支持所需的方法 - 不要修改
/// 使用代码编辑器修改此方法的内容。
/// </summary>
private void InitializeComponent()
{
this.SuspendLayout();
//
// FaceImageShow
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.Name = "FaceImageShow";
this.MouseDown += new System.Windows.Forms.MouseEventHandler(this.FaceImageShow_MouseDown);
this.MouseMove += new System.Windows.Forms.MouseEventHandler(this.FaceImageShow_MouseMove);
this.MouseUp += new System.Windows.Forms.MouseEventHandler(this.FaceImageShow_MouseUp);
this.ResumeLayout(false);
}
#endregion
}
}
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Windows.Forms;
namespace FaceControl
{
[DefaultProperty("Image")]
public partial class FaceImageShow : ControlBase
{
private Bitmap _bmp;
private bool borderOver = false;
private int buttonOver = -1;
private int buttonDown = -1;
private GraphicsPath borderPath = new GraphicsPath();
private RectangleF[] buttonRect = new RectangleF[3];
private RectangleF[] textRect = new RectangleF[3];
private Point oldPoint = new Point(0, 0);
private PointF oldOffset = new PointF(0, 0);
private PointF Offset = new PointF(0, 0);
private int oldZoom = 0;
private int zoom = 30; //缩放比例
private List<PointF> codeCenter = new List<PointF>();
private RectangleF[] codeCenterRect;
private const int BUTTON_SIZE = 50;
private readonly string[] BUTTON_TEXT = new string[3] { "-", "+", "□" };
private readonly Font BUTTON_FONT = new Font("宋体", 20f);
private readonly Font CENTER_FONT = new Font("宋体", 11f);
private const int ZOOM_MAX = 200; //200%
private const int ZOOM_MIN = 10; //10%
private const int ZOOM_PRECISE = 5; //5%
public FaceImageShow()
{
InitializeComponent();
MouseWheel += Pic_MouseWheel;
}
//[Browsable(true), Category(""), Description("图像改变时发生")]
//public event EventHandler ImageChanged;
[Browsable(true), Category(""), Description("控件上显示的图像"), DefaultValue(null)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
public Bitmap Image
{
get => _bmp;
set
{
_bmp = value;
//polygonGray.Clear();
//polygonRed.Clear();
codeCenter.Clear();
Autofit();
Refresh();
}
}
public void AddCodeCenter(params PointF[] pt)
{
codeCenter.AddRange(pt);
CalcSize();
Refresh();
}
public void CodeCenterClear()
{
codeCenter.Clear();
CalcSize();
Refresh();
}
protected override void CalcSize()
{
base.CalcSize();
CalcTextLocation();
CalcShape();
}
protected override void DrawEnabled(Graphics g)
{
base.DrawEnabled(g);
if (_bmp != null)
{
RectangleF destRect = new RectangleF(Offset.X, Offset.Y, _bmp.Width * zoom / 100f, _bmp.Height * zoom / 100f);
RectangleF srcRect = new RectangleF(0, 0, _bmp.Width, _bmp.Height);
g.DrawImage(_bmp, destRect, srcRect, GraphicsUnit.Pixel);
Region reg = new Region(new Rectangle(0, 0, Width, Height));
reg.Exclude(borderPath);
g.FillRegion(new SolidBrush(theme.BACK_COLOR), reg);
}
//显示比例
string s = string.Format("{0:F0}%", zoom);
SizeF sf = g.MeasureString(s, BUTTON_FONT);
float w = sf.Width + 10;
g.FillRectangle(new SolidBrush(theme.OVER_COLOR), borderRect.X, borderRect.Bottom - BUTTON_SIZE, w, BUTTON_SIZE);
g.DrawString(s, BUTTON_FONT, new SolidBrush(ForeColor), borderRect.X + (w - sf.Width) / 2f, borderRect.Bottom - BUTTON_SIZE + (BUTTON_SIZE - sf.Height) / 2f);
for (int i = 0; i < codeCenterRect.Length; i++)
{
g.FillRectangle(Brushes.LightGray, codeCenterRect[i]);
g.DrawString((i + 1).ToString(), CENTER_FONT, Brushes.Red, codeCenterRect[i]);
}
//控件边框
if (CursorInside && borderOver)
{
for (int i = 0; i < buttonRect.Length; i++)
{
if (i == buttonDown)
{
g.FillRectangle(new SolidBrush(theme.DOWN_COLOR), buttonRect[i]);
}
else if (i == buttonOver)
{
g.FillRectangle(new SolidBrush(theme.OVER_COLOR), buttonRect[i]);
}
}
if (BorderWidth > 0)
g.DrawPath(borderInsidePen, borderPath);
}
else
{
//g.FillPath(new SolidBrush(BackColor), borderPath);
if (BorderWidth > 0)
g.DrawPath(borderOutsidePen, borderPath);
}
for (int i = 0; i < textRect.Length; i++)
{
g.DrawString(BUTTON_TEXT[i], BUTTON_FONT, new SolidBrush(ForeColor), textRect[i]);
}
}
protected override void DrawDisabled(Graphics g)
{
base.DrawDisabled(g);
//控件边框
if (BorderWidth > 0)
g.DrawPath(borderOutsidePen, borderPath);
}
private void Pic_MouseWheel(object sender, MouseEventArgs e)
{
if (!Enabled) return;
if (_bmp == null) return;
oldZoom = zoom;
if (e.Delta > 0)
{
if (zoom < ZOOM_MAX)
zoom += 1;
else
zoom = ZOOM_MAX;
}
else
{
if (zoom > ZOOM_MIN)
zoom -= 1;
else
zoom = ZOOM_MIN;
}
float x = (e.X - Offset.X) * (Width * zoom / 100f) / (Width * oldZoom / 100f);
float y = (e.Y - Offset.Y) * (Height * zoom / 100f) / (Height * oldZoom / 100f);
Offset = new PointF(e.X - x, e.Y - y);
Refresh();
}
private void CalcShape()
{
borderPath = new GraphicsPath();
float n;
switch (FaceShape)
{
case Model.ButtonShape.Rectangle:
borderPath.AddRectangle(borderRect);
break;
case Model.ButtonShape.RoundRectangle:
n = borderRect.Height / 8f;
borderPath.AddLine(borderRect.X + n, borderRect.Y, borderRect.Right - n, borderRect.Y);
borderPath.AddArc(borderRect.Right - n - n, borderRect.Y, n + n, n + n, 270, 90);
borderPath.AddLine(borderRect.Right, borderRect.Y + n, borderRect.Right, borderRect.Bottom - n);
borderPath.AddArc(borderRect.Right - n - n, borderRect.Bottom - n - n, n + n, n + n, 0, 90);
borderPath.AddLine(borderRect.Right - n, borderRect.Bottom, borderRect.X + n, borderRect.Bottom);
borderPath.AddArc(borderRect.X, borderRect.Bottom - n - n, n + n, n + n, 90, 90);
borderPath.AddLine(borderRect.X, borderRect.Bottom - n, borderRect.X, borderRect.Y + n);
borderPath.AddArc(borderRect.X, borderRect.Y, n + n, n + n, 180, 90);
break;
case Model.ButtonShape.Ellipse:
borderPath.AddEllipse(borderRect);
break;
case Model.ButtonShape.EllipseRectangle:
n = borderRect.Height / 2f;
borderPath.AddLine(borderRect.X + n, borderRect.Y, borderRect.Right - n, borderRect.Y);
borderPath.AddArc(borderRect.Right - n - n, borderRect.Y, n + n, n + n, 270, 180);
borderPath.AddLine(borderRect.Right - n, borderRect.Bottom, borderRect.X + n, borderRect.Bottom);
borderPath.AddArc(borderRect.X, borderRect.Y, n + n, n + n, 90, 180);
break;
case Model.ButtonShape.Circle:
if (borderRect.Width > borderRect.Height)
borderPath.AddEllipse((borderRect.Width - borderRect.Height) / 2f, borderRect.Y, borderRect.Height, borderRect.Height);
else
borderPath.AddEllipse(borderRect.X, (borderRect.Height - borderRect.Width) / 2f, borderRect.Width, borderRect.Width);
break;
}
}
private void CalcTextLocation()
{
SizeF sf;
Graphics g = CreateGraphics();
float x = borderRect.Right - BUTTON_SIZE * 3;
float y = borderRect.Y + borderRect.Height - BUTTON_SIZE;
for (int i = 0; i < buttonRect.Length; i++)
{
buttonRect[i] = new RectangleF(x, y, BUTTON_SIZE, BUTTON_SIZE);
x += BUTTON_SIZE;
sf = g.MeasureString(BUTTON_TEXT[i], BUTTON_FONT);
textRect[i] = new RectangleF(buttonRect[i].X + (buttonRect[i].Width - sf.Width) / 2f, buttonRect[i].Y + (buttonRect[i].Height - sf.Height) / 2f, sf.Width, sf.Height);
}
codeCenterRect = new RectangleF[codeCenter.Count];
for (int i = 0; i < codeCenterRect.Length; i++)
{
sf = g.MeasureString((i + 1).ToString(), CENTER_FONT);
x = Offset.X + codeCenter[i].X * zoom / 100f - sf.Width / 2f - 3;
y = Offset.Y + codeCenter[i].Y * zoom / 100f - sf.Height / 2f - 3;
codeCenterRect[i] = new RectangleF(x, y, sf.Width, sf.Height);
}
}
private void FaceImageShow_MouseMove(object sender, MouseEventArgs e)
{
if (!Enabled) return;
borderOver = borderPath.IsVisible(e.Location);
if (e.Button == MouseButtons.Left)
{
Offset = new PointF(e.X - oldPoint.X + oldOffset.X, e.Y - oldPoint.Y + oldOffset.Y);
}
else
{
buttonOver = -1;
for (int i = 0; i < buttonRect.Length; i++)
{
if (buttonRect[i].Contains(e.Location))
{
buttonOver = i;
break;
}
}
}
CalcTextLocation();
Refresh();
}
private void FaceImageShow_MouseDown(object sender, MouseEventArgs e)
{
if (!Enabled) return;
if (e.Button == MouseButtons.Left)
{
buttonDown = buttonOver;
oldPoint = e.Location;
oldOffset = Offset;
Refresh();
}
}
private void FaceImageShow_MouseUp(object sender, MouseEventArgs e)
{
if (!Enabled) return;
if (e.Button == MouseButtons.Left)
{
if (buttonDown == 0)
Small();
else if (buttonDown == 1)
Large();
else if (buttonDown == 2)
Autofit();
buttonDown = -1;
CalcTextLocation();
Refresh();
}
}
private void Autofit()
{
if (_bmp == null) return;
float w, h;
w = Width;
h = w * _bmp.Height / _bmp.Width;
if (h > Height)
{
h = Height;
w = h * _bmp.Width / _bmp.Height;
}
float scale = w / _bmp.Width * 100f;
if (scale > ZOOM_MAX)
zoom = ZOOM_MAX;
else if (scale < ZOOM_MIN)
zoom = ZOOM_MIN;
else
zoom = Convert.ToInt32(scale);
float x = (Width - _bmp.Width * zoom / 100f) / 2f;
float y = (Height - _bmp.Height * zoom / 100f) / 2f;
Offset = new PointF(x, y);
//Refresh();
}
private void Large()
{
if (_bmp == null) return;
oldZoom = zoom;
if (zoom < ZOOM_MAX)
zoom += ZOOM_PRECISE;
else
zoom = ZOOM_MAX;
float x = (_bmp.Width * zoom / 100f - _bmp.Width * oldZoom / 100f) / 2f;
float y = (_bmp.Height * zoom / 100f - _bmp.Height * oldZoom / 100f) / 2f;
Offset = new PointF(Offset.X - x, Offset.Y - y);
//Refresh();
}
private void Small()
{
if (_bmp == null) return;
oldZoom = zoom;
if (zoom > ZOOM_MIN)
zoom -= ZOOM_PRECISE;
else
zoom = ZOOM_MIN;
float x = (_bmp.Width * zoom / 100f - _bmp.Width * oldZoom / 100f) / 2f;
float y = (_bmp.Height * zoom / 100f - _bmp.Height * oldZoom / 100f) / 2f;
Offset = new PointF(Offset.X - x, Offset.Y - y);
//Refresh();
}
}
}
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
</root>
\ No newline at end of file \ No newline at end of file

namespace FaceControl
{
partial class FaceLabel
{
/// <summary>
/// 必需的设计器变量。
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// 清理所有正在使用的资源。
/// </summary>
/// <param name="disposing">如果应释放托管资源,为 true;否则为 false。</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region 组件设计器生成的代码
/// <summary>
/// 设计器支持所需的方法 - 不要修改
/// 使用代码编辑器修改此方法的内容。
/// </summary>
private void InitializeComponent()
{
this.SuspendLayout();
//
// FaceLabel
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.Name = "FaceLabel";
this.Size = new System.Drawing.Size(85, 45);
this.MouseMove += new System.Windows.Forms.MouseEventHandler(this.FaceLabel_MouseMove);
this.ResumeLayout(false);
}
#endregion
}
}
using System;
using System.ComponentModel;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Windows.Forms;
namespace FaceControl
{
[DefaultProperty("Text")]
[DefaultEvent("Click")]
public partial class FaceLabel : ControlBase
{
private bool buttonOver = false;
private RectangleF imgRect = new RectangleF();
private RectangleF textRect = new RectangleF();
private GraphicsPath borderPath = new GraphicsPath();
private Bitmap _img = null;
private Size _imgSize = new Size();
private const int SPACE = 6; //图片与文字的间隔
public FaceLabel()
{
InitializeComponent();
}
#region 事件
[Browsable(true), Category("操作"), Description("单击组件时发生")]
public new event EventHandler Click;
#endregion
#region 属性
[Browsable(true), Category("外观"), Description("控件上显示的图像"), DefaultValue(null)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
public Bitmap Image
{
get => _img;
set
{
_img = value;
if (_img == null)
ImageSize = new Size();
else
ImageSize = _img.Size;
CalcSize();
Refresh();
}
}
[Browsable(true), Category("外观"), Description("控件上显示的图像的大小")]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
public Size ImageSize
{
get => _imgSize;
set
{
_imgSize = value;
CalcSize();
Refresh();
}
}
#endregion
protected override void CalcSize()
{
base.CalcSize();
CalcTextLocation();
CalcShape();
}
protected override void DrawEnabled(Graphics g)
{
base.DrawEnabled(g);
g.FillPath(new SolidBrush(BackColor), borderPath);
//控件边框
if (CursorInside && buttonOver)
{
if (BorderWidth > 0)
g.DrawPath(borderInsidePen, borderPath);
}
else
{
if (BorderWidth > 0)
g.DrawPath(borderOutsidePen, borderPath);
}
//图标
if (_img != null)
g.DrawImage(_img, imgRect, new RectangleF(0, 0, _img.Width, _img.Height), GraphicsUnit.Pixel);
//文字
StringFormat format = StringFormat.GenericTypographic;
format.FormatFlags |= StringFormatFlags.MeasureTrailingSpaces;
g.DrawString(Text, Font, new SolidBrush(ForeColor), textRect, format);
}
protected override void DrawDisabled(Graphics g)
{
base.DrawDisabled(g);
//控件边框
if (BorderWidth > 0)
g.DrawPath(borderOutsidePen, borderPath);
//图标
if (_img != null)
g.DrawImage(_img, imgRect, new RectangleF(0, 0, _img.Width, _img.Height), GraphicsUnit.Pixel);
//文字
g.DrawString(Text, Font, new SolidBrush(theme.LOST_FOCUS_COLOR), textRect);
}
private void CalcShape()
{
borderPath = new GraphicsPath();
float n;
switch (FaceShape)
{
case Model.ButtonShape.Rectangle:
borderPath.AddRectangle(borderRect);
break;
case Model.ButtonShape.RoundRectangle:
n = borderRect.Height / 8f;
borderPath.AddLine(borderRect.X + n, borderRect.Y, borderRect.Right - n, borderRect.Y);
borderPath.AddArc(borderRect.Right - n - n, borderRect.Y, n + n, n + n, 270, 90);
borderPath.AddLine(borderRect.Right, borderRect.Y + n, borderRect.Right, borderRect.Bottom - n);
borderPath.AddArc(borderRect.Right - n - n, borderRect.Bottom - n - n, n + n, n + n, 0, 90);
borderPath.AddLine(borderRect.Right - n, borderRect.Bottom, borderRect.X + n, borderRect.Bottom);
borderPath.AddArc(borderRect.X, borderRect.Bottom - n - n, n + n, n + n, 90, 90);
borderPath.AddLine(borderRect.X, borderRect.Bottom - n, borderRect.X, borderRect.Y + n);
borderPath.AddArc(borderRect.X, borderRect.Y, n + n, n + n, 180, 90);
break;
case Model.ButtonShape.Ellipse:
borderPath.AddEllipse(borderRect);
break;
case Model.ButtonShape.EllipseRectangle:
n = borderRect.Height / 2f;
borderPath.AddLine(borderRect.X + n, borderRect.Y, borderRect.Right - n, borderRect.Y);
borderPath.AddArc(borderRect.Right - n - n, borderRect.Y, n + n, n + n, 270, 180);
borderPath.AddLine(borderRect.Right - n, borderRect.Bottom, borderRect.X + n, borderRect.Bottom);
borderPath.AddArc(borderRect.X, borderRect.Y, n + n, n + n, 90, 180);
break;
case Model.ButtonShape.Circle:
if (borderRect.Width > borderRect.Height)
borderPath.AddEllipse((borderRect.Width - borderRect.Height) / 2f, borderRect.Y, borderRect.Height, borderRect.Height);
else
borderPath.AddEllipse(borderRect.X, (borderRect.Height - borderRect.Width) / 2f, borderRect.Width, borderRect.Width);
break;
}
}
private void CalcTextLocation()
{
if (string.IsNullOrEmpty(Text)) return;
imgRect = new RectangleF(0, (Height - _imgSize.Height) / 2f, _imgSize.Width, _imgSize.Height);
Graphics g = CreateGraphics();
StringFormat format = StringFormat.GenericTypographic;
format.FormatFlags |= StringFormatFlags.MeasureTrailingSpaces;
SizeF sf = g.MeasureString(Text, Font, (int)borderRect.Width, format);
float w = Convert.ToSingle(Math.Ceiling(sf.Width));
float h = Convert.ToSingle(Math.Ceiling(sf.Height));
textRect = new RectangleF(0, (Height - h) / 2f, w, h);
float x;
switch (TextAlign)
{
case HorizontalAlignment.Left:
x = BorderWidth;
if (_img != null)
{
imgRect.X = x;
x += _imgSize.Width + SPACE;
}
textRect.X = x;
break;
case HorizontalAlignment.Center:
if (_img != null)
{
x = (Width - w - _imgSize.Width - SPACE) / 2f;
imgRect.X = x;
x += _imgSize.Width + SPACE;
}
else
{
x = (Width - w) / 2f;
}
textRect.X = x;
break;
case HorizontalAlignment.Right:
x = Width - BorderWidth - w;
textRect.X = x;
if (_img != null)
{
x -= (SPACE + _imgSize.Width);
imgRect.X = x;
}
break;
}
}
private void FaceLabel_MouseMove(object sender, MouseEventArgs e)
{
buttonOver = borderPath.IsVisible(e.Location);
Refresh();
}
}
}
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
</root>
\ No newline at end of file \ No newline at end of file

namespace FaceControl
{
partial class FaceList
{
/// <summary>
/// 必需的设计器变量。
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// 清理所有正在使用的资源。
/// </summary>
/// <param name="disposing">如果应释放托管资源,为 true;否则为 false。</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region 组件设计器生成的代码
/// <summary>
/// 设计器支持所需的方法 - 不要修改
/// 使用代码编辑器修改此方法的内容。
/// </summary>
private void InitializeComponent()
{
this.SuspendLayout();
//
// FaceList
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.Name = "FaceList";
this.MouseDown += new System.Windows.Forms.MouseEventHandler(this.FaceButtonGroup_MouseDown);
this.MouseMove += new System.Windows.Forms.MouseEventHandler(this.FaceButtonGroup_MouseMove);
this.MouseUp += new System.Windows.Forms.MouseEventHandler(this.FaceButtonGroup_MouseUp);
this.ResumeLayout(false);
}
#endregion
}
}
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Windows.Forms;
namespace FaceControl
{
[DefaultProperty("SelectedText")]
[DefaultEvent("SelectedIndexChanged")]
public partial class FaceList : ControlBase
{
private bool borderOver = false;
private int buttonOverIndex = -1;
private int _selectedIndex = -1;
private int _itemHeight = 30;
private Item _item;
private RectangleF[] listRect;
private RectangleF[] textRect;
private GraphicsPath borderPath = new GraphicsPath();
private FaceScrollBar sbar = new FaceScrollBar();
public FaceList()
{
InitializeComponent();
MouseWheel += FaceButtonGroup_MouseWheel;
sbar.AllowHideDrop = false;
sbar.Left = Width - BorderWidth - sbar.Width;
sbar.Top = BorderWidth + 1;
sbar.Height = Height - BorderWidth - BorderWidth - 2;
sbar.Anchor = AnchorStyles.Top | AnchorStyles.Right | AnchorStyles.Bottom;
sbar.Minimum = 0;
sbar.Maximum = 10;
sbar.Visible = false;
sbar.MouseEnter += Vsb_MouseEnter;
sbar.MouseLeave += Vsb_MouseLeave;
sbar.Scroll += Vsb_Scroll;
Controls.Add(sbar);
_item = new Item(ItemRefresh);
}
#region 事件
[Browsable(true), Category("行为"), Description("属性值更改时发生")]
public event EventHandler SelectedIndexChanged;
#endregion
#region 属性
[Browsable(false)]
public int SelectedIndex
{
get => _selectedIndex;
set
{
if (value >= _item._list.Count)
_selectedIndex = _item._list.Count - 1;
else
_selectedIndex = value;
Refresh();
SelectedIndexChanged?.Invoke(this, new EventArgs());
}
}
[Browsable(false)]
public string SelectedText
{
set
{
int idx = _item._list.FindIndex(match => match == value);
if (idx == -1) return;
SelectedIndex = idx;
}
get
{
if (SelectedIndex == -1) return "";
return _item[SelectedIndex];
}
}
[Browsable(false)]
public Item Items
{
get
{
return _item;
}
}
#endregion
public void SelectedFirst()
{
SelectedIndex = 0;
}
public void SelectedLast()
{
SelectedIndex = _item._list.Count - 1;
}
protected override void CalcSize()
{
base.CalcSize();
CalcTextLocation();
CalcShape();
}
protected override void DrawEnabled(Graphics g)
{
base.DrawEnabled(g);
//控件边框
if (CursorInside && borderOver)
{
if (SelectedIndex > -1)
g.FillRectangle(new SolidBrush(theme.DOWN_COLOR), listRect[SelectedIndex]);
if (SelectedIndex != buttonOverIndex && buttonOverIndex > -1)
g.FillRectangle(new SolidBrush(theme.OVER_COLOR), listRect[buttonOverIndex]);
Region reg = new Region(new Rectangle(0, 0, Width, Height));
reg.Exclude(borderPath);
g.FillRegion(new SolidBrush(theme.BACK_COLOR), reg);
}
else
{
borderOver = false;
g.FillPath(new SolidBrush(BackColor), borderPath);
if (SelectedIndex > -1)
g.FillRectangle(new SolidBrush(theme.DOWN_COLOR), listRect[SelectedIndex]);
Region reg = new Region(new Rectangle(0, 0, Width, Height));
reg.Exclude(borderPath);
g.FillRegion(new SolidBrush(theme.BACK_COLOR), reg);
}
//文字
for (int i = 0; i < _item._list.Count; i++)
{
g.DrawString(_item._list[i], Font, new SolidBrush(ForeColor), textRect[i]);
}
if (CursorInside && borderOver)
{
if (BorderWidth > 0)
g.DrawPath(borderInsidePen, borderPath);
}
else
{
if (BorderWidth > 0)
g.DrawPath(borderOutsidePen, borderPath);
}
}
protected override void DrawDisabled(Graphics g)
{
base.DrawDisabled(g);
//控件边框
if (BorderWidth > 0)
g.DrawPath(borderOutsidePen, borderPath);
//文字
//string[] s = Text.Split(',');
//for (int i = 0; i < s.Length; i++)
// g.DrawString(s[i], Font, new SolidBrush(theme.LOST_FOCUS_COLOR), textRect[i]);
}
private void CalcShape()
{
borderPath = new GraphicsPath();
float n;
switch (FaceShape)
{
case Model.ButtonShape.Rectangle:
borderPath.AddRectangle(borderRect);
break;
case Model.ButtonShape.RoundRectangle:
n = borderRect.Height / 8f;
borderPath.AddLine(borderRect.X + n, borderRect.Y, borderRect.Right - n, borderRect.Y);
borderPath.AddArc(borderRect.Right - n - n, borderRect.Y, n + n, n + n, 270, 90);
borderPath.AddLine(borderRect.Right, borderRect.Y + n, borderRect.Right, borderRect.Bottom - n);
borderPath.AddArc(borderRect.Right - n - n, borderRect.Bottom - n - n, n + n, n + n, 0, 90);
borderPath.AddLine(borderRect.Right - n, borderRect.Bottom, borderRect.X + n, borderRect.Bottom);
borderPath.AddArc(borderRect.X, borderRect.Bottom - n - n, n + n, n + n, 90, 90);
borderPath.AddLine(borderRect.X, borderRect.Bottom - n, borderRect.X, borderRect.Y + n);
borderPath.AddArc(borderRect.X, borderRect.Y, n + n, n + n, 180, 90);
break;
case Model.ButtonShape.Ellipse:
borderPath.AddEllipse(borderRect);
break;
case Model.ButtonShape.EllipseRectangle:
n = borderRect.Height / 2f;
borderPath.AddLine(borderRect.X + n, borderRect.Y, borderRect.Right - n, borderRect.Y);
borderPath.AddArc(borderRect.Right - n - n, borderRect.Y, n + n, n + n, 270, 180);
borderPath.AddLine(borderRect.Right - n, borderRect.Bottom, borderRect.X + n, borderRect.Bottom);
borderPath.AddArc(borderRect.X, borderRect.Y, n + n, n + n, 90, 180);
break;
case Model.ButtonShape.Circle:
if (borderRect.Width > borderRect.Height)
borderPath.AddEllipse((borderRect.Width - borderRect.Height) / 2f, borderRect.Y, borderRect.Height, borderRect.Height);
else
borderPath.AddEllipse(borderRect.X, (borderRect.Height - borderRect.Width) / 2f, borderRect.Width, borderRect.Width);
break;
}
}
private void CalcTextLocation()
{
listRect = new RectangleF[Items._list.Count];
textRect = new RectangleF[Items._list.Count];
if (Items._list.Count == 0) return;
float w = borderRect.Width;
float offset = 0;
int height = Items._list.Count * _itemHeight + BorderWidth + BorderWidth;
if (height > Height)
{
w -= sbar.Width;
sbar.Visible = true;
int n = height - Height;
sbar.Maximum = Convert.ToInt32(Math.Ceiling(n / 10f));
float rowStep = (float)n / sbar.Maximum;
offset = rowStep * sbar.Value;
}
else
{
sbar.Visible = false;
}
Graphics g = CreateGraphics();
for (int i = 0; i < Items._list.Count; i++)
{
listRect[i] = new RectangleF(borderRect.X, borderRect.Y + _itemHeight * i - offset, w, _itemHeight);
SizeF sf = g.MeasureString(Items._list[i], Font);
textRect[i] = new RectangleF(0, listRect[i].Y + (_itemHeight - sf.Height) / 2f, sf.Width, sf.Height);
switch (TextAlign)
{
case HorizontalAlignment.Left:
textRect[i].X = borderRect.X;
break;
case HorizontalAlignment.Center:
textRect[i].X = borderRect.X + (w - sf.Width) / 2f;
break;
case HorizontalAlignment.Right:
textRect[i].X = borderRect.X + w - sf.Width;
break;
}
}
}
private void ItemRefresh()
{
if (_selectedIndex >= _item._list.Count)
_selectedIndex = 0;
if (_item._list.Count == 0)
_selectedIndex = -1;
CalcSize();
Refresh();
}
private void FaceButtonGroup_MouseDown(object sender, MouseEventArgs e)
{
if (!Enabled) return;
if (e.Button == MouseButtons.Left)
{
SelectedIndex = buttonOverIndex;
//Refresh();
//SelectedIndexChanged?.Invoke(this, new EventArgs());
}
}
private void FaceButtonGroup_MouseUp(object sender, MouseEventArgs e)
{
if (!Enabled) return;
if (e.Button == MouseButtons.Left)
{
//mouseDown = false;
Refresh();
//Click?.Invoke(this, new EventArgs());
}
}
private void FaceButtonGroup_MouseMove(object sender, MouseEventArgs e)
{
buttonOverIndex = -1;
for (int i = 0; i < listRect.Length; i++)
{
if (listRect[i].Contains(e.Location))
{
buttonOverIndex = i;
break;
}
}
borderOver = borderPath.IsVisible(e.Location);
Refresh();
}
private void FaceButtonGroup_MouseWheel(object sender, MouseEventArgs e)
{
if (!Enabled) return;
if (e.Delta > 0)
sbar.Value--;
else
sbar.Value++;
}
private void Vsb_MouseLeave(object sender, EventArgs e)
{
CursorInside = false;
borderOver = false;
Refresh();
}
private void Vsb_MouseEnter(object sender, EventArgs e)
{
buttonOverIndex = -1;
CursorInside = true;
borderOver = true;
Refresh();
}
private void Vsb_Scroll(object sender, ScrollEventArgs e)
{
ItemRefresh();
}
public class Item
{
internal List<string> _list = new List<string>();
private Action _action;
public Item(Action action)
{
_action = action;
}
public string this[int index]
{
set
{
if (index >= 0 || index < _list.Count)
{
_list[index] = value;
_action.Invoke();
}
}
get
{
if (index < 0 || index >= _list.Count)
return "";
else
return _list[index];
}
}
public int Count
{
get => _list.Count;
}
public void Add(string s)
{
if (s == null) return;
s = s.Replace('\r', '\0');
s = s.Replace('\n', '\0');
_list.Add(s);
_action.Invoke();
}
public void AddRange(params string[] s)
{
if (s == null) return;
for (int i = 0; i < s.Length; i++)
{
s[i] = s[i].Replace('\r', '\0');
s[i] = s[i].Replace('\n', '\0');
}
_list.AddRange(s);
_action.Invoke();
}
public void Remove(string s)
{
if (s == null) return;
_list.Remove(s);
_action.Invoke();
}
public void Clear()
{
_list.Clear();
_action.Invoke();
}
public void RemoveAt(int index)
{
if (index > -1 && index < _list.Count)
{
_list.RemoveAt(index);
_action.Invoke();
}
}
}
}
}
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
</root>
\ No newline at end of file \ No newline at end of file

namespace FaceControl
{
partial class FaceLock
{
/// <summary>
/// 必需的设计器变量。
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// 清理所有正在使用的资源。
/// </summary>
/// <param name="disposing">如果应释放托管资源,为 true;否则为 false。</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region 组件设计器生成的代码
/// <summary>
/// 设计器支持所需的方法 - 不要修改
/// 使用代码编辑器修改此方法的内容。
/// </summary>
private void InitializeComponent()
{
this.SuspendLayout();
//
// FaceLock
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.Name = "FaceLock";
this.Size = new System.Drawing.Size(85, 45);
this.MouseDown += new System.Windows.Forms.MouseEventHandler(this.FaceLock_MouseDown);
this.MouseUp += new System.Windows.Forms.MouseEventHandler(this.FaceLock_MouseUp);
this.ResumeLayout(false);
}
#endregion
}
}
using System;
using System.ComponentModel;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Windows.Forms;
namespace FaceControl
{
public partial class FaceLock : ControlBase
{
//private bool mouseDown = false;
//private RectangleF checkOutRect = new RectangleF();
//private RectangleF checkInRect = new RectangleF();
private GraphicsPath lockPath = new GraphicsPath();
private RectangleF textRect = new RectangleF();
private GraphicsPath borderPath = new GraphicsPath();
private bool _lock = true;
private int _lockWidth = 20;
private const int SPACE = 6; //图片与文字的间隔
public FaceLock()
{
InitializeComponent();
}
#region 事件
[Browsable(true), Category("杂项"), Description("当LockState属性更改值时发生")]
public event EventHandler LockStateChanged;
#endregion
#region 属性
[Browsable(true), Category("外观"), Description("控件上锁按钮的宽度"), DefaultValue(20)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
public int LockWidth
{
get => _lockWidth;
set
{
_lockWidth = value;
CalcSize();
Refresh();
}
}
[Browsable(true), Category("外观"), Description("锁按钮是否已锁上"), DefaultValue(true)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
public bool LockState
{
set
{
if (_lock != value)
{
_lock = value;
CalcSize();
Refresh();
}
//CheckedChanged?.Invoke(this, new EventArgs());
}
get
{
return _lock;
}
}
[Browsable(false)]
public string Password { set; get; } = "";
#endregion
protected override void CalcSize()
{
base.CalcSize();
CalcTextLocation();
CalcShape();
}
protected override void DrawEnabled(Graphics g)
{
base.DrawEnabled(g);
//控件边框
if (CursorInside)
{
g.DrawPath(new Pen(theme.DOWN_COLOR, 2), lockPath);
if (BorderWidth > 0)
g.DrawPath(borderInsidePen, borderPath);
}
else
{
if (_lock)
g.DrawPath(new Pen(ForeColor, 2), lockPath);
else
g.DrawPath(new Pen(theme.DOWN_COLOR, 2), lockPath);
if (BorderWidth > 0)
g.DrawPath(borderOutsidePen, borderPath);
}
//文字
g.DrawString(Text, Font, new SolidBrush(ForeColor), textRect);
}
protected override void DrawDisabled(Graphics g)
{
base.DrawDisabled(g);
//控件边框
g.DrawPath(new Pen(theme.LOST_FOCUS_COLOR, 2), lockPath);
if (BorderWidth > 0)
g.DrawPath(borderOutsidePen, borderPath);
//文字
g.DrawString(Text, Font, new SolidBrush(theme.LOST_FOCUS_COLOR), textRect);
}
private void CalcShape()
{
borderPath = new GraphicsPath();
float n;
switch (FaceShape)
{
case Model.ButtonShape.Rectangle:
borderPath.AddRectangle(borderRect);
break;
case Model.ButtonShape.RoundRectangle:
n = borderRect.Height / 8f;
borderPath.AddLine(borderRect.X + n, borderRect.Y, borderRect.Right - n, borderRect.Y);
borderPath.AddArc(borderRect.Right - n - n, borderRect.Y, n + n, n + n, 270, 90);
borderPath.AddLine(borderRect.Right, borderRect.Y + n, borderRect.Right, borderRect.Bottom - n);
borderPath.AddArc(borderRect.Right - n - n, borderRect.Bottom - n - n, n + n, n + n, 0, 90);
borderPath.AddLine(borderRect.Right - n, borderRect.Bottom, borderRect.X + n, borderRect.Bottom);
borderPath.AddArc(borderRect.X, borderRect.Bottom - n - n, n + n, n + n, 90, 90);
borderPath.AddLine(borderRect.X, borderRect.Bottom - n, borderRect.X, borderRect.Y + n);
borderPath.AddArc(borderRect.X, borderRect.Y, n + n, n + n, 180, 90);
break;
case Model.ButtonShape.Ellipse:
borderPath.AddEllipse(borderRect);
break;
case Model.ButtonShape.EllipseRectangle:
n = borderRect.Height / 2f;
borderPath.AddLine(borderRect.X + n, borderRect.Y, borderRect.Right - n, borderRect.Y);
borderPath.AddArc(borderRect.Right - n - n, borderRect.Y, n + n, n + n, 270, 180);
borderPath.AddLine(borderRect.Right - n, borderRect.Bottom, borderRect.X + n, borderRect.Bottom);
borderPath.AddArc(borderRect.X, borderRect.Y, n + n, n + n, 90, 180);
break;
case Model.ButtonShape.Circle:
if (borderRect.Width > borderRect.Height)
borderPath.AddEllipse((borderRect.Width - borderRect.Height) / 2f, borderRect.Y, borderRect.Height, borderRect.Height);
else
borderPath.AddEllipse(borderRect.X, (borderRect.Height - borderRect.Width) / 2f, borderRect.Width, borderRect.Width);
break;
}
}
private void CalcTextLocation()
{
if (string.IsNullOrEmpty(Text)) return;
Graphics g = CreateGraphics();
SizeF sf = g.MeasureString(Text, Font);
RectangleF rect = new RectangleF(0, (Height - _lockWidth) / 2f, _lockWidth, _lockWidth);
textRect = new RectangleF(0, (Height - sf.Height) / 2f, sf.Width, sf.Height);
float x;
switch (TextAlign)
{
case HorizontalAlignment.Left:
x = BorderWidth;
rect.X = x;
x += _lockWidth + SPACE;
textRect.X = x;
break;
case HorizontalAlignment.Center:
x = (Width - sf.Width - _lockWidth - SPACE) / 2f;
rect.X = x;
x += _lockWidth + SPACE;
textRect.X = x;
break;
case HorizontalAlignment.Right:
x = Width - BorderWidth - sf.Width;
textRect.X = x;
x -= (SPACE + _lockWidth);
rect.X = x;
break;
}
if (_lock)
lockPath = Shape.Lock(rect);
else
lockPath = Shape.Unlock(rect);
}
private void FaceLock_MouseDown(object sender, MouseEventArgs e)
{
if (!Enabled) return;
if (e.Button == MouseButtons.Left)
{
//_lock = !_lock;
//CalcTextLocation();
//Refresh();
}
}
private void FaceLock_MouseUp(object sender, MouseEventArgs e)
{
if (!Enabled) return;
if (e.Button == MouseButtons.Left)
{
if (_lock)
{
FormInput frm = new FormInput("LOCK", "PASSWORD", "");
DialogResult dr = frm.ShowDialog();
if (dr == DialogResult.OK)
{
if (frm.Msg == Password)
_lock = false;
}
}
else
{
_lock = true;
}
CalcTextLocation();
Refresh();
LockStateChanged?.Invoke(this, new EventArgs());
}
}
}
}
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
</root>
\ No newline at end of file \ No newline at end of file

namespace FaceControl
{
partial class FaceNumeric
{
/// <summary>
/// 必需的设计器变量。
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// 清理所有正在使用的资源。
/// </summary>
/// <param name="disposing">如果应释放托管资源,为 true;否则为 false。</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region 组件设计器生成的代码
/// <summary>
/// 设计器支持所需的方法 - 不要修改
/// 使用代码编辑器修改此方法的内容。
/// </summary>
private void InitializeComponent()
{
this.SuspendLayout();
//
// FaceNumeric
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.Name = "FaceNumeric";
this.Size = new System.Drawing.Size(130, 45);
this.MouseDown += new System.Windows.Forms.MouseEventHandler(this.FaceNumeric_MouseDown);
this.MouseMove += new System.Windows.Forms.MouseEventHandler(this.FaceNumeric_MouseMove);
this.MouseUp += new System.Windows.Forms.MouseEventHandler(this.FaceNumeric_MouseUp);
this.Resize += new System.EventHandler(this.FaceNumeric_Resize);
this.ResumeLayout(false);
}
#endregion
}
}
using System;
using System.ComponentModel;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Windows.Forms;
namespace FaceControl
{
[DefaultProperty("Value")]
[DefaultEvent("ValueChanged")]
public partial class FaceNumeric : ControlBase
{
private TextBox txt;
private bool[] mouseDown = new bool[2];
private bool[] buttonOver = new bool[2];
private bool borderOver = false;
private GraphicsPath borderPath = new GraphicsPath();
private RectangleF[] buttonRect = new RectangleF[2];
private RectangleF[] textRect = new RectangleF[2];
private float _min = 0;
private float _max = 100;
private float _value = 0;
private int _decimalPlaces = 2;
private const int BTN_WIDTH = 30;
private readonly string[] BTN_TEXT = new string[] { "-", "+" };
public FaceNumeric()
{
InitializeComponent();
txt = new TextBox
{
BorderStyle = BorderStyle.None,
BackColor = BackColor,
ForeColor = ForeColor,
ImeMode = ImeMode.Disable
};
txt.TextChanged += Txt_TextChanged;
txt.MouseEnter += Txt_MouseEnter;
txt.MouseLeave += Txt_MouseLeave;
txt.KeyPress += Txt_KeyPress;
Controls.Add(txt);
_decimalPlaces = 2;
Increment = 1;
ShowNumeric();
FaceNumeric_Resize(null, EventArgs.Empty);
}
#region 事件
[Browsable(true), Category("操作"), Description("控件中的值更改时发生")]
public event EventHandler ValueChanged;
#endregion
#region 属性
[Browsable(true), Category("数据"), Description("控件的最小值"), DefaultValue(0)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
public float Minimum
{
get => _min;
set
{
_min = value;
if (_value < _min) _value = _min;
ShowNumeric();
CalcSize();
Refresh();
}
}
[Browsable(true), Category("数据"), Description("控件的最大值"), DefaultValue(100)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
public float Maximum
{
get => _max;
set
{
_max = value;
if (_value > _max) _value = _max;
ShowNumeric();
CalcSize();
Refresh();
}
}
[Browsable(true), Category("外观"), Description("控件的当前值"), DefaultValue(0)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
public float Value
{
get => _value;
set
{
if (_value == value) return;
_value = value;
if (_value < _min)
_value = _min;
else if (_value > _max)
_value = _max;
ShowNumeric();
CalcSize();
Refresh();
ValueChanged?.Invoke(this, new EventArgs());
}
}
[Browsable(true), Category("数据"), Description("指示要显示的小数位数"), DefaultValue(2)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
public int DecimalPlaces
{
get => _decimalPlaces;
set
{
_decimalPlaces = value;
ShowNumeric();
}
}
[Browsable(true), Category("数据"), Description("增加或减少的数量"), DefaultValue(1)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
public float Increment { set; get; }
[Browsable(true), Category("行为"), Description("控制能否更改编辑控件中的文本"), DefaultValue(false)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
public bool ReadOnly { set => txt.ReadOnly = value; get => txt.ReadOnly; }
[Browsable(true), Category("外观"), Description("指示应该如何对齐编辑控件的文本"), DefaultValue(HorizontalAlignment.Left)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
public new HorizontalAlignment TextAlign { set => txt.TextAlign = value; get => txt.TextAlign; }
[Browsable(true), Category("外观"), Description("用于显示控件中文本的字体")]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
public override Font Font
{
get => base.Font;
set
{
base.Font = value;
FaceNumeric_Resize(null, EventArgs.Empty);
}
}
#endregion
protected override void CalcSize()
{
base.CalcSize();
CalcTextLocation();
CalcShape();
}
protected override void DrawEnabled(Graphics g)
{
base.DrawEnabled(g);
//控件边框
if (CursorInside && borderOver)
{
if (mouseDown[0])
g.FillRectangle(new SolidBrush(theme.DOWN_COLOR), buttonRect[0]); //按下
else if (buttonOver[0])
g.FillRectangle(new SolidBrush(theme.OVER_COLOR), buttonRect[0]); //经过
if (mouseDown[1])
g.FillRectangle(new SolidBrush(theme.DOWN_COLOR), buttonRect[1]); //按下
else if (buttonOver[1])
g.FillRectangle(new SolidBrush(theme.OVER_COLOR), buttonRect[1]); //经过
if (BorderWidth > 0)
g.DrawPath(borderInsidePen, borderPath);
}
else
{
g.FillPath(new SolidBrush(BackColor), borderPath);
if (BorderWidth > 0)
g.DrawPath(borderOutsidePen, borderPath);
}
g.DrawString(BTN_TEXT[0], new Font("宋体", Font.Size), new SolidBrush(ForeColor), textRect[0]);
g.DrawString(BTN_TEXT[1], new Font("宋体", Font.Size), new SolidBrush(ForeColor), textRect[1]);
}
protected override void DrawDisabled(Graphics g)
{
base.DrawDisabled(g);
//控件边框
if (BorderWidth > 0)
g.DrawPath(borderOutsidePen, borderPath);
g.DrawString(BTN_TEXT[0], new Font("宋体", Font.Size), new SolidBrush(theme.LOST_FOCUS_COLOR), textRect[0]);
g.DrawString(BTN_TEXT[1], new Font("宋体", Font.Size), new SolidBrush(theme.LOST_FOCUS_COLOR), textRect[1]);
}
private void CalcShape()
{
borderPath = new GraphicsPath();
float n;
switch (FaceShape)
{
case Model.ButtonShape.Rectangle:
borderPath.AddRectangle(borderRect);
break;
case Model.ButtonShape.RoundRectangle:
n = borderRect.Height / 8f;
borderPath.AddLine(borderRect.X + n, borderRect.Y, borderRect.Right - n, borderRect.Y);
borderPath.AddArc(borderRect.Right - n - n, borderRect.Y, n + n, n + n, 270, 90);
borderPath.AddLine(borderRect.Right, borderRect.Y + n, borderRect.Right, borderRect.Bottom - n);
borderPath.AddArc(borderRect.Right - n - n, borderRect.Bottom - n - n, n + n, n + n, 0, 90);
borderPath.AddLine(borderRect.Right - n, borderRect.Bottom, borderRect.X + n, borderRect.Bottom);
borderPath.AddArc(borderRect.X, borderRect.Bottom - n - n, n + n, n + n, 90, 90);
borderPath.AddLine(borderRect.X, borderRect.Bottom - n, borderRect.X, borderRect.Y + n);
borderPath.AddArc(borderRect.X, borderRect.Y, n + n, n + n, 180, 90);
break;
case Model.ButtonShape.Ellipse:
borderPath.AddEllipse(borderRect);
break;
case Model.ButtonShape.EllipseRectangle:
n = borderRect.Height / 2f;
borderPath.AddLine(borderRect.X + n, borderRect.Y, borderRect.Right - n, borderRect.Y);
borderPath.AddArc(borderRect.Right - n - n, borderRect.Y, n + n, n + n, 270, 180);
borderPath.AddLine(borderRect.Right - n, borderRect.Bottom, borderRect.X + n, borderRect.Bottom);
borderPath.AddArc(borderRect.X, borderRect.Y, n + n, n + n, 90, 180);
break;
case Model.ButtonShape.Circle:
if (borderRect.Width > borderRect.Height)
borderPath.AddEllipse((borderRect.Width - borderRect.Height) / 2f, borderRect.Y, borderRect.Height, borderRect.Height);
else
borderPath.AddEllipse(borderRect.X, (borderRect.Height - borderRect.Width) / 2f, borderRect.Width, borderRect.Width);
break;
}
}
private void CalcTextLocation()
{
buttonRect[0] = new RectangleF(borderRect.X, borderRect.Y, BTN_WIDTH, borderRect.Height);
buttonRect[1] = new RectangleF(borderRect.Right - BTN_WIDTH, borderRect.Y, BTN_WIDTH, borderRect.Height);
Graphics g = CreateGraphics();
SizeF sf = g.MeasureString(BTN_TEXT[0], new Font("宋体", Font.Size));
float x = buttonRect[0].X + (buttonRect[0].Width - sf.Width) / 2f;
float y = buttonRect[0].Y + (buttonRect[0].Height - sf.Height) / 2f;
textRect[0] = new RectangleF(x, y, sf.Width, sf.Height);
sf = g.MeasureString(BTN_TEXT[1], new Font("宋体", Font.Size));
x = buttonRect[1].X + (buttonRect[1].Width - sf.Width) / 2f;
y = buttonRect[1].Y + (buttonRect[1].Height - sf.Height) / 2f;
textRect[1] = new RectangleF(x, y, sf.Width, sf.Height);
}
private void ShowNumeric()
{
txt.Text = string.Format("{0:N"+ _decimalPlaces + "}", _value);
txt.SelectionStart = txt.Text.Length;
}
private void Txt_TextChanged(object sender, EventArgs e)
{
//TextChanged?.Invoke(this, new EventArgs());
}
private void Txt_KeyPress(object sender, KeyPressEventArgs e)
{
if (e.KeyChar == 13)
{
bool rtn = float.TryParse(txt.Text, out float result);
if (rtn) _value = result;
ShowNumeric();
}
else
{
if ((e.KeyChar < 48 || e.KeyChar > 57) && //0-9
(e.KeyChar != 8) && //Backspace
(e.KeyChar != 46) && //.
(e.KeyChar != 45)) //-
{
e.Handled = true;
}
}
}
private void Txt_MouseLeave(object sender, EventArgs e)
{
CursorInside = false;
borderOver = false;
Refresh();
}
private void Txt_MouseEnter(object sender, EventArgs e)
{
CursorInside = true;
borderOver = true;
Refresh();
}
private void FaceNumeric_MouseDown(object sender, MouseEventArgs e)
{
if (!Enabled) return;
if (e.Button == MouseButtons.Left)
{
if (buttonOver[0])
{
mouseDown[0] = true;
Value -= Increment;
}
else if (buttonOver[1])
{
mouseDown[1] = true;
Value += Increment;
}
Refresh();
}
}
private void FaceNumeric_MouseMove(object sender, MouseEventArgs e)
{
buttonOver[0] = buttonOver[1] = false;
if (buttonRect[0].Contains(e.Location))
buttonOver[0] = true;
else if (buttonRect[1].Contains(e.Location))
buttonOver[1] = true;
borderOver = borderPath.IsVisible(e.Location);
Refresh();
}
private void FaceNumeric_MouseUp(object sender, MouseEventArgs e)
{
if (!Enabled) return;
if (e.Button == MouseButtons.Left)
{
mouseDown[0] = mouseDown[1] = false;
Refresh();
}
}
private void FaceNumeric_Resize(object sender, EventArgs e)
{
txt.Left = BorderWidth + BTN_WIDTH + 3;
txt.Width = Width - (BorderWidth + BTN_WIDTH + 3) * 2;
txt.Top = BorderWidth + (Height - BorderWidth - BorderWidth - txt.Height) / 2;
}
}
}
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
</root>
\ No newline at end of file \ No newline at end of file

namespace FaceControl
{
partial class FacePanel
{
/// <summary>
/// 必需的设计器变量。
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// 清理所有正在使用的资源。
/// </summary>
/// <param name="disposing">如果应释放托管资源,为 true;否则为 false。</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region 组件设计器生成的代码
/// <summary>
/// 设计器支持所需的方法 - 不要修改
/// 使用代码编辑器修改此方法的内容。
/// </summary>
private void InitializeComponent()
{
components = new System.ComponentModel.Container();
}
#endregion
}
}
using System;
using System.ComponentModel;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Windows.Forms;
namespace FaceControl
{
[DefaultProperty("Image")]
public partial class FacePanel : PanelBase
{
private bool buttonOver = false;
private RectangleF imgRect = new RectangleF();
private RectangleF textRect = new RectangleF();
private GraphicsPath borderPath = new GraphicsPath();
private Bitmap _img = null;
private Size _imgSize = new Size();
private int _textHeight = 28;
private bool _showText = true;
private const int SPACE = 6; //图片与文字的间隔
public FacePanel()
{
InitializeComponent();
MouseMove += FaceButton_MouseMove;
}
#region 属性
[Browsable(true), Category("外观"), Description("控件上显示的图像"), DefaultValue(null)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
public Bitmap Image
{
get => _img;
set
{
_img = value;
if (_img == null)
ImageSize = new Size();
else
ImageSize = _img.Size;
CalcSize();
Refresh();
}
}
[Browsable(true), Category("外观"), Description("控件上显示的图像的大小")]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
public Size ImageSize
{
get => _imgSize;
set
{
_imgSize = value;
CalcSize();
Refresh();
}
}
[Browsable(true), Category("外观"), Description("与控件关联的文本高度"), DefaultValue(28)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
public int TextHeight
{
get => _textHeight;
set
{
_textHeight = value;
CalcSize();
Refresh();
}
}
[Browsable(true), Category("外观"), Description("与控件关联的文本是否显示"), DefaultValue(true)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
public bool ShowText
{
get => _showText;
set
{
_showText = value;
CalcSize();
Refresh();
}
}
#endregion
protected override void CalcSize()
{
base.CalcSize();
CalcTextLocation();
CalcShape();
}
protected override void DrawEnabled(Graphics g)
{
base.DrawEnabled(g);
if (_showText)
{
Region reg = new Region(borderPath);
reg.Intersect(new RectangleF(0, borderRect.Y, Width, _textHeight));
g.FillRegion(new SolidBrush(theme.DOWN_COLOR), reg);
//文字
g.DrawString(Text, TitleFont, new SolidBrush(ForeColor), textRect);
}
//控件边框
//if (CursorInside && buttonOver)
//{
if (BorderWidth > 0)
g.DrawPath(borderInsidePen, borderPath);
//}
//else
//{
// if (BorderWidth > 0)
// g.DrawPath(borderOutsidePen, borderPath);
//}
//图标
if (_img != null)
g.DrawImage(_img, imgRect, new RectangleF(0, 0, _img.Width, _img.Height), GraphicsUnit.Pixel);
}
protected override void DrawDisabled(Graphics g)
{
base.DrawDisabled(g);
if (_showText)
{
//Region reg = new Region(borderPath);
//reg.Intersect(new RectangleF(0, borderRect.Y, Width, _textHeight));
//g.FillRegion(new SolidBrush(theme.LOST_FOCUS_COLOR), reg);
//文字
g.DrawString(Text, TitleFont, new SolidBrush(theme.LOST_FOCUS_COLOR), textRect);
}
//控件边框
if (BorderWidth > 0)
g.DrawPath(borderOutsidePen, borderPath);
//图标
if (_img != null)
g.DrawImage(_img, imgRect, new RectangleF(0, 0, _img.Width, _img.Height), GraphicsUnit.Pixel);
}
private void CalcShape()
{
borderPath = new GraphicsPath();
float n;
switch (FaceShape)
{
case Model.ButtonShape.Rectangle:
borderPath.AddRectangle(borderRect);
break;
case Model.ButtonShape.RoundRectangle:
n = borderRect.Height / 8f;
borderPath.AddLine(borderRect.X + n, borderRect.Y, borderRect.Right - n, borderRect.Y);
borderPath.AddArc(borderRect.Right - n - n, borderRect.Y, n + n, n + n, 270, 90);
borderPath.AddLine(borderRect.Right, borderRect.Y + n, borderRect.Right, borderRect.Bottom - n);
borderPath.AddArc(borderRect.Right - n - n, borderRect.Bottom - n - n, n + n, n + n, 0, 90);
borderPath.AddLine(borderRect.Right - n, borderRect.Bottom, borderRect.X + n, borderRect.Bottom);
borderPath.AddArc(borderRect.X, borderRect.Bottom - n - n, n + n, n + n, 90, 90);
borderPath.AddLine(borderRect.X, borderRect.Bottom - n, borderRect.X, borderRect.Y + n);
borderPath.AddArc(borderRect.X, borderRect.Y, n + n, n + n, 180, 90);
break;
case Model.ButtonShape.Ellipse:
borderPath.AddEllipse(borderRect);
break;
case Model.ButtonShape.EllipseRectangle:
n = borderRect.Height / 2f;
borderPath.AddLine(borderRect.X + n, borderRect.Y, borderRect.Right - n, borderRect.Y);
borderPath.AddArc(borderRect.Right - n - n, borderRect.Y, n + n, n + n, 270, 180);
borderPath.AddLine(borderRect.Right - n, borderRect.Bottom, borderRect.X + n, borderRect.Bottom);
borderPath.AddArc(borderRect.X, borderRect.Y, n + n, n + n, 90, 180);
break;
case Model.ButtonShape.Circle:
if (borderRect.Width > borderRect.Height)
borderPath.AddEllipse((borderRect.Width - borderRect.Height) / 2f, borderRect.Y, borderRect.Height, borderRect.Height);
else
borderPath.AddEllipse(borderRect.X, (borderRect.Height - borderRect.Width) / 2f, borderRect.Width, borderRect.Width);
break;
}
}
private void CalcTextLocation()
{
if (string.IsNullOrEmpty(Text)) return;
Graphics g = CreateGraphics();
SizeF sf = g.MeasureString(Text, TitleFont);
imgRect = new RectangleF(0, (_textHeight - _imgSize.Height) / 2f, _imgSize.Width, _imgSize.Height);
textRect = new RectangleF(0, (_textHeight - sf.Height) / 2f, sf.Width, sf.Height);
float x;
switch (TextAlign)
{
case HorizontalAlignment.Left:
x = BorderWidth;
if (_img != null)
{
imgRect.X = x;
x += _imgSize.Width + SPACE;
}
textRect.X = x;
break;
case HorizontalAlignment.Center:
if (_img != null)
{
x = (Width - sf.Width - _imgSize.Width - SPACE) / 2f;
imgRect.X = x;
x += _imgSize.Width + SPACE;
}
else
{
x = (Width - sf.Width) / 2f;
}
textRect.X = x;
break;
case HorizontalAlignment.Right:
x = Width - BorderWidth - sf.Width;
textRect.X = x;
if (_img != null)
{
x -= (SPACE + _imgSize.Width);
imgRect.X = x;
}
break;
}
}
private void FaceButton_MouseMove(object sender, MouseEventArgs e)
{
//buttonOver = borderPath.IsVisible(e.Location);
//Refresh();
}
}
}

namespace FaceControl
{
partial class FaceRadio
{
/// <summary>
/// 必需的设计器变量。
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// 清理所有正在使用的资源。
/// </summary>
/// <param name="disposing">如果应释放托管资源,为 true;否则为 false。</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region 组件设计器生成的代码
/// <summary>
/// 设计器支持所需的方法 - 不要修改
/// 使用代码编辑器修改此方法的内容。
/// </summary>
private void InitializeComponent()
{
this.SuspendLayout();
//
// FaceRadio
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.Name = "FaceRadio";
this.Size = new System.Drawing.Size(85, 45);
this.MouseDown += new System.Windows.Forms.MouseEventHandler(this.FaceRadio_MouseDown);
this.MouseMove += new System.Windows.Forms.MouseEventHandler(this.FaceRadio_MouseMove);
this.MouseUp += new System.Windows.Forms.MouseEventHandler(this.FaceRadio_MouseUp);
this.ResumeLayout(false);
}
#endregion
}
}
using System;
using System.ComponentModel;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Windows.Forms;
namespace FaceControl
{
[DefaultProperty("Text")]
[DefaultEvent("CheckedChanged")]
public partial class FaceRadio : ControlBase
{
private bool mouseDown = false;
private RectangleF ringOutRect = new RectangleF();
private RectangleF ringInRect = new RectangleF();
private RectangleF ringPoint = new RectangleF();
private RectangleF textRect = new RectangleF();
private GraphicsPath borderPath = new GraphicsPath();
private bool _check = false;
private int _ringWidth = 18;
private const int SPACE = 6; //图片与文字的间隔
public FaceRadio()
{
InitializeComponent();
}
#region 事件
[Browsable(true), Category("杂项"), Description("当checked属性更改值时发生")]
public event EventHandler CheckedChanged;
#endregion
#region 属性
[Browsable(true), Category("外观"), Description("控件上环形开关的宽度"), DefaultValue(18)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
public int RingWidth
{
get => _ringWidth;
set
{
_ringWidth = value;
CalcSize();
Refresh();
}
}
[Browsable(true), Category(""), Description("单选按钮是否已选中"), DefaultValue(false)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
public bool Checked
{
set
{
if (_check != value)
{
_check = value;
CalcSize();
Refresh();
}
if (_check)
SetGroup();
CheckedChanged?.Invoke(this, new EventArgs());
}
get
{
return _check;
}
}
[Browsable(true), Category(""), Description("相同的内容为一组,同一组的单选按钮只能选中一个。"), DefaultValue("")]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
public string Group { set; get; }
#endregion
protected override void CalcSize()
{
base.CalcSize();
CalcTextLocation();
CalcShape();
}
protected override void DrawEnabled(Graphics g)
{
base.DrawEnabled(g);
//控件边框
if (CursorInside)
{
if (_check)
{
if (mouseDown)
g.FillEllipse(new SolidBrush(theme.DOWN_COLOR), ringOutRect);
else
g.FillEllipse(new SolidBrush(ForeColor), ringOutRect);
}
else
{
if (mouseDown)
g.FillEllipse(new SolidBrush(ForeColor), ringOutRect);
else
g.FillEllipse(new SolidBrush(theme.DOWN_COLOR), ringOutRect);
}
g.FillEllipse(new SolidBrush(theme.BACK_COLOR), ringInRect);
if (BorderWidth > 0)
g.DrawPath(borderInsidePen, borderPath);
}
else
{
g.FillPath(new SolidBrush(BackColor), borderPath);
if (_check)
{
g.FillEllipse(new SolidBrush(theme.DOWN_COLOR), ringOutRect);
}
else
{
g.FillEllipse(new SolidBrush(ForeColor), ringOutRect);
}
g.FillEllipse(new SolidBrush(theme.BACK_COLOR), ringInRect);
if (BorderWidth > 0)
g.DrawPath(borderOutsidePen, borderPath);
}
//开关圆点
if (_check)
g.FillEllipse(new SolidBrush(ForeColor), ringPoint);
//文字
g.DrawString(Text, Font, new SolidBrush(ForeColor), textRect);
}
protected override void DrawDisabled(Graphics g)
{
base.DrawDisabled(g);
//控件边框
g.FillEllipse(new SolidBrush(theme.OVER_COLOR), ringOutRect);
g.FillEllipse(new SolidBrush(theme.BACK_COLOR), ringInRect);
if (BorderWidth > 0)
g.DrawPath(borderOutsidePen, borderPath);
//开关圆点
if (_check)
g.FillEllipse(new SolidBrush(theme.OVER_COLOR), ringPoint);
//文字
g.DrawString(Text, Font, new SolidBrush(theme.LOST_FOCUS_COLOR), textRect);
}
private void SetGroup()
{
if (Parent == null) return;
foreach (Control ctl in Parent.Controls)
{
if (ctl is FaceRadio)
{
FaceRadio rdo = (FaceRadio)ctl;
if (rdo == this) continue;
if (rdo.Group == Group)
{
if (rdo.Checked)
{
rdo.Checked = false;
break;
}
}
}
}
}
private void CalcShape()
{
borderPath = new GraphicsPath();
float n;
switch (FaceShape)
{
case Model.ButtonShape.Rectangle:
borderPath.AddRectangle(borderRect);
break;
case Model.ButtonShape.RoundRectangle:
n = borderRect.Height / 8f;
borderPath.AddLine(borderRect.X + n, borderRect.Y, borderRect.Right - n, borderRect.Y);
borderPath.AddArc(borderRect.Right - n - n, borderRect.Y, n + n, n + n, 270, 90);
borderPath.AddLine(borderRect.Right, borderRect.Y + n, borderRect.Right, borderRect.Bottom - n);
borderPath.AddArc(borderRect.Right - n - n, borderRect.Bottom - n - n, n + n, n + n, 0, 90);
borderPath.AddLine(borderRect.Right - n, borderRect.Bottom, borderRect.X + n, borderRect.Bottom);
borderPath.AddArc(borderRect.X, borderRect.Bottom - n - n, n + n, n + n, 90, 90);
borderPath.AddLine(borderRect.X, borderRect.Bottom - n, borderRect.X, borderRect.Y + n);
borderPath.AddArc(borderRect.X, borderRect.Y, n + n, n + n, 180, 90);
break;
case Model.ButtonShape.Ellipse:
borderPath.AddEllipse(borderRect);
break;
case Model.ButtonShape.EllipseRectangle:
n = borderRect.Height / 2f;
borderPath.AddLine(borderRect.X + n, borderRect.Y, borderRect.Right - n, borderRect.Y);
borderPath.AddArc(borderRect.Right - n - n, borderRect.Y, n + n, n + n, 270, 180);
borderPath.AddLine(borderRect.Right - n, borderRect.Bottom, borderRect.X + n, borderRect.Bottom);
borderPath.AddArc(borderRect.X, borderRect.Y, n + n, n + n, 90, 180);
break;
case Model.ButtonShape.Circle:
if (borderRect.Width > borderRect.Height)
borderPath.AddEllipse((borderRect.Width - borderRect.Height) / 2f, borderRect.Y, borderRect.Height, borderRect.Height);
else
borderPath.AddEllipse(borderRect.X, (borderRect.Height - borderRect.Width) / 2f, borderRect.Width, borderRect.Width);
break;
}
}
private void CalcTextLocation()
{
if (string.IsNullOrEmpty(Text)) return;
Graphics g = CreateGraphics();
SizeF sf = g.MeasureString(Text, Font);
ringOutRect = new RectangleF(0, (Height - _ringWidth) / 2f, _ringWidth, _ringWidth);
textRect = new RectangleF(0, (Height - sf.Height) / 2f, sf.Width, sf.Height);
float x;
switch (TextAlign)
{
case HorizontalAlignment.Left:
x = BorderWidth;
ringOutRect.X = x;
x += _ringWidth + SPACE;
textRect.X = x;
break;
case HorizontalAlignment.Center:
x = (Width - sf.Width - _ringWidth - SPACE) / 2f;
ringOutRect.X = x;
x += _ringWidth + SPACE;
textRect.X = x;
break;
case HorizontalAlignment.Right:
x = Width - BorderWidth - sf.Width;
textRect.X = x;
x -= (SPACE + _ringWidth);
ringOutRect.X = x;
break;
}
float w = _ringWidth / 6f;
ringInRect = new RectangleF(ringOutRect.X + w, ringOutRect.Y + w, w * 4, w * 4);
ringPoint = new RectangleF(ringOutRect.X + w * 2, ringOutRect.Y + w * 2, w * 2, w * 2);
}
private void FaceRadio_MouseDown(object sender, MouseEventArgs e)
{
if (!Enabled) return;
if (e.Button == MouseButtons.Left)
{
mouseDown = true;
_check = !_check;
Refresh();
if (_check)
SetGroup();
}
}
private void FaceRadio_MouseUp(object sender, MouseEventArgs e)
{
if (!Enabled) return;
if (e.Button == MouseButtons.Left)
{
mouseDown = false;
Refresh();
CheckedChanged?.Invoke(this, new EventArgs());
}
}
private void FaceRadio_MouseMove(object sender, MouseEventArgs e)
{
//buttonOver = borderPath.IsVisible(e.Location);
//Refresh();
}
}
}
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
</root>
\ No newline at end of file \ No newline at end of file

namespace FaceControl
{
partial class FaceRadioGroup
{
/// <summary>
/// 必需的设计器变量。
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// 清理所有正在使用的资源。
/// </summary>
/// <param name="disposing">如果应释放托管资源,为 true;否则为 false。</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region 组件设计器生成的代码
/// <summary>
/// 设计器支持所需的方法 - 不要修改
/// 使用代码编辑器修改此方法的内容。
/// </summary>
private void InitializeComponent()
{
this.SuspendLayout();
//
// FaceRadioGroup
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.Name = "FaceRadioGroup";
this.Size = new System.Drawing.Size(85, 45);
this.MouseDown += new System.Windows.Forms.MouseEventHandler(this.FaceRadioGroup_MouseDown);
this.MouseMove += new System.Windows.Forms.MouseEventHandler(this.FaceRadioGroup_MouseMove);
this.MouseUp += new System.Windows.Forms.MouseEventHandler(this.FaceRadioGroup_MouseUp);
this.ResumeLayout(false);
}
#endregion
}
}
using System;
using System.ComponentModel;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Windows.Forms;
namespace FaceControl
{
[DefaultProperty("SelectedIndex")]
[DefaultEvent("CheckedChanged")]
public partial class FaceRadioGroup : ControlBase
{
private int buttonOverIndex = -1;
private int buttonDownIndex = -1;
private RectangleF[] textRect;
private RectangleF[] buttonRect;
private GraphicsPath borderPath = new GraphicsPath();
public FaceRadioGroup()
{
InitializeComponent();
}
#region 事件
[Browsable(true), Category("杂项"), Description("当checked属性更改值时发生")]
public event EventHandler CheckedChanged;
#endregion
#region 属性
[Browsable(false)]
public int SelectedIndex
{
get => buttonDownIndex;
set
{
buttonDownIndex = value;
Refresh();
CheckedChanged?.Invoke(this, new EventArgs());
}
}
[Browsable(false)]
public string SelectedText
{
set
{
string[] s = Text.Split(',');
int idx = Array.FindIndex(s, match => match == value);
if (idx == -1) return;
SelectedIndex = idx;
}
get
{
if (buttonDownIndex == -1) return "";
string[] s = Text.Split(',');
return s[buttonDownIndex];
}
}
#endregion
protected override void CalcSize()
{
base.CalcSize();
CalcTextLocation();
CalcShape();
}
protected override void DrawEnabled(Graphics g)
{
base.DrawEnabled(g);
//控件边框
if (CursorInside && buttonOverIndex > -1)
{
if (buttonDownIndex != -1)
g.FillRectangle(new SolidBrush(theme.DOWN_COLOR), buttonRect[buttonDownIndex]);
if (buttonDownIndex != buttonOverIndex)
g.FillRectangle(new SolidBrush(theme.OVER_COLOR), buttonRect[buttonOverIndex]); //经过
Region reg = new Region(new Rectangle(0, 0, Width, Height));
reg.Exclude(borderPath);
g.FillRegion(new SolidBrush(theme.BACK_COLOR), reg);
if (BorderWidth > 0)
g.DrawPath(borderInsidePen, borderPath);
}
else
{
buttonOverIndex = -1;
g.FillPath(new SolidBrush(BackColor), borderPath);
if (buttonDownIndex != -1)
g.FillRectangle(new SolidBrush(theme.DOWN_COLOR), buttonRect[buttonDownIndex]);
Region reg = new Region(new Rectangle(0, 0, Width, Height));
reg.Exclude(borderPath);
g.FillRegion(new SolidBrush(theme.BACK_COLOR), reg);
if (BorderWidth > 0)
g.DrawPath(borderOutsidePen, borderPath);
}
//文字
string[] s = Text.Split(',');
for (int i = 0; i < s.Length; i++)
g.DrawString(s[i], Font, new SolidBrush(ForeColor), textRect[i]);
}
protected override void DrawDisabled(Graphics g)
{
base.DrawDisabled(g);
//控件边框
if (BorderWidth > 0)
g.DrawPath(borderOutsidePen, borderPath);
//文字
string[] s = Text.Split(',');
for (int i = 0; i < s.Length; i++)
g.DrawString(s[i], Font, new SolidBrush(theme.LOST_FOCUS_COLOR), textRect[i]);
}
private void CalcShape()
{
borderPath = new GraphicsPath();
float n;
switch (FaceShape)
{
case Model.ButtonShape.Rectangle:
borderPath.AddRectangle(borderRect);
break;
case Model.ButtonShape.RoundRectangle:
n = borderRect.Height / 8f;
borderPath.AddLine(borderRect.X + n, borderRect.Y, borderRect.Right - n, borderRect.Y);
borderPath.AddArc(borderRect.Right - n - n, borderRect.Y, n + n, n + n, 270, 90);
borderPath.AddLine(borderRect.Right, borderRect.Y + n, borderRect.Right, borderRect.Bottom - n);
borderPath.AddArc(borderRect.Right - n - n, borderRect.Bottom - n - n, n + n, n + n, 0, 90);
borderPath.AddLine(borderRect.Right - n, borderRect.Bottom, borderRect.X + n, borderRect.Bottom);
borderPath.AddArc(borderRect.X, borderRect.Bottom - n - n, n + n, n + n, 90, 90);
borderPath.AddLine(borderRect.X, borderRect.Bottom - n, borderRect.X, borderRect.Y + n);
borderPath.AddArc(borderRect.X, borderRect.Y, n + n, n + n, 180, 90);
break;
case Model.ButtonShape.Ellipse:
borderPath.AddEllipse(borderRect);
break;
case Model.ButtonShape.EllipseRectangle:
n = borderRect.Height / 2f;
borderPath.AddLine(borderRect.X + n, borderRect.Y, borderRect.Right - n, borderRect.Y);
borderPath.AddArc(borderRect.Right - n - n, borderRect.Y, n + n, n + n, 270, 180);
borderPath.AddLine(borderRect.Right - n, borderRect.Bottom, borderRect.X + n, borderRect.Bottom);
borderPath.AddArc(borderRect.X, borderRect.Y, n + n, n + n, 90, 180);
break;
case Model.ButtonShape.Circle:
if (borderRect.Width > borderRect.Height)
borderPath.AddEllipse((borderRect.Width - borderRect.Height) / 2f, borderRect.Y, borderRect.Height, borderRect.Height);
else
borderPath.AddEllipse(borderRect.X, (borderRect.Height - borderRect.Width) / 2f, borderRect.Width, borderRect.Width);
break;
}
}
private void CalcTextLocation()
{
if (string.IsNullOrEmpty(Text)) return;
Graphics g = CreateGraphics();
string[] s = Text.Split(',');
buttonRect = new RectangleF[s.Length];
textRect = new RectangleF[s.Length];
float w = (Width - BorderWidth - BorderWidth) / (float)s.Length;
float h = Height - BorderWidth - BorderWidth;
for (int i = 0; i < s.Length; i++)
{
buttonRect[i] = new RectangleF(BorderWidth + w * i, BorderWidth, w, h);
SizeF sf = g.MeasureString(s[i], Font);
textRect[i] = new RectangleF(0, (h - sf.Height) / 2f, sf.Width, sf.Height);
switch (TextAlign)
{
case HorizontalAlignment.Left:
textRect[i].X = buttonRect[i].X;
break;
case HorizontalAlignment.Center:
textRect[i].X = buttonRect[i].X + (buttonRect[i].Width - sf.Width) / 2f;
break;
case HorizontalAlignment.Right:
textRect[i].X = buttonRect[i].X + buttonRect[i].Width - sf.Width;
break;
}
}
}
private void FaceRadioGroup_MouseDown(object sender, MouseEventArgs e)
{
if (!Enabled) return;
if (e.Button == MouseButtons.Left)
{
buttonDownIndex = buttonOverIndex;
Refresh();
}
}
private void FaceRadioGroup_MouseUp(object sender, MouseEventArgs e)
{
if (!Enabled) return;
if (e.Button == MouseButtons.Left)
{
Refresh();
CheckedChanged?.Invoke(this, new EventArgs());
}
}
private void FaceRadioGroup_MouseMove(object sender, MouseEventArgs e)
{
buttonOverIndex = -1;
for (int i = 0; i < buttonRect.Length; i++)
{
if (buttonRect[i].Contains(e.Location))
{
buttonOverIndex = i;
break;
}
}
Refresh();
}
}
}
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
</root>
\ No newline at end of file \ No newline at end of file

namespace FaceControl
{
partial class FaceScrollBar
{
/// <summary>
/// 必需的设计器变量。
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// 清理所有正在使用的资源。
/// </summary>
/// <param name="disposing">如果应释放托管资源,为 true;否则为 false。</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region 组件设计器生成的代码
/// <summary>
/// 设计器支持所需的方法 - 不要修改
/// 使用代码编辑器修改此方法的内容。
/// </summary>
private void InitializeComponent()
{
this.SuspendLayout();
//
// FaceScrollBar
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.Name = "FaceScrollBar";
this.Size = new System.Drawing.Size(25, 97);
this.MouseDown += new System.Windows.Forms.MouseEventHandler(this.FaceButton_MouseDown);
this.MouseMove += new System.Windows.Forms.MouseEventHandler(this.FaceButton_MouseMove);
this.MouseUp += new System.Windows.Forms.MouseEventHandler(this.FaceButton_MouseUp);
this.ResumeLayout(false);
}
#endregion
}
}
using System;
using System.ComponentModel;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Windows.Forms;
namespace FaceControl
{
[DefaultProperty("Value")]
[DefaultEvent("Scroll")]
public partial class FaceScrollBar : ControlBase
{
//private bool mouseDown = false;
private int buttonOverIndex = -1;
private int buttonDownIndex = -1;
private bool borderOver = false;
private float trackStep = 0;
private RectangleF[] textRect = new RectangleF[3];
private RectangleF[] buttonRect = new RectangleF[3];
private GraphicsPath borderPath = new GraphicsPath();
//private Rectangle _button1 = new Rectangle();
//private Rectangle _button2 = new Rectangle();
//private RectangleF _slider = new RectangleF();
//private GraphicsPath _btnShape1 = new GraphicsPath();
//private GraphicsPath _btnShape2 = new GraphicsPath();
//private int _over = -1;
//private int _down = -1;
private int _oldY = -1;
private int _max = 100;
private int _min = 0;
private int _value = 0;
//private float _step = SLIDER_STEP;
private const int BTN_HEIGHT = 28;
private const int SLIDER_MIN = 15;
private const int SLIDER_STEP = 2;
//private static readonly Color BACK = Color.FromArgb(40, 40, 40);
//private static readonly Brush BTN_BRUSH = new SolidBrush(Color.FromArgb(60, 60, 60));
//private static readonly Brush SLIDER_BRUSH = new SolidBrush(Color.FromArgb(60, 60, 60));
//private static readonly Brush SLIDER_OVER = new SolidBrush(Color.FromArgb(70, 70, 70));
public FaceScrollBar()
{
InitializeComponent();
}
#region 事件
[Browsable(true), Category("操作"), Description("用户移动滚动框时发生")]
public new event ScrollEventHandler Scroll;
#endregion
#region 属性
[Browsable(true), Category("行为"), Description("滑块位置的最小值"), DefaultValue(0)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
public int Minimum
{
get => _min;
set
{
_min = value;
if (_value < _min) _value = _min;
CalcSize();
Refresh();
}
}
[Browsable(true), Category("行为"), Description("滑块位置的最大值"), DefaultValue(100)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
public int Maximum
{
get => _max;
set
{
_max = value;
if (_value > _max) _value = _max;
CalcSize();
Refresh();
}
}
[Browsable(true), Category("行为"), Description("滑块的位置"), DefaultValue(0)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
public int Value
{
get => _value;
set
{
if (_value == value) return;
_value = value;
if (_value < _min)
_value = _min;
else if (_value > _max)
_value = _max;
CalcSize();
Refresh();
Scroll?.Invoke(this, new ScrollEventArgs(ScrollEventType.EndScroll, _value));
}
}
#endregion
protected override void CalcSize()
{
base.CalcSize();
CalcTextLocation();
CalcShape();
}
protected override void DrawEnabled(Graphics g)
{
base.DrawEnabled(g);
//控件边框
if (CursorInside && borderOver)
{
//if (mouseDown)
// g.FillRectangle(new SolidBrush(theme.DOWN_COLOR), buttonRect[buttonOverIndex]); //按下
//else
// g.FillRectangle(new SolidBrush(theme.OVER_COLOR), buttonRect[buttonOverIndex]); //经过
//if (buttonDownIndex != -1)
// g.FillRectangle(new SolidBrush(theme.DOWN_COLOR), buttonRect[buttonDownIndex]);
//if (buttonDownIndex != buttonOverIndex)
// g.FillRectangle(new SolidBrush(theme.OVER_COLOR), buttonRect[buttonOverIndex]); //经过
if (buttonDownIndex == 0)
g.FillRectangle(new SolidBrush(theme.DOWN_COLOR), buttonRect[0]);
else
g.FillRectangle(new SolidBrush(theme.OVER_COLOR), buttonRect[0]);
if (buttonDownIndex == 1)
g.FillRectangle(new SolidBrush(theme.DOWN_COLOR), buttonRect[1]);
else
g.FillRectangle(new SolidBrush(theme.OVER_COLOR), buttonRect[1]);
if (buttonDownIndex == 2)
g.FillRectangle(new SolidBrush(theme.DOWN_COLOR), buttonRect[2]);
else
g.FillRectangle(new SolidBrush(theme.OVER_COLOR), buttonRect[2]);
Region reg = new Region(new Rectangle(0, 0, Width, Height));
reg.Exclude(borderPath);
g.FillRegion(new SolidBrush(theme.BACK_COLOR), reg);
if (BorderWidth > 0)
g.DrawPath(borderInsidePen, borderPath);
}
else
{
buttonOverIndex = -1;
g.FillPath(new SolidBrush(BackColor), borderPath);
//g.FillRectangle(new SolidBrush(theme.OVER_COLOR), buttonRect[0]);
//g.FillRectangle(new SolidBrush(theme.OVER_COLOR), buttonRect[1]);
//g.FillRectangle(new SolidBrush(theme.OVER_COLOR), buttonRect[2]);
Region reg = new Region(new Rectangle(0, 0, Width, Height));
reg.Exclude(borderPath);
g.FillRegion(new SolidBrush(theme.BACK_COLOR), reg);
if (BorderWidth > 0)
g.DrawPath(borderOutsidePen, borderPath);
}
//文字
g.DrawString("▲", Font, new SolidBrush(ForeColor), textRect[0]);
g.DrawString("▼", Font, new SolidBrush(ForeColor), textRect[2]);
}
protected override void DrawDisabled(Graphics g)
{
base.DrawDisabled(g);
//控件边框
if (BorderWidth > 0)
g.DrawPath(borderOutsidePen, borderPath);
//文字
g.DrawString("▲", Font, new SolidBrush(theme.LOST_FOCUS_COLOR), textRect[0]);
g.DrawString("▼", Font, new SolidBrush(theme.LOST_FOCUS_COLOR), textRect[2]);
}
private void CalcShape()
{
borderPath = new GraphicsPath();
float n;
switch (FaceShape)
{
case Model.ButtonShape.Rectangle:
borderPath.AddRectangle(borderRect);
break;
case Model.ButtonShape.RoundRectangle:
n = borderRect.Height / 8f;
borderPath.AddLine(borderRect.X + n, borderRect.Y, borderRect.Right - n, borderRect.Y);
borderPath.AddArc(borderRect.Right - n - n, borderRect.Y, n + n, n + n, 270, 90);
borderPath.AddLine(borderRect.Right, borderRect.Y + n, borderRect.Right, borderRect.Bottom - n);
borderPath.AddArc(borderRect.Right - n - n, borderRect.Bottom - n - n, n + n, n + n, 0, 90);
borderPath.AddLine(borderRect.Right - n, borderRect.Bottom, borderRect.X + n, borderRect.Bottom);
borderPath.AddArc(borderRect.X, borderRect.Bottom - n - n, n + n, n + n, 90, 90);
borderPath.AddLine(borderRect.X, borderRect.Bottom - n, borderRect.X, borderRect.Y + n);
borderPath.AddArc(borderRect.X, borderRect.Y, n + n, n + n, 180, 90);
break;
case Model.ButtonShape.Ellipse:
borderPath.AddEllipse(borderRect);
break;
case Model.ButtonShape.EllipseRectangle:
n = borderRect.Height / 2f;
borderPath.AddLine(borderRect.X + n, borderRect.Y, borderRect.Right - n, borderRect.Y);
borderPath.AddArc(borderRect.Right - n - n, borderRect.Y, n + n, n + n, 270, 180);
borderPath.AddLine(borderRect.Right - n, borderRect.Bottom, borderRect.X + n, borderRect.Bottom);
borderPath.AddArc(borderRect.X, borderRect.Y, n + n, n + n, 90, 180);
break;
case Model.ButtonShape.Circle:
if (borderRect.Width > borderRect.Height)
borderPath.AddEllipse((borderRect.Width - borderRect.Height) / 2f, borderRect.Y, borderRect.Height, borderRect.Height);
else
borderPath.AddEllipse(borderRect.X, (borderRect.Height - borderRect.Width) / 2f, borderRect.Width, borderRect.Width);
break;
}
}
private void CalcTextLocation()
{
//if (string.IsNullOrEmpty(Text)) return;
//Graphics g = CreateGraphics();
//string[] s = Text.Split(',');
//buttonRect = new RectangleF[s.Length];
//textRect = new RectangleF[s.Length];
//float w = (Width - BorderWidth - BorderWidth) / (float)s.Length;
//float h = Height - BorderWidth - BorderWidth;
//for (int i = 0; i < s.Length; i++)
//{
// buttonRect[i] = new RectangleF(BorderWidth + w * i, BorderWidth, w, h);
// SizeF sf = g.MeasureString(s[i], Font);
// textRect[i] = new RectangleF(0, (h - sf.Height) / 2f, sf.Width, sf.Height);
// switch (TextAlign)
// {
// case HorizontalAlignment.Left:
// textRect[i].X = buttonRect[i].X;
// break;
// case HorizontalAlignment.Center:
// textRect[i].X = buttonRect[i].X + (buttonRect[i].Width - sf.Width) / 2f;
// break;
// case HorizontalAlignment.Right:
// textRect[i].X = buttonRect[i].X + buttonRect[i].Width - sf.Width;
// break;
// }
//}
float h = borderRect.Height - BTN_HEIGHT - BTN_HEIGHT - (_max - _min) * SLIDER_STEP;
if (h < SLIDER_MIN)
{
h = SLIDER_MIN;
trackStep = (borderRect.Height - BTN_HEIGHT - BTN_HEIGHT - SLIDER_MIN) / (_max - _min);
}
else
{
trackStep = SLIDER_STEP;
}
float wh = Math.Min(borderRect.Width, borderRect.Height);
buttonRect[0] = new RectangleF(borderRect.X, borderRect.Y, wh, BTN_HEIGHT);
buttonRect[1] = new RectangleF(borderRect.X, borderRect.Y + BTN_HEIGHT + _value * trackStep, wh, h);
buttonRect[2] = new RectangleF(borderRect.X, borderRect.Bottom - BTN_HEIGHT, wh, BTN_HEIGHT);
Graphics g = CreateGraphics();
SizeF sf = g.MeasureString("▲", Font);
textRect[0] = new RectangleF(buttonRect[0].X + (buttonRect[0].Width - sf.Width) / 2f, buttonRect[0].Y + (buttonRect[0].Height - sf.Height) / 2f, sf.Width, sf.Height);
sf = g.MeasureString("▼", Font);
textRect[2] = new RectangleF(buttonRect[2].X + (buttonRect[2].Width - sf.Width) / 2f, buttonRect[2].Y + (buttonRect[2].Height - sf.Height) / 2f, sf.Width, sf.Height);
}
private void FaceButton_MouseDown(object sender, MouseEventArgs e)
{
if (!Enabled) return;
if (e.Button == MouseButtons.Left)
{
buttonDownIndex = buttonOverIndex;
_oldY = e.Y;
if (buttonDownIndex == 0)
Value--;
else if (buttonDownIndex == 2)
Value++;
Refresh();
}
}
private void FaceButton_MouseUp(object sender, MouseEventArgs e)
{
if (!Enabled) return;
if (e.Button == MouseButtons.Left)
{
buttonDownIndex = -1;
Refresh();
//CheckedChanged?.Invoke(this, new EventArgs());
}
}
private void FaceButton_MouseMove(object sender, MouseEventArgs e)
{
buttonOverIndex = -1;
for (int i = 0; i < buttonRect.Length; i++)
{
if (buttonRect[i].Contains(e.Location))
{
buttonOverIndex = i;
break;
}
}
borderOver = false;
if (borderPath.IsVisible(e.Location))
borderOver = true;
if (buttonDownIndex == 1)
{
if (trackStep != 0)
{
int n = Convert.ToInt32((e.Y - _oldY) / trackStep);
_oldY += Convert.ToInt32(n * trackStep);
Value += n;
}
}
Refresh();
}
}
}
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
</root>
\ No newline at end of file \ No newline at end of file

namespace FaceControl
{
partial class FaceText
{
/// <summary>
/// 必需的设计器变量。
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// 清理所有正在使用的资源。
/// </summary>
/// <param name="disposing">如果应释放托管资源,为 true;否则为 false。</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region 组件设计器生成的代码
/// <summary>
/// 设计器支持所需的方法 - 不要修改
/// 使用代码编辑器修改此方法的内容。
/// </summary>
private void InitializeComponent()
{
this.SuspendLayout();
//
// FaceText
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.Name = "FaceText";
this.Size = new System.Drawing.Size(130, 45);
this.MouseDown += new System.Windows.Forms.MouseEventHandler(this.FaceText_MouseDown);
this.MouseMove += new System.Windows.Forms.MouseEventHandler(this.FaceText_MouseMove);
this.MouseUp += new System.Windows.Forms.MouseEventHandler(this.FaceText_MouseUp);
this.Resize += new System.EventHandler(this.FaceText_Resize);
this.ResumeLayout(false);
}
#endregion
}
}
using System;
using System.ComponentModel;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Windows.Forms;
namespace FaceControl
{
[DefaultProperty("Text")]
[DefaultEvent("TextChanged")]
public partial class FaceText : ControlBase
{
private TextBox txt;
private bool mouseDown = false;
private bool buttonOver = false;
private bool borderOver = false;
private GraphicsPath borderPath = new GraphicsPath();
private RectangleF buttonRect = new RectangleF();
private RectangleF textRect = new RectangleF();
private const int BTN_WIDTH = 30;
private const string BTN_TEXT = "×";
public FaceText()
{
InitializeComponent();
this.GotFocus += FaceText_GotFocus;
txt = new TextBox
{
BorderStyle = BorderStyle.None,
BackColor = BackColor,
ForeColor = ForeColor
};
txt.TextChanged += Txt_TextChanged;
txt.MouseEnter += Txt_MouseEnter;
txt.MouseLeave += Txt_MouseLeave;
txt.LostFocus += Txt_LostFocus;
txt.KeyPress += Txt_KeyPress;
Controls.Add(txt);
FaceText_Resize(null, EventArgs.Empty);
}
#region 事件
[Browsable(true), Category("属性已更改"), Description("在控件上更改Text属性的值时引发的事件")]
public new event EventHandler TextChanged;
[Browsable(true), Category("键"), Description("用户按下并释放某个键后发生")]
public new event KeyPressEventHandler KeyPress;
[Browsable(true), Category("键"), Description("用户按下并释放Enter键后发生")]
public event EventHandler KeyEnterPress;
#endregion
#region 属性
[Browsable(false), Category(""), Description("选中的文本起始位置")]
public int SelectionStart { set => txt.SelectionStart = value; get => txt.SelectionStart; }
[Browsable(false), Category(""), Description("选中的文本长度")]
public int SelectionLength { set => txt.SelectionLength = value; get => txt.SelectionLength; }
[Browsable(false), Category(""), Description("选中的文本")]
public string SelectedText { set => txt.SelectedText = value; get => txt.SelectedText; }
[Browsable(true), Category("行为"), Description("控件中输入的最大字符数")]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
public int MaxLength { set => txt.MaxLength = value; get => txt.MaxLength; }
[Browsable(true), Category("行为"), Description("控制能否更改编辑控件中的文本"), DefaultValue(false)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
public bool ReadOnly { set => txt.ReadOnly = value; get => txt.ReadOnly; }
[Browsable(true), Category("外观"), Description("指示应该如何对齐编辑控件的文本"), DefaultValue(HorizontalAlignment.Left)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
public new HorizontalAlignment TextAlign { set => TextAlign = value; get => txt.TextAlign; }
[Browsable(true), Category("外观"), Description("用于显示控件中文本的字体")]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
public override Font Font
{
get => base.Font;
set
{
base.Font = value;
FaceText_Resize(null, EventArgs.Empty);
}
}
[Browsable(true), Category("外观"), Description("与控件关联的文本")]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
public override string Text
{
get => txt.Text;
set
{
txt.Text = value;
}
}
#endregion
public void AddText(string s)
{
txt.SelectedText = s;
}
protected override void CalcSize()
{
base.CalcSize();
CalcTextLocation();
CalcShape();
}
protected override void DrawEnabled(Graphics g)
{
base.DrawEnabled(g);
//控件边框
if (CursorInside && borderOver)
{
if (mouseDown)
g.FillRectangle(new SolidBrush(theme.DOWN_COLOR), buttonRect); //按下
else if (buttonOver)
g.FillRectangle(new SolidBrush(theme.OVER_COLOR), buttonRect); //经过
if (BorderWidth > 0)
g.DrawPath(borderInsidePen, borderPath);
}
else
{
g.FillPath(new SolidBrush(BackColor), borderPath);
if (BorderWidth > 0)
g.DrawPath(borderOutsidePen, borderPath);
}
g.DrawString(BTN_TEXT, new Font("宋体", Font.Size), new SolidBrush(ForeColor), textRect);
}
protected override void DrawDisabled(Graphics g)
{
base.DrawDisabled(g);
//控件边框
if (BorderWidth > 0)
g.DrawPath(borderOutsidePen, borderPath);
g.DrawString(BTN_TEXT, new Font("宋体", Font.Size), new SolidBrush(theme.LOST_FOCUS_COLOR), textRect);
}
private void CalcShape()
{
borderPath = new GraphicsPath();
float n;
switch (FaceShape)
{
case Model.ButtonShape.Rectangle:
borderPath.AddRectangle(borderRect);
break;
case Model.ButtonShape.RoundRectangle:
n = borderRect.Height / 8f;
borderPath.AddLine(borderRect.X + n, borderRect.Y, borderRect.Right - n, borderRect.Y);
borderPath.AddArc(borderRect.Right - n - n, borderRect.Y, n + n, n + n, 270, 90);
borderPath.AddLine(borderRect.Right, borderRect.Y + n, borderRect.Right, borderRect.Bottom - n);
borderPath.AddArc(borderRect.Right - n - n, borderRect.Bottom - n - n, n + n, n + n, 0, 90);
borderPath.AddLine(borderRect.Right - n, borderRect.Bottom, borderRect.X + n, borderRect.Bottom);
borderPath.AddArc(borderRect.X, borderRect.Bottom - n - n, n + n, n + n, 90, 90);
borderPath.AddLine(borderRect.X, borderRect.Bottom - n, borderRect.X, borderRect.Y + n);
borderPath.AddArc(borderRect.X, borderRect.Y, n + n, n + n, 180, 90);
break;
case Model.ButtonShape.Ellipse:
borderPath.AddEllipse(borderRect);
break;
case Model.ButtonShape.EllipseRectangle:
n = borderRect.Height / 2f;
borderPath.AddLine(borderRect.X + n, borderRect.Y, borderRect.Right - n, borderRect.Y);
borderPath.AddArc(borderRect.Right - n - n, borderRect.Y, n + n, n + n, 270, 180);
borderPath.AddLine(borderRect.Right - n, borderRect.Bottom, borderRect.X + n, borderRect.Bottom);
borderPath.AddArc(borderRect.X, borderRect.Y, n + n, n + n, 90, 180);
break;
case Model.ButtonShape.Circle:
if (borderRect.Width > borderRect.Height)
borderPath.AddEllipse((borderRect.Width - borderRect.Height) / 2f, borderRect.Y, borderRect.Height, borderRect.Height);
else
borderPath.AddEllipse(borderRect.X, (borderRect.Height - borderRect.Width) / 2f, borderRect.Width, borderRect.Width);
break;
}
}
private void CalcTextLocation()
{
buttonRect = new RectangleF(borderRect.Right - BTN_WIDTH, borderRect.Y, BTN_WIDTH, borderRect.Height);
Graphics g = CreateGraphics();
SizeF sf = g.MeasureString(BTN_TEXT, new Font("宋体", Font.Size));
textRect = new RectangleF(buttonRect.X + (buttonRect.Width - sf.Width) / 2f, buttonRect.Y + (buttonRect.Height - sf.Height) / 2f, sf.Width, sf.Height);
}
private void Txt_TextChanged(object sender, EventArgs e)
{
TextChanged?.Invoke(this, new EventArgs());
}
private void Txt_MouseLeave(object sender, EventArgs e)
{
CursorInside = false;
borderOver = false;
Refresh();
}
private void Txt_MouseEnter(object sender, EventArgs e)
{
CursorInside = true;
borderOver = true;
Refresh();
}
private void Txt_LostFocus(object sender, EventArgs e)
{
InvokeLostFocus(this, new EventArgs());
}
private void Txt_KeyPress(object sender, KeyPressEventArgs e)
{
if (e.KeyChar == '\r')
KeyEnterPress?.Invoke(this, e);
else if (e.KeyChar == '\n')
{ }
else
KeyPress?.Invoke(this, e);
}
private void FaceText_GotFocus(object sender, EventArgs e)
{
txt.Focus();
}
private void FaceText_MouseDown(object sender, MouseEventArgs e)
{
if (!Enabled) return;
if (buttonOver && e.Button == MouseButtons.Left)
{
mouseDown = true;
Refresh();
}
}
private void FaceText_MouseMove(object sender, MouseEventArgs e)
{
buttonOver = false;
if (buttonRect.Contains(e.Location))
buttonOver = true;
borderOver = borderPath.IsVisible(e.Location);
Refresh();
}
private void FaceText_MouseUp(object sender, MouseEventArgs e)
{
if (!Enabled) return;
if (e.Button == MouseButtons.Left)
{
if (mouseDown)
{
txt.Clear();
mouseDown = false;
}
Refresh();
}
}
private void FaceText_Resize(object sender, EventArgs e)
{
txt.Left = BorderWidth + 3;
txt.Width = Width - BorderWidth - BorderWidth - BTN_WIDTH - 3 - 3;
txt.Top = BorderWidth + (Height - BorderWidth - BorderWidth - txt.Height) / 2;
}
}
}
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
</root>
\ No newline at end of file \ No newline at end of file

namespace FaceControl
{
partial class FaceTrackBar
{
/// <summary>
/// 必需的设计器变量。
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// 清理所有正在使用的资源。
/// </summary>
/// <param name="disposing">如果应释放托管资源,为 true;否则为 false。</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region 组件设计器生成的代码
/// <summary>
/// 设计器支持所需的方法 - 不要修改
/// 使用代码编辑器修改此方法的内容。
/// </summary>
private void InitializeComponent()
{
this.SuspendLayout();
//
// FaceTrackBar
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.Name = "FaceTrackBar";
this.Size = new System.Drawing.Size(216, 33);
this.MouseDown += new System.Windows.Forms.MouseEventHandler(this.FaceTrackBar_MouseDown);
this.MouseMove += new System.Windows.Forms.MouseEventHandler(this.FaceTrackBar_MouseMove);
this.MouseUp += new System.Windows.Forms.MouseEventHandler(this.FaceTrackBar_MouseUp);
this.ResumeLayout(false);
}
#endregion
}
}
using System;
using System.ComponentModel;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Windows.Forms;
namespace FaceControl
{
[DefaultProperty("Value")]
[DefaultEvent("Scroll")]
public partial class FaceTrackBar : ControlBase
{
private bool mouseDown = false;
private bool buttonOver = false;
private float trackStep = 0;
private GraphicsPath borderPath = new GraphicsPath();
private GraphicsPath slidePath = new GraphicsPath();
private RectangleF trackActual = new RectangleF();
private int _trackHeight = 14;
private int _min = 0;
private int _max = 100;
private int _value = 0;
private const int SLIDE_WIDTH = 14;
public FaceTrackBar()
{
InitializeComponent();
}
#region 事件
[Browsable(true), Category("行为"), Description("移动滑块时发生")]
public new event EventHandler Scroll;
#endregion
#region 属性
[Browsable(true), Category("外观"), Description("控件的轨道高度"), DefaultValue(14)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
public int TrackHeight
{
get => _trackHeight;
set
{
_trackHeight = value;
CalcSize();
Refresh();
}
}
[Browsable(true), Category("行为"), Description("滑块位置的最小值"), DefaultValue(0)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
public int Minimum
{
get => _min;
set
{
_min = value;
if (_value < _min) _value = _min;
CalcSize();
Refresh();
}
}
[Browsable(true), Category("行为"), Description("滑块位置的最大值"), DefaultValue(100)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
public int Maximum
{
get => _max;
set
{
_max = value;
if (_value > _max) _value = _max;
CalcSize();
Refresh();
}
}
[Browsable(true), Category("行为"), Description("滑块的位置"), DefaultValue(0)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
public int Value
{
get => _value;
set
{
if (_value == value) return;
_value = value;
if (_value < _min)
_value = _min;
else if (_value > _max)
_value = _max;
CalcSize();
Refresh();
Scroll?.Invoke(this, new EventArgs());
}
}
#endregion
protected override void CalcSize()
{
base.CalcSize();
CalcShape();
CalcSlideLocation();
}
protected override void DrawEnabled(Graphics g)
{
base.DrawEnabled(g);
//填充当前的值
Region reg = new Region(borderPath);
reg.Intersect(trackActual);
g.FillRegion(new SolidBrush(theme.DOWN_COLOR), reg);
//控件边框
if (CursorInside && buttonOver)
{
//if (mouseDown)
// g.FillPath(new SolidBrush(theme.DOWN_COLOR), borderPath); //按下
//else
// g.FillPath(new SolidBrush(theme.OVER_COLOR), borderPath); //经过
if (BorderWidth > 0)
g.DrawPath(borderInsidePen, borderPath);
//滑块
if (mouseDown)
{
g.FillPath(new SolidBrush(theme.DOWN_COLOR), slidePath);
}
else
{
g.FillPath(new SolidBrush(theme.OVER_COLOR), slidePath);
g.DrawPath(new Pen(theme.DOWN_COLOR, 2), slidePath);
}
}
else
{
if (BorderWidth > 0)
g.DrawPath(borderOutsidePen, borderPath);
//滑块
g.FillPath(new SolidBrush(theme.BACK_COLOR), slidePath);
g.DrawPath(new Pen(theme.DOWN_COLOR, 2), slidePath);
}
}
protected override void DrawDisabled(Graphics g)
{
base.DrawDisabled(g);
//控件边框
if (BorderWidth > 0)
g.DrawPath(borderOutsidePen, borderPath);
g.FillPath(new SolidBrush(theme.LOST_FOCUS_COLOR), slidePath);
}
private void CalcShape()
{
borderRect.X += SLIDE_WIDTH / 2f;
borderRect.Y = (borderRect.Height - _trackHeight) / 2f;
borderRect.Width -= SLIDE_WIDTH;
borderRect.Height = _trackHeight;
borderPath = new GraphicsPath();
float n;
switch (FaceShape)
{
case Model.ButtonShape.Rectangle:
borderPath.AddRectangle(borderRect);
break;
case Model.ButtonShape.RoundRectangle:
n = borderRect.Height / 8f;
borderPath.AddLine(borderRect.X + n, borderRect.Y, borderRect.Right - n, borderRect.Y);
borderPath.AddArc(borderRect.Right - n - n, borderRect.Y, n + n, n + n, 270, 90);
borderPath.AddLine(borderRect.Right, borderRect.Y + n, borderRect.Right, borderRect.Bottom - n);
borderPath.AddArc(borderRect.Right - n - n, borderRect.Bottom - n - n, n + n, n + n, 0, 90);
borderPath.AddLine(borderRect.Right - n, borderRect.Bottom, borderRect.X + n, borderRect.Bottom);
borderPath.AddArc(borderRect.X, borderRect.Bottom - n - n, n + n, n + n, 90, 90);
borderPath.AddLine(borderRect.X, borderRect.Bottom - n, borderRect.X, borderRect.Y + n);
borderPath.AddArc(borderRect.X, borderRect.Y, n + n, n + n, 180, 90);
break;
case Model.ButtonShape.Ellipse:
borderPath.AddEllipse(borderRect);
break;
case Model.ButtonShape.EllipseRectangle:
n = borderRect.Height / 2f;
borderPath.AddLine(borderRect.X + n, borderRect.Y, borderRect.Right - n, borderRect.Y);
borderPath.AddArc(borderRect.Right - n - n, borderRect.Y, n + n, n + n, 270, 180);
borderPath.AddLine(borderRect.Right - n, borderRect.Bottom, borderRect.X + n, borderRect.Bottom);
borderPath.AddArc(borderRect.X, borderRect.Y, n + n, n + n, 90, 180);
break;
case Model.ButtonShape.Circle:
if (borderRect.Width > borderRect.Height)
borderPath.AddEllipse((borderRect.Width - borderRect.Height) / 2f, borderRect.Y, borderRect.Height, borderRect.Height);
else
borderPath.AddEllipse(borderRect.X, (borderRect.Height - borderRect.Width) / 2f, borderRect.Width, borderRect.Width);
break;
}
}
private void CalcSlideLocation()
{
trackStep = borderRect.Width / (_max - _min);
float curr = (_value - _min) * trackStep;
trackActual = new RectangleF(borderRect.X, borderRect.Y, curr, borderRect.Height);
slidePath = new GraphicsPath();
float half = SLIDE_WIDTH / 2f;
RectangleF rect = new RectangleF(borderRect.X + curr - half, borderRect.Y - half, SLIDE_WIDTH, SLIDE_WIDTH);
slidePath.AddArc(rect, 180, 180);
slidePath.AddLine(borderRect.X + curr + half, borderRect.Y, borderRect.X + curr + half, borderRect.Bottom);
rect = new RectangleF(borderRect.X + curr - half, borderRect.Bottom - half, SLIDE_WIDTH, SLIDE_WIDTH);
slidePath.AddArc(rect, 0, 180);
slidePath.AddLine(borderRect.X + curr - half, borderRect.Bottom, borderRect.X + curr - half, borderRect.Y);
}
private void FaceTrackBar_MouseDown(object sender, MouseEventArgs e)
{
if (!Enabled) return;
if (e.Button == MouseButtons.Left)
{
if (slidePath.IsVisible(e.Location))
{
mouseDown = true;
Refresh();
}
}
}
private void FaceTrackBar_MouseUp(object sender, MouseEventArgs e)
{
if (!Enabled) return;
if (e.Button == MouseButtons.Left)
{
mouseDown = false;
Refresh();
//Click?.Invoke(this, new EventArgs());
}
}
private void FaceTrackBar_MouseMove(object sender, MouseEventArgs e)
{
if (!Enabled) return;
buttonOver = borderPath.IsVisible(e.Location) || slidePath.IsVisible(e.Location);
if (mouseDown)
{
float val = (e.X - borderRect.X) / trackStep;
Value = (int)val;
}
Refresh();
}
}
}
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
</root>
\ No newline at end of file \ No newline at end of file

namespace FaceControl
{
partial class ProgressStep
{
/// <summary>
/// 必需的设计器变量。
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// 清理所有正在使用的资源。
/// </summary>
/// <param name="disposing">如果应释放托管资源,为 true;否则为 false。</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region 组件设计器生成的代码
/// <summary>
/// 设计器支持所需的方法 - 不要修改
/// 使用代码编辑器修改此方法的内容。
/// </summary>
private void InitializeComponent()
{
this.SuspendLayout();
//
// ProgressStep
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.Name = "ProgressStep";
this.Size = new System.Drawing.Size(164, 31);
this.MouseMove += new System.Windows.Forms.MouseEventHandler(this.ProgressStep_MouseMove);
this.ResumeLayout(false);
}
#endregion
}
}
using System;
using System.ComponentModel;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Windows.Forms;
namespace FaceControl
{
[DefaultProperty("Value")]
public partial class ProgressStep : ControlBase
{
private bool buttonOver = false;
private RectangleF[] stepTextRect;
private RectangleF[] textRect;
private GraphicsPath borderPath = new GraphicsPath();
private Region regMax;
private Region regValue;
private int _max = 10;
private int _value = 0;
private int _stepSize = 30;
private const float SPACE = 12;
//private readonly Font STEP_FONT = new Font("宋体", 10f);
public ProgressStep()
{
InitializeComponent();
}
#region 属性
[Browsable(true), Category("外观"), Description("控件上步骤节点的宽度"), DefaultValue(18)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
public int StepWidth
{
get => _stepSize;
set
{
_stepSize = value;
CalcSize();
Refresh();
}
}
[Browsable(true), Category("行为"), Description("滑块位置的最大值"), DefaultValue(10)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
public int Maximum
{
get => _max;
set
{
_max = value;
if (_value > _max) _value = _max;
CalcSize();
Refresh();
}
}
[Browsable(true), Category("行为"), Description("滑块的位置"), DefaultValue(0)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
public int Value
{
get => _value;
set
{
if (_value == value) return;
_value = value;
if (_value > _max)
_value = _max;
CalcSize();
Refresh();
//Scroll?.Invoke(this, new ScrollEventArgs(ScrollEventType.EndScroll, _value));
}
}
#endregion
protected override void CalcSize()
{
base.CalcSize();
CalcTextLocation();
CalcShape();
}
protected override void DrawEnabled(Graphics g)
{
base.DrawEnabled(g);
//g.FillPath(new SolidBrush(theme.OVER_COLOR), borderPath);
g.FillRegion(new SolidBrush(theme.OVER_COLOR), regMax);
g.FillRegion(new SolidBrush(theme.DOWN_COLOR), regValue);
//控件边框
if (CursorInside && buttonOver)
{
//if (mouseDown)
// g.FillPath(new SolidBrush(theme.DOWN_COLOR), borderPath); //按下
//else
// g.FillPath(new SolidBrush(theme.OVER_COLOR), borderPath); //经过
if (BorderWidth > 0)
g.DrawPath(borderInsidePen, borderPath);
}
else
{
//g.FillPath(new SolidBrush(BackColor), borderPath);
if (BorderWidth > 0)
g.DrawPath(borderOutsidePen, borderPath);
}
for (int i = 0; i < stepTextRect.Length; i++)
{
g.DrawString((i + 1).ToString(), new Font("宋体", Font.Size), new SolidBrush(ForeColor), stepTextRect[i]);
}
string[] s = Text.Split(',');
for (int i = 0; i < textRect.Length; i++)
{
g.DrawString(s[i], Font, new SolidBrush(ForeColor), textRect[i]);
}
}
protected override void DrawDisabled(Graphics g)
{
base.DrawDisabled(g);
//控件边框
if (BorderWidth > 0)
g.DrawPath(borderOutsidePen, borderPath);
}
private void CalcShape()
{
borderPath = new GraphicsPath();
float n;
borderPath.AddRectangle(borderRect);
//switch (FaceShape)
//{
// case Model.ButtonShape.Rectangle:
// borderPath.AddRectangle(borderRect);
// break;
// case Model.ButtonShape.RoundRectangle:
// n = borderRect.Height / 8f;
// borderPath.AddLine(borderRect.X + n, borderRect.Y, borderRect.Right - n, borderRect.Y);
// borderPath.AddArc(borderRect.Right - n - n, borderRect.Y, n + n, n + n, 270, 90);
// borderPath.AddLine(borderRect.Right, borderRect.Y + n, borderRect.Right, borderRect.Bottom - n);
// borderPath.AddArc(borderRect.Right - n - n, borderRect.Bottom - n - n, n + n, n + n, 0, 90);
// borderPath.AddLine(borderRect.Right - n, borderRect.Bottom, borderRect.X + n, borderRect.Bottom);
// borderPath.AddArc(borderRect.X, borderRect.Bottom - n - n, n + n, n + n, 90, 90);
// borderPath.AddLine(borderRect.X, borderRect.Bottom - n, borderRect.X, borderRect.Y + n);
// borderPath.AddArc(borderRect.X, borderRect.Y, n + n, n + n, 180, 90);
// break;
// case Model.ButtonShape.Ellipse:
// borderPath.AddEllipse(borderRect);
// break;
// case Model.ButtonShape.EllipseRectangle:
// n = borderRect.Height / 2f;
// borderPath.AddLine(borderRect.X + n, borderRect.Y, borderRect.Right - n, borderRect.Y);
// borderPath.AddArc(borderRect.Right - n - n, borderRect.Y, n + n, n + n, 270, 180);
// borderPath.AddLine(borderRect.Right - n, borderRect.Bottom, borderRect.X + n, borderRect.Bottom);
// borderPath.AddArc(borderRect.X, borderRect.Y, n + n, n + n, 90, 180);
// break;
// case Model.ButtonShape.Circle:
// if (borderRect.Width > borderRect.Height)
// borderPath.AddEllipse((borderRect.Width - borderRect.Height) / 2f, borderRect.Y, borderRect.Height, borderRect.Height);
// else
// borderPath.AddEllipse(borderRect.X, (borderRect.Height - borderRect.Width) / 2f, borderRect.Width, borderRect.Width);
// break;
//}
}
private GraphicsPath CalcStep(PointF pt)
{
GraphicsPath path = new GraphicsPath();
RectangleF rect = new RectangleF(pt.X - _stepSize / 2f, pt.Y - _stepSize / 2f, _stepSize, _stepSize);
float n;
switch (FaceShape)
{
case Model.ButtonShape.Rectangle:
path.AddRectangle(rect);
break;
case Model.ButtonShape.RoundRectangle:
n = 3f;
path.AddLine(rect.X + n, rect.Y, rect.Right - n, rect.Y);
path.AddArc(rect.Right - n - n, rect.Y, n + n, n + n, 270, 90);
path.AddLine(rect.Right + 1, rect.Y + n, rect.Right + 1, rect.Bottom - n);
path.AddArc(rect.Right - n - n, rect.Bottom - n - n, n + n, n + n, 0, 90);
path.AddLine(rect.Right - n, rect.Bottom + 1, rect.X + n, rect.Bottom + 1);
path.AddArc(rect.X, rect.Bottom - n - n, n + n, n + n, 90, 90);
path.AddLine(rect.X, rect.Bottom - n, rect.X, rect.Y + n);
path.AddArc(rect.X, rect.Y, n + n, n + n, 180, 90);
break;
case Model.ButtonShape.Ellipse:
path.AddEllipse(rect);
break;
case Model.ButtonShape.EllipseRectangle:
n = rect.Height / 2f;
path.AddLine(rect.X + n, rect.Y, rect.Right - n, rect.Y);
path.AddArc(rect.Right - n - n, rect.Y, n + n, n + n, 270, 180);
path.AddLine(rect.Right - n, rect.Bottom, rect.X + n, rect.Bottom);
path.AddArc(rect.X, rect.Y, n + n, n + n, 90, 180);
break;
case Model.ButtonShape.Circle:
path.AddEllipse(rect.X, rect.Y, rect.Width, rect.Width);
break;
}
return path;
}
private RectangleF CalcStep(PointF pt1, PointF pt2)
{
float height = _stepSize / 2f;
RectangleF rect = new RectangleF(pt1.X, pt1.Y - height / 2f, pt2.X - pt1.X, height);
return rect;
}
private void CalcTextLocation()
{
regMax = new Region();
regMax.MakeEmpty();
regValue = new Region();
regValue.MakeEmpty();
float one = (Width - SPACE - SPACE - _stepSize) / (_max - 1);
PointF[] stepPoint = new PointF[_max];
for (int i = 0; i < stepPoint.Length; i++)
stepPoint[i] = new PointF(SPACE + _stepSize / 2f + one * i, SPACE + _stepSize / 2f);
for (int i = 0; i < _max; i++)
{
if (i < _value)
regValue.Union(CalcStep(stepPoint[i]));
else
regMax.Union(CalcStep(stepPoint[i]));
}
for (int i = 0; i < _max - 1; i++)
{
if (i < _value - 1)
regValue.Union(CalcStep(stepPoint[i], stepPoint[i + 1]));
else
regMax.Union(CalcStep(stepPoint[i], stepPoint[i + 1]));
}
Graphics g = CreateGraphics();
stepTextRect = new RectangleF[_max];
for (int i = 0; i < _max; i++)
{
SizeF sf = g.MeasureString((i + 1).ToString(), new Font("宋体", Font.Size));
stepTextRect[i] = new RectangleF(stepPoint[i].X - sf.Width / 2f, stepPoint[i].Y - sf.Height / 2f, sf.Width, sf.Height);
}
string[] s = Text.Split(',');
textRect = new RectangleF[Math.Min(_max, s.Length)];
for (int i = 0; i < textRect.Length; i++)
{
SizeF sf = g.MeasureString(s[i], Font);
float x = stepPoint[i].X - sf.Width / 2f;
if (x < BorderWidth)
x = BorderWidth;
else if (x + sf.Width > Width - BorderWidth)
x = Width - BorderWidth - sf.Width;
textRect[i] = new RectangleF(x, stepPoint[i].Y + _stepSize / 2f + sf.Height / 2f, sf.Width, sf.Height);
}
}
private void ProgressStep_MouseMove(object sender, MouseEventArgs e)
{
buttonOver = borderPath.IsVisible(e.Location);
Refresh();
}
}
}
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
</root>
\ No newline at end of file \ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{06F6C6E6-02F6-4134-945A-BE51BEEF58A4}</ProjectGuid>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>FaceControl</RootNamespace>
<AssemblyName>FaceControl</AssemblyName>
<TargetFrameworkVersion>v4.6</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<Deterministic>true</Deterministic>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup>
<LangVersion>preview</LangVersion>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Drawing" />
<Reference Include="System.Windows.Forms" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Data" />
<Reference Include="System.Net.Http" />
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="API.cs" />
<Compile Include="Base\ControlBase.cs">
<SubType>UserControl</SubType>
</Compile>
<Compile Include="Base\ControlBase.Designer.cs">
<DependentUpon>ControlBase.cs</DependentUpon>
</Compile>
<Compile Include="Control\FaceButtonGroup.cs">
<SubType>UserControl</SubType>
</Compile>
<Compile Include="Control\FaceButtonGroup.Designer.cs">
<DependentUpon>FaceButtonGroup.cs</DependentUpon>
</Compile>
<Compile Include="Control\FaceRadio.cs">
<SubType>UserControl</SubType>
</Compile>
<Compile Include="Control\FaceRadio.Designer.cs">
<DependentUpon>FaceRadio.cs</DependentUpon>
</Compile>
<Compile Include="Control\FaceCheck.cs">
<SubType>UserControl</SubType>
</Compile>
<Compile Include="Control\FaceCheck.Designer.cs">
<DependentUpon>FaceCheck.cs</DependentUpon>
</Compile>
<Compile Include="Control\FaceTrackBar.cs">
<SubType>UserControl</SubType>
</Compile>
<Compile Include="Control\FaceTrackBar.Designer.cs">
<DependentUpon>FaceTrackBar.cs</DependentUpon>
</Compile>
<Compile Include="Control\FaceLabel.cs">
<SubType>UserControl</SubType>
</Compile>
<Compile Include="Control\FaceLabel.Designer.cs">
<DependentUpon>FaceLabel.cs</DependentUpon>
</Compile>
<Compile Include="Control\FacePanel.cs">
<SubType>Component</SubType>
</Compile>
<Compile Include="Control\FacePanel.Designer.cs">
<DependentUpon>FacePanel.cs</DependentUpon>
</Compile>
<Compile Include="Control\FaceCheckGroup.cs">
<SubType>UserControl</SubType>
</Compile>
<Compile Include="Control\FaceCheckGroup.Designer.cs">
<DependentUpon>FaceCheckGroup.cs</DependentUpon>
</Compile>
<Compile Include="Control\FaceList.cs">
<SubType>UserControl</SubType>
</Compile>
<Compile Include="Control\FaceList.Designer.cs">
<DependentUpon>FaceList.cs</DependentUpon>
</Compile>
<Compile Include="Control\FaceCombo.cs">
<SubType>UserControl</SubType>
</Compile>
<Compile Include="Control\FaceCombo.Designer.cs">
<DependentUpon>FaceCombo.cs</DependentUpon>
</Compile>
<Compile Include="Control\FaceNumeric.cs">
<SubType>UserControl</SubType>
</Compile>
<Compile Include="Control\FaceNumeric.Designer.cs">
<DependentUpon>FaceNumeric.cs</DependentUpon>
</Compile>
<Compile Include="Control\FaceImageShow.cs">
<SubType>UserControl</SubType>
</Compile>
<Compile Include="Control\FaceImageShow.Designer.cs">
<DependentUpon>FaceImageShow.cs</DependentUpon>
</Compile>
<Compile Include="FaceDateTime.cs">
<SubType>UserControl</SubType>
</Compile>
<Compile Include="FaceDateTime.Designer.cs">
<DependentUpon>FaceDateTime.cs</DependentUpon>
</Compile>
<Compile Include="Control\FaceLock.cs">
<SubType>UserControl</SubType>
</Compile>
<Compile Include="Control\FaceLock.Designer.cs">
<DependentUpon>FaceLock.cs</DependentUpon>
</Compile>
<Compile Include="FaceNumericKeypad.cs">
<SubType>UserControl</SubType>
</Compile>
<Compile Include="FaceNumericKeypad.Designer.cs">
<DependentUpon>FaceNumericKeypad.cs</DependentUpon>
</Compile>
<Compile Include="Control\FaceRadioGroup.cs">
<SubType>UserControl</SubType>
</Compile>
<Compile Include="Control\FaceRadioGroup.Designer.cs">
<DependentUpon>FaceRadioGroup.cs</DependentUpon>
</Compile>
<Compile Include="Control\FaceScrollBar.cs">
<SubType>UserControl</SubType>
</Compile>
<Compile Include="Control\FaceScrollBar.Designer.cs">
<DependentUpon>FaceScrollBar.cs</DependentUpon>
</Compile>
<Compile Include="Control\FaceText.cs">
<SubType>UserControl</SubType>
</Compile>
<Compile Include="Control\FaceText.Designer.cs">
<DependentUpon>FaceText.cs</DependentUpon>
</Compile>
<Compile Include="Form\FormInput.cs">
<SubType>Form</SubType>
</Compile>
<Compile Include="Form\FormInput.Designer.cs">
<DependentUpon>FormInput.cs</DependentUpon>
</Compile>
<Compile Include="Language.cs" />
<Compile Include="Model.cs" />
<Compile Include="Base\PanelBase.cs">
<SubType>Component</SubType>
</Compile>
<Compile Include="Base\PanelBase.Designer.cs">
<DependentUpon>PanelBase.cs</DependentUpon>
</Compile>
<Compile Include="Control\ProgressStep.cs">
<SubType>UserControl</SubType>
</Compile>
<Compile Include="Control\ProgressStep.Designer.cs">
<DependentUpon>ProgressStep.cs</DependentUpon>
</Compile>
<Compile Include="Shape.cs" />
<Compile Include="Theme\LightTheme.cs" />
<Compile Include="Theme\DarkTheme.cs" />
<Compile Include="Control\FaceButton.cs">
<SubType>UserControl</SubType>
</Compile>
<Compile Include="Control\FaceButton.Designer.cs">
<DependentUpon>FaceButton.cs</DependentUpon>
</Compile>
<Compile Include="Form\FormControlBox.cs">
<SubType>UserControl</SubType>
</Compile>
<Compile Include="Form\FormControlBox.Designer.cs">
<DependentUpon>FormControlBox.cs</DependentUpon>
</Compile>
<Compile Include="Form\FormDialog.cs">
<SubType>Form</SubType>
</Compile>
<Compile Include="Form\FormDialog.Designer.cs">
<DependentUpon>FormDialog.cs</DependentUpon>
</Compile>
<Compile Include="Form\FormFixed.cs">
<SubType>Form</SubType>
</Compile>
<Compile Include="Form\FormFixed.Designer.cs">
<DependentUpon>FormFixed.cs</DependentUpon>
</Compile>
<Compile Include="Form\FormNormal.cs">
<SubType>Form</SubType>
</Compile>
<Compile Include="Form\FormNormal.Designer.cs">
<DependentUpon>FormNormal.cs</DependentUpon>
</Compile>
<Compile Include="Form\FormBase.cs">
<SubType>Form</SubType>
</Compile>
<Compile Include="Form\FormBase.Designer.cs">
<DependentUpon>FormBase.cs</DependentUpon>
</Compile>
<Compile Include="Theme\IFaceTheme.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>
<ItemGroup />
<ItemGroup>
<EmbeddedResource Include="Base\ControlBase.resx">
<DependentUpon>ControlBase.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="Control\FaceButton.resx">
<DependentUpon>FaceButton.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="Control\FaceButtonGroup.resx">
<DependentUpon>FaceButtonGroup.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="Control\FaceRadio.resx">
<DependentUpon>FaceRadio.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="Control\FaceCheck.resx">
<DependentUpon>FaceCheck.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="Control\FaceTrackBar.resx">
<DependentUpon>FaceTrackBar.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="Control\FaceLabel.resx">
<DependentUpon>FaceLabel.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="Control\FaceCheckGroup.resx">
<DependentUpon>FaceCheckGroup.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="Control\FaceList.resx">
<DependentUpon>FaceList.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="Control\FaceCombo.resx">
<DependentUpon>FaceCombo.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="Control\FaceNumeric.resx">
<DependentUpon>FaceNumeric.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="Control\FaceImageShow.resx">
<DependentUpon>FaceImageShow.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="FaceDateTime.resx">
<DependentUpon>FaceDateTime.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="Control\FaceLock.resx">
<DependentUpon>FaceLock.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="FaceNumericKeypad.resx">
<DependentUpon>FaceNumericKeypad.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="Control\FaceRadioGroup.resx">
<DependentUpon>FaceRadioGroup.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="Control\FaceScrollBar.resx">
<DependentUpon>FaceScrollBar.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="Control\FaceText.resx">
<DependentUpon>FaceText.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="Form\FormFixed.resx">
<DependentUpon>FormFixed.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="Form\FormInput.resx">
<DependentUpon>FormInput.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="Form\FormBase.resx">
<DependentUpon>FormBase.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="Form\FormControlBox.resx">
<DependentUpon>FormControlBox.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="Form\FormDialog.resx">
<DependentUpon>FormDialog.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="Form\FormNormal.resx">
<DependentUpon>FormNormal.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="Control\ProgressStep.resx">
<DependentUpon>ProgressStep.cs</DependentUpon>
</EmbeddedResource>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<PropertyGroup>
<PostBuildEvent>if not exist "C:\Neotel\DLL\$(TargetName)" md "C:\Neotel\DLL\$(TargetName)"
copy "$(TargetPath)" "C:\Neotel\DLL\$(TargetName)\$(TargetFileName)"
copy "$(TargetDir)$(TargetName).pdb" "C:\Neotel\DLL\$(TargetName)\$(TargetName).pdb"</PostBuildEvent>
</PropertyGroup>
</Project>
\ No newline at end of file \ No newline at end of file

namespace FaceControl
{
partial class FaceDateTime
{
/// <summary>
/// 必需的设计器变量。
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// 清理所有正在使用的资源。
/// </summary>
/// <param name="disposing">如果应释放托管资源,为 true;否则为 false。</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region 组件设计器生成的代码
/// <summary>
/// 设计器支持所需的方法 - 不要修改
/// 使用代码编辑器修改此方法的内容。
/// </summary>
private void InitializeComponent()
{
this.SuspendLayout();
//
// FaceDateTime
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.Name = "FaceDateTime";
this.MouseDown += new System.Windows.Forms.MouseEventHandler(this.FaceDateTime_MouseDown);
this.MouseMove += new System.Windows.Forms.MouseEventHandler(this.FaceDateTime_MouseMove);
this.MouseUp += new System.Windows.Forms.MouseEventHandler(this.FaceDateTime_MouseUp);
this.ResumeLayout(false);
}
#endregion
}
}
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace FaceControl
{
public partial class FaceDateTime : ControlBase
{
//private bool itemDown = false;
private int itemOverIndex = -1;
private int itemSelected = -1;
private List<GraphicsPath> items = new List<GraphicsPath>();
private List<Size> itemGridSize = new List<Size>();
private RectangleF itemGridRect;
private bool _showYear = true;
private bool _showMonth = true;
private bool _showDay = true;
private bool _showHour = true;
private bool _showMinute = true;
private bool _showSecond = true;
private const int SPACE = 12;
private const int ITEMS_HEIGHT = 45;
private readonly Dictionary<string, Size> GRID_SIZE = new Dictionary<string, Size>
{
{ "Year", new Size(5, 5) },
{ "Month", new Size(4, 3) },
{ "Day", new Size(7, 5) },
{ "Hour", new Size(6, 4) },
{ "Minute", new Size(10, 6) },
{ "Second", new Size(10, 6) }
};
public FaceDateTime()
{
InitializeComponent();
}
#region 属性
[Browsable(true), Category("外观"), Description("是否显示日期的年"), DefaultValue(true)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
public bool ShowYear
{
get => _showYear;
set
{
_showYear = value;
CalcSize();
Refresh();
}
}
[Browsable(true), Category("外观"), Description("是否显示日期的月"), DefaultValue(true)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
public bool ShowMonth
{
get => _showMonth;
set
{
_showMonth = value;
CalcSize();
Refresh();
}
}
[Browsable(true), Category("外观"), Description("是否显示日期的日"), DefaultValue(true)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
public bool ShowDay
{
get => _showDay;
set
{
_showDay = value;
CalcSize();
Refresh();
}
}
[Browsable(true), Category("外观"), Description("是否显示时间的时"), DefaultValue(true)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
public bool ShowHour
{
get => _showHour;
set
{
_showHour = value;
CalcSize();
Refresh();
}
}
[Browsable(true), Category("外观"), Description("是否显示时间的分"), DefaultValue(true)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
public bool ShowMinute
{
get => _showMinute;
set
{
_showMinute = value;
CalcSize();
Refresh();
}
}
[Browsable(true), Category("外观"), Description("是否显示时间的秒"), DefaultValue(true)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
public bool ShowSecond
{
get => _showSecond;
set
{
_showSecond = value;
CalcSize();
Refresh();
}
}
#endregion
protected override void CalcSize()
{
base.CalcSize();
CalcShape();
CalcItemLocation();
CalcItemGridLocation();
}
protected override void DrawEnabled(Graphics g)
{
base.DrawEnabled(g);
if (CursorInside)
{
for (int i = 0; i < items.Count; i++)
{
if (i == itemSelected)
{
g.FillPath(new SolidBrush(theme.DOWN_COLOR), items[itemSelected]);
if (i != itemOverIndex)
g.DrawPath(new Pen(theme.OVER_COLOR, BorderWidth), items[i]);
}
else
{
if (i == itemOverIndex)
{
g.FillPath(new SolidBrush(theme.OVER_COLOR), items[itemOverIndex]);
g.DrawPath(new Pen(theme.DOWN_COLOR, BorderWidth), items[i]);
}
else
{
g.DrawPath(new Pen(theme.OVER_COLOR, BorderWidth), items[i]);
}
}
}
if (BorderWidth > 0)
g.DrawRectangle(borderInsidePen, borderRect.X, borderRect.Y, borderRect.Width, borderRect.Height);
}
else
{
itemOverIndex = -1;
for (int i = 0; i < items.Count; i++)
{
if (i == itemSelected)
g.FillPath(new SolidBrush(theme.DOWN_COLOR), items[itemSelected]);
g.DrawPath(new Pen(theme.OVER_COLOR, BorderWidth), items[i]);
}
if (BorderWidth > 0)
g.DrawRectangle(borderOutsidePen, borderRect.X, borderRect.Y, borderRect.Width, borderRect.Height);
}
g.DrawRectangle(borderInsidePen, itemGridRect.X, itemGridRect.Y, itemGridRect.Width, itemGridRect.Height);
}
protected override void DrawDisabled(Graphics g)
{
base.DrawDisabled(g);
Region reg = new Region(new Rectangle(0, 0, Width, Height));
reg.Exclude(borderRect);
g.FillRegion(new SolidBrush(theme.BACK_COLOR), reg);
//控件边框
if (BorderWidth > 0)
g.DrawRectangle(borderOutsidePen, borderRect.X, borderRect.Y, borderRect.Width, borderRect.Height);
}
private void CalcShape()
{
//borderRect = new GraphicsPath();
//float n;
//switch (FaceShape)
//{
// case Model.ButtonShape.Rectangle:
// borderRect.AddRectangle(base.borderRect);
// break;
// case Model.ButtonShape.RoundRectangle:
// n = base.borderRect.Height / 8f;
// borderRect.AddLine(base.borderRect.X + n, base.borderRect.Y, base.borderRect.Right - n, base.borderRect.Y);
// borderRect.AddArc(base.borderRect.Right - n - n, base.borderRect.Y, n + n, n + n, 270, 90);
// borderRect.AddLine(base.borderRect.Right, base.borderRect.Y + n, base.borderRect.Right, base.borderRect.Bottom - n);
// borderRect.AddArc(base.borderRect.Right - n - n, base.borderRect.Bottom - n - n, n + n, n + n, 0, 90);
// borderRect.AddLine(base.borderRect.Right - n, base.borderRect.Bottom, base.borderRect.X + n, base.borderRect.Bottom);
// borderRect.AddArc(base.borderRect.X, base.borderRect.Bottom - n - n, n + n, n + n, 90, 90);
// borderRect.AddLine(base.borderRect.X, base.borderRect.Bottom - n, base.borderRect.X, base.borderRect.Y + n);
// borderRect.AddArc(base.borderRect.X, base.borderRect.Y, n + n, n + n, 180, 90);
// break;
// case Model.ButtonShape.Ellipse:
// borderRect.AddEllipse(base.borderRect);
// break;
// case Model.ButtonShape.EllipseRectangle:
// n = base.borderRect.Height / 2f;
// borderRect.AddLine(base.borderRect.X + n, base.borderRect.Y, base.borderRect.Right - n, base.borderRect.Y);
// borderRect.AddArc(base.borderRect.Right - n - n, base.borderRect.Y, n + n, n + n, 270, 180);
// borderRect.AddLine(base.borderRect.Right - n, base.borderRect.Bottom, base.borderRect.X + n, base.borderRect.Bottom);
// borderRect.AddArc(base.borderRect.X, base.borderRect.Y, n + n, n + n, 90, 180);
// break;
// case Model.ButtonShape.Circle:
// if (base.borderRect.Width > base.borderRect.Height)
// borderRect.AddEllipse((base.borderRect.Width - base.borderRect.Height) / 2f, base.borderRect.Y, base.borderRect.Height, base.borderRect.Height);
// else
// borderRect.AddEllipse(base.borderRect.X, (base.borderRect.Height - base.borderRect.Width) / 2f, base.borderRect.Width, base.borderRect.Width);
// break;
//}
}
private void CalcItemLocation()
{
int itemCount = 0;
itemGridSize.Clear();
if (_showYear)
{
itemGridSize.Add(GRID_SIZE["Year"]);
itemCount++;
}
if (_showMonth)
{
itemGridSize.Add(GRID_SIZE["Month"]);
itemCount++;
}
if (_showDay)
{
itemGridSize.Add(GRID_SIZE["Day"]);
itemCount++;
}
if (_showHour)
{
itemGridSize.Add(GRID_SIZE["Hour"]);
itemCount++;
}
if (_showMinute)
{
itemGridSize.Add(GRID_SIZE["Minute"]);
itemCount++;
}
if (_showSecond)
{
itemGridSize.Add(GRID_SIZE["Second"]);
itemCount++;
}
float w = (borderRect.Width - SPACE * (itemCount + 1)) / itemCount;
items.Clear();
for (int i = 0; i < itemCount; i++)
{
GraphicsPath path = new GraphicsPath();
path.AddRectangle(new RectangleF(borderRect.X + SPACE + (w + SPACE) * i, borderRect.Y + SPACE, w, ITEMS_HEIGHT));
items.Add(path);
}
itemGridRect = new RectangleF(borderRect.X + SPACE, borderRect.Y + ITEMS_HEIGHT + SPACE * 2, borderRect.Width - SPACE * 2, borderRect.Bottom - SPACE * 3 - ITEMS_HEIGHT);
}
private void CalcItemGridLocation()
{
}
private void FaceDateTime_MouseDown(object sender, MouseEventArgs e)
{
if (!Enabled) return;
if (e.Button == MouseButtons.Left)
{
itemSelected = itemOverIndex;
Refresh();
}
}
private void FaceDateTime_MouseMove(object sender, MouseEventArgs e)
{
itemOverIndex = -1;
for (int i = 0; i < items.Count; i++)
{
if (items[i].IsVisible(e.Location))
{
itemOverIndex = i;
break;
}
}
Refresh();
}
private void FaceDateTime_MouseUp(object sender, MouseEventArgs e)
{
if (!Enabled) return;
if (e.Button == MouseButtons.Left)
{
//itemDown = false;
Refresh();
//Click?.Invoke(this, new EventArgs());
}
}
}
}
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
</root>
\ No newline at end of file \ No newline at end of file

namespace FaceControl
{
partial class FaceNumericKeypad
{
/// <summary>
/// 必需的设计器变量。
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// 清理所有正在使用的资源。
/// </summary>
/// <param name="disposing">如果应释放托管资源,为 true;否则为 false。</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region 组件设计器生成的代码
/// <summary>
/// 设计器支持所需的方法 - 不要修改
/// 使用代码编辑器修改此方法的内容。
/// </summary>
private void InitializeComponent()
{
this.SuspendLayout();
//
// FaceNumericKeypad
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.Name = "FaceNumericKeypad";
this.Size = new System.Drawing.Size(250, 158);
this.MouseDown += new System.Windows.Forms.MouseEventHandler(this.FaceNumericKeypad_MouseDown);
this.MouseMove += new System.Windows.Forms.MouseEventHandler(this.FaceNumericKeypad_MouseMove);
this.MouseUp += new System.Windows.Forms.MouseEventHandler(this.FaceNumericKeypad_MouseUp);
this.ResumeLayout(false);
}
#endregion
}
}
using System;
using System.ComponentModel;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Windows.Forms;
namespace FaceControl
{
public partial class FaceNumericKeypad : ControlBase
{
private bool mouseDown = false;
private int buttonOverIndex = -1;
private RectangleF[] textRect;
private RectangleF[] buttonRect;
private PointF[,] borderLine;
private KeypadText[] keypadText = new KeypadText[]
{
new KeypadText(55, "7"),
new KeypadText(56, "8"),
new KeypadText(57, "9"),
new KeypadText(8, "←"),
new KeypadText(52, "4"),
new KeypadText(53, "5"),
new KeypadText(54, "6"),
new KeypadText(0, "C"),
new KeypadText(49, "1"),
new KeypadText(50, "2"),
new KeypadText(51, "3"),
new KeypadText(13, "↵"),
new KeypadText(48, "0"),
new KeypadText(46, ".")
};
public FaceNumericKeypad()
{
InitializeComponent();
}
public ControlBase TransformControl { set; get; }
protected override void CalcSize()
{
base.CalcSize();
CalcShape();
CalcTextLocation();
}
protected override void DrawEnabled(Graphics g)
{
base.DrawEnabled(g);
Pen pen;
if (CursorInside && buttonOverIndex > -1)
{
pen = new Pen(theme.DOWN_COLOR, BorderWidth);
if (mouseDown)
g.FillRectangle(new SolidBrush(theme.DOWN_COLOR), buttonRect[buttonOverIndex]); //按下
else
g.FillRectangle(new SolidBrush(theme.OVER_COLOR), buttonRect[buttonOverIndex]); //经过
}
else
{
pen = new Pen(theme.OVER_COLOR, BorderWidth);
}
for (int i = 0; i < borderLine.GetLength(0); i++)
{
g.DrawLine(pen, borderLine[i, 0], borderLine[i, 1]);
}
for (int i = 0; i < textRect.Length; i++)
{
g.DrawString(keypadText[i].Text, Font, new SolidBrush(ForeColor), textRect[i]);
}
}
protected override void DrawDisabled(Graphics g)
{
base.DrawDisabled(g);
for (int i = 0; i < borderLine.GetLength(0); i++)
{
g.DrawLine(borderOutsidePen, borderLine[i, 0], borderLine[i, 1]);
}
for (int i = 0; i < textRect.Length; i++)
{
g.DrawString(keypadText[i].Text, Font, new SolidBrush(theme.LOST_FOCUS_COLOR), textRect[i]);
}
}
private void CalcShape()
{
float w = borderRect.Width / 4f;
float h = borderRect.Height / 4f;
borderLine = new PointF[10, 2];
buttonRect = new RectangleF[14];
borderLine[0, 0] = new PointF(borderRect.X, borderRect.Y);
borderLine[0, 1] = new PointF(borderRect.Right, borderRect.Y);
borderLine[1, 0] = new PointF(borderRect.X, borderRect.Y + h);
borderLine[1, 1] = new PointF(borderRect.Right, borderRect.Y + h);
borderLine[2, 0] = new PointF(borderRect.X, borderRect.Y + h * 2);
borderLine[2, 1] = new PointF(borderRect.Right, borderRect.Y + h * 2);
borderLine[3, 0] = new PointF(borderRect.X, borderRect.Y + h * 3);
borderLine[3, 1] = new PointF(borderRect.X + w * 3, borderRect.Y + h * 3);
borderLine[4, 0] = new PointF(borderRect.X, borderRect.Y + h * 4);
borderLine[4, 1] = new PointF(borderRect.Right, borderRect.Y + h * 4);
borderLine[5, 0] = new PointF(borderRect.X, borderRect.Y);
borderLine[5, 1] = new PointF(borderRect.X, borderRect.Bottom);
borderLine[6, 0] = new PointF(borderRect.X + w, borderRect.Y);
borderLine[6, 1] = new PointF(borderRect.X + w, borderRect.Y + h * 3);
borderLine[7, 0] = new PointF(borderRect.X + w * 2, borderRect.Y);
borderLine[7, 1] = new PointF(borderRect.X + w * 2, borderRect.Bottom);
borderLine[8, 0] = new PointF(borderRect.X + w * 3, borderRect.Y);
borderLine[8, 1] = new PointF(borderRect.X + w * 3, borderRect.Bottom);
borderLine[9, 0] = new PointF(borderRect.X + w * 4, borderRect.Y);
borderLine[9, 1] = new PointF(borderRect.X + w * 4, borderRect.Bottom);
buttonRect[0] = new RectangleF(borderRect.X, borderRect.Y, w, h);
buttonRect[1] = new RectangleF(borderRect.X + w, borderRect.Y, w, h);
buttonRect[2] = new RectangleF(borderRect.X + w * 2, borderRect.Y, w, h);
buttonRect[3] = new RectangleF(borderRect.X + w * 3, borderRect.Y, w, h);
buttonRect[4] = new RectangleF(borderRect.X, borderRect.Y + h, w, h);
buttonRect[5] = new RectangleF(borderRect.X + w, borderRect.Y + h, w, h);
buttonRect[6] = new RectangleF(borderRect.X + w * 2, borderRect.Y + h, w, h);
buttonRect[7] = new RectangleF(borderRect.X + w * 3, borderRect.Y + h, w, h);
buttonRect[8] = new RectangleF(borderRect.X, borderRect.Y + h * 2, w, h);
buttonRect[9] = new RectangleF(borderRect.X + w, borderRect.Y + h * 2, w, h);
buttonRect[10] = new RectangleF(borderRect.X + w * 2, borderRect.Y + h * 2, w, h);
buttonRect[11] = new RectangleF(borderRect.X + w * 3, borderRect.Y + h * 2, w, h * 2);
buttonRect[12] = new RectangleF(borderRect.X, borderRect.Y + h * 3, w * 2, h);
buttonRect[13] = new RectangleF(borderRect.X + w * 2, borderRect.Y + h * 3, w, h);
}
private void CalcTextLocation()
{
Graphics g = CreateGraphics();
textRect = new RectangleF[buttonRect.Length];
for (int i = 0; i < textRect.Length; i++)
{
SizeF sf = g.MeasureString(keypadText[i].Text, Font);
textRect[i] = new RectangleF(buttonRect[i].X + (buttonRect[i].Width - sf.Width) / 2f, buttonRect[i].Y + (buttonRect[i].Height - sf.Height) / 2f, sf.Width, sf.Height);
}
}
private void FaceNumericKeypad_MouseDown(object sender, MouseEventArgs e)
{
if (!Enabled) return;
if (e.Button == MouseButtons.Left)
{
mouseDown = true;
Refresh();
}
}
private void FaceNumericKeypad_MouseUp(object sender, MouseEventArgs e)
{
if (!Enabled) return;
if (e.Button == MouseButtons.Left)
{
mouseDown = false;
Refresh();
if (buttonOverIndex == -1) return;
if (TransformControl == null) return;
if (keypadText[buttonOverIndex].Ascii == 0)
{
TransformControl.Text = "";
}
else if (keypadText[buttonOverIndex].Ascii == 8)
{
int len = TransformControl.Text.Length;
if (len == 0) return;
TransformControl.Text = TransformControl.Text.Substring(0, len - 1);
}
else
TransformControl.Text += (char)keypadText[buttonOverIndex].Ascii;
}
}
private void FaceNumericKeypad_MouseMove(object sender, MouseEventArgs e)
{
buttonOverIndex = -1;
for (int i = 0; i < buttonRect.Length; i++)
{
if (buttonRect[i].Contains(e.Location))
{
buttonOverIndex = i;
break;
}
}
Refresh();
}
private struct KeypadText
{
public int Ascii { set; get; }
public string Text { set; get; }
public KeypadText(int ascii, string text)
{
Ascii = ascii;
Text = text;
}
}
}
}
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
</root>
\ No newline at end of file \ No newline at end of file
namespace FaceControl
{
partial class FormBase
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.LblBar = new System.Windows.Forms.Label();
this.SuspendLayout();
//
// LblBar
//
this.LblBar.BackColor = System.Drawing.Color.Red;
this.LblBar.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
this.LblBar.Location = new System.Drawing.Point(12, 9);
this.LblBar.Margin = new System.Windows.Forms.Padding(3);
this.LblBar.Name = "LblBar";
this.LblBar.Size = new System.Drawing.Size(100, 23);
this.LblBar.TabIndex = 0;
//
// FormBase
//
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.None;
this.ClientSize = new System.Drawing.Size(614, 436);
this.ControlBox = false;
this.Controls.Add(this.LblBar);
this.DoubleBuffered = true;
this.Font = new System.Drawing.Font("宋体", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.None;
this.MaximizeBox = false;
this.MinimizeBox = false;
this.Name = "FormBase";
this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen;
this.Text = "FormBase";
this.Activated += new System.EventHandler(this.FormBase_Activated);
this.Deactivate += new System.EventHandler(this.FormBase_Deactivate);
this.Load += new System.EventHandler(this.FormBase_Load);
this.Paint += new System.Windows.Forms.PaintEventHandler(this.FormBase_Paint);
this.MouseDown += new System.Windows.Forms.MouseEventHandler(this.FormBase_MouseDown);
this.MouseMove += new System.Windows.Forms.MouseEventHandler(this.FormBase_MouseMove);
this.MouseUp += new System.Windows.Forms.MouseEventHandler(this.FormBase_MouseUp);
this.Resize += new System.EventHandler(this.FormBase_Resize);
this.ResumeLayout(false);
}
#endregion
private System.Windows.Forms.Label LblBar;
}
}
\ No newline at end of file \ No newline at end of file
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace FaceControl
{
public partial class FormBase : Form
{
private Theme.IFaceTheme _theme;
private int _borderW;
private Bitmap _iconBmp;
private Font _titleFont;
private Color _titleColor;
private int _titleHeight;
private bool _maximize;
private bool _canResize;
private Control controlBox;
private Rectangle titleRect;
private RectangleF titleTextRect;
private Pen borderPen;
private RectangleF borderRect;
private RectangleF iconRect;
private CursorPlace place;
private Point[] sizeTriangle;
private bool activate;
public FormBase()
{
_theme = new Theme.DarkTheme();
_borderW = 2;
_iconBmp = new Bitmap(32, 32);
_titleFont = new Font("宋体", 12f);
_titleColor = _theme.TITLE_COLOR;
_titleHeight = 42;
_maximize = false;
_canResize = true;
place = CursorPlace.None;
InitializeComponent();
CalcSize();
}
#region 属性
[Browsable(false)]
public new AutoScaleMode AutoScaleMode { set => base.AutoScaleMode = value; get => base.AutoScaleMode; }
[Browsable(false)]
public new FormBorderStyle FormBorderStyle { set => base.FormBorderStyle = value; get => base.FormBorderStyle; }
[Browsable(false)]
public override Font Font { get => base.Font; set => base.Font = value; }
[Browsable(true), Category(""), Description("图标")]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
public new Bitmap Icon
{
get => _iconBmp;
set
{
_iconBmp = value;
CalcSize();
Refresh();
}
}
[Browsable(true), Category("Border"), Description("边框宽度"), DefaultValue(2)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
public int BorderWidth
{
get => _borderW;
set
{
if (value < 0)
_borderW = 0;
else
_borderW = value;
CalcSize();
Refresh();
}
}
[Browsable(true), Category("Title"), Description("标题字体")]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
public Font TitleFont
{
get => _titleFont;
set
{
_titleFont = value;
CalcSize();
Refresh();
}
}
[Browsable(true), Category("Title"), Description("标题颜色")]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
public Color TitleColor
{
get => _titleColor;
set
{
_titleColor = value;
Refresh();
}
}
[Browsable(true), Category("Title"), Description("标题栏高度"), DefaultValue(36)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
public int TitleHeight
{
get => _titleHeight;
set
{
_titleHeight = value;
CalcSize();
Refresh();
}
}
[Browsable(true)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
public override string Text
{
get => base.Text;
set
{
base.Text = value;
CalcSize();
Refresh();
}
}
#endregion
internal Theme.IFaceTheme FaceColor
{
get => _theme;
set
{
_theme = value;
Refresh();
}
}
internal bool Maximize
{
get => _maximize;
set
{
_maximize = value;
Refresh();
}
}
internal bool CanResize
{
get => _canResize;
set
{
_canResize = value;
Refresh();
}
}
internal void SetControlBox(Control ctl)
{
controlBox = ctl;
CalcSize();
Refresh();
}
internal void HideDrop(IntPtr ptr)
{
HideDrop(this, ptr);
}
public void ShowTopMost()
{
TopMost = true;
Show(Parent);
activate = true;
}
private void InitControl()
{
if (DesignMode)
{
LblBar.Location = new Point(_borderW, _borderW + _titleHeight - 1);
LblBar.Size = new Size(Width - _borderW * 2, 1);
}
if (controlBox != null)
{
controlBox.Location = new Point(Width - _borderW - controlBox.Width, _borderW);
controlBox.Height = _titleHeight - 2;
}
}
private void CalcSize()
{
InitControl();
borderRect = new RectangleF(_borderW / 2f, _borderW / 2f, Width - _borderW, Height - _borderW);
borderPen = new Pen(_theme.BORDER_COLOR, _borderW);
sizeTriangle = FormSizeTriangle(ClientRectangle, 5);
int width = Width - _borderW * 2;
if (controlBox != null) width -= controlBox.Width;
titleRect = new Rectangle(_borderW, _borderW, width, _titleHeight);
SizeF sf = CreateGraphics().MeasureString(Text, _titleFont);
float x = titleRect.X + (titleRect.Width - sf.Width) / 2f;
float y = titleRect.Y + (titleRect.Height - sf.Height) / 2f;
titleTextRect = new RectangleF(x, y, sf.Width, sf.Height);
float h = _titleHeight - 6;
float w = Icon.Width * h / Icon.Height;
iconRect = new RectangleF(BorderWidth + 3, BorderWidth + 3, w, h);
}
private Point[] FormSizeTriangle(Rectangle rect, int space)
{
Point[] pt = new Point[8];
pt[0] = new Point(rect.Right - space - 7, rect.Bottom - space - 1);
pt[1] = new Point(rect.Right - space, rect.Bottom - space - 1);
pt[2] = new Point(rect.Right - space - 5, rect.Bottom - space - 3);
pt[3] = new Point(rect.Right - space, rect.Bottom - space - 3);
pt[4] = new Point(rect.Right - space - 3, rect.Bottom - space - 5);
pt[5] = new Point(rect.Right - space, rect.Bottom - space - 5);
pt[6] = new Point(rect.Right - space - 1, rect.Bottom - space - 7);
pt[7] = new Point(rect.Right - space, rect.Bottom - space - 7);
return pt;
}
private void FormBase_Paint(object sender, PaintEventArgs e)
{
BufferedGraphicsContext current = BufferedGraphicsManager.Current;
BufferedGraphics bg = current.Allocate(e.Graphics, e.ClipRectangle);
Graphics g = bg.Graphics;
g.Clear(_theme.BACK_COLOR);
DrawBorder(g);
DrawTitle(g);
DrawTriangle(g);
bg.Render();
bg.Dispose();
}
private void FormBase_Load(object sender, EventArgs e)
{
if (!DesignMode)
{
LblBar.Visible = false;
Screen screen = Screen.FromHandle(Handle);
Location = new Point((screen.WorkingArea.Width - Width) / 2, (screen.WorkingArea.Height - Height) / 2);
}
CalcSize();
Refresh();
}
private void FormBase_Resize(object sender, EventArgs e)
{
CalcSize();
Refresh();
}
private void FormBase_MouseDown(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Left)
{
if (!Maximize)
ChangeSize();
HideDrop(this, Handle);
}
}
private void FormBase_MouseUp(object sender, MouseEventArgs e)
{
}
private void FormBase_MouseMove(object sender, MouseEventArgs e)
{
if (MouseButtons == MouseButtons.None)
{
if (!Maximize) //不是最大化
ChangeCursor(e.Location);
}
}
private void FormBase_Activated(object sender, EventArgs e)
{
System.Diagnostics.Debug.Print("111");
}
private void FormBase_Deactivate(object sender, EventArgs e)
{
if (activate)
{
Activate();
Show();
//Task.Run(FlashWindow);
}
}
private void DrawBorder(Graphics g)
{
if (_borderW > 0)
g.DrawRectangle(borderPen, borderRect.X, borderRect.Y, borderRect.Width, borderRect.Height);
}
private void DrawTitle(Graphics g)
{
//g.DrawIcon(Icon, iconRect);
g.DrawImage(Icon, iconRect, new RectangleF(0, 0, Icon.Width, Icon.Height), GraphicsUnit.Pixel);
g.DrawString(Text, _titleFont, new SolidBrush(_titleColor), titleTextRect);
}
private void DrawTriangle(Graphics g)
{
if (Maximize || !CanResize) return;
Pen pen = new Pen(_theme.FORE_COLOR, 1) { DashStyle = System.Drawing.Drawing2D.DashStyle.Dot };
for (int i = 0; i < sizeTriangle.Length; i += 2)
g.DrawLine(pen, sizeTriangle[i], sizeTriangle[i + 1]);
}
/// <summary>
/// 改变鼠标光标
/// </summary>
/// <param name="pt"></param>
private void ChangeCursor(Point pt)
{
int space = 6;
Cursor cursor = Cursors.Default;
if (CanResize)
{
if (pt.X <= space && pt.Y <= space) //左上角
{
cursor = Cursors.SizeNWSE;
place = CursorPlace.LeftTop;
}
else if (pt.X > space && pt.X < Width - space && pt.Y <= space) //上边
{
cursor = Cursors.SizeNS;
place = CursorPlace.Top;
}
else if (pt.X >= Width - space && pt.Y <= space) //右上角
{
cursor = Cursors.SizeNESW;
place = CursorPlace.RightTop;
}
else if (pt.X <= space && pt.Y > space && pt.Y < Height - space) //左边
{
cursor = Cursors.SizeWE;
place = CursorPlace.Left;
}
else if (pt.X >= Width - space && pt.Y > space && pt.Y < Height - space) //右边
{
cursor = Cursors.SizeWE;
place = CursorPlace.Right;
}
else if (pt.X <= space && pt.Y >= Height - space) //左下角
{
cursor = Cursors.SizeNESW;
place = CursorPlace.LeftBottom;
}
else if (pt.X > space && pt.X < Width - space && pt.Y >= Height - space) //下边
{
cursor = Cursors.SizeNS;
place = CursorPlace.Bottom;
}
else if (pt.X >= Width - space - space && pt.Y >= Height - space - space) //右下角
{
cursor = Cursors.SizeNWSE;
place = CursorPlace.RightBottom;
}
else if (pt.X > space && pt.X < Width - space && pt.Y > space && pt.Y < _titleHeight) //标题栏
{
cursor = Cursors.Default;
place = CursorPlace.Inside;
}
else if (pt.X > space && pt.X < Width - space && pt.Y > _titleHeight && pt.Y < Height - space) //中间
{
cursor = Cursors.Default;
place = CursorPlace.None;
}
}
else
{
if (pt.X > space && pt.X < Width - space && pt.Y > space && pt.Y < _titleHeight) //标题栏
{
cursor = Cursors.Default;
place = CursorPlace.Inside;
}
else
{
cursor = Cursors.Default;
place = CursorPlace.None;
}
}
if (cursor != Cursor)
Cursor = cursor;
}
/// <summary>
/// 改变窗口大小
/// </summary>
private void ChangeSize()
{
if (place == CursorPlace.None)
return;
API.ReleaseCapture();
API.SendMessage(Handle, API.WM_SYSCOMMAND, (int)place, 0);
}
private void HideDrop(Control ctl, IntPtr ptr)
{
foreach (Control cc in ctl.Controls)
{
if (cc is ControlBase @base)
{
if (@base.Handle == ptr) continue;
@base.HideDrop();
}
else if (cc is PanelBase)
{
HideDrop(cc, ptr);
}
}
}
private void FlashWindow()
{
Invoke(new Action(() =>
{
if (this.IsDisposed) return;
borderPen = new Pen(_theme.LOST_FOCUS_COLOR, _borderW);
Refresh();
System.Threading.Thread.Sleep(50);
if (this.IsDisposed) return;
borderPen = new Pen(_theme.BORDER_COLOR, _borderW);
Refresh();
System.Threading.Thread.Sleep(50);
if (this.IsDisposed) return;
borderPen = new Pen(_theme.LOST_FOCUS_COLOR, _borderW);
Refresh();
System.Threading.Thread.Sleep(50);
if (this.IsDisposed) return;
borderPen = new Pen(_theme.BORDER_COLOR, _borderW);
Refresh();
System.Threading.Thread.Sleep(50);
if (this.IsDisposed) return;
borderPen = new Pen(_theme.LOST_FOCUS_COLOR, _borderW);
Refresh();
System.Threading.Thread.Sleep(50);
if (this.IsDisposed) return;
borderPen = new Pen(_theme.BORDER_COLOR, _borderW);
Refresh();
}));
}
private enum CursorPlace : int
{
None = 0,
Left = 0xF001,
Top = 0xF003,
Right = 0xF002,
Bottom = 0xF006,
LeftTop = 0xF004,
RightTop = 0xF005,
LeftBottom = 0xF007,
RightBottom = 0xF008,
Inside = API.SC_MOVE + API.HTCAPTION
}
}
}
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
</root>
\ No newline at end of file \ No newline at end of file
namespace FaceControl
{
partial class FormControlBox
{
/// <summary>
/// 必需的设计器变量。
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// 清理所有正在使用的资源。
/// </summary>
/// <param name="disposing">如果应释放托管资源,为 true;否则为 false。</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region 组件设计器生成的代码
/// <summary>
/// 设计器支持所需的方法 - 不要修改
/// 使用代码编辑器修改此方法的内容。
/// </summary>
private void InitializeComponent()
{
this.LblClose = new System.Windows.Forms.Label();
this.LblMax = new System.Windows.Forms.Label();
this.LblMin = new System.Windows.Forms.Label();
this.SuspendLayout();
//
// LblClose
//
this.LblClose.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(255)))), ((int)(((byte)(192)))), ((int)(((byte)(192)))));
this.LblClose.Font = new System.Drawing.Font("Webdings", 12F);
this.LblClose.Location = new System.Drawing.Point(120, 0);
this.LblClose.Margin = new System.Windows.Forms.Padding(0);
this.LblClose.Name = "LblClose";
this.LblClose.Size = new System.Drawing.Size(60, 35);
this.LblClose.TabIndex = 5;
this.LblClose.Text = "r";
this.LblClose.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
//
// LblMax
//
this.LblMax.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(255)))), ((int)(((byte)(192)))), ((int)(((byte)(192)))));
this.LblMax.Font = new System.Drawing.Font("Webdings", 12F);
this.LblMax.Location = new System.Drawing.Point(60, 0);
this.LblMax.Margin = new System.Windows.Forms.Padding(0);
this.LblMax.Name = "LblMax";
this.LblMax.Size = new System.Drawing.Size(60, 35);
this.LblMax.TabIndex = 4;
this.LblMax.Text = "1";
this.LblMax.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
//
// LblMin
//
this.LblMin.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(255)))), ((int)(((byte)(192)))), ((int)(((byte)(192)))));
this.LblMin.Font = new System.Drawing.Font("Webdings", 12F);
this.LblMin.Location = new System.Drawing.Point(0, 0);
this.LblMin.Margin = new System.Windows.Forms.Padding(0);
this.LblMin.Name = "LblMin";
this.LblMin.Size = new System.Drawing.Size(60, 35);
this.LblMin.TabIndex = 3;
this.LblMin.Text = "0";
this.LblMin.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
//
// FormControlBox
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.Controls.Add(this.LblClose);
this.Controls.Add(this.LblMax);
this.Controls.Add(this.LblMin);
this.Name = "FormControlBox";
this.Size = new System.Drawing.Size(187, 41);
this.Resize += new System.EventHandler(this.FormControlBox_Resize);
this.ResumeLayout(false);
}
#endregion
private System.Windows.Forms.Label LblClose;
private System.Windows.Forms.Label LblMax;
private System.Windows.Forms.Label LblMin;
}
}
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace FaceControl
{
internal partial class FormControlBox : UserControl
{
private Theme.IFaceTheme _theme;
private bool maximize;
private Rectangle windowRect;
public delegate void MaximizeChange(bool max);
public event MaximizeChange MaximizeChanged;
public FormControlBox()
{
InitializeComponent();
_theme = new Theme.DarkTheme();
InitEvent();
InitColor();
}
[Browsable(false)]
public override Font Font { get => base.Font; set => base.Font = value; }
[Browsable(true), Category("ShowButton"), Description("显示最小化按钮"), DefaultValue(true)]
public bool ShowMinButton
{
get => LblMin.Visible;
set
{
LblMin.Visible = value;
CalcSize();
}
}
[Browsable(true), Category("ShowButton"), Description("显示最大化按钮"), DefaultValue(true)]
public bool ShowMaxButton
{
get => LblMax.Visible;
set
{
LblMax.Visible = value;
CalcSize();
}
}
[Browsable(true), Category("ShowButton"), Description("显示关闭按钮"), DefaultValue(true)]
public bool ShowCloseButton
{
get => LblClose.Visible;
set
{
LblClose.Visible = value;
CalcSize();
}
}
[Browsable(true), Category("ShowButton"), Description("按钮文本大小"), DefaultValue(12)]
public float ShowButtonSize
{
get => LblClose.Font.Size;
set
{
LblClose.Font = new Font("Webdings", value);
LblMax.Font = new Font("Webdings", value);
LblMin.Font = new Font("Webdings", value);
CalcSize();
}
}
public Theme.IFaceTheme FaceColor
{
get => _theme;
set
{
_theme = value;
InitColor();
Refresh();
}
}
private void CalcSize()
{
int num = 0;
if (LblMin.Visible) num++;
if (LblMax.Visible) num++;
if (LblClose.Visible) num++;
if (num == 0) return;
int x = 0;
int width = Width / num;
if (LblMin.Visible)
{
LblMin.Location = new Point(x, 0);
LblMin.Size = new Size(width, Height);
x += width;
}
if(LblMax.Visible)
{
LblMax.Location = new Point(x, 0);
LblMax.Size = new Size(width, Height);
x += width;
}
if (LblClose.Visible)
{
LblClose.Location = new Point(x, 0);
LblClose.Size = new Size(width, Height);
}
}
private void InitEvent()
{
LblMin.MouseLeave += Box_MouseLeave;
LblMin.MouseEnter += Box_MouseEnter;
LblMin.MouseUp += Box_MouseUp;
LblMin.MouseDown += Box_MouseDown;
LblMax.MouseLeave += Box_MouseLeave;
LblMax.MouseEnter += Box_MouseEnter;
LblMax.MouseUp += Box_MouseUp;
LblMax.MouseDown += Box_MouseDown;
LblClose.MouseLeave += Box_MouseLeave;
LblClose.MouseEnter += Box_MouseEnter;
LblClose.MouseUp += Box_MouseUp;
LblClose.MouseDown += Box_MouseDown;
}
private void InitColor()
{
BackColor = _theme.BACK_COLOR;
LblMin.BackColor = _theme.BACK_COLOR;
LblMin.ForeColor = _theme.TITLE_COLOR;
LblMax.BackColor = _theme.BACK_COLOR;
LblMax.ForeColor = _theme.TITLE_COLOR;
LblClose.BackColor = _theme.BACK_COLOR;
LblClose.ForeColor = _theme.TITLE_COLOR;
}
private void FormControlBox_Resize(object sender, EventArgs e)
{
CalcSize();
}
private void Box_MouseLeave(object sender, EventArgs e)
{
Label lbl = sender as Label;
lbl.BackColor = _theme.BACK_COLOR;
}
private void Box_MouseEnter(object sender, EventArgs e)
{
Label lbl = sender as Label;
switch (lbl.Name)
{
case "LblMin": lbl.BackColor = _theme.TITLE_MIN_BUTTON_OVER; break;
case "LblMax": lbl.BackColor = _theme.TITLE_MAX_BUTTON_OVER; break;
case "LblClose": lbl.BackColor = _theme.TITLE_CLOSE_BUTTON_OVER; break;
}
}
private void Box_MouseUp(object sender, MouseEventArgs e)
{
Label lbl = sender as Label;
switch (lbl.Name)
{
case "LblMin":
lbl.BackColor = _theme.TITLE_MIN_BUTTON_OVER;
MinForm();
break;
case "LblMax":
lbl.BackColor = _theme.TITLE_MAX_BUTTON_OVER;
MaxForm();
break;
case "LblClose":
lbl.BackColor = _theme.TITLE_CLOSE_BUTTON_OVER;
CloseForm();
break;
}
}
private void Box_MouseDown(object sender, MouseEventArgs e)
{
Label lbl = sender as Label;
switch (lbl.Name)
{
case "LblMin": lbl.BackColor = _theme.TITLE_MIN_BUTTON_DOWN; break;
case "LblMax": lbl.BackColor = _theme.TITLE_MAX_BUTTON_DOWN; break;
case "LblClose": lbl.BackColor = _theme.TITLE_CLOSE_BUTTON_DOWN; break;
}
}
private void MinForm()
{
if (Parent is Form frm)
frm.WindowState = FormWindowState.Minimized;
}
private void MaxForm()
{
if (Parent is Form frm)
{
if (maximize)
{
frm.Left = windowRect.Left;
frm.Top = windowRect.Top;
frm.Width = windowRect.Width;
frm.Height = windowRect.Height;
maximize = false;
LblMax.Text = "1";
}
else
{
windowRect = new Rectangle(frm.Location, frm.Size);
Screen screen = Screen.FromHandle(frm.Handle);
frm.Top = screen.WorkingArea.Top;
frm.Left = screen.WorkingArea.Left;
frm.Width = screen.WorkingArea.Width;
frm.Height = screen.WorkingArea.Height;
maximize = true;
LblMax.Text = "2";
}
MaximizeChanged?.Invoke(maximize);
}
}
private void CloseForm()
{
if (Parent is Form frm)
frm.Close();
}
}
}
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
</root>
\ No newline at end of file \ No newline at end of file
namespace FaceControl
{
partial class FormDialog
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
FaceControl.Theme.DarkTheme darkTheme1 = new FaceControl.Theme.DarkTheme();
this.formControlBox1 = new FaceControl.FormControlBox();
this.faceLabel1 = new FaceControl.FaceLabel();
this.BtnMessage = new FaceControl.FaceButtonGroup();
this.SuspendLayout();
//
// formControlBox1
//
this.formControlBox1.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
this.formControlBox1.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(20)))), ((int)(((byte)(20)))), ((int)(((byte)(20)))));
this.formControlBox1.FaceColor = darkTheme1;
this.formControlBox1.Location = new System.Drawing.Point(406, 2);
this.formControlBox1.Name = "formControlBox1";
this.formControlBox1.ShowButtonSize = 12F;
this.formControlBox1.ShowMaxButton = false;
this.formControlBox1.ShowMinButton = false;
this.formControlBox1.Size = new System.Drawing.Size(57, 41);
this.formControlBox1.TabIndex = 1;
//
// faceLabel1
//
this.faceLabel1.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
| System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.faceLabel1.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(20)))), ((int)(((byte)(20)))), ((int)(((byte)(20)))));
this.faceLabel1.BorderWidth = 0;
this.faceLabel1.CursorInside = false;
this.faceLabel1.Font = new System.Drawing.Font("宋体", 12F);
this.faceLabel1.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(230)))), ((int)(((byte)(230)))), ((int)(((byte)(230)))));
this.faceLabel1.ImageSize = new System.Drawing.Size(0, 0);
this.faceLabel1.Location = new System.Drawing.Point(12, 50);
this.faceLabel1.Name = "faceLabel1";
this.faceLabel1.Size = new System.Drawing.Size(441, 168);
this.faceLabel1.TabIndex = 12;
this.faceLabel1.Text = "faceLabel1";
//
// BtnMessage
//
this.BtnMessage.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
this.BtnMessage.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(20)))), ((int)(((byte)(20)))), ((int)(((byte)(20)))));
this.BtnMessage.CursorInside = false;
this.BtnMessage.Font = new System.Drawing.Font("宋体", 12F);
this.BtnMessage.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(230)))), ((int)(((byte)(230)))), ((int)(((byte)(230)))));
this.BtnMessage.Location = new System.Drawing.Point(253, 224);
this.BtnMessage.Name = "BtnMessage";
this.BtnMessage.SelectedIndex = -1;
this.BtnMessage.Size = new System.Drawing.Size(200, 45);
this.BtnMessage.TabIndex = 13;
this.BtnMessage.Text = "faceButtonGroup1";
this.BtnMessage.Click += new System.EventHandler(this.BtnMessage_Click);
//
// FormDialog
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(465, 281);
this.Controls.Add(this.BtnMessage);
this.Controls.Add(this.faceLabel1);
this.Controls.Add(this.formControlBox1);
this.Location = new System.Drawing.Point(0, 0);
this.Name = "FormDialog";
this.Text = "FormDialog";
this.Controls.SetChildIndex(this.formControlBox1, 0);
this.Controls.SetChildIndex(this.faceLabel1, 0);
this.Controls.SetChildIndex(this.BtnMessage, 0);
this.ResumeLayout(false);
}
#endregion
private FormControlBox formControlBox1;
private FaceLabel faceLabel1;
private FaceButtonGroup BtnMessage;
}
}
\ No newline at end of file \ No newline at end of file
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace FaceControl
{
public partial class FormDialog : FormBase
{
private System.Windows.Forms.DialogResult[] dr;
public FormDialog()
{
InitializeComponent();
CanResize = false;
SetControlBox(formControlBox1);
}
public FormDialog(string title, string hint, System.Windows.Forms.MessageBoxButtons button) : this()
{
Text = title;
faceLabel1.Text = hint;
dr = new System.Windows.Forms.DialogResult[3];
switch (button)
{
case System.Windows.Forms.MessageBoxButtons.OK:
BtnMessage.Text = "OK";
dr[0] = System.Windows.Forms.DialogResult.OK;
break;
case System.Windows.Forms.MessageBoxButtons.OKCancel:
BtnMessage.Text = "OK,Cancel";
dr[0] = System.Windows.Forms.DialogResult.OK;
dr[1] = System.Windows.Forms.DialogResult.Cancel;
break;
case System.Windows.Forms.MessageBoxButtons.AbortRetryIgnore:
BtnMessage.Text = "Abort,Retry,Ignore";
dr[0] = System.Windows.Forms.DialogResult.Abort;
dr[1] = System.Windows.Forms.DialogResult.Retry;
dr[2] = System.Windows.Forms.DialogResult.Ignore;
break;
case System.Windows.Forms.MessageBoxButtons.YesNoCancel:
BtnMessage.Text = "Yes,No,Cancel";
dr[0] = System.Windows.Forms.DialogResult.Yes;
dr[1] = System.Windows.Forms.DialogResult.No;
dr[2] = System.Windows.Forms.DialogResult.Cancel;
break;
case System.Windows.Forms.MessageBoxButtons.YesNo:
BtnMessage.Text = "Yes,No";
dr[0] = System.Windows.Forms.DialogResult.Yes;
dr[1] = System.Windows.Forms.DialogResult.No;
break;
case System.Windows.Forms.MessageBoxButtons.RetryCancel:
BtnMessage.Text = "Retry,Cancel";
dr[0] = System.Windows.Forms.DialogResult.Retry;
dr[1] = System.Windows.Forms.DialogResult.Cancel;
break;
}
}
private void BtnMessage_Click(object sender, EventArgs e)
{
DialogResult = dr[BtnMessage.SelectedIndex];
}
}
}
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
</root>
\ No newline at end of file \ No newline at end of file
namespace FaceControl
{
partial class FormFixed
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
FaceControl.Theme.DarkTheme darkTheme3 = new FaceControl.Theme.DarkTheme();
this.formControlBox1 = new FaceControl.FormControlBox();
this.SuspendLayout();
//
// formControlBox1
//
this.formControlBox1.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
this.formControlBox1.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(20)))), ((int)(((byte)(20)))), ((int)(((byte)(20)))));
this.formControlBox1.FaceColor = darkTheme3;
this.formControlBox1.Location = new System.Drawing.Point(420, 2);
this.formControlBox1.Name = "formControlBox1";
this.formControlBox1.ShowButtonSize = 12F;
this.formControlBox1.ShowMaxButton = false;
this.formControlBox1.ShowMinButton = false;
this.formControlBox1.Size = new System.Drawing.Size(57, 41);
this.formControlBox1.TabIndex = 13;
//
// FormFixed
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(479, 280);
this.Controls.Add(this.formControlBox1);
this.Location = new System.Drawing.Point(0, 0);
this.Name = "FormFixed";
this.Text = "FormFixed";
this.Controls.SetChildIndex(this.formControlBox1, 0);
this.ResumeLayout(false);
}
#endregion
private FormControlBox formControlBox1;
}
}
\ No newline at end of file \ No newline at end of file
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace FaceControl
{
public partial class FormFixed : FormBase
{
public FormFixed()
{
InitializeComponent();
CanResize = false;
Maximize = false;
SetControlBox(formControlBox1);
}
}
}
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
</root>
\ No newline at end of file \ No newline at end of file

namespace FaceControl
{
partial class FormInput
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
FaceControl.Theme.DarkTheme darkTheme2 = new FaceControl.Theme.DarkTheme();
this.formControlBox1 = new FaceControl.FormControlBox();
this.faceButtonGroup1 = new FaceControl.FaceButtonGroup();
this.faceLabel1 = new FaceControl.FaceLabel();
this.faceText1 = new FaceControl.FaceText();
this.SuspendLayout();
//
// formControlBox1
//
this.formControlBox1.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
this.formControlBox1.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(20)))), ((int)(((byte)(20)))), ((int)(((byte)(20)))));
this.formControlBox1.FaceColor = darkTheme2;
this.formControlBox1.Location = new System.Drawing.Point(401, 2);
this.formControlBox1.Name = "formControlBox1";
this.formControlBox1.ShowButtonSize = 12F;
this.formControlBox1.ShowMaxButton = false;
this.formControlBox1.ShowMinButton = false;
this.formControlBox1.Size = new System.Drawing.Size(57, 41);
this.formControlBox1.TabIndex = 2;
//
// faceButtonGroup1
//
this.faceButtonGroup1.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
this.faceButtonGroup1.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(20)))), ((int)(((byte)(20)))), ((int)(((byte)(20)))));
this.faceButtonGroup1.CursorInside = false;
this.faceButtonGroup1.Font = new System.Drawing.Font("宋体", 12F);
this.faceButtonGroup1.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(230)))), ((int)(((byte)(230)))), ((int)(((byte)(230)))));
this.faceButtonGroup1.Location = new System.Drawing.Point(268, 193);
this.faceButtonGroup1.Margin = new System.Windows.Forms.Padding(4, 4, 4, 4);
this.faceButtonGroup1.Name = "faceButtonGroup1";
this.faceButtonGroup1.SelectedIndex = -1;
this.faceButtonGroup1.Size = new System.Drawing.Size(180, 45);
this.faceButtonGroup1.TabIndex = 1;
this.faceButtonGroup1.Text = "OK,Cancel";
this.faceButtonGroup1.Click += new System.EventHandler(this.faceButtonGroup1_Click);
//
// faceLabel1
//
this.faceLabel1.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.faceLabel1.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(20)))), ((int)(((byte)(20)))), ((int)(((byte)(20)))));
this.faceLabel1.BorderWidth = 0;
this.faceLabel1.CursorInside = false;
this.faceLabel1.Font = new System.Drawing.Font("宋体", 12F);
this.faceLabel1.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(230)))), ((int)(((byte)(230)))), ((int)(((byte)(230)))));
this.faceLabel1.ImageSize = new System.Drawing.Size(0, 0);
this.faceLabel1.Location = new System.Drawing.Point(12, 50);
this.faceLabel1.Margin = new System.Windows.Forms.Padding(4, 4, 4, 4);
this.faceLabel1.Name = "faceLabel1";
this.faceLabel1.Size = new System.Drawing.Size(436, 45);
this.faceLabel1.TabIndex = 6;
this.faceLabel1.Text = "faceLabel1";
this.faceLabel1.TextAlign = System.Windows.Forms.HorizontalAlignment.Left;
//
// faceText1
//
this.faceText1.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.faceText1.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(20)))), ((int)(((byte)(20)))), ((int)(((byte)(20)))));
this.faceText1.CursorInside = false;
this.faceText1.Font = new System.Drawing.Font("宋体", 12F);
this.faceText1.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(230)))), ((int)(((byte)(230)))), ((int)(((byte)(230)))));
this.faceText1.Location = new System.Drawing.Point(12, 101);
this.faceText1.MaxLength = 32767;
this.faceText1.Name = "faceText1";
this.faceText1.SelectedText = "";
this.faceText1.SelectionLength = 0;
this.faceText1.SelectionStart = 0;
this.faceText1.Size = new System.Drawing.Size(436, 45);
this.faceText1.TabIndex = 0;
this.faceText1.KeyEnterPress += new System.EventHandler(this.faceText1_KeyEnterPress);
//
// FormInput
//
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.None;
this.ClientSize = new System.Drawing.Size(460, 250);
this.Controls.Add(this.faceButtonGroup1);
this.Controls.Add(this.faceLabel1);
this.Controls.Add(this.faceText1);
this.Controls.Add(this.formControlBox1);
this.Location = new System.Drawing.Point(0, 0);
this.Name = "FormInput";
this.ShowIcon = false;
this.ShowInTaskbar = false;
this.Text = "FormInput";
this.TopMost = true;
this.Load += new System.EventHandler(this.FormInput_Load);
this.Controls.SetChildIndex(this.formControlBox1, 0);
this.Controls.SetChildIndex(this.faceText1, 0);
this.Controls.SetChildIndex(this.faceLabel1, 0);
this.Controls.SetChildIndex(this.faceButtonGroup1, 0);
this.ResumeLayout(false);
}
#endregion
private FormControlBox formControlBox1;
private FaceButtonGroup faceButtonGroup1;
private FaceLabel faceLabel1;
private FaceText faceText1;
}
}
\ No newline at end of file \ No newline at end of file
using System;
using System.Windows.Forms;
namespace FaceControl
{
public partial class FormInput : FormBase
{
public FormInput()
{
InitializeComponent();
CanResize = false;
SetControlBox(formControlBox1);
}
public FormInput(string title, string hint, string msg = "") : this()
{
Text = title;
faceLabel1.Text = hint;
faceText1.Text = msg;
}
public string Msg { private set; get; } = "";
private void faceButtonGroup1_Click(object sender, EventArgs e)
{
if (faceButtonGroup1.SelectedIndex == 0)
{
Msg = faceText1.Text;
DialogResult = DialogResult.OK;
}
else
{
Msg = "";
DialogResult = DialogResult.Cancel;
}
}
private void FormInput_Load(object sender, EventArgs e)
{
faceText1.Focus();
}
private void faceText1_KeyEnterPress(object sender, EventArgs e)
{
faceButtonGroup1.SelectedIndex = 0;
}
}
}
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
</root>
\ No newline at end of file \ No newline at end of file
namespace FaceControl
{
partial class FormNormal
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
FaceControl.Theme.DarkTheme darkColor1 = new FaceControl.Theme.DarkTheme();
this.formControlBox1 = new FaceControl.FormControlBox();
this.SuspendLayout();
//
// formControlBox1
//
this.formControlBox1.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(30)))), ((int)(((byte)(30)))), ((int)(((byte)(30)))));
this.formControlBox1.FaceColor = darkColor1;
this.formControlBox1.Location = new System.Drawing.Point(537, 12);
this.formControlBox1.Name = "formControlBox1";
this.formControlBox1.ShowButtonSize = 12F;
this.formControlBox1.Size = new System.Drawing.Size(165, 40);
this.formControlBox1.TabIndex = 1;
//
// FormNormal
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(714, 460);
this.Controls.Add(this.formControlBox1);
this.Location = new System.Drawing.Point(0, 0);
this.Name = "FormNormal";
this.Text = "FormNormal";
this.Controls.SetChildIndex(this.formControlBox1, 0);
this.ResumeLayout(false);
}
#endregion
private FormControlBox formControlBox1;
}
}
\ No newline at end of file \ No newline at end of file
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace FaceControl
{
public partial class FormNormal : FormBase
{
public FormNormal()
{
InitializeComponent();
formControlBox1.MaximizeChanged += FormControlBox1_MaximizeChanged;
SetControlBox(formControlBox1);
}
private void FormControlBox1_MaximizeChanged(bool max)
{
Maximize = max;
}
}
}
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
</root>
\ No newline at end of file \ No newline at end of file
using System;
using System.Xml;
using System.Windows.Forms;
using System.Collections.Generic;
using System.Drawing;
namespace FaceControl
{
/// <summary>
/// 多语言类
/// </summary>
public class Language
{
private XmlDocument _doc;
private string[] _file; //XML文件的路径
private int _index = -1;
private Dictionary<string, string> DialogText = new Dictionary<string, string>();
private List<ClsLangForm> langForm = new List<ClsLangForm>();
/// <summary>
/// 多语言
/// </summary>
/// <param name="path"></param>
public Language(string path)
{
if (!System.IO.Directory.Exists(path))
System.IO.Directory.CreateDirectory(path);
_file = System.IO.Directory.GetFiles(path, "*.xml");
_doc = new XmlDocument();
Name = new string[_file.Length];
for (int i = 0; i < _file.Length; i++)
{
_doc.Load(_file[i]);
Name[i] = _doc.LastChild.Attributes["Name"].Value;
}
}
/// <summary>
/// 语言名称
/// </summary>
public string[] Name { private set; get; }
/// <summary>
/// 语言索引
/// </summary>
public int Index
{
set
{
if (value > -1 && value < _file.Length)
{
_index = value;
LoadLanguage();
foreach (Form frm in Application.OpenForms)
{
if (frm is FormBase)
SetLanguage((FormBase)frm);
}
}
}
get
{
return _index;
}
}
/// <summary>
/// 加载语言
/// </summary>
/// <param name="name"></param>
public void Load(string name)
{
int idx = Array.FindIndex(Name, s => s == name);
Index = idx;
}
/// <summary>
/// 对话框
/// </summary>
/// <param name="key"></param>
/// <returns></returns>
public string Dialog(string key)
{
if (_index == -1) return "";
if (DialogText.TryGetValue(key, out string value))
return value;
else
return "";
}
/// <summary>
/// 创建窗口的文本
/// </summary>
/// <param name="frm"></param>
public void CreateForm(ControlBase frm)
{
//if (_index == -1) return;
//_doc.Load(_file[_index]);
//XmlNode root = _doc.LastChild;
//XmlElement ele;
//XmlNode node = root.SelectSingleNode(frm.Name);
//if (node == null)
//{
// ele = _doc.CreateElement(frm.Name);
// root.AppendChild(ele);
//}
//else
//{
// node.RemoveAll();
// ele = (XmlElement)node;
//}
//ele.SetAttribute("Text", frm.Text);
//ele.SetAttribute("Font", ConvFont(frm.TitleFont));
//GetLang(ele, frm);
//_doc.Save(_file[_index]);
}
/// <summary>
/// 设置语言
/// </summary>
/// <param name="frm"></param>
public void SetLanguage(FormBase frm)
{
int langIdx = langForm.FindIndex(s => s.FormLang.Name == frm.Name);
if (langIdx == -1) return;
frm.Text = langForm[langIdx].FormLang.Text;
frm.TitleFont = langForm[langIdx].FormLang.Font;
SetLang(langIdx, frm);
}
/// <summary>
/// 设置语言
/// </summary>
/// <param name="frm"></param>
public void SetLanguage(Form frm)
{
int langIdx = langForm.FindIndex(s => s.FormLang.Name == frm.Name);
if (langIdx == -1) return;
//frm.Text = langForm[langIdx].FormLang.Text;
//frm.TitleFont = langForm[langIdx].FormLang.Font;
SetLang(langIdx, frm);
}
/// <summary>
/// 设置语言
/// </summary>
/// <param name="ctl"></param>
public void SetLanguage(Control ctl)
{
int langIdx = langForm.FindIndex(s => s.FormLang.Name == ctl.Name);
if (langIdx == -1) return;
//frm.Text = langForm[langIdx].FormLang.Text;
//frm.TitleFont = langForm[langIdx].FormLang.Font;
SetLang(langIdx, ctl);
}
private void LoadLanguage()
{
_doc.Load(_file[_index]);
XmlNode root = _doc.LastChild;
langForm.Clear();
DialogText.Clear();
foreach (XmlNode node in root.ChildNodes)
{
if (node.Name == "Dialog")
{
foreach (XmlNode tt in node.ChildNodes)
DialogText.Add(tt.Name, tt.InnerText);
}
else
{
ClsLangForm lang = new ClsLangForm();
lang.FormLang.Name = node.Name;
if (node.Attributes["Text"] != null) lang.FormLang.Text = node.Attributes["Text"].Value;
if (node.Attributes["Font"] != null) lang.FormLang.Font = ConvFont(node.Attributes["Font"].Value);
if (node.Attributes["Tag"] != null) lang.FormLang.Tag = node.Attributes["Tag"].Value;
foreach (XmlNode tt in node.ChildNodes)
{
ClsLangText ll = new ClsLangText();
ll.Name = tt.Name;
if (tt.Attributes["Text"] != null) ll.Text = tt.Attributes["Text"].Value;
if (tt.Attributes["Font"] != null) ll.Font = ConvFont(tt.Attributes["Font"].Value);
if (tt.Attributes["Tag"] != null) ll.Tag = tt.Attributes["Tag"].Value;
lang.ControlLang.Add(ll);
}
langForm.Add(lang);
}
}
}
private void SetLang(int langIndex, Control ctl)
{
foreach (Control cc in ctl.Controls)
{
if (cc.Name == "") continue;
int idx = langForm[langIndex].ControlLang.FindIndex(s => s.Name == cc.Name);
if (idx > -1)
{
cc.Text = langForm[langIndex].ControlLang[idx].Text;
if (cc is PanelBase)
((PanelBase)cc).TitleFont = langForm[langIndex].ControlLang[idx].Font;
else
cc.Font = langForm[langIndex].ControlLang[idx].Font;
cc.Tag = langForm[langIndex].ControlLang[idx].Tag;
}
if (cc.HasChildren)
SetLang(langIndex, cc);
}
}
private void GetLang(XmlElement ele, Control ctl)
{
//foreach (Control cc in ctl.Controls)
//{
// if (cc.Name == "") continue;
// XmlElement ele1 = _doc.CreateElement(cc.Name);
// ele1.SetAttribute("Text", cc.Text);
// ele1.SetAttribute("Font", ConvFont(cc.Font));
// ele.AppendChild(ele1);
// if (cc.HasChildren)
// GetLang(ele, cc);
//}
}
/// <summary>
/// 转换字体
/// </summary>
/// <param name="s">格式:字体,字号,粗体,斜体</param>
/// <returns></returns>
private Font ConvFont(string s)
{
string[] t = s.Split(',');
float emSize = Convert.ToSingle(t[1]);
FontStyle style = FontStyle.Regular;
if (t[2] == "B") style |= FontStyle.Bold;
if (t[3] == "I") style |= FontStyle.Italic;
Font font = new Font(t[0], emSize, style);
return font;
}
/// <summary>
/// 转换字体
/// </summary>
/// <param name="f">字体</param>
/// <returns></returns>
private string ConvFont(Font f)
{
string[] s = new string[4];
s[0] = f.Name;
s[1] = f.Size.ToString();
if (f.Bold) s[2] = "B";
if (f.Italic) s[3] = "I";
return string.Join(",", s);
}
private class ClsLangForm
{
public ClsLangText FormLang;
public List<ClsLangText> ControlLang;
public ClsLangForm()
{
FormLang = new ClsLangText();
ControlLang = new List<ClsLangText>();
}
}
private class ClsLangText
{
public string Name = "";
public string Text = "";
public Font Font = null;
public string Tag = "";
}
}
}
\ No newline at end of file \ No newline at end of file
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace FaceControl.Model
{
public enum ButtonShape
{
/// <summary>
/// 矩形
/// </summary>
Rectangle,
/// <summary>
/// 圆角矩形
/// </summary>
RoundRectangle,
/// <summary>
/// 椭圆
/// </summary>
Ellipse,
/// <summary>
/// 椭圆矩形
/// </summary>
EllipseRectangle,
/// <summary>
/// 圆形
/// </summary>
Circle
}
}
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
// 有关程序集的一般信息由以下
// 控制。更改这些特性值可修改
// 与程序集关联的信息。
[assembly: AssemblyTitle("FaceControl")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("FaceControl")]
[assembly: AssemblyCopyright("Copyright © 2020")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// 将 ComVisible 设置为 false 会使此程序集中的类型
//对 COM 组件不可见。如果需要从 COM 访问此程序集中的类型
//请将此类型的 ComVisible 特性设置为 true。
[assembly: ComVisible(false)]
// 如果此项目向 COM 公开,则下列 GUID 用于类型库的 ID
[assembly: Guid("06f6c6e6-02f6-4134-945a-be51beef58a4")]
// 程序集的版本信息由下列四个值组成:
//
// 主版本
// 次版本
// 生成号
// 修订号
//
//可以指定所有这些值,也可以使用“生成号”和“修订号”的默认值
//通过使用 "*",如下所示:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.1.0.0")]
[assembly: AssemblyFileVersion("1.1.0.0")]
using System;
using System.Drawing;
using System.Drawing.Drawing2D;
namespace FaceControl
{
public static class Shape
{
public static GraphicsPath Lock(RectangleF rect)
{
float min = Math.Min(rect.Width, rect.Height);
float centerX = rect.X + rect.Width / 2f;
GraphicsPath path = new GraphicsPath();
//黄金比例
float goldenRatio = Convert.ToSingle((Math.Sqrt(5) - 1) / 2);
float bodyHeight = min * goldenRatio;
float bodyWidth = min * goldenRatio;
float headHeight = min - bodyHeight;
float offsetY = rect.Y + (rect.Height - bodyHeight - headHeight) / 2f;
float diameter = bodyWidth / 2f;
float radius = diameter / 2f;
//锁体
float size = min / 6f;
float half = size / 2f;
float bodyOffset = (rect.Width - bodyWidth) / 2f;
RectangleF lockBody = new RectangleF(rect.X + bodyOffset, offsetY + headHeight, bodyWidth, bodyHeight);
RectangleF rectLeftTop = new RectangleF(lockBody.X, lockBody.Y, size, size);
RectangleF rectRightTop = new RectangleF(lockBody.Right - size, lockBody.Y, size, size);
RectangleF rectLeftBottom = new RectangleF(lockBody.X, lockBody.Bottom - size, size, size);
RectangleF rectRightBottpm = new RectangleF(lockBody.Right - size, lockBody.Bottom - size, size, size);
path.AddLine(rectLeftTop.X + half, rectLeftTop.Y, rectRightTop.X + half, rectRightTop.Y);
path.AddArc(rectRightTop, 270, 90);
path.AddLine(rectRightTop.Right, rectRightTop.Y + half, rectRightBottpm.Right, rectRightBottpm.Y + half);
path.AddArc(rectRightBottpm, 0, 90);
path.AddLine(rectRightBottpm.X + half, rectRightBottpm.Bottom, rectLeftBottom.X + half, rectLeftBottom.Bottom);
path.AddArc(rectLeftBottom, 90, 90);
path.AddLine(rectLeftBottom.X, rectLeftBottom.Y + half, rectLeftTop.X, rectLeftTop.Y + half);
path.AddArc(rectLeftTop, 180, 90);
//锁头
path.AddLine(centerX - radius, offsetY + headHeight, centerX - radius, offsetY + radius);
RectangleF headCurve = new RectangleF(centerX - radius, offsetY, diameter, diameter);
path.AddArc(headCurve, 180, 180);
path.AddLine(centerX + radius, offsetY + radius, centerX + radius, offsetY + headHeight);
return path;
}
public static GraphicsPath Unlock(RectangleF rect)
{
float min = Math.Min(rect.Width, rect.Height);
float centerX = rect.X + rect.Width / 2f;
GraphicsPath path = new GraphicsPath();
//黄金比例
float goldenRatio = Convert.ToSingle((Math.Sqrt(5) - 1) / 2);
float bodyHeight = min * goldenRatio;
float bodyWidth = min * goldenRatio;
float headHeight = min - bodyHeight;
float offsetY = rect.Y + (rect.Height - bodyHeight - headHeight) / 2f;
float diameter = bodyWidth / 2f;
float radius = diameter / 2f;
//锁体
float size = min / 6f;
float half = size / 2f;
float bodyOffset = (rect.Width - bodyWidth) / 2f;
RectangleF lockBody = new RectangleF(rect.X + bodyOffset, offsetY + headHeight, bodyWidth, bodyHeight);
RectangleF rectLeftTop = new RectangleF(lockBody.X, lockBody.Y, size, size);
RectangleF rectRightTop = new RectangleF(lockBody.Right - size, lockBody.Y, size, size);
RectangleF rectLeftBottom = new RectangleF(lockBody.X, lockBody.Bottom - size, size, size);
RectangleF rectRightBottpm = new RectangleF(lockBody.Right - size, lockBody.Bottom - size, size, size);
path.AddLine(rectLeftTop.X + half, rectLeftTop.Y, rectRightTop.X + half, rectRightTop.Y);
path.AddArc(rectRightTop, 270, 90);
path.AddLine(rectRightTop.Right, rectRightTop.Y + half, rectRightBottpm.Right, rectRightBottpm.Y + half);
path.AddArc(rectRightBottpm, 0, 90);
path.AddLine(rectRightBottpm.X + half, rectRightBottpm.Bottom, rectLeftBottom.X + half, rectLeftBottom.Bottom);
path.AddArc(rectLeftBottom, 90, 90);
path.AddLine(rectLeftBottom.X, rectLeftBottom.Y + half, rectLeftTop.X, rectLeftTop.Y + half);
path.AddArc(rectLeftTop, 180, 90);
//锁头
path.AddLine(centerX + radius, offsetY + headHeight, centerX + radius, offsetY + radius);
RectangleF headCurve = new RectangleF(centerX + radius, offsetY, diameter, diameter);
path.AddArc(headCurve, 180, 180);
path.AddLine(centerX + radius * 3, offsetY + radius, centerX + radius * 3, offsetY + headHeight);
return path;
}
}
}
using System;
using System.Drawing;
namespace FaceControl.Theme
{
public class DarkTheme : IFaceTheme
{
public Color BACK_COLOR { get; } = Color.FromArgb(20, 20, 20);
public Color FORE_COLOR { get; } = Color.FromArgb(230, 230, 230);
public Color DOWN_COLOR { get; } = Color.FromArgb(0, 122, 204);
public Color OVER_COLOR { get; } = Color.FromArgb(50, 50, 50);
public Color BORDER_COLOR { get; } = Color.FromArgb(0, 122, 204);
public Color LOST_FOCUS_COLOR { get; } = Color.FromArgb(50, 50, 50);
public Color TITLE_COLOR { get; } = Color.FromArgb(230, 230, 230);
public Color TITLE_CLOSE_BUTTON_BACK { get; } = Color.FromArgb(30, 30, 30);
public Color TITLE_CLOSE_BUTTON_OVER { get; } = Color.FromArgb(150, 50, 50);
public Color TITLE_CLOSE_BUTTON_DOWN { get; } = Color.FromArgb(240, 70, 90);
public Color TITLE_MIN_BUTTON_BACK { get; } = Color.FromArgb(30, 30, 30);
public Color TITLE_MIN_BUTTON_OVER { get; } = Color.FromArgb(80, 80, 80);
public Color TITLE_MIN_BUTTON_DOWN { get; } = Color.FromArgb(0, 122, 204);
public Color TITLE_MAX_BUTTON_BACK { get; } = Color.FromArgb(30, 30, 30);
public Color TITLE_MAX_BUTTON_OVER { get; } = Color.FromArgb(80, 80, 80);
public Color TITLE_MAX_BUTTON_DOWN { get; } = Color.FromArgb(0, 122, 204);
}
}
using System;
using System.Drawing;
namespace FaceControl.Theme
{
public interface IFaceTheme
{
public Color BACK_COLOR { get; }
public Color FORE_COLOR { get; }
public Color DOWN_COLOR { get; }
public Color OVER_COLOR { get; }
public Color BORDER_COLOR { get; }
public Color LOST_FOCUS_COLOR { get; }
public Color TITLE_COLOR { get; }
public Color TITLE_CLOSE_BUTTON_BACK { get; }
public Color TITLE_CLOSE_BUTTON_OVER { get; }
public Color TITLE_CLOSE_BUTTON_DOWN { get; }
public Color TITLE_MIN_BUTTON_BACK { get; }
public Color TITLE_MIN_BUTTON_OVER { get; }
public Color TITLE_MIN_BUTTON_DOWN { get; }
public Color TITLE_MAX_BUTTON_BACK { get; }
public Color TITLE_MAX_BUTTON_OVER { get; }
public Color TITLE_MAX_BUTTON_DOWN { get; }
}
}
using System;
using System.Drawing;
namespace FaceControl.Theme
{
public class LightTheme : IFaceTheme
{
public Color BACK_COLOR { get; } = Color.FromArgb(230, 230, 230);
public Color FORE_COLOR { get; } = Color.FromArgb(30, 30, 30);
public Color DOWN_COLOR { get; } = Color.FromArgb(0, 122, 204);
public Color OVER_COLOR { get; } = Color.FromArgb(0, 122, 204);
public Color BORDER_COLOR { get; } = Color.FromArgb(0, 122, 204);
public Color LOST_FOCUS_COLOR { get; } = Color.FromArgb(30, 30, 30);
public Color TITLE_COLOR { get; } = Color.FromArgb(230, 230, 230);
public Color TITLE_CLOSE_BUTTON_BACK { get; } = Color.FromArgb(30, 30, 30);
public Color TITLE_CLOSE_BUTTON_OVER { get; } = Color.FromArgb(150, 50, 50);
public Color TITLE_CLOSE_BUTTON_DOWN { get; } = Color.FromArgb(240, 70, 90);
public Color TITLE_MIN_BUTTON_BACK { get; } = Color.FromArgb(30, 30, 30);
public Color TITLE_MIN_BUTTON_OVER { get; } = Color.FromArgb(80, 80, 80);
public Color TITLE_MIN_BUTTON_DOWN { get; } = Color.FromArgb(0, 122, 204);
public Color TITLE_MAX_BUTTON_BACK { get; } = Color.FromArgb(30, 30, 30);
public Color TITLE_MAX_BUTTON_OVER { get; } = Color.FromArgb(80, 80, 80);
public Color TITLE_MAX_BUTTON_DOWN { get; } = Color.FromArgb(0, 122, 204);
}
}
C:\Users\Company\Documents\FaceControl\FaceControl\obj\Debug\FaceControl.FormBase.resources
C:\Users\Company\Documents\FaceControl\FaceControl\obj\Debug\FaceControl.csproj.GenerateResource.cache
C:\Users\Company\Documents\FaceControl\FaceControl\obj\Debug\FaceControl.csproj.CoreCompileInputs.cache
C:\Users\Company\Documents\FaceControl\FaceControl\bin\Debug\FaceControl.dll
C:\Users\Company\Documents\FaceControl\FaceControl\bin\Debug\FaceControl.pdb
C:\Users\Company\Documents\FaceControl\FaceControl\obj\Debug\FaceControl.dll
C:\Users\Company\Documents\FaceControl\FaceControl\obj\Debug\FaceControl.pdb
C:\Users\Company\Documents\FaceControl\FaceControl\obj\Debug\FaceControl.FormControlBox.resources
C:\Users\Company\Documents\FaceControl\FaceControl\obj\Debug\FaceControl.FormNormal.resources
C:\Users\Company\Documents\FaceControl\FaceControl\obj\Debug\FaceControl.csprojAssemblyReference.cache
C:\Users\Company\Documents\FaceControl\FaceControl\obj\Debug\FaceControl.FormDialog.resources
C:\Neotel\Program_Beta\FaceControl\FaceControl\obj\Debug\FaceControl.FormBase.resources
C:\Neotel\Program_Beta\FaceControl\FaceControl\obj\Debug\FaceControl.FormControlBox.resources
C:\Neotel\Program_Beta\FaceControl\FaceControl\obj\Debug\FaceControl.FormDialog.resources
C:\Neotel\Program_Beta\FaceControl\FaceControl\obj\Debug\FaceControl.FormNormal.resources
C:\Neotel\Program_Beta\FaceControl\FaceControl\obj\Debug\FaceControl.csproj.GenerateResource.cache
C:\Neotel\Program_Beta\FaceControl\FaceControl\obj\Debug\FaceControl.csproj.CoreCompileInputs.cache
C:\Neotel\Program_Beta\FaceControl\FaceControl\obj\Debug\FaceControl.dll
C:\Neotel\Program_Beta\FaceControl\FaceControl\obj\Debug\FaceControl.pdb
C:\Neotel\Program_Beta\FaceControl\FaceControl\bin\Debug\FaceControl.dll
C:\Neotel\Program_Beta\FaceControl\FaceControl\bin\Debug\FaceControl.pdb
C:\Neotel\Program_Beta\FaceControl\FaceControl\obj\Debug\FaceControl.ControlBase.resources
C:\Neotel\Program_Beta\FaceControl\FaceControl\obj\Debug\FaceControl.FaceButton.resources
C:\Neotel\Program_Beta\FaceControl\FaceControl\obj\Debug\FaceControl.FaceButtonGroup.resources
C:\Neotel\Program_Beta\FaceControl\FaceControl\obj\Debug\FaceControl.FaceRadio.resources
C:\Neotel\Program_Beta\FaceControl\FaceControl\obj\Debug\FaceControl.FaceCheck.resources
C:\Neotel\Program_Beta\FaceControl\FaceControl\obj\Debug\FaceControl.FaceTrackBar.resources
C:\Neotel\Program_Beta\FaceControl\FaceControl\obj\Debug\FaceControl.FaceLabel.resources
C:\Neotel\Program_Beta\FaceControl\FaceControl\obj\Debug\FaceControl.FaceNumericKeypad.resources
C:\Neotel\Program_Beta\FaceControl\FaceControl\obj\Debug\FaceControl.FaceRadioGroup.resources
C:\Neotel\Program_Beta\FaceControl\FaceControl\obj\Debug\FaceControl.FaceCheckGroup.resources
C:\Neotel\Program_Beta\FaceControl\FaceControl\obj\Debug\FaceControl.FaceScrollBar.resources
C:\Neotel\Program_Beta\FaceControl\FaceControl\obj\Debug\FaceControl.FaceList.resources
C:\Neotel\Program_Beta\FaceControl\FaceControl\obj\Debug\FaceControl.FaceText.resources
C:\Neotel\Program_Beta\FaceControl\FaceControl\obj\Debug\FaceControl.FaceCombo.resources
C:\Neotel\Program_Beta\FaceControl\FaceControl\obj\Debug\FaceControl.FaceNumeric.resources
C:\Neotel\Program_Beta\FaceControl\FaceControl\obj\Debug\FaceControl.FaceImageShow.resources
C:\Neotel\Program_Beta\FaceControl\FaceControl\obj\Debug\FaceControl.ProgressStep.resources
C:\Neotel\Program_Beta\FaceControl\FaceControl\obj\Debug\FaceControl.FormInput.resources
C:\Neotel\Program_Beta\FaceControl\FaceControl\obj\Debug\FaceControl.FormFixed.resources
C:\Neotel\Program_Beta\FaceControl\FaceControl\obj\Debug\FaceControl.FaceDateTime.resources
C:\Neotel\Program_Beta\FaceControl\FaceControl\obj\Debug\FaceControl.FaceLock.resources
C:\Neotel\Program_Beta\FaceControl\FaceControl\obj\Debug\FaceControl.csprojAssemblyReference.cache
namespace Test
{
partial class Form1
{
/// <summary>
/// 必需的设计器变量。
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// 清理所有正在使用的资源。
/// </summary>
/// <param name="disposing">如果应释放托管资源,为 true;否则为 false。</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows 窗体设计器生成的代码
/// <summary>
/// 设计器支持所需的方法 - 不要修改
/// 使用代码编辑器修改此方法的内容。
/// </summary>
private void InitializeComponent()
{
System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(Form1));
this.button1 = new System.Windows.Forms.Button();
this.faceLock1 = new FaceControl.FaceLock();
this.SuspendLayout();
//
// button1
//
this.button1.Location = new System.Drawing.Point(226, 125);
this.button1.Name = "button1";
this.button1.Size = new System.Drawing.Size(75, 23);
this.button1.TabIndex = 3;
this.button1.Text = "button1";
this.button1.UseVisualStyleBackColor = true;
//
// faceLock1
//
this.faceLock1.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(20)))), ((int)(((byte)(20)))), ((int)(((byte)(20)))));
this.faceLock1.CursorInside = false;
this.faceLock1.FaceShape = FaceControl.Model.ButtonShape.RoundRectangle;
this.faceLock1.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(230)))), ((int)(((byte)(230)))), ((int)(((byte)(230)))));
this.faceLock1.Location = new System.Drawing.Point(329, 219);
this.faceLock1.LockWidth = 50;
this.faceLock1.Name = "faceLock1";
this.faceLock1.Size = new System.Drawing.Size(247, 82);
this.faceLock1.TabIndex = 4;
this.faceLock1.Text = "faceLock1";
//
// Form1
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(780, 540);
this.Controls.Add(this.faceLock1);
this.Controls.Add(this.button1);
this.Icon = ((System.Drawing.Bitmap)(resources.GetObject("$this.Icon")));
this.MaximizeBox = true;
this.MinimizeBox = true;
this.Name = "Form1";
this.Text = "Form1";
this.Load += new System.EventHandler(this.Form1_Load);
this.Controls.SetChildIndex(this.button1, 0);
this.Controls.SetChildIndex(this.faceLock1, 0);
this.ResumeLayout(false);
}
#endregion
private System.Windows.Forms.Button button1;
private FaceControl.FaceLock faceLock1;
}
}
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace Test
{
public partial class Form1 : FaceControl.FormNormal
{
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
faceLock1.Password = "yuiop";
}
}
}
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<assembly alias="System.Drawing" name="System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
<data name="$this.Icon" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>
iVBORw0KGgoAAAANSUhEUgAAAZsAAABeCAYAAAD1yrlLAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAL
EgAACxIB0t1+/AAAGLxJREFUeF7tnd3PHNV9x/MnzFVsbGyvA+Yl6csWlMamoZ2QqFGiRlkDtgkUWAKB
1IawgRRIIHRN47YEjBeDeTHGbHhJGsrLAgUi9aJzkVxElapVVFWperNSo6o3rUaNFKVS1en3N7Ozz+w8
v505M+fMeh/zvfgoysHPnjPn/M7vM3PmzMyHoigihBBCGkUtJIQQQlyiFhJCCCEuUQsJIYQQl6iFhBBC
iEvUQkIIIcQlaiEhhBDiErWQEEIIcYlaSAghhLhELSSEEEJcohYSQgghLlELCSGEEJeohYQQQohL1EJC
CCHEJWohIYQQ4hK1kBBCCHGJWkgIIYS4RC0khBBCXKIWEkIIIS5RCwkhhBCXqIWEEEKIS9RCQgghxCVq
ISGEEOIStfBs5MNf/K4/paX9d0IIIc2hFp4tfLjzSHvHNQ/9GIKJsmy5+sh/bTtweKD9DSGEEPeohWcD
rWuPHIRs5iST59wDD/0H/tfT/p4QQog71MKNzkU39f9o05VHozLZCNuu6f+n9hsuQT0e6IL+lB7gch4h
5AODWriROWf/wNt64JFfm8pGuPirXzuu/ZYtm6581EMbBlqdU0aAV1aEkLMetXAjs/Wax368+erHoiqy
2X7tg7/SfssGtMGDbMYGbQhBW/sNQgg5W1ALNyrnXHO8jyubqKpshM89tcfpshbaMIJsTNsw1n6DEELO
FtTCjciWa5/0IZuormx+94EDr2m/Wwe0oZe0wVg2Qlf7LVMufuh9D/gX/dm7/oXffse/4P63/Au++aa/
657X/fO/8Tf+eXf90P9I7wfWV1BoZ7qFXKP092dtfOBtfxfad/6fvpa07c7v+zsPveTv+OrQ3/6V5/1t
N530z73haX/LdRjXA4/76E9/U+cRrU7Beimy9Sff83fc9kJ/+1dOB9tvPjVG/dG5Nz4Tbb3+qWjLdSei
LV96YoJ2BJv3HRtsuupoZ9PeR1dy+XPnHS+3Wgdf7OJYhttvORXgOCbox2grjkHmx+Z9g2RufPG7wRS5
hyj3E52ebG378nPeud1nO1uvf3qAMQxQ93izzM2rMC/m50TaDllulnY4ucrH8SOOTvvbbj6VxNKNz/gY
S8TTCR9jmcTUvmNO6kJMty8+/J5/0YN/G8f1Bd8a+bvue8M//57X/PPvftU/7+t/LfFtFS/oF7nvq8V+
ysovx6uFG42tf/yUB9mENrK54tHP/EL77aqgDe21NlSSTaD9nimSxEGERB5BNhFkE0E2EWQTQTYREnoE
2YQ7v/aKVVJR2p2l9BhmbXzg7QiyiSCbpG13fj+CbCLIJoJsojjZI0kiUUVIDEl/Lu5LX6urDNTZ2nnH
K0PUG0I2ERIU6j4dQTZJ/fOySdqx71gE2USQjdQ7BCux0QN92MX4BpBNBNkkx3LL9Dh02WiMgdXx7Lht
2MH4jSCbCLJB/03HUOrWZaMxAbVFgLFsp2MJ2RSNZaj9fVUQ0wFkE0E2cVxDNhFkE0E2EWQTQTYS3yPt
b01Bf4hQtL5KqTUHlolauNGAbALIJg7oOrI556ojsowWfebEno72+6agDR7aMKkpG/yE/rsmGMomgmxs
g15t+5QNIRskAA8JYBjXeccrcb01ZZMi0jkjZ5ZIam30YTAbXzvZCLWS1s7bX/ZR7wSyScbPTjZC7eSJ
sRwYykbG0mrOC4aykbGpXZf0R65/8lA2TXPuDc/0IZvIRjYfPXh7KpuhVocpaMNwvg0rKRtJrjZBr7Z9
ysrLBvW1kQDCtQTgRDbC0jd6YIy7SGrhrA/PgGxQr4d+HEI203pXQjaQnrFsrOa8UEE2Ifqo1kmJ9Eeu
f/JQNk2y7aZn25BNZCMbuar5w2OfTmUT+k/sqRUMaEN3fRsqycbqkr6ibGTZqG7Qa21PWWnZ7Lr3ja7U
N58AnMkmxeremylIbB0Z4zipnSHZIK481DuO+3FFZIOx7GTH0kA2oe39twqykT6q9eYS6Y9c/+ShbJpi
283PeZDNxFY2v//QldEXntmTyiaCbConC0zmNtoQWsrGanmromwkudaqT2l3lpWVDfqiC9nE9TUsG6HR
iY/E5iGxhWdSNrvufb2NuApnY7c6shlWlI2Mpe3mnCqykRivfGzSH7n+ydNozLlALdwIQDYjyAYTqb5s
fqd3W7T32T152ZQmzCyYUB4m81hvQyXZWAVLDdnIhKy8nKa0O8tKyubC+99qx32xPNnIklpjGweQ2PqS
2AxlI7vRAsimj9jsQzZ9zA3Z/SWbAbS2l8Yh+tKDbMazuFoR2WAsvfxYGsrG9kSvqmwmO249XelqSvoj
1z95KJsmQDD3IBsEUX3ZnHf9/dG+5/Zosok+efwy40SBCTWMzxztZGMV7EJN2UzQl1WDXmt/igvZ9NAm
Z1uf0RceZDOpIJsRZNOV+uXvkaA8JCjZLttDO2Trs4lshEonLVVAYgsNZDOGbAoTENqYvkZJ5JO220Q2
AWSzFlflshnHots/8CGb2X0tqWuKbL/OtsGoHXkwlt0C2YQlJw61Tw5qyCaCbCotp0l/ZPpGg7JxDYKo
HQezhWy2XH0k2nv8iiLZ9LW682BCdWVCWcpGtnlarRkLNWUjiaFq0GvHkOJCNk4nDfpiANkkfVEsm7HE
lvYbWZCgfCSoiYFsBOf3b9B/8kxHnNgKZCPHUufMWRJ+Yf9f+MBbvaQvjWQzgmyMkzjqFvmJeOTKsI5s
ggLZBCWy6Wm/aUJN2ciVp/ExSn+AfHxloWxcgiDyEERyNm4lm0/3D0TXntpdJJuJVn+W7bc838aECh3I
xtWDZXVlI4mhStBrx5CyUrK5qP9uS/rCQDaVdiQhQXlIUIuWobKUxlFV0H8dA9lYb+fVQJ0eZBMayCaU
EzHtN0xAv4l0KskSbZBnpnKxPSebTolsar/Fw0I2xnWifZTNMkEQjWYJsqZsLrnjUHTD6d1lsok+Mbis
UAKQzXh69mYjm9pnU3ksZTPBcRhNbuUYsqyabIYGsqmVZJCgWjheOQPX+iGL06sb9F/fQDaNJB7UOYRs
pn1ZKJulbgEX0IZekWzk30A24wLZCLWW0ixkg7l30mgVBW2jbJZF69BLvbkEWUM2u264P7r+5OWmsll4
trvj1hcGkM1sXbqmbKzv02QxkM2kQDZyHKZBrx1LysrI5uLD73uQTdwXJbKpvVaP45VPRWj9kMX1OJvI
xmmdAuqMd8AZyMb50qEJaMOkQDZxf0A2vRLZ1NqWXCIbeaYrLJCNXHWVyhlto2yWAQapDdlkXilSXTZb
rz4SHTj+2ejLL+w2lY363AsCpQPZIFCsZOPkPk0WA9nI60zkdTWLZCPHYRL02vGkrJJsugaysX6gD8cs
Y6n1RRZnY43+M1lGk7GtLVEN1NlNkmmhbErHvwkwlu0kmS+UTSxAyKZVIptay54lspFY65fIpvTqGm2j
bJoGg+RhkMaQzXyCrCibz//5gejW7+2uIpvo0mOXzZ2ltQ692EKghA5k43yZwUA28iLOfolsTIJeO56U
VZLN0EA21gkZx1z0vaIUZ/dQ0H8mGwRkbMMqN6DLQJ0jA9k4FZwpGMuFrx6aymYme8hmXCAbofLcLJON
/Bu0b1wgG9mWXbikjnZRNk2DQRrGg2Qhm0/ceSg6+OLuOrKZW46AbMZJoFjJxtl9miwmspF/B9mMC2SD
4zhRuJyWO5Y8qySbSYlsat8QzoJjbuf6QMNoidIUJLaJgWySZHbTyRHG1VoCa8l0oWyc9GcdMJbTZSpV
NnNzGLLplcim8tWuoWz8EtmEaNvCcUK7KJsmQRB1kyCyks34tlN/8G5N2US/fTR55gZtGEA200CpLZvG
lhkqyKZdIhscxxMLz+4yx6LhQjZVn7NRl6ggm6hENrXW5zXQBq0vsri9bzNd0jKUTTKu152Q9/bVSkgY
s9nVVIFsGjmJKgNj2cFYJm3QZTO3OiEJvUQ2lV8bZSIbIc4hi2UjO+UWzh+0S2I92848lE1dzrv71fba
GYuVbNp3vry7YyGbHtrQSdpgJRvZueT0Pk0WA9nMkgEmZL9ENkVBnx6PhgvZJG2aJkmDNwism2RxX5TL
xtmNbLQh/0BiHucnGUhs44qyiWNz875BgLlR6djRn7P7RAWyOSPJDmM5KpHNujkH2YwLZCNUWvZE/5jK
xsPYTApkI/eTVGmjTZRNE2DyeJDNeC2IastmNnCQTVhHNr/58Of/GW0IHcim0WCIE2yxbOaWctCX8uDf
ItlIgl8U9NkAz7ORZONsPNCGMyGbNsY4rCGbZG4kGxuM+gD9OdsBt0g2+b9ZBpInpmO5SDbqFaUk9BLZ
VLoSRf8YyUbA2MgHAotkE56z//F1y2kyVrk25qFs6oAgGkI2mSCqJZu5gIFsBnVkc8F9RzNtqC0bp2v2
GnGCrSYb+TJlkWxCTEYt6PNBnoWy0Zlof2cLxriNpGb7iQFpe+EVN/pzVWXTLZGNegWHhN4qkY1gvAqB
/jGWjYAYHxTIBvnj8XWyQ3soG9cgIXTiyWMnmwkm1FywQDbtqrL52OG7cm2oJRvnZ7UacYKtIBsBfTko
kI1MxnVtV4I8ywdVNmU70hq7eY6k1sIx2X48rfBbPOjPVZXNuEQ2C4WBmBqXyMZ4qRH9U1U2HmQzKZAN
4v3Y3FIe2kPZuARB3EJCSM7U7GSjThzIZmwqm0se3q+0obJsQsjG+AzJhjjBVpeNh76cFMhGJuPccpoS
5Fl4ZaPT+AkH+rAH2STLvdVlk6Leq0B/rpxsMJYi2XQsNdkULoUhpnolsjEeM/RPJdkIkI1fIpswe8KM
9lA2LkEQj9OEYCEb9V6DANn0TGTze4NPYTK97EI2SwuAOMFWlI2AvvRLZBNu2rsmTCXIs1A2Oo3LRoBs
5Jm0PmSTfKmyumzUTyOgP0tls/P2l5dyUpWCseyXyKbwygQx1SqRjbBwK3IW9E9l2QgYn1GBbGScZsJE
WygbVyAhDLIJoaZsCs9mIJuWiWw+9uDjaAMmkp1sGr9PkyVOsDVkI+A4BgWywWR8JBv0WqCnuJDNEOPb
R5Lsoz19yKaPtvSlPyEbeSNwHi05mshm4UlJVdCGsrcIFMZlE0iyRTILKspGWPecCfrTRDZLTXYYy0mJ
bErlh/gel8jGKEbQP3Vl40E2YYFsZBk+7le0hbJxwYUPvtPJJ4QasplgMpUGGGQzKpLNpX/xjWQi2clm
6Q+4xQm2vmw8HId8ZGuRbCSY4yWWXIDncSEb60mDOjwD2Vi/qkbAMcsbirW+yLLUE48skI08ryQfTzOV
jTAncPSnydbnpR0j6vdzY6nJBnli9gaB9VcPc/G9UDZG8xj9U0s2AmTTKZFN/GorQNnYgoTQgmxCB7Ix
6mzIprtINp987MDaRKovmxCyMbr8dgkCvrZsBByHJKUi2cTPCWWCW2MlZCNANmGJbCo/vKeBY5aPj2l9
kcXZ62rqAtl0EJsTQ9nMndFjzEwe6lzaCRbqHy5JNkLp62tsZCOgbaMC2UgbZAMKZWMLEsIYslmXECrK
ptJZFWQT5mXz2Sc/FV307VddyOaMJBZb2Qg4jmGBbIRhJrg1Vkk2oxLZSJ3WD3bimEe5PtBY6v2MRSA2
PchGbjxrbcyybtnPQDayMWEpCQ/1h0uUTembJhzIxkPb5HU1i2QjyJJxtl15KJsiMEj9OCHYyabyzVfI
ZpiXzSVHjq4l6PqycfYKlKo4ko0H2YQFshGKvuGySrIxeeuz1dk4jle+aaP1Q5al368pArLpG8hm3Tgi
mZq8iLPxqxuMZXfBWDYlm4nWjiy2shHQtk6JbIrmnUDZFIFBSl6WWF82IWRT+awRsvGzsrn86J3zCbqe
bEonGv62hb/xt153ovKbZctwIRsBsumUyKaIVZKN6fdsam8UkOPNHb+G9dWTSyAbr6ZsTD4xgPk5bPSE
C2M5KhjLJmQjFK5WuJCNgLaNCmRTBmWzCAxQO048drKp3cGQzURk87kn965P0NVlE0I2C+/T4Hg6+I34
nUjyN3KzFoEuZypyaexkiQV96UQ2AmQz2uiyERBbJl/qlHoryx8JqmxJUXByXyhLPG8Ov2e1VIskVnmr
Nuo0/XiazM9GBIux9AzGsgnZFG4mwZi4ko28JFReV0PZuGSWHOvLptJ9mjyQTV9kc+lfPu1CNgsnPyZn
V45HfgN/259e2cgDZellsXzL3lo4s/50IxsPk1FeV7PRZdMylI18mM84gaNPhgYJSnC2vTolHucksQ0w
xpXjBlc2LYMrG3XpD3X2DWUjc2OIuVG5fahbPtkgMlwXBxjLnsFY+hhLeRWTD9n4kE3yBvEbn/EhGx8J
3UdCT94kvu+Yj7H0MZZl8i08acCYOJGNgLb1KBvHzJJjPdmUJrUyIJvWF57aG8VBYiebhcsGcowyOaey
mWT/GwJdJJMGivU23Fl/OpCNgMnY2eiyEdAX/Qpnw0MkqIVXOeiTLvpkYng23Mj9i3icp4kNYywv4pSH
G42S+jnXHG9BNmMD2aiSRJ0e4jmczZFi2cjcCLdeHz8rVbg7E/XJvS/5xHZ2TmiyGZeMZa37YxhLkx2F
C6/WMCbOZCNANgFl4xAMkBcnnuqyCRHMTpaerhh8/eeWshkXnb1JEGZkEyfS647/3eW4spGzqnywWG2X
jpOQQ9kIaOPoDMgmSVay9HGD0RsEUtTJhr6QpZdxQYLKygZ1n46233xqgvoDnA0HOBsOcDYc1Fh6cX5f
TojHeU02SVJL+nD0kd4PeohTH0l/Fks4jrZceSPm5Hs2uFqt/pxNFsRzZzZHymUTQTbJGErd+wfB5qse
CzCOciWRsujG99x4ImZMrlJrXUliLE2elVooMpnnjmXTgmySXYOUjRtkkGrIxtnW4o8//OTIQjYhJlRh
QpHEmpXNt374D788/t7Pov3fefO/P37w+XywWK1zx0nIvWw8JFZ5XU2+rYtYOdkIiK02+sJ4uyxkY7vO
39imgHicddnYvIgzS+kYoi8HNWQTQTYRZFM2jil52QwMZFP7hA311d7CjjFxKhsBsulRNg6RiVNRNk53
uvzGd974poVsShOKJNZUNvI79735s+hX//O/0U/+6d+0CW91DypOQo5lIyCx9ja6bAT0RRuxFb/ktWHZ
NCYaIR7n5mQjVxlGV2SYI8Mly2ZSIhvbbey1l9IwJs5lI2CcAsrGIZDNwFA2pYmsKgiS5MnoirLZfvD4
j7TfyyOJVWST/v+Tf/8vP/mr0T9Gj73+01//6Kf/+ltShiBJdzVZBUuchBqQjQDZlN1ATVlZ2QiIrTbq
mzQom0ZFI8Tj3JxsKrUfcdVfhmwuPvx+J43rAtlYbcZAfSZLaarQMCZNyaZF2TgGspFdJtMbj6psGtu7
/9GH3vn3SrK5/fFf4srG6J4RgnA8vbKJ/z0SaXDZfa+mW5/jMgRJelPU6DcXESeh5mQjN3DLHioTVlo2
gowFEkDhp4RryEbGsJF7NHnicXYvGxnbWsvTqDfe1t+wbIYGsrG65ymgTpOltHX1YEwakY0A2ZS9OSCF
sjEFQeQhiHoIohGCKECiDxBEfRdBVASCxDeWzR2n/m/7PXcf0H5HA0HYmcomxG8MJJHKJJzKRgI7fVvw
yu1Gy4M2ym6hfIDnWXnZpGBcfdQZWMpGxq/xq5ks6L8WYjZwKBu5srY60UE/epBNH/WGjmQj/RrPexyv
vFQ1LJGNk51/qNNkKW3dPEIbG5ONgDqzu/QWQdlsBBDIXSPZ3PXwg9rfFwHZDGVSyG/kZJMGiQSS1WQX
EPDykGyAYwlwLAGOJcCxBJBNANnIlxytkyLaKYkpu5MoT+kV6KyND7wdQDYB+kbaFsSJ/9BLgVz9IVnJ
q/EDJMkAiSpAkg8gm/wupjy1riwgmzbqHUA2yTdgymUTQjbynI2zjSp1QGJrYYx7SGrSh1VlIyc6cvJg
HXd5IJsuxm+IOA8rykbGUM7i58YR8YIrubW4hmySuL43Pu4AyVxOSp0IH3XLUlo+rvKsi3G0cTA9AYjj
GrIJ4nG5J2lf/t9XBXWmzx4VsZQraxvUwg8iCGT/gvvf/IUmm/PuOvlzTOLag4lJ0UUyzb9BQCaY9Vkl
cQcStAfZ+JBNB0m6D9n0IZs+ZNOBbORBwEavsm2AbFqQjY84la3PfRxLH7JJvwskW599JPylth+y8SAb
H7KRN073IZs+ZJN+l0jeYiysbJ8St6iFH2QgmzZk04Vs+pBNF7JxNhkgmzZkI28QkOdsKBlCyAcGtZAQ
QghxiVpICCGEuEQtJIQQQlyiFhJCCCEuUQsJIYQQl6iFhBBCiEvUQkIIIcQlaiEhhBDiErWQEEIIcYla
SAghhLhELSSEEEJcohYSQgghLlELCSGEEJeohYQQQohL1EJCCCHEJWohIYQQ4hK1kBBCCHGJWkgIIYS4
RC0khBBCXKIWEkIIIS5RCwkhhBCXqIWEEEKIS9RCQgghxCVqISGEEOKO6EP/D5U/zTNn9UImAAAAAElF
TkSuQmCC
</value>
</data>
</root>
\ No newline at end of file \ No newline at end of file

namespace Test
{
partial class Form2
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.components = new System.ComponentModel.Container();
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(800, 450);
this.Text = "Form2";
}
#endregion
}
}
\ No newline at end of file \ No newline at end of file
此文件类型无法预览
此文件类型无法预览
此文件类型无法预览
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.6" />
</startup>
</configuration>
\ No newline at end of file \ No newline at end of file
此文件类型无法预览
// <autogenerated />
using System;
using System.Reflection;
[assembly: global::System.Runtime.Versioning.TargetFrameworkAttribute(".NETFramework,Version=v4.6", FrameworkDisplayName = ".NET Framework 4.6")]
C:\Users\Company\Documents\FaceControl\Test\bin\Debug\Test.exe.config
C:\Users\Company\Documents\FaceControl\Test\bin\Debug\Test.exe
C:\Users\Company\Documents\FaceControl\Test\bin\Debug\Test.pdb
C:\Users\Company\Documents\FaceControl\Test\bin\Debug\FaceControl.dll
C:\Users\Company\Documents\FaceControl\Test\bin\Debug\FaceControl.pdb
C:\Users\Company\Documents\FaceControl\Test\obj\Debug\Test.csprojAssemblyReference.cache
C:\Users\Company\Documents\FaceControl\Test\obj\Debug\Test.Form1.resources
C:\Users\Company\Documents\FaceControl\Test\obj\Debug\Test.Properties.Resources.resources
C:\Users\Company\Documents\FaceControl\Test\obj\Debug\Test.csproj.GenerateResource.cache
C:\Users\Company\Documents\FaceControl\Test\obj\Debug\Test.csproj.CoreCompileInputs.cache
C:\Users\Company\Documents\FaceControl\Test\obj\Debug\Test.csproj.CopyComplete
C:\Users\Company\Documents\FaceControl\Test\obj\Debug\Test.exe
C:\Users\Company\Documents\FaceControl\Test\obj\Debug\Test.pdb
C:\Neotel\Program_Beta\FaceControl\Test\bin\Debug\Test.exe.config
C:\Neotel\Program_Beta\FaceControl\Test\bin\Debug\Test.exe
C:\Neotel\Program_Beta\FaceControl\Test\bin\Debug\Test.pdb
C:\Neotel\Program_Beta\FaceControl\Test\bin\Debug\FaceControl.dll
C:\Neotel\Program_Beta\FaceControl\Test\bin\Debug\FaceControl.pdb
C:\Neotel\Program_Beta\FaceControl\Test\obj\Debug\Test.csprojAssemblyReference.cache
C:\Neotel\Program_Beta\FaceControl\Test\obj\Debug\Test.Form1.resources
C:\Neotel\Program_Beta\FaceControl\Test\obj\Debug\Test.Properties.Resources.resources
C:\Neotel\Program_Beta\FaceControl\Test\obj\Debug\Test.csproj.GenerateResource.cache
C:\Neotel\Program_Beta\FaceControl\Test\obj\Debug\Test.csproj.CoreCompileInputs.cache
C:\Neotel\Program_Beta\FaceControl\Test\obj\Debug\Test.csproj.CopyComplete
C:\Neotel\Program_Beta\FaceControl\Test\obj\Debug\Test.exe
C:\Neotel\Program_Beta\FaceControl\Test\obj\Debug\Test.pdb
此文件类型无法预览
此文件类型无法预览
<?xml version="1.0" encoding="utf-8" ?> <?xml version="1.0" encoding="utf-8" ?>
<configuration> <configuration>
<startup> <startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.6" /> <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.7.2" />
</startup> </startup>
</configuration> </configuration>
\ No newline at end of file \ No newline at end of file
 namespace WindowsFormsApp1
namespace FaceControl
{ {
partial class PanelBase partial class Form1
{ {
/// <summary> /// <summary>
/// 必需的设计器变量。 /// 必需的设计器变量。
/// </summary> /// </summary>
private System.ComponentModel.IContainer components = null; private System.ComponentModel.IContainer components = null;
/// <summary> /// <summary>
/// 清理所有正在使用的资源。 /// 清理所有正在使用的资源。
/// </summary> /// </summary>
/// <param name="disposing">如果应释放托管资源,为 true;否则为 false。</param> /// <param name="disposing">如果应释放托管资源,为 true;否则为 false。</param>
...@@ -21,17 +20,21 @@ namespace FaceControl ...@@ -21,17 +20,21 @@ namespace FaceControl
base.Dispose(disposing); base.Dispose(disposing);
} }
#region 组件设计器生成的代码 #region Windows 窗体设计器生成的代码
/// <summary> /// <summary>
/// 设计器支持所需的方法 - 不要修改 /// 设计器支持所需的方法 - 不要修改
/// 使用代码编辑器修改此方法的内容。 /// 使用代码编辑器修改此方法的内容。
/// </summary> /// </summary>
private void InitializeComponent() private void InitializeComponent()
{ {
components = new System.ComponentModel.Container(); this.components = new System.ComponentModel.Container();
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(800, 450);
this.Text = "Form1";
} }
#endregion #endregion
} }
} }
...@@ -8,11 +8,11 @@ using System.Text; ...@@ -8,11 +8,11 @@ using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
using System.Windows.Forms; using System.Windows.Forms;
namespace Test namespace WindowsFormsApp1
{ {
public partial class Form2 : FaceControl.FormNormal public partial class Form1 : Form
{ {
public Form2() public Form1()
{ {
InitializeComponent(); InitializeComponent();
} }
......
...@@ -4,7 +4,7 @@ using System.Linq; ...@@ -4,7 +4,7 @@ using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
using System.Windows.Forms; using System.Windows.Forms;
namespace Test namespace WindowsFormsApp1
{ {
static class Program static class Program
{ {
......
...@@ -5,12 +5,12 @@ using System.Runtime.InteropServices; ...@@ -5,12 +5,12 @@ using System.Runtime.InteropServices;
// 有关程序集的一般信息由以下 // 有关程序集的一般信息由以下
// 控制。更改这些特性值可修改 // 控制。更改这些特性值可修改
// 与程序集关联的信息。 // 与程序集关联的信息。
[assembly: AssemblyTitle("Test")] [assembly: AssemblyTitle("WindowsFormsApp1")]
[assembly: AssemblyDescription("")] [assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")] [assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")] [assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("Test")] [assembly: AssemblyProduct("WindowsFormsApp1")]
[assembly: AssemblyCopyright("Copyright © 2020")] [assembly: AssemblyCopyright("Copyright © 2021")]
[assembly: AssemblyTrademark("")] [assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")] [assembly: AssemblyCulture("")]
...@@ -20,7 +20,7 @@ using System.Runtime.InteropServices; ...@@ -20,7 +20,7 @@ using System.Runtime.InteropServices;
[assembly: ComVisible(false)] [assembly: ComVisible(false)]
// 如果此项目向 COM 公开,则下列 GUID 用于类型库的 ID // 如果此项目向 COM 公开,则下列 GUID 用于类型库的 ID
[assembly: Guid("30cc76c8-f637-4323-bd65-efe963de17e8")] [assembly: Guid("ad9f4add-a002-4ced-8fff-bce1b07538b0")]
// 程序集的版本信息由下列四个值组成: // 程序集的版本信息由下列四个值组成:
// //
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
// </auto-generated> // </auto-generated>
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
namespace Test.Properties namespace WindowsFormsApp1.Properties
{ {
...@@ -44,7 +44,7 @@ namespace Test.Properties ...@@ -44,7 +44,7 @@ namespace Test.Properties
{ {
if ((resourceMan == null)) if ((resourceMan == null))
{ {
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Test.Properties.Resources", typeof(Resources).Assembly); global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("WindowsFormsApp1.Properties.Resources", typeof(Resources).Assembly);
resourceMan = temp; resourceMan = temp;
} }
return resourceMan; return resourceMan;
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
// </auto-generated> // </auto-generated>
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
namespace Test.Properties namespace WindowsFormsApp1.Properties
{ {
......
...@@ -4,11 +4,11 @@ ...@@ -4,11 +4,11 @@
<PropertyGroup> <PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration> <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform> <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{30CC76C8-F637-4323-BD65-EFE963DE17E8}</ProjectGuid> <ProjectGuid>{AD9F4ADD-A002-4CED-8FFF-BCE1B07538B0}</ProjectGuid>
<OutputType>WinExe</OutputType> <OutputType>WinExe</OutputType>
<RootNamespace>Test</RootNamespace> <RootNamespace>WindowsFormsApp1</RootNamespace>
<AssemblyName>Test</AssemblyName> <AssemblyName>WindowsFormsApp1</AssemblyName>
<TargetFrameworkVersion>v4.6</TargetFrameworkVersion> <TargetFrameworkVersion>v4.7.2</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment> <FileAlignment>512</FileAlignment>
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects> <AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
<Deterministic>true</Deterministic> <Deterministic>true</Deterministic>
...@@ -52,17 +52,8 @@ ...@@ -52,17 +52,8 @@
<Compile Include="Form1.Designer.cs"> <Compile Include="Form1.Designer.cs">
<DependentUpon>Form1.cs</DependentUpon> <DependentUpon>Form1.cs</DependentUpon>
</Compile> </Compile>
<Compile Include="Form2.cs">
<SubType>Form</SubType>
</Compile>
<Compile Include="Form2.Designer.cs">
<DependentUpon>Form2.cs</DependentUpon>
</Compile>
<Compile Include="Program.cs" /> <Compile Include="Program.cs" />
<Compile Include="Properties\AssemblyInfo.cs" /> <Compile Include="Properties\AssemblyInfo.cs" />
<EmbeddedResource Include="Form1.resx">
<DependentUpon>Form1.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="Properties\Resources.resx"> <EmbeddedResource Include="Properties\Resources.resx">
<Generator>ResXFileCodeGenerator</Generator> <Generator>ResXFileCodeGenerator</Generator>
<LastGenOutput>Resources.Designer.cs</LastGenOutput> <LastGenOutput>Resources.Designer.cs</LastGenOutput>
...@@ -85,11 +76,5 @@ ...@@ -85,11 +76,5 @@
<ItemGroup> <ItemGroup>
<None Include="App.config" /> <None Include="App.config" />
</ItemGroup> </ItemGroup>
<ItemGroup>
<ProjectReference Include="..\FaceControl\FaceControl.csproj">
<Project>{06f6c6e6-02f6-4134-945a-be51beef58a4}</Project>
<Name>FaceControl</Name>
</ProjectReference>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
</Project> </Project>
\ No newline at end of file \ No newline at end of file
// <autogenerated /> // <autogenerated />
using System; using System;
using System.Reflection; using System.Reflection;
[assembly: global::System.Runtime.Versioning.TargetFrameworkAttribute(".NETFramework,Version=v4.6", FrameworkDisplayName = ".NET Framework 4.6")] [assembly: global::System.Runtime.Versioning.TargetFrameworkAttribute(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
支持 Markdown 格式
你添加了 0 到此讨论。请谨慎行事。
Finish editing this message first!