添加项目文件。
This commit is contained in:
156
SamplePreSystem.UI/BaseControls/BaseWindow.cs
Normal file
156
SamplePreSystem.UI/BaseControls/BaseWindow.cs
Normal file
@@ -0,0 +1,156 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Input;
|
||||
using System.Windows.Media;
|
||||
|
||||
namespace SamplePre.UIWpf.BaseWindows
|
||||
{
|
||||
public class BaseWindow : Window
|
||||
{
|
||||
public BaseWindow()
|
||||
{
|
||||
//InitializeStyle();
|
||||
//this.Loaded += delegate
|
||||
//{
|
||||
// InitializeEvent();
|
||||
//};
|
||||
|
||||
InitializeStyle();
|
||||
// 一定要在 Loaded 里执行,确保模板已加载
|
||||
Loaded += (s, e) => InitializeEvent();
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
private void InitializeEvent()
|
||||
{
|
||||
// ✅ 关键:从可视化树查找模板内的元素
|
||||
Button btnMin = FindChild<Button>(this, "btnMin");
|
||||
Button btnMax = FindChild<Button>(this, "btnMax");
|
||||
Button btnClose = FindChild<Button>(this, "btnClose");
|
||||
Border borderTitle = FindChild<Border>(this, "borderTitle");
|
||||
|
||||
// 最小化
|
||||
if (btnMin != null)
|
||||
btnMin.Click += (s, e) => WindowState = WindowState.Minimized;
|
||||
|
||||
// 最大化/还原
|
||||
if (btnMax != null)
|
||||
btnMax.Click += (s, e) =>
|
||||
WindowState = WindowState == WindowState.Normal ? WindowState.Maximized : WindowState.Normal;
|
||||
|
||||
// 关闭
|
||||
if (btnClose != null)
|
||||
btnClose.Click += (s, e) => Close();
|
||||
|
||||
// 拖动窗口
|
||||
if (borderTitle != null)
|
||||
{
|
||||
borderTitle.MouseMove += (s, e) =>
|
||||
{
|
||||
if (e.LeftButton == MouseButtonState.Pressed)
|
||||
DragMove();
|
||||
};
|
||||
|
||||
// 双击标题最大化
|
||||
borderTitle.MouseLeftButtonDown += (s, e) =>
|
||||
{
|
||||
if (e.ClickCount >= 2)
|
||||
WindowState = WindowState == WindowState.Normal ? WindowState.Maximized : WindowState.Normal;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
#region 万能查找控件方法(核心)
|
||||
/// <summary>
|
||||
/// 在可视化树中查找指定名称的子元素
|
||||
/// </summary>
|
||||
public static T FindChild<T>(DependencyObject parent, string childName) where T : DependencyObject
|
||||
{
|
||||
if (parent == null) return null;
|
||||
|
||||
T foundChild = null;
|
||||
int childrenCount = VisualTreeHelper.GetChildrenCount(parent);
|
||||
|
||||
for (int i = 0; i < childrenCount; i++)
|
||||
{
|
||||
var child = VisualTreeHelper.GetChild(parent, i);
|
||||
|
||||
if (child is T tChild && child is FrameworkElement element && element.Name == childName)
|
||||
{
|
||||
foundChild = tChild;
|
||||
break;
|
||||
}
|
||||
|
||||
foundChild = FindChild<T>(child, childName);
|
||||
if (foundChild != null) break;
|
||||
}
|
||||
return foundChild;
|
||||
}
|
||||
#endregion
|
||||
|
||||
private void InitializeStyle()
|
||||
{
|
||||
Style = (Style)Application.Current.Resources["BaseWindowStyle"];
|
||||
}
|
||||
|
||||
////==================================================
|
||||
//private void InitializeEvent()
|
||||
//{
|
||||
// ControlTemplate baseWindowTemplate = (ControlTemplate)App.Current.Resources["BaseWindowControlTemplate"];
|
||||
|
||||
// //Button minBtn = (Button)baseWindowTemplate.FindName("btnMin", this);
|
||||
// //minBtn.Click += delegate
|
||||
// //{
|
||||
|
||||
// // this.WindowState = WindowState.Minimized;
|
||||
// //};
|
||||
|
||||
// //Button maxBtn = (Button)baseWindowTemplate.FindName("btnMax", this);
|
||||
// //maxBtn.Click += delegate
|
||||
// //{
|
||||
|
||||
// // this.WindowState = (this.WindowState == WindowState.Normal ? WindowState.Maximized : WindowState.Normal);
|
||||
// //};
|
||||
|
||||
// //Button closeBtn = this.FindName("btnClose") as Button;
|
||||
|
||||
// Button closeBtn = (Button)baseWindowTemplate.FindName("btnClose", this);
|
||||
// closeBtn.Click += delegate
|
||||
// {
|
||||
// this.Close();
|
||||
// };
|
||||
|
||||
// Border borderTitle = (Border)baseWindowTemplate.FindName("borderTitle", this);
|
||||
// borderTitle.MouseMove += delegate (object sender, MouseEventArgs e)
|
||||
// {
|
||||
// if (e.LeftButton == MouseButtonState.Pressed)
|
||||
// {
|
||||
// this.DragMove();
|
||||
// }
|
||||
// };
|
||||
// borderTitle.MouseLeftButtonDown += delegate (object sender, MouseButtonEventArgs e)
|
||||
// {
|
||||
// if (e.ClickCount >= 2)
|
||||
// {
|
||||
// //maxBtn.RaiseEvent(new RoutedEventArgs(Button.ClickEvent));
|
||||
// }
|
||||
// };
|
||||
//}
|
||||
|
||||
|
||||
//private void InitializeStyle()
|
||||
//{
|
||||
// this.Style = (Style)App.Current.Resources["BaseWindowStyle"];
|
||||
//}
|
||||
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
86
SamplePreSystem.UI/BaseControls/PasswordAttaExt.cs
Normal file
86
SamplePreSystem.UI/BaseControls/PasswordAttaExt.cs
Normal file
@@ -0,0 +1,86 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
|
||||
namespace SamplePreSystem.UI.BaseControls
|
||||
{
|
||||
public class PasswordAttaExt
|
||||
{
|
||||
|
||||
|
||||
public static string GetCustomPwd(DependencyObject obj)
|
||||
{
|
||||
return (string)obj.GetValue(CustomPwdProperty);
|
||||
}
|
||||
|
||||
public static void SetCustomPwd(DependencyObject obj, string value)
|
||||
{
|
||||
obj.SetValue(CustomPwdProperty, value);
|
||||
}
|
||||
|
||||
// Using a DependencyProperty as the backing store for CustomPwd. This enables animation, styling, binding, etc...
|
||||
public static readonly DependencyProperty CustomPwdProperty =
|
||||
DependencyProperty.RegisterAttached("CustomPwd", typeof(string), typeof(PasswordAttaExt), new PropertyMetadata("", OnPropertyChangeBack));
|
||||
|
||||
private static void OnPropertyChangeBack(DependencyObject d, DependencyPropertyChangedEventArgs e)
|
||||
{
|
||||
PasswordBox pb = d as PasswordBox;
|
||||
if (pb != null)
|
||||
{
|
||||
if (e.NewValue.ToString() != pb.Password)
|
||||
{
|
||||
pb.Password = e.NewValue.ToString();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
#region 设置事件绑定触发条件
|
||||
|
||||
|
||||
public static bool GetIsOpenPwdBading(DependencyObject obj)
|
||||
{
|
||||
return (bool)obj.GetValue(IsOpenPwdBadingProperty);
|
||||
}
|
||||
|
||||
public static void SetIsOpenPwdBading(DependencyObject obj, bool value)
|
||||
{
|
||||
obj.SetValue(IsOpenPwdBadingProperty, value);
|
||||
}
|
||||
|
||||
// Using a DependencyProperty as the backing store for IsOpenPwdBading. This enables animation, styling, binding, etc...
|
||||
public static readonly DependencyProperty IsOpenPwdBadingProperty =
|
||||
DependencyProperty.RegisterAttached("IsOpenPwdBading", typeof(bool), typeof(PasswordAttaExt), new PropertyMetadata(false, OnValEventChangeBack));
|
||||
|
||||
private static void OnValEventChangeBack(DependencyObject d, DependencyPropertyChangedEventArgs e)
|
||||
{
|
||||
PasswordBox pd = d as PasswordBox;
|
||||
if (pd != null)
|
||||
{
|
||||
pd.PasswordChanged -= Pd_PasswordChanged;
|
||||
pd.PasswordChanged += Pd_PasswordChanged;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static void Pd_PasswordChanged(object sender, RoutedEventArgs e)
|
||||
{
|
||||
PasswordBox pb = sender as PasswordBox;
|
||||
if (pb != null)
|
||||
{
|
||||
SetCustomPwd((DependencyObject)sender, pb.Password);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
117
SamplePreSystem.UI/BaseControls/RingProgressBar.cs
Normal file
117
SamplePreSystem.UI/BaseControls/RingProgressBar.cs
Normal file
@@ -0,0 +1,117 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
using System.Windows.Media;
|
||||
|
||||
namespace SamplePreSystem.UI.BaseControls
|
||||
{
|
||||
public class RingProgressBar : FrameworkElement
|
||||
{
|
||||
/// <summary>
|
||||
/// 声明并注册一个依赖属性 Progress,用于控制进度条显示的百分比(0 ~ 100)。
|
||||
/// </summary>
|
||||
public static readonly DependencyProperty ProgressProperty =
|
||||
DependencyProperty.Register(
|
||||
nameof(Progress), // 属性名称
|
||||
typeof(double), // 属性类型
|
||||
typeof(RingProgressBar), // 所属类型
|
||||
new FrameworkPropertyMetadata(
|
||||
0.0, // 默认值
|
||||
FrameworkPropertyMetadataOptions.AffectsRender // 当值变化时自动触发重绘
|
||||
));
|
||||
|
||||
/// <summary>
|
||||
/// Progress 属性包装器,提供进度值的获取和设置。
|
||||
/// 设置时自动裁剪到 0~100 范围。
|
||||
/// </summary>
|
||||
public double Progress
|
||||
{
|
||||
get => (double)GetValue(ProgressProperty);
|
||||
set => SetValue(ProgressProperty, Math.Max(0, Math.Min(100, value)));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 重写 OnRender 方法,使用 DrawingContext 绘制控件外观。
|
||||
/// </summary>
|
||||
protected override void OnRender(DrawingContext dc)
|
||||
{
|
||||
double width = ActualWidth;
|
||||
double height = ActualHeight;
|
||||
|
||||
// 根据控件尺寸计算圆环半径,保留 5 像素边距
|
||||
double radius = Math.Min(width, height) / 2 - 5;
|
||||
|
||||
// 圆心位置
|
||||
Point center = new Point(width / 2, height / 2);
|
||||
|
||||
// 1. 绘制背景圆环(灰色圆环)
|
||||
dc.DrawEllipse(
|
||||
null, // 无填充
|
||||
new Pen(Brushes.LightGray, 30), // 使用浅灰色画笔,宽度10
|
||||
center, // 圆心
|
||||
radius, radius // 水平半径 & 垂直半径
|
||||
);
|
||||
|
||||
// 2. 计算进度角度(转换为 0~360)
|
||||
double angle = Progress / 100 * 360;
|
||||
|
||||
// 3. 将角度转换为弧度,-90 是为了从正上方开始绘制
|
||||
double radians = (angle - 90) * Math.PI / 180;
|
||||
|
||||
// 4. 圆环起点:圆顶部
|
||||
Point startPoint = new Point(center.X, center.Y - radius);
|
||||
|
||||
// 5. 计算终点:根据弧度计算 X/Y
|
||||
Point endPoint = new Point(
|
||||
center.X + radius * Math.Cos(radians),
|
||||
center.Y + radius * Math.Sin(radians)
|
||||
);
|
||||
|
||||
// 6. 判断是否需要绘制大角度弧(超过180度)
|
||||
bool isLargeArc = angle > 180;
|
||||
|
||||
// 7. 创建一个弧线段,从 startPoint 到 endPoint,构成圆环的一部分
|
||||
PathFigure figure = new PathFigure(
|
||||
startPoint, // 弧线起点
|
||||
new[]
|
||||
{
|
||||
new ArcSegment(
|
||||
endPoint, // 弧线终点
|
||||
new Size(radius, radius), // 弧线的X/Y半径
|
||||
0, // 旋转角度
|
||||
isLargeArc, // 是否为大角度弧线
|
||||
SweepDirection.Clockwise, // 顺时针方向
|
||||
true // 弧线是否可见(用于裁剪,一般设为 true)
|
||||
)
|
||||
},
|
||||
false // 图形是否闭合(环形不闭合)
|
||||
);
|
||||
|
||||
// 8. 创建 PathGeometry 对象用于绘制
|
||||
PathGeometry geometry = new PathGeometry();
|
||||
geometry.Figures.Add(figure);
|
||||
|
||||
// 9. 绘制进度圆环(蓝色)
|
||||
dc.DrawGeometry(
|
||||
null, // 无填充
|
||||
new Pen(Brushes.SteelBlue, 30), // 钢蓝色画笔,宽度10
|
||||
geometry // 绘制路径
|
||||
);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Measure 阶段:建议大小为 100x100。
|
||||
/// </summary>
|
||||
protected override Size MeasureOverride(Size availableSize) => new Size(100, 100);
|
||||
|
||||
/// <summary>
|
||||
/// Arrange 阶段:直接接受布局系统给予的最终大小。
|
||||
/// </summary>
|
||||
protected override Size ArrangeOverride(Size finalSize) => finalSize;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user