Drawing rectangle does not work in Windows Forms - c#

The program should draw a rectangle on click. But it does not. Maybe some problem with my understanding of delegates. What's the catch?
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Windows.Forms;
namespace forms1
{
public partial class MainForm : Form
{
public MainForm()
{
//
// The InitializeComponent() call is required for Windows Forms designer support.
//
InitializeComponent();
//this.Paint+= new PaintEventHandler(MujPaintHandler);
this.Click += new EventHandler(MujClickHandler);
}
public void MujPaintHandler(object sender,PaintEventArgs e)
{
Graphics gfx=e.Graphics;
gfx.FillRectangle(new SolidBrush(Color.DarkViolet),100,100,200,200);
}
public void MujClickHandler(object sender,EventArgs e)
{
this.Text="aaaaa";
this.Paint+= new PaintEventHandler(MujPaintHandler);
}
}
}

The code you've written works for me, but your form's window has to be big enough to show the rectangle.
Diagnostically, the first thing I'd check is whether the title of the form changes to "aaaaa". If it does, then you know the click handler is being called - but maybe you've got a problem with the paint handler. If it doesn't, then for some reason your click handler isn't being called.
Note that this isn't the normal way you'd draw a rectangle on a click in Windows Forms, but I'm assuming this is just a learning exercise.

Try forcing a redraw after assigning the event handler:
public void MujClickHandler(object sender,EventArgs e)
{
this.Text="aaaaa";
this.Paint+= new PaintEventHandler(MujPaintHandler);
this.Invalidate();
}
Also, if you click twice, the event handler gets assigned twice, which is not something you want.

Maybe you have to force a redraw. Does the rect appear if you move the window? Just call the PaintHandler after click.

I think you are only attaching the Paint event handler. You are not invoking the Paint event.
Try this
public void MujClickHandler(object sender,EventArgs e)
{
this.Text="aaaaa";
this.Paint+= new PaintEventHandler(MujPaintHandler);
this.Invalidate();
}

It will only draw the rectangle if it happens to be inside the area that is invalidated to update the text that you change.
When you change the text, it creates a message that the text has to be redrawn, which will call the Paint event to do the drawing. The event will have a Graphics object that is clipped to the rectangle that needs to be redrawn to update the text, so only the part of the rectangle that intersects with the text will be drawn.
You have to cause a redraw that covers the entire rectangle, so the easiest is to cause the whole window to be redrawn:
this.Invalidate();
Note that you should not hook up the Paint event from the Click event handler. That means that the event will be hooked up one more time each click, so after five clicks the Paint event handler will be called five times every time something needs to be redrawn.

Looking at your code, I understand that you are trying to add an eventhandler for paint event on Click... You would also need to invoke the paint event.. Here is a sample code where I am assigning the Paint EventHandler on a button click and raising the paint event on the click as you are doing
public Form1()
{
InitializeComponent();
this.Click += new EventHandler(MujClickHandler);
}
private void Form1_KeyDown(object sender, KeyEventArgs e)
{
if (e.KeyCode == Keys.ControlKey)
{
MessageBox.Show(e.KeyCode.ToString());
}
}
private void Form1_Load(object sender, EventArgs e)
{
//this.Paint += new PaintEventHandler(MujPaintHandler);
}
public void MujPaintHandler(object sender,PaintEventArgs e)
{
Graphics gfx=e.Graphics;
gfx.FillRectangle(new SolidBrush(Color.DarkViolet),100,100,200,200);
}
public void MujClickHandler(object sender,EventArgs e)
{
this.Text="aaaaa";
this.RaisePaintEvent(this, new PaintEventArgs(this.CreateGraphics(), this.RectangleToClient(new Rectangle())));
}
private void button1_Click(object sender, EventArgs e)
{
this.Paint += new PaintEventHandler(MujPaintHandler);
}

Related

Drawing Graphics not working on Form load event

private void DrawIt()
{
System.Drawing.Graphics graphics = this.CreateGraphics();
System.Drawing.Rectangle rectangle = new System.Drawing.Rectangle(
50, 50, 150, 150);
graphics.DrawRectangle(System.Drawing.Pens.Red, rectangle);
}
private void Form1_Load(object sender, EventArgs e)
{
DrawIt();
}
private void button1_Click(object sender, EventArgs e)
{
DrawIt();
}
when putting the 'DrawIt' method in a button event it works, but in a form load event it doesn't, why?
Change Load event to Paint.
If you want redraw your form use this.Refresh();
When you are in Paint method use:
private void mForm_Paint(object sender, PaintEventArgs e)
{
e.Graphics.FillEllipse(...);
}
The Load event is run before the Form is drawn. So anything you draw is overwritten by the Form.
Call your DrawIt method from an event which fires after the Form has loaded.
You need to an event to trigger DrawIt(). You can use a panel or sth else. Then write an OnClik event. Your drawing will start after a click.
if vb6 just add call to your sub or function in Form_Activate
Instead of using Form_Load event use Form_Shown event. That should work.

C# PictureBox and Timer don't work together

so I am trying to make a simple game in C# using PictureBox for painting and timer for update functions, but what I noticed is that when I start painting on my picturebox my timer stops working.. I have no idea why..
Here is the picturebox code:
private void pictureBox1_Paint(object sender, PaintEventArgs e)
{
Console.WriteLine("PicBox running!");
if (this.MyGame.InGame)
{
this.pictureBox1.Refresh();
e.Graphics.Clear(Color.White);
MyGame.CurrentMap.Draw(e.Graphics);
//e.Graphics.Dispose(); <- if I uncomment this, then the whole programm just freezes
}
}
Here is the timer code:
private void timer1_Tick(object sender, EventArgs e)
{
Console.WriteLine("Timer running!");
if (this.MyGame.InGame)
{
MyGame.CurrentMap.Update();
MyGame.UpdateTime();
}
}
Here is a method called by MyGame.CurrentMap.Draw(e.Graphics); :
public void Draw(Graphics g)
{
foreach(Planet item in Entities){
item.Draw(g);
}
}
Any help would be greately appreciated. I come from javascript, so I don't really know if I am doing something terribly wrong here.
When a timer tick occurs, you want to repaint your PictureBox. To do this, you should make it so that the PictureBox receives a Paint event. This is what Refresh() does, so the call to this.pictureBox1.Refresh(); goes in the end of timer1_Tick.
It doesn't make sense for the Paint event to contain a call to Refresh, because this, in turn, generates a Paint event.

MouseUp Event Error

I am new to WinForms events and I am getting a strange error.Well I write when I start my control:
this.MouseUp += MouseUpMethod;
But the problem is, when I release the mouse button out of my control, the program recognize as I release the mouse over the Control. I am not able to understand this error.
Did ever someone got this error?
It's because, by default, your control captures mouse. Just set Control.Capture to false somewhere in your MouseDown event handler, for example:
void MouseDown(object sender, MouseEventArgs e) {
this.Capture = false;
}
As alternative just check in MouseUp that mouse is still inside your control:
void MouseUp(object sender, MouseEventArgs e) {
if (ClientRectangle.Contains(PointToClient(Cursor.Position))) {
// Your code here
}
}
see, you need to associate event with event handler just after your InitializeComponent()
public Form1()
{
InitializeComponent();
this.button2.MouseUp += new System.Windows.Forms.MouseEventHandler(this.button2_MouseUp);
}
then your event handler should be
private void button2_MouseUp(object sender, MouseEventArgs e)
{
//Do stuff here
}

Mouse events not fired

I'm making a C# WinForms application. The MouseMove and MouseClick events of the form aren't getting fired for some reason. (I'm probably going to feel like an idiot when I find out why.)
It is a transparent form (TransparencyKey is set to the background colour) with a semi-transparent animated gif in a Picture Box. I am making a screensaver.
Any suggestions?
EDIT:
MainScreensaver.cs
Random randGen = new Random();
public MainScreensaver(Rectangle bounds)
{
InitializeComponent();
this.Bounds = Bounds;
}
private void timer1_Tick(object sender, EventArgs e)
{
Rectangle screen = Screen.PrimaryScreen.Bounds;
Point position = new Point(randGen.Next(0,screen.Width-this.Width)+screen.Left,randGen.Next(0,screen.Height-this.Height)+screen.Top);
this.Location = position;
}
private void MainScreensaver_Load(object sender, EventArgs e)
{
Cursor.Hide();
TopMost = true;
}
private Point mouseLocation;
private void MainScreensaver_MouseMove(object sender, MouseEventArgs e)
{
if (!mouseLocation.IsEmpty)
{
// Terminate if mouse is moved a significant distance
if (Math.Abs(mouseLocation.X - e.X) > 5 ||
Math.Abs(mouseLocation.Y - e.Y) > 5)
Application.Exit();
}
// Update current mouse location
mouseLocation = e.Location;
}
private void MainScreensaver_KeyPress(object sender, KeyPressEventArgs e)
{
Application.Exit();
}
private void MainScreensaver_Deactive(object sender, EventArgs e)
{
Application.Exit();
}
private void MainScreensaver_MouseClick(object sender, MouseEventArgs e)
{
Application.Exit();
}
Excerpt from MainScreensaver.Designer.cs InitialiseComponent()
this.MouseClick += new System.Windows.Forms.MouseEventHandler(this.MainScreensaver_MouseClick);
this.MouseMove += new System.Windows.Forms.MouseEventHandler(this.MainScreensaver_MouseMove);
This isn't an answer to you question, but I'm leaving this answer in case anyone else stumbles upon this question while trying to debug this same issue (which is how I got here)
In my case, I had a class that was derived from Form.
I was also using TransparencyKey.
Some things I noticed
The events will not fire on the transparent parts of the form.
The events will not fire if the mouse cursor is over another control on the form.
The events will not fire if you override WndProc and set the result of a WM_NCHITTEST message. Windows doesn't even send out the corresponding mouse messages that would cause the .NET events.
My Solution
In my constructor, I had forgotten to call InitializeComponent().
Which was where the event handlers were being bound to my controls.
Events were not firing because the handlers were not being bound.
Are you sure that your form has focus? If your form does not have focus, the mouse events will not be fired.

Invalidating again and again Windows Forms

I am using this code to draw some circles but it keeps redrawing and redrawing and stops with error that textBox1.text has bad number format even when I try 5 or 6. What is wrong with this?
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Windows.Forms;
using System.Drawing.Drawing2D;
namespace terc
{
/// <summary>
/// Description of MainForm.
/// </summary>
public partial class MainForm : Form
{
public MainForm()
{
//
// The InitializeComponent() call is required for Windows Forms designer support.
//
InitializeComponent();
//
// TODO: Add constructor code after the InitializeComponent() call.
//
}
void Button1Click(object sender, EventArgs e)
{
this.Paint += new PaintEventHandler(KresliTerc);
}
protected void KresliTerc(object sender,PaintEventArgs e)
{
Graphics grfx = e.Graphics;
int pocet = int.Parse(textBox1.Text);
label1.Text = pocet.ToString();
for(int i=1; i <= pocet; i++)
{
grfx.FillEllipse(Brushes.Black,ClientSize.Width/2,ClientSize.Height/2,50*i,50*i);
Invalidate();
}
}
}
}
Why do you attach the event handler each time that the button is clicked? This means that you will have as many event handlers as button clicks, which is I doubt is what you want.
However, your repaint problem is probably the fact that you call Invalidate inside the Paint event handler. This will force a new repaint of the form. So for each time that you paint, you will trigger a new paint, which will trigger a new paint and so on.
You should not invalidate in a Paint call.
Handle the painting based on some integer or boolean values.
Set the integer or boolean values in click events and just call Invalidate in the button click handler.
this.Paint += new PaintEventHandler(KresliTerc);
where are you calling this , since it is a paint event it will call again and again when painting occurs
Boolean isButtonClicked;
protected override void OnPaint(PaintEventArgs e)
{
if (this.isButtonClicked)
{
this.isButtonClicked = false;
// some paint logic goes down here...
e.Graphics.FillEllipse(Brushes.YellowGreen, 12, 12, 54, 54);
}
}
private void HandleOnButtonClick(Object sender, EventArgs e)
{
this.isButtonClicked = true;
this.Invalidate();
}

Categories