Winamp & Shoutcast Forums NSIS on HiDPI displays

 18th July 2017, 09:37 #1 mgrand Junior Member   Join Date: Jul 2017 Posts: 8 NSIS on HiDPI displays Hello guys, With the growth of HiDPI monitors, I'd like to have my NSIS installer compatible and running to its full potential. As suggested by the documentation, I added code:ManifestDPIAware true to my script and it works well for most of the GUI. However, I'm running into 2 issues: - I provided welcome and header bitmaps at twice the recommended size, and it works on HiDPI displays. But on standard displays, the downsampling applied looks very cheap to me and I would prefer to provide separate bitmaps for each scale factor, is that possible? - The checkboxes used in components page are not rescaled on HiDPI (they appear very small). Is there a way to use native Windows checkboxes instead of bitmaps? Thanks for the help
 18th July 2017, 10:25 #2 JasonFriday13 Major Dude     Join Date: May 2005 Location: New Zealand Posts: 891 For the checkboxes, I had a quick look at the code and the image list seems to be hardcoded to 16x16. I guess if the scaled size of the treeview can be retrieved, then the check bitmap could be resized in memory and then applied to the treeview. This also depends on how old the OS is as to how well this would work. "Only a MouseHelmet will save you from a MouseTrap" -Jason Ross (Me) NSIS 3 POSIX Ninja Wiki Profile
 18th July 2017, 11:25 #3 Anders Moderator     Join Date: Jun 2002 Location: ${NSISDIR} Posts: 5,296 I tried to create a "native" checkbox plug-in years ago but I never finished it because the theme API does not really support flat checkboxes IIRC. IntOp$PostCount $PostCount + 1  29th July 2017, 13:57 #4 mgrand Junior Member Join Date: Jul 2017 Posts: 8 It would be a nice addition to have flat checkboxes support. Looks like the only missing piece to a fully native-looking GUI. Any ideas about welcome & header bitmaps? What's the proper way to have those bitmaps compatible with HiDPI diplays?  29th July 2017, 19:15 #5 Anders Moderator Join Date: Jun 2002 Location:${NSISDIR} Posts: 5,296 There are some stretch options for the bitmap IIRC but it is never going to look great. You could have images of multiple sizes and extract in .onInit I guess. IntOp $PostCount$PostCount + 1
31st July 2017, 15:52   #6
Anders
Moderator

Join Date: Jun 2002
Location: ${NSISDIR} Posts: 5,296 PHP Code:  !include LogicLib.nsh System::Call USER32::GetDpiForSystem()i.r0${If} $0 U<= 0 System::Call USER32::GetDC(i0)i.r1 System::Call GDI32::GetDeviceCaps(ir1,i88)i.r0 System::Call USER32::ReleaseDC(i0,ir1)${EndIf} MessageBox mb_ok SysDpi=$0  and extract with a size based on https://msdn.microsoft.com/en-us/lib...px#CLOSEST_FIT Quote:  int iSourceImageDPIToUse = 96; // We will assume 96 by default. if (gDPI > 144) iSourceImageDPIToUse = 192; else if (gDPI > 120) iSourceImageDPIToUse = 144; else if (gDPI > 96) iSourceImageDPIToUse = 120; IntOp$PostCount $PostCount + 1  3rd August 2017, 12:53 #7 mgrand Junior Member Join Date: Jul 2017 Posts: 8 Thanks! I will try that  5th August 2017, 18:11 #8 Anders Moderator Join Date: Jun 2002 Location:${NSISDIR} Posts: 5,296 I looked at what it takes to create this plug-in again and even before I get to the theme stuff I see that the classic DrawFrameControl function does not know how to draw read-only checkboxes so some post paint tweaking will be required. IntOp $PostCount$PostCount + 1
 6th August 2017, 13:32 #9 mgrand Junior Member   Join Date: Jul 2017 Posts: 8 If anybody interested, here is the piece of code I used to show different bitmaps according to the DPI setting PHP Code:  ManifestDPIAware true !define MUI_PAGE_CUSTOMFUNCTION_SHOW showHiDpi !insertmacro MUI_PAGE_WELCOME !insertmacro MUI_PAGE_LICENSE "Resource\license.rtf" !insertmacro MUI_PAGE_COMPONENTS !insertmacro MUI_PAGE_INSTFILES !define MUI_PAGE_CUSTOMFUNCTION_SHOW showHiDpi !insertmacro MUI_PAGE_FINISH Function .onInit     File /oname=$PLUGINSDIR\welcome96.bmp Resource\welcome96.bmp File /oname=$PLUGINSDIR\welcome120.bmp Resource\welcome120.bmp     File /oname=$PLUGINSDIR\welcome144.bmp Resource\welcome144.bmp File /oname=$PLUGINSDIR\welcome192.bmp Resource\welcome192.bmp     File /oname=$PLUGINSDIR\header96.bmp Resource\header96.bmp File /oname=$PLUGINSDIR\header120.bmp Resource\header120.bmp     File /oname=$PLUGINSDIR\header144.bmp Resource\header144.bmp File /oname=$PLUGINSDIR\header192.bmp Resource\header192.bmp FunctionEnd Function showHiDpi     System::Call USER32::GetDpiForSystem()i.r0      ${If}$0 U<= 0          System::Call USER32::GetDC(i0)i.r1          System::Call GDI32::GetDeviceCaps(ir1,i88)i.r0          System::Call USER32::ReleaseDC(i0,ir1)      ${EndIf}${Unless} $0 == 120${AndUnless} $0 == 144${AndUnless} $0 == 192 StrCpy$0 96     ${EndIf}${NSD_SetImage} $mui.WelcomePage.Image$PLUGINSDIR\welcome$0.bmp$mui.WelcomePage.Image.Bitmap     ${NSD_SetImage}$mui.FinishPage.Image $PLUGINSDIR\welcome$0.bmp $mui.FinishPage.Image.Bitmap SetBrandingImage /IMGID=1046 "$PLUGINSDIR\header$0.bmp" FunctionEnd  Also, it's important to note that HiDPI bitmaps size is not exactly the standard size multiplied by the scaling factor. Here are the values I used to fit perfectly (at least on Windows 10): Header bitmap: 96dpi: 150x57 120dpi: 175x70 144dpi: 225x83 192dpi: 300x109 Welcome/Finish bitmap: 96dpi: 164x314 120dpi: 191x386 144dpi: 245x458 192dpi: 327x603  6th August 2017, 13:57 #10 Anders Moderator Join Date: Jun 2002 Location:${NSISDIR} Posts: 5,296 I would strongly recommend that you use the algorithm I posted, use >=, not == and pick the largest image you can fit. IntOp $PostCount$PostCount + 1
6th August 2017, 17:58   #11
mgrand
Junior Member

Join Date: Jul 2017
Posts: 8
It looks good! Checkboxes scale correctly with the DPI.
Are they native Windows controls or custom drawing?

Quote:
 Originally Posted by Anders I would strongly recommend that you use the algorithm I posted, use >=, not == and pick the largest image you can fit.
Right, thanks
Attached Thumbnails

6th August 2017, 14:16   #12
Anders
Moderator

Join Date: Jun 2002
Location: ${NSISDIR} Posts: 5,296 Here is a very basic attempt to do native checkboxes, only classic style for now, will investigate themes later. Quote:  XPStyle on ManifestDPIAware true Page Components "" OnCompShow Page InstFiles Function OnCompShow SysCompImg::ApplyFlat FunctionEnd Section Normal SectionEnd SectionGroup /e Group Section /o UnChecked SectionEnd Section Checked SectionEnd SectionGroupEnd Section /o RO:U SectionIn RO SectionEnd Section RO:C SectionIn RO SectionEnd Let me know how this looks Attached Files  SysCompImg.zip (1.4 KB, 226 views) IntOp$PostCount $PostCount + 1  6th August 2017, 18:57 #13 Anders Moderator Join Date: Jun 2002 Location:${NSISDIR} Posts: 5,296 It uses the DrawFrameControl API to draw on a custom imagelist. It is probably the same API used by the classic theme. IntOp $PostCount$PostCount + 1
 9th August 2017, 19:36 #14 Anders Moderator     Join Date: Jun 2002 Location: ${NSISDIR} Posts: 5,296 On the theme side of things, on Vista+ the TVS_EX_PARTIALCHECKBOXES style would be usable but TVS_EX_DIMMEDCHECKBOXES cannot be used for the read-only image so there is no way to get native flat themed checkboxes. Next step is to try to use the theme API to draw 3d checkboxes. IntOp$PostCount $PostCount + 1  16th August 2017, 10:02 #15 mgrand Junior Member Join Date: Jul 2017 Posts: 8 Thanks for investigating I'm not familiar with neither Windows API nor NSIS internal programming, but wouldn't it make more sense to use native checkbox controls instead, like nsDialogs? 25th August 2017, 13:14 #16 Anders Moderator Join Date: Jun 2002 Location:${NSISDIR}
Posts: 5,296
New version.

SetClassic: Classic flat look
SetFlat: Same as classic for now
SetThemed: Themed on XP+, same as SetFlat on <= 2000
GetSysDpi: System DPI in $0 Attached Files  SysCompImg.zip (1.8 KB, 204 views) IntOp$PostCount $PostCount + 1  26th August 2017, 09:06 #17 mgrand Junior Member Join Date: Jul 2017 Posts: 8 Awesome! The checkboxes now really look consistent with the rest of the GUI 27th August 2017, 17:26 #18 Anders Moderator Join Date: Jun 2002 Location:${NSISDIR}
Posts: 5,296
New version, added Unicode and 64-bit builds.

Support for custom bitmaps:

Quote:
 Function OnCompShow SysCompImg::GetSysDpi ${If}$0 > 144 File "/oname=$PluginsDir\check.bmp" "${NSISDIR}\Contrib\Graphics\Checks\big.bmp" ; 192 ${ElseIf}$0 > 120 File "/oname=$PluginsDir\check.bmp" "${NSISDIR}\Contrib\Graphics\Checks\red-round.bmp" ; 144 ${ElseIf}$0 > 96 File "/oname=$PluginsDir\check.bmp" "${NSISDIR}\Contrib\Graphics\Checks\grey.bmp" ; 120 ${Else} File "/oname=$PluginsDir\check.bmp" "${NSISDIR}\Contrib\Graphics\Checks\simple.bmp" ; 96${EndIf} SysCompImg::SetCustom "$PluginsDir\check.bmp" FunctionEnd Attached Files  SysCompImg.zip (6.3 KB, 241 views) IntOp$PostCount $PostCount + 1  11th September 2017, 17:15 #19 mgrand Junior Member Join Date: Jul 2017 Posts: 8 Really cool Will this be merged into NSIS?  11th September 2017, 22:10 #20 Nutzzz Member Join Date: May 2007 Location: Orange County, CA, U.S.A. Posts: 70 Yes, thanks for this, @Anders ! I've experimented with this a bit, and another issue is the scrollbars (for, e.g., the License Agreement) are very small.  12th September 2017, 11:39 #21 Anders Moderator Join Date: Jun 2002 Location:${NSISDIR} Posts: 5,296 Windows is drawing the scrollbars, not us. There is EnableNonClientDpiScaling but I don't think we can use it. I will investigate PerMonitorAwareV2, we might be able to support that. IntOp $PostCount$PostCount + 1
 10th August 2018, 23:20 #22 Hugh Junior Member   Join Date: Apr 2016 Posts: 11 I've tried using both a normal-size and an over-sized banner bmp (2x) using the modern_headerbmp.exe UI, but unlike mgrand I'm not seeing it scale properly at HiDPI (ie. at 200% I would have expected to work with the 2x sized banner). It appears to maintain the exact pixel counts regardless of scale or the image being used, instead of percentage coverage, as if the size was pixel-fixed (possibly in the modern_headerbmp.exe resource?). I used ResourceHacker to check the control sizes in the exe, but I couldn't determine which control affects the banner (a full-width banner, unlike 1046 which appears to be a 100x35 image). ManifestDPIAware and ManifestSupportedOS have been set (true and all, respectively), which fixes the text scaling, but not the image. I've tried all the different settings with MUI_HEADERIMAGE_BITMAP_STRETCH to no avail. I've also attempted to use SetBrandingImage (as per https://stackoverflow.com/questions/...stallers-pages), along with using AddBrandingImage before calling SetBrandingImage to see if that changes the behaviour when using the oversized image, but I'm getting "no branding image found in chosen UI!" and I'm not sure that's the right way of solving this issue. Any ideas?
 11th August 2018, 18:24 #23 Anders Moderator     Join Date: Jun 2002 Location: ${NSISDIR} Posts: 5,296 Resources use dialog units, not pixels. The final pixel size is calculated by Windows at run-time and it is based on the font size (dialog unit) and DPI. More information would be nice. Windows version? Is the primary monitor 200% DPI? Logged out and back in after changing DPI? IntOp$PostCount $PostCount + 1  14th August 2018, 23:24 #24 Hugh Junior Member Join Date: Apr 2016 Posts: 11 After some further investigation, it looks like we're manually setting image sizes via SetWindowPos(), which would explain the issues, so this has been resolved. However, I noticed that the window size is slightly narrower in 120dpi mode (125%), while all other modes (100%, 150%, 200%) show the correct window width. This shows up because it will cut off part of the banner on the right side, as well as wrap text that doesn't wrap in any other dpi mode. I'm also seeing something similar happening with jp/ko languages as well, regardless of DPI, but not to en-us or zh-cn. In the language case, the window is much wider than the normal window. I'm not sure it's necessarily related to the 125% mode issue, but it may be due to a similar mechanism.  15th August 2018, 09:36 #25 Anders Moderator Join Date: Jun 2002 Location:${NSISDIR} Posts: 5,296 Again, you are not telling me your Windows version. The pixel size depends on the font because dialog units are based on the font. On Windows 10, some far east fonts are no longer installed by default and that might mess things up so make sure the font listed in the .nlf language file is actually installed. (Installing the keyboard layout and/or UI language should fix it IIRC) IntOp $PostCount$PostCount + 1
 16th August 2018, 00:10 #26 Hugh Junior Member   Join Date: Apr 2016 Posts: 11 For the 125% DPI problem, the Windows versions I have seen this on are Windows 7, 8.1, 10, and Server 2008 R2 non-exhaustive. For the language issues, I've been testing with localized Windows 7 installations, but I believe I have seen them across a similar range at some point or another. So the takeaway here is to ensure that the font specified in the .nlf language files exist on the system first for localized installations...I will check on that, thanks.
 16th August 2018, 08:49 #27 Anders Moderator     Join Date: Jun 2002 Location: ${NSISDIR} Posts: 5,296 The font issue only exists on Windows 10 (and 95/NT4 if you care about those). I believe 120 dpi used to be known as Large Fonts in Windows and might have some weird compatibility hacks, not sure. IntOp$PostCount \$PostCount + 1
 Winamp & Shoutcast Forums NSIS on HiDPI displays