grundic
30th May 2009 10:02 UTC
Move control according to DPI
Hello!
I'm developing nsis setup with nsDialogs custom pages. I've figured out, that when i use units, not pixels, the control's position is OK on different DPI.
But I've encounter a different problem: I need to move BrandingText. Right now I do it this way:
setBrandTextPos
GetDlgItem$0 $HWNDPARENT 1028
System
::Call "User32::SetWindowPos(i, i, i, i, i, i, i) b ($0, 0, 25, 307, 510, 230, ${SWP_NOZORDER}|${SWP_NOMOVE})"
GetDlgItem $0 $HWNDPARENT 1256
System::Call "User32::SetWindowPos(i, i, i, i, i, i, i) b ($0, 0, 25, 307, 510, 230, ${SWP_NOZORDER}|${SWP_NOMOVE})"
GetDlgItem $0 $HWNDPARENT 1035
System::Call "User32::BringWindowToTop(i) b ($0)"
>FunctionEnd
>
That is - via
System::Call "User32::SetWindowPos. But I don't know, how to make it independent to the DPI.
I read several times h++p://forums.winamp.com/showthread.php?s=&threadid=275299, but I can't figure out the idea.
Can somebody give me a working example?
Thanks in advance.
Afrow UK
30th May 2009 11:07 UTC
Move it using Resource Hacker.
Stu
grundic
30th May 2009 13:38 UTC
I changed modern.exe with ResHacker, but my custom page is the same. What ID should I use in nsDialogs::Create? Currently I'm using 1018.
Afrow UK
30th May 2009 18:54 UTC
What has the branding text label got to do with your custom page? The branding text label (1028) is on the outer dialog (105) and therefore applies to the entire install (all pages as they are child dialogs of the outer dialog).
Edit: You should also make a copy of the modern.exe into your install script folder and use it with !define MUI_UI modern_mod.exe. Otherwise when you upgrade NSIS it will be overwritten.
Stu
Animaether
31st May 2009 15:18 UTC
Just to answer the original question a bit more... dialog units are not just dependent on DPI, but also on the font used by the dialog (see: SetFont). That's why you'll find that if you create a button that is 100x100 dialog units, it's typically not square; the dialog units are defined based on the average width of the font's glyphs horizontally, and the average height of the font's glyphs vertically.
Here's a very dirty way to get the dialog unit > pixels multiplier:
!addplugindir "."
!addincludedir "."
!include "nsDialogs.nsh"
!include "winmessages.nsh"
!include "logiclib.nsh"
!include "MUI2.nsh"
!include "LoadRTF.nsh"
OutFile "test.exe"
SetFont "Times New Roman" 12
var dialog
var hwnd
var null
Page Custom CustomPage
Function CustomPage
nsDialogs::Create 1018
Pop $dialog
; Define some sizes (in dialog units, but don't add the 'u' here!)
!define width 100
!define height 100
; Create a button with the dialog units.
; This could be moved off-screen or
; be invoked but never displayed on installer startup, etc.
${NSD_CreateButton} 0 0 ${width}u ${height}u "A"
Pop $hwnd
System::Call "*(i, i, i, i) i .r1"
System::Call "User32::GetWindowRect(i $hwnd, i r1) i .r2"
System::Call "*$1(i .r2, i.r3, i.r4, i.r5)"
System::Free $1
IntOp $2 $4 - $2 ; $2 now contains the width of $hwnd
IntOp $3 $5 - $3 ; $3 now contains the height of $hwnd
Math::Script "r0 = $2 / ${width}.0" ; Need float?
Math::Script "r1 = $3 / ${height}.0" ; Need float!
MessageBox MB_OK "Dialog units: ${width}u × ${height}u$\r$\nPixels: $2px × $3px$\r$\nMultiplier: $0 × $1"
; Now let's create another button next to it that should
; match (1 pixel error margin) the first.
${NSD_CreateButton} ${width}u 0 $2 $3 "B"
Pop $null
nsDialogs::Show
FunctionEnd
Section
SectionEnd
!insertmacro MUI_LANGUAGE "English"
Edit: The more appropriate methods are explained at Microsoft here:
http://support.microsoft.com/kb/145994
grundic
1st June 2009 12:02 UTC
Thanks a lot for your answers! Gona test it now.
By the way, I've found, that when I use
!define MUI_HEADERIMAGE then branding text position is always left aligned (after I resourceHacked it). If I remove this define, than everything is Ok.