基于WPF實現(xiàn)擬物音量控件
WPF 實現(xiàn)擬物音量控件
控件名:Wheel
作者:WPFDevelopersOrg - 俞宏偉
原文鏈接:https://github.com/WPFDevelopersOrg/SimulationControl
- 框架使用
.NET6; Visual Studio 2022;- 繪制使用了
Canvas作為容器控件,DrawingContext上繪制水平線。 - 當鼠標滾動滾輪時或按下鼠標向上向下拖動時計算角度偏移并更新圖層。

實現(xiàn)代碼
1)創(chuàng)建 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)創(chuàng)建 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)創(chuàng)建 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>刻度線數(shù)量</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);
????????????//?開始旋轉(zhuǎn)計算刻度位置
????????????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)創(chuàng)建 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實現(xiàn)擬物音量控件的詳細內(nèi)容,更多關(guān)于WPF擬物音量控件的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
Unity3D實現(xiàn)鼠標控制視角轉(zhuǎn)動
這篇文章主要為大家詳細介紹了Unity3D實現(xiàn)鼠標控制視角轉(zhuǎn)動,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下2019-02-02
C#利用iTextSharp組件給PDF文檔添加圖片/文字水印
這篇文章主要給大家介紹了關(guān)于如何C#利用iTextSharp組件給PDF文檔添加圖片/文字水印的相關(guān)資料,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2020-10-10

