👾 修复 Tooltip 并发不消失、重构 ContextMenuStrip

This commit is contained in:
Tom
2025-07-25 20:54:26 +08:00
parent cf5a7cbb29
commit f8edbd3c40
11 changed files with 1131 additions and 955 deletions

View File

@@ -36,93 +36,32 @@ namespace Demo.Controls
menulist = new AntdUI.IContextMenuStripItem[]
{
new AntdUI.ContextMenuStripItem("返回", "Alt+向左键")
{
IconSvg = svg_back
},
new AntdUI.ContextMenuStripItem("刷新", "Ctrl+R")
{
IconSvg = svg_refresh
},
new AntdUI.ContextMenuStripItemDivider(),
new AntdUI.ContextMenuStripItem("另存为", "Ctrl+S")
{
IconSvg = svg_save
},
new AntdUI.ContextMenuStripItem("打印", "Ctrl+P")
{
IconSvg = svg_print
},
new AntdUI.ContextMenuStripItemDivider(),
new AntdUI.ContextMenuStripItem("发送标签页到你的设备")
{
IconSvg = svg_laptop
},
new AntdUI.ContextMenuStripItem("为此页面创建QR代码")
{
IconSvg = svg_qr
},
new AntdUI.ContextMenuStripItem("大声朗读", "Ctrl+Shift+U")
{
IconSvg = svg_a
},
new AntdUI.ContextMenuStripItem("翻译为 中文(简体)")
{
IconSvg = svg_fy
},
new AntdUI.ContextMenuStripItem("将页面添加到集锦")
{
Sub = new AntdUI.IContextMenuStripItem[]
{
new AntdUI.ContextMenuStripItem("返回", "Alt+向左键")
{
IconSvg = svg_back,
Sub = new AntdUI.IContextMenuStripItem[]
{
new AntdUI.ContextMenuStripItem("返回", "Alt+向左键")
{
IconSvg = svg_back
},
new AntdUI.ContextMenuStripItem("刷新", "Ctrl+R")
{
IconSvg = svg_refresh, Checked = true
},
new AntdUI.ContextMenuStripItemDivider(),
new AntdUI.ContextMenuStripItem("另存为", "Ctrl+S")
{
IconSvg = svg_save
},
new AntdUI.ContextMenuStripItem("打印", "Ctrl+P")
{
IconSvg = svg_print
},
},
},
new AntdUI.ContextMenuStripItem("刷新", "Ctrl+R")
{
IconSvg = svg_refresh, Checked = true
},
new AntdUI.ContextMenuStripItemDivider(),
new AntdUI.ContextMenuStripItem("另存为", "Ctrl+S")
{
IconSvg = svg_save
},
new AntdUI.ContextMenuStripItem("打印", "Ctrl+P")
{
IconSvg = svg_print
},
},
IconSvg = svg_add
},
new AntdUI.ContextMenuStripItemDivider(),
new AntdUI.ContextMenuStripItem("共享")
{
IconSvg = svg_share
},
new AntdUI.ContextMenuStripItem("关于")
{
IconSvg = svg_about
},
new AntdUI.ContextMenuStripItem("返回", "Alt+向左键").SetIcon(svg_back),
new AntdUI.ContextMenuStripItem("刷新", "Ctrl+R").SetIcon(svg_refresh),
new AntdUI.ContextMenuStripItemDivider(),
new AntdUI.ContextMenuStripItem("另存为", "Ctrl+S").SetIcon(svg_save),
new AntdUI.ContextMenuStripItem("打印", "Ctrl+P").SetIcon(svg_print),
new AntdUI.ContextMenuStripItemDivider(),
new AntdUI.ContextMenuStripItem("发送标签页到你的设备").SetIcon(svg_laptop),
new AntdUI.ContextMenuStripItem("为此页面创建QR代码").SetIcon(svg_qr),
new AntdUI.ContextMenuStripItem("大声朗读", "Ctrl+Shift+U").SetIcon(svg_a),
new AntdUI.ContextMenuStripItem("翻译为 中文(简体)").SetIcon(svg_fy),
new AntdUI.ContextMenuStripItem("将页面添加到集锦").SetIcon(svg_add).SetSub(
new AntdUI.ContextMenuStripItem("返回", "Alt+向左键").SetIcon(svg_back).SetSub(
new AntdUI.ContextMenuStripItem("返回", "Alt+向左键").SetIcon(svg_back),
new AntdUI.ContextMenuStripItem("刷新", "Ctrl+R").SetIcon(svg_refresh),
new AntdUI.ContextMenuStripItemDivider(),
new AntdUI.ContextMenuStripItem("另存为", "Ctrl+S").SetIcon(svg_save),
new AntdUI.ContextMenuStripItem("打印", "Ctrl+P").SetIcon(svg_print)
),
new AntdUI.ContextMenuStripItem("刷新", "Ctrl+R").SetIcon(svg_refresh),
new AntdUI.ContextMenuStripItemDivider(),
new AntdUI.ContextMenuStripItem("另存为", "Ctrl+S").SetIcon(svg_save),
new AntdUI.ContextMenuStripItem("打印", "Ctrl+P").SetIcon(svg_print)
),
new AntdUI.ContextMenuStripItemDivider(),
new AntdUI.ContextMenuStripItem("共享").SetIcon(svg_share),
new AntdUI.ContextMenuStripItem("关于").SetIcon(svg_about)
};
}

View File

@@ -23,7 +23,7 @@
<ItemGroup>
<PackageReference Include="PublishAotCompressed" Version="1.0.5" />
<PackageReference Include="VC-LTL" Version="5.2.1" />
<PackageReference Include="VC-LTL" Version="5.2.2" />
<PackageReference Include="WinFormsComInterop" Version="0.5.0" />
<PackageReference Include="YY-Thunks" Version="1.1.7" />
<RdXmlFile Include="rd.xml" />

View File

@@ -18,6 +18,7 @@
// QQ: 17379620
using System;
using System.Collections.Concurrent;
using System.Drawing;
using System.Windows.Forms;
@@ -36,6 +37,7 @@ namespace AntdUI
/// <param name="items">内容</param>
public static Form? open(Control control, Action<ContextMenuStripItem> call, IContextMenuStripItem[] items, int sleep = 0) => open(new Config(control, call, items, sleep));
static ConcurrentDictionary<NotifyIcon, Form> dic = new ConcurrentDictionary<NotifyIcon, Form>();
/// <summary>
/// ContextMenuStrip 右键菜单
/// </summary>
@@ -45,11 +47,16 @@ namespace AntdUI
/// <param name="items">内容</param>
public static Form? open(Control control, NotifyIcon notifyIcon, Action<ContextMenuStripItem> call, IContextMenuStripItem[] items, int sleep = 0)
{
return open(new Config(control, call, items, sleep)
var form = open(new Config(control, call, items, sleep)
{
TopMost = true,
Align = TAlign.TL
});
if (form == null) return form;
if (dic.TryRemove(notifyIcon, out var find)) find.Close();
dic.TryAdd(notifyIcon, form);
form.FormClosed += (a, b) => dic.TryRemove(notifyIcon, out _);
return form;
}
/// <summary>
@@ -138,6 +145,11 @@ namespace AntdUI
/// </summary>
public class ContextMenuStripItem : IContextMenuStripItem
{
/// <summary>
/// 右键菜单项
/// </summary>
public ContextMenuStripItem() { }
/// <summary>
/// 右键菜单项
/// </summary>
@@ -163,13 +175,13 @@ namespace AntdUI
/// </summary>
public string? ID { get; set; }
string _text;
string? _text;
/// <summary>
/// 文本
/// </summary>
public string Text
public string? Text
{
get => Localization.GetLangIN(LocalizationText, _text, new string?[] { "{id}", ID });
get => Localization.GetLangI(LocalizationText, _text, new string?[] { "{id}", ID });
set => _text = value;
}
@@ -208,6 +220,8 @@ namespace AntdUI
/// </summary>
public string? IconSvg { get; set; }
internal bool HasIcon => IconSvg != null || Icon != null;
/// <summary>
/// 使能
/// </summary>
@@ -227,6 +241,72 @@ namespace AntdUI
/// 用户定义数据
/// </summary>
public object? Tag { get; set; }
#region
public ContextMenuStripItem SetFore(Color? value)
{
Fore = value;
return this;
}
public ContextMenuStripItem SetID(string? value)
{
ID = value;
return this;
}
public ContextMenuStripItem SetText(string value, string? localization = null)
{
Text = value;
LocalizationText = localization;
return this;
}
public ContextMenuStripItem SetSubText(string value, string? localization = null)
{
SubText = value;
LocalizationSubText = localization;
return this;
}
#region
public ContextMenuStripItem SetIcon(Image? img)
{
Icon = img;
return this;
}
public ContextMenuStripItem SetIcon(string? svg)
{
IconSvg = svg;
return this;
}
#endregion
public ContextMenuStripItem SetEnabled(bool value = false)
{
Enabled = value;
return this;
}
public ContextMenuStripItem SetChecked(bool value = true)
{
Checked = value;
return this;
}
public ContextMenuStripItem SetSub(params IContextMenuStripItem[] value)
{
Sub = value;
return this;
}
public ContextMenuStripItem SetTag(object? value)
{
Tag = value;
return this;
}
#endregion
}
/// <summary>

View File

@@ -870,13 +870,13 @@ namespace AntdUI
string? oldmove, oldmove2;
TooltipForm? toolTip;
void CloseTip(bool clear = true)
public void CloseTip(bool clear = true)
{
toolTip?.IClose();
toolTip = null;
if (clear) oldmove = null;
}
void OpenTip(Rectangle rect, string tooltip)
public void OpenTip(Rectangle rect, string tooltip)
{
if (toolTip == null)
{

View File

@@ -230,10 +230,12 @@ namespace AntdUI
bool multiline = false;
int? maxWidth;
int arrowSize = 0, arrowX = -1;
public override bool MessageEnable => true;
public TooltipForm(Control control, string txt, ITooltipConfig component) : base(240)
{
ocontrol = control;
control.Parent.SetTopMost(Handle);
MessageCloseMouseLeave = true;
Text = txt;
Font = component.Font ?? Config.Font ?? control.Font;
ArrowSize = component.ArrowSize;
@@ -261,13 +263,13 @@ namespace AntdUI
ArrowAlign = align;
SetLocation(x, y);
}
control.LostFocus += Control_LostFocus;
control.MouseLeave += Control_LostFocus;
control.Disposed += Control_Close;
}
public TooltipForm(Control control, Rectangle rect, string txt, ITooltipConfig component, bool hasmax = true) : base(240)
{
ocontrol = control;
control.SetTopMost(Handle);
MessageCloseMouseLeave = true;
Text = txt;
Font = component.Font ?? Config.Font ?? control.Font;
ArrowSize = component.ArrowSize;
@@ -283,6 +285,7 @@ namespace AntdUI
new CalculateCoordinate(control, TargetRect, arrowSize, gap, gap * 2, rect).Auto(ref align, gap + (int)(Radius * Config.Dpi), out int x, out int y, out arrowX);
ArrowAlign = align;
SetLocation(x, y);
control.Disposed += Control_Close;
}
public override string name => nameof(Tooltip);
@@ -299,7 +302,7 @@ namespace AntdUI
Print();
}
private void Control_LostFocus(object? sender, EventArgs e) => IClose();
private void Control_Close(object? sender, EventArgs e) => IClose();
#region
@@ -360,9 +363,7 @@ namespace AntdUI
protected override void Dispose(bool disposing)
{
base.Dispose(disposing);
if (ocontrol == null) return;
ocontrol.LostFocus -= Control_LostFocus;
ocontrol.MouseLeave -= Control_LostFocus;
ocontrol.Disposed -= Control_Close;
}
}

View File

@@ -46,7 +46,7 @@ namespace AntdUI
#region
ITask? task;
bool run_end = false, ok_end = false;
bool ok_end = false;
public void Start(string name)
{
@@ -74,15 +74,19 @@ namespace AntdUI
}
else CallStart();
}
public bool End(string name)
{
if (ok_end) return false;
else if (run_end) return true;
if (ok_end)
{
CallEnd();
return false;
}
ok_end = true;
task?.Dispose();
if (Config.HasAnimation(name))
{
call_end();
run_end = true;
var t = Animation.TotalFrames(10, 80);
task = new ITask((i) =>
{
@@ -113,7 +117,6 @@ namespace AntdUI
{
bmp_tmp?.Dispose();
bmp_tmp = null;
ok_end = true;
form.IClose(true);
}

View File

@@ -237,7 +237,8 @@ namespace AntdUI
#endregion
bool switchClose = true, switchDispose = true;
bool switchClose = true;
int countClose = 0;
public virtual void IClosing() { }
public void IClose(bool isdispose = false)
{
@@ -248,14 +249,15 @@ namespace AntdUI
Invoke(() => IClose(isdispose));
return;
}
if (switchClose) Close();
switchClose = false;
if (countClose > 2) isdispose = true;
if (isdispose)
{
IClosing();
if (switchDispose) Dispose();
switchDispose = false;
Dispose();
return;
}
//countClose++;
Close();
}
catch { }
}

View File

@@ -53,6 +53,7 @@ namespace AntdUI
public virtual void LoadOK()
{
RunAnimation = false;
IsLoad = false;
LoadCompleted?.Invoke();
}

View File

@@ -210,579 +210,160 @@ namespace AntdUI
SafeBitmap? shadow_temp;
}
public class CalculateCoordinate
public abstract class ILayeredShadowFormOpacity : ILayeredFormOpacity
{
public CalculateCoordinate(Control control, Rectangle drop, int ArrowSize, int Shadow, int Shadow2, Rectangle? rect_real = null)
public int shadow = 0, shadow2 = 0;
bool ShadowEnabled = Config.ShadowEnabled;
public ILayeredShadowFormOpacity(byte maxalpha = 255) : base(maxalpha)
{
var point = control.PointToScreen(Point.Empty);
var size = control.ClientSize;
sx = point.X;
sy = point.Y;
cw = size.Width;
ch = size.Height;
if (control is IControl icontrol)
if (ShadowEnabled)
{
crect = icontrol.ReadRectangle;
padd = GetPadding(icontrol);
shadow = (int)(10 * Config.Dpi);
shadow2 = shadow * 2;
}
else crect = control.ClientRectangle;
dw = drop.Width;
dh = drop.Height;
arrow = ArrowSize;
shadow = Shadow;
shadow2 = Shadow2;
creal = rect_real;
}
/// <summary>
/// 屏幕坐标X控件
/// </summary>
public int sx { get; set; }
#region
/// <summary>
/// 屏幕坐标Y控件
/// </summary>
public int sy { get; set; }
/// <summary>
/// 控件宽度
/// </summary>
public int cw { get; set; }
/// <summary>
/// 控件高度
/// </summary>
public int ch { get; set; }
/// <summary>
/// 控件真实容器
/// </summary>
public Rectangle crect { get; set; }
/// <summary>
/// 控件边距
/// </summary>
public int padd { get; set; }
/// <summary>
/// 下拉宽度
/// </summary>
public int dw { get; set; }
/// <summary>
/// 下拉高度
/// </summary>
public int dh { get; set; }
public int arrow { get; set; }
public int shadow { get; set; }
public int shadow2 { get; set; }
/// <summary>
/// 内容区域
/// </summary>
public Rectangle? creal { get; set; }
public Rectangle? iscreen { get; set; }
int GetPadding(IControl control)
public override void SetRect(Rectangle rect)
{
if (control is Button button) return (int)((button.WaveSize + button.BorderWidth) * Config.Dpi);
else if (control is Input input) return (int)((input.WaveSize + input.BorderWidth) * Config.Dpi);
else if (control is ColorPicker colorPicker) return (int)((colorPicker.WaveSize + colorPicker.BorderWidth) * Config.Dpi);
else if (control is Switch _switch) return (int)(_switch.WaveSize * Config.Dpi);
else if (control is Panel panel) return (int)(panel.BorderWidth * Config.Dpi);
else if (control is Alert alert) return (int)(alert.BorderWidth * Config.Dpi);
else if (control is Avatar avatar) return (int)(avatar.BorderWidth * Config.Dpi);
else if (control is Tag tag) return (int)(tag.BorderWidth * Config.Dpi);
else if (control is Table table) return (int)(table.BorderWidth * Config.Dpi);
else if (control is ContainerPanel containerPanel) return (int)(containerPanel.BorderWidth * Config.Dpi);
return 0;
if (ShadowEnabled)
{
SetLocation(rect.X - shadow, rect.Y - shadow);
base.SetSize(rect.Width + shadow2, rect.Height + shadow2);
}
else base.SetRect(rect);
}
public override void SetSize(Size size)
{
if (ShadowEnabled) base.SetSize(size.Width + shadow2, size.Height + shadow2);
else base.SetSize(size);
}
public override void SetSize(int w, int h)
{
if (ShadowEnabled) base.SetSize(w + shadow2, h + shadow2);
else base.SetSize(w, h);
}
public override void SetSize(int size)
{
if (ShadowEnabled) base.SetSize(size + shadow2);
else base.SetSize(size);
}
public override void SetSizeW(int w)
{
if (ShadowEnabled) base.SetSizeW(w + shadow2);
else base.SetSizeW(w);
}
public override void SetSizeH(int h)
{
if (ShadowEnabled) base.SetSizeH(h + shadow2);
else base.SetSizeH(h);
}
#region
/// <summary>
/// 居中X
/// </summary>
public int CenterX()
public void SetLocationO(Point point) => SetLocationO(point.X, point.Y);
public void SetLocationOX(int x)
{
if (creal.HasValue) return sx + creal.Value.X + (creal.Value.Width - dw) / 2 + shadow;
return (sx + (cw - dw) / 2) + shadow;
if (ShadowEnabled) SetLocationX(x - shadow);
else SetLocationX(x);
}
/// <summary>
/// 居中Y
/// </summary>
public int CenterY()
public void SetLocationOY(int y)
{
if (creal.HasValue) return sy + creal.Value.Y + (creal.Value.Height - dh) / 2 + shadow;
return (sy + (ch - dh) / 2) + shadow;
if (ShadowEnabled) SetLocationY(y - shadow);
else SetLocationY(y);
}
/// <summary>
/// 左X ← (齐头)
/// </summary>
public int L()
public void SetLocationO(int x, int y)
{
if (creal.HasValue) return sx + creal.Value.X + crect.X;
return sx + crect.X;
}
/// <summary>
/// 右X → (齐头)
/// </summary>
public int R()
{
if (creal.HasValue) return sx + creal.Value.X + creal.Value.Width - dw + shadow2;
return sx + (crect.X + crect.Width) - dw + shadow2;
}
/// <summary>
/// 上Y ↑
/// </summary>
public int TopY()
{
if (creal.HasValue) return sy - dh + creal.Value.Y + crect.Y + padd - arrow;
return sy - dh + crect.Y + padd - arrow;
}
/// <summary>
/// 下Y ↓
/// </summary>
public int BottomY()
{
if (creal.HasValue) return sy + creal.Value.Bottom - padd + arrow;
return sy + crect.Bottom - padd + arrow;
}
/// <summary>
/// 左X ←
/// </summary>
public int Left()
{
if (creal.HasValue) return sx + creal.Value.X - dw;
return sx - dw;
}
/// <summary>
/// 右X →
/// </summary>
public int Right()
{
if (creal.HasValue) return sx + creal.Value.Right + shadow + arrow;
return sx + cw;
}
/// <summary>
/// 上Y ↑ (齐头)
/// </summary>
public int Y()
{
if (creal.HasValue) return sy + creal.Value.Y + padd - arrow;
return sy;
}
/// <summary>
/// 下Y ↓ (齐头)
/// </summary>
public int B()
{
if (creal.HasValue) return sy + creal.Value.Bottom - dh;
return sy + ch - dh;
if (ShadowEnabled) SetLocation(x - shadow, y - shadow);
else SetLocation(x, y);
}
#endregion
public void Auto(TAlignFrom placement, PushAnimateConfig animate, bool collision, out TAlign align, out int x, out int y)
#region
protected virtual void OnMouseDown(MouseButtons button, int clicks, int x, int y, int delta) { }
protected virtual void OnMouseMove(MouseButtons button, int clicks, int x, int y, int delta) { }
protected virtual void OnMouseUp(MouseButtons button, int clicks, int x, int y, int delta) { }
protected virtual void OnMouseWheel(MouseButtons button, int clicks, int x, int y, int delta) { }
protected override void OnMouseDown(MouseEventArgs e)
{
bool inverted = false;
switch (placement)
{
case TAlignFrom.Top:
Top(collision, out align, out x, out y, ref inverted);
break;
case TAlignFrom.TL:
TL(collision, out align, out x, out y, ref inverted);
break;
case TAlignFrom.TR:
TR(collision, out align, out x, out y, ref inverted);
break;
case TAlignFrom.Bottom:
Bottom(collision, out align, out x, out y, ref inverted);
break;
case TAlignFrom.BR:
BR(collision, out align, out x, out y, ref inverted);
break;
case TAlignFrom.BL:
default:
BL(collision, out align, out x, out y, ref inverted);
break;
}
animate.Inverted = inverted;
if (RunAnimation) return;
base.OnMouseDown(e);
OnMouseDown(e.Button, e.Clicks, e.X - shadow, e.Y - shadow, e.Delta);
}
public void Auto(ref TAlign align, int gap, out int x, out int y, out int ox)
protected override void OnMouseUp(MouseEventArgs e)
{
switch (align)
{
case TAlign.Top:
Top(true, gap, out align, out x, out y, out ox);
break;
case TAlign.TL:
TL(true, gap, out align, out x, out y, out ox);
break;
case TAlign.TR:
TR(true, gap, out align, out x, out y, out ox);
break;
case TAlign.LT:
LT(true, gap, out align, out x, out y, out ox);
break;
case TAlign.Left:
Left(true, gap, out align, out x, out y, out ox);
break;
case TAlign.LB:
LB(true, gap, out align, out x, out y, out ox);
break;
case TAlign.RT:
RT(true, gap, out align, out x, out y, out ox);
break;
case TAlign.Right:
Right(true, gap, out align, out x, out y, out ox);
break;
case TAlign.RB:
RB(true, gap, out align, out x, out y, out ox);
break;
case TAlign.Bottom:
Bottom(true, gap, out align, out x, out y, out ox);
break;
case TAlign.BL:
BL(true, gap, out align, out x, out y, out ox);
break;
case TAlign.BR:
BR(true, gap, out align, out x, out y, out ox);
break;
default:
Top(true, gap, out align, out x, out y, out ox);
break;
}
if (RunAnimation) return;
base.OnMouseUp(e);
OnMouseUp(e.Button, e.Clicks, e.X - shadow, e.Y - shadow, e.Delta);
}
#region
#region TAlignFrom
public void Top(bool collision, out TAlign align, out int x, out int y, ref bool inverted)
protected override void OnMouseMove(MouseEventArgs e)
{
align = TAlign.Bottom;
x = CenterX();
y = TopY();
inverted = true;
if (collision)
{
var screen = iscreen ?? Screen.FromPoint(new Point(x, y)).WorkingArea;
if (y < screen.Y)
{
inverted = false;
y = BottomY();
align = TAlign.Top;
}
}
if (RunAnimation) return;
base.OnMouseMove(e);
OnMouseMove(e.Button, e.Clicks, e.X - shadow, e.Y - shadow, e.Delta);
}
public void TL(bool collision, out TAlign align, out int x, out int y, ref bool inverted)
protected override void OnMouseWheel(MouseEventArgs e)
{
align = TAlign.BL;
x = L();
y = TopY();
inverted = true;
if (collision)
{
var screen = iscreen ?? Screen.FromPoint(new Point(x, y)).WorkingArea;
if (x + dw > screen.Right)
{
x = R();
align = TAlign.BR;
}
}
}
public void TR(bool collision, out TAlign align, out int x, out int y, ref bool inverted)
{
align = TAlign.BR;
x = R();
y = TopY();
inverted = true;
if (collision)
{
var screen = iscreen ?? Screen.FromPoint(new Point(x, y)).WorkingArea;
if (x < screen.X)
{
x = L();
align = TAlign.BL;
}
}
}
public void Bottom(bool collision, out TAlign align, out int x, out int y, ref bool inverted)
{
align = TAlign.Top;
x = CenterX();
y = BottomY();
if (collision)
{
var screen = iscreen ?? Screen.FromPoint(new Point(x, y)).WorkingArea;
if (y + dh > screen.Bottom)
{
inverted = true;
y = TopY();
align = TAlign.Bottom;
}
}
}
public void BR(bool collision, out TAlign align, out int x, out int y, ref bool inverted)
{
align = TAlign.TR;
x = R();
y = BottomY();
if (collision)
{
var screen = iscreen ?? Screen.FromPoint(new Point(x, y)).WorkingArea;
if (x < screen.X)
{
x = L();
align = TAlign.TL;
}
}
}
public void BL(bool collision, out TAlign align, out int x, out int y, ref bool inverted)
{
align = TAlign.TL;
x = L();
y = BottomY();
if (collision)
{
var screen = iscreen ?? Screen.FromPoint(new Point(x, y)).WorkingArea;
if (x + dw > screen.Right)
{
x = R();
align = TAlign.TR;
}
}
if (RunAnimation) return;
base.OnMouseWheel(e);
OnMouseWheel(e.Button, e.Clicks, e.X - shadow, e.Y - shadow, e.Delta);
}
#endregion
#region TAlign
/// <summary>
/// 圆角
/// </summary>
[Description("圆角"), Category("外观"), DefaultValue(0)]
public int Radius { get; set; }
public void Top(bool collision, int gap, out TAlign align, out int x, out int y, out int arrowX)
public abstract void PrintContent(Canvas g, Rectangle rect, GraphicsState state);
public abstract void PrintBg(Canvas g, Rectangle rect, GraphicsPath path);
public void PrintAndClear()
{
x = CenterX();
y = TopY();
align = TAlign.Top;
var screen = iscreen ?? Screen.FromPoint(new Point(sx, sy)).WorkingArea;
if (collision && y < screen.Y)
{
y = BottomY();
align = TAlign.Bottom;
}
int cx = dw / 2, tsize = arrow + gap;
arrowX = cx;
if (x < screen.X)
{
arrowX = cx - (screen.X - x);
if (arrowX < tsize) arrowX = tsize;
x = screen.X;
}
else if (x > screen.Right - dw)
{
int rx = screen.Right - dw;
arrowX = cx - (rx - x);
if (arrowX > dw - tsize) arrowX = dw - tsize;
x = rx;
}
}
public void Bottom(bool collision, int gap, out TAlign align, out int x, out int y, out int arrowX)
{
x = CenterX();
y = BottomY();
align = TAlign.Bottom;
var screen = iscreen ?? Screen.FromPoint(new Point(sx, sy)).WorkingArea;
if (collision && y + dh > screen.Bottom)
{
y = TopY();
align = TAlign.Top;
}
int cx = dw / 2, tsize = arrow + gap;
arrowX = cx;
if (x < screen.X)
{
arrowX = cx - (screen.X - x);
if (arrowX < tsize) arrowX = tsize;
x = screen.X;
}
else if (x > screen.Right - dw)
{
int rx = screen.Right - dw;
arrowX = cx - (rx - x);
if (arrowX > dw - tsize) arrowX = dw - tsize;
x = rx;
}
}
public void TL(bool collision, int gap, out TAlign align, out int x, out int y, out int arrowX)
{
x = L();
y = TopY();
align = TAlign.TL;
var screen = iscreen ?? Screen.FromPoint(new Point(sx, sy)).WorkingArea;
if (collision && x + dw > screen.Right)
{
x = R();
align = TAlign.TR;
}
arrowX = -1;
if (x < screen.X) x = screen.X;
else if (x > screen.Right - dw) x = screen.Right - dw;
}
public void TR(bool collision, int gap, out TAlign align, out int x, out int y, out int arrowX)
{
x = R();
y = TopY();
align = TAlign.TR;
var screen = iscreen ?? Screen.FromPoint(new Point(sx, sy)).WorkingArea;
if (collision && x < screen.X)
{
x = L();
align = TAlign.TL;
}
arrowX = -1;
if (x < screen.X) x = screen.X;
else if (x > screen.Right - dw) x = screen.Right - dw;
}
public void LT(bool collision, int gap, out TAlign align, out int x, out int y, out int arrowX)
{
x = Left();
y = Y();
align = TAlign.LT;
var screen = iscreen ?? Screen.FromPoint(new Point(sx, sy)).WorkingArea;
if (collision && x < screen.X)
{
x = Right();
align = TAlign.RT;
}
arrowX = -1;
if (x < screen.X) x = screen.X;
else if (x > screen.Right - dw) x = screen.Right - dw;
}
public void Left(bool collision, int gap, out TAlign align, out int x, out int y, out int arrowX)
{
x = Left();
y = CenterY();
align = TAlign.Left;
var screen = iscreen ?? Screen.FromPoint(new Point(sx, sy)).WorkingArea;
if (collision && x < screen.X)
{
x = Right();
align = TAlign.Right;
}
arrowX = -1;
if (x < screen.X) x = screen.X;
else if (x > screen.Right - dw) x = screen.Right - dw;
}
public void LB(bool collision, int gap, out TAlign align, out int x, out int y, out int arrowX)
{
x = Left();
y = B();
align = TAlign.LB;
var screen = iscreen ?? Screen.FromPoint(new Point(sx, sy)).WorkingArea;
if (collision && x < screen.X)
{
x = Right();
align = TAlign.RB;
}
arrowX = -1;
if (x < screen.X) x = screen.X;
else if (x > screen.Right - dw) x = screen.Right - dw;
}
public void RT(bool collision, int gap, out TAlign align, out int x, out int y, out int arrowX)
{
x = Right();
y = Y();
align = TAlign.RT;
var screen = iscreen ?? Screen.FromPoint(new Point(sx, sy)).WorkingArea;
if (collision && x + dw > screen.Right)
{
x = Left();
align = TAlign.LT;
}
arrowX = -1;
if (x < screen.X) x = screen.X;
else if (x > screen.Right - dw) x = screen.Right - dw;
}
public void Right(bool collision, int gap, out TAlign align, out int x, out int y, out int arrowX)
{
x = Right();
y = CenterY();
align = TAlign.Right;
var screen = iscreen ?? Screen.FromPoint(new Point(sx, sy)).WorkingArea;
if (collision && x + dw > screen.Right)
{
x = Left();
align = TAlign.Left;
}
arrowX = -1;
if (x < screen.X) x = screen.X;
else if (x > screen.Right - dw) x = screen.Right - dw;
}
public void RB(bool collision, int gap, out TAlign align, out int x, out int y, out int arrowX)
{
x = Right();
y = B();
align = TAlign.RB;
var screen = iscreen ?? Screen.FromPoint(new Point(sx, sy)).WorkingArea;
if (collision && x + dw > screen.Right)
{
x = Left();
align = TAlign.LB;
}
arrowX = -1;
if (x < screen.X) x = screen.X;
else if (x > screen.Right - dw) x = screen.Right - dw;
}
public void BL(bool collision, int gap, out TAlign align, out int x, out int y, out int arrowX)
{
align = TAlign.BL;
x = L();
y = BottomY();
var screen = iscreen ?? Screen.FromPoint(new Point(sx, sy)).WorkingArea;
if (collision && x + dw > screen.Right)
{
x = R();
align = TAlign.BR;
}
arrowX = -1;
if (x < screen.X) x = screen.X;
else if (x > screen.Right - dw) x = screen.Right - dw;
}
public void BR(bool collision, int gap, out TAlign align, out int x, out int y, out int arrowX)
{
align = TAlign.BR;
x = R();
y = BottomY();
var screen = iscreen ?? Screen.FromPoint(new Point(sx, sy)).WorkingArea;
if (collision && x < screen.X)
{
x = L();
align = TAlign.BL;
}
arrowX = -1;
if (x < screen.X) x = screen.X;
else if (x > screen.Right - dw) x = screen.Right - dw;
shadow_temp?.Dispose();
shadow_temp = null;
Print();
}
#endregion
public override Bitmap PrintBit()
{
var rect = TargetRectXY;
Bitmap original_bmp = new Bitmap(rect.Width, rect.Height);
using (var g = Graphics.FromImage(original_bmp).HighLay())
{
if (ShadowEnabled)
{
var rect_read = new Rectangle(shadow, shadow, rect.Width - shadow2, rect.Height - shadow2);
using (var path = rect_read.RoundPath(Radius))
{
if (shadow_temp == null)
{
shadow_temp?.Dispose();
shadow_temp = path.PaintShadow(rect.Width, rect.Height, shadow);
}
#endregion
g.Image(shadow_temp.Bitmap, rect, .2F);
PrintBg(g, rect_read, path);
}
g.SetClip(rect_read);
g.TranslateTransform(shadow, shadow);
var state = g.Save();
PrintContent(g, new Rectangle(0, 0, rect_read.Width, rect_read.Height), state);
}
else
{
using (var path = rect.RoundPath(Radius))
{
PrintBg(g, rect, path);
}
PrintContent(g, rect, g.Save());
}
}
return original_bmp;
}
SafeBitmap? shadow_temp;
}
}

View File

@@ -26,17 +26,17 @@ using System.Windows.Forms;
namespace AntdUI
{
internal class LayeredFormContextMenuStrip : ILayeredFormOpacity, SubLayeredForm
internal class LayeredFormContextMenuStrip : ILayeredShadowFormOpacity, SubLayeredForm
{
ContextMenuStrip.Config config;
public override bool MessageEnable => true;
public override bool MessageCloseSub => true;
public override bool MessageClickMe => false;
Font FontSub;
float radius = 0;
Font? FontSub;
public LayeredFormContextMenuStrip(ContextMenuStrip.Config _config) : base(250)
{
var point = _config.Location ?? MousePosition;
PARENT = this;
if (_config.TopMost)
{
@@ -44,52 +44,38 @@ namespace AntdUI
MessageCloseMouseLeave = true;
}
else _config.Control.SetTopMost(Handle);
var point = _config.Location ?? MousePosition;
config = _config;
Font = config.Font ?? config.Control.Font;
FontSub = Font;
rectsContent = Init(config.Items);
scrollY = new ScrollY(this);
rectsContent = LoadLayout(config.Items);
ScrollBar = new ScrollBar(this, TAMode.Auto);
switch (config.Align)
{
case TAlign.BL:
case TAlign.LB:
point.X -= TargetRect.Width;
point.Offset(10, -10);
point.X -= TargetRect.Width - shadow2;
break;
case TAlign.TL:
case TAlign.LT:
point.X -= TargetRect.Width;
point.Y -= TargetRect.Height;
point.Offset(10, 10);
point.X -= TargetRect.Width - shadow2;
point.Y -= TargetRect.Height - shadow2;
break;
case TAlign.Left:
point.X -= TargetRect.Width;
point.X -= TargetRect.Width - shadow2;
point.Y -= TargetRect.Height / 2;
point.Offset(10, 0);
break;
case TAlign.Right:
point.Y -= TargetRect.Height / 2;
point.Offset(-10, 0);
break;
case TAlign.Top:
point.X -= TargetRect.Width / 2;
point.Y -= TargetRect.Height;
point.Offset(0, 10);
point.Y -= TargetRect.Height - shadow2;
break;
case TAlign.Bottom:
point.X -= TargetRect.Width / 2;
point.Offset(0, -10);
break;
case TAlign.TR:
case TAlign.RT:
point.Y -= TargetRect.Height;
point.Offset(-10, 10);
break;
case TAlign.BR:
case TAlign.RB:
default:
point.Offset(-10, -10);
point.Y -= TargetRect.Height - shadow2;
break;
}
Init(point);
@@ -148,13 +134,9 @@ namespace AntdUI
if (select_index > -1)
{
var it = rectsContent[select_index];
if (it.Tag != null && it.Tag.Sub != null && it.Tag.Sub.Length > 0)
if (it.Tag is ContextMenuStripItem item && item.Sub != null && item.Sub.Length > 0)
{
if (subForm == null)
{
subForm = new LayeredFormContextMenuStrip(config, this, new Point(TargetRect.X + (it.Rect.X + it.Rect.Width) - 20, TargetRect.Y + it.Rect.Y - 20 - (scrollY.Show ? (int)scrollY.Value : 0)), it.Tag.Sub);
subForm.Show(this);
}
if (subForm == null) OpenDown(item, it.Rect, item.Sub);
else
{
subForm?.IClose();
@@ -169,116 +151,140 @@ namespace AntdUI
};
}
ScrollY scrollY;
ScrollBar ScrollBar;
public LayeredFormContextMenuStrip(ContextMenuStrip.Config _config, LayeredFormContextMenuStrip parent, Point point, IContextMenuStripItem[] subs) : base(250)
{
PARENT = parent;
config = _config;
Font = config.Font ?? config.Control.Font;
FontSub = Font;
if (_config.TopMost) Helper.SetTopMost(Handle);
else _config.Control.SetTopMost(Handle);
rectsContent = Init(subs);
scrollY = new ScrollY(this);
rectsContent = LoadLayout(subs);
ScrollBar = new ScrollBar(this, TAMode.Auto);
Init(point);
}
public override string name => nameof(AntdUI.ContextMenuStrip);
#region
void Init(Point point)
{
var screen = Screen.FromPoint(point).WorkingArea;
if (point.X < screen.X) point.X = screen.X;
else if (point.X > (screen.X + screen.Width) - TargetRect.Width) point.X = screen.X + screen.Width - TargetRect.Width;
else if (point.X > (screen.X + screen.Width) - TargetRect.Width + shadow) point.X = screen.X + screen.Width - TargetRect.Width + shadow;
if (TargetRect.Height > screen.Height)
{
int gap_y = rectsContent[0].y / 2 / 2, vr = TargetRect.Height, height = screen.Height;
scrollY.Rect = new Rectangle(TargetRect.Width - gap_y - scrollY.SIZE, 10 + gap_y, scrollY.SIZE, height - 20 - gap_y * 2);
scrollY.Show = true;
scrollY.SetVrSize(vr, height);
int vr = TargetRect.Height - shadow2, height = screen.Height - shadow2;
SetSizeH(height);
ScrollBar.SizeChange(new Rectangle(0, 0, TargetRect.Width - ScrollBar.SIZE, height));
ScrollBar.SetVrSize(0, vr);
SetLocation(point.X - shadow, screen.Y);
}
else
{
if (point.Y < screen.Y) point.Y = screen.Y;
else if (point.Y > (screen.Y + screen.Height) - TargetRect.Height + shadow) point.Y = screen.Y + screen.Height - TargetRect.Height + shadow;
SetLocation(point.X - shadow, point.Y - shadow);
}
if (point.Y < screen.Y) point.Y = screen.Y;
else if (point.Y > (screen.Y + screen.Height) - TargetRect.Height) point.Y = screen.Y + screen.Height - TargetRect.Height;
SetLocation(point);
if (OS.Win7OrLower) Select();
}
bool has_subtext = false;
InRect[] Init(IContextMenuStripItem[] Items)
InRect[] LoadLayout(IContextMenuStripItem[] Items)
{
return Helper.GDI(g =>
{
var dpi = Config.Dpi;
radius = (int)(config.Radius * dpi);
int split = (int)Math.Round(1F * dpi), sp = (int)Math.Round(8F * dpi), spm = sp / 2, padding = (int)Math.Round(16 * dpi), padding2 = padding * 2;
Padding = new Padding(padding);
var _rectsContent = new List<InRect>(Items.Length);
int usew = 0, useh = 0, has_icon = 0, has_checked = 0, has_sub = 0;
Radius = (int)(config.Radius * dpi);
var list = new List<InRect>(Items.Length);
int text_height = g.MeasureString(Config.NullText, Font).Height;
int split = (int)Math.Round(1 * dpi), gap = (int)(text_height * .286F), icon_size = (int)(text_height * 1.14F), icon_gap = (int)(text_height * .6F);
int check_size = (int)(text_height * .8F), gap_y = (int)(text_height * .432F), gap_x = (int)(text_height * .72F), gap2 = gap * 2, gap_x2 = gap_x * 2, gap_y2 = gap_y * 2;
int item_height = text_height + gap_y2, icon_xy = (item_height - icon_size) / 2, check_xy = (item_height - check_size) / 2;
ItemMaxWidth(Items, out bool has_checked, out bool has_icon, out bool has_subText, out bool has_subs);
#region
int maxw = 0;
foreach (var it in Items)
{
if (it is ContextMenuStripItem item)
{
if (!has_subtext && item.SubText != null) has_subtext = true;
list.Add(new InRect(item));
var size = g.MeasureText(item.Text + item.SubText, Font);
int w = size.Width, hc = size.Height, h = hc + sp;
if (has_sub == 0 && (item.Sub != null && item.Sub.Length > 0)) has_sub = hc;
if (has_icon == 0 && (item.Icon != null || item.IconSvg != null)) has_icon = (int)(hc * 0.68F);
if (has_checked == 0 && item.Checked) has_checked = (int)(hc * 0.8F);
if (w > usew) usew = w;
_rectsContent.Add(new InRect(item, padding + useh, h));
useh += h + spm;
}
else if (it is ContextMenuStripItemDivider divider)
{
_rectsContent.Add(new InRect(padding + useh, sp));
useh += sp;
int tmp2 = size.Width;
if (has_checked) tmp2 += check_size + icon_gap;
if (has_icon) tmp2 += icon_size + icon_gap;
if (item.Sub != null && item.Sub.Length > 0) tmp2 += icon_size + icon_gap;
if (tmp2 > maxw) maxw = tmp2;
}
else if (it is ContextMenuStripItemDivider divider) list.Add(new InRect(divider));
}
if (has_subtext) FontSub = new Font(FontSub.FontFamily, FontSub.Size * 0.8F);
if (has_subText) FontSub = new Font(Font.FontFamily, Font.Size * .8F);
int use_r;
if (has_icon > 0 || has_checked > 0)
{
if (has_icon > 0 && has_checked > 0) use_r = has_icon + has_checked + spm * 3;
else if (has_icon > 0) use_r = has_icon + spm;
else use_r = has_checked + spm;
}
else use_r = 0;
#endregion
int sp2 = sp * 2, x = padding + use_r;
usew += use_r;
int readw = usew + has_sub + padding2 + sp2;
foreach (var it in _rectsContent)
int w = maxw + gap_x2, y = 0;
foreach (var it in list)
{
if (it.Tag == null) it.Rect = new Rectangle(10, it.y + (it.h - split) / 2, readw - 20, split);
else
if (it.Tag is ContextMenuStripItem item)
{
it.Rect = new Rectangle(padding, it.y, usew + has_sub + sp2, it.h);
if (it.Tag.Sub != null && it.Tag.Sub.Length > 0) it.RectSub = new Rectangle(it.Rect.Right - spm - has_sub, it.y + (it.h - has_sub) / 2, has_sub, has_sub);
int usex = padding + spm;
if (has_checked > 0)
it.Rect = new Rectangle(gap, y + gap, w, item_height);
int x = it.Rect.X + gap_x, usx = 0;
if (has_checked)
{
if (it.Tag.Checked) it.RectCheck = new Rectangle(usex + spm, it.y + (it.h - has_checked) / 2, has_checked, has_checked);
usex += has_checked + sp;
it.RectT = new Rectangle(x + sp, it.y, usew - use_r - spm, it.h);
it.RectCheck = new Rectangle(x, it.Rect.Y + check_xy, check_size, check_size);
x += check_size + icon_gap;
usx += check_size + icon_gap;
}
else it.RectT = new Rectangle(x + sp, it.y, usew - use_r, it.h);
if (has_icon > 0 && it.Tag.Icon != null || it.Tag.IconSvg != null) it.RectIcon = new Rectangle(usex + spm, it.y + (it.h - has_icon) / 2, has_icon, has_icon);
if (has_icon)
{
it.RectIcon = new Rectangle(x, it.Rect.Y + icon_xy, icon_size, icon_size);
x += icon_size + icon_gap;
usx += icon_size + icon_gap;
}
if (item.Sub != null && item.Sub.Length > 0)
{
it.RectSub = new Rectangle(it.Rect.Right - icon_gap - icon_size, it.Rect.Y + icon_xy, icon_size, icon_size);
usx += icon_size + icon_gap;
}
it.RectText = new Rectangle(x, it.Rect.Y + gap_y, maxw - usx, text_height);
y += item_height + gap2;
}
else if (it.Tag is ContextMenuStripItemDivider divider)
{
it.Rect = new Rectangle(gap, y, w, split);
y += split;
}
}
SetSize(readw, useh - spm + padding2);
return _rectsContent.ToArray();
SetSize(maxw + gap2 + gap_x2, y);
return list.ToArray();
});
}
void ItemMaxWidth(IContextMenuStripItem[] items, out bool has_checked, out bool has_icon, out bool has_subText, out bool has_subs)
{
has_checked = has_icon = has_subText = has_subs = false;
foreach (var it in items)
{
if (it is ContextMenuStripItem item)
{
if (!has_checked && item.Checked) has_checked = true;
if (!has_icon && item.HasIcon) has_icon = true;
if (!has_subText && item.SubText != null) has_subText = true;
if (!has_subs && item.Sub != null && item.Sub.Length > 0) has_subs = true;
if (has_checked && has_icon && has_subText && has_subs) return;
}
}
}
#endregion
protected override void OnDeactivate(EventArgs e)
{
@@ -290,7 +296,7 @@ namespace AntdUI
protected override void Dispose(bool disposing)
{
if (has_subtext) FontSub.Dispose();
FontSub?.Dispose();
subForm?.IClose();
subForm = null;
resetEvent?.WaitDispose();
@@ -302,120 +308,109 @@ namespace AntdUI
#region
readonly StringFormat stringLeft = Helper.SF_Ellipsis(lr: StringAlignment.Near);
readonly StringFormat stringRight = Helper.SF_Ellipsis(lr: StringAlignment.Far);
public override Bitmap PrintBit()
readonly StringFormat sfl = Helper.SF_Ellipsis(lr: StringAlignment.Near), sfr = Helper.SF_Ellipsis(lr: StringAlignment.Far);
public override void PrintBg(Canvas g, Rectangle rect, GraphicsPath path)
{
var rect = TargetRectXY;
var rect_read = new Rectangle(10, 10, rect.Width - 20, rect.Height - 20);
Bitmap original_bmp = new Bitmap(rect.Width, rect.Height);
using (var g = Graphics.FromImage(original_bmp).High())
using (var brush = new SolidBrush(Colour.BgElevated.Get("ContextMenuStrip")))
{
using (var path_sh = DrawShadow(g, rect, rect_read))
g.Fill(brush, path);
}
}
public override void PrintContent(Canvas g, Rectangle rect, GraphicsState state)
{
using (var brush = new SolidBrush(Colour.Text.Get("ContextMenuStrip")))
using (var brushSplit = new SolidBrush(Colour.Split.Get("ContextMenuStrip")))
using (var brushSecondary = new SolidBrush(Colour.TextSecondary.Get("ContextMenuStrip")))
using (var brushEnabled = new SolidBrush(Colour.TextQuaternary.Get("ContextMenuStrip")))
{
g.TranslateTransform(0, -ScrollBar.Value);
foreach (var it in rectsContent)
{
g.Fill(Colour.BgElevated.Get("ContextMenuStrip"), path_sh);
using (var brush = new SolidBrush(Colour.Text.Get("ContextMenuStrip")))
using (var brushSplit = new SolidBrush(Colour.Split.Get("ContextMenuStrip")))
using (var brushSecondary = new SolidBrush(Colour.TextSecondary.Get("ContextMenuStrip")))
using (var brushEnabled = new SolidBrush(Colour.TextQuaternary.Get("ContextMenuStrip")))
if (it.Tag is ContextMenuStripItem item)
{
if (scrollY.Show)
if (it.Hover)
{
g.SetClip(path_sh);
g.TranslateTransform(0, -scrollY.Value);
}
foreach (var it in rectsContent)
{
if (it.Tag == null) g.Fill(brushSplit, it.Rect);
else
using (var path = Helper.RoundPath(it.Rect, Radius))
{
if (it.Hover)
{
using (var path = Helper.RoundPath(it.Rect, radius))
{
g.Fill(Colour.PrimaryBg.Get("ContextMenuStrip"), path);
}
}
if (it.Tag.Enabled)
{
g.DrawText(it.Tag.SubText, FontSub, brushSecondary, it.RectT, stringRight);
if (it.Tag.Fore.HasValue)
{
using (var brush_fore = new SolidBrush(it.Tag.Fore.Value))
{
g.DrawText(it.Tag.Text, Font, brush_fore, it.RectT, stringLeft);
}
}
else g.DrawText(it.Tag.Text, Font, brush, it.RectT, stringLeft);
if (it.Tag.Sub != null && it.Tag.Sub.Length > 0)
{
using (var pen = new Pen(Colour.TextSecondary.Get("ContextMenuStrip"), 2F * Config.Dpi))
{
pen.StartCap = pen.EndCap = LineCap.Round;
g.DrawLines(pen, TAlignMini.Right.TriangleLines(it.RectSub));
}
}
if (it.Tag.Checked)
{
using (var pen = new Pen(Colour.Primary.Get("ContextMenuStrip"), 3F * Config.Dpi))
{
g.DrawLines(pen, PaintArrow(it.RectCheck));
}
}
if (it.Tag.IconSvg != null)
{
using (var bmp = it.Tag.IconSvg.SvgToBmp(it.RectIcon.Width, it.RectIcon.Height, it.Tag.Fore ?? brush.Color))
{
if (bmp != null) g.Image(bmp, it.RectIcon);
}
}
else if (it.Tag.Icon != null) g.Image(it.Tag.Icon, it.RectIcon);
}
else
{
g.DrawText(it.Tag.SubText, FontSub, brushEnabled, it.RectT, stringRight);
g.DrawText(it.Tag.Text, Font, brushEnabled, it.RectT, stringLeft);
if (it.Tag.Sub != null && it.Tag.Sub.Length > 0)
{
using (var pen = new Pen(Colour.TextQuaternary.Get("ContextMenuStrip"), 2F * Config.Dpi))
{
pen.StartCap = pen.EndCap = LineCap.Round;
g.DrawLines(pen, TAlignMini.Right.TriangleLines(it.RectSub));
}
}
if (it.Tag.Checked)
{
using (var pen = new Pen(Colour.Primary.Get("ContextMenuStrip"), 3F * Config.Dpi))
{
g.DrawLines(pen, PaintArrow(it.RectCheck));
}
}
if (it.Tag.IconSvg != null)
{
using (var bmp = it.Tag.IconSvg.SvgToBmp(it.RectIcon.Width, it.RectIcon.Height, brushEnabled.Color))
{
if (bmp != null) g.Image(bmp, it.RectIcon);
}
}
else if (it.Tag.Icon != null) g.Image(it.Tag.Icon, it.RectIcon);
}
g.Fill(Colour.PrimaryBg.Get("ContextMenuStrip"), path);
}
}
g.ResetTransform();
g.ResetClip();
scrollY.Paint(g);
if (item.Enabled)
{
if (FontSub != null) g.DrawText(item.SubText, FontSub, brushSecondary, it.RectText, sfr);
if (item.Fore.HasValue)
{
using (var brush_fore = new SolidBrush(item.Fore.Value))
{
g.DrawText(item.Text, Font, brush_fore, it.RectText, sfl);
}
}
else g.DrawText(item.Text, Font, brush, it.RectText, sfl);
if (item.Sub != null && item.Sub.Length > 0)
{
using (var pen = new Pen(Colour.TextSecondary.Get("ContextMenuStrip"), 2F * Config.Dpi))
{
pen.StartCap = pen.EndCap = LineCap.Round;
g.DrawLines(pen, TAlignMini.Right.TriangleLines(it.RectSub));
}
}
if (item.Checked)
{
using (var pen = new Pen(Colour.Primary.Get("ContextMenuStrip"), 3F * Config.Dpi))
{
g.DrawLines(pen, PaintArrow(it.RectCheck));
}
}
if (item.IconSvg != null)
{
using (var bmp = item.IconSvg.SvgToBmp(it.RectIcon.Width, it.RectIcon.Height, item.Fore ?? brush.Color))
{
if (bmp != null) g.Image(bmp, it.RectIcon);
}
}
else if (item.Icon != null) g.Image(item.Icon, it.RectIcon);
}
else
{
if (FontSub != null) g.DrawText(item.SubText, FontSub, brushEnabled, it.RectText, sfr);
g.DrawText(item.Text, Font, brushEnabled, it.RectText, sfl);
if (item.Sub != null && item.Sub.Length > 0)
{
using (var pen = new Pen(Colour.TextQuaternary.Get("ContextMenuStrip"), 2F * Config.Dpi))
{
pen.StartCap = pen.EndCap = LineCap.Round;
g.DrawLines(pen, TAlignMini.Right.TriangleLines(it.RectSub));
}
}
if (item.Checked)
{
using (var pen = new Pen(Colour.Primary.Get("ContextMenuStrip"), 3F * Config.Dpi))
{
g.DrawLines(pen, PaintArrow(it.RectCheck));
}
}
if (item.IconSvg != null)
{
using (var bmp = item.IconSvg.SvgToBmp(it.RectIcon.Width, it.RectIcon.Height, brushEnabled.Color))
{
if (bmp != null) g.Image(bmp, it.RectIcon);
}
}
else if (item.Icon != null) g.Image(item.Icon, it.RectIcon);
}
}
else if (it.Tag is ContextMenuStripItemDivider item_divider) g.Fill(brushSplit, it.Rect);
}
g.Restore(state);
ScrollBar.Paint(g);
}
return original_bmp;
}
internal PointF[] PaintArrow(Rectangle rect)
PointF[] PaintArrow(Rectangle rect)
{
float size = rect.Height * 0.15F, size2 = rect.Height * 0.2F, size3 = rect.Height * 0.26F;
float size = rect.Height * .15F, size2 = rect.Height * .2F, size3 = rect.Height * .26F;
return new PointF[] {
new PointF(rect.X+size,rect.Y+rect.Height/2),
new PointF(rect.X+rect.Width*0.4F,rect.Y+(rect.Height-size3)),
@@ -423,123 +418,97 @@ namespace AntdUI
};
}
SafeBitmap? shadow_temp;
/// <summary>
/// 绘制阴影
/// </summary>
/// <param name="g">GDI</param>
/// <param name="rect_client">客户区域</param>
/// <param name="rect_read">真实区域</param>
GraphicsPath DrawShadow(Canvas g, Rectangle rect_client, Rectangle rect_read)
{
var path = rect_read.RoundPath(radius);
if (Config.ShadowEnabled)
{
if (shadow_temp == null || (shadow_temp.Width != rect_client.Width || shadow_temp.Height != rect_client.Height))
{
shadow_temp?.Dispose();
shadow_temp = path.PaintShadow(rect_client.Width, rect_client.Height);
}
g.Image(shadow_temp.Bitmap, rect_client, .2F);
}
return path;
}
#endregion
#region
int select_index = -1;
InRect? MDown;
protected override void OnMouseDown(MouseEventArgs e)
protected override void OnMouseDown(MouseButtons button, int clicks, int x, int y, int delta)
{
if (scrollY.MouseDown(e.X, e.Y))
if (ScrollBar.MouseDown(x, y))
{
OnTouchDown(e.X, e.Y);
OnTouchDown(x, y);
select_index = -1;
if (e.Button == MouseButtons.Left)
if (button == MouseButtons.Left)
{
int y = scrollY.Show ? (int)scrollY.Value : 0;
int ry = ScrollBar.Show ? ScrollBar.Value : 0;
for (int i = 0; i < rectsContent.Length; i++)
{
var it = rectsContent[i];
if (it.Tag != null && it.Tag.Enabled && it.Rect.Contains(e.X, e.Y + y))
if (it.Tag is ContextMenuStripItem item && item.Enabled && it.Rect.Contains(x, y + ry))
{
select_index = i;
MDown = it;
base.OnMouseDown(e);
return;
}
}
}
base.OnMouseDown(e);
}
}
protected override void OnMouseUp(MouseEventArgs e)
protected override void OnMouseUp(MouseButtons button, int clicks, int x, int y, int delta)
{
if (scrollY.MouseUp(e.X, e.Y) && OnTouchUp())
if (ScrollBar.MouseUp() && OnTouchUp())
{
int y = scrollY.Show ? (int)scrollY.Value : 0;
int ry = ScrollBar.Show ? ScrollBar.Value : 0;
if (MDown == null) return;
var it = MDown;
MDown = null;
if (it.Rect.Contains(e.X, e.Y + y)) ClickItem(it);
if (it.Rect.Contains(x, y + ry)) ClickItem(it);
}
base.OnMouseUp(e);
}
bool ClickItem(InRect it)
{
if (it.Tag == null) return false;
if (it.Tag.Sub == null || it.Tag.Sub.Length == 0)
if (it.Tag is ContextMenuStripItem item)
{
if (Config.HasAnimation(name))
if (item.Sub == null || item.Sub.Length == 0)
{
IClose();
CloseSub();
resetEvent = new ManualResetEvent(false);
ITask.Run(() =>
{
if (resetEvent.Wait(false)) return;
if (config.CallSleep > 0) Thread.Sleep(config.CallSleep);
config.Control.BeginInvoke(new Action(() => config.Call(it.Tag)));
});
}
else
{
if (config.CallSleep > 0)
if (Config.HasAnimation(name))
{
IClose();
CloseSub();
resetEvent = new ManualResetEvent(false);
ITask.Run(() =>
{
Thread.Sleep(config.CallSleep);
config.Control.BeginInvoke(new Action(() => config.Call(it.Tag)));
if (resetEvent.Wait(false)) return;
if (config.CallSleep > 0) Thread.Sleep(config.CallSleep);
config.Control.BeginInvoke(new Action(() => config.Call(item)));
});
}
else
{
IClose();
CloseSub();
config.Call(it.Tag);
if (config.CallSleep > 0)
{
IClose();
CloseSub();
ITask.Run(() =>
{
Thread.Sleep(config.CallSleep);
config.Control.BeginInvoke(new Action(() => config.Call(item)));
});
}
else
{
IClose();
CloseSub();
config.Call(item);
}
}
}
}
else
{
if (subForm == null)
{
subForm = new LayeredFormContextMenuStrip(config, this, new Point(TargetRect.X + (it.Rect.X + it.Rect.Width) - 20, TargetRect.Y + it.Rect.Y - 20 - (scrollY.Show ? (int)scrollY.Value : 0)), it.Tag.Sub);
subForm.Show(this);
}
else
{
subForm?.IClose();
subForm = null;
if (subForm == null) OpenDown(item, it.Rect, item.Sub);
else
{
subForm?.IClose();
subForm = null;
}
}
return true;
}
return true;
return false;
}
void CloseSub()
@@ -557,38 +526,40 @@ namespace AntdUI
{
if (it.SetHover(true))
{
if (scrollY.Show) scrollY.Value = it.Rect.Y - it.Rect.Height;
if (ScrollBar.Show) ScrollBar.Value = it.Rect.Y - it.Rect.Height;
Print();
}
}
int oldSub = -1;
protected override void OnMouseMove(MouseEventArgs e)
protected override void OnMouseMove(MouseButtons button, int clicks, int x, int y, int delta)
{
if (scrollY.MouseMove(e.X, e.Y) && OnTouchMove(e.X, e.Y))
if (ScrollBar.MouseMove(x, y) && OnTouchMove(x, y))
{
int count = 0, hand = -1;
int y = scrollY.Show ? (int)scrollY.Value : 0;
int ry = ScrollBar.Show ? ScrollBar.Value : 0;
for (int i = 0; i < rectsContent.Length; i++)
{
var it = rectsContent[i];
if (it.Tag == null) continue;
if (it.Tag.Enabled)
if (it.Tag is ContextMenuStripItem item)
{
bool hover = it.Rect.Contains(e.X, e.Y + y);
if (hover) hand = i;
if (it.Hover != hover)
if (item.Enabled)
{
it.Hover = hover;
count++;
bool hover = it.Rect.Contains(x, y + ry);
if (hover) hand = i;
if (it.Hover != hover)
{
it.Hover = hover;
count++;
}
}
}
else
{
if (it.Hover != false)
else
{
it.Hover = false;
count++;
if (it.Hover != false)
{
it.Hover = false;
count++;
}
}
}
}
@@ -603,11 +574,7 @@ namespace AntdUI
oldSub = hand;
subForm?.IClose();
subForm = null;
if (it.Tag != null && it.Tag.Sub != null && it.Tag.Sub.Length > 0)
{
subForm = new LayeredFormContextMenuStrip(config, this, new Point(TargetRect.X + (it.Rect.X + it.Rect.Width) - 20, TargetRect.Y + it.Rect.Y - 20 - (scrollY.Show ? (int)scrollY.Value : 0)), it.Tag.Sub);
subForm.Show(this);
}
if (it.Tag is ContextMenuStripItem item && item.Sub != null && item.Sub.Length > 0) OpenDown(item, it.Rect, item.Sub);
}
else
{
@@ -617,15 +584,16 @@ namespace AntdUI
SetCursor(false);
}
}
base.OnMouseMove(e);
}
void OpenDown(ContextMenuStripItem item, Rectangle rect, IContextMenuStripItem[] sub)
{
var trect = TargetRect;
subForm = new LayeredFormContextMenuStrip(config, this, new Point(trect.X + trect.Width - rect.X - shadow2, trect.Y + rect.Y + shadow / 2 - ScrollBar.Value), sub);
subForm.Show(this);
}
protected override void OnMouseWheel(MouseEventArgs e)
{
scrollY.MouseWheel(e.Delta);
base.OnMouseWheel(e);
}
protected override bool OnTouchScrollY(int value) => scrollY.MouseWheelCore(value);
protected override void OnMouseWheel(MouseButtons button, int clicks, int x, int y, int delta) => ScrollBar.MouseWheel(delta);
protected override bool OnTouchScrollY(int value) => ScrollBar.MouseWheelYCore(value);
ManualResetEvent? resetEvent;
@@ -636,26 +604,27 @@ namespace AntdUI
class InRect
{
public InRect(ContextMenuStripItem tag, int _y, int _h)
public InRect(IContextMenuStripItem tag)
{
Tag = tag;
y = _y;
h = _h;
}
public InRect(int _y, int _h)
{
y = _y;
h = _h;
}
public ContextMenuStripItem? Tag { get; set; }
public IContextMenuStripItem Tag { get; set; }
public bool Hover { get; set; }
public Rectangle RectT { get; set; }
public Rectangle RectIcon { get; set; }
public Rectangle RectCheck { get; set; }
public Rectangle RectSub { get; set; }
#region
public Rectangle Rect { get; set; }
public int y { get; set; }
public int h { get; set; }
public Rectangle RectCheck { get; set; }
public Rectangle RectIcon { get; set; }
/// <summary>
/// 文本区域
/// </summary>
public Rectangle RectText { get; set; }
public Rectangle RectSub { get; set; }
#endregion
internal bool SetHover(bool val)
{

View File

@@ -0,0 +1,600 @@
// 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.
// GITCODE: https://gitcode.com/AntdUI/AntdUI
// GITEE: https://gitee.com/AntdUI/AntdUI
// GITHUB: https://github.com/AntdUI/AntdUI
// CSDN: https://blog.csdn.net/v_132
// QQ: 17379620
using System.Drawing;
using System.Windows.Forms;
namespace AntdUI
{
public class CalculateCoordinate
{
public CalculateCoordinate(Control control, Rectangle drop, int ArrowSize, int Shadow, int Shadow2, Rectangle? rect_real = null)
{
var point = control.PointToScreen(Point.Empty);
var size = control.ClientSize;
sx = point.X;
sy = point.Y;
cw = size.Width;
ch = size.Height;
if (control is IControl icontrol)
{
crect = icontrol.ReadRectangle;
padd = GetPadding(icontrol);
}
else crect = control.ClientRectangle;
dw = drop.Width;
dh = drop.Height;
arrow = ArrowSize;
shadow = Shadow;
shadow2 = Shadow2;
creal = rect_real;
}
/// <summary>
/// 屏幕坐标X控件
/// </summary>
public int sx { get; set; }
/// <summary>
/// 屏幕坐标Y控件
/// </summary>
public int sy { get; set; }
/// <summary>
/// 控件宽度
/// </summary>
public int cw { get; set; }
/// <summary>
/// 控件高度
/// </summary>
public int ch { get; set; }
/// <summary>
/// 控件真实容器
/// </summary>
public Rectangle crect { get; set; }
/// <summary>
/// 控件边距
/// </summary>
public int padd { get; set; }
/// <summary>
/// 下拉宽度
/// </summary>
public int dw { get; set; }
/// <summary>
/// 下拉高度
/// </summary>
public int dh { get; set; }
public int arrow { get; set; }
public int shadow { get; set; }
public int shadow2 { get; set; }
/// <summary>
/// 内容区域
/// </summary>
public Rectangle? creal { get; set; }
public Rectangle? iscreen { get; set; }
int GetPadding(IControl control)
{
if (control is Button button) return (int)((button.WaveSize + button.BorderWidth) * Config.Dpi);
else if (control is Input input) return (int)((input.WaveSize + input.BorderWidth) * Config.Dpi);
else if (control is ColorPicker colorPicker) return (int)((colorPicker.WaveSize + colorPicker.BorderWidth) * Config.Dpi);
else if (control is Switch _switch) return (int)(_switch.WaveSize * Config.Dpi);
else if (control is Panel panel) return (int)(panel.BorderWidth * Config.Dpi);
else if (control is Alert alert) return (int)(alert.BorderWidth * Config.Dpi);
else if (control is Avatar avatar) return (int)(avatar.BorderWidth * Config.Dpi);
else if (control is Tag tag) return (int)(tag.BorderWidth * Config.Dpi);
else if (control is Table table) return (int)(table.BorderWidth * Config.Dpi);
else if (control is ContainerPanel containerPanel) return (int)(containerPanel.BorderWidth * Config.Dpi);
return 0;
}
#region
/// <summary>
/// 居中X
/// </summary>
public int CenterX()
{
if (creal.HasValue) return sx + creal.Value.X + (creal.Value.Width - dw) / 2 + shadow;
return (sx + (cw - dw) / 2) + shadow;
}
/// <summary>
/// 居中Y
/// </summary>
public int CenterY()
{
if (creal.HasValue) return sy + creal.Value.Y + (creal.Value.Height - dh) / 2 + shadow;
return (sy + (ch - dh) / 2) + shadow;
}
/// <summary>
/// 左X ← (齐头)
/// </summary>
public int L()
{
if (creal.HasValue) return sx + creal.Value.X + crect.X;
return sx + crect.X;
}
/// <summary>
/// 右X → (齐头)
/// </summary>
public int R()
{
if (creal.HasValue) return sx + creal.Value.X + creal.Value.Width - dw + shadow2;
return sx + (crect.X + crect.Width) - dw + shadow2;
}
/// <summary>
/// 上Y ↑
/// </summary>
public int TopY()
{
if (creal.HasValue) return sy - dh + creal.Value.Y + crect.Y + padd - arrow;
return sy - dh + crect.Y + padd - arrow;
}
/// <summary>
/// 下Y ↓
/// </summary>
public int BottomY()
{
if (creal.HasValue) return sy + creal.Value.Bottom - padd + arrow;
return sy + crect.Bottom - padd + arrow;
}
/// <summary>
/// 左X ←
/// </summary>
public int Left()
{
if (creal.HasValue) return sx + creal.Value.X - dw;
return sx - dw;
}
/// <summary>
/// 右X →
/// </summary>
public int Right()
{
if (creal.HasValue) return sx + creal.Value.Right + shadow + arrow;
return sx + cw;
}
/// <summary>
/// 上Y ↑ (齐头)
/// </summary>
public int Y()
{
if (creal.HasValue) return sy + creal.Value.Y + padd - arrow;
return sy;
}
/// <summary>
/// 下Y ↓ (齐头)
/// </summary>
public int B()
{
if (creal.HasValue) return sy + creal.Value.Bottom - dh;
return sy + ch - dh;
}
#endregion
public void Auto(TAlignFrom placement, PushAnimateConfig animate, bool collision, out TAlign align, out int x, out int y)
{
bool inverted = false;
switch (placement)
{
case TAlignFrom.Top:
Top(collision, out align, out x, out y, ref inverted);
break;
case TAlignFrom.TL:
TL(collision, out align, out x, out y, ref inverted);
break;
case TAlignFrom.TR:
TR(collision, out align, out x, out y, ref inverted);
break;
case TAlignFrom.Bottom:
Bottom(collision, out align, out x, out y, ref inverted);
break;
case TAlignFrom.BR:
BR(collision, out align, out x, out y, ref inverted);
break;
case TAlignFrom.BL:
default:
BL(collision, out align, out x, out y, ref inverted);
break;
}
animate.Inverted = inverted;
}
public void Auto(ref TAlign align, int gap, out int x, out int y, out int ox)
{
switch (align)
{
case TAlign.Top:
Top(true, gap, out align, out x, out y, out ox);
break;
case TAlign.TL:
TL(true, gap, out align, out x, out y, out ox);
break;
case TAlign.TR:
TR(true, gap, out align, out x, out y, out ox);
break;
case TAlign.LT:
LT(true, gap, out align, out x, out y, out ox);
break;
case TAlign.Left:
Left(true, gap, out align, out x, out y, out ox);
break;
case TAlign.LB:
LB(true, gap, out align, out x, out y, out ox);
break;
case TAlign.RT:
RT(true, gap, out align, out x, out y, out ox);
break;
case TAlign.Right:
Right(true, gap, out align, out x, out y, out ox);
break;
case TAlign.RB:
RB(true, gap, out align, out x, out y, out ox);
break;
case TAlign.Bottom:
Bottom(true, gap, out align, out x, out y, out ox);
break;
case TAlign.BL:
BL(true, gap, out align, out x, out y, out ox);
break;
case TAlign.BR:
BR(true, gap, out align, out x, out y, out ox);
break;
default:
Top(true, gap, out align, out x, out y, out ox);
break;
}
}
#region
#region TAlignFrom
public void Top(bool collision, out TAlign align, out int x, out int y, ref bool inverted)
{
align = TAlign.Bottom;
x = CenterX();
y = TopY();
inverted = true;
if (collision)
{
var screen = iscreen ?? Screen.FromPoint(new Point(x, y)).WorkingArea;
if (y < screen.Y)
{
inverted = false;
y = BottomY();
align = TAlign.Top;
}
}
}
public void TL(bool collision, out TAlign align, out int x, out int y, ref bool inverted)
{
align = TAlign.BL;
x = L();
y = TopY();
inverted = true;
if (collision)
{
var screen = iscreen ?? Screen.FromPoint(new Point(x, y)).WorkingArea;
if (x + dw > screen.Right)
{
x = R();
align = TAlign.BR;
}
}
}
public void TR(bool collision, out TAlign align, out int x, out int y, ref bool inverted)
{
align = TAlign.BR;
x = R();
y = TopY();
inverted = true;
if (collision)
{
var screen = iscreen ?? Screen.FromPoint(new Point(x, y)).WorkingArea;
if (x < screen.X)
{
x = L();
align = TAlign.BL;
}
}
}
public void Bottom(bool collision, out TAlign align, out int x, out int y, ref bool inverted)
{
align = TAlign.Top;
x = CenterX();
y = BottomY();
if (collision)
{
var screen = iscreen ?? Screen.FromPoint(new Point(x, y)).WorkingArea;
if (y + dh > screen.Bottom)
{
inverted = true;
y = TopY();
align = TAlign.Bottom;
}
}
}
public void BR(bool collision, out TAlign align, out int x, out int y, ref bool inverted)
{
align = TAlign.TR;
x = R();
y = BottomY();
if (collision)
{
var screen = iscreen ?? Screen.FromPoint(new Point(x, y)).WorkingArea;
if (x < screen.X)
{
x = L();
align = TAlign.TL;
}
}
}
public void BL(bool collision, out TAlign align, out int x, out int y, ref bool inverted)
{
align = TAlign.TL;
x = L();
y = BottomY();
if (collision)
{
var screen = iscreen ?? Screen.FromPoint(new Point(x, y)).WorkingArea;
if (x + dw > screen.Right)
{
x = R();
align = TAlign.TR;
}
}
}
#endregion
#region TAlign
public void Top(bool collision, int gap, out TAlign align, out int x, out int y, out int arrowX)
{
x = CenterX();
y = TopY();
align = TAlign.Top;
var screen = iscreen ?? Screen.FromPoint(new Point(sx, sy)).WorkingArea;
if (collision && y < screen.Y)
{
y = BottomY();
align = TAlign.Bottom;
}
int cx = dw / 2, tsize = arrow + gap;
arrowX = cx;
if (x < screen.X)
{
arrowX = cx - (screen.X - x);
if (arrowX < tsize) arrowX = tsize;
x = screen.X;
}
else if (x > screen.Right - dw)
{
int rx = screen.Right - dw;
arrowX = cx - (rx - x);
if (arrowX > dw - tsize) arrowX = dw - tsize;
x = rx;
}
}
public void Bottom(bool collision, int gap, out TAlign align, out int x, out int y, out int arrowX)
{
x = CenterX();
y = BottomY();
align = TAlign.Bottom;
var screen = iscreen ?? Screen.FromPoint(new Point(sx, sy)).WorkingArea;
if (collision && y + dh > screen.Bottom)
{
y = TopY();
align = TAlign.Top;
}
int cx = dw / 2, tsize = arrow + gap;
arrowX = cx;
if (x < screen.X)
{
arrowX = cx - (screen.X - x);
if (arrowX < tsize) arrowX = tsize;
x = screen.X;
}
else if (x > screen.Right - dw)
{
int rx = screen.Right - dw;
arrowX = cx - (rx - x);
if (arrowX > dw - tsize) arrowX = dw - tsize;
x = rx;
}
}
public void TL(bool collision, int gap, out TAlign align, out int x, out int y, out int arrowX)
{
x = L();
y = TopY();
align = TAlign.TL;
var screen = iscreen ?? Screen.FromPoint(new Point(sx, sy)).WorkingArea;
if (collision && x + dw > screen.Right)
{
x = R();
align = TAlign.TR;
}
arrowX = -1;
if (x < screen.X) x = screen.X;
else if (x > screen.Right - dw) x = screen.Right - dw;
}
public void TR(bool collision, int gap, out TAlign align, out int x, out int y, out int arrowX)
{
x = R();
y = TopY();
align = TAlign.TR;
var screen = iscreen ?? Screen.FromPoint(new Point(sx, sy)).WorkingArea;
if (collision && x < screen.X)
{
x = L();
align = TAlign.TL;
}
arrowX = -1;
if (x < screen.X) x = screen.X;
else if (x > screen.Right - dw) x = screen.Right - dw;
}
public void LT(bool collision, int gap, out TAlign align, out int x, out int y, out int arrowX)
{
x = Left();
y = Y();
align = TAlign.LT;
var screen = iscreen ?? Screen.FromPoint(new Point(sx, sy)).WorkingArea;
if (collision && x < screen.X)
{
x = Right();
align = TAlign.RT;
}
arrowX = -1;
if (x < screen.X) x = screen.X;
else if (x > screen.Right - dw) x = screen.Right - dw;
}
public void Left(bool collision, int gap, out TAlign align, out int x, out int y, out int arrowX)
{
x = Left();
y = CenterY();
align = TAlign.Left;
var screen = iscreen ?? Screen.FromPoint(new Point(sx, sy)).WorkingArea;
if (collision && x < screen.X)
{
x = Right();
align = TAlign.Right;
}
arrowX = -1;
if (x < screen.X) x = screen.X;
else if (x > screen.Right - dw) x = screen.Right - dw;
}
public void LB(bool collision, int gap, out TAlign align, out int x, out int y, out int arrowX)
{
x = Left();
y = B();
align = TAlign.LB;
var screen = iscreen ?? Screen.FromPoint(new Point(sx, sy)).WorkingArea;
if (collision && x < screen.X)
{
x = Right();
align = TAlign.RB;
}
arrowX = -1;
if (x < screen.X) x = screen.X;
else if (x > screen.Right - dw) x = screen.Right - dw;
}
public void RT(bool collision, int gap, out TAlign align, out int x, out int y, out int arrowX)
{
x = Right();
y = Y();
align = TAlign.RT;
var screen = iscreen ?? Screen.FromPoint(new Point(sx, sy)).WorkingArea;
if (collision && x + dw > screen.Right)
{
x = Left();
align = TAlign.LT;
}
arrowX = -1;
if (x < screen.X) x = screen.X;
else if (x > screen.Right - dw) x = screen.Right - dw;
}
public void Right(bool collision, int gap, out TAlign align, out int x, out int y, out int arrowX)
{
x = Right();
y = CenterY();
align = TAlign.Right;
var screen = iscreen ?? Screen.FromPoint(new Point(sx, sy)).WorkingArea;
if (collision && x + dw > screen.Right)
{
x = Left();
align = TAlign.Left;
}
arrowX = -1;
if (x < screen.X) x = screen.X;
else if (x > screen.Right - dw) x = screen.Right - dw;
}
public void RB(bool collision, int gap, out TAlign align, out int x, out int y, out int arrowX)
{
x = Right();
y = B();
align = TAlign.RB;
var screen = iscreen ?? Screen.FromPoint(new Point(sx, sy)).WorkingArea;
if (collision && x + dw > screen.Right)
{
x = Left();
align = TAlign.LB;
}
arrowX = -1;
if (x < screen.X) x = screen.X;
else if (x > screen.Right - dw) x = screen.Right - dw;
}
public void BL(bool collision, int gap, out TAlign align, out int x, out int y, out int arrowX)
{
align = TAlign.BL;
x = L();
y = BottomY();
var screen = iscreen ?? Screen.FromPoint(new Point(sx, sy)).WorkingArea;
if (collision && x + dw > screen.Right)
{
x = R();
align = TAlign.BR;
}
arrowX = -1;
if (x < screen.X) x = screen.X;
else if (x > screen.Right - dw) x = screen.Right - dw;
}
public void BR(bool collision, int gap, out TAlign align, out int x, out int y, out int arrowX)
{
align = TAlign.BR;
x = R();
y = BottomY();
var screen = iscreen ?? Screen.FromPoint(new Point(sx, sy)).WorkingArea;
if (collision && x < screen.X)
{
x = L();
align = TAlign.BL;
}
arrowX = -1;
if (x < screen.X) x = screen.X;
else if (x > screen.Right - dw) x = screen.Right - dw;
}
#endregion
#endregion
}
}