Paint on panel allowing auto scroll - c#

I'm implementing an application which want to draw lines in the panel. But the panel must be auto scrolled as it size can be expand at run time. The panel paint method I have used is as below.When I run the program it draws lines, but when I scroll down the panel the lines get crashes.How can I avoid that?
private void panel1_Paint(object sender, PaintEventArgs e)
{
this.DoubleBuffered = true;
Pen P = new Pen(Color.Red);
for (int i = 0; i < 10; i++) {
e.Graphics.DrawLine(P, (new Point(i * 40, 0)), (new Point(i * 40, 60 * 40)));
}
for (int i = 0; i < 60; i++)
{
e.Graphics.DrawLine(P, (new Point(0, i *40)), (new Point(10 * 40, i * 40)));
}
}

I'll assume that "get crashes" doesn't actually mean that your code crashes. You'll need to offset the drawing by the scroll amount. That's easy to do:
private void panel1_Paint(object sender, PaintEventArgs e) {
e.Graphics.TranslateTransform(panel1.AutoScrollPosition.X, panel1.AutoScrollPosition.Y);
// etc
//...
}

Related

How to operate on drawn graphics

I created two Rectangles. I want to add events on them. For example when mouse hover on one, the hovered one will change color, can do resize or drag them(rectangles) to other place...
I was just wondering if I could control the drawn graphic, or it will like Microsoft Paint that after you painted, the object can not be operate unless you clear canvas and do redraw.
Is it possible to control a drawn graphic, thanks for any suggestion.
Simple code of my drawn graphics
private void Form1_Paint(object sender, PaintEventArgs e)
{
// Create pen.
Pen blackPen = new Pen(Color.Black, 3);
// Create rectangle.
Rectangle rect1 = new Rectangle(20, 20, 250, 250);
Rectangle rect2 = new Rectangle(70, 70, 150, 150);
// Draw rectangle to screen.
e.Graphics.FillRectangle(Brushes.DeepSkyBlue, rect1);
e.Graphics.FillRectangle(Brushes.LightBlue, rect2);
}
Also, you can create your own control like:
class RectangleControl : Control
{
public void FillRectangle(Color color)
{
this.BackColor = color;
}
}
Then :
private void Form1_Paint(object sender, PaintEventArgs e)
{
RectangleControl rect1 = new RectangleControl() { Parent = this, Left = 20, Top = 20, Width = 250, Height = 250 };
rect1.FillRectangle(Color.DeepSkyBlue);
RectangleControl rect2 = new RectangleControl() { Parent = rect1, Left = 50, Top = 50, Width = 150, Height = 150 };
rect2.FillRectangle(Color.LightBlue);
rect1.MouseHover += Rect1_MouseHover;
rect2.MouseLeave += Rect2_MouseLeave;
}
private void Rect2_MouseLeave(object sender, EventArgs e)
{
(sender as RectangleControl).BackColor = Color.Yellow;
}
private void Rect1_MouseHover(object sender, EventArgs e)
{
(sender as RectangleControl).BackColor = Color.LightBlue;
}
You can use Panel control instead.
Just add 2 panel controls as you would like them to be arranged and add 2 event handlers:
private void panel1_MouseHover(object sender, EventArgs e)
{
panel1.BackColor = Color.Yellow;
}
private void panel1_MouseLeave(object sender, EventArgs e)
{
panel1.BackColor = Color.LightBlue;
}
You can monitor the MouseMove.
Here's code using MouseMove and some brush values used by the rectangles.
using System.Drawing;
using System.Windows.Forms;
namespace Question_Answer_WinForms_App
{
public partial class Form1 : Form
{
public Brush outerRectangleBrush = Brushes.DeepSkyBlue;
public Brush innerRectangleBrush = Brushes.LightBlue;
public Form1()
{
InitializeComponent();
Paint += Form1_Paint;
MouseMove += Form1_MouseMove;
}
private void Form1_MouseMove(object sender, MouseEventArgs e)
{
var isWithinOuterRectangle = e.Location.X >= 20
&& e.Location.X <= 250 + 20
&& e.Location.Y >= 20
&& e.Location.Y <= 250 + 20;
var isWithinInnerRectangle = e.Location.X >= 70
&& e.Location.X <= 150 + 70
&& e.Location.Y >= 70
&& e.Location.Y <= 150 + 70;
if (isWithinOuterRectangle)
{
if (isWithinInnerRectangle)
{
outerRectangleBrush = Brushes.DeepSkyBlue;
innerRectangleBrush = Brushes.Red;
Refresh();
}
else
{
outerRectangleBrush = Brushes.Red;
innerRectangleBrush = Brushes.LightBlue;
Refresh();
}
}
else
{
outerRectangleBrush = Brushes.DeepSkyBlue;
innerRectangleBrush = Brushes.LightBlue;
Refresh();
}
}
private void Form1_Paint(object sender, PaintEventArgs e)
{
// Create pen.
Pen blackPen = new Pen(Color.Black, 3);
// Create rectangle.
Rectangle rect1 = new Rectangle(20, 20, 250, 250);
Rectangle rect2 = new Rectangle(70, 70, 150, 150);
// Draw rectangle to screen.
e.Graphics.FillRectangle(outerRectangleBrush, rect1);
e.Graphics.FillRectangle(innerRectangleBrush, rect2);
}
}
}
#FJF, writing a ms-paint like application is not a complicated task. Windows Forms applications are using GDI+ to render graphics. so you can write a simple paint application using WindowsForms.
#nexolini uses a panel to do some draws. actually Ms-Paint does the same somehow. Ms-Paint is a Single-Layer Editor. So you can't resize all objects anytime you wanted (but as I said before you can assume that you have a panel for each newly drawn Shapes; Something like what Ms-Paint does).
So what is the problem?
Ms-Paint doesn't tracks your mouse movements and it doesn't needed (as it's a single layer). You can do all of it's tasks using these Answers.
e.g: for adding a Fill Color tool you can use a getpixel and putpixel to do a recursive algorithm on you image. and you are not needed to know which shape you are working on.
all the other tasks could be implemented easy.
for multi-layer Editors I will prefer to use a more powerful framework (but it's also could be implemented in Windows forms in a bad way), Like WPF. WPF uses DirectX to render your graphics and you are able to write an smooth Editor. WPF is designed to handle your graphical request so it does better on graphics.
#Reza_Aghaei 's comments are useful for Windows Forms.

C# - How to Draw a rectangle with pre-determined size after button click + retangle follow move movements + get coords

Sorry for my eng. Im quite new to C#, and i need this:
After clicking a button, a rectangle form with pre-determined size will appear;
This rectangle must move all around the form + move on screen even if the form is minimized;
The retangle must follow the mouse movements;
When i make a mouse click on the place of screen i want, i need that all coordinates of the area of the rectangle are stored in variables.
This coordinates of rectangle will later be checked by a read-pixel code that i already have, so i really need that the rectangle area of where i clicked really be stored in variables.
EDIT:
Im really new to c# and what i have done so far is:
private void button5_Click(object sender, EventArgs e)
{
Graphics dc = this.CreateGraphics();
Pen Bluepen = new Pen(Color.Blue, 3);
dc.DrawRectangle(Bluepen, 0, 0, 50, 50);
}
And:
private void button5_MouseMove(object sender, MouseEventArgs e)
{
if (isMouseDown == true)
{
rect.Location = e.Location;
if (rect.Right > pictureBox1.Width)
{
rect.X = pictureBox1.Width - rect.Width;
}
if (rect.Top < 0)
{
rect.Y = 0;
}
if (rect.Left < 0 )
{
rect.X = 0;
}
if (rect.Bottom > pictureBox1.Height)
{
rect.Y = pictureBox1.Height - rect.Height;
}
Refresh();
}
}
Thanks in advance!!

Partially fill a Rectangle object

I was wondering if it's possible to fill a certain percentage of a Rectangle object that's been draw on-screen so that it behaves like a Progress Bar, where you can watch its "level" go up and down. Specifically, I'd like to fill it from top to bottom rather than left to right.
You can try this.
private void button1_Click(object sender, EventArgs e)
{
panel1.Width = 400;
panel1.Height = 50;
using (Graphics g = this.panel1.CreateGraphics())
{
g.Clear(Color.Black);
Pen pen = new Pen(Color.Red, 2);
for (int i = 0; i <= 50;i++ )
{
g.DrawRectangle(pen, 0, 0, 400, i);
Thread.Sleep(100);
}
pen.Dispose();
}
}

Append a Rectangle to the old Rectangles

Hye there I am new to C# and learning it to my own. My problem is that I want to append a new rectangle to the old rectangles and move them all using a timer my code is:
Rectangle[] rec;
int rec_part = 4;
int rec_x = 0;
Color c = Color.FromArgb(255, 255, 255);
public Form1()
{
InitializeComponent();
rec = new Rectangle[rec_part];
for (int i = 0; i < rec_part; i++)
{
rec_x += 43;
rec[i] = new Rectangle(rec_x, 100, 40,40);
}
}
it will initialize 4 Rectangles, then:
Graphics g;
private void Form1_Paint(object sender, PaintEventArgs e)
{
g = e.Graphics;
g.SmoothingMode = SmoothingMode.AntiAlias;
for (int i = 0; i < rec_part; i++)
g.FillRectangle(new SolidBrush(Color.Red), rec[i]);
}
This will draw 4 Rectangle Controls on the Form, then:
int speed = 2;
private void timer1_Tick(object sender, EventArgs e)
{
for (int i = 0; i < rec.Length; i++)
{
rec[i].X += speed;
rec_part += 1; \\Here I want to append a new Rectangle to the existing rectangles
\\ the array size is to increment so that that a new rectangle will append
}
Refresh();
}
But the problem is that an "index out of range" exception has been thrown within my code but if I use my timer as:
int speed = 2;
private void timer1_Tick(object sender, EventArgs e)
{
for (int i = 0; i < rec.Length; i++)
{
rec[i].X += speed;
if (rec_part == rec.Length)
rec_part = 0;
else
rec_part += 1;
}
Refresh();
}
All works fine with this code, but it starts blinking so much so that one can unable to watch it perfectly, and every time it draws new rectangles in number of 4 whereas I want to append a new rectangle!
Sorry for my English. Can somebody help me out sorting thing problem? Thanks.
I advise you adding the rectangles to a list instead of an array.
I also advice you not to use winforms for drawing rectangles WPF is way faster in drawing lots of stuff it's a bit more complicated but it's faster.
reply if you need any code samples and i'll update my answer
This is my code:
rectangles2[i] = rectangleupdated(rectangles2[i]);
Rectangles2 is a list of rectangles, rectangleupdated has as parameters an rectangles then it modifys the rectangles like this:
Rectangle rectangleupdated(Rectangle rect){
return rect.Y--;
}
This is my result after collision checking and everything(It's a powdergame)

Change color of panel when mouse clicked?

I am very new to visual C#
I want to make a ticket booking system (like in cinemas), I have created the seats using panel, each seating is 40 * 40
Here's my code:
private void panel2_Paint(object sender, PaintEventArgs e)
{
int a, b;
for (a = 0; a <= 1; a++)
{
for (b = 0; b < 12; b++)
{
Graphics g = e.Graphics;
g.FillRectangle(new SolidBrush(Color.White), b * 40, a * 40, 40, 40);
g.DrawRectangle(new Pen(Color.Black), b * 40, a * 40, 40, 40);
}
}
}
Now I want to change the color of each seating by a mouse click to show what seat has been selected; but so far no luck
You would be better off creating seperate controls for each of your selected seats and handling their Click events. In this example I added 24 PictureBox's to the Panel. I then placed their index in the Tag Property of the Control and attached a common Click Event Handler. I am also using a Bool array to keep track of selected status.
public partial class Form1 : Form
{
bool[] selected = new bool[24];
public Form1()
{
InitializeComponent();
foreach (PictureBox pb in panel1.Controls)
{
pb.Click += new EventHandler(pictureBox_Click);
}
}
private void pictureBox_Click(object sender, EventArgs e)
{
PictureBox pb = (PictureBox)sender;
int index ;
if (int.TryParse(pb.Tag.ToString(), out index))
{
if (selected[index])
{
selected[index] = false;
pb.BackColor = Color.White;
}
else
{
selected[index] = true;
pb.BackColor = Color.Red;
}
}
}
}
You can use what you have if you create a boolean array to store the state of the Seat, use the Panel's MouseDown Event to set the variable and Invalidate the screeen rectangle that is accociated with your seat.
Something like this.
public partial class Form1 : Form
{
bool[,] selected = new bool[2,12];
public Form1()
{
InitializeComponent();
}
private void panel1_Paint(object sender, PaintEventArgs e)
{
int a, b;
for (a = 0; a <= 1; a++)
{
for (b = 0; b < 12; b++)
{
if (selected[a, b])
{
e.Graphics.FillRectangle(new SolidBrush(Color.Red), b * 40, a * 40, 40, 40);
}
else
{
e.Graphics.FillRectangle(new SolidBrush(Color.White ), b * 40, a * 40, 40, 40);
}
e.Graphics.DrawRectangle(new Pen(Color.Black), b * 40, a * 40, 40, 40);
}
}
}
private void panel1_MouseDown(object sender, MouseEventArgs e)
{
int xPos, yPos;
xPos = e.X / 40;
yPos = e.Y / 40;
if ((xPos > 11) || (yPos > 1)) return;
if(selected[yPos,xPos])
selected[yPos, xPos] = false;
else
selected[yPos, xPos] = true;
((Panel)sender).Invalidate(new Rectangle(xPos * 40,yPos *40,40,40)) ;
}
}
Rather than using a Graphics object and drawing directly to the form, you may be able to get away with simply setting the BackColor property of the control that corresponds to the selected seat when the OnMouseClick event fires.

Categories

Resources