Search code examples
c#wpfwindowsdrawingsystem.windows.media

System.Windows.Media.DrawingContext.DrawImage() showing white pixels instead of black in semi-transparent areas like shadows


I have a WPF Button subclass that overrides OnRender() to draw one of several bitmaps depending on the current state. The simplified (1-bitmap) code is shown below...

    protected override void OnRender(DrawingContext context)
    {
        context.DrawImage(_MyBitmapSource, new Rect(0, 0, Width, Height));
    }

The semitransparent black pixels of the shadows in each bitmap incorrectly render as semitransparent white.

Likewise if I set one of these images as the Background brush the same thing happens.

For Image controls setting the same image to Source looks correct, so I know WPF is able to draw the shadows correctly. I'm obviously missing something — possibly something else that needs to be set in OnRender() before the call to DrawImage().

There's nothing special about the PNG images. Just to be certain that wasn't the problem I downloaded a few PNGs from images.google.com and they all had the same issue.


Solution

  • In other frameworks, events such as Paint or Render are usually used to change look of controls.

    WPF has lookless controls - you can template a wpf control to be just about anything you can imagine. This is rather mind numbing, extremely powerful and makes some things way easier than they would be in those other frameworks.

    Hence the "conventional" wpf approach to creating an image that has the behaviour of a button is just to set the template of a button to an image. You can then set imagessource by code or markup. Markkup is usually preferred by WPF developers and you have multiple options including datatriggers, triggers, templating and visual states.

    Other benefits of this approach are that markup allows you to get an immediate idea of what will happen and you can fairly easily simplify it right down for any trouble shooting.