Skip to content

Commit fd3a2fb

Browse files
committed
优化工具栏外观
1 parent 6e1ea0a commit fd3a2fb

1 file changed

Lines changed: 133 additions & 69 deletions

File tree

ContextMenuManager/BluePointLilac.Controls/MyToolBar.cs

Lines changed: 133 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,8 @@ namespace BluePointLilac.Controls
99
{
1010
public sealed class MyToolBar : Panel
1111
{
12-
// 提高不透明度值,使白色背景更加明显
13-
public const float SelctedOpacity = 0.8F;
14-
public const float HoveredOpacity = 0.4F;
12+
public const float SelctedOpacity = 1.0F;
13+
public const float HoveredOpacity = 0.6F;
1514
public const float UnSelctedOpacity = 0;
1615

1716
private readonly FlowLayoutPanel buttonContainer;
@@ -25,7 +24,6 @@ public MyToolBar()
2524
BackColor = DarkModeHelper.TitleArea;
2625
ForeColor = DarkModeHelper.FormFore;
2726

28-
// 创建按钮容器(左侧)
2927
buttonContainer = new FlowLayoutPanel
3028
{
3129
Dock = DockStyle.Left,
@@ -36,7 +34,6 @@ public MyToolBar()
3634
BackColor = Color.Transparent
3735
};
3836

39-
// 创建搜索框容器(右侧)
4037
searchBoxContainer = new Panel
4138
{
4239
Dock = DockStyle.Right,
@@ -48,7 +45,6 @@ public MyToolBar()
4845
Controls.Add(buttonContainer);
4946
Controls.Add(searchBoxContainer);
5047

51-
// 监听主题变化
5248
DarkModeHelper.ThemeChanged += OnThemeChanged;
5349
}
5450

@@ -61,16 +57,18 @@ public MyToolBarButton SelectedButton
6157
if (selectedButton == value) return;
6258
if (selectedButton != null)
6359
{
64-
selectedButton.Opacity = UnSelctedOpacity; // 动画过渡到未选中状态
60+
selectedButton.Opacity = UnSelctedOpacity;
6561
selectedButton.Cursor = Cursors.Hand;
66-
selectedButton.UpdateTextColor(); // 更新文字颜色
62+
selectedButton.UpdateTextColor();
63+
selectedButton.IsSelected = false;
6764
}
6865
selectedButton = value;
6966
if (selectedButton != null)
7067
{
71-
selectedButton.Opacity = SelctedOpacity; // 动画过渡到选中状态
68+
selectedButton.Opacity = SelctedOpacity;
7269
selectedButton.Cursor = Cursors.Default;
73-
selectedButton.UpdateTextColor(); // 更新文字颜色
70+
selectedButton.UpdateTextColor();
71+
selectedButton.IsSelected = true;
7472
}
7573
SelectedButtonChanged?.Invoke(this, null);
7674
}
@@ -85,7 +83,6 @@ public int SelectedIndex
8583
null : (MyToolBarButton)buttonContainer.Controls[value];
8684
}
8785

88-
// 添加一个方法来获取所有按钮(用于兼容旧代码)
8986
public Control.ControlCollection ButtonControls => buttonContainer.Controls;
9087

9188
public void AddButton(MyToolBarButton button)
@@ -104,17 +101,19 @@ public void AddButton(MyToolBarButton button)
104101
{
105102
if (button != SelectedButton)
106103
{
107-
button.Opacity = HoveredOpacity; // 动画过渡到悬停状态
108-
button.UpdateTextColor(); // 更新文字颜色
104+
button.Opacity = HoveredOpacity;
105+
button.UpdateTextColor();
106+
button.IsHovered = true;
109107
}
110108
};
111109

112110
button.MouseLeave += (sender, e) =>
113111
{
114112
if (button != SelectedButton)
115113
{
116-
button.Opacity = UnSelctedOpacity; // 动画过渡到未选中状态
117-
button.UpdateTextColor(); // 更新文字颜色
114+
button.Opacity = UnSelctedOpacity;
115+
button.UpdateTextColor();
116+
button.IsHovered = false;
118117
}
119118
};
120119

@@ -128,13 +127,10 @@ public void AddButtons(MyToolBarButton[] buttons)
128127
Array.ForEach(buttons, button => { button.Width = maxWidth; AddButton(button); });
129128
}
130129

131-
// 添加搜索框到工具栏右侧
132130
public void AddSearchBox(SearchBox searchBox)
133131
{
134-
// 清除现有搜索框
135132
searchBoxContainer.Controls.Clear();
136133

137-
// 设置搜索框
138134
searchBox.Parent = searchBoxContainer;
139135
searchBox.Width = searchBoxContainer.Width - 40.DpiZoom();
140136
searchBox.Height = 36.DpiZoom();
@@ -146,13 +142,11 @@ protected override void OnResize(EventArgs e)
146142
{
147143
base.OnResize(e);
148144

149-
// 调整搜索框容器的宽度
150145
if (searchBoxContainer != null)
151146
{
152147
searchBoxContainer.Width = 240.DpiZoom();
153148
searchBoxContainer.Height = Height;
154149

155-
// 确保搜索框在容器中垂直居中
156150
var searchBox = searchBoxContainer.Controls.OfType<SearchBox>().FirstOrDefault();
157151
if (searchBox != null)
158152
{
@@ -167,30 +161,28 @@ protected override void OnPaintBackground(PaintEventArgs e)
167161
base.OnPaintBackground(e);
168162

169163
var rect = ClientRectangle;
164+
var g = e.Graphics;
165+
g.SmoothingMode = SmoothingMode.AntiAlias;
170166

171-
// 使用DarkModeHelper中的颜色
172167
var color1 = DarkModeHelper.ToolBarGradientTop;
173168
var color2 = DarkModeHelper.ToolBarGradientMiddle;
174169
var color3 = DarkModeHelper.ToolBarGradientBottom;
175170

176-
// 创建三色渐变
177-
using var brush = new LinearGradientBrush(
178-
rect, Color.Empty, Color.Empty, LinearGradientMode.Vertical);
179-
// 使用ColorBlend创建三色渐变
171+
using var brush = new LinearGradientBrush(rect, Color.Empty, Color.Empty, LinearGradientMode.Vertical);
180172
var colorBlend = new ColorBlend(3);
181173
colorBlend.Colors = new Color[] { color1, color2, color3 };
182174
colorBlend.Positions = new float[] { 0f, 0.5f, 1f };
183175
brush.InterpolationColors = colorBlend;
184176

185-
e.Graphics.FillRectangle(brush, rect);
177+
g.FillRectangle(brush, rect);
178+
179+
using var borderPen = new Pen(DarkModeHelper.IsDarkTheme ?
180+
Color.FromArgb(60, 60, 60) : Color.FromArgb(220, 220, 220), 1);
181+
g.DrawLine(borderPen, 0, rect.Bottom - 1, rect.Right, rect.Bottom - 1);
186182
}
187183

188-
// 重写Controls属性以保持向后兼容(注意:这可能会影响一些代码)
189-
public new Control.ControlCollection Controls =>
190-
// 返回包含所有子控件的集合
191-
base.Controls;
184+
public new Control.ControlCollection Controls => base.Controls;
192185

193-
// 主题变化事件处理
194186
private void OnThemeChanged(object sender, EventArgs e)
195187
{
196188
BackColor = DarkModeHelper.TitleArea;
@@ -212,9 +204,43 @@ public sealed class MyToolBarButton : Panel
212204
{
213205
private float targetOpacity;
214206
private float currentOpacity;
207+
private float currentScale = 1.0f;
208+
private float targetScale = 1.0f;
215209
private readonly Timer animationTimer = new() { Interval = 16 };
216-
private const float AnimationSpeed = 0.15f;
217-
private readonly int borderRadius = 10; // 圆角半径
210+
private const float AnimationSpeed = 0.12f;
211+
private const float ScaleAnimationSpeed = 0.15f;
212+
private readonly int borderRadius = 12;
213+
214+
private bool isSelected = false;
215+
private bool isHovered = false;
216+
217+
public bool IsSelected
218+
{
219+
get => isSelected;
220+
set
221+
{
222+
if (isSelected != value)
223+
{
224+
isSelected = value;
225+
targetScale = value ? 1.02f : 1.0f;
226+
if (!animationTimer.Enabled) animationTimer.Start();
227+
}
228+
}
229+
}
230+
231+
public bool IsHovered
232+
{
233+
get => isHovered;
234+
set
235+
{
236+
if (isHovered != value && !isSelected)
237+
{
238+
isHovered = value;
239+
targetScale = value ? 1.01f : 1.0f;
240+
if (!animationTimer.Enabled) animationTimer.Start();
241+
}
242+
}
243+
}
218244

219245
public MyToolBarButton(Image image, string text)
220246
{
@@ -225,16 +251,16 @@ public MyToolBarButton(Image image, string text)
225251
Cursor = Cursors.Hand;
226252
Size = new Size(72, 72).DpiZoom();
227253

228-
// 启用透明背景
229254
SetStyle(ControlStyles.SupportsTransparentBackColor, true);
230255
SetStyle(ControlStyles.Opaque, false);
256+
SetStyle(ControlStyles.ResizeRedraw, true);
231257

232258
animationTimer.Tick += (s, e) => UpdateAnimation();
233259

234260
Controls.AddRange(new Control[] { picImage, lblText });
235261
lblText.Resize += (sender, e) => OnResize(null);
236-
picImage.Top = 6.DpiZoom();
237-
lblText.Top = 52.DpiZoom();
262+
picImage.Top = 8.DpiZoom();
263+
lblText.Top = 50.DpiZoom();
238264
lblText.SetEnabled(false);
239265
Image = image;
240266
Text = text;
@@ -244,7 +270,7 @@ public MyToolBarButton(Image image, string text)
244270
private readonly PictureBox picImage = new()
245271
{
246272
SizeMode = PictureBoxSizeMode.StretchImage,
247-
Size = new Size(40, 40).DpiZoom(),
273+
Size = new Size(36, 36).DpiZoom(),
248274
BackColor = Color.Transparent,
249275
Enabled = false
250276
};
@@ -253,7 +279,7 @@ public MyToolBarButton(Image image, string text)
253279
{
254280
ForeColor = DarkModeHelper.FormFore,
255281
BackColor = Color.Transparent,
256-
Font = SystemFonts.MenuFont,
282+
Font = new Font(SystemFonts.MenuFont.FontFamily, SystemFonts.MenuFont.SizeInPoints, FontStyle.Regular, GraphicsUnit.Point),
257283
AutoSize = true,
258284
Anchor = AnchorStyles.Left | AnchorStyles.Right
259285
};
@@ -271,7 +297,7 @@ public Image Image
271297
}
272298

273299
public bool CanBeSelected = true;
274-
private readonly float opacity;
300+
275301
public float Opacity
276302
{
277303
get => currentOpacity;
@@ -284,40 +310,61 @@ public float Opacity
284310
}
285311
}
286312

287-
// 重写OnPaint方法以实现圆角效果
288313
protected override void OnPaint(PaintEventArgs e)
289314
{
290-
// 调用基类绘制以确保子控件正确显示
291315
base.OnPaint(e);
292316

293-
// 创建圆角矩形路径
294-
using var path = DarkModeHelper.CreateRoundedRectanglePath(ClientRectangle, borderRadius);
295-
// 根据当前模式选择颜色
317+
var g = e.Graphics;
318+
g.SmoothingMode = SmoothingMode.AntiAlias;
319+
g.InterpolationMode = InterpolationMode.HighQualityBicubic;
320+
296321
var isDarkMode = DarkModeHelper.IsDarkTheme;
322+
var mainColor = DarkModeHelper.MainColor;
323+
324+
var padding = 4;
325+
var drawRect = new Rectangle(
326+
padding,
327+
padding,
328+
Width - padding * 2,
329+
Height - padding * 2);
297330

298-
// 深色模式使用白色,浅色模式使用黑色
299-
var baseColor = isDarkMode ? Color.White : Color.Black;
331+
using var path = DarkModeHelper.CreateRoundedRectanglePath(drawRect, borderRadius);
300332

301-
// 减少两种模式的不透明度
302-
var opacityFactor = isDarkMode ? 0.4f : 0.6f; // 深色模式减少更多(0.4),浅色模式减少较少(0.6)
303-
var alpha = (int)(currentOpacity * 255 * opacityFactor);
304-
alpha = Math.Max(0, Math.Min(255, alpha)); // 确保alpha值在有效范围内
333+
if (currentOpacity > 0.01f)
334+
{
335+
var baseColor = isDarkMode ? Color.White : mainColor;
336+
var opacityFactor = isDarkMode ? 0.35f : 0.5f;
337+
var alpha = (int)(currentOpacity * 255 * opacityFactor);
338+
alpha = Math.Max(0, Math.Min(255, alpha));
339+
var fillColor = Color.FromArgb(alpha, baseColor);
340+
341+
using var brush = new SolidBrush(fillColor);
342+
g.FillPath(brush, path);
305343

306-
var fillColor = Color.FromArgb(alpha, baseColor);
344+
if (isSelected && currentOpacity > 0.5f)
345+
{
346+
var glowAlpha = (int)(currentOpacity * 60);
347+
var glowColor = Color.FromArgb(glowAlpha, mainColor);
348+
using var glowPath = DarkModeHelper.CreateRoundedRectanglePath(
349+
new Rectangle(drawRect.X - 2, drawRect.Y - 2, drawRect.Width + 4, drawRect.Height + 4),
350+
borderRadius + 2);
351+
using var glowPen = new Pen(glowColor, 2);
352+
g.DrawPath(glowPen, glowPath);
353+
}
307354

308-
// 使用计算出的颜色填充圆角矩形
309-
using var brush = new SolidBrush(fillColor);
310-
e.Graphics.SmoothingMode = SmoothingMode.AntiAlias;
311-
e.Graphics.FillPath(brush, path);
355+
var borderColor = isSelected ?
356+
Color.FromArgb(180, mainColor) :
357+
Color.FromArgb(100, isDarkMode ? Color.White : mainColor);
358+
using var borderPen = new Pen(borderColor, 1);
359+
g.DrawPath(borderPen, path);
360+
}
312361
}
313362

314-
// 更新文字颜色的方法
315363
public void UpdateTextColor()
316364
{
317365
var isDarkMode = DarkModeHelper.IsDarkTheme;
318366

319-
// 浅色模式下,当按钮被选中或悬停时,文字颜色改为白色
320-
if (!isDarkMode && currentOpacity > 0.1f)
367+
if (!isDarkMode && currentOpacity > 0.3f)
321368
{
322369
lblText.ForeColor = Color.White;
323370
}
@@ -329,38 +376,55 @@ public void UpdateTextColor()
329376

330377
private void UpdateAnimation()
331378
{
332-
currentOpacity += (targetOpacity - currentOpacity) * AnimationSpeed;
333-
var difference = Math.Abs(currentOpacity - targetOpacity);
379+
var needsUpdate = false;
334380

335-
if (difference < 0.01f)
381+
var opacityDiff = targetOpacity - currentOpacity;
382+
if (Math.Abs(opacityDiff) > 0.001f)
383+
{
384+
currentOpacity += opacityDiff * AnimationSpeed;
385+
needsUpdate = true;
386+
}
387+
else
336388
{
337389
currentOpacity = targetOpacity;
338-
animationTimer.Stop();
339390
}
340391

341-
// 更新文字颜色
392+
var scaleDiff = targetScale - currentScale;
393+
if (Math.Abs(scaleDiff) > 0.001f)
394+
{
395+
currentScale += scaleDiff * ScaleAnimationSpeed;
396+
needsUpdate = true;
397+
}
398+
else
399+
{
400+
currentScale = targetScale;
401+
}
402+
342403
UpdateTextColor();
343404

344-
// 强制重绘
345-
this.Invalidate();
346-
this.Update();
405+
Invalidate();
406+
Update();
407+
408+
if (!needsUpdate)
409+
{
410+
animationTimer.Stop();
411+
}
347412
}
348413

349414
protected override void OnResize(EventArgs e)
350415
{
351416
base.OnResize(e);
352417
lblText.Left = (Width - lblText.Width) / 2;
353418
picImage.Left = (Width - picImage.Width) / 2;
354-
this.Invalidate(); // 重绘以确保圆角正确显示
419+
Invalidate();
355420
}
356421

357-
// 确保透明背景正确渲染
358422
protected override CreateParams CreateParams
359423
{
360424
get
361425
{
362426
var cp = base.CreateParams;
363-
cp.ExStyle |= 0x20; // 添加 WS_EX_TRANSPARENT 样式
427+
cp.ExStyle |= 0x20;
364428
return cp;
365429
}
366430
}

0 commit comments

Comments
 (0)