Archive: Move control according to DPI


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.

Move it using Resource Hacker.

Stu


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.


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


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

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.