As someone has already pointed out this looks like it's probably a driver
problem - works fine when I try your code.

However there are some problems in your code.  They're unrelated, but you
should know about them:

>     gr.FillRectangle( new SolidBrush( SystemColors.ControlLight ), rect );

It would be easier just to use SystemBrushes.ControlLight here instead of
creating your own brush.  It would also be more efficient, as the framework
will cache the Brush that it creates, which will save you from creating a
new one every time.

Also, since you are creating your own brush here you should be calling
Dispose on it when you are finished.  As it stands, this code is relying on
the GC to free the Brush, which means you will consume far more GDI+
resources than necessary.  But in this case, going with the SystemBrushes
class is the preferable solution (they don't need to be Disposed. in fact
they mustn't be diposed.)

However, there's another potential problem.  What behaviour do you want when
the user changes the menu color in the system properties?  Don't you want
your highlight to change colour accordingly?  Otherwise things are going to
look a bit strange.  So what you probably wanted was this:

  Color menuLight = ControlPaint.Light(SystemColors.Menu);
  using (Brush b = new SolidBrush(menuLightBrush))
  {
     gr.FillRectangle( menuLightBrush, rect );
  }

Here we go back to creating our own SolidBrush - this is because there is no
SystemColors.MenuLight, and therefore there is no corresponding
SystemBrushes.MenuLight, so we have to create our own.  Note the use of the
using construct to make sure the brush gets freed.


>     gr.FillRectangle( new SolidBrush( Color.FromArgb(173, 173, 209) ),
rect );

This hard-coded color probably isn't what you want either.  I'm assuming
you're looking for Office XP/VS.NET-style menu drawing here.  Those menus
are all sensitive to the user's setting for selected items.  By default it
is blue, but if you change your selected item colour to, say, green, then
the Office/VS menu item selection is also in green.  The following code
seems to come up with the same selection colour that Office XP and VS.NET
use:

    Color sel = SystemColors.Highlight;
    Color mix = SystemColors.Window;
    Color selectLight = Color.FromArgb((sel.R + mix.R*2)/3,
        (sel.G + mix.G*2)/3, (sel.B + mix.B*2)/3);
    using (Brush b = new SolidBrush(selectLight))
    {
        gr.FillRectangle( b, rect );
    }

So we've created a colour which is 1/3 menu highlight, and 2/3 Window (i.e.
white on most systems).  This looks right to me, although I've no idea if
it's officially The Right Colour.



>     gr.DrawRectangle( new Pen( Color.DarkBlue ), rect.X,
>     rect.Y, rect.Width - 1 , rect.Height - 1 );

This hardcoding is also bad, as is the failure to dispose.  You want to use
SystemPens.Highlight, which will give you the correct colour, and will not
need to be disposed.


>       gr.FillRectangle( new SolidBrush( SystemColors.ControlLight ),
rect );
>                         rect.X     += bitmap_size + 5;
>                         rect.Width -= bitmap_size + 5;
>       gr.FillRectangle( new SolidBrush( SystemColors.ControlLightLight ),
rect );

This is arguably bad practice - why are you filling the whole area with one
colour when you then paint most of that straight over with another colour?
Just paint the areas you need to paint.

Also, I'm not sure these are the right colours to use.  As it happens,
Office XP and VS.NET appear to be using SystemColors.Window for the pale
part.  I'm not completely sure what it's using for the darker part - it
seems to be the same colour as the face of the toolbars.  This is not a
system color, but it is apparently influenced by SystemColors.Window - it's
a very washed out version of it.  (Try changing your Window colour on your
system to Fuschia and you'll see what I mean.)  So I guess they're maybe
applying a colour transformation to derive that colour.  But I think it
looks kind of odd.

ControlLight actually looks like a good approximation in the default colour
scheme though.  Using Window would be closer to office XP/VS.NET behaviour
for the second one.

Again in both cases you should be using SystemBrushes for two reasons (1) so
that the fact that you've not called Dispose on these brushes is not a
problem, and (2) because it'll be more efficient.

>         gr.FillRectangle( SystemBrushes.Control, rect );

So how come you used SystemBrushes here?  It's the right thing to do, I just
assumed you didn't know about it, since you hadn't used it anywhere else...
:-)


--
Ian Griffiths
DevelopMentor

You can read messages from the DOTNET archive, unsubscribe from DOTNET, or
subscribe to other DevelopMentor lists at http://discuss.develop.com.

Reply via email to