1、优化LOG显示与引用

2、添加PMA工具,工具内容待完善
3、修复流程树显示
4、添加开源项目,优化UI空间
5、其他BUG更改
This commit is contained in:
liu.wenjie
2021-11-23 15:51:37 +08:00
parent 47f77f5e64
commit a24dda2525
474 changed files with 91916 additions and 6429 deletions

View File

@@ -0,0 +1,537 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
namespace HZH_Controls.Controls
{
[ProvideProperty("UserCustomScrollbar", typeof(Control))]
public class ScrollbarComponent : Component, IExtenderProvider
{
public ScrollbarComponent()
{
}
public ScrollbarComponent(IContainer container)
{
container.Add(this);
}
Dictionary<Control, bool> m_controlCache = new Dictionary<Control, bool>();
public bool CanExtend(object extendee)
{
if (extendee is ScrollableControl)
{
ScrollableControl control = (ScrollableControl)extendee;
if (control.AutoScroll == true)
{
return true;
}
}
else if (extendee is TreeView)
{
TreeView control = (TreeView)extendee;
if (control.Scrollable)
{
return true;
}
}
else if (extendee is TextBox)
{
TextBox control = (TextBox)extendee;
if (control.Multiline && control.ScrollBars != ScrollBars.None)
{
return true;
}
}
return false;
}
[Browsable(true), Category("自定义属性"), Description("是否使用自定义滚动条"), DisplayName("UserCustomScrollbar"), Localizable(true)]
public bool GetUserCustomScrollbar(Control control)
{
if (m_controlCache.ContainsKey(control))
return m_controlCache[control];
return true;
}
public void SetUserCustomScrollbar(Control control, bool blnUserCustomScrollbar)
{
m_controlCache[control] = blnUserCustomScrollbar;
if (!blnUserCustomScrollbar)
return;
control.VisibleChanged += control_VisibleChanged;
control.SizeChanged += control_SizeChanged;
control.LocationChanged += control_LocationChanged;
control.Disposed += control_Disposed;
if (control is TreeView)
{
TreeView tv = (TreeView)control;
tv.MouseWheel += tv_MouseWheel;
tv.AfterSelect += tv_AfterSelect;
tv.AfterExpand += tv_AfterExpand;
tv.AfterCollapse += tv_AfterCollapse;
}
else if (control is TextBox)
{
TextBox txt = (TextBox)control;
txt.MouseWheel += txt_MouseWheel;
txt.TextChanged += txt_TextChanged;
txt.KeyDown += txt_KeyDown;
}
control_SizeChanged(control, null);
}
void control_Disposed(object sender, EventArgs e)
{
Control control = (Control)sender;
if (m_lstVCache.ContainsKey(control) && m_lstVCache[control].Parent != null)
{
m_lstVCache[control].Parent.Controls.Remove(m_lstVCache[control]);
m_lstVCache.Remove(control);
}
}
void control_LocationChanged(object sender, EventArgs e)
{
ResetScrollLocation(sender);
}
void control_SizeChanged(object sender, EventArgs e)
{
if (ControlHelper.IsDesignMode())
{
return;
}
else
{
var control = sender as Control;
bool blnHasVScrollbar = control.IsHandleCreated && (ControlHelper.GetWindowLong(control.Handle, STYLE) & VSCROLL) != 0;
bool blnHasHScrollbar = control.IsHandleCreated && (ControlHelper.GetWindowLong(control.Handle, STYLE) & HSCROLL) != 0;
if (blnHasVScrollbar)
{
if (!m_lstVCache.ContainsKey(control))
{
if (control.Parent != null)
{
UCVScrollbar barV = new UCVScrollbar();
barV.Width = SystemInformation.VerticalScrollBarWidth;
barV.Scroll += barV_Scroll;
m_lstVCache[control] = barV;
if (blnHasHScrollbar)
{
barV.Height = control.Height - barV.Width - 2;
}
else
{
barV.Height = control.Height - 2;
}
SetVMaxNum(control);
barV.Location = new System.Drawing.Point(control.Right - barV.Width - 1, control.Top + 1);
control.Parent.Controls.Add(barV);
int intControlIndex = control.Parent.Controls.GetChildIndex(control);
control.Parent.Controls.SetChildIndex(barV, intControlIndex);
}
}
else
{
SetVMaxNum(control);
}
}
else
{
if (m_lstVCache.ContainsKey(control) && m_lstVCache[control].Parent != null)
{
m_lstVCache[control].Parent.Controls.Remove(m_lstVCache[control]);
m_lstVCache.Remove(control);
}
}
if (blnHasHScrollbar)
{
if (!m_lstHCache.ContainsKey(control))
{
if (control.Parent != null)
{
UCHScrollbar barH = new UCHScrollbar();
barH.Height = SystemInformation.HorizontalScrollBarHeight;
barH.Scroll += barH_Scroll;
m_lstHCache[control] = barH;
if (blnHasHScrollbar)
{
barH.Width = control.Width - barH.Height - 2;
}
else
{
barH.Width = control.Width - 2;
}
SetHMaxNum(control);
barH.Location = new System.Drawing.Point(control.Left + 1, control.Bottom - barH.Height - 1);
control.Parent.Controls.Add(barH);
int intControlIndex = control.Parent.Controls.GetChildIndex(control);
control.Parent.Controls.SetChildIndex(barH, intControlIndex);
}
}
else
{
SetHMaxNum(control);
}
}
else
{
if (m_lstHCache.ContainsKey(control))
{
if (m_lstHCache[control].Visible && m_lstHCache[control].Parent != null)
{
m_lstHCache[control].Parent.Controls.Remove(m_lstHCache[control]);
}
}
}
}
ResetScrollLocation(sender);
}
private void SetVMaxNum(Control control)
{
if (!m_lstVCache.ContainsKey(control))
return;
var into = ControlHelper.GetVScrollBarInfo(control.Handle);
var intoH = ControlHelper.GetHScrollBarInfo(control.Handle);
UCVScrollbar barV = m_lstVCache[control];
if (control is ScrollableControl)
{
barV.Maximum = (control as ScrollableControl).VerticalScroll.Maximum;
barV.Value = (control as ScrollableControl).VerticalScroll.Value;
}
else if (control is TreeView)
{
barV.Maximum = GetTreeNodeMaxY(control as TreeView);
barV.Value = (control as TreeView).AutoScrollOffset.Y;
}
else if (control is TextBox)
{
TextBox txt = (TextBox)control;
int intTxtMaxHeight = 0;
int intTextHeight = 0;
using (var g = txt.CreateGraphics())
{
intTxtMaxHeight = (int)g.MeasureString(txt.Text, txt.Font).Height;
intTextHeight = (int)g.MeasureString(txt.Text.Substring(0, txt.SelectionStart), txt.Font).Height;
}
barV.Maximum = intTxtMaxHeight;
barV.Value = (control as TextBox).AutoScrollOffset.Y;
}
}
private void SetHMaxNum(Control control)
{
if (!m_lstHCache.ContainsKey(control))
return;
UCHScrollbar barH = m_lstHCache[control];
if (control is ScrollableControl)
{
barH.Maximum = (control as ScrollableControl).HorizontalScroll.Maximum;
barH.Value = (control as ScrollableControl).HorizontalScroll.Value;
}
else if (control is TreeView)
{
barH.Maximum = GetTreeNodeMaxX(control as TreeView);
barH.Value = (control as TreeView).AutoScrollOffset.X;
}
else if (control is TextBox)
{
TextBox txt = (TextBox)control;
int intTxtMaxWidth = 0;
int intTextWidth = 0;
using (var g = txt.CreateGraphics())
{
intTxtMaxWidth = (int)g.MeasureString(txt.Text, txt.Font).Width;
intTextWidth = (int)g.MeasureString(txt.Text.Substring(0, txt.SelectionStart), txt.Font).Width;
}
barH.Maximum = intTxtMaxWidth;
barH.Value = (control as TextBox).AutoScrollOffset.Y;
}
}
/// <summary>
/// Resets the v scroll location.
/// </summary>
/// <param name="sender">The sender.</param>
private void ResetScrollLocation(object sender)
{
Control control = (Control)sender;
bool blnHasVScrollbar = control.IsHandleCreated && (ControlHelper.GetWindowLong(control.Handle, STYLE) & VSCROLL) != 0;
bool blnHasHScrollbar = control.IsHandleCreated && (ControlHelper.GetWindowLong(control.Handle, STYLE) & HSCROLL) != 0;
if (control.Visible)
{
if (m_lstVCache.ContainsKey(control))
{
m_lstVCache[control].Location = new System.Drawing.Point(control.Right - m_lstVCache[control].Width - 1, control.Top + 1);
if (blnHasHScrollbar)
{
m_lstVCache[control].Height = control.Height - m_lstVCache[control].Width - 2;
}
else
{
m_lstVCache[control].Height = control.Height - 2;
}
}
if (m_lstHCache.ContainsKey(control))
{
m_lstHCache[control].Location = new System.Drawing.Point(control.Left + 1, control.Bottom - m_lstHCache[control].Height - 1);
if (blnHasHScrollbar)
{
m_lstHCache[control].Width = control.Width - m_lstHCache[control].Height - 2;
}
else
{
m_lstHCache[control].Width = control.Width - 2;
}
}
}
}
/// <summary>
/// Handles the VisibleChanged event of the control control.
/// </summary>
/// <param name="sender">The source of the event.</param>
/// <param name="e">The <see cref="EventArgs"/> instance containing the event data.</param>
void control_VisibleChanged(object sender, EventArgs e)
{
Control control = (Control)sender;
if (!control.Visible)
{
if (m_lstVCache.ContainsKey(control) && m_lstVCache[control].Parent != null)
{
m_lstVCache[control].Parent.Controls.Remove(m_lstVCache[control]);
m_lstVCache.Remove(control);
}
if (m_lstHCache.ContainsKey(control) && m_lstHCache[control].Parent != null)
{
m_lstHCache[control].Parent.Controls.Remove(m_lstHCache[control]);
m_lstHCache.Remove(control);
}
}
}
private const int HSCROLL = 0x100000;
private const int VSCROLL = 0x200000;
private const int STYLE = -16;
private Dictionary<Control, UCVScrollbar> m_lstVCache = new Dictionary<Control, UCVScrollbar>();
private Dictionary<Control, UCHScrollbar> m_lstHCache = new Dictionary<Control, UCHScrollbar>();
void barV_Scroll(object sender, EventArgs e)
{
UCVScrollbar bar = (UCVScrollbar)sender;
if (m_lstVCache.ContainsValue(bar))
{
Control c = m_lstVCache.FirstOrDefault(p => p.Value == bar).Key;
if (c is ScrollableControl)
{
(c as ScrollableControl).AutoScrollPosition = new Point((c as ScrollableControl).AutoScrollPosition.X, bar.Value);
}
else if (c is TreeView)
{
TreeView tv = (c as TreeView);
SetTreeViewVScrollLocation(tv, tv.Nodes, bar.Value);
}
else if (c is TextBox)
{
TextBox txt = (c as TextBox);
SetTextBoxVScrollLocation(txt, bar.Value);
}
}
}
void barH_Scroll(object sender, EventArgs e)
{
UCHScrollbar bar = (UCHScrollbar)sender;
if (m_lstHCache.ContainsValue(bar))
{
Control c = m_lstHCache.FirstOrDefault(p => p.Value == bar).Key;
if (c is ScrollableControl)
{
(c as ScrollableControl).AutoScrollPosition = new Point(bar.Value, (c as ScrollableControl).AutoScrollPosition.Y);
}
else if (c is TreeView)
{
//TreeView tv = (c as TreeView);
//SetTreeViewVScrollLocation(tv, tv.Nodes, bar.Value);
}
else if (c is TextBox)
{
//TextBox txt = (c as TextBox);
//SetTextBoxVScrollLocation(txt, bar.Value);
}
}
}
#region Treeview处理 English:Treeview\u5904\u7406
void tv_AfterCollapse(object sender, TreeViewEventArgs e)
{
control_SizeChanged(sender as Control, null);
}
void tv_AfterExpand(object sender, TreeViewEventArgs e)
{
control_SizeChanged(sender as Control, null);
}
/// <summary>
/// Gets the tree node 最大高度
/// </summary>
/// <param name="tv">The tv.</param>
/// <returns>System.Int32.</returns>
private int GetTreeNodeMaxY(TreeView tv)
{
TreeNode tnLast = tv.Nodes[tv.Nodes.Count - 1];
begin:
if (tnLast.IsExpanded && tnLast.Nodes.Count > 0)
{
tnLast = tnLast.LastNode;
goto begin;
}
return tnLast.Bounds.Bottom;
}
private int GetTreeNodeMaxX(TreeView tv)
{
return tv.Nodes.Count != 0 ? tv.Nodes[0].Bounds.Right : 0;
}
void tv_AfterSelect(object sender, TreeViewEventArgs e)
{
TreeView tv = (TreeView)sender;
if (m_lstVCache.ContainsKey(tv))
{
m_lstVCache[tv].Value = tv.Nodes.Count > 0 ? Math.Abs(tv.Nodes[0].Bounds.Top) : 0;
}
}
void tv_MouseWheel(object sender, MouseEventArgs e)
{
TreeView tv = (TreeView)sender;
if (m_lstVCache.ContainsKey(tv))
{
m_lstVCache[tv].Value = tv.Nodes.Count > 0 ? Math.Abs(tv.Nodes[0].Bounds.Top) : 0;
}
}
/// <summary>
/// Sets the TreeView scroll location.
/// </summary>
/// <param name="tv">The tv.</param>
/// <param name="tns">The TNS.</param>
/// <param name="intY">The int y.</param>
/// <returns><c>true</c> if XXXX, <c>false</c> otherwise.</returns>
private bool SetTreeViewVScrollLocation(TreeView tv, TreeNodeCollection tns, int intY)
{
for (int i = 0; i < tns.Count; i++)
{
if (intY >= tns[i].Bounds.Top - tv.Nodes[0].Bounds.Top - 3 && intY <= tns[i].Bounds.Bottom - tv.Nodes[0].Bounds.Top + 3)
{
tns[i].EnsureVisible();
return true;
}
else if (tns[i].IsExpanded && tns[i].Nodes.Count > 0)
{
bool bln = SetTreeViewVScrollLocation(tv, tns[i].Nodes, intY);
if (bln)
return true;
}
}
return false;
}
#endregion
#region TextBox处理 English:TextBox Processing
void txt_TextChanged(object sender, EventArgs e)
{
TextBox txt = sender as TextBox;
control_SizeChanged(txt, null);
SetVMaxNum(txt);
if (m_lstVCache.ContainsKey(txt))
{
using (var g = txt.CreateGraphics())
{
var size = g.MeasureString(txt.Text.Substring(0, txt.SelectionStart), txt.Font);
m_lstVCache[txt].Value = (int)size.Height;
}
}
}
private void SetTextBoxVScrollLocation(TextBox txt, int intY)
{
using (var g = txt.CreateGraphics())
{
for (int i = 0; i < txt.Lines.Length; i++)
{
string str = string.Join("\n", txt.Lines.Take(i + 1));
var size = g.MeasureString(str, txt.Font);
if (size.Height >= intY)
{
txt.SelectionStart = str.Length;
txt.ScrollToCaret();
return;
}
}
}
}
void txt_KeyDown(object sender, KeyEventArgs e)
{
if (e.KeyCode == Keys.Up || e.KeyCode == Keys.Down)
{
TextBox txt = (TextBox)sender;
if (m_lstVCache.ContainsKey(txt))
{
using (var g = txt.CreateGraphics())
{
var size = g.MeasureString(txt.Text.Substring(0, txt.SelectionStart), txt.Font);
m_lstVCache[txt].Value = (int)size.Height;
}
}
}
}
void txt_MouseWheel(object sender, MouseEventArgs e)
{
TextBox txt = (TextBox)sender;
if (m_lstVCache.ContainsKey(txt))
{
using (var g = txt.CreateGraphics())
{
StringBuilder str = new StringBuilder();
for (int i = 0; i < System.Windows.Forms.SystemInformation.MouseWheelScrollLines; i++)
{
str.AppendLine("A");
}
var height = (int)g.MeasureString(str.ToString(), txt.Font).Height;
if (e.Delta < 0)
{
if (height + m_lstVCache[txt].Value > m_lstVCache[txt].Maximum)
m_lstVCache[txt].Value = m_lstVCache[txt].Maximum;
else
m_lstVCache[txt].Value += height;
}
else
{
if (m_lstVCache[txt].Value - height < 0)
m_lstVCache[txt].Value = 0;
else
m_lstVCache[txt].Value -= height;
}
}
}
}
#endregion
}
}

View File

@@ -0,0 +1,43 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Windows.Forms.Design;
namespace HZH_Controls.Controls
{
/// <summary>
/// Class ScrollbarControlDesigner.
/// Implements the <see cref="System.Windows.Forms.Design.ControlDesigner" />
/// </summary>
/// <seealso cref="System.Windows.Forms.Design.ControlDesigner" />
internal class ScrollbarControlDesigner : System.Windows.Forms.Design.ControlDesigner
{
/// <summary>
/// 获取指示组件的移动功能的选择规则。
/// </summary>
/// <value>The selection rules.</value>
public override SelectionRules SelectionRules
{
get
{
SelectionRules selectionRules = base.SelectionRules;
PropertyDescriptor propDescriptor = TypeDescriptor.GetProperties(this.Component)["AutoSize"];
if (propDescriptor != null)
{
bool autoSize = (bool)propDescriptor.GetValue(this.Component);
if (autoSize)
{
selectionRules = SelectionRules.Visible | SelectionRules.Moveable | SelectionRules.BottomSizeable | SelectionRules.TopSizeable;
}
else
{
selectionRules = SelectionRules.Visible | SelectionRules.AllSizeable | SelectionRules.Moveable;
}
}
return selectionRules;
}
}
}
}

View File

@@ -0,0 +1,485 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
namespace HZH_Controls.Controls
{
[Designer(typeof(ScrollbarControlDesigner))]
[DefaultEvent("Scroll")]
public class UCHScrollbar : UCControlBase
{
#region English:attribute
/// <summary>
/// The mo large change
/// </summary>
protected int moLargeChange = 10;
/// <summary>
/// The mo small change
/// </summary>
protected int moSmallChange = 1;
/// <summary>
/// The mo minimum
/// </summary>
protected int moMinimum = 0;
/// <summary>
/// The mo maximum
/// </summary>
protected int moMaximum = 100;
/// <summary>
/// The mo value
/// </summary>
protected int moValue = 0;
/// <summary>
/// The n click point
/// </summary>
private int nClickPoint;
/// <summary>
/// The mo thumb top
/// </summary>
protected int moThumbLeft = 0;
/// <summary>
/// The mo automatic size
/// </summary>
protected bool moAutoSize = false;
/// <summary>
/// The mo thumb down
/// </summary>
private bool moThumbMouseDown = false;
/// <summary>
/// The mo thumb dragging
/// </summary>
private bool moThumbMouseDragging = false;
/// <summary>
/// Occurs when [scroll].
/// </summary>
public new event EventHandler Scroll = null;
/// <summary>
/// Occurs when [value changed].
/// </summary>
public event EventHandler ValueChanged = null;
/// <summary>
/// The BTN height
/// </summary>
private int btnWidth = 18;
/// <summary>
/// The m int thumb minimum height
/// </summary>
private int m_intThumbMinWidth = 15;
/// <summary>
/// Gets or sets the height of the BTN.
/// </summary>
/// <value>The height of the BTN.</value>
public int BtnWidth
{
get { return btnWidth; }
set { btnWidth = value; }
}
/// <summary>
/// Gets or sets the large change.
/// </summary>
/// <value>The large change.</value>
[EditorBrowsable(EditorBrowsableState.Always), Browsable(true), DefaultValue(false), Category("自定义"), Description("LargeChange")]
public int LargeChange
{
get { return moLargeChange; }
set
{
moLargeChange = value;
Invalidate();
}
}
/// <summary>
/// Gets or sets the small change.
/// </summary>
/// <value>The small change.</value>
[EditorBrowsable(EditorBrowsableState.Always), Browsable(true), DefaultValue(false), Category("自定义"), Description("SmallChange")]
public int SmallChange
{
get { return moSmallChange; }
set
{
moSmallChange = value;
Invalidate();
}
}
/// <summary>
/// Gets or sets the minimum.
/// </summary>
/// <value>The minimum.</value>
[EditorBrowsable(EditorBrowsableState.Always), Browsable(true), DefaultValue(false), Category("自定义"), Description("Minimum")]
public int Minimum
{
get { return moMinimum; }
set
{
moMinimum = value;
Invalidate();
}
}
/// <summary>
/// Gets or sets the maximum.
/// </summary>
/// <value>The maximum.</value>
[EditorBrowsable(EditorBrowsableState.Always), Browsable(true), DefaultValue(false), Category("自定义"), Description("Maximum")]
public int Maximum
{
get { return moMaximum; }
set
{
moMaximum = value;
Invalidate();
}
}
/// <summary>
/// Gets or sets the value.
/// </summary>
/// <value>The value.</value>
[EditorBrowsable(EditorBrowsableState.Always), Browsable(true), DefaultValue(false), Category("自定义"), Description("Value")]
public int Value
{
get { return moValue; }
set
{
moValue = value;
int nTrackWidth = (this.Width - btnWidth * 2);
float fThumbWidth = ((float)LargeChange / (float)Maximum) * nTrackWidth;
int nThumbWidth = (int)fThumbWidth;
if (nThumbWidth > nTrackWidth)
{
nThumbWidth = nTrackWidth;
fThumbWidth = nTrackWidth;
}
if (nThumbWidth < m_intThumbMinWidth)
{
nThumbWidth = m_intThumbMinWidth;
fThumbWidth = m_intThumbMinWidth;
}
//figure out value
int nPixelRange = nTrackWidth - nThumbWidth;
int nRealRange = (Maximum - Minimum) - LargeChange;
float fPerc = 0.0f;
if (nRealRange != 0)
{
fPerc = (float)moValue / (float)nRealRange;
}
float fLeft = fPerc * nPixelRange;
moThumbLeft = (int)fLeft;
Invalidate();
}
}
/// <summary>
/// Gets or sets a value indicating whether [automatic size].
/// </summary>
/// <value><c>true</c> if [automatic size]; otherwise, <c>false</c>.</value>
public override bool AutoSize
{
get
{
return base.AutoSize;
}
set
{
base.AutoSize = value;
if (base.AutoSize)
{
this.Width = 15;
}
}
}
/// <summary>
/// The thumb color
/// </summary>
private Color thumbColor = Color.FromArgb(255, 77, 58);
/// <summary>
/// Gets or sets the color of the thumb.
/// </summary>
/// <value>The color of the thumb.</value>
public Color ThumbColor
{
get { return thumbColor; }
set { thumbColor = value; }
}
#endregion
public UCHScrollbar()
{
InitializeComponent();
ConerRadius = 2;
FillColor = Color.FromArgb(239, 239, 239);
IsShowRect = false;
IsRadius = true;
this.SetStyle(ControlStyles.AllPaintingInWmPaint, true);
this.SetStyle(ControlStyles.DoubleBuffer, true);
this.SetStyle(ControlStyles.ResizeRedraw, true);
this.SetStyle(ControlStyles.Selectable, true);
this.SetStyle(ControlStyles.SupportsTransparentBackColor, true);
this.SetStyle(ControlStyles.UserPaint, true);
}
/// <summary>
/// Initializes the component.
/// </summary>
private void InitializeComponent()
{
this.SuspendLayout();
this.MinimumSize = new System.Drawing.Size(0, 10);
this.Name = "UCHScrollbar";
this.Size = new System.Drawing.Size(150, 18);
this.MouseDown += new System.Windows.Forms.MouseEventHandler(this.CustomScrollbar_MouseDown);
this.MouseMove += new System.Windows.Forms.MouseEventHandler(this.CustomScrollbar_MouseMove);
this.MouseUp += new System.Windows.Forms.MouseEventHandler(this.CustomScrollbar_MouseUp);
this.ResumeLayout(false);
}
#region English:Mouse event
/// <summary>
/// Handles the MouseDown event of the CustomScrollbar control.
/// </summary>
/// <param name="sender">The source of the event.</param>
/// <param name="e">The <see cref="MouseEventArgs"/> instance containing the event data.</param>
private void CustomScrollbar_MouseDown(object sender, MouseEventArgs e)
{
Point ptPoint = this.PointToClient(Cursor.Position);
int nTrackWidth = (this.Width - btnWidth * 2);
float fThumbWidth = ((float)LargeChange / (float)Maximum) * nTrackWidth;
int nThumbWidth = (int)fThumbWidth;
if (nThumbWidth > nTrackWidth)
{
nThumbWidth = nTrackWidth;
fThumbWidth = nTrackWidth;
}
if (nThumbWidth < m_intThumbMinWidth)
{
nThumbWidth = m_intThumbMinWidth;
fThumbWidth = m_intThumbMinWidth;
}
int nLeft = moThumbLeft;
nLeft += btnWidth;
Rectangle thumbrect = new Rectangle(new Point(nLeft, 1), new Size(nThumbWidth, this.Height - 2));
//滑块
if (thumbrect.Contains(ptPoint))
{
//hit the thumb
nClickPoint = (ptPoint.X - nLeft);
this.moThumbMouseDown = true;
}
else
{
//左按钮
Rectangle leftarrowrect = new Rectangle(new Point(0, 1), new Size(btnWidth, this.Height));
if (leftarrowrect.Contains(ptPoint))
{
int nRealRange = (Maximum - Minimum) - LargeChange;
int nPixelRange = (nTrackWidth - nThumbWidth);
if (nRealRange > 0)
{
if (nPixelRange > 0)
{
if ((moThumbLeft - SmallChange) < 0)
moThumbLeft = 0;
else
moThumbLeft -= SmallChange;
//figure out value
float fPerc = (float)moThumbLeft / (float)nPixelRange;
float fValue = fPerc * (Maximum - LargeChange);
moValue = (int)fValue;
if (ValueChanged != null)
ValueChanged(this, new EventArgs());
if (Scroll != null)
Scroll(this, new EventArgs());
Invalidate();
}
}
}
else
{
Rectangle rightarrowrect = new Rectangle(new Point(btnWidth + nTrackWidth, 1), new Size(btnWidth, this.Height));
if (rightarrowrect.Contains(ptPoint))
{
int nRealRange = (Maximum - Minimum) - LargeChange;
int nPixelRange = (nTrackWidth - nThumbWidth);
if (nRealRange > 0)
{
if (nPixelRange > 0)
{
if ((moThumbLeft + SmallChange) > nPixelRange)
moThumbLeft = nPixelRange;
else
moThumbLeft += SmallChange;
//figure out value
float fPerc = (float)moThumbLeft / (float)nPixelRange;
float fValue = fPerc * (Maximum - LargeChange);
moValue = (int)fValue;
if (ValueChanged != null)
ValueChanged(this, new EventArgs());
if (Scroll != null)
Scroll(this, new EventArgs());
Invalidate();
}
}
}
}
}
}
/// <summary>
/// Handles the MouseUp event of the CustomScrollbar control.
/// </summary>
/// <param name="sender">The source of the event.</param>
/// <param name="e">The <see cref="MouseEventArgs"/> instance containing the event data.</param>
private void CustomScrollbar_MouseUp(object sender, MouseEventArgs e)
{
this.moThumbMouseDown = false;
this.moThumbMouseDragging = false;
}
/// <summary>
/// Moves the thumb.
/// </summary>
/// <param name="x">The y.</param>
private void MoveThumb(int x)
{
int nRealRange = Maximum - Minimum;
int nTrackWidth = (this.Width - btnWidth * 2);
float fThumbWidth = ((float)LargeChange / (float)Maximum) * nTrackWidth;
int nThumbWidth = (int)fThumbWidth;
if (nThumbWidth > nTrackWidth)
{
nThumbWidth = nTrackWidth;
fThumbWidth = nTrackWidth;
}
if (nThumbWidth < m_intThumbMinWidth)
{
nThumbWidth = m_intThumbMinWidth;
fThumbWidth = m_intThumbMinWidth;
}
int nSpot = nClickPoint;
int nPixelRange = (nTrackWidth - nThumbWidth);
if (moThumbMouseDown && nRealRange > 0)
{
if (nPixelRange > 0)
{
int nNewThumbLeft = x - (btnWidth + nSpot);
if (nNewThumbLeft < 0)
{
moThumbLeft = nNewThumbLeft = 0;
}
else if (nNewThumbLeft > nPixelRange)
{
moThumbLeft = nNewThumbLeft = nPixelRange;
}
else
{
moThumbLeft = x - (btnWidth + nSpot);
}
float fPerc = (float)moThumbLeft / (float)nPixelRange;
float fValue = fPerc * (Maximum - LargeChange);
moValue = (int)fValue;
Application.DoEvents();
Invalidate();
}
}
}
/// <summary>
/// Handles the MouseMove event of the CustomScrollbar control.
/// </summary>
/// <param name="sender">The source of the event.</param>
/// <param name="e">The <see cref="MouseEventArgs"/> instance containing the event data.</param>
private void CustomScrollbar_MouseMove(object sender, MouseEventArgs e)
{
if (!moThumbMouseDown)
return;
if (moThumbMouseDown == true)
{
this.moThumbMouseDragging = true;
}
if (this.moThumbMouseDragging)
{
MoveThumb(e.X);
}
if (ValueChanged != null)
ValueChanged(this, new EventArgs());
if (Scroll != null)
Scroll(this, new EventArgs());
}
#endregion
protected override void OnPaint(PaintEventArgs e)
{
base.OnPaint(e);
e.Graphics.SetGDIHigh();
//draw thumb
int nTrackWidth = (this.Width - btnWidth * 2);
float fThumbWidth = ((float)LargeChange / (float)Maximum) * nTrackWidth;
int nThumbWidth = (int)fThumbWidth;
if (nThumbWidth > nTrackWidth)
{
nThumbWidth = nTrackWidth;
fThumbWidth = nTrackWidth;
}
if (nThumbWidth < m_intThumbMinWidth)
{
nThumbWidth = m_intThumbMinWidth;
fThumbWidth = m_intThumbMinWidth;
}
int nLeft = moThumbLeft;
nLeft += btnWidth;
e.Graphics.FillPath(new SolidBrush(thumbColor), new Rectangle(nLeft, 1, nThumbWidth, this.Height - 3).CreateRoundedRectanglePath(this.ConerRadius));
ControlHelper.PaintTriangle(e.Graphics, new SolidBrush(thumbColor), new Point(btnWidth - Math.Min(5, this.Height / 2), this.Height / 2), Math.Min(5, this.Height / 2), GraphDirection.Leftward);
ControlHelper.PaintTriangle(e.Graphics, new SolidBrush(thumbColor), new Point(this.Width - (btnWidth - Math.Min(5, this.Height / 2)), this.Height / 2), Math.Min(5, this.Height / 2), GraphDirection.Rightward);
}
}
}

View File

@@ -0,0 +1,520 @@
// ***********************************************************************
// Assembly : HZH_Controls
// Created : 2019-09-19
//
// ***********************************************************************
// <copyright file="UCVScrollbar.cs">
// Copyright by Huang Zhenghui(黄正辉) All, QQ group:568015492 QQ:623128629 Email:623128629@qq.com
// </copyright>
//
// Blog: https://www.cnblogs.com/bfyx
// GitHubhttps://github.com/kwwwvagaa/NetWinformControl
// giteehttps://gitee.com/kwwwvagaa/net_winform_custom_control.git
//
// If you use this code, please keep this note.
// ***********************************************************************
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Text;
using System.Windows.Forms;
using System.Windows.Forms.Design;
using System.Diagnostics;
namespace HZH_Controls.Controls
{
/// <summary>
/// Class UCVScrollbar.
/// Implements the <see cref="HZH_Controls.Controls.UCControlBase" />
/// </summary>
/// <seealso cref="HZH_Controls.Controls.UCControlBase" />
[Designer(typeof(ScrollbarControlDesigner))]
[DefaultEvent("Scroll")]
public class UCVScrollbar : UCControlBase
{
/// <summary>
/// The mo large change
/// </summary>
protected int moLargeChange = 10;
/// <summary>
/// The mo small change
/// </summary>
protected int moSmallChange = 1;
/// <summary>
/// The mo minimum
/// </summary>
protected int moMinimum = 0;
/// <summary>
/// The mo maximum
/// </summary>
protected int moMaximum = 100;
/// <summary>
/// The mo value
/// </summary>
protected int moValue = 0;
/// <summary>
/// The n click point
/// </summary>
private int nClickPoint;
/// <summary>
/// The mo thumb top
/// </summary>
protected int moThumbTop = 0;
/// <summary>
/// The mo automatic size
/// </summary>
protected bool moAutoSize = false;
/// <summary>
/// The mo thumb down
/// </summary>
private bool moThumbMouseDown = false;
/// <summary>
/// The mo thumb dragging
/// </summary>
private bool moThumbMouseDragging = false;
/// <summary>
/// Occurs when [scroll].
/// </summary>
public new event EventHandler Scroll = null;
/// <summary>
/// Occurs when [value changed].
/// </summary>
public event EventHandler ValueChanged = null;
/// <summary>
/// The BTN height
/// </summary>
private int btnHeight = 18;
/// <summary>
/// The m int thumb minimum height
/// </summary>
private int m_intThumbMinHeight = 15;
/// <summary>
/// Gets or sets the height of the BTN.
/// </summary>
/// <value>The height of the BTN.</value>
public int BtnHeight
{
get { return btnHeight; }
set { btnHeight = value; }
}
/// <summary>
/// Gets or sets the large change.
/// </summary>
/// <value>The large change.</value>
[EditorBrowsable(EditorBrowsableState.Always), Browsable(true), DefaultValue(false), Category("自定义"), Description("LargeChange")]
public int LargeChange
{
get { return moLargeChange; }
set
{
moLargeChange = value;
Invalidate();
}
}
/// <summary>
/// Gets or sets the small change.
/// </summary>
/// <value>The small change.</value>
[EditorBrowsable(EditorBrowsableState.Always), Browsable(true), DefaultValue(false), Category("自定义"), Description("SmallChange")]
public int SmallChange
{
get { return moSmallChange; }
set
{
moSmallChange = value;
Invalidate();
}
}
/// <summary>
/// Gets or sets the minimum.
/// </summary>
/// <value>The minimum.</value>
[EditorBrowsable(EditorBrowsableState.Always), Browsable(true), DefaultValue(false), Category("自定义"), Description("Minimum")]
public int Minimum
{
get { return moMinimum; }
set
{
moMinimum = value;
Invalidate();
}
}
/// <summary>
/// Gets or sets the maximum.
/// </summary>
/// <value>The maximum.</value>
[EditorBrowsable(EditorBrowsableState.Always), Browsable(true), DefaultValue(false), Category("自定义"), Description("Maximum")]
public int Maximum
{
get { return moMaximum; }
set
{
moMaximum = value;
Invalidate();
}
}
/// <summary>
/// Gets or sets the value.
/// </summary>
/// <value>The value.</value>
[EditorBrowsable(EditorBrowsableState.Always), Browsable(true), DefaultValue(false), Category("自定义"), Description("Value")]
public int Value
{
get { return moValue; }
set
{
moValue = value;
int nTrackHeight = (this.Height - btnHeight * 2);
float fThumbHeight = ((float)LargeChange / (float)Maximum) * nTrackHeight;
int nThumbHeight = (int)fThumbHeight;
if (nThumbHeight > nTrackHeight)
{
nThumbHeight = nTrackHeight;
fThumbHeight = nTrackHeight;
}
if (nThumbHeight < m_intThumbMinHeight)
{
nThumbHeight = m_intThumbMinHeight;
fThumbHeight = m_intThumbMinHeight;
}
//figure out value
int nPixelRange = nTrackHeight - nThumbHeight;
int nRealRange = (Maximum - Minimum) - LargeChange;
float fPerc = 0.0f;
if (nRealRange != 0)
{
fPerc = (float)moValue / (float)nRealRange;
}
float fTop = fPerc * nPixelRange;
moThumbTop = (int)fTop;
Invalidate();
}
}
/// <summary>
/// Gets or sets a value indicating whether [automatic size].
/// </summary>
/// <value><c>true</c> if [automatic size]; otherwise, <c>false</c>.</value>
public override bool AutoSize
{
get
{
return base.AutoSize;
}
set
{
base.AutoSize = value;
if (base.AutoSize)
{
this.Width = 15;
}
}
}
/// <summary>
/// The thumb color
/// </summary>
private Color thumbColor = Color.FromArgb(255, 77, 58);
/// <summary>
/// Gets or sets the color of the thumb.
/// </summary>
/// <value>The color of the thumb.</value>
public Color ThumbColor
{
get { return thumbColor; }
set { thumbColor = value; }
}
/// <summary>
/// Initializes a new instance of the <see cref="UCVScrollbar"/> class.
/// </summary>
public UCVScrollbar()
{
InitializeComponent();
ConerRadius = 2;
FillColor = Color.FromArgb(239, 239, 239);
IsShowRect = false;
IsRadius = true;
this.SetStyle(ControlStyles.AllPaintingInWmPaint, true);
this.SetStyle(ControlStyles.DoubleBuffer, true);
this.SetStyle(ControlStyles.ResizeRedraw, true);
this.SetStyle(ControlStyles.Selectable, true);
this.SetStyle(ControlStyles.SupportsTransparentBackColor, true);
this.SetStyle(ControlStyles.UserPaint, true);
}
/// <summary>
/// Initializes the component.
/// </summary>
private void InitializeComponent()
{
this.SuspendLayout();
//
// UCVScrollbar
//
this.MinimumSize = new System.Drawing.Size(10, 0);
this.Name = "UCVScrollbar";
this.Size = new System.Drawing.Size(18, 150);
this.MouseDown += new System.Windows.Forms.MouseEventHandler(this.CustomScrollbar_MouseDown);
this.MouseMove += new System.Windows.Forms.MouseEventHandler(this.CustomScrollbar_MouseMove);
this.MouseUp += new System.Windows.Forms.MouseEventHandler(this.CustomScrollbar_MouseUp);
this.ResumeLayout(false);
}
/// <summary>
/// 引发 <see cref="E:System.Windows.Forms.Control.Paint" /> 事件。
/// </summary>
/// <param name="e">包含事件数据的 <see cref="T:System.Windows.Forms.PaintEventArgs" />。</param>
protected override void OnPaint(PaintEventArgs e)
{
base.OnPaint(e);
e.Graphics.SetGDIHigh();
//draw thumb
int nTrackHeight = (this.Height - btnHeight * 2);
float fThumbHeight = ((float)LargeChange / (float)Maximum) * nTrackHeight;
int nThumbHeight = (int)fThumbHeight;
if (nThumbHeight > nTrackHeight)
{
nThumbHeight = nTrackHeight;
fThumbHeight = nTrackHeight;
}
if (nThumbHeight < m_intThumbMinHeight)
{
nThumbHeight = m_intThumbMinHeight;
fThumbHeight = m_intThumbMinHeight;
}
int nTop = moThumbTop;
nTop += btnHeight;
e.Graphics.FillPath(new SolidBrush(thumbColor), new Rectangle(1, nTop, this.Width - 3, nThumbHeight).CreateRoundedRectanglePath(this.ConerRadius));
ControlHelper.PaintTriangle(e.Graphics, new SolidBrush(thumbColor), new Point(this.Width / 2, btnHeight - Math.Min(5, this.Width / 2)), Math.Min(5, this.Width / 2), GraphDirection.Upward);
ControlHelper.PaintTriangle(e.Graphics, new SolidBrush(thumbColor), new Point(this.Width / 2, this.Height - (btnHeight - Math.Min(5, this.Width / 2))), Math.Min(5, this.Width / 2), GraphDirection.Downward);
}
/// <summary>
/// Handles the MouseDown event of the CustomScrollbar control.
/// </summary>
/// <param name="sender">The source of the event.</param>
/// <param name="e">The <see cref="MouseEventArgs"/> instance containing the event data.</param>
private void CustomScrollbar_MouseDown(object sender, MouseEventArgs e)
{
Point ptPoint = this.PointToClient(Cursor.Position);
int nTrackHeight = (this.Height - btnHeight * 2);
float fThumbHeight = ((float)LargeChange / (float)Maximum) * nTrackHeight;
int nThumbHeight = (int)fThumbHeight;
if (nThumbHeight > nTrackHeight)
{
nThumbHeight = nTrackHeight;
fThumbHeight = nTrackHeight;
}
if (nThumbHeight < m_intThumbMinHeight)
{
nThumbHeight = m_intThumbMinHeight;
fThumbHeight = m_intThumbMinHeight;
}
int nTop = moThumbTop;
nTop += btnHeight;
Rectangle thumbrect = new Rectangle(new Point(1, nTop), new Size(this.Width - 2, nThumbHeight));
if (thumbrect.Contains(ptPoint))
{
//hit the thumb
nClickPoint = (ptPoint.Y - nTop);
//MessageBox.Show(Convert.ToString((ptPoint.Y - nTop)));
this.moThumbMouseDown = true;
}
else
{
Rectangle uparrowrect = new Rectangle(new Point(1, 0), new Size(this.Width, btnHeight));
if (uparrowrect.Contains(ptPoint))
{
int nRealRange = (Maximum - Minimum) - LargeChange;
int nPixelRange = (nTrackHeight - nThumbHeight);
if (nRealRange > 0)
{
if (nPixelRange > 0)
{
if ((moThumbTop - SmallChange) < 0)
moThumbTop = 0;
else
moThumbTop -= SmallChange;
//figure out value
float fPerc = (float)moThumbTop / (float)nPixelRange;
float fValue = fPerc * (Maximum - LargeChange);
moValue = (int)fValue;
if (ValueChanged != null)
ValueChanged(this, new EventArgs());
if (Scroll != null)
Scroll(this, new EventArgs());
Invalidate();
}
}
}
else
{
Rectangle downarrowrect = new Rectangle(new Point(1, btnHeight + nTrackHeight), new Size(this.Width, btnHeight));
if (downarrowrect.Contains(ptPoint))
{
int nRealRange = (Maximum - Minimum) - LargeChange;
int nPixelRange = (nTrackHeight - nThumbHeight);
if (nRealRange > 0)
{
if (nPixelRange > 0)
{
if ((moThumbTop + SmallChange) > nPixelRange)
moThumbTop = nPixelRange;
else
moThumbTop += SmallChange;
//figure out value
float fPerc = (float)moThumbTop / (float)nPixelRange;
float fValue = fPerc * (Maximum - LargeChange);
moValue = (int)fValue;
if (ValueChanged != null)
ValueChanged(this, new EventArgs());
if (Scroll != null)
Scroll(this, new EventArgs());
Invalidate();
}
}
}
}
}
}
/// <summary>
/// Handles the MouseUp event of the CustomScrollbar control.
/// </summary>
/// <param name="sender">The source of the event.</param>
/// <param name="e">The <see cref="MouseEventArgs"/> instance containing the event data.</param>
private void CustomScrollbar_MouseUp(object sender, MouseEventArgs e)
{
this.moThumbMouseDown = false;
this.moThumbMouseDragging = false;
}
/// <summary>
/// Moves the thumb.
/// </summary>
/// <param name="y">The y.</param>
private void MoveThumb(int y)
{
int nRealRange = Maximum - Minimum;
int nTrackHeight = (this.Height - btnHeight * 2);
float fThumbHeight = ((float)LargeChange / (float)Maximum) * nTrackHeight;
int nThumbHeight = (int)fThumbHeight;
if (nThumbHeight > nTrackHeight)
{
nThumbHeight = nTrackHeight;
fThumbHeight = nTrackHeight;
}
if (nThumbHeight < m_intThumbMinHeight)
{
nThumbHeight = m_intThumbMinHeight;
fThumbHeight = m_intThumbMinHeight;
}
int nSpot = nClickPoint;
int nPixelRange = (nTrackHeight - nThumbHeight);
if (moThumbMouseDown && nRealRange > 0)
{
if (nPixelRange > 0)
{
int nNewThumbTop = y - (btnHeight + nSpot);
if (nNewThumbTop < 0)
{
moThumbTop = nNewThumbTop = 0;
}
else if (nNewThumbTop > nPixelRange)
{
moThumbTop = nNewThumbTop = nPixelRange;
}
else
{
moThumbTop = y - (btnHeight + nSpot);
}
float fPerc = (float)moThumbTop / (float)nPixelRange;
float fValue = fPerc * (Maximum - LargeChange);
moValue = (int)fValue;
Application.DoEvents();
Invalidate();
}
}
}
/// <summary>
/// Handles the MouseMove event of the CustomScrollbar control.
/// </summary>
/// <param name="sender">The source of the event.</param>
/// <param name="e">The <see cref="MouseEventArgs"/> instance containing the event data.</param>
private void CustomScrollbar_MouseMove(object sender, MouseEventArgs e)
{
if (!moThumbMouseDown)
return;
if (moThumbMouseDown == true)
{
this.moThumbMouseDragging = true;
}
if (this.moThumbMouseDragging)
{
MoveThumb(e.Y);
}
if (ValueChanged != null)
ValueChanged(this, new EventArgs());
if (Scroll != null)
Scroll(this, new EventArgs());
}
}
}

View File

@@ -0,0 +1,120 @@
<?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>