Search code examples
wpfbitmapzoomingdpi

How to display a Bitmap Windows zoom level (DPI?) independent in WPF


I am new to WPF, and facing to the following issue. I am displaying a bitmap, xaml:

<ControlTemplate x:Key="MyEditorImageTemplate">
    <Image  VerticalAlignment="Top" Margin="3,1,0,0"
            RenderOptions.BitmapScalingMode="NearestNeighbor"
            Stretch="None">
        <Image.Source>
            <MultiBinding Converter="{StaticResource MyEditorConverter}">
                <Binding Path="....." />

The Bitmap is coming from BitmapSource, provided the following way:

Bitmap^ bitmap = System::Drawing::Image::FromHbitmap((IntPtr)aBmp);
IntPtr hbmp = bitmap->GetHbitmap();
BitmapSource bs = 
     Imaging::CreateBitmapSourceFromHBitmap(hbmp, 
                                            System::IntPtr::Zero,
                                            Int32Rect(0,0,nWidth,nHeight),
                                            BitmapSizeOptions::FromEmptyOptions());

Now this works fine, until I have the windows zoom level at 100%. If I change it in Windows to 125%:

The bitmap is also zoomed on the GUI.

I understand that this is -sort of- the expected, but is there any way that I still show it 1-1 pixel size, ignoring windows zoom settings?


Solution

  • Ok, I found the solution. You just need an own Image class, derived from Image, and simple override the OnRender, where you take care of the proper resizing (if necessary).

    protected override void OnRender(DrawingContext dc)
    {
        //base.OnRender(dc);    --> we do out own painting
        Rect targetRect = new Rect(RenderSize);
        PresentationSource ps = PresentationSource.FromVisual(this);
        if (ps != null && Source != null)
        {
            Matrix fromDevice = ps.CompositionTarget.TransformFromDevice;
            Vector currentVisibleSize = new Vector(Source.Width, Source.Height);
            Vector originalRestoredSize = fromDevice.Transform(currentVisibleSize);
            targetRect = new Rect(new Size(originalRestoredSize.X, originalRestoredSize.Y));
        }
        dc.DrawImage(Source, targetRect);
    }
    

    With this, regardless of the Windows zoom setting, you will have always the 100% original size. I got the idea from this site: http://blogs.msdn.com/b/dwayneneed/archive/2007/10/05/blurry-bitmaps.aspx