Take the 2-minute tour ×
Game Development Stack Exchange is a question and answer site for professional and independent game developers. It's 100% free, no registration required.

I have an artillery game (hobby-learning project) and when the projectile hits it leaves a hole in the ground. I want this hole to have antialiased edges. I'm using System.Drawing for this. I've tried with clipping paths, and drawing with a transparent color using gfx.CompositingMode = CompositingMode.SourceCopy, but it gives me the same result. If I draw a circle with a solid color it works fine, but I need a hole, a circle with 0 alpha values.

I have enabled these but they work only with solid colors:

gfx.CompositingQuality = CompositingQuality.HighQuality;
gfx.InterpolationMode = InterpolationMode.HighQualityBicubic;
gfx.SmoothingMode = SmoothingMode.AntiAlias;

In the two pictures consider black as being transparent.

This is what I have (zoomed in):
What I have

And what I need is something like this (made with photoshop):
What I need

This will be just a visual effect, in code for collision detection I still treat everything with alpha > 128 as solid.

Edit: I'm usink OpenTK for this game. But for this question I think it doesn't really matter probably it is gdi+ related.

share|improve this question

2 Answers 2

up vote 3 down vote accepted

As you have noticed clipping or regions in GDI+ are not antialiased as they are both pixel based where a given pixel can either be completely included or excluded.

To do what you want in GDI+ you can apply an alpha mask to the image yourself. Basically you fill a rectangle of the size of the area affected with black color and then draw the hole with white using the high quality settings for Antialiasing and smoothing. Then you apply the resulting image as an alpha mask to the original image. (which means that you re-calculate the alpha value of the pixels involved based on the black/white image where completely white pixels will be transparent) To do this quickly you should use the fast pointer access to the pixel data via LockBits()..

Here is a GDI+ example. This will only work if the images are 32bppArgb format and both are the same size - if you only need to apply an alpha mask to a small portion of the original image I would suggest you adjust the code to do that.

public static void ApplyAlphaMask(Bitmap bmp, Bitmap alphaMaskImage)
{    
  int width = bmp.Width;
  int height = bmp.Height;

  BitmapData dataAlphaMask = alphaMaskImage.LockBits(new Rectangle(0, 0, width, height), ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb);
  try
  {
    BitmapData data = bmp.LockBits(new Rectangle(0, 0, width, height), ImageLockMode.ReadWrite, PixelFormat.Format32bppArgb);
    try
    {
      unsafe //using pointer requires the unsafe keyword
      {
        byte* pData0Mask = (byte*)dataAlphaMask.Scan0;
        byte* pData0 = (byte*)data.Scan0;

        for (int x = 0; x < width; x++)
        {
          for (int y = 0; y < height; y++)
          {
            byte* pData = pData0 + (y * data.Stride) + (x * 4);
            byte* pDataMask = pData0Mask + (y * dataAlphaMask.Stride) + (x * 4);

            byte maskBlue = pDataMask[0];
            byte maskGreen = pDataMask[1];
            byte maskRed = pDataMask[2];

            //the closer the color is to black the more opaque it will be.
            byte alpha = (byte)(255 - (maskRed + maskBlue + maskGreen) / 3);

            //respect the original alpha value
            byte originalAlpha = pData[3];
            pData[3] = (byte)(((float)(alpha * originalAlpha)) / 255f);
          }
        }
      }
    }
    finally
    {
      bmp.UnlockBits(data);
    }
  }
  finally
  {
    alphaMaskImage.UnlockBits(dataAlphaMask);
  }
}
share|improve this answer
    
Yes I have thought in the meantime of something similar myself. (Draw something with a solid color (red, green or blue) in high quality and then get the color component and treat it as alpha values and somehow combine it with my original texture). I thought there HAS to be a more simple way to do this. Oh well. Thanks anyway. –  gyozo kudor Jun 6 '11 at 9:28
    
unfortunately there doesn't seem to be a better way in GDI+ but the above mentioned technique should work fine. Have used this in production code myself. –  Patrick Klug Jun 7 '11 at 7:46
    
I used something similar to this method. I had a smaller image that was the mask. The mask was a black rectangle with a red circle on it for the hole. I checked every pixel in the mask and if there was red component in it I changed the corresponding alpha value to 255 - red in the original texture. I think I have somewhere a few off-by-one errors :), but it works ok. –  gyozo kudor Jun 7 '11 at 8:53
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
    }
}
share|improve this answer
7  
That's not a good answer, just a huge amount of code. –  bummzack Mar 27 '12 at 13:18

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.