How to draw a line on panel overlapped by other panel? - c#

IDE: visual studio, c#, Windows from application
I am trying to draw a line on a panel. I am able to draw line on panel1 by clicking on it.
//Code
public partial class Form1 : Form
{
static int px=5, py=5;
public Form1()
{
InitializeComponent();
}
private void panel1_Paint(object sender, PaintEventArgs e)
{
e.Graphics.DrawLine(Pens.Red, 5, 5, px, py);
}
private void panel1_MouseDown(object sender, MouseEventArgs e)
{
initilizeXY(e.X, e.Y);
}
private void Form1_Load(object sender, EventArgs e)
{
}
private void panel1_MouseMove(object sender, MouseEventArgs e)
{
}
private void initilizeXY( int pxx, int pyy)
{
px = pxx;
py = pyy;
}
private void panel1_MouseUp(object sender, MouseEventArgs e)
{
panel1.Refresh();
}
private void panel2_MouseDown(object sender, MouseEventArgs e)
{
initilizeXY(e.X, e.Y);
}
}
// by this code i am able to draw a line on mouse down on panel 1.
but due to some requirement changes there is another panel ( panel2) which is partially overlapping panel1.
Now i want to draw the same line on panel1 if the user click on panel1 or panel2.
Please suggest how make this work done?

This code works:
Point bgn1 = new Point(5, 5);
Point end1 = new Point(5, 5);
Point bgn2 = new Point(0, 0);
Point end2 = new Point(0, 0);
private void Form1_Load(object sender, EventArgs e)
{
Point pnt, pntscr;
pnt.X = 5;
pnt.Y = 5;
pntscr = Panel1.PointToScreen(pnt);
bgn2 = Panel2.PointToClient(pntscr);
end2 = bgn2;
}
private void panel1_MouseDown(object sender, MouseEventArgs e)
{
end1.X = e.X;
end1.Y = e.Y;
Point pntscr;
pntscr = Panel1.PointToScreen(end1);
end2 = Panel2.PointToClient(pntscr);
}
private void panel1_MouseUp(object sender, MouseEventArgs e)
{
panel1.Refresh();
panel2.Refresh();
}
private void panel2_MouseDown(object sender, MouseEventArgs e)
{
end2.X = e.X;
end2.Y = e.Y;
Point pntscr;
pntscr = Panel2.PointToScreen(end2);
end1 = Panel1.PointToClient(pntscr);
}
private void panel2_MouseUp(object sender, MouseEventArgs e)
{
panel1.Refresh();
panel2.Refresh();
}
private void panel1_Paint(object sender, PaintEventArgs e)
{
e.Graphics.DrawLine(Pens.Red, bgn1, end1);
}
private void panel2_Paint(object sender, PaintEventArgs e)
{
e.Graphics.DrawLine(Pens.Red, bgn2, end2);
}
valter

EDIT: Fixed the code to work properly.
Tested in a scenario when panel2 overlaps panel1 on the right side of panel1, starting a little lower than panel1's top.
Writing this bit of code I assumed panel2's X and Y coords are greater than panel1's. Perhaps you should reverse the offset calculation if it's the other way around.
public partial class Form1 : Form
{
static int px = 5, py = 5;
static int p2x = 0, p2y = 0;
int offsetX;
int offsetY;
public Form1()
{
InitializeComponent();
offsetX = panel2.Location.X - panel1.Location.X;
offsetY = panel2.Location.Y - panel1.Location.Y;
}
private void panel1_Paint(object sender, PaintEventArgs e)
{
e.Graphics.DrawLine(Pens.Red, 5, 5, px, py);
}
private void panel1_MouseDown(object sender, MouseEventArgs e)
{
initilizeXY(e.X, e.Y);
}
private void Form1_Load(object sender, EventArgs e)
{
}
private void initilizeXY(int pxx, int pyy)
{
px = pxx;
py = pyy;
}
private void initilizeXY2(int pxx, int pyy)
{
p2x = pxx;
p2y = pyy;
}
private void panel1_MouseUp(object sender, MouseEventArgs e)
{
panel1.Refresh();
panel2.Refresh();
}
private void panel2_MouseDown(object sender, MouseEventArgs e)
{
initilizeXY(e.X+offsetX, e.Y+offsetY);
initilizeXY2(e.X, e.Y);
}
private void panel2_Paint(object sender, PaintEventArgs e)
{
if (px > offsetX && py > offsetY)
{
int p2start = findIntersectFromLineEquation(new Point(5, 5), new Point(px, py));
e.Graphics.DrawLine(Pens.Red, 0, p2start - offsetY, p2x, p2y);
}
}
private int findIntersectFromLineEquation(Point start, Point end)
{
if (start.X == end.X || start.Y == end.Y)
return 0;
double a = (double)(end.Y - start.Y) / (double)(end.X - start.X);
double b = (double)(start.Y) - (double)(a * start.X);
return (int)(a * offsetX + b);
}
}
Remember to subscribe the events accordingly.

Related

What is best way to write in windows forms with pen-tablet like wacom intuos in C#

i have a problem.
I'm writing a program that writes on it with a stylus.
First, i create a windows form with a panel.
second, this code:
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Collections;
using System.Diagnostics;
using System.Drawing.Drawing2D;
namespace testWrite
{
public partial class Form1 : Form
{
Graphics g;
int x = -1;
int y = -1;
bool moving = false;
Pen pen;
public Form1()
{
InitializeComponent();
g = panel1.CreateGraphics();
pen = new Pen(Color.Black, 5);
pen.SetLineCap(System.Drawing.Drawing2D.LineCap.Round, System.Drawing.Drawing2D.LineCap.Round, System.Drawing.Drawing2D.DashCap.Round);
pen.StartCap = System.Drawing.Drawing2D.LineCap.Round;
pen.EndCap = System.Drawing.Drawing2D.LineCap.Round;
}
private void panel1_MouseMove(object sender, MouseEventArgs e)
{
if(e.Button == MouseButtons.Left)
{
g.DrawLine(pen, new Point(x, y), e.Location);
x = e.X;
y = e.Y;
}
}
private void panel1_MouseUp(object sender, MouseEventArgs e)
{
x = -1;
y = -1;
moving = false;
}
private void panel1_MouseDown(object sender, MouseEventArgs e)
{
x = e.X;
y = e.Y;
moving = true;
}
}
}
I use this app with a Wacom intuos
But the result is not so good because a few words are lost...haizzz
toi tên la trần
quang hieu
hello heloo
especially, when i write fast or the text is small.
when i write in Microsoft Paint, it is very good
What is best way to to write in windows forms with pen-tablet like wacom intuos?
UPDATE 1:
With cmt from TaW.
Thanks for your help. But, that's not what I need...
i was change my code to:
public partial class Form1 : Form
{
List<Point> curPoints = new List<Point>();
List<List<Point>> allPoints = new List<List<Point>>();
public Form1()
{
InitializeComponent();
}
private void panel1_MouseMove(object sender, MouseEventArgs e)
{
if (e.Button != MouseButtons.Left) return;
// here we should check if the distance is more than a minimum!
curPoints.Add(e.Location);
// let it show
panel1.Invalidate();
}
private void panel1_MouseUp(object sender, MouseEventArgs e)
{
if (curPoints.Count > 1)
{
// ToList creates a copy
allPoints.Add(curPoints.ToList());
curPoints.Clear();
}
}
private void panel1_MouseDown(object sender, MouseEventArgs e)
{
if (curPoints.Count > 1)
{
// begin fresh line or curve
curPoints.Clear();
// startpoint
curPoints.Add(e.Location);
}
}
private void panel1_Paint(object sender, PaintEventArgs e)
{
// here you can use DrawLines or DrawCurve
// current line
if (curPoints.Count > 1) e.Graphics.DrawCurve(Pens.Red, curPoints.ToArray());
// other lines or curves
foreach (List<Point> points in allPoints)
if (points.Count > 1) e.Graphics.DrawCurve(Pens.Red, points.ToArray());
}
}
But nothing better. The result is worse...
I tried to write: "Hello my name is Hieu", but is not run...
Looks like a pen-tablet differs from a mouse when use to write. Because, with mouse i feel that is better in this code...
UPDATE 2:
With code by Idle_Mind. It will be fine if i set pen-tablet:
With setting "Click", it is not OK
How to fix it, i don't want to set "Double Click" to my pen !
Here's my version...worked great for me. You might need to adjust your tablet settings so that it picks up everything correctly:
public partial class FormTablet : Form
{
private Point lastPoint;
private GraphicsPath GP = null;
private List<GraphicsPath> GPs = new List<GraphicsPath>();
public FormTablet()
{
InitializeComponent();
}
private void checkBox1_CheckedChanged(object sender, EventArgs e)
{
pictureBox1.Invalidate();
}
private void pictureBox1_MouseDown(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Left)
{
lastPoint = new Point(e.X, e.Y);
GP = new GraphicsPath();
GP.AddLine(lastPoint, lastPoint);
GPs.Add(GP);
}
}
private void pictureBox1_MouseMove(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Left)
{
Point pt = new Point(e.X, e.Y);
GP.AddLine(lastPoint, pt);
lastPoint = pt;
pictureBox1.Invalidate();
}
}
private void pictureBox1_MouseUp(object sender, MouseEventArgs e)
{
GP = null;
pictureBox1.Invalidate();
}
private void pictureBox1_Paint(object sender, PaintEventArgs e)
{
if (checkBox1.Checked)
{
e.Graphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
}
using(Pen p = new Pen(Color.Black, (int)numericUpDown1.Value))
{
p.LineJoin = LineJoin.Round;
p.MiterLimit = p.Width / 2;
foreach (GraphicsPath path in GPs)
{
if (path.PathPoints.Count() > 2)
{
// draw the path
e.Graphics.DrawPath(p, path);
}
else
{
// just draw a single dot
Rectangle rc = new Rectangle(Point.Round(path.PathPoints[0]), new Size(1, 1));
rc.Inflate((int)numericUpDown1.Value, (int)numericUpDown1.Value);
e.Graphics.FillEllipse(Brushes.Black, rc);
}
}
}
}
private void numericUpDown1_ValueChanged(object sender, EventArgs e)
{
pictureBox1.Invalidate();
}
private void button1_Click(object sender, EventArgs e)
{
GPs.Clear();
pictureBox1.Invalidate();
}
}

Drag and drop in winforms

I need to drag 6 images, which are in PictureBoxes, to 6 answer panels, one at a time and if the correct image is dragged to the correct spot it adds 1 to the score which is in a class called 'score'. There is code below to show one of the pcitures working but the form lags alot and if the image is dragged anywhere above the panel, it will snap into place. is there a way to stop this?
namespace DragAndDropQuiz
{
public partial class Form2 : Form
{
public Form2()
{
InitializeComponent();
}
private void pcBxLiverpool_MouseEnter(object sender, EventArgs e)
{
this.Cursor = Cursors.Hand;
}
private void pcBxLiverpool_MouseLeave(object sender, EventArgs e)
{
this.Cursor = Cursors.Default;
}
private int xPos;
private int yPos;
private void pcBxGeneral_MouseDown(object sender, MouseEventArgs e)
{
if (e.Button == System.Windows.Forms.MouseButtons.Left)
{
xPos = e.X;
yPos = e.Y;
}
}
private void pcBxGeneral_MouseMove(object sender, MouseEventArgs e)
{
if (sender != null && sender.GetType() == typeof(PictureBox))
{
if (e.Button == System.Windows.Forms.MouseButtons.Left)
{
((PictureBox)sender).Top += (e.Y - yPos);
((PictureBox)sender).Left += (e.X - xPos);
this.Refresh();
}
}
}
private void pcBxGeneral_MouseUp(object sender, MouseEventArgs e)
{
if (sender != null && sender.GetType() == typeof(PictureBox))
{
if (e.Button == System.Windows.Forms.MouseButtons.Left)
{
PictureBox answer = (PictureBox)sender;
if (answer.Location.X < pnlAnswer.Location.X)
{
if (answer.Location.X + answer.Width > pnlAnswer.Location.X)
{
if ((answer.Location.X + answer.Width) < pnlAnswer.Location.X + pnlAnswer.Width)
{
answer.Location = pnlAnswer.Location;
}
}
}
else if (answer.Location.X > pnlAnswer.Location.X)
{
if (answer.Location.X < (pnlAnswer.Location.X + pnlAnswer.Width))
{
answer.Location = pnlAnswer.Location;
}
}
}
}
}
private void Form2_Paint(object sender, PaintEventArgs e)
{
}
private void groupBox2_Paint(object sender, PaintEventArgs e)
{
Graphics g = e.Graphics;
g.DrawRectangle(new Pen(Color.Red), pnlAnswer.Location.X, pnlAnswer.Location.Y, pnlAnswer.Width, pnlAnswer.Height);
}
}
}

Why are my graphics not appearing on the panel c#

The code displayed below is used for drawing different shapes, the problem that i am facing is that when i use the same code to display the drawings on the windows form it displays,,,but when i try to display them on a panel..it shows as blank during runtime..please have a look at the code and tell me where i am going wrong. Thank in advance to whoever replies to this post!
private ArrayList ds;
private Point mold;
private Point mcurr;
private int mshape;
private float mwidth;
private Color mcolor;
public Form1()
{
InitializeComponent();
ds = new ArrayList();
mshape = 0;
//mwidth = 1;
//mcolor = Color.Black;
DoubleBuffered = true;
}
private void Form1_Load(object sender, EventArgs e)
{
richTextBox1.SelectionFont = new Font("Arial", 9);
richTextBox1.SelectionBullet = true;
richTextBox1.SelectionColor = Color.Red;
}
private Rectangle rec(Point p1, Point p2)
{
Rectangle a = new Rectangle();
a.X = (p1.X > p2.X ? p2.X : p1.X);
a.Y = (p1.Y > p2.Y ? p2.Y : p1.Y);
a.Width = Math.Abs(p1.X - p2.X);
a.Height = Math.Abs(p1.Y - p2.Y);
return a;
}
private void draw(Graphics e, Point mold, Point mcur, int mshape, float mwidth, Color mcolor)
{
Pen p = new Pen(mcolor, mwidth);
switch (mshape)
{
case 0:
e.DrawRectangle(p, rec(mold, mcur));
break;
case 1:
e.DrawEllipse(p, rec(mold, mcur));
break;
case 2:
e.DrawLine(p, mold, mcur);
break;
case 3:
//this.Invalidate();
break;
}
}
private void toolStripButtonRectangle_Click(object sender, EventArgs e)
{
mshape = 0;
}
private void toolStripButtonEllipse_Click(object sender, EventArgs e)
{
mshape = 1;
}
private void toolStripButtonLine_Click(object sender, EventArgs e)
{
mshape = 2;
}
private void panel1_MouseDown(object sender, MouseEventArgs e)
{
panel1.Cursor = Cursors.Cross;
if (e.Button == MouseButtons.Left)
{
this.mold = e.Location;
}
}
private void panel1_MouseUp(object sender, MouseEventArgs e)
{
panel1.Cursor = Cursors.Default;
Class1 a = new Class1(mold, mcur, mshape, mwidth, mcolor);/// create a class
ds.Add(a);
}
private void panel1_MouseMove(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Left)
{
mcur = e.Location;
Invalidate();
}
}
private void panel1_Paint(object sender, PaintEventArgs e)
{
foreach (Class1 a in ds)
{
draw(e.Graphics, a.old, a.cur, a.shape, a.width, a.color);
}
draw(e.Graphics, mold, mcur, mshape, mwidth, mcolor);
}
private void btn_Clear_Click(object sender, EventArgs e)
{
Graphics erase = panel1.CreateGraphics();
erase.Clear(panel1.BackColor);
// g1.Clear(Color.Transparent);
}
}
}

How to draw straight line to the mouse coordinates?

When user press the left button and move the mouse it should appears a straight line(not permanent line) from previous point to the current mouse moving position. Finally a real straight line will appear when the user releases the left mouse. please help me ..how do i do it?
List<Point> points = new List<Point>();
private void pictureBox1_MouseDown(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Left)
{
points.Add(e.Location);
pictureBox1.Invalidate();
}
}
private void pictureBox1_Paint(object sender, PaintEventArgs e)
{
if (points.Count > 1)
e.Graphics.DrawLines(Pens.Black, points.ToArray());
}
This is what you're looking for
private Stack<Point> points = new Stack<Point>();
private void pictureBox1_MouseDown(object sender, MouseEventArgs e)
{
points.Clear();
points.Push(e.Location);
}
private void pictureBox1_MouseMove(object sender, MouseEventArgs e)
{
if (points.Count > 1)
{
points.Pop();
}
if (points.Count > 0 && e.Button == System.Windows.Forms.MouseButtons.Left)
{
points.Push(e.Location);
pictureBox1.Invalidate();
}
}
private void pictureBox1_Paint(object sender, PaintEventArgs e)
{
if (points.Count > 1)
e.Graphics.DrawLines(Pens.Black, points.ToArray());
}
I used Stack for ease of use, you are free to change to whatever collection of your choice.
To draw several line you can do something like this
private Stack<Line> lines = new Stack<Line>();
private void pictureBox1_MouseDown(object sender, MouseEventArgs e)
{
lines.Push(new Line { Start = e.Location });
}
private void pictureBox1_MouseMove(object sender, MouseEventArgs e)
{
if (lines.Count > 0 && e.Button == System.Windows.Forms.MouseButtons.Left)
{
lines.Peek().End = e.Location;
pictureBox1.Invalidate();
}
}
private void pictureBox1_Paint(object sender, PaintEventArgs e)
{
foreach (var line in lines)
{
e.Graphics.DrawLine(Pens.Black, line.Start, line.End);
}
}
class Line
{
public Point Start { get; set; }
public Point End { get; set; }
}
you can use mentioned code
Point currentPoint = new Point();
private void Canvas_MouseDown_1(object sender, System.Windows.Input.MouseButtonEventArgs e)
{
if (e.ButtonState == MouseButtonState.Pressed)
currentPoint = e.GetPosition(this);
}
private void Canvas_MouseMove_1(object sender, System.Windows.Input.MouseEventArgs e)
{
if (e.LeftButton == MouseButtonState.Pressed)
{
Line line = new Line();
line.Stroke = SystemColors.WindowFrameBrush;
line.X1 = currentPoint.X;
line.Y1 = currentPoint.Y;
line.X2 = e.GetPosition(this).X;
line.Y2 = e.GetPosition(this).Y;
currentPoint = e.GetPosition(this);
paintSurface.Children.Add(line);
}
}

Call paint event from mouse move event

When mouse move over a panel2, I need to draw lines. So far I have done following
public Form1()
{
InitializeComponent();
}
private void panel2_Paint(object sender, PaintEventArgs e)
{
if (isDragging)
{
letsPaint(sender, e);
}
}
private void panel2_MouseMove(object sender, MouseEventArgs e)
{
if (isDragging)
{
mouseMoveX = e.X;
mouseMoveY = e.Y;
this.Paint += new PaintEventHandler(panel2_Paint);
}
}
private void letsPaint(object sender, PaintEventArgs e)
{
Pen blackpen = new Pen(Color.Black, 3);
Graphics g = e.Graphics;
g.DrawLine(blackpen, mouseClickedX, mouseClickedY, mouseMoveX, mouseMoveY);
g.Dispose();
}
But nothing happens when I move mouse. I think I did something wrong PaintEventHandler() here. Please tell me how to do this and also if there is any better way for this.
Also I think my method will drawline on the form but I need to draw line on the panel2. How to do? Thanks in advance.
You invalidate:
public Form1()
{
InitializeComponent();
panel2.Paint += new letsPaint;
}
private void panel2_MouseMove(object sender, MouseEventArgs e)
{
if (isDragging) {
mouseMoveX = e.X;
mouseMoveY = e.Y;
panel2.Invalidate();
}
}
and you don't dispose the graphic object (you didn't create it), but you do the pen:
private void letsPaint(object sender, PaintEventArgs e) {
using (Pen blackpen = new Pen(Color.Black, 3)) {
e.Graphics.DrawLine(blackpen,
mouseClickedX, mouseClickedY, mouseMoveX, mouseMoveY);
}
}
Here is a quick little method that works with a bitmap:
Bitmap bmp;
Point lastPoint;
public Form1() {
InitializeComponent();
bmp = new Bitmap(panel1.ClientSize.Width, panel1.ClientSize.Height,
System.Drawing.Imaging.PixelFormat.Format32bppPArgb);
panel1.MouseDown += panel1_MouseDown;
panel1.MouseMove += panel1_MouseMove;
panel1.Paint += panel1_Paint;
}
void panel1_Paint(object sender, PaintEventArgs e) {
e.Graphics.DrawImage(bmp, Point.Empty);
}
void panel1_MouseMove(object sender, MouseEventArgs e) {
if (e.Button == MouseButtons.Left) {
using (Graphics g = Graphics.FromImage(bmp)) {
g.DrawLine(Pens.Black, lastPoint, e.Location);
}
lastPoint = e.Location;
panel1.Invalidate();
}
}
void panel1_MouseDown(object sender, MouseEventArgs e) {
lastPoint = e.Location;
}
This will flicker, so you would want to replace your panel with a double-buffered panel. Something like this:
public class PanelEx : Panel {
public PanelEx() {
this.DoubleBuffered = true;
}
}

Categories

Resources