基于WPF实现拟物音量控件

 更新时间:2023年05月10日 09:40:14   作者:WPF开发者  
这篇文章主要为大家详细介绍了如何基于WPF实现简单的拟物音量控件,文中的示例代码讲解详细,对我们学习或工作有一定帮助,感兴趣的小伙伴可以了解一下
(福利推荐:【腾讯云】服务器最新限时优惠活动,云服务器1核2G仅99元/年、2核4G仅768元/3年,立即抢购>>>:9i0i.cn/qcloud

(福利推荐:你还在原价购买阿里云服务器?现在阿里云0.8折限时抢购活动来啦!4核8G企业云服务器仅2998元/3年,立即抢购>>>:9i0i.cn/aliyun

WPF 实现拟物音量控件

控件名:Wheel

作者:WPFDevelopersOrg - 俞宏伟

原文链接:https://github.com/WPFDevelopersOrg/SimulationControl

  • 框架使用.NET6
  • Visual Studio 2022;
  • 绘制使用了Canvas作为容器控件,DrawingContext上绘制水平线。
  • 当鼠标滚动滚轮时或按下鼠标向上向下拖动时计算角度偏移并更新图层。

实现代码

1)创建 Wheel.xaml 代码如下:

<UserControl?x:Class="TopControl.Wheel"
?????????????xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
?????????????xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
?????????????xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"?
?????????????xmlns:d="http://schemas.microsoft.com/expression/blend/2008"?
?????????????xmlns:local="clr-namespace:TopControl"
?????????????mc:Ignorable="d"?
?????????????Width="30"?Height="180">
????<Grid>
????????<!--?进度?-->
????????<Grid?Width="2"?Background="#0a0a0a"?Height="180"?HorizontalAlignment="Left"?VerticalAlignment="Bottom"/>
????????<Grid?Width="2"?x:Name="Grid_Value"?Height="0"?HorizontalAlignment="Left"?VerticalAlignment="Bottom">
????????????<Grid?Height="180"?VerticalAlignment="Bottom">
????????????????<Grid.Background>
????????????????????<LinearGradientBrush?StartPoint="0,0"?EndPoint="0,1">
????????????????????????<GradientStop?Offset="0"?Color="#f0d967"/>
????????????????????????<GradientStop?Offset="1"?Color="#33b08d"/>
????????????????????</LinearGradientBrush>
????????????????</Grid.Background>
????????????</Grid>
????????</Grid>
????????<Grid?Background="#0a0a0a"?Width="26"?HorizontalAlignment="Right"?Height="180"?Margin="2,0,0,0"/>
????????<!--?滚轮?-->
????????<Grid?x:Name="WheelArea"?Height="176"?Width="22"?HorizontalAlignment="Right"?Margin="0,0,2,0"
??????????????MouseDown="WheelArea_MouseDown"?MouseMove="WheelArea_MouseMove"?MouseUp="WheelArea_MouseUp"?MouseWheel="WheelArea_MouseWheel">
????????????<Grid.Background>
????????????????<LinearGradientBrush?StartPoint="0,0"?EndPoint="0,1">
????????????????????<GradientStop?Color="#141414"?Offset="0"/>
????????????????????<GradientStop?Color="#3c3c3c"?Offset="0.5"/>
????????????????????<GradientStop?Color="#141414"?Offset="1"/>
????????????????</LinearGradientBrush>
????????????</Grid.Background>
????????????<Grid?x:Name="LayerBox"?IsHitTestVisible="False"/>
????????</Grid>
????</Grid>
</UserControl>

2)创建 Wheel.xaml.cs 代码如下:

using?System.Windows;
using?System.Windows.Controls;
using?System.Windows.Input;

namespace?TopControl
{
????public?partial?class?Wheel?:?UserControl
????{
????????public?Wheel()
????????{
????????????InitializeComponent();
????????????Loaded?+=?Wheel_Loaded;
????????}

????????#region?属性

????????public?int?MinValue?{?get;?set;?}?=?-720;

????????public?int?MaxValue?{?get;?set;?}?=?720;

????????public?int?Value?{?get;?set;?}?=?-720;

????????#endregion

????????#region?控件事件

????????private?void?Wheel_Loaded(object?sender,?RoutedEventArgs?e)
????????{
????????????InitLayer();
????????}

????????private?void?WheelArea_MouseDown(object?sender,?MouseButtonEventArgs?e)
????????{
????????????if?(e.ChangedButton?==?MouseButton.Left)
????????????{
????????????????BeginDrag();
????????????}
????????}

????????private?void?WheelArea_MouseMove(object?sender,?MouseEventArgs?e)
????????{
????????????if?(_dragMode)
????????????{
????????????????Drag();
????????????}
????????}

????????private?void?WheelArea_MouseUp(object?sender,?MouseButtonEventArgs?e)
????????{
????????????if?(e.ChangedButton?==?MouseButton.Left?&&?_dragMode)
????????????{
????????????????EndDrag();
????????????}
????????}

????????private?void?WheelArea_MouseWheel(object?sender,?MouseWheelEventArgs?e)
????????{
????????????if?(_dragMode)?return;

????????????int?offset?=?e.Delta?/?120;
????????????if?(offset?<?0?&&?Value?>?MinValue)
????????????{
????????????????Value?+=?offset;
????????????????UpdateProgress();
????????????????_wheelLayer.AngleOffset?-=?offset?*?_wheelSpeed;
????????????????_wheelLayer.UpdateLayer();
????????????}
????????????else?if?(offset?>?0?&&?Value?<?MaxValue)
????????????{
????????????????Value?+=?offset;
????????????????UpdateProgress();
????????????????_wheelLayer.AngleOffset?-=?offset?*?_wheelSpeed;
????????????????_wheelLayer.UpdateLayer();
????????????}
????????}

????????#endregion

????????#region?鼠标操作

????????private?void?BeginDrag()
????????{
????????????_dragMode?=?true;
????????????WheelArea.CaptureMouse();

????????????_dragStart?=?Mouse.GetPosition(WheelArea);
????????????_angleStart?=?_wheelLayer.AngleOffset;

????????????_valueStart?=?Value;
????????????_offsetDown?=?Value?-?MinValue;
????????????_offsetUp?=?Value?-?MaxValue;
????????}

????????private?void?Drag()
????????{
????????????double?offset_y?=?Mouse.GetPosition(WheelArea).Y?-?_dragStart.Y;
????????????if?(offset_y?<?_offsetUp)?offset_y?=?_offsetUp;
????????????else?if?(offset_y?>?_offsetDown)?offset_y?=?_offsetDown;

????????????double?offset_angle?=?offset_y?*?_wheelSpeed;
????????????Value?=?_valueStart?-?(int)offset_y;
????????????_wheelLayer.AngleOffset?=?_angleStart?+?offset_angle;
????????????UpdateProgress();
????????????_wheelLayer.UpdateLayer();
????????}

????????private?void?EndDrag()
????????{
????????????_dragMode?=?false;
????????????WheelArea.ReleaseMouseCapture();
????????}

????????#endregion

????????#region?私有方法

????????///?<summary>
????????///?初始化图层
????????///?</summary>
????????private?void?InitLayer()
????????{
????????????_wheelLayer.Width?=?LayerBox.ActualWidth;
????????????_wheelLayer.Height?=?LayerBox.ActualHeight;
????????????LayerBox.Children.Add(_wheelLayer);
????????????_wheelLayer.Init();
????????????_wheelLayer.UpdateLayer();
????????}

????????///?<summary>
????????///?更新进度
????????///?</summary>
????????private?void?UpdateProgress()
????????{
????????????Grid_Value.Height?=?(double)(Value?-?MinValue)?/?(MaxValue?-?MinValue)?*?180;
????????}

????????#endregion

????????#region?字段

????????private?readonly?WheelLayer?_wheelLayer?=?new?WheelLayer();

????????private?Point?_dragStart?=?new?Point();
????????private?double?_angleStart?=?0;
????????private?int?_valueStart?=?0;
????????private?bool?_dragMode?=?false;

????????///?<summary>滚轮速度</summary>
????????private?readonly?double?_wheelSpeed?=?0.7;

????????///?<summary>最大向上偏移</summary>
????????private?double?_offsetUp;
????????///?<summary>最大向下偏移</summary>
????????private?double?_offsetDown;

????????#endregion
????}
}

3)创建 WheelLayer.cs 代码如下:

using?MathUtil;
using?System;
using?System.Collections.Generic;
using?System.Runtime.CompilerServices;
using?System.Windows;
using?System.Windows.Media;
using?WpfUtil;

namespace?TopControl
{
????public?class?WheelLayer?:?SingleLayer
????{
????????#region?属性

????????///?<summary>槽高度:180px -?上下边框(4px)</summary>
????????public?int?GrooveHeight?{?get;?set;?}?=?176;

????????///?<summary>角度:圆弧切线与槽边的夹角</summary>
????????public?int?Angle?{?get;?set;?}?=?90;

????????///?<summary>刻度线数量</summary>
????????public?int?LineCount?{?get;?set;?}?=?90;

????????///?<summary>角度偏移</summary>
????????public?double?AngleOffset?{?get;?set;?}?=?0;

????????#endregion

????????#region?公开方法

????????public?override?void?Init()
????????{
????????????//?起点、终点、中点
????????????Point2D?startPoint?=?new?Point2D(0,?0);
????????????Point2D?endPoint?=?new?Point2D(GrooveHeight,?0);
????????????Point2D?centerPoint?=?startPoint.CenterWith(endPoint);
????????????//?向量:中点?->?起点
????????????Vector2?centerToStart?=?new?Vector2(centerPoint,?startPoint);
????????????centerToStart.Rotate(-90);
????????????//?向量:终点?->?中点
????????????Vector2?endToCenter?=?new?Vector2(endPoint,?centerPoint);
????????????endToCenter.Rotate(-90?+?Angle);
????????????//?圆心
????????????_circleCenter?=?centerToStart.IntersectionWith(endToCenter);
????????????//?向量:圆心?->?起点
????????????Vector2?vector?=?new?Vector2(_circleCenter,?startPoint);
????????????_radius?=?vector.Distance;
????????????_anglePerLine?=?360.0?/?LineCount;
????????}

????????protected?override?void?OnUpdate()
????????{
????????????//?最高点
????????????Point2D?top?=?new?Point2D(_circleCenter.X,?_circleCenter.Y?-?_radius);
????????????//?向量:圆心?->?最高点
????????????Vector2?vector?=?new?Vector2(_circleCenter,?top);
????????????double?max?=?Math.Abs(vector.Target.Y);
????????????//?偏移角度
????????????vector.Rotate(AngleOffset);
????????????//?开始旋转计算刻度位置
????????????List<Point2D>?pointList?=?new?List<Point2D>();
????????????for?(int?counter?=?0;?counter?<?LineCount;?counter++)
????????????{
????????????????if?(vector.Target.Y?<?0)?pointList.Add(vector.Target);
????????????????vector.Rotate(-_anglePerLine);
????????????}

????????????//?绘制刻度线
????????????foreach?(var?item?in?pointList)
????????????????DrawHorizontalLine(item.X,?Math.Abs(item.Y)?/?max);
????????}

????????#endregion

????????#region?私有方法

????????///?<summary>
????????///?绘制水平线
????????///?</summary>
????????[MethodImpl(MethodImplOptions.AggressiveInlining)]
????????private?void?DrawHorizontalLine(double?y,?double?opacity)
????????{
????????????Pen?pen?=?new?Pen(new?SolidColorBrush(Color.FromArgb((byte)(opacity?*?255),?32,?32,?32)),?1);
????????????Pen?pen2?=?new?Pen(new?SolidColorBrush(Color.FromArgb((byte)(opacity?*?255),?64,?64,?64)),?1);
????????????_dc.DrawLine(pen,?new?Point(2,?y?-?0.5),?new?Point(Width?-?2,?y?-?0.5));
????????????_dc.DrawLine(pen2,?new?Point(2,?y?+?0.5),?new?Point(Width?-?2,?y?+?0.5));
????????}

????????#endregion

????????#region?字段

????????///?<summary>圆心</summary>
????????private?Point2D?_circleCenter?=?new?Point2D(0,?0);
????????///?<summary>半径</summary>
????????private?double?_radius?=?0;
????????///?<summary>刻度线之间的夹角</summary>
????????private?double?_anglePerLine?=?0;

????????#endregion
????}
}

4)创建 WheelExample.xaml 代码如下:

<wd:Window?x:Class="TopControl.MainWindow"
????????xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
????????xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
????????xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
????????xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
????????xmlns:local="clr-namespace:TopControl"
????????xmlns:wd="https://github.com/WPFDevelopersOrg/WPFDevelopers"
????????mc:Ignorable="d"?Background="#1e1e1e"
????????Title="https://github.com/WPFDevelopersOrg/SimulationControl?-?俞宏伟"?Height="450"?Width="800">
????<Grid>
????????<local:Wheel?HorizontalAlignment="Left"?VerticalAlignment="Top"?Margin="50"/>
????</Grid>
</wd:Window>

效果图

以上就是基于WPF实现拟物音量控件的详细内容,更多关于WPF拟物音量控件的资料请关注程序员之家其它相关文章!

相关文章

  • Unity ScrollView实现动态列表生成

    Unity ScrollView实现动态列表生成

    这篇文章主要为大家详细介绍了Unity ScrollView实现动态列表生成,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2020-04-04
  • C#中迭代器和分部类的使用

    C#中迭代器和分部类的使用

    迭代器和分部类是C#语言的两种重要特性,本文主要介绍了C#中迭代器和分部类的使用,具有一定的参考价值,感兴趣的可以了解一下
    2024-01-01
  • C#操作PowerPoint的方法

    C#操作PowerPoint的方法

    这篇文章主要介绍了C#操作PowerPoint的方法,涉及C#针对PowerPoint的打开、读取、播放等技巧,非常具有实用价值,需要的朋友可以参考下
    2015-04-04
  • C#禁用双击窗体图标关闭窗体的方法

    C#禁用双击窗体图标关闭窗体的方法

    这篇文章主要介绍了C#禁用双击窗体图标关闭窗体的方法,通过对窗体参数的简单设置实现C#禁用双击窗体图标关闭窗体的功能,非常简单实用,需要的朋友可以参考下
    2015-08-08
  • 使用异步方式调用同步方法(实例详解)

    使用异步方式调用同步方法(实例详解)

    .NET Framework 允许您异步调用任何方法。为此,应定义与您要调用的方法具有相同签名的委托;公共语言运行时会自动使用适当的签名为该委托定义BeginInvoke和EndInvoke方法
    2013-10-10
  • C#实现验证字符串的长度的方法详解

    C#实现验证字符串的长度的方法详解

    这篇文章主要为大家详细介绍了C#如何使用正则表达或者计算字符数组长度或字符串的长度来验证验证字符串的长度,感兴趣的小伙伴可以学习一下
    2024-02-02
  • C# 递归查找树状目录实现方法

    C# 递归查找树状目录实现方法

    这篇文章主要介绍了C# 递归查找树状目录实现方法,需要的朋友可以参考下
    2014-02-02
  • C#如何连接使用Zookeeper

    C#如何连接使用Zookeeper

    Zookeeper作为分布式的服务框架,虽然是java写的,但是强大的C#也可以连接使用。而现在主要有两个插件可供使用,分别是ZooKeeperNetEx和Zookeeper.Net,个人推荐使用ZooKeeperNetEx做开发,本文也已介绍ZooKeeperNetEx为主
    2021-06-06
  • 对int array进行排序的实例讲解

    对int array进行排序的实例讲解

    下面小编就为大家分享一篇对int array进行排序的实例讲解,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2017-12-12
  • C#使用RabbitMQ发送和接收消息工具类的实现

    C#使用RabbitMQ发送和接收消息工具类的实现

    RabbitMQ是一个消息的代理器,用于接收和发送消息,本文主要介绍了C#使用RabbitMQ发送和接收消息工具类的实现,具有一定的参考价值,感兴趣的可以了解一下
    2023-12-12

最新评论

?


http://www.vxiaotou.com