// COPYRIGHT (C) Tom. ALL RIGHTS RESERVED.
|
// THE AntdUI PROJECT IS AN WINFORM LIBRARY LICENSED UNDER THE Apache-2.0 License.
|
// LICENSED UNDER THE Apache License, VERSION 2.0 (THE "License")
|
// YOU MAY NOT USE THIS FILE EXCEPT IN COMPLIANCE WITH THE License.
|
// YOU MAY OBTAIN A COPY OF THE LICENSE AT
|
//
|
// http://www.apache.org/licenses/LICENSE-2.0
|
//
|
// UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING, SOFTWARE
|
// DISTRIBUTED UNDER THE LICENSE IS DISTRIBUTED ON AN "AS IS" BASIS,
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
// SEE THE LICENSE FOR THE SPECIFIC LANGUAGE GOVERNING PERMISSIONS AND
|
// LIMITATIONS UNDER THE License.
|
// GITEE: https://gitee.com/antdui/AntdUI
|
// GITHUB: https://github.com/AntdUI/AntdUI
|
// CSDN: https://blog.csdn.net/v_132
|
// QQ: 17379620
|
|
using System;
|
using System.Drawing;
|
using System.Drawing.Drawing2D;
|
using System.Windows.Forms;
|
|
namespace AntdUI
|
{
|
partial class Input
|
{
|
#region 渲染
|
|
StringFormat sf_font = Helper.SF_MEASURE_FONT();
|
internal StringFormat sf_center = Helper.SF_NoWrap();
|
internal StringFormat sf_placeholder = Helper.SF_ALL(lr: StringAlignment.Near);
|
|
internal Action? TakePaint;
|
public new void Invalidate()
|
{
|
if (TakePaint == null) base.Invalidate();
|
else TakePaint();
|
}
|
protected override void OnPaint(PaintEventArgs e)
|
{
|
var _rect = ClientRectangle;
|
if (_rect.Width > 0 && _rect.Height > 0)
|
{
|
Rectangle rect = _rect.PaddingRect(Padding), rect_read = rect.ReadRect((WaveSize + borderWidth / 2F) * Config.Dpi, JoinLeft, JoinRight);
|
IPaint(e.Graphics.High(), rect, rect_read);
|
}
|
base.OnPaint(e);
|
}
|
|
internal void IPaint(Graphics g, Rectangle rect, Rectangle rect_read)
|
{
|
float _radius = round ? rect_read.Height : radius * Config.Dpi;
|
bool enabled = Enabled;
|
if (backImage != null) g.PaintImg(rect_read, backImage, backFit, _radius, false);
|
using (var path = Path(rect_read, _radius))
|
{
|
Color _back = back ?? Style.Db.BgContainer,
|
_fore = fore ?? Style.Db.Text,
|
_border = borderColor ?? Style.Db.BorderColor,
|
_borderHover = BorderHover ?? Style.Db.PrimaryHover,
|
_borderActive = BorderActive ?? Style.Db.Primary;
|
|
switch (status)
|
{
|
case TType.Success:
|
_border = Style.Db.SuccessBorder;
|
_borderHover = Style.Db.SuccessHover;
|
_borderActive = Style.Db.Success;
|
break;
|
case TType.Error:
|
_border = Style.Db.ErrorBorder;
|
_borderHover = Style.Db.ErrorHover;
|
_borderActive = Style.Db.Error;
|
break;
|
case TType.Warn:
|
_border = Style.Db.WarningBorder;
|
_borderHover = Style.Db.WarningHover;
|
_borderActive = Style.Db.Warning;
|
break;
|
}
|
|
PaintClick(g, path, rect, _borderActive, _radius);
|
|
if (enabled)
|
{
|
using (var brush = backExtend.BrushEx(rect_read, _back))
|
{
|
g.FillPath(brush, path);
|
}
|
PaintIcon(g, _fore);
|
PaintText(g, _fore, rect_read.Right, rect_read.Bottom);
|
PaintOtherBor(g, rect_read, _radius, _back, _border, _borderActive);
|
PaintScroll(g, rect_read, _radius);
|
if (borderWidth > 0)
|
{
|
if (AnimationHover)
|
{
|
using (var brush = new Pen(_border, borderWidth))
|
{
|
g.DrawPath(brush, path);
|
}
|
using (var brush = new Pen(Helper.ToColor(AnimationHoverValue, _borderHover), borderWidth))
|
{
|
g.DrawPath(brush, path);
|
}
|
}
|
else if (ExtraMouseDown)
|
{
|
using (var brush = new Pen(_borderActive, borderWidth))
|
{
|
g.DrawPath(brush, path);
|
}
|
}
|
else if (ExtraMouseHover)
|
{
|
using (var brush = new Pen(_borderHover, borderWidth))
|
{
|
g.DrawPath(brush, path);
|
}
|
}
|
else
|
{
|
using (var brush = new Pen(_border, borderWidth))
|
{
|
g.DrawPath(brush, path);
|
}
|
}
|
}
|
}
|
else
|
{
|
using (var brush = new SolidBrush(Style.Db.FillTertiary))
|
{
|
g.FillPath(brush, path);
|
}
|
PaintIcon(g, Style.Db.TextQuaternary);
|
PaintText(g, Style.Db.TextQuaternary, rect_read.Right, rect_read.Bottom);
|
PaintOtherBor(g, rect_read, _radius, _back, _border, _borderActive);
|
PaintScroll(g, rect_read, _radius);
|
if (borderWidth > 0)
|
{
|
using (var brush = new Pen(_border, borderWidth))
|
{
|
g.DrawPath(brush, path);
|
}
|
}
|
}
|
}
|
}
|
|
void PaintScroll(Graphics g, Rectangle rect_read, float _radius)
|
{
|
if (ScrollYShow && autoscroll)
|
{
|
int SIZE = 20;
|
|
ScrollRect = new Rectangle(rect_read.Right - SIZE, rect_read.Y, SIZE, rect_read.Height);
|
using (var brush = new SolidBrush(Color.FromArgb(10, Style.Db.TextBase)))
|
{
|
if (JoinRight) g.FillRectangle(brush, ScrollRect);
|
else
|
{
|
using (var pathScroll = Helper.RoundPath(ScrollRect, _radius, false, true, true, false))
|
{
|
g.FillPath(brush, pathScroll);
|
}
|
}
|
}
|
|
float val = scrolly, VrValue = ScrollYMax + ScrollRect.Height;
|
float height = ((ScrollRect.Height / VrValue) * ScrollRect.Height) - 20;
|
if (height < SIZE) height = SIZE;
|
float y = val == 0 ? 0 : (val / (VrValue - ScrollRect.Height)) * (ScrollRect.Height - height);
|
if (ScrollHover) ScrollSlider = new RectangleF(ScrollRect.X + 6, ScrollRect.Y + y, 8, height);
|
else ScrollSlider = new RectangleF(ScrollRect.X + 7, ScrollRect.Y + y, 6, height);
|
if (ScrollSlider.Y < 10) ScrollSlider.Y = 10;
|
else if (ScrollSlider.Y > ScrollRect.Height - height - 6) ScrollSlider.Y = ScrollRect.Height - height - 6;
|
using (var brush = new SolidBrush(Color.FromArgb(141, Style.Db.TextBase)))
|
{
|
using (var path = ScrollSlider.RoundPath(ScrollSlider.Width))
|
{
|
g.FillPath(brush, path);
|
}
|
}
|
}
|
}
|
|
#region 渲染帮助
|
|
void PaintIcon(Graphics g, Color _fore)
|
{
|
if (prefixText != null)
|
{
|
using (var fore = new SolidBrush(_fore))
|
{
|
g.DrawStr(prefixText, Font, fore, rect_l, sf_center);
|
}
|
}
|
else if (prefixSvg != null)
|
{
|
using (var _bmp = SvgExtend.GetImgExtend(prefixSvg, rect_l, fore ?? Style.Db.Text))
|
{
|
if (_bmp != null) g.DrawImage(_bmp, rect_l);
|
}
|
}
|
else if (prefix != null) g.DrawImage(prefix, rect_l);
|
|
if (is_clear)
|
{
|
using (var bmp = SvgExtend.GetImgExtend(SvgDb.IcoError, rect_r, hover_clear ? Style.Db.TextTertiary : Style.Db.TextQuaternary))
|
{
|
if (bmp != null) g.DrawImage(bmp, rect_r);
|
}
|
}
|
else if (suffixText != null)
|
{
|
using (var fore = new SolidBrush(_fore))
|
{
|
g.DrawStr(suffixText, Font, fore, rect_r, sf_center);
|
}
|
}
|
else if (suffixSvg != null)
|
{
|
using (var _bmp = SvgExtend.GetImgExtend(suffixSvg, rect_r, fore ?? Style.Db.Text))
|
{
|
if (_bmp != null) g.DrawImage(_bmp, rect_r);
|
}
|
}
|
else if (suffix != null) g.DrawImage(suffix, rect_r);
|
else PaintRIcon(g, rect_r);
|
}
|
|
void PaintText(Graphics g, Color _fore, int w, int h)
|
{
|
if (multiline) g.SetClip(rect_text);
|
else if (RECTDIV.HasValue) g.SetClip(RECTDIV.Value);
|
else g.SetClip(new Rectangle(rect_text.X, 0, rect_text.Width, Height));
|
if (cache_font != null)
|
{
|
g.TranslateTransform(-ScrollX, -ScrollY);
|
PaintTextSelected(g, cache_font);
|
using (var fore = new SolidBrush(_fore))
|
{
|
if (HasEmoji)
|
{
|
using (var font = new Font(EmojiFont, Font.Size))
|
{
|
foreach (var it in cache_font)
|
{
|
it.show = it.rect.Y > ScrollY - it.rect.Height && it.rect.Bottom < ScrollY + h + it.rect.Height;
|
if (it.show)
|
{
|
if (IsPassWord) g.DrawStr(PassWordChar, Font, fore, it.rect, sf_font);
|
else if (it.emoji) g.DrawStr(it.text, font, fore, it.rect, sf_font);
|
else g.DrawStr(it.text, Font, fore, it.rect, sf_font);
|
}
|
}
|
}
|
}
|
else
|
{
|
foreach (var it in cache_font)
|
{
|
it.show = it.rect.Y > ScrollY - it.rect.Height && it.rect.Bottom < ScrollY + h + it.rect.Height;
|
if (it.show)
|
{
|
if (IsPassWord) g.DrawStr(PassWordChar, Font, fore, it.rect, sf_font);
|
else g.DrawStr(it.text, Font, fore, it.rect, sf_font);
|
}
|
}
|
}
|
}
|
g.ResetTransform();
|
}
|
else if (placeholderText != null && ShowPlaceholder)
|
{
|
using (var fore = placeholderColorExtend.BrushEx(rect_text, placeholderColor ?? Style.Db.TextQuaternary))
|
{
|
g.DrawStr(placeholderText, Font, fore, rect_text, sf_placeholder);
|
}
|
}
|
g.ResetClip();
|
if (showCaret && showCaretFlag)
|
{
|
g.TranslateTransform(-ScrollX, -ScrollY);
|
using (var brush = new SolidBrush(CaretColor ?? _fore))
|
{
|
g.FillRectangle(brush, CurrentCaret);
|
}
|
g.ResetTransform();
|
}
|
}
|
void PaintTextSelected(Graphics g, CacheFont[] cache_font)
|
{
|
if (selectionLength > 0 && cache_font.Length > selectionStartTemp && !BanInput)
|
{
|
try
|
{
|
int start = selectionStartTemp, end = start + selectionLength - 1;
|
if (end > cache_font.Length - 1) end = cache_font.Length - 1;
|
var first = cache_font[start];
|
using (var brush = new SolidBrush(selection))
|
{
|
for (int i = start; i <= end; i++)
|
{
|
var it = cache_font[i];
|
bool p = true;
|
if (it.ret && it.ret_has) p = false;
|
if (p) g.FillRectangle(brush, it.rect);
|
}
|
}
|
}
|
catch { }
|
}
|
}
|
|
protected virtual void PaintRIcon(Graphics g, Rectangle rect) { }
|
|
protected virtual void PaintOtherBor(Graphics g, RectangleF rect_read, float radius, Color back, Color borderColor, Color borderActive) { }
|
|
#region 点击动画
|
|
internal void PaintClick(Graphics g, GraphicsPath path, Rectangle rect, Color color, float radius)
|
{
|
if (AnimationFocus)
|
{
|
if (AnimationFocusValue > 0)
|
{
|
using (var brush = new SolidBrush(Helper.ToColor(AnimationFocusValue, color)))
|
{
|
using (var path_click = Helper.RoundPath(rect, radius, round))
|
{
|
path_click.AddPath(path, false);
|
g.FillPath(brush, path_click);
|
}
|
}
|
}
|
}
|
else if (ExtraMouseDown && WaveSize > 0)
|
{
|
using (var brush = new SolidBrush(Color.FromArgb(30, color)))
|
{
|
using (var path_click = Helper.RoundPath(rect, radius, round))
|
{
|
path_click.AddPath(path, false);
|
g.FillPath(brush, path_click);
|
}
|
}
|
}
|
}
|
|
#endregion
|
|
public override Rectangle ReadRectangle
|
{
|
get => ClientRectangle.PaddingRect(Padding).ReadRect((WaveSize + borderWidth / 2F) * Config.Dpi, JoinLeft, JoinRight);
|
}
|
|
public override GraphicsPath RenderRegion
|
{
|
get
|
{
|
var rect_read = ReadRectangle;
|
float _radius = round ? rect_read.Height : radius * Config.Dpi;
|
return Path(rect_read, _radius);
|
}
|
}
|
|
internal GraphicsPath Path(RectangleF rect_read, float _radius)
|
{
|
if (JoinLeft && JoinRight) return rect_read.RoundPath(0);
|
else if (JoinRight) return rect_read.RoundPath(_radius, true, false, false, true);
|
else if (JoinLeft) return rect_read.RoundPath(_radius, false, true, true, false);
|
return rect_read.RoundPath(_radius);
|
}
|
|
#endregion
|
|
#endregion
|
|
#region 滚动条
|
|
Rectangle ScrollRect;
|
RectangleF ScrollSlider;
|
bool scrollhover = false;
|
bool ScrollHover
|
{
|
get => scrollhover;
|
set
|
{
|
if (scrollhover == value) return;
|
scrollhover = value;
|
Invalidate();
|
}
|
}
|
int scrollx = 0, scrolly = 0, ScrollXMin = 0, ScrollXMax = 0, ScrollYMax = 0;
|
int ScrollX
|
{
|
get => scrollx;
|
set
|
{
|
if (value > ScrollXMax) value = ScrollXMax;
|
if (value < ScrollXMin) value = ScrollXMin;
|
if (scrollx == value) return;
|
scrollx = value;
|
Invalidate();
|
}
|
}
|
int ScrollY
|
{
|
get => scrolly;
|
set
|
{
|
if (value > ScrollYMax) value = ScrollYMax;
|
if (value < 0) value = 0;
|
if (scrolly == value) return;
|
scrolly = value;
|
showCaretFlag = true;
|
Invalidate();
|
}
|
}
|
|
bool ScrollXShow = false, ScrollYShow = false, ScrollYDown = false;
|
void ScrollIFTo(Rectangle r)
|
{
|
if (SpeedScrollTo)
|
{
|
if (ScrollYShow)
|
{
|
int y = CurrentCaret.Y - scrolly;
|
if (y < rect_text.Y) ScrollY = r.Y;
|
else if (y + CurrentCaret.Height > rect_text.Height) ScrollY = r.Bottom;
|
}
|
else if (ScrollXShow)
|
{
|
int x = CurrentCaret.X - scrollx;
|
if (x < rect_text.X) ScrollX = r.X;
|
else if (x + CurrentCaret.Width > rect_text.Width) ScrollX = r.Right;
|
}
|
else ScrollX = ScrollY = 0;
|
}
|
ITask.Run(() => { ScrollTo(r); });
|
}
|
void ScrollTo(Rectangle r)
|
{
|
if (ScrollYShow)
|
{
|
int tosize = CurrentCaret.Height;
|
int count = 0;
|
while (true)
|
{
|
int y = CurrentCaret.Y - scrolly;
|
if (y < rect_text.Y)
|
{
|
int value = ScrollY - tosize;
|
ScrollY = value;
|
if (ScrollY != value) return;
|
count++;
|
if (count < 4) System.Threading.Thread.Sleep(50);
|
}
|
else if (y + CurrentCaret.Height > rect_text.Height)
|
{
|
int value = ScrollY + tosize;
|
ScrollY = value;
|
if (ScrollY != value) return;
|
count++;
|
if (count < 4) System.Threading.Thread.Sleep(50);
|
}
|
else return;
|
}
|
}
|
else if (ScrollXShow)
|
{
|
int tosize = r.Width;
|
int count = 0;
|
while (true)
|
{
|
int x = CurrentCaret.X - scrollx;
|
if (x < rect_text.X)
|
{
|
int value = ScrollX - tosize;
|
ScrollX = value;
|
if (ScrollX != value) return;
|
count++;
|
if (count < 5) System.Threading.Thread.Sleep(50);
|
}
|
else if (x + CurrentCaret.Width > rect_text.Width)
|
{
|
int value = ScrollX + tosize;
|
ScrollX = value;
|
if (ScrollX != value) return;
|
count++;
|
if (count < 5) System.Threading.Thread.Sleep(50);
|
}
|
else return;
|
}
|
|
}
|
else ScrollX = ScrollY = 0;
|
}
|
|
#endregion
|
}
|
}
|