I am now drawing to a panel some dots to indicate a sort of dotted grid with 1% of margin of total panel width.
This is what I am doing now:
private void panel1_Paint(object sender, PaintEventArgs e)
{
Pen my_pen = new Pen(Color.Gray);
int x,y;
int k = 1 ,t = 1;
int onePercentWidth = panel1.Width / 100;
for (y = onePercentWidth; y < panel1.Height-1; y += onePercentWidth)
{
for (x = onePercentWidth; x < panel1.Width-1; x += onePercentWidth)
{
e.Graphics.DrawEllipse(my_pen, x, y, 1, 1);
}
}
}
What is bothering me is that when the app starts I can see the dots being drawn on the panel. Even if it is very quick it still bothers me a lot.
Is it possible to draw the dots on the panel and load it directly drawn?
Thank you for the help
You could create a bitmap and draw it instead.
But before you do that: DrawEllipse is a little expensive. Use DrawLine with a Pen that has a dotted linestyle instead:
int onePercentWidth = panel1.ClientSize.Width / 100;
using (Pen my_pen = new Pen(Color.Gray, 1f))
{
my_pen.DashStyle = System.Drawing.Drawing2D.DashStyle.Custom;
my_pen.DashPattern = new float[] { 1F, onePercentWidth -1 };
for (int y = onePercentWidth; y < panel1.ClientSize.Height - 1; y += onePercentWidth)
e.Graphics.DrawLine(my_pen, 0, y, panel1.ClientSize.Width, y);
}
Note that I am using using so I don't leak the Pen and ClientSize so I use only the inner width. Also note the exaplanation about the custom DashPattern on MSDN
Related
I need to create a WinForm application that allows the user to drag from a set of images, and position them on a grid, a tile designer of sorts.
I've tried using the TableLayoutPanel, however It seems to get rather slow when you have a grid 100x100, I was just wondering if there are any alternative methods out there that would allow the user to drag a tile onto the grid layout, and expand the size of the grid if they required.
Thank you.
If tiles are contiguous, you can get the first "empty cell"
private readonly Size tileSize = new Size(200, 200);
private void button1_Click(object sender, EventArgs e)
{
var pb = new PictureBox();
var pt = GetEmptyCell(tileSize);
pb.Location = pt;
pb.Size = tileSize;
Controls.Add(pb);
}
private Point GetEmptyCell(Size TileSize)
{
var ctrl = GetChildAtPoint(new Point(0, 0));
if (ctrl == null && TileSize.Width < Width && TileSize.Height < Height)
return new Point(0, 0);
for (int x = 0; x < Width; x++)
{
for (int y = 0; y < Height; y++)
{
ctrl = GetChildAtPoint(new Point(x, y));
if (ctrl == null && x + TileSize.Width < Width && y + TileSize.Height < Height)
return new Point(x, y);
}
}
throw new Exception("No Empty cells was found");
}
I have a jpeg image in a picturebox, on page load i am drawing the rectangle based on the x(150) and y(440) coordinates. now when i mousemove on the picturebox i need to identify the rectangle by their coordinates and highlight the image. for example see the below image ..
lets take the first rectangle, on mouse move any points inside the rectangle i need to perform some actions.. how to find the coordinates between these x and y for the rectangle?..
A rectangle has 4 Points (edges):
Left
Top
Right
Bottom
If your mouse coordinates (MouseEventArgs properties) are between them, the mouse pointer is in the rectangle.
Are the mouse coordinates greater than right or bottom or lower than left / top, your mouse is outside the rectangle.
Taking #samgak`s Comment:
if(
(point.x >= rectangle.min_x) && (point.x <= rectangle.max_x) &&
(point.y >= rectangle.min_y) && (point.y <= rectangle.max_y)) {
//do something
}
and replacing point with e is exactly what you want.
Maybe the following link will help to understand:
How to check if a point is inside a rectangle
Provided images are the same size and assuming it is stored in variable imageSize (of type System.Drawing.Size) then:
Size imageSize = new Size(...) // define the size here
...
int row = point.y / imageSize.height;
int col = point.x / imageSize.width;
var rect = new Rectangle(col * imageSize.Width, row * imageSize.Height, imageSize.Width, imageSize.Height);
You can then use rect to draw you frame around the image (you may want to inflate the rectangle by a couple of pixels)
Hi Samgak /Clijsters,
I have completed my functionality
// page level declaration
private Rectangle SelectedRect;
public List<Rectangle> listRec = new List<Rectangle>();
// on page load add all the rectangle in the rectanglelist.
private void Highlightimage_Load(object sender, EventArgs e)
{
for (int i = 0; i < table.Rows.Count; i++)
{
int x = Convert.ToInt32(table.Rows[i][0]);
int y = Convert.ToInt32(table.Rows[i][1]);
int width = Convert.ToInt32(table.Rows[i][2]);
int height = Convert.ToInt32(table.Rows[i][3]);
SelectedRect.Size = new Size(width, height);
SelectedRect.X = x;
SelectedRect.Y = y;
listRec.Add(SelectedRect);
}
}
// draw the rectangle
private void pictureBox1_Paint(object sender, PaintEventArgs e)
{ Graphics g = e.Graphics;
foreach (Rectangle rec in listRec)
{
Pen p = new Pen(Color.Red);
g.DrawRectangle(p, rec);
}
}
private Rectangle MakeRectangle(int x0, int y0, int x1, int y1)
{
return new Rectangle(
Math.Min(x0, x1),
Math.Min(y0, y1),
Math.Abs(x0 - x1),
Math.Abs(y0 - y1));
}
//finally on mouse move checking the condition
private void pictureBox1_MouseMove(object sender, MouseEventArgs e)
{
foreach (Rectangle rec in listRec)
{
SelectedRect = MakeRectangle(rec.Left, rec.Top, rec.Right, rec.Bottom);
if (
(e.X >= SelectedRect.Left) && (e.X <= SelectedRect.Right) &&
(e.Y >= SelectedRect.Top) && (e.Y <= SelectedRect.Bottom))
{
MessageBox.Show("test");
}
}
}
Also refered this link
Drawing Multiple Rectangles c#
I thought this will help some one.
Thanks
Dev
I am fully aware that I can load textures in OpenTK. But when I tried to render a picture using only points it shows really weird lines when ClientSize.Width is EXACTLY equal to the width of the picture being rendered. Like this:
And if I resize (enlarge) the ClientSize.Width of the window lines become kinda normal and there is actual reason they appear (they cover areas that can't be rendered):
This seems to occur regardless of the picture I open. Can somebody explain why there are lines in the first picture?
using System;
using System.Drawing;
using OpenTK;
using OpenTK.Graphics;
using OpenTK.Graphics.OpenGL;
namespace Miracle
{
class Program
{
public static void Main()
{
using (Window w = new Window())
w.Run(30);
}
}
class Window : GameWindow
{
private Color[,] pixels;
private int width, height;
private bool blink = true;
private int blinkcounter;
public Window() : base(1337, 666, GraphicsMode.Default, "Miracle", GameWindowFlags.Default) { }
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
Bitmap pic = new Bitmap("sample.png");
width = pic.Width;
height = pic.Height;
ClientSize = new Size(width, height);
pixels = new Color[width, height];
for (int x = 0; x < width; x++)
for (int y = 0; y < height; y++)
pixels[x, y] = pic.GetPixel(x, y);
GL.ClearColor(Color.FromArgb(0, 255, 0));
GL.Ortho(0, width, height, 0, -1, 1);
}
protected override void OnResize(EventArgs e)
{
base.OnResize(e);
Title = ClientSize.Width + "x" + ClientSize.Height + (ClientSize.Width == width && ClientSize.Height == height ? " (original)" : "");
GL.Viewport(ClientSize);
}
protected override void OnUpdateFrame(FrameEventArgs e)
{
base.OnUpdateFrame(e);
if (blinkcounter == 6)
{
GL.ClearColor(blink ? Color.FromArgb(255, 0, 0) : Color.FromArgb(0, 255, 0));
blink = !blink;
blinkcounter = 0;
}
blinkcounter++;
}
protected override void OnRenderFrame(FrameEventArgs e)
{
base.OnRenderFrame(e);
GL.Clear(ClearBufferMask.ColorBufferBit);
GL.MatrixMode(MatrixMode.Projection);
GL.Begin(PrimitiveType.Points);
for (int x = 0; x < width; x++)
for (int y = 0; y < height; y++)
{
GL.Color4(pixels[x, y]);
GL.Vertex2(x, y);
}
GL.End();
SwapBuffers();
}
}
}
I will describe a solution to your problem and also why I think you're getting the problem.
First, why I think you're getting the problem:
The rasterization of points is weird and hardware dependent. This problem looks to be an error of floating point accuracy in the rasterization stage for points. The projected point is on the boundary of choosing between 2 pixels, and it chooses the wrong one due to FP limitations.
Solution:
Rasterizing an image using points is NOT recommended. That's not what point rasterization is used for. Instead, rasterize a full screen quad, give each vertex of the quad a texture coordinate, and in the fragment shader use the interpolated texture coordinate to fetch from the texture storing the image you want to render. This avoids the problem you were experiencing with the GL_POINTS because it ensures every pixel is drawn to once.
So, I'm attempting to create a grid on the screen, and to do so, I've implemented a multidimensional array of Rectangles.
When the program starts, I use a for loop to increase the x and y coordinates to form the grid.
public Form1() {
InitializeComponent();
for (int x = 0; x < 12; x++) {
for (int y = 0; y < 12; y++) {
recArray[x, y] = new Rectangle(y * 50, x * 50, 100, 100);
}
Application.DoEvents();
}
}
My issue is trying to figure out when the user has clicked on a rectangle, and furthermore, which rectangle in the array that he/she has clicked on. As I will change the border to red when given the correct rectangle.
I'm using Visual Studio 2008, and here is my code so far.
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Linq;
using System.Text;
using System.Windows.Forms;
namespace Quoridor {
public partial class Form1 : Form {
private Pen pen = Pens.Black;
Rectangle[,] recArray = new Rectangle[12, 12];
public Form1() {
InitializeComponent();
for (int x = 0; x < 12; x++) {
for (int y = 0; y < 12; y++) {
recArray[x, y] = new Rectangle(y * 50, x * 50, 100, 100);
}
Application.DoEvents();
}
}
protected override void OnPaint(PaintEventArgs e) {
base.OnPaint(e);
for (int x = 0; x < 12; x++) {
for (int y = 0; y < 12; y++) {
e.Graphics.DrawRectangle(pen, recArray[x, y]);
Application.DoEvents();
}
}
}
private void Form1_Click(object sender, EventArgs e) {
Point cursor = this.PointToClient(Cursor.Position);
Refresh();
}
}
}
I'm making this into a real game, with classes and all. But keep in mind, this is my second month programming, so don't be harsh ^_^
First, a couple of pointers:
You are storing your calculated y coordinate as the x position of your rectangle and vice versa. Switch the first two arguments of the Rectangle constructor to resolve this.
Use the MouseClick event instead of the Click event. The former provides you with a MouseEventArgs that contains the coordinate of the click relative to your Form.
Your rectangles are currently overlapping, since they are 100 x 100 but are positioned 50 pixels apart. This appears to be unintended (as a click would then usually land on 2 rectangles). This is also why your grid appears to be 13x13 instead of 12x12. To resolve this, pass 50 instead of 100 as the width and height of your Rectangles.
You could then determine the clicked Rectangle as follows:
private void Form1_MouseClick(object sender, MouseEventArgs e)
{
Rectangle clickedRectangle = FindClickedRectangle(e.Location);
if (!clickedRectangle.IsEmpty)
Console.WriteLine("X: {0} Y: {1}", clickedRectangle.X, clickedRectangle.Y);
}
private Rectangle FindClickedRectangle(Point point)
{
// Calculate the x and y indices in the grid the user clicked
int x = point.X / 50;
int y = point.Y / 50;
// Check if the x and y indices are valid
if (x < recArray.GetLength(0) && y < recArray.GetLength(1))
return recArray[x, y];
return Rectangle.Empty;
}
Notice that I determine the clicked rectangle using a straightforward calculation, which is possible because your rectangles are positioned in a grid. If you intend to depart from the grid layout, looping over all rectangles and hit testing them using Rectangle.Contains(Point) is an alternative solution.
I have problem with my C# winform project.
I have function that draw squares:
public void DrawingSquares(int x, int y)
{
System.Drawing.Graphics graphicsObj;
graphicsObj = this.CreateGraphics();
Pen myPen = new Pen(System.Drawing.Color.Black, 5);
Rectangle myRectangle = new Rectangle(x, y, 100, 100);
graphicsObj.DrawRectangle(myPen, myRectangle);
}
private void button1_Click(object sender, EventArgs e)
{
z = Convert.ToInt16(textBox1.Text)-1;
k = Convert.ToInt16(textBox2.Text)-1;
DrawAllSquares();
}
private void DrawAllSquares()
{
int tempy = y;
for (int i = 0; i < z; i++)
{
DrawingSquares(x, y);
for (int j = 0; j < k - 1; j++)
{
tempy += 50;
DrawingSquares(x, tempy);
}
x += 50;
tempy = y;
}
}
In my project, I have a function that I use to move button around the form at runtime, but when the button is moved onto the drawing the drawing is deleted.
What can I do to make the drawing permanent?
If you need permanently (in terms of application life time), by any means, you need to use it inside you Control's (the Control where rectangle is have to be drawn), OnPaint method.
If you need an animation too: it could be resolved by using a timer and changing coordinates that you pass like a parameters to your DrawSquares.
Hope this helps.
EDIT
A pseudocode:
public class MyControl : Control
{
public override void OnPaint(PaintEventArgs e)
{
base.OnPaint(e);
DrawingSquares(e.Graphics, valueX, valueY);
}
public void DrawingSquares(Graphics graphicsObj, int x, int y)
{
Pen myPen = new Pen(System.Drawing.Color.Black, 5);
Rectangle myRectangle = new Rectangle(x, y, 100, 100);
graphicsObj.DrawRectangle(myPen, myRectangle);
}
}
valueX and valueY are relative X and Y coordinates where you want the rectangle to be drawn.
These coordinates can be constant values, or you can change them from some timer and call Invalidate() on MyControl, so paint will be executed.