3

I have a simple UserForm to prototype the concept of loading different sizes of the same image based on the Windows display scale that the user sets. For this example, I'm just testing with 100% scale (96DPI) and 200% scale (192DPI).

The source BMP images are as follows:

  • 1x image is 500px by 500px
  • 2x image is 1000px by 1000px

Using the 0.75 (72/96) pixel to points ratio, I've set an image control to 375pts wide by 375pts high and loaded the 1x BMP image. When I run the UserForm, the image renders at 500x500 pixels as expected at display scale 100%:

enter image description here

I then shut down the host Office app and change the display scale to 200% in system settings:

screenshot of Windows Settings for display scale

I restart the app (PowerPoint in my case) and this time load the 2x image into the same image control. When I run the UserForm, the image doesn't render at 1000x1000 pixels as I'd expect, but 1072x1072 pixels, complete with scaling artefacts:

enter image description here

I need to apply a fudge factor of 1000/1072 (0.933) to get the image control to render at the expected pixel size, without scaling artefacts:

enter image description here

I develop on a Parallels VM but have also tested the same behaviour on a Windows Surface machine.

Why is this happening?

Steps to reproduce:

  1. Create a VBA project with a UserForm containing two image controls named Image1 and Image2x and set both to 375pts x 375pts with scale mode set to zoom.

  2. Load a 500x500px BMP image into Image1 and a 1000x1000 BMP image into Image2x.

  3. Add the code below and run the UserForm at display scales of 100% and 200%, restarting the host app between changes.

     Private Declare PtrSafe Function GetDC Lib "user32" (ByVal hwnd As LongPtr) As LongPtr
     Private Declare PtrSafe Function GetDeviceCaps Lib "gdi32" (ByVal hdc As LongPtr, ByVal nIndex As Long) As Long
     Private Declare PtrSafe Function ReleaseDC Lib "user32" (ByVal hwnd As LongPtr, ByVal hdc As LongPtr) As Long
    
     Private Const LOGPIXELSX = 88
     Private Const LOGPIXELSY = 90
    
     Private Sub UserForm_Initialize()
         Select Case GetDPIScale
             ' If the display scale is 200%, load the 2x image from the second image control and apply the fudge factor
             Case 2
                 With Me.Image1
                     .Picture = Me.Image2x.Picture
                     .Width = .Width * 0.933
                     .Height = .Height * 0.933
                 End With
         End Select
     End Sub
    
     Private Function GetDPIScale() As Double
         Dim hdc As LongPtr
         Dim dpiX As Long
    
         hdc = GetDC(0)
         dpiX = GetDeviceCaps(hdc, LOGPIXELSX)
         ReleaseDC 0, hdc
    
         GetDPIScale = dpiX / 96 ' 96 DPI is standard baseline
     End Function
    

UPDATE:

I tested other sizes and the results are even stranger:

enter image description here

1
  • Thanks for taking a look @Tony-Sciple. I kept the Case statement as simple as possible to try to avoid confusion and focus on just one example of where logic doesn't appear to prevail. The fundamental issue is that any userform control (an image is easier to use for demonstration purposes) does not render at 2x when the Windows Display Scale is set to 200%, but 214.4% yet it does render at the expected ratio at 100%, 125% and 150%. Commented Nov 17 at 8:33

1 Answer 1

-1
  1. Noticed while debugging that 'Case 2' from above only runs when the display scale is set at 200%, since dpix = 192 and 192/96 = 2. I was not sure if there was intentionally not a Case 1.75, or Case 2.25 to handle scaling of the other zoom cases mentioned as 175% / 225%. Not sure if that was causing confusion or not?

  2. Have you tried to change the PictureSizeMode? It appears that there are three enumerated settings as follows.
    0 - fmPictureSizeModeClip
    1 - fmPictureSizeModeStretch
    3 - fmPictureSizeModeZoom

    It appears that you can change it manually in the properties window or dynamically at runtime as follows
    With Me.Image1
    .PictureSizeMode = fmPictureSizeModeZoom

  3. Potentially Helpful Related Resource: I tried to recreate a powerpoint with the image controls mentioned, but was having trouble understanding the actual problem that you were having. I had alot of trouble trying to figure out vba form control placement and sizing a few years ago, however i was working in excel rather than power point. I found the following to be a very helpful module for returning screen related parameters.
    you can search for this-> wellsr.com/vba/2019/excel/calculate-screen-size-and-other-display-details-with-vba

    Let me know if that helps any.
    Good luck!

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.