基于WPF实现拟物音量控件
wpF 实现拟物音量控件
控件名:Wheel
作者:WPFDevelopersOrg - 俞宏伟
原文链接:https://github.com/WPFDevelopersOrg/SimulationControl
- 框架使用
.NET6
; Visual Studio 2022
;- 绘制使用了
Canvas
作为容器控件,DrawingContext
上绘制水平线。 - 当鼠标滚动滚轮时或按下鼠标向上向下拖动时计算角度偏移并更新图层。
实现代码
1)创建 Wheel.xaml
代码如下:
<UserControlx: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://sche编程mas.microsoft.com/expression/blend/2008" xmlns:local="clr-namespace:TopControl" mc:Ignorable="d" Width="30"Height="180"> <Grid> <!--进度--> <Gridwidth="2"Background="#0a0a0a"Height="180"HorizontalAlignment="Left"VerticalAlignment="Bottom"/> <GridWidth="2"x:Name="Grid_Value"Height="0"HorizontalAlignment="Left"VerticalAlignment="Bottom"> <GridHeight="180"VerticalAlignment="Bottom"> <Grid.Background> <LinearGradientBrushStartPoint="0,0"EndPoint="0,1"> <GradientStopOffset="0"Color="#f0d967"/> <GradientStopOffset="1"Color="#33b08d"/> </LinearGradientBrush> </Grid.Background> </Grid> </Grid> <GridBackground="#0a0a0a"Width="26"HorizontalAlignment="Right"Height="180"Margin="2,0,0,0"/> <!--滚轮--> <Gridx: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> <LinearGradientBrushStartPoint="0,0"EndPoint="0,1"> <GradientStopColor="#141414"Offset="0"/> <GradientStopColor="#3c3c3c"Offset="0.5"/> <GradientStopColor="#141414"Offset="1"/> </LinearGradientBrush> </Grid.Background> <Gridx:Name="LayerBox"IsHitTe开发者_JAVAstVisible="False"/> </Grid> </Grid> </UserControl>
2)创建 Wheel.xaml.cs
代码如下:
usingSystem.Windows; usingSystem.Windows.Controls; usingSystem.Windows.Input; namespaceTopControl { publicpartialclassWheel:UserControl { publicWheel() { InitializeComponent(); Loaded+=Wheel_Loaded; } #region属性 publicintMinValue{get;set;}=-720; publicintMaxValue{get;set;}=720; publicintValue{get;set;}=-720; #endregion #region控件事件 privatevoidWheel_Loaded(objectsender,RoutedEventArgse) { InitLayer(); } privatevoidWheelArea_MouseDown(objectsender,MouseButtonEventArgse) { if(e.ChangedButton==MouseButton.Left) { BeginDrag(); } } privatevoidWheelArea_MouseMove(objectsender,MouseEventArgse) { if(_dragMode) { Drag(); } } privatevoidWheelArea_MouseUp(objectsender,MouseButtonEventArgse) { if(e.ChangedButton==MouseButton.Left&&_dragMode) { EndDrag(); } } privatevoidWheelArea_MouseWheel(objectsender,MouseWheelEventArgse) { if(_dragMode)return; intoffset=e.Delta/120; if(offset<0&&Value>MinValue) { Value+=offset; UpdateProgress(); _wheelLayer.AngleOffset-=offset*_wheelSpeed; _wheelLayer.UpdateLayer(); } elseif(offset>0&&Value<MaxValue) { Value+=offset; UpdateProgress(); _wheelLayer.AngleOffset-=offset*_wheelSpeed; _wheelLayer.UpdateLayer(); } } #endregion #region鼠标操作 privatevoidBeginDrag() { _dragMode=true; WheelArea.CaptureMouse(); _dragStart=Mouse.GetPosition(WheelArea); _angleStart=_wheelLayer.AngleOffset; _valueStart=Value; _offsetDown=Value-MinValue; _offsetUp=Value-MaxValue; } privatevoidDrag() { doubleoffset_y=Mouse.GetPosition(WheelArea).Y-_dragStart.Y; if(offset_y<_offsetUp)offset_y=_offsetUp; elseif(offset_y>_offsetDown)offset_y=_offsetDown; doubleoffset_angle=offset_y*_wheelSpeed; Value=_valueStart-(int)offset_y; _wheelLayer.AngleOffset=_angleStart+offset_angle; UpdateProgress(); _wheelLayer.UpdateLayer(); } privatevoidEndDrag() { _dragMode=false; WheelArea.ReleaseMouseCapture(); } #endregion #region私有方法 ///<summary> ///初始化图层 ///</summary> privatevoidInitLayer() { _wheelLayer.Width=LayerBox.ActualWidth; _wheelLayer.Height=LayerBox.ActualHeight; LayerBox.Children.Add(_wheelLayer); _wheelLayer.Init(); _wheelLayer.UpdateLayer(); } ///<summary> ///更新进度 ///</summary> privatevoidUpdateProgress() { Grid_Value.Height=(double)(Value-MinValue)/(MaxValue-MinValue)*180; } #endregion #region字段 privatereadonlyWheelLayer_wheelLayer=newWheelLayer(); privatePoint_dragStart=newPoint(); privatedouble_angleStart=0; privateint_valueStart=0; privatebool_dragMode=false; ///<summary>滚轮速度</summary> privatereadonlydouble_wheelSpeed=0.7; ///<summary>最大向上偏移</summary> privatedouble_offsetUp; ///<summary>最大向下偏移</summary> privatedouble_offsetDown; #endregion } }
3)创建 WheelLayer.cs
代码如下:
usingMathUtil; usingSystem; usingSystem.Collections.Generic; usingSystem.Runtime.CompilerServices; usingSystem.Windows; usingSystem.Windows.Media; usingWpfUtil; namespaceTopControl { publicclassWheelLayer:SingleLayer { #region属性 ///<summary>槽高度:180px -上下边框(4px)</summary> publicintGrooveHeight{get;set;}=176; ///&androidlt;summary>角度:圆弧切线与槽边的夹角</summary> publicintAngle{get;set;}=90; ///<summary>刻度线数量</summary> publicintLineCount{get;set;}=90; ///<summary>角度偏移</summary> publicdoubleAngleOffset{get;set;}=0; #endregion #region公开方法 publicoverridevoidInit() { //起点、终点、中点 Point2DstartPoint=newPoint2D(0,0); Point2DendPoint=newPoint2D(GrooveHeight,0); Point2DcenterPoint=startPoint.CenterWith(endPoint); //向量:中点->起点 Vector2centerToStart=newVector2(centerPoint,startPoint); centerToStart.Rotate(-90); //向量:终点->中点 Vector2endToCenter=newVector2(endPoint,centerPoint); endToCenter.Rotate(-90+Angle); //圆心 _circleCenter=centerToStart.IntersectionWith(endToCenter); //向量:圆心->起点 Vector2vector=newVectorandroid2(_circleCenter,startPoint); _radius=vector.Distance; _angleperline=360.0/LineCount; } protectedoverridevoidOnUpdate() { //最高点 Point2Dtop=newPoint2D(_circleCenter.X,_circleCenter.Y-_radius); //向量:圆心->最高点 Vector2vector=newVector2(_circleCenter,top); doublemax=Math.Abs(vector.Target.Y); //偏移角度 vector.Rotate(AngleOffset); //开始旋转计算刻度位置 List<Point2D>pointList=newList<Point2D>(); for(intcounter=0;counter<LineCount;counter++) { if(vector.Target.Y<0)pointList.Add(vector.Target); vector.Rotate(-_anglePerLine); } //绘制刻度线 foreach(variteminpointList) DrawHorizontalLine(item.X,Math.Abs(item.Y)/max); } #endregion #region私有方法 ///<summary> ///绘制水平线 ///</summary> [MethodImpl(MethodImplOptions.AggressiveInlining)] privatevoidDrawHorizontalLine(doubley,doubleopacity) { Penpen=newPen(newSolidColorBrush(Color.FromArgb((byte)(opacity*255),32,32,32)),1); Penpen2=newPen(newSolidColorBrush(Color.FromArgb((byte)(opacity*255),64,64,64)),1); _dc.DrawLine(pen,newPoint(2,y-0.5),newPoint(Width-2,y-0.5)); _dc.DrawLine(pen2,newPoint(2,y+0.5),newPoint(Width-2,y+0.5)); } #endregion #region字段 ///<summary>圆心</summary> privatePoint2D_circleCenter=newPoint2D(0,0); ///<summary>半径</summary> privatedouble_radius=0; ///<summary>刻度线之间的夹角</summary> privatedouble_anglePerLine=0; #endregion } }
4)创建 WheelExample.xaml
代码如下:
<wd:Windowx: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.cojsm/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:WheelHorizontalAlignment="Left"VerticalAlignment="Top"Margin="50"/> </Grid> </wd:Window>
效果图
以上就是基于WPF实现拟物音量控件的详细内容,更多关于WPF拟物音量控件的资料请关注我们其它相关文章!
精彩评论