public KryptonKnobControlEnhanced() { _dottedPen = new Pen(KryptonKnobUtilities.GetDarkColour(BackColor, 40)) { DashStyle = DashStyle.Dash, DashCap = DashCap.Flat }; InitializeComponent(); _knobTypeface = new Font(Font.FontFamily, Font.Size); _scaleTypeface = new Font(Font.FontFamily, Font.Size); // Properties initialisation // "start angle" and "end angle" possible values: // 90 = bottom (minimum value for "start angle") // 180 = left // 270 = top // 360 = right // 450 = bottom again (maximum value for "end angle") // So the couple (90, 450) will give an entire circle and the couple (180, 360) will give half a circle. _startAngle = 135; _endAngle = 405; _deltaAngle = _endAngle - _startAngle; _minimum = 0; _maximum = 100; _scaleDivisions = 11; _scaleSubDivisions = 4; _mouseWheelBarPartitions = 10; _scaleColour = Color.Black; _knobBackColour = Color.White; SetDimensions(); if (((_palette != null))) { _palette.PalettePaint += OnPalettePaint; } KryptonManager.GlobalPaletteChanged += OnGlobalPaletteChanged; _palette = KryptonManager.CurrentGlobalPalette; _paletteRedirect = new PaletteRedirect(_palette); _paletteBack = new PaletteBackInheritRedirect(_paletteRedirect); _paletteBorder = new PaletteBorderInheritRedirect(_paletteRedirect); _paletteContent = new PaletteContentInheritRedirect(_paletteRedirect); InitiliseColourScheme(); }
protected override void OnMouseWheel(MouseEventArgs e) { base.OnMouseWheel(e); if (_isFocused && _isKnobRotating && KryptonKnobUtilities.IsPointinRectangle(new Point(e.X, e.Y), _rKnob)) { // the Delta value is always 120, as explained in MSDN int v = (e.Delta / 120) * (_maximum - _minimum) / _mouseWheelBarPartitions; SetProperValue(Value + v); // Avoid to send MouseWheel event to the parent container ((HandledMouseEventArgs)e).Handled = true; } }
/// <summary> /// gets knob position that is to be drawn on control minus a small amount in order that the knob position stay inside the circle. /// </summary> /// <returns>Point that describes current knob position</returns> private Point GetKnobPosition(int l) { float cx = _pKnob.X; float cy = _pKnob.Y; // FAB: 21/08/18 float degree = _deltaAngle * (this.Value - _minimum) / (_maximum - _minimum); degree = KryptonKnobUtilities.GetRadian(degree + _startAngle); Point Pos = new Point(0, 0) { X = (int)(cx + l * Math.Cos(degree)), Y = (int)(cy + l * Math.Sin(degree)) }; return(Pos); }
protected override void OnMouseUp(MouseEventArgs e) { if (KryptonKnobUtilities.IsPointinRectangle(new Point(e.X, e.Y), _rKnob)) { if (_isFocused == true && _isKnobRotating == true) { // Change value is allowed only only after 2nd click this.Value = this.GetValueFromPosition(new Point(e.X, e.Y)); } else { // 1st click = only focus _isFocused = true; _isKnobRotating = true; } } this.Cursor = Cursors.Default; }
protected override void OnMouseDown(MouseEventArgs e) { if (KryptonKnobUtilities.IsPointinRectangle(new Point(e.X, e.Y), _rKnob)) { if (_isFocused) { // was already selected // Start Rotation of knob only if it was selected before _isKnobRotating = true; } else { // Was not selected before => select it Focus(); _isFocused = true; _isKnobRotating = false; // disallow rotation, must click again // draw dotted border to show that it is selected Invalidate(); } } }
/// <summary> /// Set position of button inside its rectangle to insure that divisions will fit. /// </summary> private void SetDimensions() { Font font; // Rectangle float x, y, w, h; x = 0; y = 0; w = h = Width; // Calculate ratio _drawRatio = w / 150; if (_drawRatio == 0.0) { _drawRatio = 1; } if (_showLargeScale) { Graphics Gr = this.CreateGraphics(); string strvalmax = _maximum.ToString(); string strvalmin = _minimum.ToString(); string strval = strvalmax.Length > strvalmin.Length ? strvalmax : strvalmin; double val = Convert.ToDouble(strval); //double val = _maximum; String str = String.Format("{0,0:D}", (int)val); float fSize = _scaleTypeface.Size; if (_scaleTypefaceAutoSize) { fSize = (float)(6F * _drawRatio); if (fSize < 6) { fSize = 6; } font = new Font(_scaleTypeface.FontFamily, fSize); } else { fSize = _scaleTypeface.Size; font = new Font(_scaleTypeface.FontFamily, _scaleTypeface.Size); } SizeF strsize = Gr.MeasureString(str, font); // Graduations outside _gradLength = 4 * _drawRatio; if (_drawDivInside) { // Graduations inside : remove only 2*8 pixels //x = y = 8; x = y = _gradLength; w = Width - 2 * x; } else { // remove 2 * size of text and length of graduation //_gradLength = 4 * _drawRatio; int strw = (int)strsize.Width; int strh = (int)strsize.Height; int max = Math.Max(strw, strh); x = max; y = max; w = (int)(Width - 2 * max - _gradLength); } if (w <= 0) { w = 1; } h = w; // Rectangle of the rounded knob this._rKnob = new Rectangle((int)x, (int)y, (int)w, (int)h); Gr.Dispose(); } else { this._rKnob = new Rectangle(0, 0, Width, Height); } // Center of knob this._pKnob = new Point(_rKnob.X + _rKnob.Width / 2, _rKnob.Y + _rKnob.Height / 2); // create offscreen image this._offScreenImage = new Bitmap(this.Width, this.Height); // create offscreen graphics this._gOffScreen = Graphics.FromImage(_offScreenImage); // Depends on retangle dimensions // create LinearGradientBrush for creating knob _brushKnob = new LinearGradientBrush( _rKnob, KryptonKnobUtilities.GetLightColour(_knobBackColour, 55), KryptonKnobUtilities.GetDarkColour(_knobBackColour, 55), LinearGradientMode.ForwardDiagonal); // create LinearGradientBrush for knobPointer _brushKnobPointer = new LinearGradientBrush( _rKnob, KryptonKnobUtilities.GetLightColour(_pointerColour, 55), KryptonKnobUtilities.GetDarkColour(_pointerColour, 55), LinearGradientMode.ForwardDiagonal); }
/// <summary> /// Draw graduations /// </summary> /// <param name="Gr"></param> /// <param name="rc">Knob rectangle</param> /// <returns></returns> private bool DrawDivisions(Graphics Gr, RectangleF rc) { if (this == null) { return(false); } float cx = _pKnob.X; float cy = _pKnob.Y; float w = rc.Width; float h = rc.Height; float tx; float ty; float incr = KryptonKnobUtilities.GetRadian((_endAngle - _startAngle) / ((_scaleDivisions - 1) * (_scaleSubDivisions + 1))); float currentAngle = KryptonKnobUtilities.GetRadian(_startAngle); float radius = (float)(rc.Width / 2); float rulerValue = (float)_minimum; Font font; Pen penL = new Pen(_scaleColour, (2 * _drawRatio)); Pen penS = new Pen(_scaleColour, (1 * _drawRatio)); SolidBrush br = new SolidBrush(_scaleColour); PointF ptStart = new PointF(0, 0); PointF ptEnd = new PointF(0, 0); int n = 0; if (_showLargeScale) { // Size of maxi string string strvalmax = _maximum.ToString(); string strvalmin = _minimum.ToString(); string strval = strvalmax.Length > strvalmin.Length ? strvalmax : strvalmin; double val = Convert.ToDouble(strval); //double val = _maximum; String str = String.Format("{0,0:D}", (int)val); float fSize; SizeF strsize; if (_scaleTypefaceAutoSize) { fSize = (float)(6F * _drawRatio); if (fSize < 6) { fSize = 6; } } else { fSize = _scaleTypeface.Size; } font = new Font(_scaleTypeface.FontFamily, fSize); strsize = Gr.MeasureString(str, font); int strw = (int)strsize.Width; int strh = (int)strsize.Height; int wmax = Math.Max(strw, strh); float l = 0; _gradLength = 2 * _drawRatio; for (; n < _scaleDivisions; n++) { // draw divisions ptStart.X = (float)(cx + (radius) * Math.Cos(currentAngle)); ptStart.Y = (float)(cy + (radius) * Math.Sin(currentAngle)); ptEnd.X = (float)(cx + (radius + _gradLength) * Math.Cos(currentAngle)); ptEnd.Y = (float)(cy + (radius + _gradLength) * Math.Sin(currentAngle)); Gr.DrawLine(penL, ptStart, ptEnd); //Draw graduation values val = Math.Round(rulerValue); str = String.Format("{0,0:D}", (int)val); // If autosize if (_scaleTypefaceAutoSize) { strsize = Gr.MeasureString(str, new Font(_scaleTypeface.FontFamily, fSize)); } else { strsize = Gr.MeasureString(str, new Font(_scaleTypeface.FontFamily, _scaleTypeface.Size)); } if (_drawDivInside) { // graduations values inside the knob l = (int)radius - (wmax / 2) - 2; tx = (float)(cx + l * Math.Cos(currentAngle)); ty = (float)(cy + l * Math.Sin(currentAngle)); } else { // graduation values outside the knob //l = (Width / 2) - (wmax / 2) ; l = radius + _gradLength + wmax / 2; tx = (float)(cx + l * Math.Cos(currentAngle)); ty = (float)(cy + l * Math.Sin(currentAngle)); } Gr.DrawString(str, font, br, tx - (float)(strsize.Width * 0.5), ty - (float)(strsize.Height * 0.5)); rulerValue += (float)((_maximum - _minimum) / (_scaleDivisions - 1)); if (n == _scaleDivisions - 1) { break; } // Subdivisions #region SubDivisions if (_scaleDivisions <= 0) { currentAngle += incr; } else { for (int j = 0; j <= _scaleSubDivisions; j++) { currentAngle += incr; // if user want to display small graduations if (_showSmallScale) { ptStart.X = (float)(cx + radius * Math.Cos(currentAngle)); ptStart.Y = (float)(cy + radius * Math.Sin(currentAngle)); ptEnd.X = (float)(cx + (radius + _gradLength / 2) * Math.Cos(currentAngle)); ptEnd.Y = (float)(cy + (radius + _gradLength / 2) * Math.Sin(currentAngle)); Gr.DrawLine(penS, ptStart, ptEnd); } } } #endregion } font.Dispose(); } return(true); }
/// <summary> /// Draw the pointer of the knob (a small button inside the main button) /// </summary> /// <param name="Gr"></param> private void DrawPointer(Graphics Gr) { try { float radius = (float)(_rKnob.Width / 2); // Draw a line if (_pointerStyle == KnobPointerStyles.LINE) { int l = (int)radius / 2; int w = l / 4; Point[] pt = GetKnobLine(Gr, l); Gr.DrawLine(new Pen(_pointerColour, w), pt[0], pt[1]); } else { // Draw a circle int w = 0; int h = 0; int l = 0; string strvalmax = _maximum.ToString(); string strvalmin = _minimum.ToString(); string strval = strvalmax.Length > strvalmin.Length ? strvalmax : strvalmin; double val = Convert.ToDouble(strval); String str = String.Format("{0,0:D}", (int)val); float fSize; SizeF strsize; if (_scaleTypefaceAutoSize) { // Use font family = _scaleTypeface, but size = automatic fSize = (float)(6F * _drawRatio); if (fSize < 6) { fSize = 6; } strsize = Gr.MeasureString(str, new Font(_scaleTypeface.FontFamily, fSize)); } else { // Use font family = _scaleTypeface, but size = fixed fSize = _scaleTypeface.Size; strsize = Gr.MeasureString(str, _scaleTypeface); } int strw = (int)strsize.Width; int strh = (int)strsize.Height; w = Math.Max(strw, strh); // radius of small circle l = (int)radius - w / 2; h = w; Point Arrow = this.GetKnobPosition(l - 2); // Remove 2 pixels to offset the small circle inside the knob // Draw pointer arrow that shows knob position Rectangle rPointer = new Rectangle(Arrow.X - w / 2, Arrow.Y - w / 2, w, h); //KryptonKnobUtilities.DrawInsetCircle(ref Gr, rPointer, new Pen(_pointerColour)); KryptonKnobUtilities.DrawInsetCircle(ref Gr, rPointer, new Pen(KryptonKnobUtilities.GetLightColour(_pointerColour, 55))); Gr.FillEllipse(_brushKnobPointer, rPointer); } } catch (Exception ex) { Console.Write(ex.Message); } }
/// <summary> /// return 2 points of a line starting from the center of the knob to the periphery /// </summary> /// <param name="l"></param> /// <returns></returns> private Point[] GetKnobLine(Graphics Gr, int l) { Point[] pret = new Point[2]; float cx = _pKnob.X; float cy = _pKnob.Y; float radius = (float)(_rKnob.Width / 2); // FAB: 21/08/18 float degree = _deltaAngle * (this.Value - _minimum) / (_maximum - _minimum); degree = KryptonKnobUtilities.GetRadian(degree + _startAngle); double val = _maximum; String str = String.Format("{0,0:D}", (int)val); float fSize; SizeF strsize; if (!_scaleTypefaceAutoSize) { fSize = _scaleTypeface.Size; strsize = Gr.MeasureString(str, _scaleTypeface); } else { fSize = (float)(6F * _drawRatio); if (fSize < 6) { fSize = 6; } _knobTypeface = new Font(_scaleTypeface.FontFamily, fSize); strsize = Gr.MeasureString(str, _knobTypeface); } int strw = (int)strsize.Width; int strh = (int)strsize.Height; int w = Math.Max(strw, strh); Point Pos = new Point(0, 0); if (_drawDivInside) { // Center (from) Pos.X = (int)(cx + (radius / 10) * Math.Cos(degree)); Pos.Y = (int)(cy + (radius / 10) * Math.Sin(degree)); pret[0] = new Point(Pos.X, Pos.Y); // External (to) Pos.X = (int)(cx + (radius - w) * Math.Cos(degree)); Pos.Y = (int)(cy + (radius - w) * Math.Sin(degree)); pret[1] = new Point(Pos.X, Pos.Y); } else { // Internal (from) Pos.X = (int)(cx + (radius - _drawRatio * 10 - l) * Math.Cos(degree)); Pos.Y = (int)(cy + (radius - _drawRatio * 10 - l) * Math.Sin(degree)); pret[0] = new Point(Pos.X, Pos.Y); // External (to) Pos.X = (int)(cx + (radius - 4) * Math.Cos(degree)); Pos.Y = (int)(cy + (radius - 4) * Math.Sin(degree)); pret[1] = new Point(Pos.X, Pos.Y); } return(pret); }