How to draw using trackbar? - c#

well how do you draw in C# using variables?
ive managed to draw some shapes but only when i hardcode in the lengths. i need to draw shapes using a trackbar to get the lengths.
public abstract class Shape
{
//private String shape;
private int length;
}
public virtual void setLength(int newLength)
{
this.length = newLength;
}
public virtual int getLength()
{
return length;
}
//public String getShape()
//{
// return shape;
//}
//abstract public double getLength(float length);
abstract public float getPerimeter(int length);
abstract public float getArea(int length);
only showing square class but this project also includes triangle and square.
using System;
using System.Drawing;
public class Square : Shape
{
private float perimeter, area;
public override float getPerimeter(int length)
{
perimeter = length*4;
return perimeter;
}
public override float getArea(int length)
{
area = length*length;
return area;
}
}
this is the class with all my event handlers
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
namespace shapes
{
//private System.Windows.Forms.TrackBar trackBar1;
public partial class Form1 : Form
{
private Shape shape;
private int length = 0;
private int shapeL = 0;
public Form1()
{
InitializeComponent();
}
private void panel2_Paint(object sender, PaintEventArgs e)
{
}
private void menuStrip1_ItemClicked(object sender, ToolStripItemClickedEventArgs e)
{
}
private void trackBar1_Scroll(object sender, EventArgs e)
{
label3.Text = "Length Slider: " + trackBar1.Value;
textBox1.Text = shape.getPerimeter(shape.getLength()).ToString("0.00");
textBox2.Text = shape.getArea(shape.getLength()).ToString("0.00");
textBox1.Refresh();
textBox2.Refresh();
length = trackBar1.Value;
shape.setLength(length);
}
private void onCircleClick(object sender, EventArgs e)
{
shape = new Circle();
//length = trackBar1.Value;
length = shape.getLength();
this.Refresh();
using (Graphics g = this.panel1.CreateGraphics())
{
Pen pen = new Pen(Color.Black, 2);
Graphics formGraphics;
formGraphics = this.panel1.CreateGraphics();
formGraphics.DrawEllipse(pen, 50, 50, length, length);
//g.DrawEllipse(pen, 100, 100, length, length);
}
}
private void onSquareClick(object sender, EventArgs e)
{
shape = new Square();
length = trackBar1.Value;
using (Graphics g = this.panel1.CreateGraphics())
{
Pen pen = new Pen(Color.Black, 2);
g.DrawRectangle(pen, 50, 50, length, length);
System.Windows.Forms.MessageBox.Show("lenght is: " + length);
}
}
private void onTriangleClick(object sender, EventArgs e)
{
shape = new Triangle();
length = trackBar1.Value;
using (Graphics g = this.panel1.CreateGraphics())
{
SolidBrush blueBrush = new SolidBrush(Color.Blue);
// Create points that define polygon.
Point point1 = new Point(50, 50);
Point point2 = new Point(50, 100);
Point point3 = new Point(100, 50);
Point[] curvePoints = { point1, point2, point3};
// Draw polygon to screen.
g.FillPolygon(blueBrush, curvePoints);
}
}
private void shapeToolStripMenuItem_Click(object sender, EventArgs e)
{
}
protected override void OnPaint(PaintEventArgs pe)
{
base.OnPaint(pe);
Pen pen = new Pen(Color.Black, 2);
Graphics g = pe.Graphics;
g = this.CreateGraphics();
g.DrawRectangle(pen, 50, 50, length, length);
}
private void OnPaint(object sender, PaintEventArgs e)
{
}
}
}
yes its very messy, as you can see ive tried various things.
whats the difference between the panel1_paint and onPaint?
as you can see im not too sure how to use eventhandlers, the onCircleClick is basically a menu item button but how do i activate a different eveenthandler(panel1_Paint) from another eventhandler(onCircleClick)?
do graphics need to drawn in a *_paint/OnPaint method? ive gotten mine to draw in just the normal panel.
next is whats the best course of action to get the trackbar value to the shape object and back again to the method? yes the data is being saved (i think) when i use displayMessage(shape.getLength) it displays the length and is usually one off.
whats the equilent to repaint() in java for c#? ive tried this.Refresh(); but it doesnt work itll draw the shape then makes it disappear.
am i writing my setters/getters properly? or should i use
public int X
{
get {return x;}
set {x = value;}
}
in java, graphics will draw on any panel, in c# does it need to be in a specific container?

this is very simple, lets say that you want to draw on panel2.
all you have to do is to write this inside your private void panel2_Paint(object sender, PaintEventArgs e) body.
{
e.Graphics.Clear(panel1.BackgroundColor);
int length = trackBar1.Value;
Pen pen = new Pen(Color.Black, 2);
e.Graphics.DrawRectangle(pen, 50, 50, length, length);
}
and whenever you want to refresh the drawing, you can call either panel2.Refresh() or panel2.Invalidate(). both would do the job.
note that if you did this, panel2 won't get cleared after drawing the shape as it happened with you before.
note also that the panel would flicker as you change the trackbar value. i know how to handle this, but i don't want to complicate the solution for now.

Related

Drag Over PictureBox over other PictureBox with transparency

I would like to design a chess board and drag over pieces (shown in pictureBox Controls) all child of the main board (pictureBox1).
Problem I encounter is the transparency is only set to the Parent pictureBox1.
Which shows this effect: The square is showing.
private void CommonPiece_Mouse_Move(object sender, MouseEventArgs e)
{
if (Piece_Selected)
{
int MousePositionX = pictureBox1.PointToClient(Cursor.Position).X;
int MousePositionY = pictureBox1.PointToClient(Cursor.Position).Y;
(sender as PictureBox).Left = MousePositionX - 35;
(sender as PictureBox).Top = MousePositionY - 25;
}
}
What would be a good way to go about it?
There are several solutions for this problem. The one in the following screen recording, is based on drawing png images as movable shapes; it uses the idea that I've explained in How to drag and move shapes in C#. Basically there's only one control -the drawing surface, and all the other stuff are movable drawings.
You can use any image for the pieces by passing an Image to the ImageShape
You can modify the size of the Pieces by setting Height of the shape
It supports snapping to the grid
You can customize the texture, easily by setting the BackgroundImage of the drawing surface
You can change the grid size, by setting GridSize property of the drawing surface
You can change the Color of White and Grid grids, by assigning the color to WhiteColor and BlackColor
It's of course a quick example showing how to draw movable objects, including png images keeping their transparency. You know how to improve it :)
Drawing and moving shapes - Chess pieces
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Text;
using System.Linq;
using System.Windows.Forms;
public interface IShape
{
bool HitTest(Point p);
void Draw(Graphics g);
void Move(int dx, int dy);
Point Location { get; set; }
}
public class ImageShape : IShape
{
public int Height { get; set; } = 100;
public Point Location { get; set; }
private Image _image;
public ImageShape(Image image)
{
_image = image;
}
public void Draw(Graphics g)
{
var r = new Rectangle(Location, new Size(Height, Height));
r.Inflate(-5, -5);
g.DrawImage(_image, r);
}
public bool HitTest(Point p)
{
return new Rectangle(Location, new Size(Height, Height)).Contains(p);
}
public void Move(int dx, int dy)
{
Location = new Point(Location.X + dx, Location.Y + dy);
}
}
public class DrawingSurface : Control
{
public List<IShape> Shapes { get; private set; }
public int GridSize { get; set; } = 100;
public Color WhiteColor = Color.FromArgb(200, Color.White);
public Color BlackColor = Color.FromArgb(120, Color.Black);
IShape selectedShape;
bool moving;
Point previousPoint = Point.Empty;
public DrawingSurface()
{
DoubleBuffered = true;
ResizeRedraw = true;
Shapes = new List<IShape>();
}
protected override void OnMouseDown(MouseEventArgs e)
{
for (var i = Shapes.Count - 1; i >= 0; i--)
if (Shapes[i].HitTest(e.Location))
{
selectedShape = Shapes[i];
break;
}
if (selectedShape != null)
{
moving = true;
previousPoint = e.Location;
Invalidate();
}
base.OnMouseDown(e);
}
protected override void OnMouseMove(MouseEventArgs e)
{
if (moving)
{
var dx = e.X - previousPoint.X;
var dy = e.Y - previousPoint.Y;
selectedShape.Move(dx, dy);
previousPoint = e.Location;
this.Invalidate();
}
base.OnMouseMove(e);
}
protected override void OnMouseUp(MouseEventArgs e)
{
if (moving)
{
int i = (e.X / GridSize) * GridSize;
int j = (e.Y / GridSize) * GridSize;
selectedShape.Location = new Point(i, j);
selectedShape = null;
moving = false;
this.Invalidate();
}
base.OnMouseUp(e);
}
protected override void OnPaint(PaintEventArgs e)
{
var g = e.Graphics;
g.InterpolationMode = InterpolationMode.High;
g.SmoothingMode = SmoothingMode.HighQuality;
g.TextRenderingHint = TextRenderingHint.AntiAliasGridFit;
g.CompositingQuality = CompositingQuality.HighQuality;
foreach (var shape in Shapes.Except(new[] { selectedShape }))
shape.Draw(g);
if (selectedShape != null)
selectedShape.Draw(g);
}
protected override void OnPaintBackground(PaintEventArgs e)
{
base.OnPaintBackground(e);
var g = e.Graphics;
using (var w = new SolidBrush(WhiteColor))
using (var b = new SolidBrush(BlackColor))
for (int i = 0; i < 8; i++)
for (int j = 0; j < 8; j++)
g.FillRectangle((i + j) % 2 == 0 ? b : w,
i * GridSize, j * GridSize, GridSize, GridSize);
}
}
To add pieces:
private void Form1_Load(object sender, EventArgs e)
{
this.drawingSurface1.Shapes.Add(new ImageShape(
Properties.Resources.KingWhite) { Location = new Point(0, 0) });
this.drawingSurface1.Shapes.Add(
new ImageShape(Properties.Resources.kingBlack) { Location = new Point(0, 100) });
}
Here's an example that makes the PictureBox Non-Rectangular. The PB will literally not exist where the transparent areas were:
using System.Runtime.InteropServices;
namespace CS_Scratch_WindowsFormsApp2
{
public partial class Form1 : Form
{
public const int HT_CAPTION = 0x2;
public const int WM_NCLBUTTONDOWN = 0xA1;
[System.Runtime.InteropServices.DllImportAttribute("user32.dll")]
public static extern bool ReleaseCapture();
[System.Runtime.InteropServices.DllImportAttribute("user32.dll")]
public static extern int SendMessage(IntPtr hWnd, int Msg, int wParam, int lParam);
public Form1()
{
InitializeComponent();
pbChessPiece.MouseMove += PbChessPiece_MouseMove;
}
private void PbChessPiece_MouseMove(object sender, MouseEventArgs e)
{
PictureBox pb = (PictureBox)sender;
if (!DesignMode && e.Button == MouseButtons.Left)
{
ReleaseCapture();
SendMessage(pb.Handle, WM_NCLBUTTONDOWN, HT_CAPTION, 0);
}
}
private void button1_Click(object sender, EventArgs e)
{
Bitmap bmp = (Bitmap)pbChessPiece.Image;
Region rgn = new Region();
rgn.Union(new Rectangle(0, 0, bmp.Width, bmp.Height));
for(int x=0; x<bmp.Width; x++)
{
for(int y=0; y<bmp.Height; y++)
{
if (bmp.GetPixel(x, y).A == 0)
{
rgn.Exclude(new Rectangle(x, y, 1, 1));
}
}
}
pbChessPiece.Region = rgn;
}
}
}
Example run:
I did something similar, but I did not use Drag & Drop events
On MouseDown I assumed a drag operation started, I've opened a translucent unfocused window on top of the drop area, and started drawing dragged image on that form. Since the form is translucent it can show images with transparency on top of everything. I did not use images, but instead draw rectangles where users could drop. If my memory serves me correct, MouseMove events are forwarded to the dragged component, the original chess piece in your case, or the opened but unfocused form, so I can easily track the location. On MouseUp event I wrapped everything.
Since you can draw the image on the new form you can tilt image chess piece image to the left or right for a nice touch.
I developed a very strict forms designer application using this technique.
You can use the panel instead of using the pictureBox and display the image in the background of the controls. Remember that your images must be "png" and the surrounding of the image must be completely transparent. Also, the background color of the controls of the panels Set by events so that it becomes transparent during drag and returns to the cell color after drag and drop.
Good luck.

C# draw in panel and shift left the drawn objects

I'm drawing rectangles in a panel starting from the left side.
When I reach the right side of the panel I'd like to shift left the rectangles previously drawn to have the space to draw another one, and so on.
Which is the simplest way to do it?
I'm drawing using System.Drawings.Graphics.
I'm using Winforms. The code is:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Runtime.InteropServices;
namespace FFViewer
{
public partial class Form1 : Form
{
[DllImport("shlwapi.dll")]
public static extern int ColorHLSToRGB(int H, int L, int S);
int x=0;
int y=300;
int h = 0;
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
panel_Paint();
x = x + 40;
h = h + 40;
if (h >= 240)
h = 0;
}
private void panel_Paint()
{
int val;
Color color;
val = ColorHLSToRGB(h, 128, 240);
Graphics g = panel1.CreateGraphics();
color = ColorTranslator.FromWin32(val);
SolidBrush sb = new SolidBrush( color );
g.FillRectangle(sb, x, y, 40, 100);
}
}
}
So, when I draw the latest rectangle on the right side, I'd like to shift left all the rectangles to leave the space to draw another one on the right side.
P.S. I don't have enough reputation to post images :(
Here's the "old school" way of doing it. This is basically what was done when a continuous graph of a real-time value needed to be displayed AND you didn't want to store the any of the values anywhere. This has severe limitations as it copies from the screen and the drawing will be erased the when window repaints itself. This first example is simply here to demonstrate the process, and is an extension of the way you created the initial blocks:
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
[DllImport("shlwapi.dll")]
public static extern int ColorHLSToRGB(int H, int L, int S);
int x = 0;
int width = 40;
int y = 300;
int height = 100;
int h = 0;
private void button1_Click(object sender, EventArgs e)
{
if (x + width > panel1.ClientSize.Width) // if drawing the next block would exceed the panel width...
{
// capture what's currently on the screen
Bitmap bmp = new Bitmap(x, height);
using (Graphics g = Graphics.FromImage(bmp))
{
g.CopyFromScreen(panel1.PointToScreen(new Point(0, y)), new Point(0, 0), bmp.Size);
}
// draw it shifted to the left
using (Graphics g = panel1.CreateGraphics())
{
g.DrawImage(bmp, new Point(-width, y));
}
// move x back so the new rectangle will draw where the last one was previously
x = x - width;
}
// draw the new block and increment values
panel_Paint();
x = x + width;
h = h + width;
if (h >= 240)
{
h = 0;
}
}
private void panel_Paint()
{
int val;
Color color;
val = ColorHLSToRGB(h, 128, 240);
color = ColorTranslator.FromWin32(val);
using (Graphics g = panel1.CreateGraphics())
{
using (SolidBrush sb = new SolidBrush(color))
{
g.FillRectangle(sb, x, y, width, height);
}
}
}
}
This could be fixed by creating a Bitmap of the correct size and drawing to that instead. Then you shift everything and draw the new block on the right side. Finally, you'd draw that Bitmap in the Paint() event. So this is doing the same thing as above except we aren't copying from the screen, and the panel will properly redraw itself when requested:
public partial class Form1 : Form
{
[DllImport("shlwapi.dll")]
public static extern int ColorHLSToRGB(int H, int L, int S);
int x = 0;
int width = 40;
int y = 300;
int height = 100;
int h = 0;
Bitmap bmp;
public Form1()
{
InitializeComponent();
this.Load += Form1_Load;
panel1.Paint += Panel1_Paint;
}
private void Form1_Load(object sender, EventArgs e)
{
int numBlocks = (int)(panel1.Width / width);
bmp = new Bitmap(numBlocks * width, height);
using (Graphics g = Graphics.FromImage(bmp))
{
g.Clear(panel1.BackColor);
}
}
private void Panel1_Paint(object sender, PaintEventArgs e)
{
if (bmp != null)
{
e.Graphics.DrawImage(bmp, new Point(0, y));
}
}
private void button1_Click(object sender, EventArgs e)
{
using (Graphics g = Graphics.FromImage(bmp))
{
if (x + width > bmp.Width) // if drawing the next block would exceed the bmp width...
{
g.DrawImage(bmp, new Point(-width, 0)); // draw ourself shifted to the left
x = x - width;
}
// draw the new block
int val;
Color color;
val = ColorHLSToRGB(h, 128, 240);
color = ColorTranslator.FromWin32(val);
using (SolidBrush sb = new SolidBrush(color))
{
g.FillRectangle(sb, x, 0, width, height);
}
}
x = x + width;
h = h + width;
if (h >= 240)
{
h = 0;
}
panel1.Invalidate(); // force panel1 to redraw itself
}
}
You should not use panel1.CreateGraphics(), but instead handle the Paint event of the panel, otherwise the rectangles might disappear, for instance after a popup appears in front of your form:
panel1.Paint += new PaintEventHandler(panel1_paint);
You'll need to paint all (visible) rectangles in the paint handler; you could keep a List<Rectangle> in your form to store the rectangles you have added:
private List<Rectangle> rectangles = new List<Rectangle>();
...
private void button1_Click(object sender, EventArgs e)
{
rectangles.Add(new Rectangle(x, y, width, height));
panel1.Invalidate(); // cause the paint event to be called
// todo increment x/y
}
Then, in the panel1_Paint handler you can simply draw the rectangles, after having called Graphics.TranslateTransform() to shift the whole drawing area:
private void panel1_Paint(object sender, PaintEventArgs e)
{
e.Graphics.TranslateTransform(-x, 0);
foreach (Rectangle rectangle in rectangles)
{
// paint em
}
e.Graphics.ResetTransform();
}

Control not drawn on panel

I'm trying to add a control to my Panel. At mouseDown on the panel the point is saved and at mouseUp the point is saved. But at panel mouseUp nothing is drawn. How to solve it?
Ellipse class:
class Ellipse : Control
{
private int x;
private int y;
private int width;
private int height;
public Ellipse(int x, int y, int width, int height)
{
setY(y);
setX(x);
setWidth(width);
setHeight(height);
}
public int getX() { return x;}
public int getY() { return y; }
public int getWidth() { return width; }
public int getHeight() { return height; }
public void setX(int newx) { x = newx; }
public void setY(int newy) { y = newy; }
public void setWidth(int newwidth) { width = newwidth; }
public void setHeight(int newheight) { height = newheight; }
protected override void OnPaint(PaintEventArgs e)
{
base.OnPaint(e);
// Call methods of the System.Drawing.Graphics object.
// Declare and instantiate a new pen.
System.Drawing.Pen myPen = new System.Drawing.Pen(Color.Aqua);
// Draw an aqua rectangle in the rectangle represented by the control.
e.Graphics.FillEllipse(Brushes.Black,x,y,width,height);
}
}
Form1 class
private void panel_MouseDown(object sender, MouseEventArgs e)
{
draw = true;
x = e.X;
y = e.Y;
}
private void panel_MouseUp(object sender, MouseEventArgs e)
{
draw = false;
xe = e.X;
ye = e.Y;
Item item;
Enum.TryParse<Item>(menuComboBoxShape.ComboBox.SelectedValue.ToString(), out item);
switch (item)
{
case Item.Pencil:
using (Graphics g = panel.CreateGraphics())
using (var pen = new Pen(System.Drawing.Color.Black)) //Create the pen used to draw the line (using statement makes sure the pen is disposed)
{
g.DrawLine(pen,new Point(x, y), new Point(xe, ye));
}
break;
case Item.Rectangle:
break;
case Item.Ellipse:
Ellipse el = new Ellipse(x,y,xe-x,ye-y);
panel.Controls.Add(el);
break;
default:
break;
}
}
You are inheriting your Ellipse class from Control, but in fact you're not using it as a control - you're not adding it in Controls collection of form, so in fact it is invisible, inactive and not receiving any events from form.
Also painting the control from outer code looks like a bad design. Control should paint itself, and you should set it bounds from outer code.
Here is snippet to drive you to the right way:
class Ellipse : Control
{
Point mDown { get; set; }
public Ellipse()
{
MouseDown += shape_MouseDown;
MouseMove += shape_MouseMove;
}
protected override void OnPaint(PaintEventArgs e)
{
base.OnPaint(e);
e.Graphics.FillEllipse(Brushes.Black, this.Bounds);
}
private void shape_MouseDown(object sender, MouseEventArgs e)
{
mDown = e.Location;
}
private void shape_MouseMove(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Left)
{
Location = new Point(e.X + Left - mDown.X, e.Y + Top - mDown.Y);
}
}
}
And in the form you should create it like:
el = new Ellipse();
el.Bounds = new Rectangle(0, 0, 100, 100);
Controls.Add(el);
Update
Based on your updated code, I can see a couple of issues:
You actually don't need x, y, width, height properties of your Ellipse class and according getter/setter methods, since it's Control, and it has its own Location and Width, Height public properties.
You are drawing your ellipse incorrectly. Assuming it should fill all the area, painting should be e.Graphics.FillEllipse(Brushes.Black,0,0,Width,Height) (here I assuming using Control.Width instead of your width and so on). Otherwise you're additionally shifting your painted ellipse.
Code in panel_MouseUp concerning ellipse creation should be something like
var el = new Ellipse();
panel.Controls.Add(el);
el.Location = new Point(x, y);
el.Width = (xe - x);
el.Height = (ye - y);
Or, if it should be one single ellipse (right now you're creating new one each time) - create this one outside of mouseUp handler and inside of handler just change it's size and location.

Drawing more then 1 graphics on pictureBox1 with button_Click + mixed up graphics

I am making an application on windows forms application. It is called a artgenerator.
The meaning of this application is that everytime that I click on a button for example button "ellipse" that an ellipse will be drawn on the form. Now everything is going smooth untill I press all three buttons after eachother. Then the application is combining all figures into 1. And that's not what I want. Also after I draw 1 ellipse, square or line and I press the same button again the graphic dissapear and a new one appear. How to fix these problems?
I will send my code down below:
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 Kunstgenerator
{
public partial class Form1 : Form
{
bool TekenCirkel = false;
bool TekenRechthoek = false;
bool TekenLijn = false;
public Form1()
{
InitializeComponent();
}
private void button4_Click(object sender, EventArgs e)
{
pictureBox1.Hide();
}
private void btnCirkel_Click(object sender, EventArgs e)
{
TekenCirkel = true;
pictureBox1.Show();
pictureBox1.Refresh();
}
private void btnRechthoek_Click(object sender, EventArgs e)
{
TekenRechthoek = true;
pictureBox1.Show();
pictureBox1.Refresh();
}
private void btnLijn_Click(object sender, EventArgs e)
{
TekenLijn = true;
pictureBox1.Refresh();
pictureBox1.Show();
}
private void pictureBox1_Resize(object sender, EventArgs e)
{
Refresh();
}
private void pictureBox1_Paint(object sender, PaintEventArgs e)
{
// Er wordt een Random aangemaakt.
Random random = new Random();
// Breedte en hoogte wordt aangemaakt en verwezen naar zichzelf.
// Hier wordt de Random gebruikt om een willekeurige hoogte en breedte te maken.
int width = random.Next(this.Width);
int height = random.Next(this.Height);
// Primaire kleuren Rood, Geel, Blauw worden hier aangemaakt.
// Door de Random is de kleuren willekeurig. Er wordt een kleur uitgekozen tussen 1 en 255
int r = random.Next(255);
int g = random.Next(255);
int b = random.Next(255);
if (TekenRechthoek)
{
Graphics graphics = e.Graphics;
if (random.Next(2) == 0)
{
graphics.FillRectangle(new SolidBrush(Color.FromArgb(r, g, b)), width, height, width, height);
}
else
{
graphics.DrawRectangle(new Pen(new SolidBrush(Color.FromArgb(r, g, b))), width, height, width, height);
}
}
if (TekenLijn)
{
Graphics graphics = e.Graphics;
graphics.DrawLine(new Pen(new SolidBrush(Color.FromArgb(r, g, b))), width, height, width, 100);
}
if (TekenCirkel)
{
Graphics graphics = e.Graphics;
if (random.Next(2) == 0)
{
graphics.FillEllipse(new SolidBrush(Color.FromArgb(r, g, b)), width, height, width, height);
}
else
{
graphics.DrawEllipse(new Pen(new SolidBrush(Color.FromArgb(r, g, b))), width, height, width, height);
}
}
}
}
}
This is all the code. I put also a picture here below to show you guys what I mean with combining graphics.
One other thing. Because my size and location of the graphics are all random they all dissapear (half-ish) from the screen. Is this fixable or is this part of the random-ness?
Thanks in advance
Btw I am a beginner in programming
Change your if statement to this:
if (TekenRechthoek)
{
}
else if ( TekenLijn )
{
}
else if ( TekenCirkel )
{
}
It is not entirely clear what you want to happen as each button is pressed. If it is one at a time, an easy way us to use RadioButtons. Set the appearance to "Button" and they will act like toggle buttons - they stay down until another one is pressed. Additionally, only one can be pressed at a time which sounds like what you want.
Then to track which shape to draw:
private enum Shapes
{
Circle,
Line,
Rect
}
// current shape var with default val
private Shapes thisShape = Shapes.Circle;
Then just set the current shape to draw in each check changed event:
private void rbCircle_CheckedChanged(object sender, EventArgs e)
{
if (rbCircle.Checked) {
thisShape = Shapes.Circle;
}
}
When you click a different button, it will get set to that shape indicator. Then draw the correct shape based on the value of thisShape. Using 3 variables to track one image state will usually result in confusion.

How do I keep animations from flickering in C# game programming?

Everytime I try to add a new line or move the paddle in this game the screen flickers.
How do I keep the screen from flickering when I move the paddle or add a line?
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
namespace WindowsFormsApplication2
{
public partial class GameTest : Form
{
int dx=3, dy=3, i =500, o = 100;
int rex = 400, rey = 450 ;
double c =0;
public GameTest()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
Graphics g = this.CreateGraphics();
Invalidate();
}
private void Form1_KeyDown(object sender, KeyEventArgs e)
{
Graphics g = this.CreateGraphics();
if (e.KeyCode == Keys.Left)
{
//Graphics g = this.CreateGraphics();
Invalidate();
Brush black = new SolidBrush(Color.White);
g.FillRectangle(black, rex, rey, 200, 20);
rex -= 40;
Brush red = new SolidBrush(Color.Green);
g.FillRectangle(red, rex, rey, 200, 20);
}
if (e.KeyCode == Keys.Right)
{
//Graphics g = this.CreateGraphics();
Brush white = new SolidBrush(Color.White);
g.FillRectangle(white, rex, rey, 200, 20);
rex += 40;
Brush red = new SolidBrush(Color.Green);
g.FillRectangle(red, rex, rey, 200, 20);
}
}
private void Form1_Paint(object sender, PaintEventArgs e)
{
DoubleBuffered = false;
Graphics g = this.CreateGraphics();
// Bitmap bmp1 = new Bitmap("G:\c#\Bouncing ball\Pic.jpg");
//TextureBrush tb2 = new TextureBrush(bmp1);
Brush green = new SolidBrush(Color.Green);
g.FillRectangle(green, rex, rey, 200, 20);
Graphics b= this.CreateGraphics();
Brush red = new SolidBrush(Color.Red);
b.FillEllipse(red, i, o, 20, 20);
Pen p = new Pen(Color.Black, 10);
//
g.DrawLine(p, 1000, 480,0,480);
g.DrawLine(p, 1000, 485, 1000, 0);
g .DrawLine(p, 0,480, 0, 0);
}
private void timer1_Tick(object sender, EventArgs e)
{
DoubleBuffered = false;
// int dx=3, dy=3, i = 300, o = 50;
i += dx;
if (i < 0)
{
dx = -dx;
}
else if (i + 50 > 1000)
{
dx = -dx;
}
o += dy;
if ((o +20>= rey) &&(i+20<=rex+200)&&(i+20>=rex))
{
//int rex = 400, rey = 450; RECTANGLE
// int dx=3, dy=3, i(x) = 500, o(y) = 100;
dy =-dy;
//c++;
//label1.Text = c.ToString();
}
// Misgeret\\
if (o < 0)
{
dy = -dy;
}
// Misgeret\\
else if (o + 50 > 600)
{
dy = -dy;
}
this.Invalidate();
}
private void label1_Click(object sender, EventArgs e)
{
label1.Text = c.ToString();
}
}
}
I noticed that you are setting DoubleBuffered to false in multiple areas of your program. That is definitely not helping since the whole reason to use double buffering is to prevent flickering.
The other thing is you are creating Graphics contexts and drawing in multiple places in your application. Try to refactor your code to only draw in the OnPaint() event handler of the form, and do not create a new Graphics context. Use the one provided in the PaintEventArgs of the OnPaint() event.
private void Form1_Paint(object sender, PaintEventArgs e)
{
Graphics g = e.Graphics;
using(Brush green = new SolidBrush(Color.Green))
{
g.FillRectangle(green, rex, rey, 200, 20);
}
// .. etc, etc..
}
Then, when you need to the form to be repainted you just need to invoke the Invalidate() method to tell the GDI that your form, or a portion of it, needs to be repainted. That will in turn cause the Paint event to be fired and the OnPaint() to be called.
As a side note, as #HighCore suggested in the comments, WinForms is definitely not the right framework to create a game in. For games try the XNA framework, or one of several open source ones available on the web such as Unity
UPDATE
To prevent flickering you can use automatic double buffering for your form. This can be enabled in the form constructor, after the call to InitializeComponent(), using a call to SetStyle:
SetStyle( ControlStyles.AllPaintingInWmPaint
| ControlStyles.UserPaint
| ControlStyles.DoubleBuffer , true);

Categories

Resources