// start selection/resizing/moving
        protected override void OnMouseDown(MouseEventArgs e)
        {
            base.OnMouseDown(e);

            if (IsSelectionAreaPresent()) // we have selected area
            {
                if (!selectionArea.Contains(e.Location))
                { // we are outside of selected => erase current selection
                    selectionArea = new Rectangle(0, 0, 0, 0);
                    Invalidate();
                    croppingState = CroppingState.NONE;
                    return;
                }
                else // we are within the selection area
                {
                    DragCorner dc = PointAtDragCorner(selectionArea, e.Location);
                    if (dc != DragCorner.NONE)
                    {                                               // we are at a corner of selection => we start resizing
                        croppingState     = CroppingState.RESIZING; // it is a special drag, where the corners are pulled for resizing
                        dragPreviousPoint = e.Location;             // initial previous drag location
                    }
                    else
                    {                                   // we are inside selection => we start dragging
                        croppingState     = CroppingState.DRAGGING;
                        dragPreviousPoint = e.Location; // initial previous drag location
                    }
                }
            }
            else // we just start selecting
            {
                croppingState       = CroppingState.SELECTING;
                selectionStartPoint = e.Location; // initial selection area location
            }
        }
        // update selection area while on move
        protected override void OnMouseMove(MouseEventArgs e)
        {
            base.OnMouseMove(e);

            // set a cursor properly
            DragCorner dragCorner = DragCorner.NONE;

            if (selectionArea.Contains(e.Location)) // we are within selection area
            {
                dragCorner = PointAtDragCorner(selectionArea, e.Location);
                switch (dragCorner)
                {
                case DragCorner.NE: Cursor.Current = Cursors.PanNE; break;

                case DragCorner.NW: Cursor.Current = Cursors.PanNW; break;

                case DragCorner.SE: Cursor.Current = Cursors.PanSE; break;

                case DragCorner.SW: Cursor.Current = Cursors.PanSW; break;

                default: Cursor.Current = Cursors.Hand; break;     // DragCorner.NONE
                }
                Application.DoEvents();
            }
            else
            {
                Cursor.Current = Cursors.Default;
            }

            // handle base case
            if (e.Button != MouseButtons.Left)
            {
                return;
            }

            // do selection area updates based on the current state
            switch (croppingState)
            {
            case CroppingState.SELECTING:
            {
                // update selection area according to start and temporary end point (e.Location)
                selectionArea.Location = new Point(
                    Math.Min(selectionStartPoint.X, e.Location.X),
                    Math.Min(selectionStartPoint.Y, e.Location.Y));
                selectionArea.Size = new Size(
                    Math.Abs(selectionStartPoint.X - e.Location.X),
                    Math.Abs(selectionStartPoint.X - e.Location.X));
                Invalidate();
                break;
            }

            case CroppingState.DRAGGING:
            {
                // update selection area position with offset from dragging
                int dX = e.Location.X - dragPreviousPoint.X;
                int dY = e.Location.Y - dragPreviousPoint.Y;
                selectionArea.Offset(dX, dY);
                dragPreviousPoint = e.Location;         // save for next move
                Invalidate();
                break;
            }

            case CroppingState.RESIZING:     // special combination of SELECTING&DRAGGING: both size and location must be updated
            {
                int dX = e.Location.X - dragPreviousPoint.X;
                int dY = e.Location.Y - dragPreviousPoint.Y;         // we are only using dX here, as we are making square avatars currently
                switch (dragCorner)
                {
                case DragCorner.NE:
                {
                    selectionArea.Size = new Size(
                        selectionArea.Width + dX,
                        selectionArea.Height + dX);
                    selectionArea.Offset(0, -dX);
                    break;
                }

                case DragCorner.NW:
                {
                    selectionArea.Size = new Size(
                        selectionArea.Width - dX,
                        selectionArea.Height - dX);
                    selectionArea.Offset(dX, dX);
                    break;
                }

                case DragCorner.SE:
                {
                    selectionArea.Size = new Size(
                        selectionArea.Width + dX,
                        selectionArea.Height + dX);
                    selectionArea.Offset(0, 0);
                    break;
                }

                case DragCorner.SW:
                {
                    selectionArea.Size = new Size(
                        selectionArea.Width - dX,
                        selectionArea.Height - dX);
                    selectionArea.Offset(dX, 0);
                    break;
                }
                }
                dragPreviousPoint = e.Location;
                Invalidate();
                break;
            }
            }
        }