Consulting

Page 2 of 2 FirstFirst 1 2
Results 21 to 32 of 32

Thread: Scale display vba code

  1. #21
    Public Function ScreenResToZoom(DPIScaler As Double)
        Select Case DPIScaler
            Case Is < 201
                ScreenResToZoom = 100
                then Me.Top = (Application.Height - 75 - Me.Height)
            Case Is < 301
                ScreenResToZoom = 95
                then Me.Top = (Application.Height - 100 - Me.Height)
            Case Is < 401
                ScreenResToZoom = 85
                then Me.Top = (Application.Height - 125 - Me.Height)
            Case Is < 501
                ScreenResToZoom = 70
                then Me.Top = (Application.Height - 150 - Me.Height)
            Case Else
                ScreenResToZoom = 50
                then Me.Top = (Application.Height - 75 - Me.Height)
        End Select
    ActiveWindow.Zoom = ScreenResToZoom
    
     End Function

  2. #22
    i get red lines and when macro is ran its says compile error

    Public Function ScreenResToZoom(DPIScaler As Double)
        Select Case DPIScaler
            Case Is = >100 to 200
                ScreenResToZoom = 100
                then Me.Top = (Application.Height - 75 - Me.Height)  '<------red lines here
            Case Is = >201 to 300
                ScreenResToZoom = 95
                then Me.Top = (Application.Height - 100 - Me.Height)   '<------red lines here
            Case Is = >301 to 400
                ScreenResToZoom = 85
                then Me.Top = (Application.Height - 125 - Me.Height)   '<------red lines here
            Case Is = >401 to 500
                ScreenResToZoom = 70
                then Me.Top = (Application.Height - 150 - Me.Height)   '<------red lines here
            Case Else
                ScreenResToZoom = 50
                then Me.Top = (Application.Height - 75 - Me.Height)   '<------red lines here
        End Select
    ActiveWindow.Zoom = ScreenResToZoom
    
    
    End Function

  3. #23
    remove the word then

  4. #24
    VBAX Expert Dave's Avatar
    Joined
    Mar 2005
    Posts
    833
    Location
    HI CC. I'm not quite sure that you want to change the sheet zoom with changes to the scale? I don't have any large monitors with that high a screen resolution or the need to scale at 400%. My largest monitor with highest scale makes all the sheet rows really thin and requires a change to the sheet zoom just to see them. So I'll assume that's what's needed. I would start with the monitor(s) at 100% scale and see how many rows are visible and then jigger with the "ScreenResToZoom" values at each scale level until the same number of rows are displayed. If you don't want to change the sheet zoom, then I left an example within the "ScreenResToZoom" function where you can adjust the userform display height for each scale (remove the zoom part and the userform placement code in the "ScreenInfo" sub.) .You will need to adjust the userform name to suit. Unfortunately, this is where you find out that the scale factor (and screen resolution) also effects the size of your userform and controls. So you will need to adjust them as well. One thing at a time. HTH. Dave
    Sub ScreenInfo()Dim DPIScale As Double, DPIScale2 As Double
    X = GetSystemMetrics(SM_CXSCREEN)
    Y = GetSystemMetrics(SM_CYSCREEN)
    DPIScale = GetDpi
    If DPIScale <> 96 Then
    DPIScale = (1 + ((DPIScale - 96) / 96)) * 100
    Else
    DPIScale = 100
    End If
    'MsgBox "Screen Resolution: " & X & " x " & Y & vbCrLf _
    & "Scale: " & DPIScale & "%"
    
    
    UserForm1.StartUpPosition = 0
    Call ScreenResToZoom(DPIScale)
    UserForm1.Left = Application.Left + (0.5 * Application.Width) - (0.5 * UserForm1.Width)
    UserForm1.Top = Application.Top + (0.9 * Application.Height) - (0.9 * UserForm1.Height)
    UserForm1.Show
    End Sub
    
    
    Public Function ScreenResToZoom(DPIScaler As Double)
        Select Case DPIScaler
            Case 100
                ScreenResToZoom = 100
            Case 100 To 199
                ScreenResToZoom = 85
                'UserForm1.Left = Application.Left + (0.5 * Application.Width) _
                                                         - (0.5 * UserForm1.Width)
                'UserForm1.Top = Application.Top + (0.9 * Application.Height) _
                                                         - (0.9 * UserForm1.Height)
            Case 200 To 299
                ScreenResToZoom = 70
            Case 300 To 399
                ScreenResToZoom = 55
            Case 400 To 499
                ScreenResToZoom = 40
            Case Else
                ScreenResToZoom = 30
       End Select
    ActiveWindow.Zoom = ScreenResToZoom
    End Function

  5. #25
    THANK YOU Dave and arnelgp! i have been testing and still working on placing position on userforms, just havent had access to the computers with the high resolution. But this is the something that i thought it was impossible to do.
    thank you again. this solved my problem is just a matter of positioning now. nothing provide me with a solution and this forum did, great people around thank you all again for all the responses.

  6. #26
    VBAX Expert Dave's Avatar
    Joined
    Mar 2005
    Posts
    833
    Location
    You are welcome. I never mind helping those that make a determined effort to help themselves. Thanks for posting your outcome. Dave
    ps. I see this thread has become a sticky again?

  7. #27
    Moderator VBAX Wizard Aussiebear's Avatar
    Joined
    Dec 2005
    Location
    Queensland
    Posts
    5,053
    Location
    @Dave, I keep removing it as a sticky as its so unnecessary.
    Remember To Do the Following....
    Use [Code].... [/Code] tags when posting code to the thread.
    Mark your thread as Solved if satisfied by using the Thread Tools options.
    If posting the same issue to another forum please show the link

  8. #28
    VBAX Mentor
    Joined
    Dec 2008
    Posts
    404
    Location
    chubbychub, I can't quite understand where you want to display the Userform on the screen. From the attached image in post #9, you can see that you want to place the Userform near the bottom edge. In post #12 you are combining to make the Userform appear in different places on the screen, depending on the scale you read.
    The rest of my post is about placing the Userform close to the bottom edge of the screen. With such an assumption, knowing the scale seems unnecessary. It is enough to read the displayed resolution (it is expressed in px), convert this to points (pt) and display the form in the appropriate place. The following code displays the form near the bottom edge of the screen regardless of the resolution and scale used
    Option Explicit
    
    Private Declare Function GetDC Lib "user32" _
                                   (ByVal hwnd As Long) As Long
    
    Private Declare Function GetDeviceCaps Lib "gdi32" _
                                           (ByVal hDC As Long, _
                                            ByVal nIndex As Long) As Long
    
    Private Declare Function ReleaseDC Lib "user32" _
                                       (ByVal hwnd As Long, _
                                        ByVal hDC As Long) As Long
    
    Private Declare Function GetSystemMetrics Lib "user32" _
                                              (ByVal nIndex As Long) As Long
    
    Private Const LOGPIXELSX = 88    'px/logical inch
    Private Const POINTS_PER_INCH As Long = 72    '1pt=1/72 inch
    
    
    Sub ShowForm()
        Dim ScrWidth    As Single    'in pt
        Dim ScrHeight   As Single    'in pt
        Dim PpP         As Single
        Dim X           As Long    'in px
        Dim Y           As Long    'in px
    
        PpP = PointsPerPixel
        Call ScreenRes(X, Y)
    
        ScrWidth = X * PpP    ' in pt
        ScrHeight = Y * PpP    'in pt
    
        With UserForm1
            .StartUpPosition = 0
            .Top = ScrHeight - .Height - 20    ' in pt
            .Left = (ScrWidth - .Width) / 2    ' in pt
            .Show    'vbModeless
        End With
    
    End Sub
    
    
    Function ScreenRes(X As Long, Y As Long) As String
        Const SM_CXSCREEN = 0
        Const SM_CYSCREEN = 1
    
        X = GetSystemMetrics(SM_CXSCREEN)
        Y = GetSystemMetrics(SM_CYSCREEN)
        ScreenRes = X & " x " & Y
    End Function
    
    
    Function PointsPerPixel() As Double
        Dim hDC         As Long
        Dim lDotsPerInch As Long
    
        hDC = GetDC(0)
        lDotsPerInch = GetDeviceCaps(hDC, LOGPIXELSX)
        PointsPerPixel = POINTS_PER_INCH / lDotsPerInch
        ReleaseDC 0, hDC
    
    End Function

    About the scale.
    On mine (Win 10), the GetDpi function, or more precisely the winAPI GetDeviceCaps function, always returns 96 regardless of the scale set. This may have made sense in the past (below Win 8). I can't check on an 8.1 system (because I don't have it anymore), but the function below should return a DPI that depends on the scale used. Unfortunately, it doesn't work properly in Win 10.
    Option Explicit
    
    'Probably only Win 8.1 - not tested!
    Private Declare PtrSafe Function GetDpiForMonitor Lib "shcore.dll" _
            (ByVal hMonitor As LongPtr, _
             ByVal dpiType As Long, _
             ByRef dpiX As Long, _
             ByRef dpiY As Long) As Long
    
    Private Declare PtrSafe Function MonitorFromWindow Lib "user32.dll" _
            (ByVal hwnd As LongPtr, _
             ByVal dwFlags As Long) As Long
    
    
    Sub TestScale()
        MsgBox GetWinScale(GetMonitorDPI) & " %"
    End Sub
    
    
    Function GetMonitorDPI() As Long
        Dim hMonitor    As LongPtr
        Dim dpiX        As Long
        Dim dpiY        As Long
    
        hMonitor = MonitorFromWindow(Application.hwnd, &H2)
        GetDpiForMonitor hMonitor, 0, dpiX, dpiY
        GetMonitorDPI = dpiX
    End Function
    
    
    Function GetWinScale(DPI As Long) As Long
        GetWinScale = 100 * DPI / 96
    End Function
    For Win 10:
    Option Explicit
    
    'Only Win 10 or greater
    Private Declare PtrSafe Function GetDpiForWindow Lib "user32.dll" _
            (ByVal hwnd As LongPtr) As Long
    
    
    Sub TestScale()
      MsgBox GetWinScale(GetMonitorDPI) & " %"
    End Sub
    
    
    Function GetMonitorDPI() As Long
        GetMonitorDPI = GetDpiForWindow(Application.hwnd)
    End Function
    
    
    Function GetWinScale(DPI As Long) As Long
        GetWinScale = 100 * DPI / 96
    End Function
    For now, I think that for the purpose of the OP task, knowledge of scale is not needed.


    Artik

  9. #29
    VBAX Expert Dave's Avatar
    Joined
    Mar 2005
    Posts
    833
    Location
    Artic thanks for posting the new API's. The GetDPI function worked until XL version 12 (07 the start of VBA7 and probably related to the MS OS change at the same time) and then always returned 96 (see my post #14). I was surprised to find it working again when I started messing around with code for this thread on Windows 11. The GetDPI also works fine on my 2 laptops with Windows 10. Your "new" API function code also work on my Windows 10 so perhaps it's a Windows 10 update version thing for you. I tend to agree with your summation but I am unable to test the real world conditions. I also use the PointPerPixel routine in combo with the screen resolution to adjust the userform size. Again, thanks. Dave

  10. #30
    Quote Originally Posted by chubbychub View Post
    I have different display Scale level, some monitors at 100%, other s at 200%, others at 175%, others at 300 %, and userform dont display when the userform is set on the bottom of the excel sheet, (the resolution on this screen are the same at 3840 x2160 on all the screens but not SCALE)
    i dont want the userform to appear in the middle, if there was a code to obtain the SCALE level , then i can put a vba code to position the userform according to scale level with a IF and else statement to position the userform accordingly. If someone can help me to code in vba about obtaining windows 11 scale level with 64bit excel 2019 please.

    P.D. I have google for a couple of days and all vba code that i have found is regarding screen resolution and pixels.
    Obtaining the scale level in VBA to position the userform correctly on different monitors with varying scaling settings can be a bit challenging, as there is no direct VBA method to retrieve the scale level in Windows. However, there is a workaround you can try using the Windows API.
    Last edited by Aussiebear; 07-04-2023 at 12:08 PM. Reason: Removed spam link

  11. #31
    VBAX Sage
    Joined
    Apr 2007
    Location
    United States
    Posts
    8,724
    Location
    Fixed syntax errors so at least it compiles. Not tested

    1. Sub instead of Function seems better
    2. The # is code for Double, the editor turns 100.0 into 100#
    3. No 'Then' on regular Case ....
    4. An input value of 200.5 would fall through and hit the 'Else' which you probably don't want
    5. Not sure what the 'Me.' refers to, but most likely a UserForm??

    Option Explicit
    
    
    Public Sub ScreenResToZoom(DPIScaler As Double)
        Select Case DPIScaler
            Case 100# To 200#
                ScreenResToZoom = 100
                Me.Top = (Application.Height - 75 - Me.Height)
            Case 200# To 300#
                ScreenResToZoom = 95
                Me.Top = (Application.Height - 100 - Me.Height)
            Case 300# To 400#
                ScreenResToZoom = 85
                Me.Top = (Application.Height - 125 - Me.Height)
            Case 400# To 500#
                ScreenResToZoom = 70
                Me.Top = (Application.Height - 150 - Me.Height)
            Case Else
                ScreenResToZoom = 50
                Me.Top = (Application.Height - 75 - Me.Height)
        End Select
    
    
    ActiveWindow.Zoom = ScreenResToZoom
    
    
    
    
    End Sub
    ---------------------------------------------------------------------------------------------------------------------

    Paul


    Remember: Tell us WHAT you want to do, not HOW you think you want to do it

    1. Use [CODE] ....[/CODE ] Tags for readability
    [CODE]PasteYourCodeHere[/CODE ] -- (or paste your code, select it, click [#] button)
    2. Upload an example
    Go Advanced / Attachments - Manage Attachments / Add Files / Select Files / Select the file(s) / Upload Files / Done
    3. Mark the thread as [Solved] when you have an answer
    Thread Tools (on the top right corner, above the first message)
    4. Read the Forum FAQ, especially the part about cross-posting in other forums
    http://www.vbaexpress.com/forum/faq...._new_faq_item3

  12. #32
    the below code worked, after a few months of changing and twisting things and trying to figure out, i finally figure out what was wrong and end up using the code below. The problem was for some reason when ran as admin, the userform didnt even show up on the screen (it was way off screen) in 8K monitors but it would appear at the bottom screen in 4k monitors and everything below 4k resolutions. but running WITHOUT admin priviledges, then the below code worked fine in ALL monitors without the windows 11 (admin prompt when opening the .XLMT file. )
    my systems configurations :
    Device name ChubbChu
    Processor 12th Gen Intel(R) Core(TM) i9-12900K 3.19 GHz
    Installed RAM 128 GB (128 GB usable)
    Device ID xxxxxxxxxxxxxxxxxxxxxx
    Product ID xxxxxxxxxxxxxxxxxxxxx
    System type 64-bit operating system, x64-based processor
    Pen and touch No pen or touch input is available for this display

    with microsoft office 2021 on windows 11

    Private Sub UserForm_Initialize()
    
    
        Me.StartUpPosition = 0
        'Me.Top = (Application.Height - Me.Height) / 2
        Me.Top = (Application.Height - 75 - Me.Height)  ''this is to move up or down
    '    Me.Left = (Application.Width - Me.Width) / 2  '''''this is to move left or right
        Me.Left = Int(((Application.Width / 2) + Application.Left - 100) - (FlooringForm.Width / 2)) '''this is for center of application
        Me.BoxesTotal.Locked = True
    End Sub
    quote from Artic "The rest of my post is about placing the Userform close to the bottom edge of the screen. With such an assumption, knowing the scale seems unnecessary. It is enough to read the displayed resolution (it is expressed in px), convert this to points (pt) and display the form in the appropriate place. The following code displays the form near the bottom edge of the screen regardless of the resolution and scale used",
    thank you for this input, as you made sense and made me think of testing other things to find the problem or the compatibility of windows 11.

    thank you all for answering, Paul_hosser,
    Haval1957, Dave, Artik, Aussiebear, and arnelgp
    i added reputation, but forum didnt allow me to give out so much reputation points to everyone but i come bakc and add it in a few days.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •