473,394 Members | 1,887 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,394 software developers and data experts.

Graphics ... almost working ... missing one line?

I previously asked about two problems I had with some graphics - the first
was that when I drew animation to a picturebox it wouldn't display when the
Form loaded.

It was suggested to me by everyone that I stop using my own CreateGraphics
calls, and override an OnPaint call to do this. As suggested, I created a
custom control "drawBox" with an override on its OnPaint. Because I am using
manual double buffering, as people suggested it was really just a matter of
putting myBuffer.Render() into the OnPaint, and using drawBox.Invalidate as
the call. In the end I only had to change/add about 8 lines of code, and its
only taken about 16 hours to work out exactly which ones.

However, there is one annoying problem that remains. I can get it to show
the initial screen just fine when it loads. But what I really want it to do
is play the opening animation.

If I put the call to animate the screen

play_animation();

As the very last line of Form1_Load or anywhere else that I have tried, then
the Form1 doesn't actually load and show anything until the animation is
finished, at which point the Form pops up showing only the final (end) frame
of the animation.

I had the same problem with the old (bad) way I did graphics, so I assume
its not related ... but FWIW, here are they key parts of my new graphics:

public partial class Form1 : Form
{
static public drawBox pictureBoxn;

....

public class drawBox : Control
{
public drawBox()
{
this.Height = 600;
this.Width = 600;
}
protected override void OnPaint(PaintEventArgs pe)
{
base.OnPaint(pe);
myBuffer.Render();

}
}

I call the following in Form1_Load:

pictureBoxn = new drawBox();
currentContext = BufferedGraphicsManager.Current;
myBuffer =
currentContext.Allocate(pictureBoxn.CreateGraphics (),
pictureBoxn.DisplayRectangle);
this.Controls.Add(pictureBoxn);

canvas = myBuffer.Graphics;
canvas.SmoothingMode =
System.Drawing.Drawing2D.SmoothingMode.AntiAlias;
// canvas.Clear(Color.White);
screenwidth = pictureBoxn.Width;
screenheight = pictureBoxn.Height;
tracks = new Bitmap((int)screenwidth, (int)screenheight);
backgroundcanvas = Graphics.FromImage(tracks);
backgroundcanvas.SmoothingMode =
System.Drawing.Drawing2D.SmoothingMode.AntiAlias;
backgroundcanvas.Clear(Color.Red);
pictureBoxn.Paint += new
System.Windows.Forms.PaintEventHandler(this.pictur eBoxn_Paint);

pictureBoxn.Refresh();
pictureBoxn.Show();
pictureBoxn.Update();
pictureBoxn.Invalidate();
Dec 8 '07 #1
11 1474
Peter,

What is in the code for play_animation? Are you looping through and
repainting on every invocation of the loop? It seems like that is the case
here.

What you really want to do is create a timer which you invalidate your
picturebox on every tick (the frame rate of your animation will depend on
the frequency of the timer).
--
- Nicholas Paldino [.NET/C# MVP]
- mv*@spam.guard.caspershouse.com

"Peter Webb" <we********@DIESPAMDIEoptusnet.com.auwrote in message
news:47***********************@news.optusnet.com.a u...
>I previously asked about two problems I had with some graphics - the first
was that when I drew animation to a picturebox it wouldn't display when the
Form loaded.

It was suggested to me by everyone that I stop using my own CreateGraphics
calls, and override an OnPaint call to do this. As suggested, I created a
custom control "drawBox" with an override on its OnPaint. Because I am
using manual double buffering, as people suggested it was really just a
matter of putting myBuffer.Render() into the OnPaint, and using
drawBox.Invalidate as the call. In the end I only had to change/add about
8 lines of code, and its only taken about 16 hours to work out exactly
which ones.

However, there is one annoying problem that remains. I can get it to show
the initial screen just fine when it loads. But what I really want it to
do is play the opening animation.

If I put the call to animate the screen

play_animation();

As the very last line of Form1_Load or anywhere else that I have tried,
then the Form1 doesn't actually load and show anything until the animation
is finished, at which point the Form pops up showing only the final (end)
frame of the animation.

I had the same problem with the old (bad) way I did graphics, so I assume
its not related ... but FWIW, here are they key parts of my new graphics:

public partial class Form1 : Form
{
static public drawBox pictureBoxn;

...

public class drawBox : Control
{
public drawBox()
{
this.Height = 600;
this.Width = 600;
}
protected override void OnPaint(PaintEventArgs pe)
{
base.OnPaint(pe);
myBuffer.Render();

}
}

I call the following in Form1_Load:

pictureBoxn = new drawBox();
currentContext = BufferedGraphicsManager.Current;
myBuffer =
currentContext.Allocate(pictureBoxn.CreateGraphics (),
pictureBoxn.DisplayRectangle);
this.Controls.Add(pictureBoxn);

canvas = myBuffer.Graphics;
canvas.SmoothingMode =
System.Drawing.Drawing2D.SmoothingMode.AntiAlias;
// canvas.Clear(Color.White);
screenwidth = pictureBoxn.Width;
screenheight = pictureBoxn.Height;
tracks = new Bitmap((int)screenwidth, (int)screenheight);
backgroundcanvas = Graphics.FromImage(tracks);
backgroundcanvas.SmoothingMode =
System.Drawing.Drawing2D.SmoothingMode.AntiAlias;
backgroundcanvas.Clear(Color.Red);
pictureBoxn.Paint += new
System.Windows.Forms.PaintEventHandler(this.pictur eBoxn_Paint);

pictureBoxn.Refresh();
pictureBoxn.Show();
pictureBoxn.Update();
pictureBoxn.Invalidate();

Dec 8 '07 #2

"Nicholas Paldino [.NET/C# MVP]" <mv*@spam.guard.caspershouse.comwrote in
message news:39**********************************@microsof t.com...
Peter,

What is in the code for play_animation? Are you looping through and
repainting on every invocation of the loop? It seems like that is the
case here.

What you really want to do is create a timer which you invalidate your
picturebox on every tick (the frame rate of your animation will depend on
the frequency of the timer).
Yes. I am looping through dozens of on-screen objects, updating their
position. That's what my program does, and spends all its time. In the main
animation loop, I still use a myBuffer.Render() command, as the
drawBox.Invalidate() command flickers (even though it just does a
myBuffer.Render() ).

I was told before (and I think by you) to use a timer in asynchronous
thread. It didn't seem an issue in my app, as most people will want to run
it flat out, so having two threads was more complexity that I didn't
understand.

The annoying thing is that it is just a problem at start up of the Form.
Everything else works brilliantly.

Is there some quick and dirty I can do for the start-up to make the form
appear before the animation starts (or even finishes!)?

Or if I have to do this properly, can you refer me to a web page that might
get me started?
Dec 8 '07 #3
On Sat, 08 Dec 2007 08:11:47 -0800, Peter Webb
<we********@DIESPAMDIEoptusnet.com.auwrote:
Yes. I am looping through dozens of on-screen objects, updating their
position.
Don't do that.
That's what my program does, and spends all its time.
Even so, don't do that.
In the main animation loop, I still use a myBuffer.Render() command, as
the drawBox.Invalidate() command flickers (even though it just does a
myBuffer.Render() ).
The flicker is because calling Invalidate() causes the entire control to
be erased first, before the OnPaint() method is called. You can avoid
this in a couple of ways, but the simplest in a custom control is to just
set the DoubleBuffered property of your control to true (note that this
property has nothing to do with your own buffering...it causes the OS to
create a new off-screen buffer to be used for drawing during updates to
the control).

Flicker isn't a good reason to abandon the standard Windows drawing
model. There are better ways to fix it.
I was told before (and I think by you) to use a timer in asynchronous
thread. It didn't seem an issue in my app, as most people will want to
run it flat out, so having two threads was more complexity that I didn't
understand.
Some points here:

* You might not need a different thread. It's possible that the
Forms.Timer class provides enough accuracy for your animation. It offers
a slightly simpler way to deal with timing.

* A second thread should not be all that complicated in this case.
The trickiest part is remembering that you need to use Control.Invoke() to
call any methods that directly use the UI component. In this case, that's
likely to just be the call to Invalidate(), which you can accomplish like
this (using an anonymous method):

myCustomControl.Invoke((MethodInvoker)delegate()
{ myCustomControl.Invalidate(); });

Note: when using a second thread, you _might_ still run into timing
issues, because while the thread itself might be able to manage its own
timing reasonably well, the redraw stuff (invalidation and redrawing after
invalidation) still has to go through the normal window message queue that
the Forms.Timer object would have had to. There are some basic
limitations when writing a regular Windows applications that will be
present no matter _how_ you do the drawing, right way or wrong way.

I would recommend you try for the Forms.Timer class first, as it provides
a nice, easy API where you don't have cross-thread issues. In addition to
the requirement to invalidate from the main GUI thread (and thus the need
to use Invoke()), using a second thread will also mean you need to impose
some sort of thread synchronization. Either you'll need to essentially
double-buffer your buffer, always having a finished copy used for handling
the control update and a second copy into which you actually draw the new
data, or you'll need to use lock() to protect any code using the buffer so
that you don't have two threads trying to manipulate the data structure at
the same time. Neither is difficult, but why introduce the complexities
if you don't have to?

Note that no matter what you do, you're going to be limited to something
like 15-20 fps using a mechanism like this. Trying to update any more
frequently than that is likely to lead to uneven animation, with some
frames being displayed much shorter or longer periods of time than
others. For faster animation than that, you simply need to get away from
the standard Windows application model completely, which you're not going
to do with a regular .NET forms application.

* It's not really true that most people "will want to run it flat
out". Practically every user I've met wants to be able to exit an
application whenever they want to. Using your design won't allow that, as
the form will not respond to user input until the animation has completed.
The annoying thing is that it is just a problem at start up of the Form.
Everything else works brilliantly.
I'm not sure I'd use the term "brilliantly" to describe how _everything
else_ in your application works. You may have gotten the animation to
animate, but other than that your application isn't a very well-behaved
Windows application.

As promised to you, by failing to adhere to the standard drawing model in
Windows, you've created new, difficult-to-solve problems.
Is there some quick and dirty I can do for the start-up to make the form
appear before the animation starts (or even finishes!)?
Well, one option would be to move your animation code to some place where
you know it will take place after the form has drawn. But keep in mind
that doing that will only change the specific scenarios in which your form
won't draw. It will be trivial to demonstrate other scenarios in which
the form needs to be draw _again_, but won't be able to because you're
stuck in your animation loop.

The correct fix, and the only one I will recommend, is to fix your code so
that your control _only_ draws itself in response to WM_PAINT messages.
In other words, in the OnPaint() method, and in there drawing only the
_current_ state of the data. Updates of the data used for animation
(which in your case basically just means your off-screen buffer) must be
done outside of the drawing code. When the data is updated, simply call
Invalidate() to cause a redraw to happen.
Or if I have to do this properly, can you refer me to a web page that
might get me started?
I posted a number of useful links in the previous thread, to pages on the
MSDN web site. I believe someone else has posted one or more links to Bob
Powell's web site as well (which I can't vouch for, but I've seen other
people recommend it highly).

Mostly though, you really need to just focus on the basics. There's a
very specific, but easily-described paradigm here:

* Make sure your drawing code responds correctly to OnPaint(),
rendering the current state of the data and being able to do so at any
time.
* Don't draw from the same place where you change the data. Call
Invalidate() instead.

From that, everything else derives.

Pete
Dec 8 '07 #4
>>Is there some quick and dirty I can do for the start-up to make the form
>>appear before the animation starts (or even finishes!)?
Yes. Try the FormShown event instead. The FormLoad event is NOT the place
to try animation.

"Peter Webb" <we********@DIESPAMDIEoptusnet.com.auwrote in message
news:47***********************@news.optusnet.com.a u...
>
"Nicholas Paldino [.NET/C# MVP]" <mv*@spam.guard.caspershouse.comwrote
in message news:39**********************************@microsof t.com...
>Peter,

What is in the code for play_animation? Are you looping through and
repainting on every invocation of the loop? It seems like that is the
case here.

What you really want to do is create a timer which you invalidate your
picturebox on every tick (the frame rate of your animation will depend on
the frequency of the timer).

Yes. I am looping through dozens of on-screen objects, updating their
position. That's what my program does, and spends all its time. In the
main animation loop, I still use a myBuffer.Render() command, as the
drawBox.Invalidate() command flickers (even though it just does a
myBuffer.Render() ).

I was told before (and I think by you) to use a timer in asynchronous
thread. It didn't seem an issue in my app, as most people will want to run
it flat out, so having two threads was more complexity that I didn't
understand.

The annoying thing is that it is just a problem at start up of the Form.
Everything else works brilliantly.

Is there some quick and dirty I can do for the start-up to make the form
appear before the animation starts (or even finishes!)?

Or if I have to do this properly, can you refer me to a web page that
might get me started?

Dec 8 '07 #5
On Sat, 08 Dec 2007 15:10:21 -0800, Joey Joe Joe <no@nothing.comwrote:
>>Is there some quick and dirty I can do for the start-up to make the
form appear before the animation starts (or even finishes!)?

Yes. Try the FormShown event instead. The FormLoad event is NOT the
place to try animation.
Neither is FormShown. _Starting_ some animation process might be
appropriate there, and would be just as appropriate in the FormLoad
event. Actually _doing_ the animation belongs there no more than it
belongs in FormLoad.
Dec 8 '07 #6
I never said that the FormShown event was the optimum place to do animation.
I was answering a specific question from the poster which is, "Is there some
quick and dirty I can do for the start-up to make the form appear before the
animation starts (or even finishes!)?" Did you notice the quick and dirty
reference? Hence, I offered the FormShown event. Quick and dirty.

"Peter Duniho" <Np*********@nnowslpianmk.comwrote in message
news:op***************@petes-computer.local...
On Sat, 08 Dec 2007 15:10:21 -0800, Joey Joe Joe <no@nothing.comwrote:
>>>Is there some quick and dirty I can do for the start-up to make the
form appear before the animation starts (or even finishes!)?

Yes. Try the FormShown event instead. The FormLoad event is NOT the
place to try animation.

Neither is FormShown. _Starting_ some animation process might be
appropriate there, and would be just as appropriate in the FormLoad
event. Actually _doing_ the animation belongs there no more than it
belongs in FormLoad.
Dec 9 '07 #7

"Joey Joe Joe" <no@nothing.comwrote in message
news:eF*************@TK2MSFTNGP04.phx.gbl...
>>>Is there some quick and dirty I can do for the start-up to make the form
appear before the animation starts (or even finishes!)?

Yes. Try the FormShown event instead. The FormLoad event is NOT the place
to try animation.
Yes, thankyou. Changing "Form_Load" to "Form_Show" solved the problem. I
suspect that this would also have solved my original problem (the PictureBox
coming up blank, instead of showing the default setup screen), without my
needing to redevelop this using a custom control and OnPaint. Having said
that, I am still pleased that I investigated and implemented OnPaint, at
least I now know how to implement V2 "more properly", and learned a lot in
the process. As it is, V1.0 is now ready to ship - thankyou again.
Dec 9 '07 #8

Thankyou for your advice now, and previously.

My app actually now works extremely well, at least on my computer. By having
it entirely single threaded, I also know that it will work on any computer -
there is obviously far less scope for timing issues etc if my app runs that
way.

Having said that, your advice has always been excellent, and if and when I
decide to develop V2 it will be done in the way you suggest (as will any
future programs).

Actually, there is a little bit of multi-threading/re-entrancy in my code.
When I kick-off the animation, I turn off all the buttons that "do" things
that aren't reasonable to change in the middle of an animation. I leave a
"Stop" button, and some options to do with the animation - level of detail,
speed, etc. I have a DoEvents call after each animation loop that allows the
buttons to respond during the animation. Clicking these buttons just set
flags and values used in the animation loop; these are all read-only in the
animation so critical races cannot occur.

I don't know how fast it runs, but having a Thread.Sleep(10) after each
animation frame makes a noticeable difference to the speed, so its pretty
fast. Considering that I redraw my entire 1000 x 768 bitmap on every loop,
its pretty good - almost a million points are copied on every animation. I
can speed this up by redrawing only the part that has changed, as you
suggested - difficult to do with how the code is implemented now (as the
draws are intermingled with the position logic code) but when I develop V2 I
will clean this up in the manner you suggest.

Again, thankyou for your advice and help.
Peter Webb

Dec 9 '07 #9
On Sat, 08 Dec 2007 16:50:33 -0800, Joey Joe Joe <no@nothing.comwrote:
I never said that the FormShown event was the optimum place to do
animation.
This isn't about what's "optimum". It's about what's correct. The world
already has plenty of crummy software. No one needs our help adding to
the list.
I was answering a specific question from the poster which is, "Is there
some quick and dirty I can do for the start-up to make the form appear
before the animation starts (or even finishes!)?" Did you notice the
quick and dirty reference? Hence, I offered the FormShown event. Quick
and dirty.
It's worse than quick and dirty. It's pure, unadulterated excrement.
Granted, it's just my opinion, but that opinion is that we as a community
have no business helping other people make .NET applications _worse_.
Which is just what you've done.

Note that now that Webb has a hack that appears to him to get done what he
thinks he wants done, he has no interest in making the application work
correctly before he releases it on whatever unsuspecting customers he's
got. So now, whatever that application does (I seem to recall something
about an orbit simulation or something), anyone who wants to do anything
with the application other than watch whatever animation is going on
(like, for example, exit the application...a basic function that every
user has the right to expect from any application) isn't going to be able
to do it.

Some questions are best left unanswered.

Pete
Dec 9 '07 #10
On Sat, 08 Dec 2007 23:01:01 -0800, Peter Webb
<we********@DIESPAMDIEoptusnet.com.auwrote:
[...]
Actually, there is a little bit of multi-threading/re-entrancy in my
code. When I kick-off the animation, I turn off all the buttons that
"do" things that aren't reasonable to change in the middle of an
animation. I leave a "Stop" button, and some options to do with the
animation - level of detail, speed, etc. I have a DoEvents call after
each animation loop that allows the buttons to respond during the
animation.
Ah. Great. You've compounded the original error with another, which is
the use of DoEvents(). :(

Oh well...at least your users can exit the application that way.
[...]
Again, thankyou for your advice and help.
I guess I should be glad you found my posts helpful. From here though, I
don't really see that any of my advice wound up in your program. Mostly,
I'm just sad about the whole thing.

Pete
Dec 9 '07 #11
_Peter_,

Man, you're _smug_ and arrogant. I bet it's not easy going though _life_ so
smug. Yet, you seem to do it with such ease. Granted, that's just _my_
opinion, but it's probably the opinion of others as well.
have no business helping other people make .NET applications _worse_.
Maybe _you're_ the reason for lousy software. People are afraid to ask
questions for fear of being ridiculed by newsgroup bullies. Did you ever
think of that? I guess calling someone's project _excrement_ is one way to
assure that they will continue to _ask_ for help in the future. Nice going,
genius.
Some questions are best left unanswered
Maybe you should _take_ your own advice for a change. I think the _reason_
you answer so many questions is because you need approval. You want people
to _say_, "Peter, you're a genius. Thanks for you help." I bet your chest
_inflates_ every time you read something like that. _No_?

"Peter Duniho" <Np*********@nnowslpianmk.comwrote in message
news:op***************@petes-computer.local...
On Sat, 08 Dec 2007 16:50:33 -0800, Joey Joe Joe <no@nothing.comwrote:
>I never said that the FormShown event was the optimum place to do
animation.

This isn't about what's "optimum". It's about what's correct. The world
already has plenty of crummy software. No one needs our help adding to
the list.
>I was answering a specific question from the poster which is, "Is there
some quick and dirty I can do for the start-up to make the form appear
before the animation starts (or even finishes!)?" Did you notice the
quick and dirty reference? Hence, I offered the FormShown event. Quick
and dirty.

It's worse than quick and dirty. It's pure, unadulterated excrement.
Granted, it's just my opinion, but that opinion is that we as a community
have no business helping other people make .NET applications _worse_.
Which is just what you've done.

Note that now that Webb has a hack that appears to him to get done what he
thinks he wants done, he has no interest in making the application work
correctly before he releases it on whatever unsuspecting customers he's
got. So now, whatever that application does (I seem to recall something
about an orbit simulation or something), anyone who wants to do anything
with the application other than watch whatever animation is going on
(like, for example, exit the application...a basic function that every
user has the right to expect from any application) isn't going to be able
to do it.

Some questions are best left unanswered.

Pete
Dec 9 '07 #12

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

2
by: Thelma Lubkin | last post by:
Arno R <arraNOcomSPAM@tiscali.nl> wrote: :> user types Mary Jane Jones :> database has MaryJane Jones : I finally understand why...
4
by: Martin | last post by:
I am using graphics as backgrounds for forms,buttons,labels etc. The question is: is it faster to load all graphics from files on app start or to use it embeded (places in editor during design)....
1
by: DBC User | last post by:
Hi Sharpies, This is a very basic question. I am using .Net IDE 2003 and System.Drawing.dll (1.1.4322). I wrote a simple program like this (ommitting the commons) using System.Drawing; .....
2
by: Tamer Abdalla via DotNetMonster.com | last post by:
Hello, everyone! I DO need some help in order to understand how to create graphics in VB.NET. I'm a little bit confused... I once knew a time when using Point & PSet was almost the only way to...
7
by: Peter Row | last post by:
Hi, I've started work on my own control some parts of which use standard controls, others I need to draw on my controls surface to get the display output I require, however.... I seem to be...
6
by: Paul_Madden | last post by:
I have a System.Windows.Forms.Form onto which I add a Panel (MyPanel) directly derived from System.Windows.Forms.Panel. Here are the important code fragments ... public class MyPanel : Panel...
6
by: AbraAbraCadabra | last post by:
Ok I think I've almost got my problem solved. I am using this code to send mail. I am simply pasting it into an .ASP page. Why doesn't this code work? I do have ..NET 2.0 installed, but I...
12
by: Xah Lee | last post by:
Of Interest: Introduction to 3D Graphics Programing http://xahlee.org/3d/index.html Currently, this introduction introduces you to the graphics format of Mathematica, and two Java Applet...
1
by: Ringo | last post by:
I need some help. I have an app that talks to a sonar board via the serial port. In my sp_DataReceived I gather all the data and put it into arrays. Then I want to draw the data in a pictureBox. I...
0
by: Charles Arthur | last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
0
by: ryjfgjl | last post by:
In our work, we often receive Excel tables with data in the same format. If we want to analyze these data, it can be difficult to analyze them because the data is spread across multiple Excel files...
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...
0
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...
0
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...
0
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.