paint rectangle on column header in c# - c#

I have painted the datagridview column header and called the repaint event in the scroll event ,but it does not seems to repaint properly . The text in the painted rectangle gets scettered ( see the second image)
here is my code,
void dataGridView1_Scroll(object sender, ScrollEventArgs e)
{
Rectangle rtHeader = this.dataGridView1.DisplayRectangle;
rtHeader.Y += 0;
rtHeader.Height = this.dataGridView1.ColumnHeadersHeight;
}
Rectangle r1;
void dataGridView1_Paint(object sender, PaintEventArgs e)
{
string[] monthes = { "APPLE", "MANGO", "CHERRY", "GRAPES", "PINEAPPLE" };
for (int j = 0; j < this.dataGridView1.ColumnCount; )
{
r1 = this.dataGridView1.GetCellDisplayRectangle(j, -1, true);
int w2 = this.dataGridView1.GetCellDisplayRectangle(j + 1, -1, true).Width;
r1.X += -2;
r1.Y += 30;
r1.Width = r1.Width + w2 - 1;
r1.Height = r1.Height / 3 - 2;
e.Graphics.FillRectangle(new SolidBrush(this.dataGridView1.ColumnHeadersDefaultCellStyle.BackColor), r1);
StringFormat format = new StringFormat();
format.Alignment = StringAlignment.Center;
format.LineAlignment = StringAlignment.Center;
e.Graphics.DrawRectangle(new Pen(Color.Black), r1);
e.Graphics.DrawString(monthes[j / 2], this.dataGridView1.ColumnHeadersDefaultCellStyle.Font, new SolidBrush(this.dataGridView1.ColumnHeadersDefaultCellStyle.ForeColor), r1, format);
j += 2;
}
string[] year = { "JANUARY", "FEBRUARY", "MARCH", "APRIL", "MAY" };
//for (int i = 0; i < this.dataGridView1.ColumnCount; )
//{
Rectangle rec = this.dataGridView1.GetCellDisplayRectangle(0, -1, true);
int wid = this.dataGridView1.GetCellDisplayRectangle(1, -1, true).Width;
rec.X += -2;
rec.Y += 1;
rec.Width = this.dataGridView1.Columns.GetColumnsWidth(DataGridViewElementStates.Visible);
rec.Height = rec.Height / 3 - 2;
e.Graphics.FillRectangle(new SolidBrush(this.dataGridView1.ColumnHeadersDefaultCellStyle.BackColor), rec);
StringFormat frm = new StringFormat();
frm.Alignment = StringAlignment.Center;
frm.LineAlignment = StringAlignment.Center;
e.Graphics.DrawRectangle(new Pen(Color.Black), rec);
e.Graphics.DrawString("Favourite fruits", new Font("Times new roman", 16, FontStyle.Regular), new SolidBrush(Color.CornflowerBlue), rec, frm);
}

private void dataGridView1_Scroll(object sender, ScrollEventArgs e)
{
/*
Rectangle rtHeader = this.dataGridView1.DisplayRectangle;
rtHeader.Y += 0;
rtHeader.Height = this.dataGridView1.ColumnHeadersHeight;
this.dataGridView1.Invalidate(rtHeader);
*/
this.dataGridView1.Invalidate();
}

if (e.RowIndex == -1 && e.ColumnIndex > -1)
{
e.PaintBackground(e.CellBounds, true);
RenderColumnHeader(e.Graphics, e.CellBounds, e.CellBounds.Contains(hotSpot) ? hotSpotColor : backColor);
RenderColumnHeaderBorder(e.Graphics, e.CellBounds, e.ColumnIndex);
using (Brush brush = new SolidBrush(e.CellStyle.ForeColor))
{
using (StringFormat sf = new StringFormat() { LineAlignment = StringAlignment.Center, Alignment = StringAlignment.Center })
{
e.Graphics.DrawString(e.Value.ToString(), e.CellStyle.Font, brush, e.CellBounds, sf);
}
}
e.Handled = true;
}
}
Color hotSpotColor = Color.LightGreen;//For hover backcolor
Color backColor = Color.MediumSeaGreen; //For backColor
Point hotSpot;
private void RenderColumnHeader(Graphics g, Rectangle headerBounds, Color c)
{
int topHeight = 10;
Rectangle topRect = new Rectangle(headerBounds.Left, headerBounds.Top + 1, headerBounds.Width, topHeight);
RectangleF bottomRect = new RectangleF(headerBounds.Left, headerBounds.Top + 1 + topHeight, headerBounds.Width, headerBounds.Height - topHeight - 4);
Color c1 = Color.FromArgb(180, c);
using (SolidBrush brush = new SolidBrush(c1))
{
g.FillRectangle(brush, topRect);
brush.Color = c;
g.FillRectangle(brush, bottomRect);
}
}
private void RenderColumnHeaderBorder(Graphics g, Rectangle headerBounds, int colIndex)
{
ControlPaint.DrawBorder3D(g, headerBounds, Border3DStyle.Raised, Border3DSide.All & ~Border3DSide.Middle);
}
//MouseMove event handler for your dataGridView1
private void dataGridView1_MouseMove(object sender, MouseEventArgs e)
{
hotSpot = e.Location;
}
//MouseLeave event handler for your dataGridView1
private void dataGridView1_MouseLeave(object sender, EventArgs e)
{
hotSpot = Point.Empty;
}

Related

click event prints all pages instead print range

I have the following code for my BeginPrint, PrintPage and Click event. Firing the click event, its printing all pages. I would like to add a print range on button event that prints from-to range:
BeginPrint:
private void printDocument1_BeginPrint(object sender, System.Drawing.Printing.PrintEventArgs e)
{
curRow = 0;
curCopy = 0;
if (printrange)
{
((PrintDocument)sender).PrinterSettings.PrintRange = PrintRange.SomePages;
((PrintDocument)sender).PrinterSettings.FromPage = 1;
((PrintDocument)sender).PrinterSettings.ToPage = 1;
printrange = false;
}
}
PrintPage :
I'm generating QRCodes, borders and text in this method. Usually I have more than 2 pages with QRCodes. The problem is that it prints all pages
private void printDocument1_PrintPage(object sender, PrintPageEventArgs e)
{
var curY = e.MarginBounds.Y;
var curX = e.MarginBounds.X + 30;//+ 10
Pen pen = new Pen(System.Drawing.ColorTranslator.FromHtml("#FFBD2D"), 1);
using (var fontNormal = new Font("Arial", 10))
using (var sf = new StringFormat())
{
sf.Alignment = sf.LineAlignment = StringAlignment.Center;
int itemHeight = (int)fontNormal.GetHeight(e.Graphics);
for (int row = curRow; row < dt.Rows.Count; row++)
{
DataRow dr = dt.Rows[row];
if (!string.IsNullOrEmpty(dr.Field<string>(1)) &&
int.TryParse(dr.Field<string>(4)?.ToString(), out int copies))
{
for (int i = curCopy; i < copies; i++)
{
var imgRect = new Rectangle(curX, curY, 156, 156);//e.MarginBounds.X
var labelRect = new Rectangle(
imgRect.X+180+20,//eltol
imgRect.Bottom-162,
itemHeight,
imgRect.Width);
using (var qrImage = GenerateQRCODE(dr[1].ToString()))
{
e.Graphics.DrawImage(RotateImage(qrImage, -90), imgRect);
}
SizeF labelSize = e.Graphics.MeasureString(dr[1].ToString(), fontNormal);
Bitmap stringmap = new Bitmap((int)labelSize.Height + 1, (int)labelSize.Width + 1);
Graphics gbitmap = Graphics.FromImage(stringmap);
gbitmap.TranslateTransform(0, labelSize.Width);
gbitmap.RotateTransform(-90);
gbitmap.DrawString(dr[1].ToString(), fontNormal, Brushes.Black, new PointF(0, 0), new StringFormat());
e.Graphics.DrawImage(stringmap, labelRect);
gbitmap.Dispose();
stringmap.Dispose();
e.Graphics.DrawLine(pen, curX, curY, curX, curY + 156);//57 |<
e.Graphics.DrawLine(pen, curX, curY + 156 , curX + 156 + 220, curY + 156);// _
e.Graphics.DrawLine(pen, curX + 156 + 220, curY + 156, curX + 156 + 220, curY);// >|
e.Graphics.DrawLine(pen, curX, curY, curX + 156 + 220, curY);// -
curX = imgRect.Right + 230; //horizontal gap
if (curX + imgRect.Width > e.MarginBounds.Right)
{
curX = e.MarginBounds.X + 30;
curY = labelRect.Bottom + 30;//55vertical gap
}
if (curY + imgRect.Height >= e.MarginBounds.Bottom)
{
curCopy = i + 1;
e.HasMorePages = true;
return;
}
}
}
curRow = row + 1;
curCopy = 0;
}
}
refreshprintbtn.Enabled = true;
printdialogbtn.Enabled = true;
}
In this click event I'm calling the print() method:
bool printrange = false;
private void printrangebtn_Click(object sender, EventArgs e)
{
printrange = true;
printDocument1.BeginPrint += printDocument1_BeginPrint;
printDocument1.PrintPage += printDocument1_PrintPage;
printDocument1.Print();
}
Thanks
You forgot to implement the PrintRange part in the PrintPage event. Just setting the PrintRange, FromPage, and ToPage properties doesn't mean that the printer knows which page should start with and which one should be the last. These properties exist to get the user inputs through the print dialogs or some setter methods and you need to use them as factors in your implementation.
For example, in PrintRange.SomePages case, use a class field to determine the target pages to print. Increment the field and print only if the value is within the .From and .To range.
// +
System.Drawing;
using System.Drawing.Printing;
// ...
private int curRow, curCopy, curPage;
public YourForm()
{
InitializeComponent();
printDocument1.BeginPrint += printDocument1_BeginPrint;
printDocument1.PrintPage += printDocument1_PrintPage;
}
private void printrangebtn_Click(object sender, EventArgs e)
{
printDocument1.PrinterSettings.PrintRange = PrintRange.SomePages;
printDocument1.PrinterSettings.FromPage = 1;
printDocument1.PrinterSettings.ToPage = 2;
printDocument1.Print();
}
private void printDocument1_BeginPrint(object sender, PrintEventArgs e)
{
curRow = 0;
curCopy = 0;
curPage = 0;
// ...
}
private void printDocument1_PrintPage(object sender, PrintPageEventArgs e)
{
var curY = e.MarginBounds.Y;
var curX = e.MarginBounds.X + 30;//+ 10
var doc = sender as PrintDocument;
using (var pen = new Pen(ColorTranslator.FromHtml("#FFBD2D")))
using (var fontNormal = new Font("Arial", 10))
using (var sf = new StringFormat())
{
sf.Alignment = sf.LineAlignment = StringAlignment.Center;
int itemHeight = (int)fontNormal.GetHeight(e.Graphics);
for (int row = curRow; row < dt.Rows.Count; row++)
{
curPage++;
var doPrint = doc.PrinterSettings.PrintRange != PrintRange.SomePages ||
(curPage >= doc.PrinterSettings.FromPage && curPage <= doc.PrinterSettings.ToPage);
DataRow dr = dt.Rows[row];
if (!string.IsNullOrEmpty(dr.Field<string>(1)) &&
int.TryParse(dr.Field<string>(4)?.ToString(), out int copies))
{
for (int i = curCopy; i < copies; i++)
{
var imgRect = new Rectangle(curX, curY, 156, 156);//e.MarginBounds.X
var labelRect = new Rectangle(
imgRect.X + 180 + 20,//eltol
imgRect.Bottom - 162,
itemHeight,
imgRect.Width);
// If not, don't print and continue the calculations...
if (doPrint)
{
using (var qrImage = GenerateQRCODE(dr[1].ToString()))
e.Graphics.DrawImage(RotateImage(qrImage, -90), imgRect);
SizeF labelSize = e.Graphics.MeasureString(dr[1].ToString(), fontNormal);
Bitmap stringmap = new Bitmap((int)labelSize.Height + 1, (int)labelSize.Width + 1);
Graphics gbitmap = Graphics.FromImage(stringmap);
gbitmap.TranslateTransform(0, labelSize.Width);
gbitmap.RotateTransform(-90);
gbitmap.DrawString(dr[1].ToString(), fontNormal, Brushes.Black, new PointF(0, 0), new StringFormat());
e.Graphics.DrawImage(stringmap, labelRect);
gbitmap.Dispose();
stringmap.Dispose();
e.Graphics.DrawLine(pen, curX, curY, curX, curY + 156);//57 |<
e.Graphics.DrawLine(pen, curX, curY + 156, curX + 156 + 220, curY + 156);// _
e.Graphics.DrawLine(pen, curX + 156 + 220, curY + 156, curX + 156 + 220, curY);// >|
e.Graphics.DrawLine(pen, curX, curY, curX + 156 + 220, curY);// -
}
curX = imgRect.Right + 230; //horizontal gap
if (curX + imgRect.Width > e.MarginBounds.Right)
{
curX = e.MarginBounds.X + 30;
curY = labelRect.Bottom + 30;//55vertical gap
}
if (curY + imgRect.Height >= e.MarginBounds.Bottom)
{
if (!doPrint) break;
curCopy = i + 1;
e.HasMorePages = true;
return;
}
}
}
if (!doPrint)
{
curX = e.MarginBounds.X;
curY = e.MarginBounds.Y;
}
curRow = row + 1;
curCopy = 0;
}
}
refreshprintbtn.Enabled = true;
printdialogbtn.Enabled = true;
}
Side Notes
You shouldn't add handlers for the PrintDocument events each time you click a Button unless you remove the current handlers first in the EndPrint for example. Just add them once as shown in the Form's ctor or Load event.
System.Drawing.Pen is a disposable object so you need to dispose of it as well. Create it with the using statement or pass an instance using (pen) ... or call the .Dispose(); method explicitly. Do the same for any object implements the IDisposable interface.

How to make OnPaint run different ControlPaint.DrawBorderStyle functions, when user selects the control

I have a UserControl (Groupbox) with the following onPaint method:
protected override void OnPaint(PaintEventArgs e) {
Size tSize = TextRenderer.MeasureText(this.Text, this.Font);
Rectangle borderRect = e.ClipRectangle;
borderRect.Y += tSize.Height / 2;
borderRect.Height -= tSize.Height / 2;
ControlPaint.DrawBorder(e.Graphics, borderRect, this.borderColor, ButtonBorderStyle.Solid);
Rectangle textRect = e.ClipRectangle;
textRect.X += 6;
textRect.Width = tSize.Width;
textRect.Height = tSize.Height;
e.Graphics.FillRectangle(new SolidBrush(this.BackColor), textRect);
e.Graphics.DrawString(this.Text, this.Font, new SolidBrush(this.ForeColor), textRect);
}
When the user selects this control, I want to change the border to be darker, so I tried the following logic:
protected override void OnPaint(PaintEventArgs e) {
Size tSize = TextRenderer.MeasureText(this.Text, this.Font);
Rectangle borderRect = e.ClipRectangle;
borderRect.Y += tSize.Height / 2;
borderRect.Height -= tSize.Height / 2;
if (ContainsFocus) {
ControlPaint.DrawBorder(e.Graphics, borderRect,
this.borderColor, 4, ButtonBorderStyle.Solid,
this.borderColor, 4, ButtonBorderStyle.Solid,
this.borderColor, 4, ButtonBorderStyle.Solid,
this.borderColor, 4, ButtonBorderStyle.Solid);
} else {
ControlPaint.DrawBorder(e.Graphics, borderRect, this.borderColor, ButtonBorderStyle.Solid);
}
Rectangle textRect = e.ClipRectangle;
textRect.X += 6;
textRect.Width = tSize.Width;
textRect.Height = tSize.Height;
e.Graphics.FillRectangle(new SolidBrush(this.BackColor), textRect);
e.Graphics.DrawString(this.Text, this.Font, new SolidBrush(this.ForeColor), textRect);
}
My control seems to be continuously entering else even when I select my user control. Any help in this direction will be appreciated.
To solve this problem I used the onMouseClick event with a combination of declaring a constructor which set the initial borderColor to a different value. like so
private Color borderColor;
private int entered;
public TUserControlGroupBox() {
this.borderColor = SystemColors.ControlDark;
}
public Color BorderColor {
get { return this.borderColor; }
set { this.borderColor = value; }
}
public BorderState Border {
set {
switch (value) {
case BorderState.Unselected:
this.BorderColor = Color.LightGray;
break;
case BorderState.Selected:
this.BorderColor = Color.Black;
break;
case BorderState.SelectedFirst:
this.BorderColor = SystemColors.ControlDark;
break;
}
this.Invalidate();
}
}
protected override void OnPaint(PaintEventArgs e) {
Size tSize = TextRenderer.MeasureText(this.Text, this.Font);
Rectangle borderRect = e.ClipRectangle;
borderRect.Y += tSize.Height / 2;
borderRect.Height -= tSize.Height / 2;
if ((this.BorderColor == Color.Black || this.borderColor == SystemColors.ControlDark) && this.entered == 1) {
ControlPaint.DrawBorder(e.Graphics, borderRect,
this.borderColor, 4, ButtonBorderStyle.Solid,
this.borderColor, 4, ButtonBorderStyle.Solid,
this.borderColor, 4, ButtonBorderStyle.Solid,
this.borderColor, 4, ButtonBorderStyle.Solid);
} else {
ControlPaint.DrawBorder(e.Graphics, borderRect, this.borderColor, ButtonBorderStyle.Solid);
}
Rectangle textRect = e.ClipRectangle;
textRect.X += 6;
textRect.Width = tSize.Width;
textRect.Height = tSize.Height;
e.Graphics.FillRectangle(new SolidBrush(this.BackColor), textRect);
e.Graphics.DrawString(this.Text, this.Font, new SolidBrush(this.ForeColor), textRect);
}
protected override void OnMouseClick(MouseEventArgs e) {
this.entered = 1;
this.Invalidate();
base.OnMouseClick(e);
}
Hope this answer helps those looking for a similar solution in the future.

Merge RTL Datagridview columns header in C#

I want to merge 3 Datagridview columns headers (the 3rd, 4th, and the 5th
columns) and the RightToleft property of the Datagridview is enabled. i user
this code:
private void PromotionButton_Click(object sender, EventArgs e)
{
dataGridView1.ColumnHeadersHeight = dataGridView1.ColumnHeadersHeight * 2;
dataGridView1.ColumnHeadersDefaultCellStyle.Alignment = DataGridViewContentAlignment.MiddleCenter;
dataGridView1.CellPainting += new DataGridViewCellPaintingEventHandler(dataGridView1_CellPainting);
dataGridView1.Paint += new PaintEventHandler(dataGridView1_Paint);
dataGridView1.Scroll += new ScrollEventHandler(dataGridView1_Scroll);
dataGridView1.ColumnWidthChanged += new DataGridViewColumnEventHandler(dataGridView1_ColumnWidthChanged);
}
private void dataGridView1_Paint(object sender, PaintEventArgs e)
{
for (int j = 2; j < 5; j++)
{
Rectangle r1 = dataGridView1.GetCellDisplayRectangle(j, -1, true);
int w2 = dataGridView1.GetCellDisplayRectangle(j + 1, -1, true).Width;
r1.X += 1;
r1.Y += 1;
r1.Width = r1.Width + w2 - 2;
r1.Height = r1.Height / 2 - 2;
e.Graphics.FillRectangle(new SolidBrush(dataGridView1.ColumnHeadersDefaultCellStyle.BackColor), r1);
StringFormat format = new StringFormat();
format.Alignment = StringAlignment.Center;
format.LineAlignment = StringAlignment.Center;
e.Graphics.DrawString("رياضيات", dataGridView1.ColumnHeadersDefaultCellStyle.Font,
new SolidBrush(dataGridView1.ColumnHeadersDefaultCellStyle.ForeColor), r1, format);
}
void dataGridView1_ColumnWidthChanged(object sender, DataGridViewColumnEventArgs e)
{
Rectangle rtHeader = dataGridView1.DisplayRectangle;
rtHeader.Height = dataGridView1.ColumnHeadersHeight / 2;
dataGridView1.Invalidate(rtHeader);
}
void dataGridView1_Scroll(object sender, ScrollEventArgs e)
{
Rectangle rtHeader = dataGridView1.DisplayRectangle;
rtHeader.Height = dataGridView1.ColumnHeadersHeight / 2;
dataGridView1.Invalidate(rtHeader);
}
void dataGridView1_CellPainting(object sender, DataGridViewCellPaintingEventArgs e)
{
if (e.RowIndex == -1 && e.ColumnIndex > -1)
{
Rectangle r2 = e.CellBounds;
r2.Y += e.CellBounds.Height / 2;
r2.Height = e.CellBounds.Height / 2;
e.PaintBackground(r2, true);
e.PaintContent(r2);
e.Handled = true;
}
}
But the result was not like what i want, it was like this:
So how to solve this?
Assuming you want those three columns merged with only one print of the merge text, and you want to merge columns indexed 2-4:
Remove the loop.
Get the width of all three desired columns (instead of column j and j+1)
Start your Rectangle at the left-most column (column 4, not 2) since your grid has RightToLeft enabled.
private void dataGridView1_Paint(object sender, PaintEventArgs e)
{
Rectangle r1 = dataGridView1.GetCellDisplayRectangle(4, -1, true);
int w2 = dataGridView1.GetCellDisplayRectangle(3, -1, true).Width;
int w3 = dataGridView1.GetCellDisplayRectangle(2, -1, true).Width;
r1.X += 1;
r1.Y += 1;
r1.Width = r1.Width + w2 + w3;
r1.Height = r1.Height / 2 - 2;
e.Graphics.FillRectangle(new SolidBrush(dataGridView1.ColumnHeadersDefaultCellStyle.BackColor), r1);
StringFormat format = new StringFormat();
format.Alignment = StringAlignment.Center;
format.LineAlignment = StringAlignment.Center;
e.Graphics.DrawString("رياضيات", dataGridView1.ColumnHeadersDefaultCellStyle.Font,
new SolidBrush(dataGridView1.ColumnHeadersDefaultCellStyle.ForeColor), r1, format);
}
Also, I would suggest using the following alignment to prevent your header text from partial obstruction:
dataGridView1.ColumnHeadersDefaultCellStyle.Alignment = DataGridViewContentAlignment.BottomCenter;

Converting C# Graph into a proper mathematical graph

Recently, I have been working on this graphing system in C#, and I am having problems with the coordinate system. As we all know, C# uses the top left corner as 0,0 coordinates. What I want to accomplish is to make 0 in the middle of the windows form.
Currently, this is what I have...
As you can see, 0,0 is on the top left, making the center of the graph 400. So is there a way to transform the coordinates into a proper mathematical graph coordinate?
I hope I was able to explain this situation well as my English is not very well.
public partial class Form1 : Form
{
public static int _wWidth;
public static int _wHeight;
int mouseX, mouseY;
Point _center = new Point(_wWidth / 2, _wHeight / 2);
public Form1()
{
InitializeComponent();
foreach (Control c in this.Controls)
{
c.MouseDown += ShowMouseDown;
}
this.MouseDown += (s, e) => { this.label3.Text = "{X: " + e.X + " Y:" + e.Y + "}"; mouseX = e.X; mouseY = e.Y; };
}
private void ShowMouseDown(object sender, MouseEventArgs e)
{
var x = e.X + ((Control)sender).Left;
var y = e.Y + ((Control)sender).Top;
this.label3.Text = x + " " + y;
}
public void Form1_Load(object sender, EventArgs e)
{
this.ClientSize = new Size(800, 800);
int windowWidth = this.ClientSize.Width;
int windowHeight = this.ClientSize.Height;
_wWidth = windowWidth;
_wHeight = windowHeight;
button1.Location = new Point(_wWidth - button1.Width,0);
//AllocConsole(); /***** Enable console for debugging *****/
}
[DllImport("kernel32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool AllocConsole();
public void Form1_Paint(object sender, PaintEventArgs e)
{
e.Graphics.SmoothingMode = SmoothingMode.AntiAlias;
_drawPlain(e);
}
public void _drawPlain(PaintEventArgs e){
Graphics formGraphics = this.CreateGraphics();
for(int x = 0; x < _wHeight; x+=50)
{
e.Graphics.DrawLine(new Pen(Color.FromArgb(80, 75, 75)), new Point(0, x), new Point(_wWidth, x));
Console.ForegroundColor = ConsoleColor.Green; if (x == 20) { Console.Write("X - "); } Console.WriteLine(x);
e.Graphics.DrawString(x.ToString(), new Font("Arial", 10), new SolidBrush(Color.White), new Point(_wWidth/2,x));
}
for (int y = 0; y < _wWidth; y += 50)
{
e.Graphics.DrawLine(new Pen(Color.FromArgb(80, 75, 75)), new Point(y, 0), new Point(y, _wHeight));
Console.ForegroundColor = ConsoleColor.Red; if (y == 20) { Console.Write("Y - "); } Console.WriteLine(y);
int num = y;
e.Graphics.DrawString(num.ToString(), new Font("Arial", 10), new SolidBrush(Color.White), new Point(y, _wHeight/2));
}
e.Graphics.DrawLine(Pens.Green, new Point(0, _wHeight/2), new Point(_wWidth, _wHeight/2));
e.Graphics.DrawLine(Pens.DarkRed, new Point(_wWidth/2, 0), new Point(_wWidth/2, _wHeight));
//e.Graphics.DrawString("0", new Font("Arial", 10), new SolidBrush(Color.White), new Point(_wWidth / 2, _wHeight / 2));
//// Create pen.
//Pen blackPen = new Pen(Color.Black, 3);
//// Create points that define polygon.
//Point point1 = new Point(100, 200);
//Point point2 = new Point(300, 200);
//Point point3 = new Point(200, 50);
//Point[] curvePoints =
// {
// point1,
// point2,
// point3
// };
//// Draw polygon to screen.
//e.Graphics.DrawPolygon(blackPen, curvePoints);
}
public static int _yCellCount()
{
int _cell = 0;
for (int i = 0; i < 20; i++)
{
_cell++;
}
return _cell;
}
private void button1_Click(object sender, EventArgs e)
{
this.Refresh();
}
private void Form1_Click(object sender, EventArgs e)
{
Graphics g = this.CreateGraphics();
g.SmoothingMode = SmoothingMode.AntiAlias;
g.DrawLine(Pens.Yellow,new Point(mouseX,mouseY),new Point(_wWidth/2,400));
}
}

C# GDI Snake Game

How do I make the snake move in all directions continuosly without having to press the buttons always
public partial class Form1 : Form
{
Rectangle rectangle;
Size recSize;
Point firstPoint;
Point[,] grid;
Graphics graphics;
Point[] snake;
Random rng;
Pen pen;
int width = 0;
int height = 0;
public Form1()
{
InitializeComponent();
firstPoint = new Point(0, 0);
recSize = new Size(this.ClientSize.Width, this.ClientSize.Height);
rectangle = new Rectangle(firstPoint, recSize);
graphics = this.CreateGraphics();
width = rectangle.Width;
height = rectangle.Height;
grid = new Point[width/4, height/4];
snake = new Point[400];
rng = new Random();
}
protected override void OnPaint(PaintEventArgs e)
{
base.OnPaint(e);
pen = new Pen(new SolidBrush(Color.Green));
//e.Graphics.DrawRectangle(pen, rectangle);
e.Graphics.FillRectangle(new SolidBrush(Color.Green), rectangle);
}
private void GameButton_Click(object sender, EventArgs e)
{
for (int i = 0; i < width / 4; i++)
{
for (int j = 0; j < height / 4; j++)
{
grid[i, j] = new Point();
grid[i, j].X = firstPoint.X + (i * 4);
grid[i, j].Y = firstPoint.Y + (j * 4);
graphics.DrawEllipse(new Pen(new SolidBrush(Color.FromArgb(255, 0,0,0))), new Rectangle(grid[i, j], new Size(2, 2)));
}
}
snake[0] = new Point();
snake[0] = grid[width /4/ 2 , height /4/ 2 ];
graphics.DrawEllipse(new Pen(new SolidBrush(Color.Black)), new Rectangle(snake[0], new Size(4, 4)));
graphics.FillEllipse(new SolidBrush(Color.Black), new Rectangle(snake[0], new Size(4, 4)));
}
private void moveSnake(KeyEventArgs e)
{
switch (e.KeyData)
{
case Keys.Up:
this.graphics.Clear(Color.Green);
snake[0].Y -= 4;
graphics.DrawEllipse(new Pen(new SolidBrush(Color.Black)), new Rectangle(snake[0], new Size(4, 4)));
graphics.FillEllipse(new SolidBrush(Color.Black), new Rectangle(snake[0], new Size(4, 4)));
graphics.Flush();
this.Invalidate();
System.Threading.Thread.Sleep(500);
// this.Refresh();
//moveSnake(e);
break;
case Keys.Down:
this.graphics.Clear(Color.Green);
snake[0].Y += 4;
graphics.DrawEllipse(new Pen(new SolidBrush(Color.Black)), new Rectangle(snake[0], new Size(4, 4)));
graphics.FillEllipse(new SolidBrush(Color.Black), new Rectangle(snake[0], new Size(4, 4)));
this.Invalidate();
System.Threading.Thread.Sleep(500);
//this.Refresh();
break;
case Keys.Left:
this.graphics.Clear(Color.Green);
snake[0].X -= 4;
graphics.DrawEllipse(new Pen(new SolidBrush(Color.Black)), new Rectangle(snake[0], new Size(4, 4)));
graphics.FillEllipse(new SolidBrush(Color.Black), new Rectangle(snake[0], new Size(4, 4)));
this.Invalidate();
System.Threading.Thread.Sleep(500);
//this.Refresh();
break;
case Keys.Right:
this.graphics.Clear(Color.Green);
snake[0].X += 4;
graphics.DrawEllipse(new Pen(new SolidBrush(Color.Black)), new Rectangle(snake[0], new Size(4, 4)));
graphics.FillEllipse(new SolidBrush(Color.Black), new Rectangle(snake[0], new Size(4, 4)));
this.Invalidate();
System.Threading.Thread.Sleep(500);
//this.Refresh();
break;
}
}
private void Form1_KeyDown(object sender, KeyEventArgs e)
{
moveSnake(e);
this.Refresh();
}
private void Form1_KeyPress(object sender, KeyPressEventArgs e)
{
MessageBox.Show(e.KeyChar.ToString());
}
protected override void OnKeyPress(KeyPressEventArgs e)
{
base.OnKeyPress(e);
MessageBox.Show(e.KeyChar.ToString());
}
}
you need a timer on the form and for every tick move in last direction one square.
With this you can speed up the snake a higher difficulty.
Instead of having Form1_KeyDown processing the keystroke immediately using moveSnake, store the keystroke value in a form level variable then process it with moveSnake using a timer.
Also get rid with the System.Threading.Thread.Sleep(500); in the moveSnake

Categories

Resources