wpf做的标尺
wpf是微软下一代的window开发平台,或者说是xaml,毕竟c++以后也支持了,在想directUI这种东西以后还会有人用吗?
因为我主要负责的是编辑器的工作,所以需要做一个标尺,下面先看下我做的效果吧
提供三个属性
DisplayPercent 当前显示比例
DisplayType 显示方式 横向/竖向
ZeroPoint 选择0点位置
可选属性
Dpi
用于确定系统目前的Dpi,来让像素转换为cm
目前还不支持Cm/Pixel切换
现在只支持Pixel的显示
代码比较少,直接文章里上,欢迎大家使用,转载的话希望注明出处,谢谢了哈
/* * /////////////////////////////////////// * /////////////////////////////////////// * /////////////////////////////////////// * 转载注明出处 gsralex.blog.163.com// * /////////////////////////////////////// * /////////////////////////////////////// * /////////////////////////////////////// */ using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Windows; using System.Windows.Controls; using System.Windows.Data; using System.Windows.Documents; using System.Windows.Input; using System.Windows.Media; using System.Windows.Media.Imaging; using System.Windows.Navigation; using System.Windows.Shapes; using System.Globalization; namespace GsrAlex { public class GsrAlexStaff : Control { public static readonly DependencyProperty DpiProperty = DependencyProperty.Register( "Dpi", typeof(Dpi), typeof(GsrAlexStaff) ); public static readonly DependencyProperty DisplayPercentProperty = DependencyProperty.Register( "DisplayPercent", typeof(double), typeof(GsrAlexStaff) ); public static readonly DependencyProperty DisplayTypeProperty = DependencyProperty.Register( "DisplayType", typeof(StaffDisplayType), typeof(GsrAlexStaff) ); public static readonly DependencyProperty DisplayUnitProperty = DependencyProperty.Register( "DisplayUnit", typeof(StaffDisplayUnit), typeof(GsrAlexStaff) ); public static readonly DependencyProperty ZeroPointProperty = DependencyProperty.Register( "ZeroPoint", typeof(double), typeof(GsrAlexStaff) ); static GsrAlexStaff() { DefaultStyleKeyProperty.OverrideMetadata( typeof(GsrAlexStaff), new FrameworkPropertyMetadata( typeof(GsrAlexStaff) ) ); } #region 属性 /* * / <summary> * / Dpi * / </summary> */ public Dpi Dpi { get { return( (Dpi) GetValue( DpiProperty ) ); } set { SetValue( DpiProperty, value ); } } public double ZeroPoint { get { return( (double) GetValue( ZeroPointProperty ) ); } set { SetValue( ZeroPointProperty, value ); InvalidateVisual(); } } /* * / <summary> * / 显示比例 * / </summary> */ public double DisplayPercent { get { return( (double) GetValue( DisplayPercentProperty ) ); } set { SetValue( DisplayPercentProperty, value ); } } /* * / <summary> * / 显示类型 * / </summary> */ public StaffDisplayType DisplayType { get { return( (StaffDisplayType) GetValue( DisplayTypeProperty ) ); } set { SetValue( DisplayTypeProperty, value ); } } /* * / <summary> * / 显示单位 * / </summary> */ public StaffDisplayUnit DisplayUnit { get { return( (StaffDisplayUnit) GetValue( DisplayUnitProperty ) ); } set { SetValue( DisplayUnitProperty, value ); } } #endregion #region 常量 public const double _inchCm = 2.54; private const int _p100StepSpanPixel = 100; private const int _p100StepSpanCm = 2; private const int _p100StepCountPixel = 20; private const int _p100StepCountCm = 20; #endregion #region 变量 /* * / <summary> * / 1cm显示的像素数除以步进跨度的系数 * / </summary> */ private double _minRatio; /* * / <summary> * / 1cm显示的像素数除以步进跨度的系数 * / </summary> */ private double _maxRatio; private double _minStepLengthCm; private double _maxStepLengthCm; private double _actualLength; private int _stepSpan; private int _stepCount; private double _stepLength; private bool _isInvalidateVisual; private Point _lastPoint; private Position _lastPosition; #endregion protected override void OnRender( DrawingContext drawingContext ) { try { Pen pen = new Pen( new SolidColorBrush( Colors.Black ), 0.5d ); pen.Freeze(); base.OnRender( drawingContext ); Initialize(); GetStep(); GetActualLength(); this.BorderBrush = new SolidColorBrush( Colors.Black ); this.BorderThickness = new Thickness( 0.5 ); /* this.Background = new SolidColorBrush(Colors.White); */ #region try double actualPx = this._actualLength / DisplayPercent; Position currentPosition = new Position { CurrentStepIndex = 0, Value = 0 }; switch ( DisplayType ) { case StaffDisplayType.Horizontal: { /* 绘制前半段 */ DrawLine( drawingContext, ZeroPoint, currentPosition, pen, 0 ); /* 绘制后半段 */ DrawLine( drawingContext, ZeroPoint, currentPosition, pen, 1 ); break; } case StaffDisplayType.Vertical: { /* 绘制前半段 */ DrawLine( drawingContext, ZeroPoint, currentPosition, pen, 0 ); /* 绘制后半段 */ DrawLine( drawingContext, ZeroPoint, currentPosition, pen, 1 ); break; } } #endregion } catch ( Exception ex ) { Console.WriteLine( ex.Message ); } } private void DrawLine( DrawingContext drawingContext, double currentPoint, Position currentPosition, Pen pen, int type ) { double linePercent = 0d; while ( true ) { if ( currentPosition.CurrentStepIndex == 0 ) { linePercent = (int) LinePercent.P100; FormattedText formattedText = GetFormattedText( currentPosition.Value.ToString() ); switch ( DisplayType ) { case StaffDisplayType.Horizontal: { drawingContext.DrawText( formattedText, new Point( currentPoint + formattedText.Width / 2, formattedText.Height / 3 ) ); break; } case StaffDisplayType.Vertical: { Point point = new Point( this.ActualWidth, currentPoint + formattedText.Height / 2 ); RotateTransform rotateTransform = new RotateTransform( 90, point.X, point.Y ); drawingContext.PushTransform( rotateTransform ); drawingContext.DrawText( formattedText, point ); drawingContext.Pop(); break; } } linePercent = (int) LinePercent.P100; }else if ( IsFinalNum( currentPosition.CurrentStepIndex, 3 ) ) { linePercent = (int) LinePercent.P30; }else if ( IsFinalNum( currentPosition.CurrentStepIndex, 5 ) ) { linePercent = (int) LinePercent.P50; }else if ( IsFinalNum( currentPosition.CurrentStepIndex, 7 ) ) { linePercent = (int) LinePercent.P30; }else if ( IsFinalNum( currentPosition.CurrentStepIndex, 0 ) ) { linePercent = (int) LinePercent.P70; }else { linePercent = (int) LinePercent.P20; } linePercent = linePercent * 0.01; if ( linePercent == 1 ) { } switch ( DisplayType ) { case StaffDisplayType.Horizontal: { drawingContext.DrawLine( pen, new Point( currentPoint, 0 ), new Point( currentPoint, this.ActualHeight * linePercent ) ); if ( type == 0 ) { currentPoint = currentPoint - _stepLength; currentPosition.CurrentStepIndex--; if ( currentPosition.CurrentStepIndex < 0 ) { currentPosition.CurrentStepIndex = _stepCount - 1; currentPosition.Value = GetNextStepValue( currentPosition.Value, _stepSpan, 0 ); }else if ( currentPosition.CurrentStepIndex == 0 ) { if ( currentPosition.Value % _stepSpan != 0 ) currentPosition.Value = GetNextStepValue( currentPosition.Value, _stepSpan, 0 ); } if ( currentPoint <= 0 ) { return; } }else { currentPoint = currentPoint + _stepLength; currentPosition.CurrentStepIndex++; if ( currentPosition.CurrentStepIndex >= _stepCount ) { currentPosition.CurrentStepIndex = 0; currentPosition.Value = GetNextStepValue( currentPosition.Value, _stepSpan, 1 ); } if ( currentPoint >= _actualLength ) { return; } } break; } case StaffDisplayType.Vertical: { drawingContext.DrawLine( pen, new Point( 0, currentPoint ), new Point( this.ActualWidth * linePercent, currentPoint ) ); if ( type == 0 ) { currentPoint = currentPoint - _stepLength; currentPosition.CurrentStepIndex--; if ( currentPosition.CurrentStepIndex < 0 ) { currentPosition.CurrentStepIndex = _stepCount - 1; currentPosition.Value = GetNextStepValue( currentPosition.Value, _stepSpan, 0 ); }else if ( currentPosition.CurrentStepIndex == 0 ) { if ( currentPosition.Value % _stepSpan != 0 ) currentPosition.Value = GetNextStepValue( currentPosition.Value, _stepSpan, 0 ); } if ( currentPoint <= 0 ) { return; } }else { currentPoint = currentPoint + _stepLength; currentPosition.CurrentStepIndex++; if ( currentPosition.CurrentStepIndex >= _stepCount ) { currentPosition.CurrentStepIndex = 0; currentPosition.Value = GetNextStepValue( currentPosition.Value, _stepSpan, 1 ); } if ( currentPoint >= _actualLength ) { return; } } break; } } } } private int GetNextStepValue( int value, int times, int type ) { if ( type == 0 ) { do { value--; } while ( value % times != 0 ); }else { do { value++; } while ( value % times != 0 ); } return(value); } private FormattedText GetFormattedText( string text ) { return(new FormattedText( text, CultureInfo.GetCultureInfo( "zh-cn" ), FlowDirection.LeftToRight, new Typeface( "Microsoft YaHei" ), 8, Brushes.Black ) ); } private bool IsFinalNum( int value, int finalNum ) { string valueStr = value.ToString(); if ( valueStr.Substring( valueStr.Length - 1, 1 ) == finalNum.ToString() ) { return(true); } return(false); } private void Initialize() { Dpi dpi = new Dpi(); dpi.DpiX = Dpi.DpiX; dpi.DpiY = Dpi.DpiY; if ( Dpi.DpiX == 0 ) { dpi.DpiX = 96; } if ( Dpi.DpiY == 0 ) { dpi.DpiY = 96; } Dpi = dpi; _maxRatio = 1 / _inchCm * GetDpi() / 80; _minRatio = 1 / _inchCm * GetDpi() / 200; _minStepLengthCm = 0.1; _maxStepLengthCm = 0.3; if ( DisplayPercent == 0 ) DisplayPercent = 1; switch ( DisplayUnit ) { case StaffDisplayUnit.pixel: { _stepSpan = _p100StepSpanPixel; _stepCount = _p100StepCountPixel; break; } case StaffDisplayUnit.cm: { _stepSpan = _p100StepSpanCm; _stepCount = _p100StepCountCm; break; } } int width = 15; switch ( DisplayType ) { case StaffDisplayType.Horizontal: { if ( this.ActualHeight == 0 ) { Height = width; } break; } case StaffDisplayType.Vertical: { if ( this.ActualWidth == 0 ) { Width = width; } break; } } } private void GetStep() { switch ( DisplayUnit ) { case StaffDisplayUnit.pixel: { /* 100px */ _stepSpan = 100; _stepCount = 20; /* 求出当前跨度应该显示的cm */ double stepSpanCm = _stepSpan / Common.Utility.ConvertDouble( GetDpi() ) * _inchCm * DisplayPercent; while ( true ) { stepSpanCm = _stepSpan / Common.Utility.ConvertDouble( GetDpi() ) * _inchCm * DisplayPercent; double stepLengthCm = stepSpanCm / _stepCount; int type = 0; bool isOut = false; if ( stepLengthCm > _maxStepLengthCm ) { type = 1; _stepCount = GetNextStepCount( _stepCount, type, ref isOut ); } if ( stepLengthCm < _minStepLengthCm ) { type = 0; _stepCount = GetNextStepCount( _stepCount, type, ref isOut ); } if ( stepLengthCm <= _maxStepLengthCm && stepLengthCm >= _minStepLengthCm ) { _stepLength = stepSpanCm / _inchCm * GetDpi() / _stepCount; break; } /* 已超出或小于最大步进长度 */ if ( isOut ) { _stepSpan = GetNextStepSpan( _stepSpan, type ); continue; } } break; } } } private int GetNextStepCount( int stepCount, int type, ref bool isOut ) { int result = stepCount; isOut = false; switch ( type ) { case 0: { if ( stepCount == 20 ) { result = 10; }else { isOut = true; } break; } case 1: { if ( stepCount == 10 ) { result = 20; }else { isOut = true; } break; } } return(result); } private int GetNextStepSpan( int stepSpan, int type ) { /* 100 200 500 */ string stepCountStr = stepSpan.ToString(); string resultStr = string.Empty; switch ( DisplayUnit ) { case StaffDisplayUnit.pixel: { switch ( type ) { case 0: { if ( stepCountStr.IndexOf( '5' ) > -1 ) { resultStr = GetNumberAndZeroNum( 1, stepCountStr.Length ); }else if ( stepCountStr.IndexOf( '2' ) > -1 ) { resultStr = GetNumberAndZeroNum( 5, stepCountStr.Length - 1 ); }else if ( stepCountStr.IndexOf( '1' ) > -1 ) { resultStr = GetNumberAndZeroNum( 2, stepCountStr.Length - 1 ); } break; } case 1: { if ( stepCountStr.IndexOf( '5' ) > -1 ) { resultStr = GetNumberAndZeroNum( 2, stepCountStr.Length - 1 ); }else if ( stepCountStr.IndexOf( '2' ) > -1 ) { resultStr = GetNumberAndZeroNum( 1, stepCountStr.Length - 1 ); }else if ( stepCountStr.IndexOf( '1' ) > -1 ) { resultStr = GetNumberAndZeroNum( 5, stepCountStr.Length - 2 ); } break; } } break; } } return(Common.Utility.ConvertInt( resultStr ) ); } private string GetNumberAndZeroNum( int num, int zeroNum ) { string result = string.Empty; result += num; for ( int i = 0; i < zeroNum; i++ ) { result += "0"; } return(result); } private int GetDpi() { switch ( DisplayType ) { case StaffDisplayType.Horizontal: { return(Dpi.DpiX); } case StaffDisplayType.Vertical: { return(Dpi.DpiY); } default: { return(Dpi.DpiX); } } } private void GetActualLength() { switch ( DisplayType ) { case StaffDisplayType.Horizontal: { _actualLength = this.ActualWidth; break; } case StaffDisplayType.Vertical: { _actualLength = this.ActualHeight; break; } } } } public enum StaffDisplayType { Horizontal, Vertical } public enum StaffDisplayUnit { cm, pixel } public enum LinePercent { P20 = 20, P30 = 30, P50 = 50, P70 = 70, P100 = 100 } public struct Dpi { public int DpiX { get; set; } public int DpiY { get; set; } } public struct Position { public int Value { get; set; } public int CurrentStepIndex { get; set; } } }
2012年7月14 于郑州 天气:晴
博客搬家从blog.163.com/gsralex 搬家到 www.cnblogs.com/gsralex
博文全部为原创,谢绝一切转载
博文全部为原创,谢绝一切转载