using System;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Windows.Forms;
using System.Collections.Generic;
[assembly: CLSCompliant(true)]
namespace PtzControl {
public partial class PtzUserControl : UserControl {
#region Private Members
/// <summary>
/// Distance between zoom rectangles and the left and right side of the control.
/// </summary>
private const int _marginForZoomRectangles = 10;
/// <summary>
/// Distance between the upper portion and the lower portion (i.e the zoom portion).
/// </summary>
private const int _marginOuterToZoomRectangles = 7;
/// <summary>
/// Encapsulates outer circle.
/// </summary>
private Rectangle _outerRectangle;
/// <summary>
/// Encapsulates middle circle.
/// </summary>
private Rectangle _middleRectangle;
/// <summary>
/// Encapsulates inner circle.
/// </summary>
private Rectangle _innerRectangle;
/// <summary>
/// Holds the Zoom In region.
/// </summary>
private Rectangle _zoomInRectangle;
/// <summary>
/// Holds Zoom Out region.
/// </summary>
private Rectangle _zoomOutRectangle;
/// <summary>
/// Region between outer circle and the middle circle.
/// </summary>
private Region _outerCircleRegion;
/// <summary>
/// Region between the middle region and the inner region.
/// </summary>
private Region _middleCircleRegion;
/// <summary>
/// Inner circlular region.
/// </summary>
private Region _innerCircleRegion;
/// <summary>
/// Pan Up Button region in OuterCircle region.
/// </summary>
private Region _upButtonRegion;
/// <summary>
/// Pan Down Button region in OuterCircle region.
/// </summary>
private Region _downButtonRegion;
/// <summary>
/// Pan Left Button region in OuterCircle region.
/// </summary>
private Region _leftButtonRegion;
/// <summary>
/// Pan Right Button region in OuterCircle region.
/// </summary>
private Region _rightButtonRegion;
/// <summary>
/// Zoom In Button region.
/// </summary>
private Region _zoomInButtonRegion;
/// <summary>
/// Zoom Out Button region.
/// </summary>
private Region _zoomOutButtonRegion;
/// <summary>
/// Pen to draw direction angles, zoom in and zoom out lines.
/// </summary>
private Pen _penToDrawLines;
/// <summary>
/// Brush used to fill the control with the default color.
/// </summary>
private SolidBrush _defaultBrush;
/// <summary>
/// PtzControl to fill the control with the hover color.
/// </summary>
private SolidBrush _hoverBrush;
/// <summary>
/// Brush used to fill the inner circle.
/// </summary>
private SolidBrush _whiteBrush;
/// <summary>
/// Graphics object fills the regions on focus gain and relese condition using respective brushes
/// (i.e hoveBrush ot defaultBrush).
/// </summary>
private Graphics _graphics;
/// <summary>
/// In the Mouse click event it is used to get where the house hasbeen clicked.
/// It stores the current mouse position in context with the mouse region.
/// </summary>
private MouseLocation _currentMouseLocation;
/// <summary>
/// Holds the previous mouse location.
/// </summary>
private MouseLocation _previousMouseLocation;
/// <summary>
/// It used to create the regions.
/// </summary>
private readonly GraphicsPath _graphicsPathToSetRegins = new GraphicsPath();
/// <summary>
/// Virtical Line in the Zoom In Button Plus Sign.
/// </summary>
private readonly List<Point> _zoomInVirticleLine = new List<Point> {
new Point(_marginForZoomRectangles + 10, 80 + _marginOuterToZoomRectangles + 15),
new Point(_marginForZoomRectangles + 20, 80 + _marginOuterToZoomRectangles + 15)};
/// <summary>
/// Horizontal Line in the Zoom In Button Plus Sign.
/// </summary>
private readonly List<Point> _zoomInHorizontolLine = new List<Point> {
new Point(_marginForZoomRectangles + 15, 80 + _marginOuterToZoomRectangles + 10),
new Point(_marginForZoomRectangles + 15, 80 + _marginOuterToZoomRectangles + 20)};
/// <summary>
/// Horizontal Line in the Zoom Out Button Minus Sign.
/// </summary>
private readonly List<Point> _zoomOutLine = new List<Point> {
new Point(_marginForZoomRectangles + 30 + 1 + 10, 80 + _marginOuterToZoomRectangles + 15),
new Point(_marginForZoomRectangles + 30 + 1 + 20, 80 + _marginOuterToZoomRectangles + 15)};
/// <summary>
/// Points in angle on the Up button.
/// </summary>
private readonly List<Point> _upButtonAngle = new List<Point> {
new Point(40, 10), new Point(35, 15), new Point(40, 10), new Point(45, 15)};
/// <summary>
/// Points in angle on Left button.
/// </summary>
private readonly List<Point> _leftButtonAngle = new List<Point> {
new Point(10, 40), new Point(15, 35), new Point(10, 40), new Point(15, 45)};
/// <summary>
/// Points in andle on right button.
/// </summary>
private readonly List<Point> _rightButtonAngle = new List<Point> {
new Point(70, 40), new Point(65, 35), new Point(70, 40), new Point(65, 45)};
/// <summary>
/// Points in angle on down button.
/// </summary>
private readonly List<Point> _downButtonAngle = new List<Point> {
new Point(40, 70), new Point(35, 65), new Point(40, 70), new Point(45, 65)};
#endregion
#region Constructor
/// <summary>
/// Creates the regions and Initialises the graphics componants.
/// **The initilization sequence must be maintained as the different componants are dependent of
/// others, here regions are dependent of the rectangles and so rectangles have to be initialize before the
/// regios.
/// </summary>
public PtzUserControl() {
InitializeComponent();
InitializeRectangles();
InitializeRegions();
InitializeGraphicsComponants();
}
#endregion
#region Private Methods
/// <summary>
/// Initilizes all the rectangles that are used to drall the control.
/// </summary>
private void InitializeRectangles() {
int _outerCircleDiameter = 80;
int _middleCircleDiameter = 32;
int _innerCircleDiameter = 12;
int _zoomRectangleWidth = 30;
int _marginBetweenOuterAndMiddleRectangle = (_outerCircleDiameter / 2 - _middleCircleDiameter / 2);
int _marginBetweenMiddleAndInnerRectangle = _marginBetweenOuterAndMiddleRectangle +
(_middleCircleDiameter / 2 - _innerCircleDiameter / 2);
_outerRectangle = new Rectangle(0, 0, _outerCircleDiameter, _outerCircleDiameter);
_middleRectangle = new Rectangle(_marginBetweenOuterAndMiddleRectangle,
_marginBetweenOuterAndMiddleRectangle, _middleCircleDiameter, _middleCircleDiameter);
_innerRectangle = new Rectangle(_marginBetweenMiddleAndInnerRectangle,
_marginBetweenMiddleAndInnerRectangle, _innerCircleDiameter, _innerCircleDiameter);
_zoomInRectangle = new Rectangle(_marginForZoomRectangles,
_outerCircleDiameter + _marginOuterToZoomRectangles, _zoomRectangleWidth, _zoomRectangleWidth);
_zoomOutRectangle = new Rectangle(_marginForZoomRectangles + _zoomRectangleWidth,
_outerCircleDiameter + _marginOuterToZoomRectangles, _zoomRectangleWidth, _zoomRectangleWidth);
}
/// <summary>
/// Initializes the graphics brushes and pen with proper colors.
/// It sets the _currentMouseLocation to NoneLocation as initialy the mouse is not on any region.
/// </summary>
private void InitializeGraphicsComponants() {
_currentMouseLocation = MouseLocation.NoneRegion;
// Default color is used to fill the control.
Color _defaultColor = Color.FromArgb(120, 128, 128, 128);
// Hover color is used to fill the region when mouses hover on it.
Color _hoverColor = Color.FromArgb(150, 64, 64, 64);
// Pen width used to draw line of this width.
const byte _penWidth = 2;
_graphics = CreateGraphics();
_graphics.SmoothingMode = SmoothingMode.AntiAlias;
_whiteBrush = new SolidBrush(Color.White);
_defaultBrush = new SolidBrush(_defaultColor);
_hoverBrush = new SolidBrush(_hoverColor);
_penToDrawLines = new Pen(_defaultBrush) {
Width = _penWidth,
Color = Color.White,
StartCap = LineCap.Round,
EndCap = LineCap.Round
};
}
/// <summary>
/// Create the Inner circular region.
/// </summary>
private void CreateInnerRegion() {
_innerCircleRegion = new Region();
_graphicsPathToSetRegins.Reset();
_graphicsPathToSetRegins.AddEllipse(_innerRectangle);
_innerCircleRegion.Intersect(_graphicsPathToSetRegins);
}
/// <summary>
/// Create the ZoomOut rectangular region.
/// </summary>
private void CreateZoomOutRegion() {
_zoomOutButtonRegion = new Region();
_zoomOutButtonRegion.MakeEmpty();
_zoomOutButtonRegion.Union(_zoomOutRectangle);
}
/// <summary>
/// Create ZoomIn rectangular region.
/// </summary>
private void CreateZoomInRegion() {
_zoomInButtonRegion = new Region();
_zoomInButtonRegion.MakeEmpty();
_zoomInButtonRegion.Union(_zoomInRectangle);
}
/// <summary>
/// Create Right button region.
/// </summary>
private void CreateRightButtonRegion() {
_rightButtonRegion = new Region();
_graphicsPathToSetRegins.Reset();
_graphicsPathToSetRegins.AddPie(_outerRectangle, 315, 90);
_rightButtonRegion.Intersect(_graphicsPathToSetRegins);
_rightButtonRegion.Exclude(_middleCircleRegion);
_rightButtonRegion.Exclude(_innerCircleRegion);
}
/// <summary>
/// Create Up Button region.
/// </summary>
private void CreateUpButtonRegion() {
_upButtonRegion = new Region();
_graphicsPathToSetRegins.Reset();
_graphicsPathToSetRegins.AddPie(_outerRectangle, 225, 90);
_upButtonRegion.Intersect(_graphicsPathToSetRegins);
_upButtonRegion.Exclude(_middleCircleRegion);
_upButtonRegion.Exclude(_innerCircleRegion);
}
/// <summary>
/// Create Left button region.
/// </summary>
private void CreateLeftButtonRegion() {
_leftButtonRegion = new Region();
_graphicsPathToSetRegins.Reset();
_graphicsPathToSetRegins.AddPie(_outerRectangle, 135, 90);
_leftButtonRegion.Intersect(_graphicsPathToSetRegins);
_leftButtonRegion.Exclude(_middleCircleRegion);
_leftButtonRegion.Exclude(_innerCircleRegion);
}
/// <summary>
/// Create Down button region.
/// </summary>
private void CreateDownButtonRegin() {
_downButtonRegion = new Region();
_graphicsPathToSetRegins.Reset();
_graphicsPathToSetRegins.AddPie(_outerRectangle, 45, 90);
_downButtonRegion.Intersect(_graphicsPathToSetRegins);
_downButtonRegion.Exclude(_middleCircleRegion);
_downButtonRegion.Exclude(_innerCircleRegion);
}
/// <summary>
/// Create Middle Circular button region.
/// </summary>
private void CreateMiddleRegion() {
_middleCircleRegion = new Region();
_graphicsPathToSetRegins.Reset();
_middleCircleRegion.MakeEmpty();
_graphicsPathToSetRegins.AddEllipse(_middleRectangle);
_graphicsPathToSetRegins.AddEllipse(_innerRectangle);
_middleCircleRegion.Union(_graphicsPathToSetRegins);
}
/// <summary>
/// Create outer Circular region.
/// This region include Complete outer circle excluding the middle and the inner circular regions.
/// </summary>
private void CreateOuterRegion() {
_outerCircleRegion = new Region();
_graphicsPathToSetRegins.Reset();
_outerCircleRegion.MakeEmpty();
_graphicsPathToSetRegins.AddEllipse(_outerRectangle);
_graphicsPathToSetRegins.AddEllipse(_middleRectangle);
_outerCircleRegion.Union(_graphicsPathToSetRegins);
}
/// <summary>
/// Creates all the region of the control.
/// </summary>
private void InitializeRegions() {
CreateInnerRegion();
CreateOuterRegion();
CreateMiddleRegion();
CreateDownButtonRegin();
CreateLeftButtonRegion();
CreateUpButtonRegion();
CreateRightButtonRegion();
CreateZoomInRegion();
CreateZoomOutRegion();
}
/// <summary>
/// When mouse is over the outer circle then according to the current position of the
/// mouse the proper button is repainted with hover Color.
/// </summary>
/// <param name="location">Point of mouse location.</param>
private void CheckButtonsInOuterRegion(Point location) {
if (_leftButtonRegion.IsVisible(location)) {
SetFocusOnOuterCircleButtons(_leftButtonRegion, _leftButtonAngle, MouseLocation.LeftButtonRegion);
} else if (_upButtonRegion.IsVisible(location)) {
SetFocusOnOuterCircleButtons(_upButtonRegion, _upButtonAngle, MouseLocation.UpButtonRegion);
} else if (_rightButtonRegion.IsVisible(location)) {
SetFocusOnOuterCircleButtons(_rightButtonRegion, _rightButtonAngle, MouseLocation.RightButtonRegion);
} else if (_downButtonRegion.IsVisible(location)) {
SetFocusOnOuterCircleButtons(_downButtonRegion, _downButtonAngle, MouseLocation.DownButtonRegion);
}
}
/// <summary>
/// Repaints the button on outer circle buttons i.e Up, Right, Down and Left with hover brush.
/// </summary>
/// <param name="region">Region to fill with hover color.</param>
/// <param name="angle">Line Angle of the respective region.</param>
/// <param name="location">MouseLocation of the region.</param>
private void SetFocusOnOuterCircleButtons(Region region, List<Point> angle, MouseLocation location) {
if (_previousMouseLocation == location)
return;
_graphics.FillRegion(_hoverBrush, region);
_graphics.DrawLine(_penToDrawLines, angle[0], angle[1]);
_graphics.DrawLine(_penToDrawLines, angle[2], angle[3]);
_currentMouseLocation = location;
}
/// <summary>
/// Repaints the Middle Circle button if the mouse moves over it.
/// </summary>
private void SetFocusOnMiddleCircleButton() {
_currentMouseLocation = MouseLocation.MiddleCircleRegion;
if (_previousMouseLocation != MouseLocation.MiddleCircleRegion) {
_graphics.FillRegion(_hoverBrush, _middleCircleRegion);
}
}
/// <summary>
/// Repaints the Zoom In button if the mouse moves over it.
/// </summary>
private void SetFocusOnZoomInButton() {
if (_previousMouseLocation == MouseLocation.ZoomInButtonRegion)
return;
_graphics.FillRegion(_hoverBrush, _zoomInButtonRegion);
_graphics.DrawLines(_penToDrawLines, _zoomInVirticleLine.ToArray());
_graphics.DrawLines(_penToDrawLines, _zoomInHorizontolLine.ToArray());
_currentMouseLocation = MouseLocation.ZoomInButtonRegion;
}
/// <summary>
/// Repaints the Left Zoom Out if the mouse moves over it.
/// </summary>
private void SetFoucsOnZoomOutButton() {
if (_previousMouseLocation == MouseLocation.ZoomOutButtonRegion)
return;
_graphics.FillRegion(_hoverBrush, _zoomOutButtonRegion);
_graphics.DrawLines(_penToDrawLines, _zoomOutLine.ToArray());
_currentMouseLocation = MouseLocation.ZoomOutButtonRegion;
}
/// <summary>
/// Repaints the button on outer circle i.e Up, Right, Down and Left with default brush.
/// with the default color.
/// </summary>
/// <param name="region">Region to repaint with the default color.</param>
/// <param name="angle">MouseLocation of the region.</param>
private void ReleseFocusFromOuterCircleButtons(Region region, List<Point> angle) {
Invalidate(region);
_graphics.FillRegion(_defaultBrush, region);
_graphics.DrawLine(_penToDrawLines, angle[0], angle[1]);
_graphics.DrawLine(_penToDrawLines, angle[2], angle[3]);
// _toolTip.Hide(this);
}
/// <summary>
/// Repaints the Middle button region with default color.
/// </summary>
private void ReleseFocusFromMidleCircleButton() {
Invalidate(_middleCircleRegion);
_graphics.FillRegion(_defaultBrush, _middleCircleRegion);
// _toolTip.Hide(this);
}
/// <summary>
/// Repaints the Zoom In button region with default color.
/// </summary>
private void ReleseFocusFromZoomInButton() {
Invalidate(_zoomInButtonRegion);
_graphics.FillRegion(_defaultBrush, _zoomInButtonRegion);
_graphics.DrawLines(_penToDrawLines, _zoomInHorizontolLine.ToArray());
_graphics.DrawLines(_penToDrawLines, _zoomInVirticleLine.ToArray());
// _toolTip.Hide(this);
}
/// <summary>
/// Repaints the Zoom Out button region with default color.
/// </summary>
private void ReleseFocusFromZoomOutButton() {
Invalidate(_zoomOutButtonRegion);
_graphics.FillRegion(_defaultBrush, _zoomOutButtonRegion);
_graphics.DrawLines(_penToDrawLines, _zoomOutLine.ToArray());
// _toolTip.Hide(this);
}
/// <summary>
/// Creates the complete control.
/// </summary>
/// <param name="g">An Instane of Graphics use to draw all the region</param>
private void FillControl(Graphics g) {
g.FillEllipse(_defaultBrush, _outerRectangle);
g.FillRegion(_defaultBrush, _zoomInButtonRegion);
g.FillRegion(_defaultBrush, _zoomOutButtonRegion);
g.FillEllipse(_whiteBrush, _innerRectangle);
DrawAllLines(g);
}
/// <summary>
/// Draws all the lines.
/// </summary>
/// <param name="g"></param>
private void DrawAllLines(Graphics g) {
g.DrawLine(_penToDrawLines, _upButtonAngle[0], _upButtonAngle[1]);
g.DrawLine(_penToDrawLines, _upButtonAngle[2], _upButtonAngle[3]);
g.DrawLine(_penToDrawLines, _downButtonAngle[0], _downButtonAngle[1]);
g.DrawLine(_penToDrawLines, _downButtonAngle[2], _downButtonAngle[3]);
g.DrawLine(_penToDrawLines, _leftButtonAngle[0], _leftButtonAngle[1]);
g.DrawLine(_penToDrawLines, _leftButtonAngle[2], _leftButtonAngle[3]);
g.DrawLine(_penToDrawLines, _rightButtonAngle[0], _rightButtonAngle[1]);
g.DrawLine(_penToDrawLines, _rightButtonAngle[2], _rightButtonAngle[3]);
g.DrawLines(_penToDrawLines, _zoomInHorizontolLine.ToArray());
g.DrawLines(_penToDrawLines, _zoomInVirticleLine.ToArray());
g.DrawLines(_penToDrawLines, _zoomOutLine.ToArray());
}
/// <summary>
/// Releses the focus from the region pointed to by previousMouseLocation.
/// </summary>
private void ReleseFocusFromPreviousRegion() {
switch (_previousMouseLocation) {
case MouseLocation.UpButtonRegion:
ReleseFocusFromOuterCircleButtons(_upButtonRegion, _upButtonAngle);
break;
case MouseLocation.RightButtonRegion:
ReleseFocusFromOuterCircleButtons(_rightButtonRegion, _rightButtonAngle);
break;
case MouseLocation.LeftButtonRegion:
ReleseFocusFromOuterCircleButtons(_leftButtonRegion, _leftButtonAngle);
break;
case MouseLocation.DownButtonRegion:
ReleseFocusFromOuterCircleButtons(_downButtonRegion, _downButtonAngle);
break;
case MouseLocation.ZoomOutButtonRegion:
ReleseFocusFromZoomOutButton();
break;
case MouseLocation.ZoomInButtonRegion:
ReleseFocusFromZoomInButton();
break;
case MouseLocation.MiddleCircleRegion:
ReleseFocusFromMidleCircleButton();
break;
}
}
#endregion
#region Events
/// <summary>
/// Initializes the graphics objects and paints the control.
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void PtzControlPaint(object sender, PaintEventArgs e) {
e.Graphics.SmoothingMode = SmoothingMode.AntiAlias;
FillControl(e.Graphics);
}
/// <summary>
/// Fills the region on which the mouse is hovering with _hoverBrush
/// and as per the mouse location the current and the previous mouse
/// location is managed.
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void PtzControlMouseMove(object sender, MouseEventArgs e) {
// Soters the current region in the previous location as when mouse mouse
// in other location the current location is set to the new locaiton and
// the previous location is presearved in the _previousMouseLocation.
_previousMouseLocation = _currentMouseLocation;
if (_outerCircleRegion.IsVisible(e.Location)) {
CheckButtonsInOuterRegion(e.Location);
} else if (_middleCircleRegion.IsVisible(e.Location)) {
SetFocusOnMiddleCircleButton();
} else if (_zoomInButtonRegion.IsVisible(e.Location)) {
SetFocusOnZoomInButton();
} else if (_zoomOutButtonRegion.IsVisible(e.Location)) {
SetFoucsOnZoomOutButton();
} else if (_innerCircleRegion.IsVisible(e.Location)) {
_currentMouseLocation = MouseLocation.InnerCircleRegion;
} else {
_currentMouseLocation = MouseLocation.NoneRegion;
}
// The focus relese is only allowed if the mouse mouve over other region
// from the current mouse location.
// by this mechnism the repainting of the region on the mouse is on is
// prevented as so avoids the flickering of the control.
if (_previousMouseLocation != _currentMouseLocation) {
ReleseFocusFromPreviousRegion();
}
}
/// <summary>
/// Detects the mouse is clicked.
/// Strings used in this fuctions are for temporary purpose actual code in inserted for click events
/// in respective click condition and fucntionality.
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void PtzControlClick(object sender, EventArgs e) {
string msg = null;
switch (_currentMouseLocation) {
case MouseLocation.MiddleCircleRegion:
msg = "Middle Circle Button Clicked.";
break;
case MouseLocation.InnerCircleRegion:
msg = "Inner Circle Button Clicked.";
break;
case MouseLocation.UpButtonRegion:
msg = "Up Button Clicked.";
break;
case MouseLocation.RightButtonRegion:
msg = "Right Button Clicked.";
break;
case MouseLocation.DownButtonRegion:
msg = "Down Button Clicked.";
break;
case MouseLocation.LeftButtonRegion:
msg = "Left Button Clicked.";
break;
case MouseLocation.ZoomOutButtonRegion:
msg = "Zoom Out Button Clicked.";
break;
case MouseLocation.ZoomInButtonRegion:
msg = "Zoom In Button Clicked";
break;
case MouseLocation.NoneRegion:
msg = "PtzControl is Clicked.";
break;
}
Console.WriteLine(msg);
}
/// <summary>
/// Repaints the region using the refresh method which inturn invokes the Paint event.
/// which recreate the control.
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void PtzControlMouseLeave(object sender, EventArgs e) {
_currentMouseLocation = MouseLocation.NoneRegion;
Refresh();
}
#endregion
}
}