Results 1 to 19 of 19

Thread: Can vb6 detect the DPI?

  1. #1

    Thread Starter
    Fanatic Member
    Join Date
    Jan 2016
    Posts
    753

    Can vb6 detect the DPI?

    Hello experts of vb6
    I'm working with a medium DPI 125% and everything looks pretty with a screen set on this DPI.
    However things looks very ugly if the DPI is higher or lower.
    I wonder if it is possible to detect the DPI of the user's machine and then suggest him to change the DPI to get a good displaying.
    thank you very much

  2. #2
    PowerPoster Elroy's Avatar
    Join Date
    Jun 2014
    Location
    Near Nashville TN
    Posts
    9,853

    Re: Can vb6 detect the DPI?

    This'll get your DPI, with 96 being 100%.

    I've got code to set/change it too, but I've got to get out of here. If someone else hasn't provided it by the time I get back, I'll give it to you.

    Code:
    
    Option Explicit
    '
    Private Declare Function GetDesktopWindow Lib "user32" () As Long
    Private Declare Function GetDC Lib "user32" (ByVal hWnd As Long) As Long
    Private Declare Function ReleaseDC Lib "user32" (ByVal hWnd As Long, ByVal hdc As Long) As Long
    Private Declare Function GetDeviceCaps Lib "gdi32" (ByVal hdc As Long, ByVal nIndex As Long) As Long
    
    Public Function DPI() As Long
        Const LOGPIXELSX = 88
        Dim hWndDesktop As Long
        Dim hDCDesktop As Long
        '
        hWndDesktop = GetDesktopWindow()
        hDCDesktop = GetDC(hWndDesktop)
        DPI = GetDeviceCaps(hDCDesktop, LOGPIXELSX)
        ReleaseDC hWndDesktop, hDCDesktop
    End Function
    
    Private Sub Form_Load()
        MsgBox DPI
    End Sub
    
    
    Any software I post in these forums written by me is provided "AS IS" without warranty of any kind, expressed or implied, and permission is hereby granted, free of charge and without restriction, to any person obtaining a copy. To all, peace and happiness.

  3. #3

    Thread Starter
    Fanatic Member
    Join Date
    Jan 2016
    Posts
    753

    Re: Can vb6 detect the DPI?

    Thank you very much sir .
    Your code is fabulous.
    I'll be so grateful to you if you submit the code that can change it.

  4. #4
    PowerPoster
    Join Date
    Feb 2017
    Posts
    4,996

    Re: Can vb6 detect the DPI?

    You can also get the DPI with:

    1440 / Screen.TwipsPerPixelX

  5. #5
    PowerPoster Elroy's Avatar
    Join Date
    Jun 2014
    Location
    Near Nashville TN
    Posts
    9,853

    Re: Can vb6 detect the DPI?

    @Eduardo: Your way will work 99% of the time. However, Screen.TwipsPerPixelX does not return correct information in certain circumstances. Specifically, if you change your monitor to portrait mode or possibly run things in a tablet (with Windows of course), Screen.TwipsPerPixelX sometimes gets fouled up. Just an FYI.

    @Mustaphi: The following is some very old code I dug up to actually change the DPI setting. When it was being used, it worked well. However, I haven't actually used it in many years. These days, all that's typically required is a logoff (and not a complete reboot) to change the DPI. The following code doesn't recognize this. You may be able to search around and find some better alternatives. But, here it is. You should be able to throw it into a standard BAS module and be all set.

    Code:
    
    Option Explicit
    '
    Private Type OSVERSIONINFO
        dwOSVersionInfoSize As Long
        dwMajorVersion As Long
        dwMinorVersion As Long
        dwBuildNumber As Long
        dwPlatformId As Long
        szCSDVersion As String * 128
    End Type
    '
    Private Type LUID
        UsedPart As Long
        IgnoredForNowHigh32BitPart As Long
    End Type
    '
    Private Type TOKEN_PRIVILEGES
        PrivilegeCount As Long
        TheLuid As LUID
        Attributes As Long
    End Type
    '
    Private Declare Function SetupChangeFontSize Lib "syssetup" (HWindow As Long, lpszFontSize As Long) As Long ' lpszFontSize must be UNICODE!! - actually the StrPtr function must be used to pass UNICODE.
    Private Declare Function GetVersionExA Lib "kernel32" (lpVersionInformation As OSVERSIONINFO) As Integer
    Private Declare Function ExitWindowsEx Lib "user32" (ByVal uFlags As Long, ByVal dwReserved As Long) As Long
    Private Declare Function GetCurrentProcess Lib "kernel32" () As Long
    Private Declare Function OpenProcessToken Lib "advapi32" (ByVal ProcessHandle As Long, ByVal DesiredAccess As Long, TokenHandle As Long) As Long
    Private Declare Function LookupPrivilegeValue Lib "advapi32" Alias "LookupPrivilegeValueA" (ByVal lpSystemName As String, ByVal lpName As String, lpLuid As LUID) As Long
    Private Declare Function AdjustTokenPrivileges Lib "advapi32" (ByVal TokenHandle As Long, ByVal DisableAllPrivileges As Long, NewState As TOKEN_PRIVILEGES, ByVal BufferLength As Long, PreviousState As TOKEN_PRIVILEGES, ReturnLength As Long) As Long
    '
    Private Const ERROR_SUCCESS = 0
    '
    Private Const EWX_LOGOFF = 0
    Private Const EWX_SHUTDOWN = 1
    Private Const EWX_REBOOT = 2
    Private Const EWX_FORCE = 4
    '
    
    Public Function ChangeDPI(iPixelsXSize As Integer) As Integer
        ' Any return means trouble, unless they are already set.
        ' 1 = error calling syssetup.dll (SetupChangeFontSize).
        ' 2 = error re-booting the computer.
        ' 3 = error because Windows NT is needed to use this function.
        Dim ret As Long
        Dim errval As Long
        Dim SFontSize As String
        '
        SFontSize = Format$(iPixelsXSize, "###")
        '
        Select Case WindowsPlatform
        Case "NT"
            On Error Resume Next
            Err = 0
            ret = SetupChangeFontSize(0, StrPtr(SFontSize))
            errval = Err
            On Error GoTo 0
        Case "9X"
            ChangeDPI = 3
            Exit Function ' This only works in NT/2000/XP because syssetup.dll is needed.
        Case Else
            ChangeDPI = 3
            Exit Function ' This only works in NT/2000/XP because syssetup.dll is needed.
        End Select
        '
        If ret <> ERROR_SUCCESS Or errval <> 0 Then
            ChangeDPI = 1
        Else
            ShutdownWindows EWX_LOGOFF Or EWX_REBOOT Or EWX_FORCE
            ChangeDPI = 2
        End If
    End Function
    
    Public Function WindowsPlatform() As String
        Dim osinfo As OSVERSIONINFO
        '
        osinfo.dwOSVersionInfoSize = 148
        osinfo.szCSDVersion = Space$(128)
        GetVersionExA osinfo
        '
        Select Case osinfo.dwPlatformId
        Case 1
            WindowsPlatform = "9X" ' Includes ME
        Case 2
            WindowsPlatform = "NT" ' Includes 2000 and XP
        Case Else
            WindowsPlatform = "Failed"
        End Select
    End Function
    
    Public Sub ShutdownWindows(lFlags As Long)
        If WindowsPlatform = "NT" Then
            AdjustTokenForNTShutdown
            ExitWindowsEx lFlags, &HFFFF
        Else
            ExitWindowsEx lFlags, 0
        End If
    End Sub
    
    Private Sub AdjustTokenForNTShutdown()
        Const TOKEN_ADJUST_PRIVILEGES = &H20
        Const TOKEN_QUERY = &H8
        Const SE_PRIVILEGE_ENABLED = &H2
        Dim hdlProcessHandle As Long
        Dim hdlTokenHandle As Long
        Dim tmpLuid As LUID
        Dim tkp As TOKEN_PRIVILEGES
        Dim tkpNewButIgnored As TOKEN_PRIVILEGES
        Dim lBufferNeeded As Long
        '
        If WindowsPlatform <> "NT" Then Exit Sub
        '
        hdlProcessHandle = GetCurrentProcess()
        OpenProcessToken hdlProcessHandle, (TOKEN_ADJUST_PRIVILEGES Or TOKEN_QUERY), hdlTokenHandle
        ' Get the LUID for shutdown privilege.
        LookupPrivilegeValue "", "SeShutdownPrivilege", tmpLuid
        '
        tkp.PrivilegeCount = 1    ' One privilege to set
        tkp.TheLuid = tmpLuid
        tkp.Attributes = SE_PRIVILEGE_ENABLED
        ' Enable the shutdown privilege in the access token of this process.
        AdjustTokenPrivileges hdlTokenHandle, False, _
        tkp, Len(tkpNewButIgnored), tkpNewButIgnored, lBufferNeeded
    End Sub
    
    
    Enjoy,
    Elroy
    Any software I post in these forums written by me is provided "AS IS" without warranty of any kind, expressed or implied, and permission is hereby granted, free of charge and without restriction, to any person obtaining a copy. To all, peace and happiness.

  6. #6
    PowerPoster
    Join Date
    Feb 2017
    Posts
    4,996

    Re: Can vb6 detect the DPI?

    Hello Elroy,

    Quote Originally Posted by Elroy View Post
    @Eduardo: Your way will work 99% of the time. However, Screen.TwipsPerPixelX does not return correct information in certain circumstances. Specifically, if you change your monitor to portrait mode or possibly run things in a tablet (with Windows of course), Screen.TwipsPerPixelX sometimes gets fouled up. Just an FYI.
    Do you have a link to information about this issue? I find it very weird.
    I cannot change the desktop orientation in my PC to test the issue (XP). It must be a driver feature that allows to change the monitor orientation.

    I guess that you don't use Object.ScaleX either.

    PS: What I know is that TwipsPerPixelX/Y won't return the right number when it should be non integer, for example 7.5, because it returns an integer number.
    But in that case the whole VB6 program will behave incorrectly.
    Last edited by Eduardo-; Feb 4th, 2017 at 11:32 PM.

  7. #7
    PowerPoster Elroy's Avatar
    Join Date
    Jun 2014
    Location
    Near Nashville TN
    Posts
    9,853

    Re: Can vb6 detect the DPI?

    Hi Eduardo,

    I'm not sure I could find any documentation, but I just remember back several years ago I ran into this problem.

    I was developing a VB6 app for an IBM ThinkPad which we intended to be used in portrait mode. This was actually a nice computer, and one of the very first tablets (even before iPad). Compared to modern day tablets, it was thick, but it did run a full version of Windows.

    What I learned was that, in VB6, the Screen object didn't pick up the changes to orientation (portrait vs landscape). However, if you made API calls, you could figure it out. Ever since then, I've pretty much abandoned the Screen object for trying to figure out any dimensional stuff about the screen. It may be only dynamic changes (changes without a reboot or relog) that foul it up, but that was enough for me to use the API approach.

    Also, I'm in the process of developing a complete set of functions to find out just about anything you'd want to know about a monitor. I've got some of it posted, but more will be coming shortly. That can be found here.

    Best Regards,
    Elroy
    Any software I post in these forums written by me is provided "AS IS" without warranty of any kind, expressed or implied, and permission is hereby granted, free of charge and without restriction, to any person obtaining a copy. To all, peace and happiness.

  8. #8
    PowerPoster
    Join Date
    Feb 2017
    Posts
    4,996

    Re: Can vb6 detect the DPI?

    Quote Originally Posted by Elroy View Post
    It may be only dynamic changes (changes without a reboot or relog) that foul it up
    Sure. VB is not ready to handle that "on the fly".

    To be able to change the DPI setting without restarting the computer is someting introduced much later, I think it was in Windows 8 or 10.

    Anyway I think that the whole program will have problems in such a case, because it's not just TwipsPerPixelX, it's the size of the fonts, controls, Etc. that VB handles automatically according to the DPI setting.
    Last edited by Eduardo-; Feb 5th, 2017 at 07:39 AM.

  9. #9

    Thread Starter
    Fanatic Member
    Join Date
    Jan 2016
    Posts
    753

    Re: Can vb6 detect the DPI?

    I tested the code but it failed to change the DPI.
    After a reboot the DPI remains the same.
    I 'm using W7.
    I googled for long hours hoping to find anything but nothing is published for this purpose.
    Anyway thank you a lot sir.

  10. #10
    PowerPoster
    Join Date
    Feb 2017
    Posts
    4,996

    Re: Can vb6 detect the DPI?

    Quote Originally Posted by Mustaphi View Post
    Hello experts of vb6
    I'm working with a medium DPI 125% and everything looks pretty with a screen set on this DPI.
    However things looks very ugly if the DPI is higher or lower.
    I wonder if it is possible to detect the DPI of the user's machine and then suggest him to change the DPI to get a good displaying.
    thank you very much
    The best would be to prepare your program to work in different DPI settings.
    To start, one important rule to let VB handle most of the things regarding to DPI is to work in Twips.

  11. #11
    PowerPoster Arnoutdv's Avatar
    Join Date
    Oct 2013
    Posts
    5,872

    Re: Can vb6 detect the DPI?

    I wonder if it is possible to detect the DPI of the user's machine and then suggest him to change the DPI to get a good displaying.
    You are not only detecting the DPI, you also want to change it!
    That's is not what applications are supposed to do, very bad manners!

    The best would be to prepare your program to work in different DPI settings.
    Indeed!

  12. #12
    PowerPoster Elroy's Avatar
    Join Date
    Jun 2014
    Location
    Near Nashville TN
    Posts
    9,853

    Re: Can vb6 detect the DPI?

    Mustaphi,

    Ahh, I'm sorry that code didn't work in post #5. Like I said, it's been many years since I've used it, and Windows security issues have been greatly tweaked in recent years. I'm not really sure but you may need to be an administrator or possibly need UAC elevation to change these things. I'm rather busy today, but I may get motivated to look into it. If you find something before I do, please be sure to post it here.

    Good Luck,
    Elroy
    Any software I post in these forums written by me is provided "AS IS" without warranty of any kind, expressed or implied, and permission is hereby granted, free of charge and without restriction, to any person obtaining a copy. To all, peace and happiness.

  13. #13

    Thread Starter
    Fanatic Member
    Join Date
    Jan 2016
    Posts
    753

    Re: Can vb6 detect the DPI?

    If you find something before I do, please be sure to post it here.
    Believe me sir I spent almost a whole day trying to find something but in vain.
    Thanks a lot for your help.

  14. #14
    New Member
    Join Date
    Feb 2021
    Posts
    10

    Re: Can vb6 detect the DPI?

    Hello,
    This post it's very old but I have a doubt about DPI in VB6 wit win 10 64bits... I tested that code above but all the time receive the value of 96 but I have defined my screen scale for 150...
    If I use that code in the VBA (office2019) it shows 144... How this is possible? Is that functions in vb6 incompatible with win10 or 64bits?
    Anyone have solution for that?
    Thank you!

  15. #15
    PowerPoster wqweto's Avatar
    Join Date
    May 2011
    Location
    Sofia, Bulgaria
    Posts
    5,120

    Re: Can vb6 detect the DPI?

    Quote Originally Posted by alcpf View Post
    Hello,
    This post it's very old but I have a doubt about DPI in VB6 wit win 10 64bits... I tested that code above but all the time receive the value of 96 but I have defined my screen scale for 150...
    If I use that code in the VBA (office2019) it shows 144... How this is possible? Is that functions in vb6 incompatible with win10 or 64bits?
    Anyone have solution for that?
    Thank you!
    You'll need to add manifest file/resource to your application to mark it as dpiAware otherwise the OS will lie about current DPI.

    Same for the IDE, you have to manifest VB6.EXE with an external manifest file to be able to test any code that retrieves current DPI.

    Search the forums here, there are a lot of threads about manifests, e.g. here is my VB6.exe.manifest as placed in C:\Program Files (x86)\Microsoft Visual Studio\VB98 folder

    Code:
    <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
    <assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0" xmlns:asmv3="urn:schemas-microsoft-com:asm.v3">
    	<assemblyIdentity 
    		version="2002.10.0.25" 
    		processorArchitecture="X86" 
    		name="vb6.exe" 
    		type="win32" />
    	<description>WindowsExecutable</description>
    	<dependency>
    		<dependentAssembly>
    			<assemblyIdentity 
    				type="win32" 
    				name="Microsoft.Windows.Common-Controls" 
    				version="6.0.0.0" 
    				processorArchitecture="X86" 
    				publicKeyToken="6595b64144ccf1df" 
    				language="*" />
    		</dependentAssembly>
    	</dependency>
        <asmv3:application>
            <asmv3:windowsSettings xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">
                <dpiAware>true</dpiAware>
            </asmv3:windowsSettings>
        </asmv3:application>
        <compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
            <application>
                <supportedOS Id="{e2011457-1546-43c5-a5fe-008deee3d3f0}" />
                <supportedOS Id="{35138b9a-5d96-4fbd-8e2d-a2440225f93a}" />
                <supportedOS Id="{4a2f28e3-53b9-4441-ba9c-d69d4a4a6e38}" />
                <supportedOS Id="{1f676c76-80e1-4239-95bb-83d0f6d0da78}" />
                <supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}" />
            </application>
        </compatibility>
    </assembly>
    cheers,
    </wqw>

  16. #16
    New Member
    Join Date
    Feb 2021
    Posts
    10

    Re: Can vb6 detect the DPI?

    Oh I see! Awesome! Thank you very much
    I lost days around this problem and many more for sure would come if was not your answer. I tested with others computers and changed video drivers and many other things... and all the time received the frustrated same value grrrrr........
    Thank you!
    Cheers

  17. #17
    New Member
    Join Date
    Feb 2021
    Posts
    10

    Re: Can vb6 detect the DPI?

    I did all you said above. My vb6.exe is now with your manifest but in resource mode and works fine.
    The software made in vb6.exe and compiled, it works too with the resource mode or manifest but I don't know why, the visual style not appear in the manifest mode but and in resource mode, shows perfectly! But the xml is exactly the same! Strange!
    I did also with the declaration setprocessdpiaware and works perfectly too and in this case not need the xml!
    But a problem that I found is case the program is running and I change the DPI, any examples above will not show me the correct value but the value when started the program. For show the correct values I need close the program and start again... Exist any other way to bypass that problem? it's not a big deal because will not change all the time the dpi.....
    In attachment I send the script with example and executable with manifest and in resource for the case of anyone need too or analise and fix something.Project original.zip

  18. #18
    PowerPoster wqweto's Avatar
    Join Date
    May 2011
    Location
    Sofia, Bulgaria
    Posts
    5,120

    Re: Can vb6 detect the DPI?

    Quote Originally Posted by alcpf View Post
    The software made in vb6.exe and compiled, it works too with the resource mode or manifest but I don't know why, the visual style not appear in the manifest mode but and in resource mode, shows perfectly! But the xml is exactly the same! Strange!
    Manifests are aggressively cached by the system keyed on process image (the .exe file) i.e. you have to either restart the OS or use touch.exe or similar utility to modify last modified date/time on the .exe for the old manifest settings to get flushed.

    Quote Originally Posted by alcpf View Post
    But a problem that I found is case the program is running and I change the DPI, any examples above will not show me the correct value but the value when started the program.
    You might have to try other values for manifest settings (e.g. PerMonitor) but I cannot tell you which combination of dpiAware vs dpiAwareness vs supportedOS marks the process with anything more that system-wide DPI aware.

    https://docs.microsoft.com/en-us/win...-for-a-process
    https://docs.microsoft.com/en-us/win...ent-on-windows

    There is WM_DPICHANGED = &H02E0 notification too which requires something like this to fire

    <dpiAware>True/PM</dpiAware>
    <dpiAwareness xmlns="http://schemas.microsoft.com/SMI/2016/WindowsSettings">PerMonitorV2,PerMonitor</dpiAwareness>

    cheers,
    </wqw>

  19. #19
    PowerPoster
    Join Date
    Feb 2006
    Posts
    24,482

    Re: Can vb6 detect the DPI?

    Quote Originally Posted by Mustaphi View Post
    I'm working with a medium DPI 125% and everything looks pretty with a screen set on this DPI.
    However things looks very ugly if the DPI is higher or lower.
    I wonder if it is possible to detect the DPI of the user's machine and then suggest him to change the DPI to get a good displaying.
    thank you very much
    What?

    This seems like a poor way to address the matter. If you can't handle DPI directly or through GDI Scaling there should be a "warning on the tin" (advertising, installation screen, etc.). Something like:

    "This program is broken and feeble.
    It looks like crap at anything but 125% DPI settings.
    I'd turn back if I were you."

    You cannot develop at anything but 100% (96) DPI and get good results without a lot of fiddling, no matter how you try to handle High DPI settings.

    I understand how hard it can be if you don't have perfect vision and you use a monitor with gratuitously high resolution. Your development monitor should come very close to 96 native pixels (or less) per physical screen inch. Use the high-res monitor for testing and other uses.

Posting Permissions

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



Click Here to Expand Forum to Full Width