I am trying to add an ellipse to my grid from my mouse position. How can I define where the ellipse is drawn?
here is my mouse down event:
private void GridCanvas_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
_sensorPoint = Mouse.GetPosition(GridCanvas);
AddSensor();
}
And my AddSensor() method:
private void AddSensor()
{
Ellipse sensorEllipse = new Ellipse();
SolidColorBrush solidColorBrush = new SolidColorBrush();
solidColorBrush.Color = Color.FromArgb(0, 0, 0, 0);
sensorEllipse.Fill = solidColorBrush;
sensorEllipse.StrokeThickness = 2;
sensorEllipse.Stroke = Brushes.Black;
sensorEllipse.Width = 10;
sensorEllipse.Height = 10;
GridCanvas.Children.Add(sensorEllipse);
}
How can I add sensorEllipse where the mouse is clicked on the canvas?
You can set position with any of those methods:
private void AddSensor()
{
Ellipse sensorEllipse = new Ellipse();
SolidColorBrush solidColorBrush = new SolidColorBrush();
solidColorBrush.Color = Color.FromArgb(0, 0, 0, 0);
sensorEllipse.Fill = solidColorBrush;
sensorEllipse.SetValue(Canvas.LeftProperty, _sensorPoint.X);
sensorEllipse.SetValue(Canvas.TopProperty, _sensorPoint.Y);
//Canvas.SetLeft(sensorEllipse, _sensorPoint.X);
//Canvas.SetTop(sensorEllipse, _sensorPoint.Y);
sensorEllipse.StrokeThickness = 2;
sensorEllipse.Stroke = Brushes.Black;
sensorEllipse.Width = 10;
sensorEllipse.Height = 10;
//adding event handler for right mouse down:
sensorEllipse.MouseRightButtonDown += new MouseButtonEventHandler(sensorEllipse_MouseRightButtonDown);
GridCanvas.Children.Add(sensorEllipse);
}
EDIT
For adding/deleting ellipses check, which mouse button was pressed at GridCanvas_MouseLeftButtonDown
private void GridCanvas_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
_sensorPoint = Mouse.GetPosition(GridCanvas);
AddSensor();
}
Then add event handler for new ellipses:
void sensorEllipse_MouseRightButtonDown(object sender, MouseButtonEventArgs e)
{
Ellipse ellipse = sender as Ellipse;
GridCanvas.Children.Remove(ellipse);
}
Related
XAML
<Canvas Name="canvas" MouseDown="canvas_MouseDown" MouseUp="canvas_MouseUp" Background="White" MouseMove="canvas_MouseMove" />
C#
Line AnimationLine;
Point P1;
private void canvas_MouseDown(object sender, MouseButtonEventArgs e)
{
P1 = e.GetPosition(canvas);
AnimationLine = new Line() { Stroke = new SolidColorBrush { Color = Colors.Blue },StrokeThickness = 3};
AnimationLine.X1 = P1.X;
AnimationLine.Y1 = P1.Y;
canvas.Children.Add(AnimationLine);
}
private void canvas_MouseUp(object sender, MouseButtonEventArgs e)
{
var P2 = e.GetPosition(canvas);
canvas.Children.Remove(AnimationLine);
//AnimationLine = new Line();
canvas.Children.Add
(new Line()
{
X1 = P1.X,
Y1 = P1.Y,
X2 = P2.X,
Y2 = P2.Y,
StrokeThickness = 3,
Stroke = new SolidColorBrush { Color = Colors.Blue }
});
}
private void canvas_MouseMove(object sender, MouseEventArgs e)
{
if(e.LeftButton == MouseButtonState.Pressed)
{
var P2 = e.GetPosition(canvas);
AnimationLine.X2 = P2.X;
AnimationLine.Y2 = P2.Y;
}
}
i am trying to draw a line first point assigned on mouse down, second point assigned on mouse up and thats when the line gets drawn, but when dragging i want to show the Animation line, animation line which is like a real time guide line.
in order to get it i want to draw a line just like in microsoft paint.
i just wrote the above and it works great, but is this really the way to do it? any built in functionalities that could help?
Your code could be simplified like shown below. In particular you should add handlers for the MouseLeftButtonDown and MouseLeftButtonUp events instead of the more general MouseDown and MouseUp events. Note also that you would typically capture the mouse, and that the only purpose for having a mouse up handler is to release the mouse capture.
XAML:
<Canvas Background="Transparent"
MouseLeftButtonDown="Canvas_MouseLeftButtonDown"
MouseLeftButtonUp="Canvas_MouseLeftButtonUp"
MouseMove="Canvas_MouseMove"/>
Code behind:
private void Canvas_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
var canvas = (Canvas)sender;
if (canvas.CaptureMouse())
{
var startPoint = e.GetPosition(canvas);
var line = new Line
{
Stroke = Brushes.Blue,
StrokeThickness = 3,
X1 = startPoint.X,
Y1 = startPoint.Y,
X2 = startPoint.X,
Y2 = startPoint.Y,
};
canvas.Children.Add(line);
}
}
private void Canvas_MouseMove(object sender, MouseEventArgs e)
{
var canvas = (Canvas)sender;
if (canvas.IsMouseCaptured && e.LeftButton == MouseButtonState.Pressed)
{
var line = canvas.Children.OfType<Line>().LastOrDefault();
if (line != null)
{
var endPoint = e.GetPosition(canvas);
line.X2 = endPoint.X;
line.Y2 = endPoint.Y;
}
}
}
private void Canvas_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
((Canvas)sender).ReleaseMouseCapture();
}
I am trying to create a Form in Visual Studio Windows Forms Apps C# in which during runtime the user or operator can create a new picturebox with a left mouse click and then have the ability to move each picturebox created.
I really do not know where to begin. Anyone have any ideas?
To add a new PictureBox dynamically, you can subscribe to the event Form_MouseClick and create the PictureBox like this:
public Form1()
{
InitializeComponent();
this.MouseClick += Form_MouseClick;
}
private void Form_MouseClick(object sender, MouseEventArgs e)
{
PictureBox pictureBox = new PictureBox();
// cursor location
pictureBox.Location = new Point(e.X, e.Y);
pictureBox.BackColor = Color.Red;
this.Controls.Add(pictureBox);
}
To drag and move the PictureBox, you also nee to subscribe to the event MouseDown, MouseUp, and MouseMove.
Here is a simple demo you can refer to.
private void Form_MouseClick(object sender, MouseEventArgs e)
{
// create new control
PictureBox pictureBox = new PictureBox();
pictureBox.Location = new Point(e.X, e.Y);
pictureBox.BackColor = Color.Red;
this.Controls.Add(pictureBox);
// bind event for each PictureBox
pictureBox.MouseDown += pictureBox_MouseDown;
pictureBox.MouseUp += pictureBox_MouseUp;
pictureBox.MouseMove += pictureBox_MouseMove;
}
Point mouseDownPoint = Point.Empty;
Rectangle rect = Rectangle.Empty;
bool isDrag = false;
private void pictureBox_MouseDown(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Left)
{
mouseDownPoint = e.Location;
rect = (sender as PictureBox).Bounds;
}
}
private void pictureBox_MouseUp(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Left)
{
if (isDrag)
{
isDrag = false;
(sender as PictureBox).Location = rect.Location;
this.Refresh();
}
reset();
}
}
private void pictureBox_MouseMove(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Left)
{
isDrag = true;
rect.Location = this.PointToClient((sender as PictureBox).PointToScreen(new Point(e.Location.X - mouseDownPoint.X, e.Location.Y - mouseDownPoint.Y)));
this.Refresh();
}
}
private void reset()
{
mouseDownPoint = Point.Empty;
rect = Rectangle.Empty;
isDrag = false;
}
You can add the form elements during runtime:
var picture = new PictureBox
{
Name = "pictureBox",
Size = new Size(16, 16),
Location = new Point(100, 100),
Image = Image.FromFile("test.jpg"),
};
this.Controls.Add(picture);
Afterward, you can move it with the Mouse Events
I want to draw area inside a container. For this i thought about using custom control.
My problem is that Canvas does not take up all the given space it gets. How to force it to use all available space?
What i have done is inherited from Canvas and created border element inside it:
public class DrawableCanvas : Canvas
{
private Border border;
static DrawableCanvas()
{
DefaultStyleKeyProperty.OverrideMetadata(typeof(DrawableCanvas), new FrameworkPropertyMetadata(typeof(DrawableCanvas)));
}
public DrawableCanvas()
{
this.border = new Border();
border.Background = new SolidColorBrush(Colors.Blue);
border.BorderThickness = new Thickness(1);
border.Width = 0;
border.Visibility = Visibility.Hidden;
border.Opacity = 0.3;
this.Children.Add(border);
this.MouseLeftButtonDown += DrawableCanvas_MouseLeftButtonDown;
this.MouseLeftButtonUp += DrawableCanvas_MouseLeftButtonUp;
this.MouseMove += DrawableCanvas_MouseMove;
}
private void DrawableCanvas_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
Debug.WriteLine("Left mouse up");
// release mouse
Mouse.Capture(null);
border.Width = 0;
border.Height = 100;
startPosition = 0;
}
double startPosition = 0;
private void DrawableCanvas_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
Debug.WriteLine("Left mouse down");
border.Visibility = Visibility.Visible;
// capture mouse
Mouse.Capture(this);
var point = e.GetPosition(this);
startPosition = point.X;
SetLeft(border, point.X);
}
private void DrawableCanvas_MouseMove(object sender, MouseEventArgs e)
{
if(this.IsMouseCaptured)
{
var point = e.GetPosition(this);
Debug.WriteLine("Mouse move");
// set the position to far left
SetLeft(border, Math.Min(startPosition, point.X));
// width is the difference between two points
border.Width = Math.Abs(startPosition - point.X);
Debug.WriteLine(Math.Min(startPosition, point.X));
Debug.WriteLine(border.Width);
}
}
}
And for view:
<DockPanel>
<local:DrawableCanvas>
<Rectangle Height="500" Width="500" Fill="Transparent" />
</local:DrawableCanvas>
</DockPanel>
I want something like this:
What I wanted to do is to create this control to enable selection on ui.
For this i needed a border/rectangle that will span only in width and use up all the height it gets
I ended up with this:
View:
<Window x:Class="Wpf.Test01.Stack_43281567"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:Wpf.Test01.Controls"
mc:Ignorable="d"
Title="Stack_43281567" Height="300" Width="300">
<Grid>
<local:DrawableCanvas />
</Grid>
</Window>
DrawableCanvas.cs:
public class DrawableCanvas : Canvas
{
private Border border;
static DrawableCanvas()
{
DefaultStyleKeyProperty.OverrideMetadata(typeof(DrawableCanvas), new FrameworkPropertyMetadata(typeof(DrawableCanvas)));
}
// when selection is done expose event to notify the user of selection change
public DrawableCanvas()
{
this.border = new Border();
border.Background = new SolidColorBrush(Colors.Blue);
border.BorderThickness = new Thickness(1);
border.Visibility = Visibility.Hidden;
border.Opacity = 0.3;
border.Height = this.ActualHeight;
this.Children.Add(border);
this.Background = new SolidColorBrush(Colors.Transparent);
this.MouseLeftButtonDown += DrawableCanvas_MouseLeftButtonDown;
this.MouseLeftButtonUp += DrawableCanvas_MouseLeftButtonUp;
this.MouseMove += DrawableCanvas_MouseMove;
this.SizeChanged += DrawableCanvas_SizeChanged;
}
private void DrawableCanvas_SizeChanged(object sender, SizeChangedEventArgs e)
{
border.Height = e.NewSize.Height;
}
private void DrawableCanvas_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
Debug.WriteLine("Left mouse up");
// release mouse
Mouse.Capture(null);
border.Width = 0;
startPosition = 0;
}
double startPosition = 0;
private void DrawableCanvas_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
Debug.WriteLine("Left mouse down");
border.Visibility = Visibility.Visible;
// capture mouse
Mouse.Capture(this);
var point = e.GetPosition(this);
startPosition = point.X;
SetLeft(border, point.X);
}
private void DrawableCanvas_MouseMove(object sender, MouseEventArgs e)
{
if (this.IsMouseCaptured)
{
var point = e.GetPosition(this);
Debug.WriteLine("Mouse move");
// set the position to far left
SetLeft(border, Math.Min(startPosition, point.X));
// width is the difference between two points
border.Width = Math.Abs(startPosition - point.X);
Debug.WriteLine(Math.Min(startPosition, point.X));
Debug.WriteLine(border.Width);
}
}
}
I have a button in my windows forms which I need to enable/disable. When disabled I need to change its backcolor and retain the forecolor to show that it is disabled.
Following is what I tried. this retains the forecolor(white here), but does not change the backcolor
private void button1_EnabledChanged(object sender, System.EventArgs e)
{
buttonScan.ForeColor = Color.White;
buttonScan.BackColor = Color.Aqua;
}
private void button1_Paint(object sender, PaintEventArgs e)
{
var btn = (Button)sender;
var drawBrush = new SolidBrush(btn.ForeColor);
var sf = new StringFormat { Alignment = StringAlignment.Center, LineAlignment = StringAlignment.Center};
e.Graphics.DrawString(btn.Text, btn.Font, drawBrush, e.ClipRectangle, sf);
drawBrush.Dispose();
sf.Dispose();
}
I need to change the backcolor when the button is disabled
f you want to use your custom color, you need to set UseVisualStyleBackColor to false or the color will only be applied to the button upon mouse over.
a simple test uploaded to GitHub
public partial class mainForm : Form
{
Random randonGen = new Random();
public mainForm()
{
InitializeComponent();
}
private void mainForm_Load(object sender, EventArgs e)
{
populate();
}
private void populate()
{
Control[] buttonsLeft = createButtons().ToArray();
Control[] buttonsRight = createButtons().ToArray();
pRight.Controls.AddRange(buttonsRight);
pLeft.Controls.AddRange(buttonsLeft);
}
private List<Button> createButtons()
{
List<Button> buttons = new List<Button>();
for (int i = 1; i <= 5; i++)
{
buttons.Add(
new Button()
{
Size = new Size(200, 35),
Enabled = true,
BackColor = GetColor(),
ForeColor = GetColor(),
UseVisualStyleBackColor = false,
Left = 20,
Top = (i * 40),
Text = String.Concat("Button ", i)
});
}
return buttons;
}
private Color GetColor()
{
return Color.FromArgb(randonGen.Next(255), randonGen.Next(255), randonGen.Next(255));
}
}
I'm trying to draw a single line using OnMouseMove() event. My Problem is that everytime I move the mouse It leaves a trail. I tried to use the refresh method, but when I stop moving the mouse the line is gone. I don't want the line to be drawn OnPaint();, Just want to draw it OnMouseMove().
EDIT: I'm using a transparent panel(cp.ExStyle |= 0x20;), so I cant use the graphics.Clear() and BackColor()
Here's a Sample Image without the Refresh():
Here's my code:
private void panel1_MouseMove(object sender, MouseEventArgs e)
{
Graphics g = panel1.CreateGraphics();
g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias;
using (var p = new Pen(Color.Black, 3))
{
p.StartCap = System.Drawing.Drawing2D.LineCap.ArrowAnchor;
p.EndCap = System.Drawing.Drawing2D.LineCap.ArrowAnchor;
g.DrawLine(p, st, e.Location);
}
Thread.Sleep(30);
Invalidate();
//this.Refresh();
g.Dispose();
}
Regards
The following works for me. Basically keep track of the last line drawn and draw over it with the background color of the panel (gives the effect of clearing it).
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private const int PEN_WIDTH = 3;
private const LineCap START_CAP = LineCap.ArrowAnchor;
private const LineCap END_CAP = LineCap.ArrowAnchor;
Point mAnchorPoint = new Point(10, 10);
Point mPreviousPoint = Point.Empty;
private void panel1_MouseMove(object sender, MouseEventArgs e)
{
using (Graphics g = panel1.CreateGraphics())
{
// Clear last line drawn
using (Pen clear_pen = new Pen(panel1.BackColor, PEN_WIDTH))
{
clear_pen.StartCap = START_CAP;
clear_pen.EndCap = END_CAP;
g.DrawLine(clear_pen, mAnchorPoint, mPreviousPoint);
}
// Update previous point
mPreviousPoint = e.Location;
// Draw the new line
using (Pen draw_pen = new Pen(Color.Black, PEN_WIDTH))
{
draw_pen.StartCap = START_CAP;
draw_pen.EndCap = END_CAP;
g.DrawLine(draw_pen, mAnchorPoint, e.Location);
}
}
}
}
If you panel's background color is set to Transparent, you will need to change panel1.BackColor to panel1.Parent.BackColor
If the Transparent Panel is not working, you could use the DrawReversibleLine function (although this doesn't allow the color or thickness of the line to be changed, it should have no issues with drawing/erasing even if the panel is Transparent:
Point mAnchorPoint = new Point(200, 200);
Point mPreviousPoint = Point.Empty;
private void panel1_MouseMove(object sender, MouseEventArgs e)
{
if (mPreviousPoint != Point.Empty)
{
// Clear last line drawn
ControlPaint.DrawReversibleLine(PointToScreen(mAnchorPoint), PointToScreen(mPreviousPoint), Color.Pink);
}
// Update previous point
mPreviousPoint = e.Location;
mPreviousPoint.Offset(myPanel1.Location);
// Draw the new line
ControlPaint.DrawReversibleLine(PointToScreen(mAnchorPoint), PointToScreen(mPreviousPoint), Color.Pink);
}
Another simple way to draw a line with mouse in C#:
public partial class Form1 : Form
{
Options_c o = new Options_c();
public Form1()
{
InitializeComponent();
}
private void pictureBox1_MouseUp(object sender, MouseEventArgs e)
{
o.Allow = false;
}
private void pictureBox1_MouseDown(object sender, MouseEventArgs e)
{
o.Allow = true;
o.X = e.X;
o.Y = e.Y;
}
private void pictureBox1_MouseMove(object sender, MouseEventArgs e)
{
if (o.Allow == true)
{
Graphics g = pictureBox1.CreateGraphics();
Pen p1 = new Pen(o.color, 5);
g.DrawLine(p1, o.X,o.Y, e.X, e.Y);
o.X = e.X;
o.Y = e.Y;
}
}
}
class Options_c
{
public Boolean Allow = false;
public Int32 X;
public Int32 Y;
public Color color = Color.Bisque;
}
After
g.DrawLine(p, st, e.Location);
put:
st = e.Location;
Does that fix the problem?
The problem with the line disappearing is that when the panel is repainted, the line is not redrawn. What you really need is to update the end-point of the line-segment when the mouse is moved across the panel and to invalidate the panel. Of course, this will mean that you do handle the Paint event on the panel.
Code here, without the event-handler registration:
Point endPoint;
private void panel1_Paint(object sender, PaintEventArgs e)
{
Graphics g = e.Graphics;
g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias;
using (var p = new Pen(Color.Black, 3))
{
p.StartCap = System.Drawing.Drawing2D.LineCap.ArrowAnchor;
p.EndCap = System.Drawing.Drawing2D.LineCap.ArrowAnchor;
g.DrawLine(p, st, endPoint);
}
Thread.Sleep(30);
}
private void panel1_MouseMove(object sender, MouseEventArgs e)
{
endPoint = e.Location;
panel1.Invalidate();
}
OKaie, i got it! If you have to draw a line between two geopoint
location on tocuhing these two location, then u have to use the
overlay class in this shape... MY CODE IS :
in Main activity write this code also:
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
mapView = (MapView) findViewById(R.id.mapView1);
mapView.setBuiltInZoomControls(true);
mapOverlays = mapView.getOverlays();//it get the mapview all overlays...
mc = mapView.getController();
mc.setZoom(13);
GeoPoint p = new GeoPoint(34159000,73220000);//starting point Abbottabad
GeoPoint p1 = new GeoPoint(41159000,43220000);//starting point Abbottabad
List<Overlay> mapOverlays2 ;
mapOverlays2 = mapView.getOverlays();
projection = mapView.getProjection();
myoverlay = new MarkerOverlay(p,p1);
mapOverlays2.add(myoverlay);//*/
}
class MarkerOverlay extends Overlay
{
GeoPoint p,p1;
private GeoPoint pa;
public MarkerOverlay(GeoPoint p,GeoPoint p1)
{
this.p = p;
this.p1=p1;
Toast.makeText(GoogleMapShowActivity.this, "point value is "+p +"-->"+p1, Toast.LENGTH_LONG).show();
}
public void draw(Canvas canvas, MapView mapView,boolean shadow)//), long when)
{
super.draw(canvas, mapView, shadow);
Paint mPaint = new Paint();
mPaint.setDither(true);
mPaint.setColor(Color.RED);
mPaint.setStyle(Paint.Style.FILL_AND_STROKE);
mPaint.setStrokeJoin(Paint.Join.ROUND);
mPaint.setStrokeCap(Paint.Cap.ROUND);
mPaint.setStrokeWidth(4);
GeoPoint gP1 = new GeoPoint(p.getLatitudeE6(),p.getLongitudeE6());//starting point Abbottabad
GeoPoint gP2 = new GeoPoint(p1.getLatitudeE6(),p1.getLongitudeE6());//(33695043,73050000);//End point Islamabad
Point p1 = new Point();
Point p2 = new Point();
Path path1 = new Path();
projection.toPixels(gP1, p1); //changing the latitude into the screen pixels.
projection.toPixels(gP2, p2);
path1.moveTo(p1.x, p1.y);//Moving to Abbottabad location
path1.lineTo(p2.x,p2.y);//Path till Islamabad
canvas.drawPath(path1, mPaint);//Actually drawing the path from Abbottabad to Islamabad
}
//--------------------------//
public boolean onTouchEvent(MotionEvent event, MapView mapView)
{
location_touch++;//this is called two times before executing other codes in thsi method(),
// Toast.makeText(GoogleMapShowActivity.this, "this is mmmm"+location_touch, Toast.LENGTH_LONG).show();
if (event.getAction() == 1)
{
// Toast.makeText(GoogleMapShowActivity.this, "this is me ..."+location_touch, Toast.LENGTH_LONG).show();
GeoPoint p = mapView.getProjection().fromPixels((int) event.getX(), (int) event.getY());
if((location_touch%2)!=0)
{
location_touch=0;
Toast.makeText(GoogleMapShowActivity.this, "VALUE 2..."+location_touch+"gp is "+p+",,"+p1, Toast.LENGTH_LONG).show();
mapView.getOverlays().add(new MarkerOverlay(p,pa));
mapView.invalidate();
}
else //if((location_touch==0 ))
{
pa=p;
Toast.makeText(GoogleMapShowActivity.this, "VALUE 1.."+location_touch+",,,"+p1, Toast.LENGTH_LONG).show();
location_touch++;
}