|
-
Dec 14th, 2008, 08:44 PM
#1
Thread Starter
Frenzied Member
[RESOLVED] [2.0] Analog clock?
Always wanted to learn about cos/sin so I am trying to make an analog clock. The problem is more in the GDI+ then the actual clock. This is what I am using.
Code:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
namespace Analog_Clock
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
const int HourLength = 100;
const int MinuteLength = 150;
const int SecondLength = 200;
bool MyDisposed = false;
void MyPaint()
{
Graphics maing = Graphics.FromHwnd(SafeGetHandle());
Bitmap backbuffer = new Bitmap(this.Width, this.Height);
Graphics g = Graphics.FromImage(backbuffer);
float centerx = this.Width / 2;
float centery = this.Height / 2;
g.Clear(Color.Black);
//Draw the hour hand
int hour = DateTime.Now.Hour % 12;
g.DrawLine(new Pen(Color.Red, 3), centerx, centery, centerx + (float)(HourLength * Degrees.Cos((hour * 30) - 90)), centery + (float)(HourLength * Degrees.Sin((hour * 30) - 90)));
//Draw the minute hand
int minute = DateTime.Now.Minute;
g.DrawLine(new Pen(Color.Red, 2), centerx, centery, centerx + (float)(MinuteLength * Degrees.Cos((minute * 6) - 90)), centery + (float)(MinuteLength * Degrees.Sin((minute * 6) - 90)));
//Draw the second hand
int second = DateTime.Now.Second;
g.DrawLine(new Pen(Color.Red, 1), centerx, centery, centerx + (float)(SecondLength * Degrees.Cos((second * 6) - 90)), centery + (float)(SecondLength * Degrees.Sin((second * 6) - 90)));
//Draw the millisecond hand for fun
int milli = DateTime.Now.Millisecond;
g.DrawLine(new Pen(Color.Red, 1), centerx, centery, centerx + (float)(20 * Degrees.Cos((milli * .36) - 90)), centery + (float)(20 * Degrees.Sin((milli * .36) - 90)));
maing.DrawImageUnscaled(backbuffer, 0, 0);
}
public IntPtr SafeGetHandle()
{
if (this.InvokeRequired)
return (IntPtr)this.Invoke(new SafeGetHandleD(SafeGetHandle));
return this.Handle;
}
public delegate IntPtr SafeGetHandleD();
private void Form1_Load(object sender, EventArgs e)
{
System.Timers.Timer t = new System.Timers.Timer(10);
t.Elapsed += new System.Timers.ElapsedEventHandler(t_Elapsed);
t.Start();
}
void t_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
{
MyPaint();
}
private void Form1_Paint(object sender, PaintEventArgs e)
{
MyPaint();
}
}
}
How should I do the back buffer? Also the error is on
return (IntPtr)this.Invoke(new SafeGetHandleD(SafeGetHandle));
when I close the app.
I tried adding ifs about this.IsDisposed. But it is false when it gets called.
Last edited by high6; Dec 14th, 2008 at 10:34 PM.
-
Dec 14th, 2008, 09:02 PM
#2
Re: [2.0] Analog clock?
You aren't disposing your Graphics objects for a start, which is bad. You should create a Graphics object with a Using block.
Also, I don't understand what that SafeHandle stuff is for. Just use the form's CreateGraphics method, which is thread-safe by design.
-
Dec 14th, 2008, 09:07 PM
#3
Thread Starter
Frenzied Member
Re: [2.0] Analog clock?
 Originally Posted by jmcilhinney
You aren't disposing your Graphics objects for a start, which is bad. You should create a Graphics object with a Using block.
Also, I don't understand what that SafeHandle stuff is for. Just use the form's CreateGraphics method, which is thread-safe by design.
I put paint in a timer so its a cross thread.
And what do you mean by using block?
-
Dec 14th, 2008, 09:11 PM
#4
Re: [2.0] Analog clock?
What you should really be doing is declaring a method that takes a Graphics object as an argument and then draws your Bitmap onto its canvas. You can then call that method from the Paint event handler and pass e.Graphics or from a background thread and pass the result of CreateGraphics, e.g.
vb.net Code:
Public Class Form1 Private WithEvents alarm As New Timers.Timer Private Sub Form1_Paint(ByVal sender As Object, _ ByVal e As PaintEventArgs) Handles Me.Paint Me.Draw(e.Graphics) End Sub Private Sub alarm_Elapsed(ByVal sender As Object, _ ByVal e As Timers.ElapsedEventArgs) Handles alarm.Elapsed Using g As Graphics = Me.CreateGraphics() Me.Draw(g) End Using End Sub Private Sub Draw(ByVal g As Graphics) Dim picture As New Bitmap(Me.Width, Me.Height) Using canvas As Graphics = Graphics.FromImage(picture) '... End Using g.DrawImage(picture, Point.Empty) End Sub End Class
-
Dec 14th, 2008, 09:13 PM
#5
Re: [2.0] Analog clock?
Ah, bummer! I just realised we're in the C# forum. The principle is the same though and C# supports 'using' statements too.
 Originally Posted by high6
I put paint in a timer so its a cross thread.
As I said, and as the documentation says, CreateGraphics is thread-safe already so it's OK to call it form any thread you like.
-
Dec 14th, 2008, 09:19 PM
#6
Re: [2.0] Analog clock?
Here's the C# code:
CSharp Code:
private System.Timers.Timer ticker = new System.Timers.Timer(); private void Form1_Load(object sender, EventArgs e) { this.ticker.AutoReset = true; this.ticker.Interval = 1000; this.ticker.Elapsed += new System.Timers.ElapsedEventHandler(ticker_Elapsed); } private void Form1_Paint(object sender, PaintEventArgs e) { this.Draw(e.Graphics); } private void ticker_Elapsed(object sender, System.Timers.ElapsedEventArgs e) { using (Graphics g = this.CreateGraphics()) { this.Draw(g); } } private void Draw(Graphics g) { Bitmap picture = new Bitmap(this.Width, this.Height); using (Graphics canvas = Graphics.FromImage(picture)) { // ... } g.DrawImage(picture, Point.Empty); }
-
Dec 14th, 2008, 10:34 PM
#7
Thread Starter
Frenzied Member
Re: [2.0] Analog clock?
cool thanks .
also had to add
if (this.IsDisposed)
return;
to the timer.
-
Dec 14th, 2008, 10:48 PM
#8
Re: [2.0] Analog clock?
 Originally Posted by high6
cool thanks  .
also had to add
if (this.IsDisposed)
return;
to the timer.
No, that's not right. The Timer should not be raisoing any Elapsed events if the form's disposed because you should be stopping the Timer when the form's closed, i.e. in its FormClosed event handler. In fact, you should be disposing the Timer too.
It's possible that that might still leave a tiny chance of an issue though, so maybe FormClosing would be safer.
-
Dec 14th, 2008, 10:55 PM
#9
Thread Starter
Frenzied Member
Re: [RESOLVED] [2.0] Analog clock?
Ya, I changed it to a thread now although now I get lower errors.
Code:
System.Threading.Thread t = new System.Threading.Thread(t_Elapsed);
t.Start();
void t_Elapsed()
{
using (Graphics g = this.CreateGraphics())
{
while (!this.IsDisposed)
{
MyPaint(g);
}
}
}
With the timer I was only get 60fps max. With the thread I get 400+.
although when closing I got this
"A generic error occurred in GDI+."
on
maing.DrawImageUnscaled(backbuffer, Point.Empty);
-
Dec 14th, 2008, 11:10 PM
#10
Re: [RESOLVED] [2.0] Analog clock?
Why would you need 400+ refreshes per second? A clock is only going to change it's display once every second so I would think that even 60 refreshes per second is excessive.
-
Dec 14th, 2008, 11:14 PM
#11
Thread Starter
Frenzied Member
Re: [RESOLVED] [2.0] Analog clock?
I was just testing the framerate of GDI+.
Posting Permissions
- You may not post new threads
- You may not post replies
- You may not post attachments
- You may not edit your posts
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|