Repository navigation
Expand file tree
/
Copy pathTrayMenu.cs
More file actions
145 lines (126 loc) · 5.31 KB
/
Copy pathTrayMenu.cs
File metadata and controls
145 lines (126 loc) · 5.31 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
using System.Drawing.Drawing2D;
namespace WinTextCapture;
/// <summary>The tray context menu: same items and actions as before, drawn in the app theme.</summary>
internal sealed class TrayMenu
{
public ContextMenuStrip Strip { get; }
public ToolStripMenuItem CaptureItem { get; }
public ToolStripMenuItem SettingsItem { get; }
public ToolStripMenuItem AboutItem { get; }
public ToolStripMenuItem ExitItem { get; }
public TrayMenu(Action capture, Action settings, Action about, Action exit)
{
CaptureItem = Item((s, e) => capture());
SettingsItem = Item((s, e) => settings());
AboutItem = Item((s, e) => about());
ExitItem = Item((s, e) => exit());
Strip = new ContextMenuStrip
{
Font = new Font("Segoe UI", 9f),
ShowImageMargin = false,
ShowCheckMargin = false,
Padding = new Padding(4, 4, 4, 4),
MinimumSize = new Size(208, 0),
};
Strip.Items.Add(CaptureItem);
Strip.Items.Add(new ToolStripSeparator());
Strip.Items.Add(SettingsItem);
Strip.Items.Add(AboutItem);
Strip.Items.Add(new ToolStripSeparator());
Strip.Items.Add(ExitItem);
Strip.Opened += (s, e) => RoundCorners();
}
private static ToolStripMenuItem Item(EventHandler click) =>
new("", null, click) { Padding = new Padding(4, 5, 4, 5) };
/// <summary>Texts in the current language and the current hotkey on the right of "Capture now".</summary>
public void ApplyText(Settings settings)
{
CaptureItem.Text = Strings.MenuCapture;
CaptureItem.ShortcutKeyDisplayString = settings.HotKeyShortText();
SettingsItem.Text = Strings.MenuSettings;
AboutItem.Text = Strings.MenuAbout;
ExitItem.Text = Strings.MenuExit;
}
public void ApplyTheme(Theme theme)
{
Strip.Renderer = new ThemedMenuRenderer(theme);
Strip.BackColor = theme.Surface;
Strip.ForeColor = theme.Text;
}
private void RoundCorners()
{
if (!Strip.IsHandleCreated) return;
int preference = Native.DWMWCP_ROUNDSMALL;
Native.DwmSetWindowAttribute(Strip.Handle, Native.DWMWA_WINDOW_CORNER_PREFERENCE, ref preference, sizeof(int));
}
}
internal readonly record struct MenuColors(Color Back, Color Text, Color Shortcut, Color Hover, Color Border, Color Separator, Color Disabled);
/// <summary>Flat menu renderer: theme surface, rounded hover, muted shortcut text, no grey icon gutter.</summary>
internal sealed class ThemedMenuRenderer : ToolStripRenderer
{
public ThemedMenuRenderer(Theme theme)
{
Theme = theme;
Colors = For(theme);
}
public Theme Theme { get; }
public MenuColors Colors { get; }
public static MenuColors For(Theme t) =>
new(Back: t.Surface, Text: t.Text, Shortcut: t.Subtle, Hover: t.AccentWeak, Border: t.BorderStrong, Separator: t.Border, Disabled: t.Faint);
protected override void OnRenderToolStripBackground(ToolStripRenderEventArgs e)
{
using var brush = new SolidBrush(Colors.Back);
e.Graphics.FillRectangle(brush, e.AffectedBounds);
}
protected override void OnRenderToolStripBorder(ToolStripRenderEventArgs e)
{
using var pen = new Pen(Colors.Border);
var r = e.AffectedBounds;
e.Graphics.DrawRectangle(pen, r.X, r.Y, r.Width - 1, r.Height - 1);
}
protected override void OnRenderImageMargin(ToolStripRenderEventArgs e)
{
using var brush = new SolidBrush(Colors.Back);
e.Graphics.FillRectangle(brush, e.AffectedBounds);
}
protected override void OnRenderMenuItemBackground(ToolStripItemRenderEventArgs e)
{
if (!e.Item.Selected || !e.Item.Enabled) return;
var r = new Rectangle(Point.Empty, e.Item.Size);
r.Inflate(-2, -1);
e.Graphics.SmoothingMode = SmoothingMode.AntiAlias;
using var path = Theming.Rounded(r, 4);
using var brush = new SolidBrush(Colors.Hover);
e.Graphics.FillPath(brush, path);
}
protected override void OnRenderItemText(ToolStripItemTextRenderEventArgs e)
{
bool shortcut = e.Item is ToolStripMenuItem item
&& !string.IsNullOrEmpty(item.ShortcutKeyDisplayString)
&& e.Text == item.ShortcutKeyDisplayString;
e.TextColor = !e.Item.Enabled ? Colors.Disabled : shortcut ? Colors.Shortcut : Colors.Text;
var r = e.TextRectangle;
if (shortcut)
{
// Right-align the hotkey 12 px from the item edge, however wide the menu is.
e.TextRectangle = new Rectangle(r.X, r.Y, Math.Max(1, e.Item.Width - 12 - r.X), r.Height);
e.TextFormat = (e.TextFormat & ~TextFormatFlags.HorizontalCenter) | TextFormatFlags.Right;
}
else
{
e.TextRectangle = new Rectangle(r.X + 8, r.Y, r.Width, r.Height); // inner padding without an icon gutter
}
base.OnRenderItemText(e);
}
protected override void OnRenderSeparator(ToolStripSeparatorRenderEventArgs e)
{
int y = e.Item.Height / 2;
using var pen = new Pen(Colors.Separator);
e.Graphics.DrawLine(pen, 8, y, e.Item.Width - 8, y);
}
protected override void OnRenderArrow(ToolStripArrowRenderEventArgs e)
{
e.ArrowColor = Colors.Text;
base.OnRenderArrow(e);
}
}