How to animate dots in UserControl Paint event? - c#

In paint event because i want to be able to control the dots size colors and more properties.
using System.ComponentModel;
using System.Drawing;
using System.Drawing.Drawing2D;
public partial class LoadingLabel : UserControl
{
public LoadingLabel()
{
InitializeComponent();
}
private void LoadingLabel_Paint(object sender, PaintEventArgs e)
{
e.Graphics.SmoothingMode = SmoothingMode.AntiAlias;
e.Graphics.FillEllipse(Brushes.Red, 1, 1, 20, 20);
Thread.Sleep(1);
e.Graphics.FillEllipse(Brushes.Red, 1, 1, 0, 0);
Thread.Sleep(1);
}
}
I tried first to make a simple dot that is disappearing after some time and then show again but it's not working i see a red still dot(point).
later when this will work i want to make 3 dots animating like a loading animation.
This is what I've tried:
using System.ComponentModel;
using System.Drawing;
using System.Drawing.Drawing2D;
public partial class LoadingLabel : UserControl
{
private bool animate = false;
public LoadingLabel()
{
InitializeComponent();
timer1.Enabled = true;
}
private void LoadingLabel_Paint(object sender, PaintEventArgs e)
{
e.Graphics.SmoothingMode = SmoothingMode.AntiAlias;
if (animate == false)
{
e.Graphics.FillEllipse(Brushes.Red, 1, 1, 20, 20);
}
else
{
e.Graphics.FillEllipse(Brushes.Red, 5, 1, 20, 20);
}
}
int count = 0;
private void timer1_Tick(object sender, EventArgs e)
{
count++;
if(count == 10 && animate == false)
{
animate = true;
}
if(count == 20 && animate)
{
animate = false;
count = 0;
}
this.Invalidate();
}
}
the result is the first point draw then the second point draw but the first one is gone:
it looks like the point is moving to the right and back to the left.
but i want a loading effect with 3 points. and not moving point.
This is working with 3 points but it looks too complicated for 3 points. and if i want 100 points?
maybe i should use a loop inside the paint event ?
using System.ComponentModel;
using System.Drawing;
using System.Drawing.Drawing2D;
public partial class LoadingLabel : UserControl
{
private int numofpoints = 0;
public LoadingLabel()
{
InitializeComponent();
timer1.Enabled = true;
}
private void LoadingLabel_Paint(object sender, PaintEventArgs e)
{
e.Graphics.SmoothingMode = SmoothingMode.AntiAlias;
if(numofpoints == 0)
{
e.Graphics.FillEllipse(Brushes.Red, 1, 1, 20, 20);
}
if(numofpoints == 1)
{
e.Graphics.FillEllipse(Brushes.Red, 5, 1, 20, 20);
}
if(numofpoints == 2)
{
e.Graphics.FillEllipse(Brushes.Red, 10, 1, 20, 20);
}
}
int count = 0;
private void timer1_Tick(object sender, EventArgs e)
{
count++;
if(count == 10)
{
numofpoints = 0;
}
if(count == 20)
{
numofpoints = 1;
}
if(count == 30)
{
numofpoints = 2;
count = 0;
}
this.Invalidate();
}
}
Another update of what I've tried:
using System.ComponentModel;
using System.Drawing;
using System.Drawing.Drawing2D;
public partial class LoadingLabel : UserControl
{
private List<PointF> points = new List<PointF>();
public LoadingLabel()
{
InitializeComponent();
points.Add(new PointF(0, 0));
timer1.Enabled = true;
}
private void LoadingLabel_Paint(object sender, PaintEventArgs e)
{
e.Graphics.SmoothingMode = SmoothingMode.AntiAlias;
for (int i = 0; i < points.Count; i++)
{
e.Graphics.FillEllipse(Brushes.Red, points[i].X, points[i].Y, 20, 20);
}
}
int count = 0;
private void timer1_Tick(object sender, EventArgs e)
{
count++;
if (count < 3)
{
points.Add(new PointF(count * 20, 0));
//points = new List<PointF>();
}
//this.Invalidate();
}
}
If i will make the instance in the tick event it will not draw anything. if i will use the Invalidate line it will make the points to be like blinking.
what i want is to create a loading effect animation.
the result as the code now is still 3 points, and i want to animate them like in the link.
Something like this:

Since, based on the image you have posted, you want to animate a series of Dots, where only the active one changes color, your UserControl can define Properties that allow to specify the number of Dots, the Color of a Dot and the Color of the active Dot.
A Timer can be used to change the current active Dot, so the paint procedure knows when to change the color of one of the Dots.
The UserControl is automatically resized when the number of Dots specified changes.
Also when the UserControl is first created, it sets its MinimumSize, so the Dots are always visible.
You can expand on this template, adding more features.
Note these lines in the Constructor of the UserControl:
components = new Container();
dotsTimer = new Timer(components) { ... };
This instructs the Timer Component to add itself to the Components of the Parent container, so when the Parent is disposed, the Timer is also disposed and its event handler(s) removed.
Setting DoubleBuffered = true; avoids flickering when the Dots are drawn.
Call the Start() method to start the animation and the Stop() method to, well, stop it.
using System.ComponentModel;
using System.Drawing;
using System.Drawing.Drawing2D;
public partial class LoadingLabel : UserControl {
private int m_NumberOfDots = 5;
private Color m_DotColor = Color.Cyan;
private Color m_DotActiveColor = Color.Blue;
private float dotSize = 20.0f;
private float dotSpacing = 20.0f;
private int currentDot = 0;
private Timer dotsTimer = null;
public LoadingLabel()
{
InitializeComponent();
components = new Container();
dotsTimer = new Timer(components) { Interval = 200 };
dotsTimer.Tick += DotsTimer_Tick;
DoubleBuffered = true;
Padding = new Padding(5);
}
[DefaultValue(5)]
public int NumberOfDots {
get => m_NumberOfDots;
set {
value = Math.Max(3, Math.Min(value, 7));
if (m_NumberOfDots != value) {
m_NumberOfDots = value;
bool running = dotsTimer.Enabled;
Stop();
SetMinSize();
if (running) Start();
}
}
}
[DefaultValue(typeof(Color), "Cyan")]
public Color DotColor {
get => m_DotColor;
set {
m_DotColor = value;
Invalidate();
}
}
[DefaultValue(typeof(Color), "Blue")]
public Color DotActiveColor {
get => m_DotActiveColor;
set {
m_DotActiveColor = value;
Invalidate();
}
}
protected override void OnPaint(PaintEventArgs e) {
e.Graphics.SmoothingMode = SmoothingMode.AntiAlias;
for (int dot = 0; dot < m_NumberOfDots; dot++) {
var color = dot == currentDot ? DotActiveColor : DotColor;
var pos = Padding.Left + (dotSize + dotSpacing) * dot;
using (var brush = new SolidBrush(color)) {
e.Graphics.FillEllipse(brush, pos, Padding.Top, dotSize, dotSize);
}
}
base.OnPaint(e);
}
protected override void OnHandleCreated(EventArgs e) {
base.OnHandleCreated(e);
SetMinSize();
}
protected override void OnHandleDestroyed(EventArgs e) {
Stop();
base.OnHandleDestroyed(e);
}
private void DotsTimer_Tick(object sender, EventArgs e) {
currentDot += 1;
currentDot %= m_NumberOfDots;
Invalidate();
}
public void Start() => dotsTimer.Start();
public void Stop() {
dotsTimer.Stop();
currentDot = 0;
Invalidate();
}
private void SetMinSize() {
var width = Padding.Left + Padding.Right +
(dotSize * m_NumberOfDots) + (dotSpacing * (m_NumberOfDots - 1)) + 1;
var height = Padding.Top + Padding.Bottom + dotSize + 1;
MinimumSize = new Size((int)width, (int)height);
Size = MinimumSize;
}
}
This is how it works:
On demand, this is the PasteBin of the custom ComboBox Control used to select a Color.

A single call to the Paint method/event should draw the control as it is supposed to look at that instant. If you wish to add animation, you should make the control redraw itself repeatedly and use some internal state to keep track of the animation.

Related

C# Graphics class want to make signature panel : input from drawing tablet

i am trying to make signature panel in c# windowsform application where input is from drawing tablet
my code as below this code working for line drawing not dot created.
So please suggest how dot and line both are create.
{
Graphics graphics;
Boolean cusorMoving = false;
Pen cursorPen;
int cursorX = -1;
int cursorY = -1;
public SignPad()
{
InitializeComponent();
graphics = panel2.CreateGraphics();
cursorPen = new Pen(Color.Black, 2);
graphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias;
cursorPen.StartCap = System.Drawing.Drawing2D.LineCap.Round;
cursorPen.EndCap = System.Drawing.Drawing2D.LineCap.Round;
}
Mouse Down event
private void panel2_MouseDown(object sender, MouseEventArgs e)
{
cusorMoving = true;
cursorX = e.X;
cursorY = e.Y;
}
private void panel2_MouseUp(object sender, MouseEventArgs e)
{
cusorMoving = false;
cursorX = -1;
cursorY = -1;
}
Mouse Move event
private void panel2_MouseMove(object sender, MouseEventArgs e)
{
if (cursorX != -1 && cursorY != -1 && cusorMoving == true)
{
graphics.DrawLine(cursorPen, new Point(cursorX, cursorY), e.Location);
cursorX = e.X;
cursorY = e.Y;
}
}
You need to store individual points in a collection and draw them separately in the Paint handler. Every time you add a point to the collection, you also need to tell the panel to draw the area where the new segment was added. Something like this:
using System.Collections.Generic;
using System.Drawing;
namespace Lines
{
public partial class SignPad : Form
{
Pen cursorPen = SystemPens.ControlText;
List<Point> points = new List<Point>();
bool cursorMoving = false;
public SignPad()
{
InitializeComponent();
cursorPen = new Pen(Color.Black, 2);
cursorPen.StartCap = System.Drawing.Drawing2D.LineCap.Round;
cursorPen.EndCap = System.Drawing.Drawing2D.LineCap.Round;
}
private void panel2_Paint(object? sender, PaintEventArgs e)
{
var g = e.Graphics;
g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias;
for (int i = 1; i < points.Count; ++i)
g.DrawLine(cursorPen, points[i - 1], points[i]);
}
private void panel2_MouseDown(object? sender, MouseEventArgs e)
{
if (!cursorMoving)
{
cursorMoving = true;
points.Clear();
points.Add(e.Location);
panel2.Invalidate();
}
}
private void panel2_MouseMove(object? sender, MouseEventArgs e)
{
if (cursorMoving && points.Count > 0)
{
var p = e.Location;
var q = points[points.Count - 1];
var r = Rectangle.FromLTRB(Math.Min(p.X, q.X), Math.Min(p.Y, q.Y), Math.Max(p.X, q.X), Math.Max(p.Y, q.Y));
r = Rectangle.Inflate(r, (int)cursorPen.Width, (int)cursorPen.Width);
points.Add(p);
panel2.Invalidate(r);
}
}
private void panel2_MouseUp(object? sender, MouseEventArgs e)
{
cursorMoving = false;
}
}
}
Don't forget to add the Paint handler the same way you added MouseMove, MouseDown and MouseUp handlers - in the Designer.

How can I click on drawn points and make a external window opening?

I want to click on points that I drew.
It would be also cool if a window would popup and I could do something with that. But the general thing i want to do is clicking on a drawn point. I want to make it work, that i can click on the map on points that I drew.
Example image:
public partial class Form1 : Form
{
Graphics g;
Pen p;
Point cursor;
int k = 0;
Point[] points = new Point[50];
public Form1()
{
InitializeComponent();
g = pbxkarte.CreateGraphics();
p = new Pen(Color.DeepSkyBlue, 3);
}
private void Form1_Load(object sender, EventArgs e)
{
}
private void Pbxkarte_Click(object sender, EventArgs e)
{
if (drawmodecbx.Checked == true)
{
g.DrawEllipse(p, cursor.X - 10, cursor.Y - 10, 20, 20);
points[k++] = new Point(cursor.X, cursor.Y);
lbxDrawnPoints.Items.Add("X:" + cursor.X + "Y:" + cursor.Y);
}
}
private void Pbxkarte_MouseMove(object sender, MouseEventArgs e)
{
cursor = this.PointToClient(Cursor.Position);
xydisplay.Text = "X:" + cursor.X + "Y:" + cursor.Y;
}
}
}
Example code:
Two class level variables and a helper function:
List<Point> dots = new List<Point>();
int dotSize = 12;
Rectangle fromPoint(Point pt, int size)
{
return new Rectangle(pt.X - size/ 2, pt.Y - size / 2, size, size);
}
The mouseclick (as opposed to the click event) contains the location:
private void Pbxkarte_MouseClick(object sender, MouseEventArgs e)
{
if (!dots.Contains(e.Location))
{
dots.Add(e.Location);
Pbxkarte.Invalidate(); // show the dots
}
}
You could add code to remove dots or change the properties, esp. if you create a dot class. - If you want to avoid overlapping dots you can to use code like the one in the mousemove to detect this. But. Don't repeat the code! Instead factor out a boolOrPoint IsDotAt(Point) function you can use both times!!
In the mousemove I only show the hit state. You do your thing..
private void Pbxkarte_MouseMove(object sender, MouseEventArgs e)
{
bool hit = false;
foreach (var dot in dots)
{
using (GraphicsPath gp = new GraphicsPath())
{
gp.AddEllipse(fromPoint(dot, dotSize));
if (gp.IsVisible(e.Location))
{
hit = true; break;
}
}
}
Cursor = hit ? Cursors.Hand : Cursors.Default;
}
All dot in the list must get shown every time anything changes, both in the list or in the system.:
private void Pbxkarte_Paint(object sender, PaintEventArgs e)
{
foreach (var dot in dots)
{
using (GraphicsPath gp = new GraphicsPath())
{
gp.AddEllipse(fromPoint(dot, dotSize));
e.Graphics.FillPath(Brushes.Red, gp);
}
}
}
If you want more properties, like texts or colors do create a class dot and use a List<dot> !

Change ComboBox Border Color - Flash when SelectedIndex changed

I just wanted to know if in windows forms I can create a red line around the border of a combobox when its changed? Like just a flash of red and then gone again just to show that it was changed. Catch the user's eye or something. I will provide screens to represent what i would like.
If it is possible, please tell me where I can look it up to gain some information on it.
No border
Border flash on change
Border gone again after a second or two
Anytime the combobox changes, I want to flash a border to indicate it has changed.
The main idea is using a timer and drawing a border for some times. You can draw the border using different solutions. For example you can (1) draw the border on ComboBox or (2) you can draw border on Parent of ComboBox.
In the answer which I posed, I created a MyComboBox and added a FlashHotBorder method which can be called to flash border. Also I added a HotBorderColor property which can be used to set border color.
Flashing Border of ComboBox
To draw a border for ComboBox you can handle WM_Paint message of ComboBox and draw a border for control. Then to flash the border, you need to use a timer and turn on and turn off border for some times:
MyComboBox Code
I've created a FlashHotBorder method which you can call in SelectedIndexChanged event. Also if always you want to flash border when selected index changes, you can call it in OnSelectedIndexChanged. I prefer to call it in event handler. Here is the implementation:
using System.Drawing;
using System.Windows.Forms;
public class MyComboBox : ComboBox
{
int flash = 0;
private const int WM_PAINT = 0xF;
private int buttonWidth = SystemInformation.HorizontalScrollBarArrowWidth;
public Color HotBorderColor { get; set; }
private bool DrawBorder { get; set; }
Timer timer;
public MyComboBox()
{
this.HotBorderColor = Color.Red;
timer = new Timer() { Interval = 100 };
timer.Tick += new System.EventHandler(timer_Tick);
}
protected override void WndProc(ref Message m)
{
base.WndProc(ref m);
if (m.Msg == WM_PAINT && this.DrawBorder)
using (var g = Graphics.FromHwnd(this.Handle))
using (var p = new Pen(this.HotBorderColor))
g.DrawRectangle(p, 0, 0, this.Width - 1, this.Height - 1);
}
public void FlashHotBorder()
{
flash = 0;
timer.Start();
}
void timer_Tick(object sender, System.EventArgs e)
{
if (flash < 10)
{
flash++;
this.DrawBorder = !this.DrawBorder;
this.Invalidate();
}
else
{
timer.Stop();
flash = 0;
DrawBorder = false;
}
}
protected override void Dispose(bool disposing)
{
if (disposing) { timer.Dispose(); }
base.Dispose(disposing);
}
}
Then it's enough to use this event handler for SelectedIndexChanged event of eeach combo which you want to flash:
private void myComboBox1_SelectedIndexChanged(object sender, EventArgs e)
{
var combo = sender as FlatCombo;
if (combo != null)
combo.FlashHotBorder();
}
You can create an outline/draw a border outside a comboBox or any other control using the DrawRectangle method.
The border will be drawn outside the comboBox if the SelectedIndex range condition satisfies else it'll revert to it's original state with no outline.
bool changed = false;
private void Form1_Paint(object sender, PaintEventArgs e)
{
if (changed)
{
Pen p = new Pen(Color.Red);
Graphics g = e.Graphics;
int diff = 1;
g.DrawRectangle(p, new Rectangle(comboBox1.Location.X - diff, comboBox1.Location.Y - diff, comboBox1.Width + diff, comboBox1.Height + diff));
}
}
And, I am calling the Form1_Paint event on SelectedIndexChanged event of the comboBox.
private void comboBox1_SelectedIndexChanged(object sender, EventArgs e)
{
if (comboBox1.SelectedIndex >= 1 && comboBox1.SelectedIndex <= 9)
{
changed = true;
this.Refresh();
}
else
{
changed = false;
this.Refresh();
}
}
                    Outline                                         Without Outline
So I came up with this. It's the shortest and easiest way to do it I think. If you have any recommendation, feel free to post them or comment it. thanx for all the help :).
public partial class Form1 : Form
{
private int tick = 0;
public Form1()
{
InitializeComponent();
}
bool changed = false;
private void comboBox1_SelectedIndexChanged(object sender, EventArgs e)
{
if (changed == true)
{
changed = false;
this.Refresh();
}
else
{
if(tick<3)
{
timer1.Enabled = true;
timer1.Start();
}
changed = true;
this.Refresh();
}
}
private void Form1_Paint(object sender, PaintEventArgs e)
{
if (changed)
{
Graphics g1 = e.Graphics;
int diff = 1;
Rectangle rect2 = new Rectangle(comboBox1.Location.X - diff, comboBox1.Location.Y - diff, comboBox1.Width + diff, comboBox1.Height + diff);
using (LinearGradientBrush br = new LinearGradientBrush(rect2,Color.Red,Color.Blue,LinearGradientMode.Horizontal))
{
ColorBlend color_blend = new ColorBlend();
color_blend.Colors = new Color[] { Color.Red, Color.Orange, Color.Yellow, Color.Lime, Color.Blue, Color.Indigo, Color.DarkViolet};
color_blend.Positions = new float[] { 0 / 6f, 1 / 6f, 2 / 6f, 3 / 6f, 4 / 6f, 5 / 6f, 6 / 6f };
br.InterpolationColors = color_blend;
Pen p = new Pen(br, 10);
e.Graphics.DrawRectangle(p, rect2);
}
}
else
{
Pen p = new Pen(Color.Transparent);
Graphics g = e.Graphics;
int diff = 1;
g.DrawRectangle(p, new Rectangle(comboBox1.Location.X - diff, comboBox1.Location.Y - diff, comboBox1.Width + diff, comboBox1.Height + diff));
}
}
private void timer1_Tick(object sender, EventArgs e)
{
if(tick<3)
{
comboBox1_SelectedIndexChanged(null, null);
tick++;
}
else
{
timer1.Stop();
tick = 0;
}
}
}

How to move dynamically added graphics line in winforms

I am displaying two lines dynamically in form and want to move line vertically.
I tried to move using mousemove event but it's moving both lines together.
So is it possible to move dynamically added line individually on the form?
Here is my code
Graphics g;
int Y = 250;
public Form2()
{
InitializeComponent();
}
private void Form2_Load(object sender, EventArgs e)
{
}
private void Form2_Paint(object sender, PaintEventArgs e)
{
g = e.Graphics;
g.DrawLine(Pens.Red, new Point(0, Y), new Point(1500, Y));
g.DrawLine(Pens.LimeGreen, new Point(0, Y+50), new Point(1500, Y+50));
}
public void Form2_MouseMove(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Left)
{
Y = e.Location.Y;
Refresh();
}
}
Any input will be greatly appreciated.
You may use following code to solve your purpose.
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace TestWin
{
public partial class Form3 : Form
{
public Form3()
{
InitializeComponent();
this.DoubleBuffered = true;
this.Paint += new PaintEventHandler(LineMover_Paint);
this.MouseMove += new MouseEventHandler(LineMover_MouseMove);
this.MouseDown += new MouseEventHandler(LineMover_MouseDown);
this.MouseUp += new MouseEventHandler(LineMover_MouseUp);
this.Lines = new List<GraphLine>()
{
new GraphLine (10, 10, 100, 200),
new GraphLine (10, 150, 120, 40),
};
}
void LineMover_MouseUp(object sender, MouseEventArgs e)
{
if (Moving != null)
{
this.Capture = false;
Moving = null;
}
RefreshLineSelection(e.Location);
}
void LineMover_MouseDown(object sender, MouseEventArgs e)
{
RefreshLineSelection(e.Location);
if (this.SelectedLine != null && Moving == null)
{
this.Capture = true;
Moving = new MoveInfo
{
Line = this.SelectedLine,
StartLinePoint = SelectedLine.StartPoint,
EndLinePoint = SelectedLine.EndPoint,
StartMoveMousePoint = e.Location
};
}
RefreshLineSelection(e.Location);
}
void LineMover_Paint(object sender, PaintEventArgs e)
{
e.Graphics.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.High;
e.Graphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
foreach (var line in Lines)
{
var color = line == SelectedLine ? Color.Red : Color.Black;
var pen = new Pen(color, 2);
e.Graphics.DrawLine(pen, line.StartPoint, line.EndPoint);
}
}
void LineMover_MouseMove(object sender, MouseEventArgs e)
{
if (Moving != null)
{
Moving.Line.StartPoint = new PointF(Moving.StartLinePoint.X + e.X - Moving.StartMoveMousePoint.X, Moving.StartLinePoint.Y + e.Y - Moving.StartMoveMousePoint.Y);
Moving.Line.EndPoint = new PointF(Moving.EndLinePoint.X + e.X - Moving.StartMoveMousePoint.X, Moving.EndLinePoint.Y + e.Y - Moving.StartMoveMousePoint.Y);
}
RefreshLineSelection(e.Location);
}
private void RefreshLineSelection(Point point)
{
var selectedLine = FindLineByPoint(Lines, point);
if (selectedLine != this.SelectedLine)
{
this.SelectedLine = selectedLine;
this.Invalidate();
}
if (Moving != null)
this.Invalidate();
this.Cursor =
Moving != null ? Cursors.Hand :
SelectedLine != null ? Cursors.SizeAll :
Cursors.Default;
}
public List<GraphLine> Lines = new List<GraphLine>();
GraphLine SelectedLine = null;
MoveInfo Moving = null;
static GraphLine FindLineByPoint(List<GraphLine> lines, Point p)
{
var size = 10;
var buffer = new Bitmap(size * 2, size * 2);
foreach (var line in lines)
{
//draw each line on small region around current point p and check pixel in point p
using (var g = Graphics.FromImage(buffer))
{
g.Clear(Color.Black);
g.DrawLine(new Pen(Color.Green, 3), line.StartPoint.X - p.X + size, line.StartPoint.Y - p.Y + size, line.EndPoint.X - p.X + size, line.EndPoint.Y - p.Y + size);
}
if (buffer.GetPixel(size, size).ToArgb() != Color.Black.ToArgb())
return line;
}
return null;
}
public class MoveInfo
{
public GraphLine Line;
public PointF StartLinePoint;
public PointF EndLinePoint;
public Point StartMoveMousePoint;
}
public class GraphLine
{
public GraphLine(float x1, float y1, float x2, float y2)
{
this.StartPoint = new PointF(x1, y1);
this.EndPoint = new PointF(x2, y2);
}
public PointF StartPoint;
public PointF EndPoint;
}
}
}
Both of your lines take there position from the same variable Y (declared at the top of the source code) to do what you want you will need to firstly create a second variable to keep track of where the lines are individually.
Your second problem is going to be deciding which line you want to move perhaps alternating which line is moved based on which mouse button is down during Form2_MouseMove() .

How can i use a flag to draw or not to draw in the pictureBox paint event?

I have a flag in the Form1 top level: addFrame wich is set to false in the constructor.
Then in the picnt event i check if its false let me draw if its true also let me draw. The problem here is that i want to be able to draw when im running the program first time !
But when im moving the trackBar to the right i dont want it to draw anything .
private void pictureBox1_Paint(object sender, System.Windows.Forms.PaintEventArgs e)
{
Graphics g = e.Graphics;
g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias;
moveCounter++;
label6.Text = moveCounter.ToString();
if (addFrame == false)
{
WireObjectGraphics.Draw(wireObject1, g);
}
else
{
addFrame = false;
WireObjectGraphics.Draw(wireObject1, g);
}
}
This is the button click event where im clicking to set the addFrame to true:
private void button16_Click(object sender, EventArgs e)
{
wireObjectAnimation1.AddFrame();
addFrame = true;
trackBar1.Select();
}
And the scroll bar event in this case i want to make that if i move the trackBar to the right and there are no any draws already then just show the image in the pictureBox dont draw anything ! But if i move it to the right and there are already draws then do show them.
If i move it to the left allways show the previous draws.
private void trackBar1_Scroll(object sender, EventArgs e)
{
if (addFrame == false)
{
}
else
{
currentFrameIndex = trackBar1.Value - 1;
textBox1.Text = "Frame Number : " + trackBar1.Value;
wireObject1.woc.Set(wireObjectAnimation1.GetFrame(currentFrameIndex));
trackBar1.Minimum = 0;
trackBar1.Maximum = fi.Length - 1;
if (checkBox1.Checked)
{
setpicture(trackBar1.Value);
Graphics g = Graphics.FromImage(pictureBox1.Image);
g.Clear(SystemColors.Control);
pictureBox1.Invalidate();
}
else
{
setpicture(trackBar1.Value);
}
pictureBox1.Refresh();
button1.Enabled = false;
button2.Enabled = false;
button3.Enabled = false;
button4.Enabled = false;
button8.Enabled = false;
SaveFormPicutreBoxToBitMapIncludingDrawings(currentFrameIndex);
return;
}
}
This is the draw function in the WireObjectGraphics class:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing;
namespace AnimationEditor
{
class WireObjectGraphics
{
static Point connectionPointStart;
static Point connectionPointEnd;
static SolidBrush brush;
static Pen p = null;
public WireObjectGraphics()
{
}
public static void Draw(WireObject wo, Graphics graphics)
{
brush = new SolidBrush(Color.Red);
p = new Pen(brush);
Graphics g = graphics;
WireObject wireObject1 = wo;
if (wireObject1 != null)
{
for (int idx = 0; idx < wireObject1.woc.Point_X.Count; ++idx)
{
Point dPoint = new Point((int)wireObject1.woc.Point_X[idx], (int)wireObject1.woc.Point_Y[idx]);
dPoint.X = dPoint.X - 5; // was - 2
dPoint.Y = dPoint.Y - 5; // was - 2
Rectangle rect = new Rectangle(dPoint, new Size(10, 10));
g.FillEllipse(brush, rect);
// bitmapGraphics.FillEllipse(brush, rect);
// g.FillEllipse(brush, rect);
}
for (int i = 0; i < wireObject1._connectionstart.Count; i++)
{
int startIndex = wireObject1._connectionstart[i];
int endIndex = wireObject1._connectionend[i];
connectionPointStart = new Point((int)wireObject1.woc.Point_X[startIndex], (int)wireObject1.woc.Point_Y[startIndex]);
connectionPointEnd = new Point((int)wireObject1.woc.Point_X[endIndex], (int)wireObject1.woc.Point_Y[endIndex]);
p.Width = 2;
g.DrawLine(p, connectionPointStart, connectionPointEnd);
// bitmapGraphics.DrawLine(p, connectionPointStart, connectionPointEnd);
}
}
}
}
}
What i need is that first time running the program to be able to draw !
Then when moving the trackBar to the righ to check if draws already exists show them if not exist show only the image and only when i click the button it will add the draws on the frame im on.
If i move to the left allways show the draws i did in the other frames.
WireObject class:
Constructor:
class WireObject
{
private string an;
private bool fnExt;
public string lockObject;
private int idx;
public WireObjectCoordinates woc;
private List<int> connectionStart = new List<int>();
private List<int> connectionEnd = new List<int>();
private const string version = "01.00";
string wo_name;
public WireObject( string name )
{
wo_name = name;
woc = new WireObjectCoordinates();
fnExt = false;
}
In the wireobject class i have some function like connecting points(pixels) like delete pixels like save and load...
WireObjectCoordinates class is:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace AnimationEditor
{
class WireObjectCoordinates
{
public List<float> Point_X = new List<float>();
public List<float> Point_Y = new List<float>();
public WireObjectCoordinates()
{
}
public WireObjectCoordinates(WireObjectCoordinates w)
{
Point_X.AddRange(w.Point_X);
Point_Y.AddRange(w.Point_Y);
}
public void Set(WireObjectCoordinates w)
{
if (w == null)
{
}
else
{
for (int i = 0; i < Point_X.Count; i++)
{
Point_X[i] = w.Point_X[i];
Point_Y[i] = w.Point_Y[i];
}
}
}
}
}
The problem is still in Form1 with the flag when to show the pixels i mean when and how to call the paint event like pictureBox1.Refresh(); but oncei t will use the Draw function inside and once it will not. When i run the program let me use the draw function once i moved the trackBar to the right dont use the draw function.
For a windows form control OnPaint is only called when a.) a window overlapping the current control is moved out of the way OR b.) you manually invalidate the control : http://msdn.microsoft.com/en-us/library/1e430ef4.aspx
So OnPaint should be getting called too often.

Categories

Resources