Can you help me with this piece of code ?
I want to learn to use Invalidate and Update , but I'm not sure how to use it
This code doesn't work. I want set new text but it doesn't "refresh" and doesnt write the new string "Prova". Thanks
namespace Invalidate
{
public partial class Form1 : Form
{
private String txt;
private PointF xy;
public Form1()
{
InitializeComponent();
}
private void panel1_Paint(object sender, PaintEventArgs e)
{
e.Graphics.DrawString("This is the text that prints!",
this.Font, System.Drawing.Brushes.Azure, 0, 0);
}
private void Form1_Load(object sender, EventArgs e)
{
Panel pHText = new Panel();
pHText.Name = "ctrId";
pHText.Location = new Point(10, 10);
pHText.Size = new Size(200, 200);
pHText.BackColor = Color.White;
pHText.Paint += paintingUrCtr;
Controls.Add(pHText);
}
private void paintingUrCtr(object sender, PaintEventArgs e)
{
Font myFont = new Font("Arial", 14);
e.Graphics.DrawLine(new Pen(Color.Black), 0, 0, 10, 10);
e.Graphics.DrawString(this.txt, myFont, Brushes.Blue, 10, 10);
}
public void setText(String text, PointF pos)
{
this.txt = text;
this.xy = pos;
}
private void button_Click(object sender, EventArgs e)
{
setText("Prova", new PointF(100, 100));
this.Invalidate();
this.Update();
}
}
}
Calling this.Invalidate(); does not invalidate child controls, you need to use the overload that takes in a bool and pass in true
private void button_Click(object sender, EventArgs e)
{
setText("Prova", new PointF(100, 100));
this.Invalidate(true);
this.Update();
}
EDIT: as mentioned in the comments, you could also just invalidate the single child control and update that.
private void button_Click(object sender, EventArgs e)
{
setText("Prova", new PointF(100, 100));
this.Controls["ctrId"].Invalidate(true);
this.Controls["ctrId"].Update();
}
Related
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();
}
}
Hi I'm using the code below to draw a circle on a pictureBox, The problem is I don't know why some times if I draw a circle it whon show until I draw an other, some times it will show on the first circle.
public partial class Form1 : Form
{
private bool isMoving = false;
private Point mouseDownPosition = Point.Empty;
private Point mouseMovePosition = Point.Empty;
private List<Tuple<Point, Point>> lines = new List<Tuple<Point, Point>>();
public Form1()
{
InitializeComponent();
//
// pictureBox1
//
this.pictureBox1.Location = new System.Drawing.Point(0, 0);
this.pictureBox1.Name = "pictureBox1";
this.pictureBox1.Size = new System.Drawing.Size(231, 235);
this.pictureBox1.TabIndex = 0;
this.pictureBox1.TabStop = false;
this.pictureBox1.Paint += new System.Windows.Forms.PaintEventHandler(this.pictureBox1_Paint);
this.pictureBox1.MouseDown += new System.Windows.Forms.MouseEventHandler(this.pictureBox1_MouseDown);
this.pictureBox1.MouseMove += new System.Windows.Forms.MouseEventHandler(this.pictureBox1_MouseMove);
this.pictureBox1.MouseUp += new System.Windows.Forms.MouseEventHandler(this.pictureBox1_MouseUp);
this.Controls.Add(this.pictureBox1);
}
private void pictureBox1_Paint(object sender, PaintEventArgs e)
{
var g = e.Graphics;
if (isMoving)
{
g.Clear(pictureBox1.BackColor);
g.DrawLine(Pens.Black, mouseDownPosition, mouseMovePosition);
foreach (var line in lines)
{
g.DrawLine(Pens.Black, line.Item1, line.Item2);
}
}
}
private void pictureBox1_MouseDown(object sender, MouseEventArgs e)
{
isMoving = true;
mouseDownPosition = e.Location;
}
private void pictureBox1_MouseMove(object sender, MouseEventArgs e)
{
if (isMoving)
{
mouseMovePosition = e.Location;
pictureBox1.Invalidate();
}
}
private void pictureBox1_MouseUp(object sender, MouseEventArgs e)
{
if (isMoving)
{
lines.Add(Tuple.Create(mouseDownPosition, mouseMovePosition));
}
isMoving = false;
}
}
Use Refresh() instead of using Invalidate(). This will force the re-paint event to be called. Note that you may see a performance drop if you excessively repaint the screen.
private void pictureBox1_MouseMove(object sender, MouseEventArgs e)
{
if (isMoving)
{
mouseMovePosition = e.Location;
pictureBox1.Refresh();
}
}
I don't see any circles in your sample:)
I noticed your code was behaving a bit weird, when I added the following it seemed to make it run a bit better.
this.pictureBox1.MouseClick += pictureBox1_MouseClick;
...
void pictureBox1_MouseClick(object sender, MouseEventArgs e)
{
isMoving = false;
}
Hope this helps :)
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.
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;
}
}
i need to animate an object in c# windows application
int l_nCircleXpos = 9, l_nCircleYpos = 0;
private void Form1_Paint(object sender, PaintEventArgs e)
{
Graphics l_objGraphics = this.CreateGraphics();
Pen l_circlePen = new Pen(Color.Blue);
SolidBrush l_circleBrush = new SolidBrush(Color.Blue);
l_objGraphics.DrawEllipse(l_circlePen, l_nCircleXpos, l_nCircleYpos, 30, 30);
l_objGraphics.FillEllipse(l_circleBrush, l_nCircleXpos, l_nCircleYpos, 30, 30);
Pen l_rectPen = new Pen(Color.Red);
}
private void timer1_Tick(object sender, EventArgs e)
{
l_nCircleXpos++;
l_nCircleYpos++;
}
private void timer2_Tick(object sender, EventArgs e)
{
Invalidate();
}
but in timer2 its invalidating the entire form. i need to invalidate the specific circle area only.
please help to do this in a better way
You can pass a Rectangle (or better, a Region) as a parameter to Invalidate, to invalidate only the area you need to refresh :
Region region = /* region you need to refresh */;
this.Invalidate(region);