C# Draw polyline(s) on mouse move - c#

I want to draw something on my canvas whenever drawing_mode and is_drawing booleans are on. Right now I am using a polyline list and BackgroundWorker for threading. My main problem is that my code only creates one polyline and the dots are ALWAYS connected. In other words I can stop drawing for a while but then wherever I click a new line connection is made with the previous one. The end result is that my canvas.Children only has one polyline element with all the points. Could anyone help me solve this?
P.S. I am not very good with threading yet...
private BackgroundWorker drawing_worker;
private void drawing_worker_ProgressChanged(object sender, ProgressChangedEventArgs eventargs)
{
Polyline polyline = new Polyline();
polyline.Points = last_polyline.Points;
canvas.Children.Remove(last_polyline);
var pos = canvas_relative_pos;
polyline.Points.Add(pos);
polyline.Stroke = new SolidColorBrush(Colors.Black);
polyline.StrokeThickness = 1;
canvas.Children.Add(polyline);
last_polyline = polyline;
}
private void drawing_worker_DoWork(object sender, DoWorkEventArgs eventargs)
{
while (drawing_mode_enabled && is_drawing)
{
drawing_worker.ReportProgress(0);
Thread.Sleep(5);
if (drawing_worker.CancellationPending) break;
}
}
private void ContentControl_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
if (drawing_mode_enabled)
{
is_drawing = true;
drawing_worker = new BackgroundWorker
{
WorkerReportsProgress = true,
WorkerSupportsCancellation = true
};
drawing_worker.ProgressChanged += drawing_worker_ProgressChanged;
drawing_worker.DoWork += drawing_worker_DoWork;
drawing_worker.RunWorkerAsync();
}
}

You don't need a BackgroundWorker or any other asynchronous stuff to draw polylines on Canvas.
Just create a Canvas with a Background (so that it gets input events) and handlers for the MouseLeftButtonDown, MouseLeftButtonUp and MouseMove events:
<Canvas Background="Transparent"
MouseLeftButtonDown="CanvasMouseLeftButtonDown"
MouseLeftButtonUp="CanvasMouseLeftButtonUp"
MouseMove="CanvasMouseMove"/>
In the mouse down handler create a new Polyline and add it to the Canvas. Also capture the mouse so that you get mouse move events even when the mouse cursor leaves the Canvas. In the mouse up handler release the mouse capture. Finally, in the mouse move handler, add points to the last polyline child of the Canvas.
private void CanvasMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
var panel = (Panel)sender;
var polyline = new Polyline
{
Stroke = Brushes.Black,
StrokeThickness = 3
};
panel.Children.Add(polyline);
panel.CaptureMouse();
}
private void CanvasMouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
((UIElement)sender).ReleaseMouseCapture();
}
private void CanvasMouseMove(object sender, MouseEventArgs e)
{
var panel = (Panel)sender;
if (panel.IsMouseCaptured)
{
var polyline = panel.Children.OfType<Polyline>().Last();
polyline.Points.Add(e.GetPosition(panel));
}
}

Related

While dragging rectangle object fast, dragging stops

While dragging rectangle object fast, dragging stops and cursor only moves. Without releasing button click button, moving the cursor on the rectangle object starts the dragging again. It is dragging fine when i drag on a constant speed.
My code is,
private void ConnectorMethod()
{
_draggedLine = new Rectangle();
_draggedLine.Width = 100;
_draggedLine.Height = 12;
_controlModel.PlayerCanvas.Children.Add(_draggedLine);
_draggedLine.PreviewMouseLeftButtonDown += copy_Connector;
_draggedLine.PreviewMouseLeftButtonUp += connector_leftUp;
}
private void copy_Connector(object sender, MouseButtonEventArgs e)
{
_connecting_Connector = (Rectangle)sender;
_Connector_position = e.GetPosition(_connecting_Connector);
_connecting_Connector.PreviewMouseMove += ConnectorMouseMove;
}
private void connector_leftUp(object sender, MouseButtonEventArgs e)
{
_connecting_Connector.PreviewMouseMove -= ConnectorMouseMove;
}
private void ConnectorMouseMove(object sender, MouseEventArgs e)
{
if (e.LeftButton == MouseButtonState.Pressed)
{
Point canvasRelativePosition = e.GetPosition(_controlModel.PlayerCanvas);
Canvas.SetTop(_connecting_Connector, canvasRelativePosition.Y - _Connector_position.Y);
Canvas.SetLeft(_connecting_Connector, canvasRelativePosition.X - _Connector_position.X);
e.Handled = true;
}
}
Thanks in Advance.
I have fixed it with implementation canvas rectangle object in

How to draw random/irregular line in XAML canvas?

I have a canvas in XAML in which I want to draw random irregular (Hand drawn) line using C#.
This is what I want: http://jsfiddle.net/GfGVE/9/ HTML Canvas but in XAML C#
I want the line to be drawn Horizontally.
Xaml:
<Canvas Grid.Column="1" x:Name="ItemCanvas"></Canvas>
C#:
public ItemControl()
{
this.InitializeComponent();
canvas = this.ItemCanvas;
}
You need to add methods for the events MouseMove, MouseDown, MouseEnter, MouseUp and MouseLeave. Additionally you need two variables for the current position and the last position. If you also want to undo you need to add a Stack<int> for this. These are the needed methods:
private void Canvas_MouseDown(Object sender, MouseButtonEventArgs e)
{
// push start of line onto undo stack
this.undo.Push(this.paintCanvas.Children.Count);
this.last = e.GetPosition(this.paintCanvas);
}
private void Canvas_MouseMove(Object sender, MouseEventArgs e)
{
if (e.LeftButton == MouseButtonState.Pressed)
{
if (this.last.X != -1)
{
Point current = e.GetPosition(this.paintCanvas);
Line l = new Line();
l.X1 = this.last.X;
l.Y1 = this.last.Y;
l.X2 = current.X;
l.Y2 = current.Y;
l.Stroke = this.brush;
l.StrokeThickness = this.thickness;
this.paintCanvas.Children.Add(l);
this.last = current;
}
}
}
private void Canvas_MouseUp(Object sender, MouseButtonEventArgs e)
{
// push end of line onto undo stack
this.undo.Push(this.paintCanvas.Children.Count);
}
private void Canvas_MouseLeave(Object sender, MouseEventArgs e)
{
this.last = new Point(-1, -1);
}
private void Canvas_MouseEnter(Object sender, MouseEventArgs e)
{
this.last = e.GetPosition(this.paintCanvas);
}
To remove the last line from your canvas you can call this Undo-method:
private void Undo()
{
if (this.undo.Count == 0)
return;
// pop indexes of last line (start index is one below top of stack)
int to = this.undo.Pop();
int from = this.undo.Pop();
// remove last line from UIElement collection
this.paintCanvas.Children.RemoveRange(from, to);
}
You could use InkCanvas for this purpose. It defines an area that receives and displays ink strokes:
<Grid>
<InkCanvas Name="InkCanvas1"></InkCanvas>
</Grid>
Result:

Relocate image on mouseover

I am trying to recreate a mac style menu bar is c# on visual studio 2012. I can get the image to move on mouseEnter and relocate back to the original place on mouseLeave. I do this by setting the location of the picturebox.
The problem I have is when I mouseEnter the image if I leave the mouse in the area at the bottom of the image between the bottom of the old image location and the bottom of the new image location the image will jump constantly between the two location.
Can anyone advise how to stop this or avoid it.
private void pic1_MouseEnter(object sender, EventArgs e)
{
pic1.Location = new Point(328, 300);
}
private void pic1_MouseLeave(object sender, EventArgs e)
{
pic1.Location = new Point(328, 316);
}
Try to detach event handler before moving image location, then attach it back after. Something like this :
private void pic1_MouseEnter(object sender, EventArgs e)
{
pic1.MouseEnter -= pic1_MouseEnter;
pic1.MouseLeave -= pic1_MouseLeave;
pic1.Location = new Point(328, 300);
pic1.MouseEnter += pic1_MouseEnter;
pic1.MouseLeave += pic1_MouseLeave;
}
True, since moving the image triggers the MouseLeave event, Leave callback sends it to its original location, thus triggering MouseEnter and so on for ever and ever (unless you move the mouse away).
I would suggest you eliminate MouseLeave callback and keep a state of where the image is:
private bool retracted = false;
private void pic1_MouseEnter(object sender, EventArgs e)
{
if (retracted)
{
pic1.Location = new Point(328, 316);
}
else
{
pic1.Location = new Point(328, 300);
}
retracted = !retracted;
}
Thanks for all the solutions but none had the desired effect but I have come up with a solution using mouseHover and mouseLeave. On hover moves the image to the desired location ad the leave returns it to the original spot.
private void pic1_MouseLeave(object sender, EventArgs e)
{
pic1.Location = new Point(328, 316);
}
private void pic1_MouseHover(object sender, EventArgs e)
{
pic1.Location = new Point(328, 310);
}

Touch manipulations with AddManipulator

When using AddManipulator, are touches routed to the new Manipulation? When I do the following, it all works but touches are left after the TouchLeave event. So for example if I do a single finger rotate, leave the touched element and touch it again, it becomes a two finger zoom.
private void HV3DTouchDown(object sender, TouchEventArgs e)
{
Canvas canvas = sender as Canvas
Manipulation.AddManipulator(canvas, e.TouchDevice.AsManipulator());
e.Handled = true;
CaptureTouch(e.TouchDevice);
}
private void HV3DTouchLeave(object sender, TouchEventArgs e)
{
Canvas canvas = sender as Canvas
Manipulation.RemoveManipulator(canvas, e.TouchDevice.AsManipulator());
e.Handled = true;
ReleaseTouchCapture(e.TouchDevice);
}

How can I capture mouse events that occur outside of a (WPF) window?

I have a Window element that has WindowStyle="None" and AllowsTransparency="True", therefore it has no title bar and supports transparency.
I want the user to be able to move the Window to any position on the screen by left-clicking anywhere within the Window and dragging. The Window should drag along with the mouse as long as the left mouse button is pressed down.
I was able to get this functionality to work with one exception: when the mouse moves outside of the Window (such as when the left mouse button was pressed down near the edge of the Window and the mouse is moved quicly), the Window no longer captures the mouse position and does not drag along with the mouse.
Here is the code from the code-behind that I use to get the job done:
public Point MouseDownPosition { get; set; }
public Point MousePosition { get; set; }
public bool MouseIsDown { get; set; }
private void window_MyWindowName_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
MouseDownPosition = e.GetPosition(null);
MouseIsDown = true;
}
private void window_MyWindowName_MouseMove(object sender, MouseEventArgs e)
{
if (MouseIsDown)
{
MousePosition = e.GetPosition(null);
Left += MousePosition.X - MouseDownPosition.X;
Top += MousePosition.Y - MouseDownPosition.Y;
}
}
private void window_MyWindowName_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
MouseIsDown = false;
}
I think you are looking for this: Processing Global Mouse and Keyboard Hooks in C#
Url: Processing Global Mouse and Keyboard Hooks in C#
This class allows you to tap keyboard and mouse and/or to detect their activity even when an application runs in the background or does not have any user interface at all.
This class raises common .NET events with KeyEventArgs and MouseEventArgs, so you can easily retrieve any information you need.
There is an example and explain and demo to use.
Great tutorial!
Example:
UserActivityHook actHook;
void MainFormLoad(object sender, System.EventArgs e)
{
actHook= new UserActivityHook(); // crate an instance
// hang on events
actHook.OnMouseActivity+=new MouseEventHandler(MouseMoved);
actHook.KeyDown+=new KeyEventHandler(MyKeyDown);
actHook.KeyPress+=new KeyPressEventHandler(MyKeyPress);
actHook.KeyUp+=new KeyEventHandler(MyKeyUp);
}
Now, an example of how to process an event:
public void MouseMoved(object sender, MouseEventArgs e)
{
labelMousePosition.Text=String.Format("x={0} y={1}", e.X, e.Y);
if (e.Clicks>0) LogWrite("MouseButton - " + e.Button.ToString());
}
I believe you are reinventing the wheel. Search for "Window.DragMove".
Example:
private void title_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
this.DragMove();
}
Try it this way:
// method to convert from 'old' WinForms Point to 'new' WPF Point structure:
public System.Windows.Point ConvertToPoint(System.Drawing.Point p)
{
return new System.Windows.Point(p.X,p.Y);
}
// some locals you will need:
bool mid = false; // Mouse Is Down
int x=0, y=0;
// Mouse down event
private void MainForm_MouseDown(object sender, MouseButtonEventArgs e)
{
mid=true;
Point p = e.GetPosition(this);
x = (int)p.X;
y = (int)p.Y;
}
// Mouse move event
private void MainForm_MouseMove(object sender, MouseButtonEventArgs e)
{
if(mid)
{
int x1 = e.GetPosition(this).X;
int y1 = e.GetPosition(this).Y;
Left = x1-x;
Top = y1-y;
}
}
// Mouse up event
private void MainForm_MouseUp(object sender, MouseButtonEventArgs e)
{
mid = false;
}

Categories

Resources