I found out how to draw Rectangles and some code to find when two rectangles overlap but I can't connect these procedures.
I have the two rectangles that I wanted but then a cannot determine whether these intersect, to then add this information to a ListBox.
Here is my code:
public partial class Form1 : Form
{
Graphics g;
Pen p;
Point cursor;
int k = 0;
Point[] tocke = new Point[2];
public Form1()
{
InitializeComponent();
g = this.CreateGraphics();
p = new Pen(Color.Black, 3);
}
private void Form1_MouseMove(object sender, MouseEventArgs e)
{
cursor = this.PointToClient(Cursor.Position);
statusMisa.Text = "X: " + cursor.X + " Y: " + cursor.Y;
}
private void Form1_Click(object sender, EventArgs e)
{
bool Preklapanje(int l1x, int l1y, int l2x, int l2y, int r1x, int r1y, int r2x, int r2y)
{
if (l1x >= r2x || l2x >= r1x)
{
return false;
}
if (l1y <= r2y || l2y <= r1y)
{
return false;
}
return true;
}
List<int> pozX = new List<int>();
List<int> pozY = new List<int>();
if (checkCrtanje.Checked == true)
{
Rectangle rect = new Rectangle(cursor.X - 50, cursor.Y - 50, 100, 100);
if (k < 2)
{
g.DrawRectangle(p, rect);
tocke[k++] = new Point(cursor.X, cursor.Y);
listBox1.Items.Add("X: " + cursor.X + " Y: " + cursor.Y);
pozX.Add(cursor.X);
pozY.Add(cursor.Y);
}
else
{
MessageBox.Show("Možeš nacrtati samo dva kvadrata!");
}
}
if (k == 3)
{
if (Preklapanje(pozX[0] - 50, pozY[0] - 50, pozX[0] + 50, pozY[0] + 50, pozX[1] - 50, pozY[1] - 50, pozX[1] + 50, pozY[1] + 50))
{
listBox1.Items.Add("Preklapaju se.");
}
else
{
listBox1.Items.Add("Ne preklapaju se.");
}
}
}
}
► As noted, you shouldn't use CreateGraphics() to draw on a Control's surface: this object becomes invalid (belongs to the past) as soon as the Control where the drawing is performed is invalidated (is repainted).
All Controls that have a drawable surface, raise a Paint event and have an OnPaint method that we can override to perform custom painting (the OnPaint method is responsible to raise the Paint event, so we need to handle just one).
The argument of both the event and the method, represents a PaintEventArgs object, which provides a fresh Graphics object that we can use to paint.
We can call the Invalidate() method to repaint a Control when needed. This method causes the generation of a new PaintEventArgs object (thus, a new Graphics object). After, the OnPaint method is called, which - in turn - raises the Paint event.
► To determine whether a Rectangle intersects another (or more than one), we can use the Rectangle.IntersetWith() method (it returns true or false) and the Rectangle.Interset() method → this is used to generate a Rectangle that represents the intersection of two other rectangles.
See also:
→ Rectangle.Contains([Rectangle])
→ Rectangle.Union([Rectangle a], [Rectangle b]).
Here, I'm using a few collections to store the shapes currently drawn and their intersections (just rectangles, but you can build more complex shapes using GraphicsPath objects):
A List<Rectangle> (rects) which stores the Rectangles already created.
A List<Rectangle> (intersections), to store the intersections which belong to the past (intersections already drawn).
A List<Rectangle> (currentIntersects), used to temporarily store the intersection generated when a new Rectangle shaped is being drawn, so we can use different colors (as soon as we release the Mouse Button, this collection is fixed and added to the intersections collection).
A Rectangle structure (currentRect) which represents the Rectangle that is currently being drawn on the surface (when the Mouse Button is released, this object is added to the rects collection).
A Point structure (startPosition), used to store the initial position of the Rectangle currently drawn. It's reset when the OnMouseDown method is called (when a new Rectangle shape is generated).
► To use this code, create a new Form and paste the code you find here in its Code file. No need to subscribe to any event: since we're drawing on a Form, I'm overriding its methods (OnPaint, OnMouseDown, OnMouseUp, OnMouseMove), no event is used.
You can do the same with a Custom Control or a UserControl.
To add these collection, or just the intersections collection, to e.g., a ListBox, to handle the collections visually, see here (the currentIntersects and intersections collections already contain the information):
How to call a method that uses PaintEventArgs and coordinates variables
NOTE:
► Here, in the OnPaint method override, I'm not calling base.OnPaint(), so the event is not generated. This speeds up the process a bit, but keep in mind that subscribing to the Form's Paint event is useless.
► You need to activate double-buffering: (set DoubleBuffered = true), otherwise you'll notice a lot of flickering (this is quite normal).
This is how it works:
public partial class FormDrawings : Form
{
private List<Rectangle> rects = new List<Rectangle>();
private List<Rectangle> intersections = new List<Rectangle>();
private List<Rectangle> currentIntersects = new List<Rectangle>();
private Rectangle currentRect = Rectangle.Empty;
private Point startPosition = Point.Empty;
private float penSize = 2.0f;
protected override void OnMouseDown(MouseEventArgs e)
{
base.OnMouseDown(e);
if (e.Button == MouseButtons.Left) {
startPosition = e.Location;
currentRect = new Rectangle(startPosition, Size.Empty);
}
}
protected override void OnMouseMove(MouseEventArgs e)
{
base.OnMouseMove(e);
if (e.Button == MouseButtons.Left) {
if (e.Y < startPosition.Y) { currentRect.Location = new Point(currentRect.X, e.Y); }
if (e.X < startPosition.X) { currentRect.Location = new Point(e.X, currentRect.Y); }
currentRect.Size = new Size(Math.Abs(startPosition.X - e.X), Math.Abs(startPosition.Y - e.Y));
currentIntersects.Clear();
foreach (var rect in rects) {
if (currentRect.IntersectsWith(rect)) {
currentIntersects.Add(Rectangle.Intersect(currentRect, rect));
}
}
this.Invalidate();
}
}
protected override void OnMouseUp(MouseEventArgs e)
{
base.OnMouseUp(e);
if (currentRect.Size != Size.Empty) rects.Add(currentRect);
if (currentIntersects.Count > 0) {
intersections.AddRange(currentIntersects);
}
}
protected override void OnPaint(PaintEventArgs e)
{
using (var borderPen = new Pen(Color.LightGreen, penSize))
using (var iBrush = new SolidBrush(Color.FromArgb(128, Color.Orange)))
using (var crBrush = new SolidBrush(Color.FromArgb(128, Color.DeepSkyBlue))) {
intersections.ForEach(r => e.Graphics.FillRectangle(iBrush, r));
currentIntersects.ForEach(r => e.Graphics.FillRectangle(crBrush, r));
e.Graphics.DrawRectangle(borderPen, currentRect);
rects.ForEach(r => e.Graphics.DrawRectangle(borderPen, r));
}
}
}
Related
You know, we can easily to make line cursor for Chart (ex: Fig). But with PictureBox, how can I do it? Is there anyone has the solution?
You can intercept the MouseMove and the Paint events. Just draw the cross on the paint.
The advantage of using the Paint method, is that the original image is not changed, so no need to restore the overwritten pixels by the crosshair.
Here's an example:
I dropped a picturebox on a winform and linked some events.
using System;
using System.Drawing;
using System.Windows.Forms;
namespace MouseCrosshair
{
public partial class Form1 : Form
{
// to store the latest mouse position
private Point? _mousePos;
// the pen to draw the crosshair.
private Pen _pen = new Pen(Brushes.Red);
public Form1()
{
InitializeComponent();
}
private void pictureBox1_MouseEnter(object sender, EventArgs e)
{
// when the mouse enters the picturebox, we just hide it.
Cursor.Hide();
}
private void pictureBox1_MouseMove(object sender, MouseEventArgs e)
{
var pictureBox = (PictureBox)sender;
// on a mouse move, save the current location (to be used when drawing the crosshair)
_mousePos = e.Location;
// force an update to the picturebox.
pictureBox.Invalidate();
}
private void pictureBox1_Paint(object sender, PaintEventArgs e)
{
// if the mousepos is assigned (meaning we have a mouse pos, draw the crosshair)
if (_mousePos.HasValue)
{
var pictureBox = (PictureBox)sender;
// draw a vertical line
e.Graphics.DrawLine(_pen, new Point(_mousePos.Value.X, 0), new Point(_mousePos.Value.X, pictureBox.Height));
// draw a horizontal line
e.Graphics.DrawLine(_pen, new Point(0, _mousePos.Value.Y), new Point(pictureBox.Width, _mousePos.Value.Y));
}
}
private void pictureBox1_MouseLeave(object sender, EventArgs e)
{
// when the mouse is outside the picturebox, clear the mousepos
_mousePos = null;
// repaint the picturebox
pictureBox1.Invalidate();
// show the mouse cursor again.
Cursor.Show();
}
}
}
Because the events are using the sender, you can link multiple pictureboxes to these events.
It's also possible to inherit from the PictureBox, and write a new CrosshairPictureBox control, which has a crosshair by default.
If you want to draw charts in a PictureBox, use a Bitmap and draw on that using the Graphics.FromImage(bitmap) and put it in the PictureBox.Image. Don't forget to dispose the Graphics object.
You can achieve this by storing the position of the last point received, and then draw a line using the Graphics.DrawLine method between the old position and the new one.
Please also note, that when the mouse is moving, the Control.MouseMove event for every single pixel traveled by the mouse pointer isn't received for every single move. You do receive the Control.MouseMove events at a fairly consistent time interval. That means that the faster the mouse moves, the further apart the points you'll be actually receiving.
Check out this walkthrough for some examples - https://www.c-sharpcorner.com/UploadFile/mahesh/drawing-lines-in-gdi/
If I understand the question correctly, you are interested to draw x-axis and y-axis for a chart, but not using a chat control.
In this case, what you need to do is: Handle the Paint event of the PictureBox and draw the line from top middle to bottom middle and from left middle to right middle.
Here is the code which I write to produce above chart, y = Sin(x)
:
private void pictureBox1_Paint(object sender, PaintEventArgs e)
{
var axisWidth = 3;
var axisColor = Color.Red;
var chartLineWidth = 2;
var chartLineColor = Color.Blue;
var scale = 90;
var gridSize = 45;
var gridLineWidth = 1;
var gridLineColor = Color.LightGray;
var g = e.Graphics;
g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias;
var w = pictureBox1.ClientRectangle.Width / 2;
var h = pictureBox1.ClientRectangle.Height / 2;
g.TranslateTransform(w, h);
g.ScaleTransform(1, -1);
//Draw grid
for (int i = -w / gridSize; i <= w / gridSize; i++)
using (var axisPen = new Pen(gridLineColor, gridLineWidth))
g.DrawLine(axisPen, i * gridSize, -h, i * gridSize, h);
for (int i = -h / gridSize; i <= h / gridSize; i++)
using (var axisPen = new Pen(gridLineColor, gridLineWidth))
g.DrawLine(axisPen, -w, i * gridSize, w, i * gridSize);
//Draw axis
using (var axisPen = new Pen(axisColor, axisWidth))
{
g.DrawLine(axisPen, -w, 0, w, 0); //X-Asxis
g.DrawLine(axisPen, 0, -h, 0, h); //Y-Asxis
}
//Draw y = Sin(x)
var points = new List<PointF>();
for (var x = -w; x < w; x++)
{
var y = System.Math.Sin(x * Math.PI / 180);
points.Add(new PointF(x, scale * (float)y));
}
using (var chartLinePen = new Pen(chartLineColor, chartLineWidth))
{
g.DrawCurve(chartLinePen, points.ToArray());
}
g.ResetTransform();
}
You also need the following piece of code to handle resizing of the picture box:
private void MyForm_Load(object sender, EventArgs e)
{
this.pictureBox1.GetType().GetProperty("ResizeRedraw",
System.Reflection.BindingFlags.NonPublic |
System.Reflection.BindingFlags.Instance).SetValue(
this.pictureBox1, true);
}
You can also add a crosshair and rubber-band rectangle to the control, like the following image:
In fact , I want to draw circle in new position each time double-click and without remove before circle ,It should be noted that, I used PictureBox.
public Point postionCursor { get; set; }
List<Point> points = new List<Point>();
private void pictureBox1_DoubleClick(object sender, EventArgs e)
{
postionCursor = this.PointToClient(new Point(Cursor.Position.X - 25, Cursor.Position.Y - 25));
points.Add(postionCursor);
pictureBox1.Invalidate();
pictureBox1.Paint += new PaintEventHandler(pic_Paint);
}
private void pic_Paint(object sender, PaintEventArgs e)
{
Graphics g = e.Graphics;
g.SmoothingMode = SmoothingMode.AntiAlias;
foreach (Point pt in points)
{
Pen p = new Pen(Color.Tomato, 2);
SolidBrush myb = new SolidBrush(Color.White);
g.DrawEllipse(p, postionCursor.X, postionCursor.Y, 20, 20);
g.FillEllipse(myb, postionCursor.X, postionCursor.Y, 20, 20);
p.Dispose();
}
}
You're not using the pt variable in the foreach loop.
foreach (Point pt in points)
{
using(Pen p = new Pen(Color.Tomato, 2))
using(SolidBrush myb = new SolidBrush(Color.White))
{
g.FillEllipse(myb, pt.X, pt.Y, 20, 20);
g.DrawEllipse(p, pt.X, pt.Y, 20, 20);
}
}
In your code, you were just overwriting the circle in the same location for every Point in the points list.
Also, as Reza mentioned in the comments, you don't need to attach the PaintEventHandler event hanlder every time the PictureBox is clicked, you just need to do it once.
So I got to thinking, and then Visual Studio-ing, that perhaps we don't even need the foreach loop. I still maintain a List so we know where the user has clicked, but there's no need to loop through it and redraw everything every time.
I realize this doesn't handle the case where the underlying list is modified, but nor does the original sample. Here's my entire Form1 class:
public partial class Form1 : Form
{
private const int CircleDiameter = 20;
private const int PenWidth = 2;
private readonly List<Point> _points = new List<Point>();
public Form1()
{
InitializeComponent();
pictureBox1.Paint += (sender, args) =>
{
_points.ForEach(p => DrawPoint(p, args.Graphics));
};
}
private void pictureBox1_DoubleClick(object sender, EventArgs e)
{
var cursorLocation = pictureBox1.PointToClient(Cursor.Position);
_points.Add(cursorLocation);
var circleArea = new Rectangle(
cursorLocation.X - CircleDiameter/2 - PenWidth,
cursorLocation.Y - CircleDiameter/2 - PenWidth,
CircleDiameter + PenWidth*2,
CircleDiameter + PenWidth*2);
pictureBox1.Invalidate(circleArea);
}
private static void DrawPoint(Point point, Graphics graphics)
{
point.X -= CircleDiameter / 2;
point.Y -= CircleDiameter / 2;
using (var pen = new Pen(Color.Tomato, PenWidth))
using (var brush = new SolidBrush(Color.White))
{
graphics.SmoothingMode = SmoothingMode.AntiAlias;
graphics.DrawEllipse(pen, point.X, point.Y, CircleDiameter, CircleDiameter);
graphics.FillEllipse(brush, point.X, point.Y, CircleDiameter, CircleDiameter);
}
}
}
Update 1:
So I updated the code to use the Paint event which has the foreach loop. However, I don't Invalidate (and Paint) every time a circle is added - there's no need for that. Just adding a circle by drawing means the control only invalidates and re-paints the region where the new circle was added.
Try setting a breakpoint on the DrawAllPoints method. You'll see it only happens during full invalidation operations such as minimizing and restoring.
Update 2:
After further chat, I agree the Invalidate method is superior. Code updated to use Invalidate with a rectangle to invalidate.
And now it's looking very much like the OP :)
The goal of this little program I am working on is to draw a red circle while radiobutton1 is checked, and draw a black circle while radiobutton2 is checked.
Below is my code, the problem with this code is when radiobutton1 is checked, it does draw red circles, but then if I click radiobutton2, then all the red circles will turn black. Then if check radiobutton1 again, the all the dots will turn red again.
How do I keep both color circles on the panel?
List<Point> points = new List<Point>();
Graphics g;
private void panel1_MouseDown(object sender, MouseEventArgs e)
{
points.Add(e.Location);
panel1.Invalidate();
}
private void panel1_Paint(object sender, PaintEventArgs e)
{
int count = 0;
if (radioButton1.Checked)
{
g = e.Graphics;
while (count < points.Count())
{
g.FillEllipse(Brushes.Red, points[count].X, points[count].Y, 10, 10);
count++;
}
}
else if (radioButton2.Checked)
{
g = e.Graphics;
while (count < points.Count())
{
g.FillEllipse(Brushes.Black, points[count].X, points[count].Y, 10, 10);
count++;
}
}
}
The way graphics works in Windows Forms is, the Paint method redraws the entire panel.
You are already drawing every point every time the paint method executes: this is correct.
But you have no way of remembering which point is supposed to be which color, so all you have to go on when you do the painting is the current values of the radiobuttons. You need some way of recording the current color when you add a circle.
One way to do this would be to define a Circle class which stores the location and color of a circle:
class Circle
{
public Point Location { get; set; }
public Brush Fill { get; set; }
}
Then instead of points being a List<Point>, it can be a List<Circle>, and when you see a mouse click, you can add a new Circle instead of a Point:
var circle = new Circle()
{
Location = e.Location,
Fill = radioButton1.Checked ? Brushes.Red : Brushes.Black
};
points.Add(circle);
And when you do the painting, you can check each circle's color as you draw them - all you have to do is this:
foreach (var circle in points)
{
e.Graphics.FillEllipse(circle.Fill, circle.Location.X, circle.Location.Y, 10, 10);
}
Note that you do not need a member level Graphics g - and it's a bad idea to keep a Graphics object after the Paint method has finished. It will not necessarily still be valid later. Always just use e.Graphics.
I also replaced your while loop with a simpler foreach.
If I understand your intent correctly, you need to keep two lists of points, one for each color. Then, when you click somewhere, put the clicked point in the appropriate list (red or black). Then, in your Paint event handler, replace the conditional code with two loops, one through each list of points (drawing the points from the red list in red and the points from the black list in black).
Code:
List<Point> redPoints = new List<Point>();
List<Point> blackPoints = new List<Point>();
private void panel1_MouseDown(object sender, MouseEventArgs e)
{
if (radioButton1.Checked)
redPoints.Add(e.Location);
else
blackPoints.Add(e.Location);
panel1.Invalidate();
}
private void panel1_Paint(object sender, PaintEventArgs e)
{
int count = 0;
Graphics g = e.Graphics;
foreach (Point p in redPoints)
{
g.FillEllipse(Brushes.Red, p.X, p.Y, 10, 10);
}
foreach (Point p in blackPoints)
{
g.FillEllipse(Brushes.Black, p.X, p.Y, 10, 10);
}
}
Note: if your circles overlap one another and you care about maintaining the layering order (first-clicked circles drawing first), then #Blorgbeard's solution is better because it keeps all the circles in the same list, thus maintaining the original layering. Feel free to switch the accepted answer.
My form has two objects: a background image that takes up the entire screen, and a dragable dialog control that only takes up a portion of the screen. I am using Mouse events for dragging and dropping the dialog control within the background image.
My problem is that while dragging, there is a copy of the control that is visible at it's previous location.
What is causing this shadow copy to appear, and how can I prevent it from happening?
My code looks something like this:
private void dialog_MouseDown(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Left)
{
_dialogDragStart = e.Location;
dialog.MouseMove += new MouseEventHandler(dialog_MouseMove);
}
}
private void dialog_MouseUp(object sender, MouseEventArgs e)
{
dialog.MouseMove -= new MouseEventHandler(dialog_MouseMove);
_isDragging.Value = false;
}
private void dialog_MouseMove(object sender, MouseEventArgs e)
{
var difference = new Point(e.Location.X - _dialogDragStart.X, e.Location.Y - _dialogDragStart.Y);
if (!_isDragging.Value)
{
if (Math.Abs(difference.X) > SystemInformation.DragSize.Width || Math.Abs(difference.Y) > SystemInformation.DragSize.Height)
{
_isDragging.Value = true;
}
}
else if (_isDragging.Value && !difference.IsEmpty)
{
DialogOffset = GetValidDialogOffset(DialogOffset.X + difference.X, DialogOffset.Y + difference.Y);
this.Invalidate();
this.Update();
}
}
It should be noted that this entire UserControl contains a custom OnPaint event. The Paint event recalculates the Size and Location of the Dialog before painting it in a custom format. To get this working, I have simply adjusted the Location calculation to include the DialogOffset.
const int padding = 1;
const int shadowDepth = 3;
const int roudeCornerRadius = 5;
private void Paint(Graphics g, Rectangle clipRect)
{
try
{
dialog.Size = GetSize();
dialog.Location = new Point(
((backgroundImage.Width - dialog.Width) / 2) + DialogOffset.X,
((backgroundImage.Height - dialog.Height) / 2) + DialogOffset.Y);
if (Image != null && !backgroundImage.ClientRectangle.IsEmpty)
{
Rectangle imageBounds = new Rectangle(Point.Empty, Image.Size);
using (BufferedGraphics buffer = BufferedGraphicsManager.Current.Allocate(g, backgroundImage.ClientRectangle))
{
using (Bitmap img = ((Bitmap)backgroundImage).Clone(imageBounds, PixelFormat.Format16bppArgb1555) as Bitmap)
{
buffer.Graphics.Clear(Color.White);
buffer.Graphics.DrawImage(img,backgroundImage.ClientRectangle, imageBounds, GraphicsUnit.Pixel);
buffer.Render(g);
}
}
}
//Create Rectangles
Rectangle outerRect = dialog.ClientRectangle;
Rectangle innerRect = new Rectangle(padding, padding, outerRect.Width - (padding + shadowDepth), outerRect.Height - (padding + shadowDepth));
//create Paths
using (GraphicsPath innerPath = new GraphicsPath())
{
GraphicsHelper.GetRoundedRect(innerPath, innerRect, roudeCornerRadius, 1, 1);
//Assign outer rounded rectangle to the dialog's region property
Region region = new Region(innerPath);
if (dialog.Region != null)
dialog.Region.Dispose();
dialog.Region = region;
}
}
catch (Exception ex)
{
// Log error
}
}
I've seen suggestions to set the DoubleBufferred property to true, however its explicitly set to false in the existing code, and setting it to true causes no update at all while dragging.
I've tried taking a screenshot of the problem, however all screenshots only show one copy of the dialog control being dragged, even though I can clearly see a 2nd copy of the control on my screen while dragging.
What can be causing this, and how can I fix it?
I'm making a simple game in winform (tic-tac-toe), and I'm having some problem to paint block control.
Here is the class I made, that represent a block in the game (without game logic, is only UI).
public class UI_Block : Control
{
private Rectangle block;
private SIGNS sign;
public SIGNS Sign
{
get {return sign;}
set
{
if (sign == SIGNS.EMPTY)
sign = value;
}
}
public UI_Block( ) {
sign = SIGNS.EMPTY;
}
public void SetBlockOnBoard(int x, int y)
{
this.Location = new Point( x , y );
this.Size = new Size(Parent.Width /3, Parent.Height / 3);
block = new Rectangle(this.Location, this.Size);
}
public void DrawSign(Graphics g)
{
Pen myPen = new Pen(Color.Red);
if (sign == SIGNS.O)
{
drawO(g,new Pen(Brushes.Black));
}
if (sign == SIGNS.X)
{
drawX(g, new Pen(Brushes.Red));
}
}
protected override void OnPaint(PaintEventArgs e)
{
DrawSign(e.Graphics);
base.OnPaint(e);
}
//Draw X
private void drawX(Graphics g, Pen myPen)
{
//draw first daignol
Point daignolStart = new Point { X = this.Location.X , Y = this.Location.Y };
Point daignolEnd = new Point { X = this.Size.Width , Y = this.Size.Height };
g.DrawLine(myPen, daignolStart, daignolEnd);
//draw second daignol
daignolStart = new Point { X = Size.Width , Y = this.Location.Y };
daignolEnd = new Point { X = Location.X, Y = Size.Height };
g.DrawLine(myPen, daignolEnd, daignolStart);
}
//Draw O
private void drawO(Graphics g, Pen myPen)
{
g.DrawEllipse(myPen, block);
}
}
I added them both to the winForm class and to see how it looks like when I paint them:
public partial class Form1 : Form
{
UI.UI_Block block;
UI.UI_Block blockX;
public Form1()
{
InitializeComponent();
block = new UI.UI_Block();
blockX = new UI.UI_Block();
Controls.Add(block);
Controls.Add(blockX);
}
protected override void OnLoad(EventArgs e)
{
block. SetBlockOnBoard(0, 0);
blockX.SetBlockOnBoard(0, block.Height);
block.Sign = SIGNS.X;
blockX.Sign = SIGNS.O;
base.OnLoad(e);
}
protected override void OnPaint(PaintEventArgs e)
{
//block.DrawSign(e.Graphics);
//block.DrawSign(e.Graphics);
base.OnPaint(e);
}
}
I tried few things, like not using the onPaint event and I still get the same result.
Here what I see when I run it:
Any idea why I can't paint both of them?
You are not drawing the contents of your control in it's visible area, so it is drawing fine but you can't see it.
Every control has it's own coordinate space (client coords), which starts at 0,0 regardless of where it is positioned within the parent control. You are placing the control in it's parent correctly by setting its Location, but then you are also using the Location to offset the graphics, so they are essentially offset twice.
(If you make your control bigger you'll be able to see the X being drawn further down the screen)
To fix this, do all your drawing in the client coordinate space of your control, i.e. draw in the area (0, 0, width, height)
(P.S. You could just draw all 9 tiles in the parent control, which is a more efficient approach than creating 9 child controls. But what you are doing will work fine)