Когда я рисую линию на Canvas
путем перетаскивания Mouse
, я должен добавить Lines
для детей Canvas
«s, а не добавить текущую позицию Mouse
- Я думаю, что это вызвано, так как Mouse
Движение происходит быстрее, чем Rendering
Canvas
.Изменение курсора внутри прямоугольника с #
Я создал новый класс BoundingBox
, который наследует от Shape
и реализует собственность DefiningGeometry
. Этот новый Shape
состоит из Rectangle
и Text
:
IShapeBase:
public abstract class IShapeBase : Shape
{
public uint Id { get; set; }
public bool ShapeReady { get; set; }
public Point Location { get; set; }
public Brush Color { get; set; }
public string Text { get; set; }
public bool OnResizing { get; set; }
public bool OnMoving { get; set; }
protected IShapeBase() { ShapeReady = false; }
public abstract bool IsInBounds(Point currentLocation);
}
BoudingBox:
public class BoundingBox : IShapeBase
{
private enum ResizeDirection { None, Top, Left, Bottom, Right, TopLeft, TopRight, BottomRight, BottomLeft }
private PathGeometry m_pathGeometry;
private RectangleGeometry m_rectangleGeometry;
private Geometry m_textGeometry;
private Point m_downClick = new Point(-1, -1);
private Point m_previousLocation = new Point(-1, -1);
private Rect m_rectangle;
private ResizeDirection m_resizeDirection = ResizeDirection.None;
protected override Geometry DefiningGeometry
{
get
{
var formattedText = new FormattedText(Text, CultureInfo.CurrentCulture, FlowDirection.LeftToRight, new Typeface("Times New-Roman"), 14, Brushes.Transparent);
var chosenTextPoint = new Point
{
X = ((Location.X < BottomRight.X) ? Location.X : BottomRight.X) + 5,
Y = ((Location.Y < BottomRight.Y) ? Location.Y : BottomRight.Y) + 5
};
Stroke = Color;
StrokeThickness = IsMouseDirectlyOver ? 1.5 : 1;
m_rectangle = new Rect(Location, BottomRight);
m_pathGeometry = new PathGeometry();
m_rectangleGeometry = new RectangleGeometry(m_rectangle);
m_textGeometry = formattedText.BuildGeometry(chosenTextPoint);
m_pathGeometry.AddGeometry(m_rectangleGeometry);
m_pathGeometry.AddGeometry(m_textGeometry);
Fill = Brushes.Transparent;
return m_pathGeometry;
}
}
public Point BottomRight { get; set; }
public Rect Rectangle { get { return m_rectangle; } }
private void CheckHowToResize(Point currentLocation)
{
var currentTopLeft = m_rectangle.TopLeft;
var currentBottomRight = m_rectangle.BottomRight;
if (m_resizeDirection != ResizeDirection.None) return;
if ((currentLocation.X >= currentTopLeft.X - 5) && (currentLocation.X <= currentTopLeft.X + 5))
m_resizeDirection = ((currentLocation.Y >= currentBottomRight.Y - 5) && (currentLocation.Y <= currentBottomRight.Y + 5)) ? ResizeDirection.BottomLeft : ResizeDirection.Left;
if ((currentLocation.Y >= currentTopLeft.Y - 5) && (currentLocation.Y <= currentTopLeft.Y + 5))
m_resizeDirection = (m_resizeDirection == ResizeDirection.Left) ? ResizeDirection.TopLeft : ResizeDirection.Top;
if ((currentLocation.X >= currentBottomRight.X - 5) && (currentLocation.X <= currentBottomRight.X + 5))
m_resizeDirection = (m_resizeDirection == ResizeDirection.Top) ? ResizeDirection.TopRight : ResizeDirection.Right;
if ((currentLocation.Y >= currentBottomRight.Y - 5) && (currentLocation.Y <= currentBottomRight.Y + 5) && (m_resizeDirection != ResizeDirection.BottomLeft))
m_resizeDirection = (m_resizeDirection == ResizeDirection.Right) ? ResizeDirection.BottomRight : ResizeDirection.Bottom;
if (m_resizeDirection != ResizeDirection.None)
OnResizing = true;
}
private void Resize(Point currentLocation)
{
switch (m_resizeDirection)
{
case ResizeDirection.Left:
{
Location = new TranslateTransform(currentLocation.X - Location.X, 0).Transform(Location);
Mouse.OverrideCursor = Cursors.SizeWE;
break;
}
case ResizeDirection.Top:
{
Location = new TranslateTransform(0, currentLocation.Y - Location.Y).Transform(Location);
Mouse.OverrideCursor = Cursors.SizeNS;
break;
}
case ResizeDirection.TopLeft:
{
Location = new TranslateTransform(currentLocation.X - Location.X, currentLocation.Y - Location.Y).Transform(Location);
Mouse.OverrideCursor = Cursors.SizeNWSE;
break;
}
case ResizeDirection.Right:
{
BottomRight = new TranslateTransform(currentLocation.X - BottomRight.X, 0).Transform(BottomRight);
Mouse.OverrideCursor = Cursors.SizeWE;
break;
}
case ResizeDirection.Bottom:
{
BottomRight = new TranslateTransform(0, currentLocation.Y - BottomRight.Y).Transform(BottomRight);
Mouse.OverrideCursor = Cursors.SizeNS;
break;
}
case ResizeDirection.BottomRight:
{
BottomRight = new TranslateTransform(currentLocation.X - BottomRight.X, currentLocation.Y - BottomRight.Y).Transform(BottomRight);
Mouse.OverrideCursor = Cursors.SizeNWSE;
break;
}
case ResizeDirection.TopRight:
{
Location = new TranslateTransform(0, currentLocation.Y - Location.Y).Transform(Location);
BottomRight = new TranslateTransform(currentLocation.X - BottomRight.X, 0).Transform(BottomRight);
Mouse.OverrideCursor = Cursors.SizeNESW;
break;
}
case ResizeDirection.BottomLeft:
{
Location = new TranslateTransform(currentLocation.X - Location.X, 0).Transform(Location);
BottomRight = new TranslateTransform(0, currentLocation.Y - BottomRight.Y).Transform(BottomRight);
Mouse.OverrideCursor = Cursors.SizeNESW;
break;
}
}
}
public override bool IsInBounds(Point currentLocation)
{
return ((currentLocation.X >= m_rectangle.Left - 2) && (currentLocation.X <= m_rectangle.Right + 2) &&
(currentLocation.Y >= m_rectangle.Top - 2) && (currentLocation.Y <= m_rectangle.Bottom + 2));
}
protected override void OnMouseDown(MouseButtonEventArgs e)
{
Mouse.Capture(this);
if (e.LeftButton == MouseButtonState.Pressed)
m_downClick = e.GetPosition(this);
}
protected override void OnMouseMove(MouseEventArgs e)
{
if (e.LeftButton != MouseButtonState.Pressed) return;
Thread.Sleep(20);
var currentLocation = e.GetPosition(this);
if (!OnMoving)
{
CheckHowToResize(currentLocation);
if (OnResizing)
{
Resize(currentLocation);
return;
}
}
m_pathGeometry.Transform = new TranslateTransform((currentLocation.X - m_downClick.X), (currentLocation.Y - m_downClick.Y));
Mouse.OverrideCursor = Cursors.ScrollAll;
OnMoving = true;
m_previousLocation = currentLocation;
}
protected override void OnMouseUp(MouseButtonEventArgs e)
{
m_downClick = new Point(-1, -1);
ReleaseMouseCapture();
OnResizing = false;
OnMoving = false;
m_resizeDirection = ResizeDirection.None;
Location = m_pathGeometry.Transform.Transform(Location);
BottomRight = m_pathGeometry.Transform.Transform(BottomRight);
}
protected override void OnIsMouseDirectlyOverChanged(DependencyPropertyChangedEventArgs e)
{
StrokeThickness = IsMouseDirectlyOver ? 1.5 : 1;
}
}
Я хотел бы, чтобы убедиться, что BoudningBox
сможет перемещаться только в границах Canvas
, на котором он нарисован.
В настоящее время, так как я использую ClipCursor
снаружи, я могу ограничить создание и изменение размеров Shape
к границам Canvas
«s, но если я пытаюсь переместить его, нажав на центр Shape
и перетаскивая его, тогда я могу переместить его, пока мышь не достигнет границ Canvas
, но Shape
находится наполовину на Canvas
и наполовину снаружи.
Моя главная трудность обнаружения, когда именно делает Mouse
удар либо Shape
или границ Canvas
»потому, что (опять же, я думаю) rendering
медленнее, чем движение Mouse
.
Это влияет на все, что я пытаюсь реализовать:
1), подчеркивающие BoundingBox
при наведении курсора мыши на нем.
2) Изменение курсора Mouse
для прокрутки/изменения размера/стрелки в зависимости от того, что находится под текущим местоположением Mouse
.
3) Переместить BoundinBox
в пределах его parent
Холст`.
Можно ли достичь такой точности?
Я пробовал все то, что вы написали с помощью системы осей «Холст» (отметьте между 0 и 'CanvasWidth' для координат' X' и между 0 и 'CanvasHeight' для координат' Y'). Это не сработало, движение не было гладким. Считаете ли вы, что добавление прямоугольника границы будет отличаться? – Idanis
Посмотрите, помогает ли использование RenderTransform. – Makubex