// 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; } } }