[...]
Also, during testing, I noticed an interesting thing about the Bitmap
class. The default constructor appears to set the transparency of each
pixel to 100%. This means that if I draw something to a Bitmap and then
render the bitmap, only the objects that I have drawn to the bitmap are
overlayed (ie there is no no change to the background). This is
actually perverse operation in my case, because my Bitmap is the
background, and I will need to suppress this through a
clearscreen(backgroundcolour) call to initialise the bitmap when it is
created (trivial, of course).
You may prefer then to provide an explicit pixel format when creating
the bitmap, and make sure it's a 24-bit-per-pixel bitmap instead of a
format that supports alpha (such as 32-bpp, which is probably what
you're getting now).
Of course, that's only really helpful if you want your background to be
black. But at least you get that default black background instead of
see-through.
It does raise some interesting possibilities for the future, because
the use of transparency almost directly allows sprites to be created.
My code isn't written that way, but its great to know.
Yes, GDI supports alpha (transparency) reasonably well. Unfortunately,
the Windows control classes don't; they always paint a background, so
even if you draw a transparent bitmap into the control, you can't see
through it to other controls underneath.
So, transparency works great _within_ a specific control, but don't
expect to easily be able to layer overlapping controls in a form and
have that work okay, or even to have transparent controls on top of a
form with a custom-drawn background.
I don't use OnPaint or any Paint commands. I implement my Graphics
instances directly through CreateGraphics commands. This is the first
technique I got to work, and so naturally it will be the technique I
will always use unless it stops working. Unless you can identify a
reason to change, I won't.
You need to change.
First, based on the code you posted, I think there's a good chance
you're not disposing the creating Graphics instance properly. You need
to learn to do that anyway (it applies to the Graphics you get from the
Bitmap as well, and possibly other objects you create...basically, if
the object implements IDisposable, you need to dispose it), but you can
avoid at least that part of the problem just by moving to a more
appropriate rendering method.
As for a more specific reason to change, it's basically a matter of
sticking with the approved paradigm in Windows. You don't draw
whenever you feel like it. You draw when Windows tells you to. Doing
it any other way will result in a variety of bugs where you either have
trouble figuring out how to draw exactly what you need to at the
appropriate time, or you just don't do it at all.
A common way to expose such bugs is to drag windows on the screen
around, either moving other windows over your own, or moving yours
around so that it becomes partially obscured (such as off the screen).
Even when you have to draw because you know you've changed the data to
be displayed, you don't do that directly. You invalidate the area on
your window (form) that has changed (sometimes this is the entire
window, but if you know it's less than that, you get much better
performance only invalidating the area that changed). At an
appropriate time, you'll get a window message (event) telling your code
to draw, which is handled either in the OnPaint() method, or in a Paint
event handler.
You know how you write "I was always 'fighting against' how C# wanted
to work"? This is an example of that. Right now, you are fighting
against how Windows wants to work, and it's going to cause problems.
If not now, then eventually, and likely sooner rather than later.
This is my first serious foray into programming in 30 years. I have
been at this now for about a month, and the first 2 weeks was spent
with almost no idea as to what a "class" actually is. This OO stuff was
completely new to me. When I started, everything was difficult, because
I was always "fighting against" how C# wanted to work. Now I seldom
have this problem.
For what it's worth, a suggestion: when you receive some advice in this
newsgroup, if you are thinking to yourself "no, that won't work for
me", your first thought after that should be "hmm...maybe it will, and
I'm just misunderstanding".
We can work through the misunderstanding, but it goes a lot faster if
you don't start out with the assumption that the person trying to help
you doesn't actually have the answer. They won't always, granted, but
they often will and telling them that what they are trying to offer
isn't going to help just makes it take longer to get to the useful
point.
This is especially true given your lack of experience. Based on your
explanation, I'd say you have a _long_ way to go before your intuition
about whether someone's advice is actually applicable or not can be
trusted. You might as well give a person the benefit of the doubt
before telling them what they're offering won't work.
If not for this newsgroup, I would probably still be doing "Hello
Worlds". I am very grateful indeed to you and the other people that
have helped - this newsgroup is one of the best reasons to use C#. Your
time and insights have been appreciated very much; thankyou.
You're welcome.
Pete