T
Tim Crews
Hello:
I was the original poster for a previous thread entitled "Why must I paint the
form background for an owner-draw control?", which can be reviewed at the
following URL, if you recombine all of the lines:
http://groups.google.com/groups?
hl=en&lr=lang_en&safe=off&threadm=OpoxJYbsEHA.904%40TK2MSFTNGP11.phx.gbl&rnum=1
&prev=/groups%3Fhl%3Den%26lr%3Dlang_en%26safe%3Doff%26selm%3DOpoxJYbsEHA.904%
2540TK2MSFTNGP11.phx.gbl
I was having a performance problem with non-rectangular owner-drawn controls
placed on a form that had a BackgroundImage. Because the parent Form control
clips to the child windows before it paints its background image, each of the
owner-drawn controls is responsible for re-painting the portion of the form
background that it occupies. The computer that I will be running my program on
is taking 8 seconds to draw a form with 40 to 50 such owner-drawn controls.
Stoitcho Goutsev, Frank Hileman, and Mick Doherty had several helpful
suggestions. Eventually, I was able to configure the owner-drawn controls so
that my owner-draw code did not have to explicitly fill in the background
areas. Instead, the control's transparency color was used so that the Windows
Forms infrastructure took care of the background painting itself.
Unfortunately, the performance problem was just as bad that way as it was when
I explicitly painted the form background around the controls.
The last suggestion I received was from Mick Doherty:
-----------------------------------------
If this is still an issue I have a workaround that may be satisfactory.
Inherit from Picturebox and give it the ScrollableControlDesigner Attribute.
You can then Dock this to the fill the form and place the buttons in that
instead.
[System.ComponentModel.Designer(typeof
(System.Windows.Forms.Design.ScrollableControlDesigner))]
public class PictureBoxContainer : System.Windows.Forms.PictureBox
{
//Standard code ommitted...
}
note: you'll need a reference to System.Design.dll
------------------------------------------
Mick, If you are still around, I need a little more detail on some of the steps
here. I have made an attempt at what you suggested, but it looks to me like
the PictureBox control is _also_ clipping the child windows, so that I still
have to (either explicitly or implicitly) cause the PictureBox background to be
painted around the owner-drawn control.
Here's what I did:
1) Created a new form.
2) Editing the form in design mode, I created a PictureBox control that fills
the entire form. I assigned a BackgroundImage to the PictureBox. I did not
"dock" the PictureBox control. Did you mean this literally, and if so, how do
I do it?
3) Editing the code for the form, I augmented the form code to add a
PictureBoxContainer class as you specified in your example. As for the
"Standard code ommitted", all I added was a constructor that calls the base()
constructor. Was there any other standard code I should have written?
4) I edited the code for the PictureBox instance to make it a
PictureBoxContainer instance.
5) Back in form design mode, I created a Button in the middle of the form.
6) Back in code mode, I changed the Button instance to make it an instance of
my owner-drawn "FancyButton" class.
7) For that "FancyButton" instance, I assigned the PictureBoxContainer
instance as the Parent of the FancyButton. Was this the proper way to make the
PictureBoxContainer the container for the FancyButton?
8) I modified the FancyButton constructor so that Windows doesn't try to
simulate transparency (which is what's causing the performance problem). I did
this by commenting out three lines of code from the original constructor:
public FancyButton() : base()
{
PenWidth = 1;
ButtonPressed = false;
SetStyle(ControlStyles.UserPaint, true);
//SetStyle(ControlStyles.Opaque, false);
SetStyle(ControlStyles.ResizeRedraw, true);
//SetStyle (ControlStyles.SupportsTransparentBackColor, true);
//base.BackColor = Color.Transparent;
}
Anyway, the result of all of this is that at design time, the fancy button is
surrounded by the Form's background color, instead of by the PictureBox's
background image. At runtime, the fancy button is surrounded by black (not the
Form's background color), and the fancy button is not the same size/location as
it was in design mode. (I suppose the reason for the different location/size is
that I dynamically re-parent the button at run-time. There must be a design-
time way of accomplishing the re-parenting.) When the button is pressed, which
causes an animation of the button moving slightly down and to the right, an
image of the un-pressed button is left behind.
Mick, if you have any advice on how I can properly implement what you
suggested, I would be glad to have it. Given the difference in behavior
between design-time and run-time, I am not convinced I have actually
accomplished what you suggested.
But on the other hand, the behavior on the button press leads me to an
observation of a problem: On the initial draw of the form and its buttons,
maybe eventually I will be able to rely on the background image already being
present when the buttons are drawn, so that I don't have to re-draw it. But
when I animate the button press, it seems to me that there is no way around a
redraw of the form background image around that button as the button is moved.
Am I right about that? If so, I guess I have two options:
a) Re-design the button so that it gives some other visual indicator of the
pressing action, without actually moving the button.
b) Add code to the owner-drawn button class that knows the difference between
an initial draw and a button-animation draw. The performance hit on the
drawing of a single button is no big deal.
Thank you to anyone who has any advice or input.
Tim Crews
GECO, Inc.
I was the original poster for a previous thread entitled "Why must I paint the
form background for an owner-draw control?", which can be reviewed at the
following URL, if you recombine all of the lines:
http://groups.google.com/groups?
hl=en&lr=lang_en&safe=off&threadm=OpoxJYbsEHA.904%40TK2MSFTNGP11.phx.gbl&rnum=1
&prev=/groups%3Fhl%3Den%26lr%3Dlang_en%26safe%3Doff%26selm%3DOpoxJYbsEHA.904%
2540TK2MSFTNGP11.phx.gbl
I was having a performance problem with non-rectangular owner-drawn controls
placed on a form that had a BackgroundImage. Because the parent Form control
clips to the child windows before it paints its background image, each of the
owner-drawn controls is responsible for re-painting the portion of the form
background that it occupies. The computer that I will be running my program on
is taking 8 seconds to draw a form with 40 to 50 such owner-drawn controls.
Stoitcho Goutsev, Frank Hileman, and Mick Doherty had several helpful
suggestions. Eventually, I was able to configure the owner-drawn controls so
that my owner-draw code did not have to explicitly fill in the background
areas. Instead, the control's transparency color was used so that the Windows
Forms infrastructure took care of the background painting itself.
Unfortunately, the performance problem was just as bad that way as it was when
I explicitly painted the form background around the controls.
The last suggestion I received was from Mick Doherty:
-----------------------------------------
If this is still an issue I have a workaround that may be satisfactory.
Inherit from Picturebox and give it the ScrollableControlDesigner Attribute.
You can then Dock this to the fill the form and place the buttons in that
instead.
[System.ComponentModel.Designer(typeof
(System.Windows.Forms.Design.ScrollableControlDesigner))]
public class PictureBoxContainer : System.Windows.Forms.PictureBox
{
//Standard code ommitted...
}
note: you'll need a reference to System.Design.dll
------------------------------------------
Mick, If you are still around, I need a little more detail on some of the steps
here. I have made an attempt at what you suggested, but it looks to me like
the PictureBox control is _also_ clipping the child windows, so that I still
have to (either explicitly or implicitly) cause the PictureBox background to be
painted around the owner-drawn control.
Here's what I did:
1) Created a new form.
2) Editing the form in design mode, I created a PictureBox control that fills
the entire form. I assigned a BackgroundImage to the PictureBox. I did not
"dock" the PictureBox control. Did you mean this literally, and if so, how do
I do it?
3) Editing the code for the form, I augmented the form code to add a
PictureBoxContainer class as you specified in your example. As for the
"Standard code ommitted", all I added was a constructor that calls the base()
constructor. Was there any other standard code I should have written?
4) I edited the code for the PictureBox instance to make it a
PictureBoxContainer instance.
5) Back in form design mode, I created a Button in the middle of the form.
6) Back in code mode, I changed the Button instance to make it an instance of
my owner-drawn "FancyButton" class.
7) For that "FancyButton" instance, I assigned the PictureBoxContainer
instance as the Parent of the FancyButton. Was this the proper way to make the
PictureBoxContainer the container for the FancyButton?
8) I modified the FancyButton constructor so that Windows doesn't try to
simulate transparency (which is what's causing the performance problem). I did
this by commenting out three lines of code from the original constructor:
public FancyButton() : base()
{
PenWidth = 1;
ButtonPressed = false;
SetStyle(ControlStyles.UserPaint, true);
//SetStyle(ControlStyles.Opaque, false);
SetStyle(ControlStyles.ResizeRedraw, true);
//SetStyle (ControlStyles.SupportsTransparentBackColor, true);
//base.BackColor = Color.Transparent;
}
Anyway, the result of all of this is that at design time, the fancy button is
surrounded by the Form's background color, instead of by the PictureBox's
background image. At runtime, the fancy button is surrounded by black (not the
Form's background color), and the fancy button is not the same size/location as
it was in design mode. (I suppose the reason for the different location/size is
that I dynamically re-parent the button at run-time. There must be a design-
time way of accomplishing the re-parenting.) When the button is pressed, which
causes an animation of the button moving slightly down and to the right, an
image of the un-pressed button is left behind.
Mick, if you have any advice on how I can properly implement what you
suggested, I would be glad to have it. Given the difference in behavior
between design-time and run-time, I am not convinced I have actually
accomplished what you suggested.
But on the other hand, the behavior on the button press leads me to an
observation of a problem: On the initial draw of the form and its buttons,
maybe eventually I will be able to rely on the background image already being
present when the buttons are drawn, so that I don't have to re-draw it. But
when I animate the button press, it seems to me that there is no way around a
redraw of the form background image around that button as the button is moved.
Am I right about that? If so, I guess I have two options:
a) Re-design the button so that it gives some other visual indicator of the
pressing action, without actually moving the button.
b) Add code to the owner-drawn button class that knows the difference between
an initial draw and a button-animation draw. The performance hit on the
drawing of a single button is no big deal.
Thank you to anyone who has any advice or input.
Tim Crews
GECO, Inc.