I want to obtain the height and width properties of a winforms form to be able to color all of it?
I've tried this code..
private void Form1_Load(object sender, EventArgs e)
{
using (Graphics g = this.CreateGraphics())
{
Rectangle r=this.DisplayRectangle;
g.DrawRectangle(Pens.Black, new Rectangle(0, 0, r.X, r.Y));
}
}
But it doesn't do the job. How do I color the whole form in black with the graphics object and Rectangle object?
If you do like that, you will just be painting on the screen where the window happens to be. The window is not aware of that, and when the window is updated for any reason it will be redrawn without the color.
Use the Paint event to draw graphics on the window. Add an event handler for the event, and it will be called whenever the window has to be redrawn. The event arguments contains a Graphics object that you should use for drawing.
Use the Width and Height properties of the DisplayRectangle as width and height, not the X and Y properties. However, as the Graphics object is clipped to the area that is to be updated, you could just use the Clear method to fill it with a color.
I have two buttons on my form(in design view) button1_Click is to paint it black, and button2_Click is to paint form back to Control color.
public partial class Form2 : Form
{
private Brush brushToPaint;
public Form2()
{
InitializeComponent();
brushToPaint = SystemBrushes.Control;
}
protected override void OnPaint(PaintEventArgs e)
{
e.Graphics.FillRectangle(brushToPaint, this.DisplayRectangle);
}
private void button1_Click(object sender, EventArgs e)
{
brushToPaint = Brushes.Black;
InvokePaint(this, new PaintEventArgs(this.CreateGraphics(), this.DisplayRectangle));
}
private void button2_Click(object sender, EventArgs e)
{
brushToPaint = SystemBrushes.Control;
InvokePaint(this, new PaintEventArgs(this.CreateGraphics(), this.DisplayRectangle));
}
}
Do you have to do this using Graphics and DisplayRectangle?
The form has a property called BackColor, which you could simply set to black:
private void Form1_Load(object sender, EventArgs e)
{
this.BackColor = Color.Black;
}
Related
Using panel as a selection indicator . The panel changes its size according to cursor position on MouseMove event . However when I draw the border as below , previous borders leave their mark on the panel and it displays too many border within same panel . Even tried refresh() before every draw but that makes it glitchy and slow
private void panel1_Paint(object sender, PaintEventArgs e)
{
this.panel1.Refresh();
ControlPaint.DrawBorder(e.Graphics, this.panel1.ClientRectangle, Color.DarkBlue, ButtonBorderStyle.Solid);
}
private void drawboard_MouseMove(object sender, MouseEventArgs e)
{
panel1.Width = e.Location.X - panel1.Left;
panel1.Height = e.Location.Y - panel1.Top;
}
First off, you should never call control paint affecting methods like Invalidate or Refresh inside the control paint handler.
You can solve the original issue by calling Invalidate or Refresh after modifying the size of the panel. Note that it's better to set the Size property with one call rather than Width and Height separately:
private void panel1_Paint(object sender, PaintEventArgs e)
{
ControlPaint.DrawBorder(e.Graphics, this.panel1.ClientRectangle, Color.DarkBlue, ButtonBorderStyle.Solid);
}
private void drawboard_MouseMove(object sender, MouseEventArgs e)
{
var size = new Size(Math.Max(e.Location.X - panel1.Left, 0),
Math.Max(e.Location.Y - panel1.Top, 0));
if (panel1.Size != size)
{
panel1.Size = size;
panel1.Invalidate();
}
}
A better option is to set ResizeRedraw property of the selection panel to true. Since it's a protected property, you need to create and use your own Panel subclass. As a bonus, you can also set DoubleBuffered property to true to avoid the flickering, and also move the painting code inside:
class SelectionBox : Panel
{
public SelectionBox()
{
ResizeRedraw = true;
DoubleBuffered = true;
}
protected override void OnPaint(PaintEventArgs e)
{
base.OnPaint(e);
ControlPaint.DrawBorder(e.Graphics, ClientRectangle, Color.DarkBlue, ButtonBorderStyle.Solid);
}
}
Make your panel1 to be SelectionBox, remove the Paint event handler, and then the mouse move handler could be simple
private void drawboard_MouseMove(object sender, MouseEventArgs e)
{
panel1.Size = new Size(Math.Max(e.Location.X - panel1.Left, 0),
Math.Max(e.Location.Y - panel1.Top, 0));
}
I want when I click button, add one rectangle to the form
I can add in form paint how much I want but I can't add shape like rectangle by click button and I searched about it but I didn't find a solution for it
is here somebody know how to do it?
This is my code in form paint
private void Form1_Paint(object sender, PaintEventArgs e)
{
locationX = locationX + 20;
locationY = locationY + 20;
e.Graphics.DrawRectangle(Pens.Black,
new Rectangle(10 + locationX, 10 + locationY, 50, 30));
}
and this one is my button code
private void button1_Click(object sender, EventArgs e)
{
this.Paint += Form1_Paint;
}
but its not working when I click button. why its not working?
The line
this.Paint += Form1_Paint;
Associate the event Paint of your Form to your function Form1_Paint. It doesn't trigger it. This is something you want to do only 1 time, not everytime you hit a button.
To trigger the Paint event, the usual way is to call the Invalidate() method of the Form class. In fact, Invalidate is a method of Control. But Form derivate from Control, so we have access to the method in Form too.
So the right way to trigger a repaint in Windows Forms is to put the subscribe in the Load method :
private void Form1_Load(object sender, EventArgs e)
{
this.Paint += Form1_Paint;
}
It should already be hidden in the auto generated code.
Your method Form1_Paint is ok.
Finally, the button click method should be :
private void button1_Click(object sender, EventArgs e)
{
this.Invalidate(); // force Redraw the form
}
From the doc :
Invalidate() : Invalidates the entire surface of the control and causes the control to be redrawn.
Edit :
With this method, you can draw only 1 rectangle at a time, because the whole surface is redrawn, so the surface is completly erase, and then it draws only what you asked in the Form1_Paint method.
For the answer on how to draw multiple rectangles, you should create a List of Rectangle. At each click button, you add a Rectangle to the list, and you redraw all the rectangles.
List<Rectangle> _rectangles = new List<Rectangle>();
private void button1_Click(object sender, EventArgs e)
{
locationX = locationX + 20;
locationY = locationY + 20;
var rectangle = new Rectangle(locationX, locationY, 50, 30));
this._rectangles.Add(rectangle);
this.Invalidate(); // force Redraw the form
}
private void Form1_Paint(object sender, PaintEventArgs e)
{
foreach(var rectangle in this._rectangles)
{
e.Graphics.DrawRectangle(Pens.Black, rectangle);
}
}
to call a method you need the parenthesys.
private void button1_Click(object sender, EventArgs e)
{
Form1_Paint(sender, e);
}
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
Bitmap b = new Bitmap(#"F:\face.jpeg");
Graphics g = this.CreateGraphics();
g.DrawImage(b, 20, 30);
}
}
Image doesn't load with the form.
What is the reason for this? And, how can i do this?
Because it's not a proper way to draw in WinForms. Move your draw code to OnPaint() method like this:
protected override void OnPaint(PaintEventArgs e)
{
base.OnPaint(e);
e.Graphics.DrawImage(bmp, 20, 30);
}
Of course it's fine to load the bitmap earlier.
Use Paint event... Refer Form graphics not set when form loads
I want to create two picture boxes, overlapping.
The first Picturebox is used as the background, the picture of the screen.
using this method:
public void BckShow()
{
Rectangle rect = Screen.GetBounds(this);
gBackImg = Graphics.FromImage(bBackImg);
gBackImg.CopyFromScreen(0,0,0,0,
Screen.PrimaryScreen.Bounds.Size,
CopyPixelOperation.SourceCopy);
}
The second picturebox is above the first one, a transparent picture box that can be drawn using this mouse event:
public void Draw(bool draw, Point sp, Point ep)
{
if (draw)
{
gCanvas.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias;
pen = new Pen(new SolidBrush(ColorName), BrushSize);
if (toolPen.Checked)
{
gCanvas.DrawLine(pen, sp, ep);
}
else if (toolEreser.Checked)
{
Rectangle rect = new Rectangle(ep.X, ep.Y, BrushSize*5, BrushSize*5);
gCanvas.DrawEllipse(pen, rect);
gCanvas.FillEllipse(new SolidBrush(ColorName), rect);
}
bCanvas.MakeTransparent(Color.White);
pbxCanvas.Refresh();
dirty = true;
toolSave.Enabled = true;
}
}
private void pbxCanvas_MouseDown(object sender, MouseEventArgs e)
{
sp = e.Location;
if (e.Button == MouseButtons.Left)
{
ActivePaint = true;
}
}
private void pbxCanvas_MouseUp(object sender, MouseEventArgs e)
{
ActivePaint = false;
}
private void pbxCanvas_MouseMove(object sender, MouseEventArgs e)
{
ep = e.Location;
Draw(ActivePaint, sp, ep);
sp = ep;
}
but when i run the program, the second PictureBox does not draw anything when the mouse event was fired. how i can fix this?
I do this because I just want to save the image in the second picture box. Unlike PrintScreen but seemed to make notes on the screen and save the image apart from the screen image.
Is there another way to do this? like using controls other than picture box, or may directly use the screen as a background but still can save the image in the transparent PictureBox separately.
This is the example I want to achieve:
when drawing:
results stored images:
I hope you all will help me to fix this. sorry for poor explanation.
this the document outline window for more detail:
It's likely that your surface being overdrawn by refresh. You should be tracking what you want to draw, and then drawing it in the picture box's Paint event. That way, you get handed a Graphics object and every refresh, you're drawing.
That's assuming, of course, that you have a valid, and correct, Graphics object in the first place.
BTW: passing a form-scope variable to Draw is confusing, just use it.
Check your gCanvas initializer, if it is used from within Paint event (e.Graphics), then your changes are lost when you call the Refresh() method. Refresh() causes a new Paint event to be fired, creating a new Graphics object and therefore invalidating yours.
Create a new graphics object from your PictureBox's Image to persist your changes permanently.
private List<Point> points = new List<Point>();
private void pbxCanvas_MouseDown(object sender, MouseEventArgs e) {
if (e.Button == MouseButtons.Left) {
ActivePaint = true;
}
}
private void pbxCanvas_MouseUp(object sender, MouseEventArgs e) {
ActivePaint = false;
points.Clear();
}
private void pbxCanvas_MouseMove(object sender, MouseEventArgs e) {
if (ActivePaint) {
points.Add(e.Location);
Refresh();
}
}
private void pbxCanvas_Paint(object sender, PaintEventArgs e) {
using (var graphics = Graphics.FromImage(pbxCanvas.Image)) {
for (int i = 0; i < points.Count - 1; i++) {
graphics.DrawLine(Pens.Black, points[i], points[i + 1]);
}
}
}
First I load an image in a picturebox. Then I measure the areas in it and create a new picture. Now I want to load the image in a panel and draw a line by mouse.
I added to my form:
private Image imag;
I also added to my project:
private void drawP_Paint(object sender, PaintEventArgs e)
{
Graphics g = drawP.CreateGraphics();
g.DrawImage(imag, new Point(0,0));
}
I set the image in a function:
imag = (Image)bm;
// or
imag = picturebox1.Image; // the made picture
drawP.Invalidate();
But nothing appears when running the project.
You should place your code in panel Paint event.
private void panel1_Paint(object sender, PaintEventArgs e)
{
Image imag = Image.FromFile(filename);
e.Graphics.DrawImage(imag, new Point(0,0));
}
This makes you sure that everytime panel is redrawn (after beeing invalidated for any reason) your image is visible.
Try changing it to this:
private void drawP_Paint(object sender, PaintEventArgs e)
{
e.Graphics.DrawImage(imag, new Point(0,0));
}
Also, from your comments, it sounds like you may not have the event wired up. Example:
public Form1()
{
InitializeComponent();
drawP.Paint += drawP_Paint;
}
To draw a line on that image:
private void button1_Click(object sender, EventArgs e) {
using (Graphics g = Graphics.FromImage(imag)) {
g.DrawLine(Pens.Red, new Point(0, 0), new Point(32, 32));
}
drawP.Invalidate();
}