i write a little application in C# with wpf. My goal is to draw a circle in a picture. As long as the mouse button is pressed, the circle should be movable and only after the user has released the mouse button the circle should be finally drawn. For drawing the ellipse i use DrawEllipse.
grf.DrawEllipse(
myPen,
(float)xOriginal - 25,
(float)yOriginal - 25,
radius,
radius
);
After the mouse is released, the circle should be drawn. Then I would like to pick up the coordinates and save.
My idea is to use MouseDown, MouseMove and MouseUp. MouseDown registers the click. With MouseMove, the circles should be redrawn each time and with MouseUp, the circle should be finally drawn.
My problem is that with MouseMove the circle is drawn again and again and not deleted. In addition, it is incredibly delayed. Is there a better solution
Here is my quick and dirty code snippet:
bool registerClick = false;
private void Image_imageBox_MouseregisterClick(object sender, MouseButtonEventArgs e)
{
registerClick = true;
}
private void Image_imageBox_MouseMove(object sender, MouseEventArgs e)
{
if (registerClick)
{
Pen myPen = new Pen(Color.FromArgb(255, 0, 0, 0), 10);
int radius = 50;
Bitmap b1 = _detektion.BildOriginal.Bitmap;
using (Graphics grf = Graphics.FromImage(b1))
{
// zeichne denkreis ein
grf.DrawEllipse(
myPen,
((float)e.GetPosition(imageBox_Image).X - 25,
(float)e.GetPosition(imageBox_Image).X - 25,
radius,
radius
);
}
imageBox_Image.Source = DGX_Body.Utility.Images.ConvertBitmapToBitmapImage(b1);
}
}
private void Image_imageBox_MouseUp(object sender, MouseButtonEventArgs e)
{
Console.WriteLine("Up!");
registerClick = false;
}
Can you help me please.
Thank you
Here is a very basic example of Ellipses in a Canvas with mouse input.
XAML:
<Grid>
<Image Source="C:\Users\Public\Pictures\Sample Pictures\Koala.jpg"
Stretch="None" HorizontalAlignment="Left" VerticalAlignment="Top"/>
<Canvas Background="Transparent"
MouseLeftButtonDown="CanvasMouseLeftButtonDown"
MouseLeftButtonUp="CanvasMouseLeftButtonUp"
MouseMove="CanvasMouseMove"/>
</Grid>
Code behind with event handlers:
private Ellipse currentEllipse;
private void CanvasMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
var canvas = (Canvas)sender;
var pos = e.GetPosition(canvas);
canvas.CaptureMouse();
currentEllipse = new Ellipse
{
Width = 50,
Height = 50,
Margin = new Thickness(-25, -25, 0, 0),
Stroke = Brushes.White,
StrokeThickness = 3
};
Canvas.SetLeft(currentEllipse, pos.X);
Canvas.SetTop(currentEllipse, pos.Y);
canvas.Children.Add(currentEllipse);
}
private void CanvasMouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
var canvas = (Canvas)sender;
canvas.ReleaseMouseCapture();
currentEllipse = null;
}
private void CanvasMouseMove(object sender, MouseEventArgs e)
{
if (currentEllipse != null)
{
var canvas = (Canvas)sender;
var pos = e.GetPosition(canvas);
Canvas.SetLeft(currentEllipse, pos.X);
Canvas.SetTop(currentEllipse, pos.Y);
}
}
With this small change you may also pick existing Ellipses:
private void CanvasMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
var canvas = (Canvas)sender;
var pos = e.GetPosition(canvas);
canvas.CaptureMouse();
currentEllipse = e.OriginalSource as Ellipse;
if (currentEllipse == null)
{
currentEllipse = new Ellipse
{
Width = 50,
Height = 50,
Margin = new Thickness(-25, -25, 0, 0),
Fill = Brushes.Transparent,
Stroke = Brushes.White,
StrokeThickness = 3
};
canvas.Children.Add(currentEllipse);
}
Canvas.SetLeft(currentEllipse, pos.X);
Canvas.SetTop(currentEllipse, pos.Y);
}
Related
I have a panel with multiple picturebox created at runtime.
The user will create a rectangle on any picture box and the selected part will be displayed on a preview picturebox.
I have successfully done the above using the below code.
Question
I want to clear the selection rectangle at mouseup event. Used invalidate but not working.
From how to clear the graphics(rectangle shape) in picturebox
Also, when I scroll the panel the same rectangle(mouse selection) is shown on all picturebox.
private void Picture_Paint(object sender, PaintEventArgs e)
{
if (Rect!=null && Rect.Width>0 && Rect.Height>0)
{
e.Graphics.FillRectangle(selectionBrush, Rect);
}
}
private void Picture_MouseDown(object sender, MouseEventArgs e)
{
RecStartpoint = e.Location;
((PictureBox)sender).Invalidate();
}
private void Picture_MouseMove(object sender, MouseEventArgs e)
{
if (e.Button != MouseButtons.Left) return;
Point tempEndPoint = e.Location;
Rect.Location = new Point(
Math.Min(RecStartpoint.X, tempEndPoint.X),
Math.Min(RecStartpoint.Y, tempEndPoint.Y));
Rect.Size = new Size(
Math.Abs(RecStartpoint.X - tempEndPoint.X),
Math.Abs(RecStartpoint.Y - tempEndPoint.Y));
((PictureBox)sender).Invalidate();
}
private void Picture_MouseUp(object sender, MouseEventArgs e)
{
if (e.Button != MouseButtons.Left) return;
PictureBox org_pic = (PictureBox)(sender);
Point RecEndpoint=e.Location;
int xDown = Math.Min(RecStartpoint.X,RecEndpoint.X);
int yDown = Math.Min(RecStartpoint.Y, RecEndpoint.Y);
int xUp = Math.Max(RecStartpoint.X,RecEndpoint.X);
int yUp = Math.Max(RecStartpoint.Y,RecEndpoint.Y);
Rectangle rec = new Rectangle(xDown, yDown, Math.Abs(xUp - xDown), Math.Abs(yUp - yDown));
xDown = xDown * org_pic.Image.Width / org_pic.Width;
yDown = yDown * org_pic.Image.Height / org_pic.Height;
xUp = xUp * org_pic.Image.Width / org_pic.Width;
yUp = yUp * org_pic.Image.Height / org_pic.Height;
rectCropArea = new Rectangle(xDown, yDown, Math.Abs(xUp - xDown), Math.Abs(yUp - yDown));
pictureBox_preview_photo.Refresh();
Bitmap sourceBitmap = new Bitmap(org_pic.ImageLocation);
Graphics g = pictureBox_preview_photo.CreateGraphics();
g.DrawImage(sourceBitmap, new Rectangle(0, 0, pictureBox_preview_photo.Width, pictureBox_preview_photo.Height), rectCropArea, GraphicsUnit.Pixel);
}
I would try this approach:
First, make Image variable, in the scope of form
public partial class Form1 : Form
{
//variable for holding original image, before rectangle is drawn on it
Image originalImage = null;
public Form1()
{
InitializeComponent();
}
//rest of form's code...
second, save current picture in that variable on MouseDown
private void Picture_MouseDown(object sender, MouseEventArgs e)
{
//save it
startImage = ((PictureBox)sender).Image;
RecStartpoint = e.Location;
((PictureBox)sender).Invalidate();
}
lastly, on the end of MouseUp event, set Rectangle's width and height to zero and restore saved, original image
//snipped code
pictureBox_preview_photo.Refresh();
Bitmap sourceBitmap = new Bitmap(org_pic.ImageLocation);
Graphics g = pictureBox_preview_photo.CreateGraphics();
g.DrawImage(sourceBitmap, new Rectangle(0, 0, pictureBox_preview_photo.Width, pictureBox_preview_photo.Height), rectCropArea, GraphicsUnit.Pixel);
//make rectangle's widht and height 0 so that Paint event won't draw it
Rect.Width = Rect.Height = 0;
//restore image
this.Picture.Image = startImage;
I didn't understand that second question.
I am trying to make a paint program in C# I started out using a panel, and using a pen, but whenever the window refreshed, the drawing was removed.
What program is meant to do:
Open image, allow user to draw on it, and allow user to save modified image
Old code:
private void canvas_MouseMove(object sender, MouseEventArgs e)
{
if (canDraw)
{
//canvas.BackgroundImage = buffer;
if (drawSquare)
{
isDrawn = true;
SolidBrush sb = new SolidBrush(btn_brushColor.BackColor);
Rectangle path1 = new Rectangle(e.X, e.Y, int.Parse(shapeSize.Text), int.Parse(shapeSize.Text));
//Rectangle path1 = new Rectangle(100, 100, int.Parse(shapeSize.Text), int.Parse(shapeSize.Text));
Rectangle path2 = new Rectangle(e.X + (int.Parse(shapeSize.Text) / 20), e.Y + (int.Parse(shapeSize.Text) / 20), (int.Parse(shapeSize.Text) / 10 * 9), (int.Parse(shapeSize.Text) / 10 * 9));
//Rectangle path2 = new Rectangle(e.X, e.Y, 2/(int.Parse(shapeSize.Text)), 2/(int.Parse(shapeSize.Text)));
// Create a region from the Outer circle.
Region region = new Region(path1);
// Exclude the Inner circle from the region
region.Exclude(path2);
// Draw the region to your Graphics object
g.FillRegion(sb, region);
//drawRectangle = false;
debug.Text = ("recf");
}
if (drawEraser)
{
isDrawn = true;
Pen d = new Pen(Color.White, float.Parse(cmb_brushSize.Text));
g.DrawLine(d, new Point(initX ?? e.X, initY ?? e.Y), new Point(e.X, e.Y));
initX = e.X;
initY = e.Y;
}
if (drawbrush)
{
isDrawn = true;
Pen p = new Pen(btn_brushColor.BackColor, float.Parse(cmb_brushSize.Text));
g.DrawLine(p, new Point(initX ?? e.X, initY ?? e.Y), new Point(e.X, e.Y));
initX = e.X;
initY = e.Y;
}
}
}
private void canvas_MouseDown(object sender, MouseEventArgs e)
{
debug.Text = ("running");
canDraw = true;
}
private void canvas_MouseUp(object sender, MouseEventArgs e)
{
canDraw = false;
initX = null;
initY = null;
}
I am trying to use picBox_Paint(PaintEventArgs...) to draw, but I can't figure out how to capture _MouseDown/_MouseMove/_MouseUp with the paint event to draw when the mouse is moved over the pictureBox and MouseDown is true.
Or if there is a way to make DrawLine on mouseEvent Permanent.
Current code:
private void picBox_Paint(object sender, System.Windows.Forms.PaintEventArgs e)
{
Graphics g = e.Graphics;
g.DrawString("This is a diagonal line drawn on the control",
new Font("Arial", 10), System.Drawing.Brushes.Blue, new Point(30, 30));
g.DrawLine(System.Drawing.Pens.Red, picBox.Left, picBox.Top,
picBox.Right, picBox.Bottom);
}
This works, and does't get removed on window refresh, but I don't know how to get mouse input now, and use MouseEvent to get the mouse points for drawing.
I am very new to C# and WPF and would to create a WPF application that draws shapes with a button. The shapes then need to be able to move around the canvas. When I create a shape in the XAML it moves. However I cannot get the one created by the button to move. Could anyone please assist? Below are the XAML and code that i am using.
XAML:
<Window x:Class="All_test.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">
<Canvas x:Name="canvas" >
<Button Content="Button" Canvas.Left="250" Canvas.Top="260" Width="75" Click="Button_Click_1" />
<Rectangle x:Name="rect"
Height="100" Width ="100" Fill="red"
MouseLeftButtonDown="rect_MouseLeftButtonDown"
MouseLeftButtonUp="rect_MouseLeftButtonUp"
MouseMove="rect_MouseMove"
Canvas.Left="342" Canvas.Top="110" />
</Canvas>
This is the code I am using to move the red square drawn in XAML. How can I do the same for the green one created by the button?
public partial class MainWindow : Window
{
private bool _isRectDragInProg;
public MainWindow()
{
InitializeComponent();
}
private void Button_Click_1(object sender, RoutedEventArgs e)
{
Rectangle rect = new Rectangle();
rect.Fill = new SolidColorBrush(Colors.Green);
rect.Stroke = new SolidColorBrush(Colors.Black);
rect.Height = 100;
rect.Width = 100;
rect.StrokeThickness = 4;
canvas.Children.Add(rect);
InitializeComponent();
}
private void rect_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
_isRectDragInProg = true;
rect.CaptureMouse();
}
private void rect_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
_isRectDragInProg = false;
rect.ReleaseMouseCapture();
}
private void rect_MouseMove(object sender, MouseEventArgs e)
{
if (!_isRectDragInProg) return;
// get the position of the mouse relative to the Canvas
var mousePos = e.GetPosition(canvas);
// center the rect on the mouse
double left = mousePos.X - (rect.ActualWidth / 2);
double top = mousePos.Y - (rect.ActualHeight / 2);
Canvas.SetLeft(rect, left);
Canvas.SetTop(rect, top);
}
You should bind the mouse events for this Rectangle:
private void Button_Click_1(object sender, RoutedEventArgs e)
{
Rectangle rect = new Rectangle();
rect.Fill = new SolidColorBrush(Colors.Green);
rect.Stroke = new SolidColorBrush(Colors.Black);
rect.Height = 100;
rect.Width = 100;
rect.StrokeThickness = 4;
// here
rect.MouseLeftButtonDown += rect_MouseLeftButtonDown;
rect.MouseLeftButtonUp += rect_MouseLeftButtonUp;
rect.MouseMove += rect_MouseMove;
canvas.Children.Add(rect);
// InitializeComponent(); <--- lose the InitializeComponent here, that's should only be called ones.. (in the constructor)
}
Recommendations:
Use the sender parameter to get the current Rectangle.
You can lose the _isRectDragInProg boolean... use the IsMouseCaptured property instead.
For example:
private void rect_MouseMove(object sender, MouseEventArgs e)
{
var rect = (Rectangle)sender;
if (!rect.IsMouseCaptured) return;
// get the position of the mouse relative to the Canvas
var mousePos = e.GetPosition(canvas);
// center the rect on the mouse
double left = mousePos.X - (rect.ActualWidth / 2);
double top = mousePos.Y - (rect.ActualHeight / 2);
Canvas.SetLeft(rect, left);
Canvas.SetTop(rect, top);
}
I have created an ellipse object which I can fill through a color combobox.
Now I need to be able to click(and hold) the circle, drag my cursor to a canvas and when I release my mousebutton a new circle should be drawn at that place, with the same dimensions and color as the circle I clicked.
I think I'm doing something wrong in the Drop event.
private Ellipse dragCircle = new Ellipse();
private void eBallColor_MouseMove(object sender, MouseEventArgs e)
{
dragCircle = (Ellipse)sender;
if (e.LeftButton == MouseButtonState.Pressed)
{
DataObject dragColor = new DataObject("theColor", dragCircle.Fill);
DragDrop.DoDragDrop(dragCircle, dragColor, DragDropEffects.Move);
}
}
private void Ellipse_Drop(object sender, DragEventArgs e)
{
Ellipse circle = (Ellipse)sender;
if (e.Data.GetDataPresent("theColor"))
{
Brush draggedColor = (Brush)e.Data.GetData("theColor");
circle.Fill = draggedColor;
dragCircle.Fill = Brushes.White;
Point pos = e.GetPosition(canvasCard);
double posX = pos.X;
double posY = pos.Y;
Canvas.SetLeft(dragCircle, posX);
Canvas.SetTop(dragCircle, posY);
canvasCard.Children.Add(dragCircle);
}
}
I'm very new in C#
I want a rectangle to appear wherever there's a mouseclick on a panel
Here's my code:
private void panel1_MouseClick(object sender, MouseEventArgs e)
{
int x = e.Location.X;
int y = e.Location.Y;
if (radioButton1.Checked == false)
{
((Panel)sender).Invalidate(new Rectangle(x * 40, y * 40, 40, 40));
}
else if (radioButton2.Checked == true)
{
return;
}
}
I wonder how to change the color of the rectangle?
Please advise me if my code is wrong.
Thanks.
Your drawing should be performed in the panel's Paint event handler. When you click the panel, create the rectangle (in the MouseUp event of the panel) and store it in a collection of rectangles (such as a dictionary). Then refresh the panel. In the panel's Paint event, draw all the rectangles. Here is a simple example:
Dictionary<Color, List<Rectangle>> rectangles = new Dictionary<Color, List<Rectangle>>();
private void panel1_Paint(object sender, PaintEventArgs e)
{
//The key value for the dictionary is the color to use to paint with, so loop through all the keys (colors)
foreach (var rectKey in rectangles.Keys)
{
using (var pen = new Pen(rectKey)) //Create the pen used to draw the rectangle (using statement makes sure the pen is disposed)
{
//Draws all rectangles for the current color
//Note that we're using the Graphics object that is passed into the event handler.
e.Graphics.DrawRectangles(pen, rectangles[rectKey].ToArray());
}
}
}
//This method just adds the rectangle to the collection.
private void panel1_MouseUp(object sender, MouseEventArgs e)
{
if (e.Button == System.Windows.Forms.MouseButtons.Left)
{
Color c = getSelectedColor(); //Gets a color for which to draw the rectangle
//Adds the rectangle using the color as the key for the dictionary
if (!rectangles.ContainsKey(c))
{
rectangles.Add(c, new List<Rectangle>());
}
rectangles[c].Add(new Rectangle(e.Location.X - 12, e.Location.Y - 12, 25, 25)); //Adds the rectangle to the collection
}
//Make the panel repaint itself.
panel1.Refresh();
}
private void panel1_MouseClick(object sender, MouseEventArgs e)
{
Graphics g = panel1.CreateGraphics();
g.DrawRectangle(new Pen(Brushes.Black),
new Rectangle(new Point(e.X, e.Y), new
Size(100, 100)));
}
you can change the color in Brushes.Black part of code, change it as you desire