-
Feb 4th, 2017, 01:43 PM
#1
Thread Starter
Fanatic Member
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
-
Feb 4th, 2017, 02:06 PM
#2
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.
-
Feb 4th, 2017, 02:39 PM
#3
Thread Starter
Fanatic Member
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.
-
Feb 4th, 2017, 05:36 PM
#4
Re: Can vb6 detect the DPI?
You can also get the DPI with:
1440 / Screen.TwipsPerPixelX
-
Feb 4th, 2017, 08:38 PM
#5
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.
-
Feb 4th, 2017, 11:21 PM
#6
Re: Can vb6 detect the DPI?
Hello Elroy,
Originally Posted by Elroy
@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.
-
Feb 5th, 2017, 01:41 AM
#7
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.
-
Feb 5th, 2017, 06:55 AM
#8
Re: Can vb6 detect the DPI?
Originally Posted by Elroy
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.
-
Feb 5th, 2017, 07:29 AM
#9
Thread Starter
Fanatic Member
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.
-
Feb 5th, 2017, 07:37 AM
#10
Re: Can vb6 detect the DPI?
Originally Posted by Mustaphi
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.
-
Feb 6th, 2017, 04:45 AM
#11
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!
-
Feb 6th, 2017, 12:27 PM
#12
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.
-
Feb 6th, 2017, 03:15 PM
#13
Thread Starter
Fanatic Member
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.
-
Feb 23rd, 2021, 01:05 AM
#14
New Member
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!
-
Feb 23rd, 2021, 02:33 AM
#15
Re: Can vb6 detect the DPI?
Originally Posted by alcpf
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>
-
Feb 23rd, 2021, 04:31 PM
#16
New Member
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
-
Feb 23rd, 2021, 09:36 PM
#17
New Member
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
-
Feb 24th, 2021, 02:26 AM
#18
Re: Can vb6 detect the DPI?
Originally Posted by alcpf
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.
Originally Posted by alcpf
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>
-
Feb 24th, 2021, 11:01 AM
#19
Re: Can vb6 detect the DPI?
Originally Posted by Mustaphi
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
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|