mirror of
https://gitee.com/AntdUI/AntdUI.git
synced 2026-03-24 06:30:44 +08:00
👾 修复 Tooltip 并发不消失、重构 ContextMenuStrip
This commit is contained in:
@@ -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)
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -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" />
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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 { }
|
||||
}
|
||||
|
||||
@@ -53,6 +53,7 @@ namespace AntdUI
|
||||
|
||||
public virtual void LoadOK()
|
||||
{
|
||||
RunAnimation = false;
|
||||
IsLoad = false;
|
||||
LoadCompleted?.Invoke();
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
600
src/AntdUI/Lib/CalculateCoordinate.cs
Normal file
600
src/AntdUI/Lib/CalculateCoordinate.cs
Normal 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
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user