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.
Related
I have a pictureBox and a button on my form. Button is just refreshing pictureBox. When pictureBox is refreshing it’s drawing line at the pictureBox.
private void button_Click(object sender, EventArgs e)
{
pictureBox.Refresh();
}
And i set OnPaint event for my PictureBox, so when my pictureBox is redrawing its call this method:
private void pictureBox1_Paint(object sender, PaintEventArgs e)
{
//logic for drawing line
//its not so important, cause even if i put messagebox.show, result is the same.
}
I spend whole day to figure out why after pressing the button, line is not appear at the picture box. Turns out that program do like that:
1) button_click -> 2)pictureBox_Paint -> 3) button_click (again!!)
How its even possible? What should i do to just implement logic:
1) button_click -> 2)pictureBox_Paint
I want to update some graphical rendering based on the form's position as I drag the form with the mouse.
Since the form is border-less, I am using ReleaseCapture and SendMessage to move it.
However, I am not able to do my calls during the dragging operation.
I suppose it is possible to spawn a thread that runs until SendMessage returns a value, however I wanted to ask if there is a native method for this particular problem?
public void MoveWindow()
{
ReleaseCapture();
SendMessage(Handle, WM_NCLBUTTONDOWN, HT_CAPTION, 0);
....
}
Best regards
You can use events of form which raise at start, during and at the end of movement:
Use Move event of form to do something during form movement.
Use ResizeBegin event of the form to do a job at start of movement.
Use ResizeEnd event of the form to do a job at the end of movement.
Example
private void Form1_Move(object sender, EventArgs e)
{
this.BackColor = this.Left/10 % 2 == 0 ? Color.Red : Color.Blue;
}
private void Form1_ResizeBegin(object sender, EventArgs e)
{
this.Text = this.Location.ToString();
}
private void Form1_ResizeEnd(object sender, EventArgs e)
{
this.Text = this.Location.ToString();
}
I am a complete beginner in C# so please be gentle if it's a stupid problem :D
I have created OnTouchFrameReported method on one frame but function fires on every screen i go from there have i done something wrong ???
I can handle this problem by checking witch frame is on... but problem is now in emulator after this method is fired and i leave the frame my button clicks and other metods take 3-4s to fire... i culd use your help here guys i am realy stuck :D
XAML is irrelevant in this case and code-behind
void OnTouchFrameReported(object sender, TouchFrameEventArgs args)
{
try
{
this.SetCrop(args.GetTouchPoints(this.SourceImg));
}
catch (ArgumentException)
{
}
}
I ran into a similar problem recently. What I did was remove the method from Touch.FrameReported whenever I was not dealing with the frame I wanted simply by doing:
Touch.FrameReported -= OnTouchFrameReported;
I know you don't want to involve XAML but I created a mouseLeftButtonDown and MouseLeftButtonUp event for the control I was working with and added and removed the touch frame reported method respectively.
XAML
<Image MouseLeftButtonDown="mouseDown" MouseLeftButtonUp="mouseUp"/>
Code
public void mouseDown(object sender, MouseButtonEventArgs m)
{
Touch.FrameReported += OnTouchFrameReported;
}
public void mouseUp(object sender, MouseButtonEventArgs m)
{
Touch.FrameReported -= OnTouchFrameReported;
}
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);
}
I have a strange bug, please, let me know if you have any clues about the reason.
I have a Timer (System.Windows.Forms.Timer) on my main form, which fires some updates, which also eventually update the main form UI. Then I have an editor, which is opened from the main form using the ShowDialog() method. On this editor I have a PropertyGrid (System.Windows.Forms.PropertyGrid).
I am unable to reproduce it everytime, but pretty often, when I use dropdowns on that property grid in editor it gets stuck, that is OK/Cancel buttons don't close the form, property grid becomes not usable, Close button in the form header doesn't work.
There are no exceptions in the background, and if I break the process I see that the app is doing some calculations related to the updates I mentioned in the beginning.
What can you recommend? Any ideas are welcome.
What's happening is that the thread timer's Tick method doesn't execute on a different thread, so it's locking everything else until it's done. I made a test winforms app that had a timer and 2 buttons on it whose events did this:
private void timer1_Tick(object sender, EventArgs e)
{
Thread.Sleep(6000);
}
private void button1_Click(object sender, EventArgs e)
{
timer1.Start();
}
private void button2_Click(object sender, EventArgs e)
{
frmShow show = new frmShow();
show.ShowDialog(); // frmShow just has some controls on it to fiddle with
}
and indeed it blocked as you described. The following solved it:
private void timer1_Tick(object sender, EventArgs e)
{
ThreadPool.QueueUserWorkItem(DoStuff);
}
private void DoStuff(object something)
{
Thread.Sleep(6000);
}