开发者

基于WPF实现拟物音量控件

wpF 实现拟物音量控件

控件名:Wheel

作者:WPFDevelopersOrg - 俞宏伟

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

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

基于WPF实现拟物音量控件

实现代码

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实现拟物音量控件的详细内容,更多关于WPF拟物音量控件的资料请关注我们其它相关文章!

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新开发

开发排行榜