Results 1 to 33 of 33

Thread: Fix the TwipsPerPixel rounding?

  1. #1

    Thread Starter
    PowerPoster
    Join Date
    Feb 2017
    Posts
    4,995

    Lightbulb Fix the TwipsPerPixel rounding?

    I'm wondering if this could be somewhat possible.
    It would involve hacking and patching VB6 (hopefully just in memory so the runtime DLLs do not need to be touched on disk).
    This question is intended to the ones that have knowledge exploring the VB6 internals (The Trick, wqweto...).

    The idea is that VB6 already uses Single types for al twips based properties, but the "only" problem is that the twips-per-pixel calculation is somewhere rounded to integers.

    This, as we all know, cause problems is some DPI settings, that are used more and more as time goes on. And if ultra-hight DPI monitors become common, at some point it will be a major issue for VB6 programs. And it will most probably happen, the only question is when.

    The idea of the question is if it could be feasible to find where this rounding occurs and correct it (surely in more than one place, but probably not many).

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

    Re: Fix the TwipsPerPixel rounding?

    I suspect that Currency is used in OLE's "metrics" calculations internally. You can see this abstraction "leak" by examining the data type used for IFont.Size for example.

    Single type for many properties might even be just a holdover from earlier versions of VB written for Windows 3.x.

  3. #3
    Angel of Code Niya's Avatar
    Join Date
    Nov 2011
    Posts
    8,598

    Re: Fix the TwipsPerPixel rounding?

    This TwipsPerPixel nonsense is one of the reasons I'm glad I don't work in VB6 anymore. I've always hated this Twips concept passionately. Why couldn't we just use pixel measurements like Win32 and just about everything else.
    Treeview with NodeAdded/NodesRemoved events | BlinkLabel control | Calculate Permutations | Object Enums | ComboBox with centered items | .Net Internals article(not mine) | Wizard Control | Understanding Multi-Threading | Simple file compression | Demon Arena

    Copy/move files using Windows Shell | I'm not wanted

    C++ programmers will dismiss you as a cretinous simpleton for your inability to keep track of pointers chained 6 levels deep and Java programmers will pillory you for buying into the evils of Microsoft. Meanwhile C# programmers will get paid just a little bit more than you for writing exactly the same code and VB6 programmers will continue to whitter on about "footprints". - FunkyDexter

    There's just no reason to use garbage like InputBox. - jmcilhinney

    The threads I start are Niya and Olaf free zones. No arguing about the benefits of VB6 over .NET here please. Happiness must reign. - yereverluvinuncleber

  4. #4
    Junior Member
    Join Date
    Jan 2017
    Posts
    30

    Re: Fix the TwipsPerPixel rounding?

    This, as we all know, cause problems is some DPI settings, that are used more and more as time goes on. And if ultra-hight DPI monitors become common, at some point it will be a major issue for VB6 programs. And it will most probably happen, the only question is when.
    Can you enlighten me on what problems you get. I agree its a case of when, but I'm not sure i've actually seen a vb6 app on a high dpi device.

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

    Re: Fix the TwipsPerPixel rounding?

    Last time I delved into it the TwipsPerPixelX propertiy was retrieved from an internal structure and the value in this struct was a 32-bit integer which I tried to convert to 32-bit float by patching the fetching instructions but didn't succeed and it all seemed like a lost cause.

    Probably The Trick has the powers to fix it but it's quite complicated as this DISPLAY (or was it DESKTOP?) structure is probably directly accessed from many functions inside the runtime.

    cheers,
    </wqw>

  6. #6

    Thread Starter
    PowerPoster
    Join Date
    Feb 2017
    Posts
    4,995

    Re: Fix the TwipsPerPixel rounding?

    OK, several related topics here.

    First, and most important, the suggestion I made in the OP:

    Quote Originally Posted by wqweto View Post
    Last time I delved into it the TwipsPerPixelX propertiy was retrieved from an internal structure and the value in this struct was a 32-bit integer which I tried to convert to 32-bit float by patching the fetching instructions but didn't succeed and it all seemed like a lost cause.

    Probably The Trick has the powers to fix it but it's quite complicated as this DISPLAY (or was it DESKTOP?) structure is probably directly accessed from many functions inside the runtime.

    cheers,
    </wqw>
    Glad to know that at least someone tried.
    OK, then it seems it is not easy.

    Second topic: possible workarounds:

    I spent some days fixing this issue in a large program, it has like 100 forms, and more than 100K LOC, with several UserControls.

    I wasn't as difficult as I thought. This is my experience:
    Intrinsic controls have no problem, only non-intrinsic control have. In my case they were MSHFlexGrids, RichTextBoxes and UserControls from the project itself and from a component that I have.

    (note: that I have the program manifested for DPIAware, if you don't have the program manifested DPIAware, everything is scaled automatically... and blurred. If you have no manifest for DPI awareness then you can manifest for GDIScaling, that improves the things a bit - compared to unaware-)

    At the start of the program I set a variable, in the Sub Main:

    Code:
    Private Declare Function GetDC Lib "user32.dll" (ByVal hWnd As Long) As Long
    Private Declare Function GetDeviceCaps Lib "gdi32" (ByVal hDC As Long, ByVal nIndex As Long) As Long
    Private Declare Function ReleaseDC Lib "user32" (ByVal hWnd As Long, ByVal hDC As Long) As Long
    
    Public gDPIF as Single
    
    Public Sub Main()
        gDPIf = GetTrueTwipsPerPixelX / Screen.TwipsPerPixelX
    End Sub
    
    Private Function GetTrueTwipsPerPixelX() As Single
        Dim h As Long
        Const LOGPIXELSX As Long = 88
        
        h = GetDC(0)
        If h <> 0 Then
            GetTrueTwipsPerPixelX = 1440 / GetDeviceCaps(h, LOGPIXELSX)
            ReleaseDC 0, h
        Else
            GetTrueTwipsPerPixelX = Screen.TwipsPerPixelX
        End If
    End Function
    Then, in the forms that a non-intrinsic control needs to fill a space, replace code (for example) from:

    Code:
    Public Sub Form_Resize()
        ' grdResults is a flex grid
        grdResults.Move 60, 60, Me.ScaleWidth - 120, Me.ScaleHeight - 120
    End Sub
    to:

    Code:
    Public Sub Form_Resize()
        grdResults.Move 60, 60, Me.ScaleWidth * gDPIf - 120, Me.ScaleHeight * gDPIf - 120
    End Sub
    The controls that are not placed by code (just set their location at design time) do not need this adjustment.
    Form the controls that do not need to fill a certain space, such as buttons, I didn't see a problem, at least noticeable. Most of them probably I had no sizing code at run time.
    For the controls that size themselves, as toolbars, there is no need to add code either.
    Also, when other controls take their size or positions from corrected controls, the scale needs to be set back like ....Top = grdResults.Height / gDPIf

    So... it was easier than I thought. In around three days I finished.
    I still did not test much, but all other things seems to work.

    For making this fix, I set Windows 10 to a custom scale of 130% (I use 125% normally). It gives a TwipsPerPixels of 11.52.

    As a side note, I used my Project Examiner to find what forms had certain controls (MSHFlexGrid, RichTextBox).

    Other possible workaround:

    I had the idea of checking at the start of the program is GetTrueTwipsPerPixelX is integer or not, and if not to shell another version of the program and exit.
    This secondversion is almost exactly the same, but whithout this check and with a manifest for GDIScaling.
    It would be a bit cumbersome because it would require to make two exe compilations for each release.

    When the problem arises:

    Quote Originally Posted by rjsnipe View Post
    I'm not sure i've actually seen a vb6 app on a high dpi device.
    It is quite easy to see the problem, you do not need a ultra high-DPI monitor, just set the screen to 200% DPI (right click on the desktop, Display settings, set a custom scale).
    This produces a TwipsPerPixels of 7.5.
    100% --> 96 DPI
    200% --> 192 DPI
    1440/192 = 7.5 TwipsPerPixels

    Or, if it is too big for your monitor, set it to 130%, it produces 11.52 TwipsPerPixels.

    Twips/Pixels, DPI awareness:

    Quote Originally Posted by Niya View Post
    This TwipsPerPixel nonsense is one of the reasons I'm glad I don't work in VB6 anymore. I've always hated this Twips concept passionately. Why couldn't we just use pixel measurements like Win32 and just about everything else.
    I used to dislike it too, but was when it didn't understand what the heck was that thing of "twips" and why they used that numbering that seemed arbitrary and not related to the real things that were pixels.

    Until I needed to make the program DPI aware and understood the advantages.

    VB6 is almost DPI aware by default... if you use twips.
    OK, this topic would require to write a lot. May be if you are interested.

    PS: in that regard (DPI independence) VB6 was quite advanced, better than other languagues (even newer ones).
    I have no idea how .Net handles DPI independence if it works in pixels.

  7. #7

    Thread Starter
    PowerPoster
    Join Date
    Feb 2017
    Posts
    4,995

    Re: Fix the TwipsPerPixel rounding?

    For the ones that don't know about this problem, I'm attaching a test project to check it.

    This project simply adjust the size of a RichTextBox to the form client area.
    The code is:

    Code:
    Private Sub Form_Resize()
        RichTextBox1.Move 0, 0, Me.ScaleWidth, Me.ScaleHeight
    End Sub
    Compile the project and run the exe on different DPI settings (close and run the exe again on each setting).

    For 100%, 125% and 150% there is no problem.
    But for 200% there is, you will see that the RichTextBox does not fill the form.
    200% makes the screen too small, so alternatively you can set a custom scale to 120% or 130%.

    Side note:
    In the test project I'm including a generic manifest for DPI awareness in the resource file. For final projects, if you want to avoid dilettante's concerns/complaints/scolding/critics, please use the actual program name.
    Attached Files Attached Files

  8. #8
    Angel of Code Niya's Avatar
    Join Date
    Nov 2011
    Posts
    8,598

    Re: Fix the TwipsPerPixel rounding?

    Quote Originally Posted by Eduardo- View Post
    For 100%, 125% and 150% there is no problem.
    But for 200% there is, you will see that the RichTextBox does not fill the form.
    I get the problem at 175%.
    Treeview with NodeAdded/NodesRemoved events | BlinkLabel control | Calculate Permutations | Object Enums | ComboBox with centered items | .Net Internals article(not mine) | Wizard Control | Understanding Multi-Threading | Simple file compression | Demon Arena

    Copy/move files using Windows Shell | I'm not wanted

    C++ programmers will dismiss you as a cretinous simpleton for your inability to keep track of pointers chained 6 levels deep and Java programmers will pillory you for buying into the evils of Microsoft. Meanwhile C# programmers will get paid just a little bit more than you for writing exactly the same code and VB6 programmers will continue to whitter on about "footprints". - FunkyDexter

    There's just no reason to use garbage like InputBox. - jmcilhinney

    The threads I start are Niya and Olaf free zones. No arguing about the benefits of VB6 over .NET here please. Happiness must reign. - yereverluvinuncleber

  9. #9
    PowerPoster
    Join Date
    Feb 2015
    Posts
    2,671

    Re: Fix the TwipsPerPixel rounding?

    There is no problem to fix Screen's properties but it's quite difficult to change all the internal structures. Just for information, this is the places where TwipsPerPixels is used:
    Code:
    Search - References to MSVBVM60:.data:66110224..66110227
    Address                          Command                                                      Comments
    66003710                         MOV EDX,DWORD PTR DS:[Sys_ScrTwipsPerPixelX]
    66005C8B                         MOV EDX,DWORD PTR DS:[Sys_ScrTwipsPerPixelX]
    66006C8C PLOT::GetRECT           MOV EDX,DWORD PTR DS:[Sys_ScrTwipsPerPixelX]
    66006CC8                         MOV EDX,DWORD PTR DS:[Sys_ScrTwipsPerPixelX]
    6600E6FA                         MOV EDX,DWORD PTR DS:[Sys_ScrTwipsPerPixelX]
    6600E74A                         MOV EDX,DWORD PTR DS:[Sys_ScrTwipsPerPixelX]
    6601AE57                         MOV DWORD PTR DS:[Sys_ScrTwipsPerPixelX],EAX
    66033F7F                         MOV EDX,DWORD PTR DS:[Sys_ScrTwipsPerPixelX]
    66034736                         MOV ECX,DWORD PTR DS:[Sys_ScrTwipsPerPixelX]
    6603475F                         MOV EDX,DWORD PTR DS:[Sys_ScrTwipsPerPixelX]
    66034859                         MOV EDX,DWORD PTR DS:[Sys_ScrTwipsPerPixelX]
    66034889                         MOV EDX,DWORD PTR DS:[Sys_ScrTwipsPerPixelX]
    6603806A                         MOV EDX,DWORD PTR DS:[Sys_ScrTwipsPerPixelX]
    6603811A                         MOV EDX,DWORD PTR DS:[Sys_ScrTwipsPerPixelX]
    66038176                         MOV EDX,DWORD PTR DS:[Sys_ScrTwipsPerPixelX]
    6603828A                         MOV ECX,DWORD PTR DS:[Sys_ScrTwipsPerPixelX]
    66038380                         MOV EDX,DWORD PTR DS:[Sys_ScrTwipsPerPixelX]
    660383A9                         MOV EDX,DWORD PTR DS:[Sys_ScrTwipsPerPixelX]
    660383EC                         MOV EDX,DWORD PTR DS:[Sys_ScrTwipsPerPixelX]
    660386B0                         MOV EDX,DWORD PTR DS:[Sys_ScrTwipsPerPixelX]
    660386BE                         MOV EDX,DWORD PTR DS:[Sys_ScrTwipsPerPixelX]
    6603D8DE                         IMUL EAX,DWORD PTR DS:[Sys_ScrTwipsPerPixelX]
    6603D93D                         FILD DWORD PTR DS:[Sys_ScrTwipsPerPixelX]
    66041277                         MOV EDX,DWORD PTR DS:[Sys_ScrTwipsPerPixelX]
    660429EF                         MOV EAX,DWORD PTR DS:[Sys_ScrTwipsPerPixelX]
    660464F9                         MOV EDX,DWORD PTR DS:[Sys_ScrTwipsPerPixelX]
    660470CA                         MOV EDX,DWORD PTR DS:[Sys_ScrTwipsPerPixelX]
    660470EE                         MOV EDX,DWORD PTR DS:[Sys_ScrTwipsPerPixelX]
    660474D9                         MOV EDX,DWORD PTR DS:[Sys_ScrTwipsPerPixelX]
    660474FC                         MOV EDX,DWORD PTR DS:[Sys_ScrTwipsPerPixelX]
    66047A55                         MOV EAX,DWORD PTR DS:[Sys_ScrTwipsPerPixelX]
    66047C82                         MOV EDX,DWORD PTR DS:[Sys_ScrTwipsPerPixelX]
    66047CA1                         MOV EDX,DWORD PTR DS:[Sys_ScrTwipsPerPixelX]
    66047CE1                         FILD DWORD PTR DS:[Sys_ScrTwipsPerPixelX]
    66048749                         MOV EAX,DWORD PTR DS:[Sys_ScrTwipsPerPixelX]
    6604B2E3                         FILD DWORD PTR DS:[Sys_ScrTwipsPerPixelX]
    660550D6                         MOV EDX,DWORD PTR DS:[Sys_ScrTwipsPerPixelX]
    6605523D                         MOV EAX,DWORD PTR DS:[Sys_ScrTwipsPerPixelX]
    660552CF                         FIDIV DWORD PTR DS:[Sys_ScrTwipsPerPixelX]
    66056908                         MOV EDX,DWORD PTR DS:[Sys_ScrTwipsPerPixelX]
    66058AAF                         FILD DWORD PTR DS:[Sys_ScrTwipsPerPixelX]
    6605E57A                         IMUL ECX,DWORD PTR DS:[Sys_ScrTwipsPerPixelX]
    6605E83C                         MOV ECX,DWORD PTR DS:[Sys_ScrTwipsPerPixelX]
    66062B81                         MOV ESI,DWORD PTR DS:[Sys_ScrTwipsPerPixelX]
    66062DAB                         MOV EDX,DWORD PTR DS:[Sys_ScrTwipsPerPixelX]
    66062DD8                         MOV EDX,DWORD PTR DS:[Sys_ScrTwipsPerPixelX]
    66062E04                         MOV EAX,DWORD PTR DS:[Sys_ScrTwipsPerPixelX]
    66062E1E                         MOV EAX,DWORD PTR DS:[Sys_ScrTwipsPerPixelX]
    66065759                         MOV EDX,DWORD PTR DS:[Sys_ScrTwipsPerPixelX]
    66065777                         MOV EDX,DWORD PTR DS:[Sys_ScrTwipsPerPixelX]
    660658E2                         MOV EDX,DWORD PTR DS:[Sys_ScrTwipsPerPixelX]
    6606BDAA                         MOV EDX,DWORD PTR DS:[Sys_ScrTwipsPerPixelX]
    6606BDFE                         MOV EDX,DWORD PTR DS:[Sys_ScrTwipsPerPixelX]
    6606BE9B                         MOV EDX,DWORD PTR DS:[Sys_ScrTwipsPerPixelX]
    6606BEED                         MOV EDX,DWORD PTR DS:[Sys_ScrTwipsPerPixelX]
    6606C0DE                         MOV EDX,DWORD PTR DS:[Sys_ScrTwipsPerPixelX]
    6606C826                         MOV EDX,DWORD PTR DS:[Sys_ScrTwipsPerPixelX]
    6606C86A                         MOV EDX,DWORD PTR DS:[Sys_ScrTwipsPerPixelX]
    6606CB4C                         MOV EDX,DWORD PTR DS:[Sys_ScrTwipsPerPixelX]
    6606D14A                         MOV EDX,DWORD PTR DS:[Sys_ScrTwipsPerPixelX]
    6606D158                         MOV EDX,DWORD PTR DS:[Sys_ScrTwipsPerPixelX]
    6606D603 CtlClientToScreen_49    MOV EDX,DWORD PTR DS:[Sys_ScrTwipsPerPixelX]
    6606D657 CtlScreenToClient_56    MOV EDX,DWORD PTR DS:[Sys_ScrTwipsPerPixelX]
    6606D6B3 CtlGetControlRect_25    MOV EDX,DWORD PTR DS:[Sys_ScrTwipsPerPixelX]
    6606D783                         MOV EDX,DWORD PTR DS:[Sys_ScrTwipsPerPixelX]
    6606E552                         MOV EDX,DWORD PTR DS:[Sys_ScrTwipsPerPixelX]
    6606E605                         MOV EDX,DWORD PTR DS:[Sys_ScrTwipsPerPixelX]
    66070428                         MOV EDX,DWORD PTR DS:[Sys_ScrTwipsPerPixelX]
    6607087E                         MOV EDX,DWORD PTR DS:[Sys_ScrTwipsPerPixelX]
    6607CE6D                         MOV EDX,DWORD PTR DS:[Sys_ScrTwipsPerPixelX]
    66083A51                         MOV EDX,DWORD PTR DS:[Sys_ScrTwipsPerPixelX]
    6608448F                         IMUL EAX,DWORD PTR DS:[Sys_ScrTwipsPerPixelX]
    660AFD63                         MOV EDX,DWORD PTR DS:[Sys_ScrTwipsPerPixelX]
    660AFF04                         MOV EDX,DWORD PTR DS:[Sys_ScrTwipsPerPixelX]
    660AFF48                         MOV EAX,DWORD PTR DS:[Sys_ScrTwipsPerPixelX]
    660B00CF                         MOV EDX,DWORD PTR DS:[Sys_ScrTwipsPerPixelX]
    660B2B55                         MOV EDX,DWORD PTR DS:[Sys_ScrTwipsPerPixelX]
    660B87B5                         IMUL ECX,DWORD PTR DS:[Sys_ScrTwipsPerPixelX]
    660B8833                         FIDIV DWORD PTR DS:[Sys_ScrTwipsPerPixelX]
    660BCFD5                         MOV EDX,DWORD PTR DS:[Sys_ScrTwipsPerPixelX]
    660BCFEA                         MOV EDX,DWORD PTR DS:[Sys_ScrTwipsPerPixelX]
    660C1760                         IMUL EAX,DWORD PTR DS:[Sys_ScrTwipsPerPixelX]
    660C18F4                         MOV EAX,DWORD PTR DS:[Sys_ScrTwipsPerPixelX]
    660C429B                         MOV EDX,DWORD PTR DS:[Sys_ScrTwipsPerPixelX]
    660C4335                         MOV ECX,DWORD PTR DS:[Sys_ScrTwipsPerPixelX]
    660C444C                         MOV EDX,DWORD PTR DS:[Sys_ScrTwipsPerPixelX]
    660C4477                         MOV EDX,DWORD PTR DS:[Sys_ScrTwipsPerPixelX]
    660C457D                         MOV EDX,DWORD PTR DS:[Sys_ScrTwipsPerPixelX]
    660C46C2                         MOV EDX,DWORD PTR DS:[Sys_ScrTwipsPerPixelX]
    660C46EC                         MOV EDX,DWORD PTR DS:[Sys_ScrTwipsPerPixelX]
    660C47DE                         MOV EDX,DWORD PTR DS:[Sys_ScrTwipsPerPixelX]
    660C4A13                         MOV EDX,DWORD PTR DS:[Sys_ScrTwipsPerPixelX]
    660C4A58                         MOV EAX,DWORD PTR DS:[Sys_ScrTwipsPerPixelX]
    660C59DF                         MOV ECX,DWORD PTR DS:[Sys_ScrTwipsPerPixelX]
    660C5A71                         MOV EDX,DWORD PTR DS:[Sys_ScrTwipsPerPixelX]
    660C5E70                         MOV EDX,DWORD PTR DS:[Sys_ScrTwipsPerPixelX]
    660C6249                         MOV EDX,DWORD PTR DS:[Sys_ScrTwipsPerPixelX]
    660CED69                         MOV EAX,DWORD PTR DS:[Sys_ScrTwipsPerPixelX]
    660DBACC                         MOV ECX,DWORD PTR DS:[Sys_ScrTwipsPerPixelX]
    There is no problem to patch them all but different runtime builds has its own addresses. BTW this is the initialization procedure which initializes twips etc:
    Code:
    BOOL __stdcall SysInit()
    {
      DWORD dwVersion;
      tVBWinVersion tVersion;
      LCID lcid; 
      HGDIOBJ hSysFont;
      HDC hdc;
      int lClrBitness;
      unsigned int lColCnt; 
      int lRasterCaps;
      struct tagSIZE sz;
    
      dwVersion = GetVersion();
      tVersion.wUnused = 0;
      tVersion.bMinor = BYTE1(dwVersion);
      tVersion.bMajor = dwVersion;
      Sys_WinVersion = *&tVersion.bMinor;
      Sys_fWinNT = WHITE_BRUSH;
      Sys_fWin95 = WHITE_BRUSH;
      if ( dwVersion >= 0x80000000 )
      {
        Sys_fWin95 = 1;
        Sys_fWin95Shell = 1;
      }
      else
      {
        Sys_fWinNT = 1;
        Sys_fWin95Shell = *&tVersion >= 0x334;
      }
      Sys_fSupports_lstrcmpiW = lstrcmpiW(&`string', &`string') != 0;
      LOWORD(lcid) = GetUserDefaultLCID();
      Sys_fSupports_CompareStringW = CompareStringW(lcid, 0x30001u, &`string', -1, &`string', -1) == 1;
      if ( !SysWinIniChange() )
        return FALSE;
      Sys_hpenBlack = GetStockObject(BLACK_PEN);
      Sys_hpenWhite = GetStockObject(WHITE_PEN);
      Sys_hpenNull = GetStockObject(NULL_PEN);
      Sys_hbrBlack = GetStockObject(BLACK_BRUSH);
      Sys_hbrGray = GetStockObject(GRAY_BRUSH);
      Sys_hbrWhite = GetStockObject(WHITE_BRUSH);
      Sys_hbrNull = GetStockObject(NULL_BRUSH);
      hSysFont = GetStockObject(SYSTEM_FONT);
      Sys_hfontSystem = hSysFont;
      if ( !Sys_hpenBlack )
        return FALSE;
      if ( !Sys_hpenWhite )
        return FALSE;
      if ( !Sys_hpenNull )
        return FALSE;
      if ( !Sys_hbrBlack )
        return FALSE;
      if ( !Sys_hbrGray )
        return FALSE;
      if ( !Sys_hbrWhite )
        return FALSE;
      if ( !Sys_hbrNull )
        return FALSE;
      if ( !hSysFont )
        return FALSE;
      hdc = GetDC(WHITE_BRUSH);
      if ( !hdc )
        return FALSE;
      GetTextExtentPointA(hdc, Rby_szZero, 1, &sz);
      Sys_cxScrSysChar = sz.cx;
      Sys_cyScrSysChar = sz.cy;
      Sys_ScrPlanes = GetDeviceCaps(hdc, PLANES);
      lClrBitness = GetDeviceCaps(hdc, BITSPIXEL);
      Sys_ScrBitsPixel = lClrBitness;
      lColCnt = 1 << Sys_ScrPlanes * lClrBitness;
      Sys_DesiredIconColorCount = 16;
      if ( lColCnt <= 16 )
        Sys_DesiredIconColorCount = lColCnt;
      Sys_ScrLogPixelsX = GetDeviceCaps(hdc, LOGPIXELSX);
      Sys_ScrTwipsPerPixelX = 1440 / Sys_ScrLogPixelsX;
      Sys_ScrLogPixelsY = GetDeviceCaps(hdc, LOGPIXELSY);
      Sys_ScrTwipsPerPixelY = 1440 / Sys_ScrLogPixelsY;
      lRasterCaps = GetDeviceCaps(hdc, RASTERCAPS);
      if ( lRasterCaps & RC_PALETTE )
        Sys_ScrSizePalette = GetDeviceCaps(hdc, SIZEPALETTE);
      ReleaseDC(0, hdc);
      return TRUE;
    }

  10. #10
    PowerPoster Arnoutdv's Avatar
    Join Date
    Oct 2013
    Posts
    5,871

    Re: Fix the TwipsPerPixel rounding?

    Then you end up with defining your own kind of twips based on the current resolution and the DPI%?
    And do all drawing yourself. Like Olaf proposed with his Cairo libraries?

  11. #11

    Thread Starter
    PowerPoster
    Join Date
    Feb 2017
    Posts
    4,995

    Re: Fix the TwipsPerPixel rounding?

    Quote Originally Posted by Niya View Post
    I get the problem at 175%.
    You'll get the problem with many settings.

    175% is --> 100 / 96 * 175 = 182.2916666666667 DPI

    1440 / 182.2916666666667 = 7.89942857142857 TwipsPerPixel (non-integer)

    Quote Originally Posted by The trick View Post
    but different runtime builds has its own addresses.
    Thank you very much for looking into this issue.
    I forgot that there are different versions. I guess if at some point you could make a fix to patch the Dlls, it should be for SP6. But for the run-time will be a problem because I think there are more than one version on the end-user machines. And still MS could issue some modifications in the future (if they need to issue a security fix).
    So, considering that, I think that adds lot of difficulty and possible problems.

    Quote Originally Posted by Arnoutdv View Post
    Then you end up with defining your own kind of twips based on the current resolution and the DPI%?
    And do all drawing yourself.
    I'm not sure to who this question is addressed and what you are asking.
    Twips are twips and TwipsPerPixel by definition depend on the DPI setting.
    Please take a look to this explanation about twips, DPI settings, and this topic.

  12. #12
    Angel of Code Niya's Avatar
    Join Date
    Nov 2011
    Posts
    8,598

    Re: Fix the TwipsPerPixel rounding?

    As a result of my participation in the other thread where I was researching DPI, I decided to tackle this and see what's up while all this DPI stuff is still fresh in my mind. First I want to address this:-
    Quote Originally Posted by Eduardo- View Post
    You'll get the problem with many settings.

    175% is --> 100 / 96 * 175 = 182.2916666666667 DPI
    That calculation is wrong. The correct way to calculate the DPI for 175% scaling is 1.75 * 96, which is equal to 168. You can confirm this with the GetDpiForWindow Win32 function.

    With that out of the way lets move on to that little project you posted. I played with it for a bit before I reached the conclusion that the problem has absolutely nothing to do with how VB6 deals with twips. The problem lies with how VB6 performs the layout for specific controls. Somewhere inside the internals of VB6, the RichTextBox isn't correctly accepting the size values when it's at 175% scaling. If you replaced the RichTextBox with a normal multi-line TextBox, you'd see that it works perfectly at 175% scaling. What's more is that you will see that it will work correctly regardless of the Form's ScaleMode setting, even when it's set to vbPixels. Twips have no part at all to play in this problem. The fault is with the RichTextBox itself.
    Treeview with NodeAdded/NodesRemoved events | BlinkLabel control | Calculate Permutations | Object Enums | ComboBox with centered items | .Net Internals article(not mine) | Wizard Control | Understanding Multi-Threading | Simple file compression | Demon Arena

    Copy/move files using Windows Shell | I'm not wanted

    C++ programmers will dismiss you as a cretinous simpleton for your inability to keep track of pointers chained 6 levels deep and Java programmers will pillory you for buying into the evils of Microsoft. Meanwhile C# programmers will get paid just a little bit more than you for writing exactly the same code and VB6 programmers will continue to whitter on about "footprints". - FunkyDexter

    There's just no reason to use garbage like InputBox. - jmcilhinney

    The threads I start are Niya and Olaf free zones. No arguing about the benefits of VB6 over .NET here please. Happiness must reign. - yereverluvinuncleber

  13. #13
    Angel of Code Niya's Avatar
    Join Date
    Nov 2011
    Posts
    8,598

    Re: Fix the TwipsPerPixel rounding?

    Turns out I was correct. The problem has nothing to do with Twips. Use this:-
    vb6 Code:
    1. Option Explicit
    2.  
    3. Private Declare Function GetDpiForWindow Lib "user32.dll" (ByVal hwnd As Long) As Long
    4. Private Declare Function SetWindowPos Lib "user32" (ByVal hwnd As Long, ByVal hWndInsertAfter As Long, ByVal x As Long, ByVal y As Long, ByVal cx As Long, ByVal cy As Long, ByVal wFlags As Long) As Long
    5.  
    6. ' SetWindowPos Flags
    7. Const SWP_NOSIZE = &H1
    8. Const SWP_NOMOVE = &H2
    9. Const SWP_NOZORDER = &H4
    10. Const SWP_NOREDRAW = &H8
    11. Const SWP_NOACTIVATE = &H10
    12. Const SWP_FRAMECHANGED = &H20        '  The frame changed: send WM_NCCALCSIZE
    13. Const SWP_SHOWWINDOW = &H40
    14. Const SWP_HIDEWINDOW = &H80
    15. Const SWP_NOCOPYBITS = &H100
    16. Const SWP_NOOWNERZORDER = &H200      '  Don't do owner Z ordering
    17.  
    18. Const SWP_DRAWFRAME = SWP_FRAMECHANGED
    19. Const SWP_NOREPOSITION = SWP_NOOWNERZORDER
    20.  
    21. ' SetWindowPos() hwndInsertAfter values
    22. Const HWND_TOP = 0
    23. Const HWND_BOTTOM = 1
    24. Const HWND_TOPMOST = -1
    25. Const HWND_NOTOPMOST = -2
    26.  
    27. Private Sub Form_Resize()
    28.     'RichTextBox1.Move 0, 0, Me.ScaleWidth, Me.ScaleHeight
    29.    
    30.     SetWindowPos RichTextBox1.hwnd, HWND_TOP, 0, 0, ScaleX(Me.ScaleWidth, Me.ScaleMode, vbPixels), ScaleY(Me.ScaleHeight, Me.ScaleMode, vbPixels), 0
    31.    
    32.     RichTextBox1.Text = "Current DPI : " + CStr(GetDpiForWindow(Me.hwnd))
    33.     RichTextBox1.Text = RichTextBox1.Text + vbCrLf + "Scale Width in pixels : " + CStr(ScaleX(Me.ScaleWidth, Me.ScaleMode, vbPixels))
    34.     RichTextBox1.Text = RichTextBox1.Text + vbCrLf + "Scale Height in pixels : " + CStr(ScaleY(Me.ScaleHeight, Me.ScaleMode, vbPixels))
    35.    
    36. End Sub

    Instead of using the RichTextBox's Move method, I used the Win32 API SetWindowPos and it now works at 175% scaling and it doesn't matter what the Form's ScaleMode is. It works, even when the Form's ScaleMode is set to vbPixels. Turns out, we don't even need to deal with all that TwipsPerPixel mess to get this to work correctly for different DPIs. Plain old pixels are enough.

    EDIT:

    I also tested positioning the RichTextBox using the plain old Left/Top/Width/Height properties and that didn't work either. I can only conclude that there is a problem deep in the VB6 infrastructure that is just not capable of dealing with higher DPIs when positioning certain Controls. Best to stick with SetWindowPos to move and size controls in your DPI aware applications.
    Last edited by Niya; Jan 22nd, 2021 at 05:24 AM.
    Treeview with NodeAdded/NodesRemoved events | BlinkLabel control | Calculate Permutations | Object Enums | ComboBox with centered items | .Net Internals article(not mine) | Wizard Control | Understanding Multi-Threading | Simple file compression | Demon Arena

    Copy/move files using Windows Shell | I'm not wanted

    C++ programmers will dismiss you as a cretinous simpleton for your inability to keep track of pointers chained 6 levels deep and Java programmers will pillory you for buying into the evils of Microsoft. Meanwhile C# programmers will get paid just a little bit more than you for writing exactly the same code and VB6 programmers will continue to whitter on about "footprints". - FunkyDexter

    There's just no reason to use garbage like InputBox. - jmcilhinney

    The threads I start are Niya and Olaf free zones. No arguing about the benefits of VB6 over .NET here please. Happiness must reign. - yereverluvinuncleber

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

    Re: Fix the TwipsPerPixel rounding?

    Quote Originally Posted by Niya View Post
    Best to stick with SetWindowPos to move and size controls in your DPI aware applications.
    SetWindowPos works but ScaleX/Y fail when actual TwipsPerPixelX/Y are not integer values in 175% scaling.

    Even if Form's ScaleMode is pixels the initial control position (in pixels) is scaled with 175% scaling as if the coordinates are persisted in twips (indeed they are).

    cheers,
    </wqw>

  15. #15
    Angel of Code Niya's Avatar
    Join Date
    Nov 2011
    Posts
    8,598

    Re: Fix the TwipsPerPixel rounding?

    Quote Originally Posted by wqweto View Post
    SetWindowPos works but ScaleX/Y fail when actual TwipsPerPixelX/Y are not integer values in 175% scaling.

    Even if Form's ScaleMode is pixels the initial control position (in pixels) is scaled with 175% scaling as if the coordinates are persisted in twips (indeed they are).

    cheers,
    </wqw>
    SetWindowPos works exclusively in pixels. The only reason I'm using ScaleX/Y is because I'm reading the dimensions of the client area from ScaleWidth/ScaleHeight properties of the Form and I need them to be in pixels so it's necessary to convert them if the ScaleMode is not in pixels. You can cut out the need for ScaleX/Y entirely by using the GetClientRect API to get the dimensions of the client area. The net of it is that you can get the correct behavior without any concern for Twips or the ScaleMode or any of that.

    Even so, the current code works correctly for me at 175% for me regardless of the ScaleMode setting.
    Treeview with NodeAdded/NodesRemoved events | BlinkLabel control | Calculate Permutations | Object Enums | ComboBox with centered items | .Net Internals article(not mine) | Wizard Control | Understanding Multi-Threading | Simple file compression | Demon Arena

    Copy/move files using Windows Shell | I'm not wanted

    C++ programmers will dismiss you as a cretinous simpleton for your inability to keep track of pointers chained 6 levels deep and Java programmers will pillory you for buying into the evils of Microsoft. Meanwhile C# programmers will get paid just a little bit more than you for writing exactly the same code and VB6 programmers will continue to whitter on about "footprints". - FunkyDexter

    There's just no reason to use garbage like InputBox. - jmcilhinney

    The threads I start are Niya and Olaf free zones. No arguing about the benefits of VB6 over .NET here please. Happiness must reign. - yereverluvinuncleber

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

    Re: Fix the TwipsPerPixel rounding?

    I have no idea what you are testing here but if you change RTB to a custom VB6 created UserControl (with a blue background for instance) and try to span it with Move 0, 0, Me.ScaleWidth, Me.ScaleHeight or SetWindowPos you will see the obvious failure in 175%.

    cgeers,
    </wqw>

  17. #17
    Angel of Code Niya's Avatar
    Join Date
    Nov 2011
    Posts
    8,598

    Re: Fix the TwipsPerPixel rounding?

    Quote Originally Posted by wqweto View Post
    I have no idea what you are testing here but if you change RTB to a custom VB6 created UserControl (with a blue background for instance) and try to span it with Move 0, 0, Me.ScaleWidth, Me.ScaleHeight or SetWindowPos you will see the obvious failure in 175%.

    cgeers,
    </wqw>
    I just tested this and it still didn't fail, even with a UserControl. If it's failing for you, I might be missing something. I've attached the project I used to test it.
    Attached Files Attached Files
    Treeview with NodeAdded/NodesRemoved events | BlinkLabel control | Calculate Permutations | Object Enums | ComboBox with centered items | .Net Internals article(not mine) | Wizard Control | Understanding Multi-Threading | Simple file compression | Demon Arena

    Copy/move files using Windows Shell | I'm not wanted

    C++ programmers will dismiss you as a cretinous simpleton for your inability to keep track of pointers chained 6 levels deep and Java programmers will pillory you for buying into the evils of Microsoft. Meanwhile C# programmers will get paid just a little bit more than you for writing exactly the same code and VB6 programmers will continue to whitter on about "footprints". - FunkyDexter

    There's just no reason to use garbage like InputBox. - jmcilhinney

    The threads I start are Niya and Olaf free zones. No arguing about the benefits of VB6 over .NET here please. Happiness must reign. - yereverluvinuncleber

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

    Re: Fix the TwipsPerPixel rounding?

    Quote Originally Posted by Niya View Post
    I just tested this and it still didn't fail, even with a UserControl. If it's failing for you, I might be missing something.
    Yes, must be the Move method that fails only and if the UserControl is Windowless=True the SetWindowPos hack is impossible.

    Also if you set Align property so that the parent form repositions the control, this fails no matter if windowless or not.

    If the UserControl is Container=True more oddities follow with contained controls, though I cannot simulate it. Probably some combination of ClipBehavior/ClipControls etc. settings on parent Form and UserControl.

    I'm using IOleInPlaceObject::SetObjectRects to fix Move method in HighDPI modes like this:

    Code:
    Public Sub SyncObjectRectsToContainer(oCtl As IUnknown)
        Const FUNC_NAME     As String = "SyncObjectRectsToContainer"
        Dim pOleObject      As IOleObject
        Dim pOleInPlaceObject As IOleInPlaceObject
        Dim pOleInPlaceSite As IOleInPlaceSite
        Dim uPosRect        As RECT
        Dim uClipRect       As RECT
        Dim uFrameInfo      As OLEINPLACEFRAMEINFO
        
        If Not oCtl Is Nothing Then
            If TypeOf oCtl Is VBOleGuids3.IOleObject Then
                Set pOleObject = oCtl
                Set pOleInPlaceObject = oCtl
                If pOleObject.GetClientSite(pOleInPlaceSite) = S_OK And Not pOleInPlaceSite Is Nothing Then
                    pOleInPlaceSite.GetWindowContext Nothing, Nothing, VarPtr(uPosRect), VarPtr(uClipRect), VarPtr(uFrameInfo)
                    pOleInPlaceObject.SetObjectRects VarPtr(uPosRect), VarPtr(uClipRect)
                End If
            End If
        End If
        Exit Sub
    EH:
    End Sub
    I just call SyncObjectRectsToContainer after each Move to be sure. This fix was shared by a member of the forums here -- The Trick or LaVolpe, don't remember exactly.

    cheers,
    </wqw>

  19. #19
    Angel of Code Niya's Avatar
    Join Date
    Nov 2011
    Posts
    8,598

    Re: Fix the TwipsPerPixel rounding?

    Ehh....well I expect there are all kinds of gremlins waiting in the dark with this. I don't know enough to cover all the edge cases that would cause it to fail. I certainly don't know enough to have come up with something like that SyncObjectRectsToContainer function.
    Treeview with NodeAdded/NodesRemoved events | BlinkLabel control | Calculate Permutations | Object Enums | ComboBox with centered items | .Net Internals article(not mine) | Wizard Control | Understanding Multi-Threading | Simple file compression | Demon Arena

    Copy/move files using Windows Shell | I'm not wanted

    C++ programmers will dismiss you as a cretinous simpleton for your inability to keep track of pointers chained 6 levels deep and Java programmers will pillory you for buying into the evils of Microsoft. Meanwhile C# programmers will get paid just a little bit more than you for writing exactly the same code and VB6 programmers will continue to whitter on about "footprints". - FunkyDexter

    There's just no reason to use garbage like InputBox. - jmcilhinney

    The threads I start are Niya and Olaf free zones. No arguing about the benefits of VB6 over .NET here please. Happiness must reign. - yereverluvinuncleber

  20. #20

    Thread Starter
    PowerPoster
    Join Date
    Feb 2017
    Posts
    4,995

    Re: Fix the TwipsPerPixel rounding?

    Quote Originally Posted by Niya View Post
    Quote Originally Posted by Eduardo- View Post
    175% is --> 100 / 96 * 175 = 182.2916666666667 DPI
    That calculation is wrong. The correct way to calculate the DPI for 175% scaling is 1.75 * 96, which is equal to 168.
    Yes, I made a mistake when I wrote the post, it is 96 / 100 and not 100 / 96.
    Sorry, but you didn't discover pawder, you just discovered a typing mistake.

    Quote Originally Posted by Niya View Post
    With that out of the way lets move on to that little project you posted. I played with it for a bit before I reached the conclusion that the problem has absolutely nothing to do with how VB6 deals with twips. The problem lies with how VB6 performs the layout for specific controls. Somewhere inside the internals of VB6, the RichTextBox isn't correctly accepting the size values when it's at 175% scaling. If you replaced the RichTextBox with a normal multi-line TextBox, you'd see that it works perfectly at 175% scaling. What's more is that you will see that it will work correctly regardless of the Form's ScaleMode setting, even when it's set to vbPixels. Twips have no part at all to play in this problem. The fault is with the RichTextBox itself.
    If you had read the OP and the thread, that was already covered. Intrinsic controls don't have this problem. You didn't discover anything once more.

    Of course using API to position controls is an alternative solution. But IMO it is easier what I suggested above.
    We are not taking about fixing one control, but a whole large project. The RichTextBox was just an example for the ones that were not aware of this issue.

  21. #21
    Angel of Code Niya's Avatar
    Join Date
    Nov 2011
    Posts
    8,598

    Re: Fix the TwipsPerPixel rounding?

    Quote Originally Posted by Eduardo- View Post
    If you had read the OP and the thread, that was already covered. Intrinsic controls don't have this problem. You didn't discover anything once more.
    You guys were focused on twips when that had nothing to do with it. All I showed was that in the case of the sample you posted, you could induce the correct behavior whether or not twips were involved in any way.
    Treeview with NodeAdded/NodesRemoved events | BlinkLabel control | Calculate Permutations | Object Enums | ComboBox with centered items | .Net Internals article(not mine) | Wizard Control | Understanding Multi-Threading | Simple file compression | Demon Arena

    Copy/move files using Windows Shell | I'm not wanted

    C++ programmers will dismiss you as a cretinous simpleton for your inability to keep track of pointers chained 6 levels deep and Java programmers will pillory you for buying into the evils of Microsoft. Meanwhile C# programmers will get paid just a little bit more than you for writing exactly the same code and VB6 programmers will continue to whitter on about "footprints". - FunkyDexter

    There's just no reason to use garbage like InputBox. - jmcilhinney

    The threads I start are Niya and Olaf free zones. No arguing about the benefits of VB6 over .NET here please. Happiness must reign. - yereverluvinuncleber

  22. #22

    Thread Starter
    PowerPoster
    Join Date
    Feb 2017
    Posts
    4,995

    Re: Fix the TwipsPerPixel rounding?

    Quote Originally Posted by Niya View Post
    You guys were focused on twips when that had nothing to do with it. All I showed was that in the case of the sample you posted, you could induce the correct behavior whether or not twips were involved in any way.
    If you mean your solution of using API everywere to position controls, it is a solution but not the best one.

    But if you say that for the other approaches internal TwipsPerPixels has nothing to do, you are wrong and totally ignorant of this issue.

  23. #23
    Angel of Code Niya's Avatar
    Join Date
    Nov 2011
    Posts
    8,598

    Re: Fix the TwipsPerPixel rounding?

    Quote Originally Posted by Eduardo- View Post
    If you mean your solution of using API everywere to position controls, it is a solution but not the best one.

    But if you say that for the other approaches internal TwipsPerPixels has nothing to do, you are wrong and totally ignorant of this issue.
    You're the one that's being ignorant here. What you are completely failing to grasp is that all these common controls and the Forms themselves are built on top of operating system abstractions. Every time you access the hwnd and hdc properties of Forms, UserControls and common controls, you are accessing operating system resources that has nothing to do with VB6. VB6's ThunderForm and UserControl classes are wrappers around these OS objects and it is these wrappers that implement all this TwipsPerPixel stuff. The OS doesn't know anything about twips as far as it's controls and top level windows are concerned. The Windows operating system measures and positions everything that has an hwnd according to pixel measuremeants, not twips. The bottom line is, whether you use twips or you develop your own system of device independent co-ordinates, at some point you are going to have to tell Windows what to do and you're going to have to do it in pixels. Do you even know how VB6 creates a Form? I'll tell you, it calls this Win32 API function named CreateWindow. That function has several variations and has undergone several changes over the years but it's ultimately what is being called to create every control and every Form in VB6. Do you see anything about twips there? No, it's measured in device units which is basically saying it's expecting sizes and positions to be expressed as pixels.

    Working with twips is a choice, not a necessity. You could use twips, you could use pixels and if they don't meet your needs, you can develop your own device independent unit like DirectX does with DIPs or whatever units WPF uses internally. Point is, all this effort trying to hack twips in VB6 for this DPI stuff shows a seriously lack of understanding of what is actually happening under the hood. Let me say this clearly so you can understand. Twips are just an abstract concept meant to facilitate conversions between different co-ordinate systems. That's all it is. It is not the be all end all of anything.

    I think you're letting the fact that I didn't know about writing DPI aware applications until recently go to your head. I never knew about it because I've never needed to. But make no mistake, I have a lot of experience dealing with this kind of stuff. I've written game engines, I've written all manner of controls. I've done all kinds of wacky things involving different kinds of windows(eg. Layered windows) and graphics. I'm not trying to boast or belittle but I'm letting you know that I know what the hell I'm talking about. I've spent countless hours over many many years learning how a lot of this stuff works. Now I'm not gonna lie, I'm no where near as good as people like Olaf, Tanner Helland, wqweto or LaVolpe but I can hold my own pretty decently. I had my time in the trenches. It took me all of 20 minutes to solve that problem in the project you posted. I know it's not a complete solution and it would probably break under a lot of different conditions but I did that even while not having not used VB6 for something like 6 years and never even knowing a problem like that existed before that day. So don't talk about what I'm ignorant of.
    Treeview with NodeAdded/NodesRemoved events | BlinkLabel control | Calculate Permutations | Object Enums | ComboBox with centered items | .Net Internals article(not mine) | Wizard Control | Understanding Multi-Threading | Simple file compression | Demon Arena

    Copy/move files using Windows Shell | I'm not wanted

    C++ programmers will dismiss you as a cretinous simpleton for your inability to keep track of pointers chained 6 levels deep and Java programmers will pillory you for buying into the evils of Microsoft. Meanwhile C# programmers will get paid just a little bit more than you for writing exactly the same code and VB6 programmers will continue to whitter on about "footprints". - FunkyDexter

    There's just no reason to use garbage like InputBox. - jmcilhinney

    The threads I start are Niya and Olaf free zones. No arguing about the benefits of VB6 over .NET here please. Happiness must reign. - yereverluvinuncleber

  24. #24

    Thread Starter
    PowerPoster
    Join Date
    Feb 2017
    Posts
    4,995

    Re: Fix the TwipsPerPixel rounding?

    Quote Originally Posted by Niya View Post
    You're the one that's being ignorant here.
    Let's see.

    Quote Originally Posted by Niya View Post
    What you are completely failing to grasp is that all these common controls and the Forms themselves are built on top of operating system abstractions. Every time you access the hwnd and hdc properties of Forms, UserControls and common controls, you are accessing operating system resources that has nothing to do with VB6. VB6's ThunderForm and UserControl classes are wrappers around these OS objects and it is these wrappers that implement all this TwipsPerPixel stuff. The OS doesn't know anything about twips as far as it's controls and top level windows are concerned. The Windows operating system measures and positions everything that has an hwnd according to pixel measuremeants, not twips. The bottom line is, whether you use twips or you develop your own system of device independent co-ordinates, at some point you are going to have to tell Windows what to do and you're going to have to do it in pixels. Do you even know how VB6 creates a Form? I'll tell you, it calls this Win32 API function named CreateWindow. That function has several variations and has undergone several changes over the years but it's ultimately what is being called to create every control and every Form in VB6. Do you see anything about twips there? No, it's measured in device units which is basically saying it's expecting sizes and positions to be expressed as pixels.
    LOL. That's a quite basic stuff that most people here already know.
    When I said ignorant I wasn't talking about that.
    I took for granted that you knew all that.
    If I thought that you didn't know that, I would not try to explain anything about this problem.

    I see you have a tendency to answer to things you don't understand. And with arrogance. Ignorance is arrogant.

    Quote Originally Posted by Niya View Post
    Working with twips is a choice
    Yes.
    But if you work in pixels the problem still happen.
    See attachment: Non-Integer_TwipsPerPixels_TestPixels.zip

    That's because even if you work in pixels, VB6 works in twips internally.

    Quote Originally Posted by Niya View Post
    , not a necessity.
    It is a necessity for making the program DPI aware.
    Well, you could do all the calculations for your own in pixels, but that would complicate things a lot.

    Quote Originally Posted by Niya View Post
    You could use twips, you could use pixels and if they don't meet your needs, you can develop your own device independent unit like DirectX does with DIPs or whatever units WPF uses internally.
    For most objects like forms and UserControls you can use a custom scale, you just need to set the scale with ScaleLeft, ScaleTop, ScaleWidth and ScaleHeight, or use the Scale method for all four at a time (and I'm the ignorant).
    But not for every control. Some work only in twips and there is no choice.

    Quote Originally Posted by Niya View Post
    Point is, all this effort trying to hack twips in VB6 for this DPI stuff shows a seriously lack of understanding of what is actually happening under the hood.
    Of you.

    Quote Originally Posted by Niya View Post
    Let me say this clearly so you can understand. Twips are just an abstract concept meant to facilitate conversions between different co-ordinate systems.
    It can be abstract or concrete, it depends how you want to see these things.
    It is concrete because it is one logical inch / 1440... or abstract, whatever you want, it is semantic.

    Quote Originally Posted by Niya View Post
    That's all it is. It is not the be all end all of anything.
    Not, it is just a bug in VB6. Or a design feature that is now is obsolete and causing problems. And it will cause more problems in the future as some DPI settings (like 200%) become more common.
    You didn't understand the problem so far, but right now I'm too tired to explain it to you (I already did with the DPI aware topic and see how you pay back). Perhaps someone else has more desire to explain things to an arrogant guy like you.

    Quote Originally Posted by Niya View Post
    I think you're letting the fact that I didn't know about writing DPI aware applications until recently go to your head.
    It is only one day that you gained some clues about what DPI aware is (because I had to taught to you because you were unable to study the subject for yourself), and you are telling me that I don't understand it, when I had done DPI aware apps for years. Even per monitor.
    You are a clinical case.

    Quote Originally Posted by Niya View Post
    I never knew about it because I've never needed to.
    I needed it since many years ago, this problem is not new. It started with Windows Vista.

    In fact, the problem was present from the start, from when Windows allowed to change the DPI setting from 96 to something else. But with old monitors and Windows it didn't appear too frequently. But I already explained all that to you.

    VB6 was quite ready from the beginning to face this problem of different DPI settings.

    Quote Originally Posted by Niya View Post
    But make no mistake, I have a lot of experience dealing with this kind of stuff. I've written game engines, I've written all manner of controls. I've done all kinds of wacky things involving different kinds of windows(eg. Layered windows) and graphics. I'm not trying to boast or belittle but I'm letting you know that I know what the hell I'm talking about.
    I've spent countless hours over many many years learning how a lot of this stuff works. Now I'm not gonna lie, I'm no where near as good as people like Olaf, Tanner Helland, wqweto or LaVolpe but I can hold my own pretty decently. I had my time in the trenches. It took me all of 20 minutes to solve that problem in the project you posted. I know it's not a complete solution and it would probably break under a lot of different conditions but I did that even while not having not used VB6 for something like 6 years and never even knowing a problem like that existed before that day. So don't talk about what I'm ignorant of.
    You proposed a third solution that is to position the controls with API. that's an alternative.
    But as I said, not a good one (at least for me).
    Do I have to explain why it is not a good one? I don't feel like it.

    This thread wasn't intended for people like you, but for people that already understand the problem and are able to intend a solution. They already answered (without asking about the problem because they already understand it).
    They are The trick and wqweto.

  25. #25
    Angel of Code Niya's Avatar
    Join Date
    Nov 2011
    Posts
    8,598

    Re: Fix the TwipsPerPixel rounding?

    Whatever, I've lost interest in arguing with you.
    Treeview with NodeAdded/NodesRemoved events | BlinkLabel control | Calculate Permutations | Object Enums | ComboBox with centered items | .Net Internals article(not mine) | Wizard Control | Understanding Multi-Threading | Simple file compression | Demon Arena

    Copy/move files using Windows Shell | I'm not wanted

    C++ programmers will dismiss you as a cretinous simpleton for your inability to keep track of pointers chained 6 levels deep and Java programmers will pillory you for buying into the evils of Microsoft. Meanwhile C# programmers will get paid just a little bit more than you for writing exactly the same code and VB6 programmers will continue to whitter on about "footprints". - FunkyDexter

    There's just no reason to use garbage like InputBox. - jmcilhinney

    The threads I start are Niya and Olaf free zones. No arguing about the benefits of VB6 over .NET here please. Happiness must reign. - yereverluvinuncleber

  26. #26

    Thread Starter
    PowerPoster
    Join Date
    Feb 2017
    Posts
    4,995

    Re: Fix the TwipsPerPixel rounding?

    Quote Originally Posted by Niya View Post
    Whatever, I've lost interest in arguing with you.
    That's the point, you come to the forum for arguing, other people come to learn and share knowledge.
    I don't have any interest in arguing with you, I don't want to convince you of anything.

  27. #27

    Thread Starter
    PowerPoster
    Join Date
    Feb 2017
    Posts
    4,995

    Re: Fix the TwipsPerPixel rounding?

    It is the same problem, UserControls, Forms, all the same issue.

    The positioning by API worked because two problems canceled each other: ScaleWidth/ScaleHeight were wrong, and ScaleX/ScaleY converted wrongly, and thus they canceled each other and returned the right pixels.

    Most of VB6 still works because all is internally wrong but consistent, but the postioning of controls via .Move or .Left/Top/Width/Height unfortunately seems to be doing the conversion"right".

  28. #28
    Angel of Code Niya's Avatar
    Join Date
    Nov 2011
    Posts
    8,598

    Re: Fix the TwipsPerPixel rounding?

    If that's the case then just avoid all that entirely and use GetClientRect/GetWindowRect with SetWindowPos to position all your Controls.
    Treeview with NodeAdded/NodesRemoved events | BlinkLabel control | Calculate Permutations | Object Enums | ComboBox with centered items | .Net Internals article(not mine) | Wizard Control | Understanding Multi-Threading | Simple file compression | Demon Arena

    Copy/move files using Windows Shell | I'm not wanted

    C++ programmers will dismiss you as a cretinous simpleton for your inability to keep track of pointers chained 6 levels deep and Java programmers will pillory you for buying into the evils of Microsoft. Meanwhile C# programmers will get paid just a little bit more than you for writing exactly the same code and VB6 programmers will continue to whitter on about "footprints". - FunkyDexter

    There's just no reason to use garbage like InputBox. - jmcilhinney

    The threads I start are Niya and Olaf free zones. No arguing about the benefits of VB6 over .NET here please. Happiness must reign. - yereverluvinuncleber

  29. #29

    Thread Starter
    PowerPoster
    Join Date
    Feb 2017
    Posts
    4,995

    Re: Fix the TwipsPerPixel rounding?

    Code:
    Control.Move 0 , 0, ScaleWidth, ScaleHeight
    Was just a sample to show the problem.
    Real programs has some forms with many controls that position in the available form space with much more complex calculations.
    To move all that code to API based positioning would take much more work than the other option that is just to put a correction factor in the existing code in the places it is needed (what I did).
    Also, as wqweto already mentioned, for windowless UserControls there is no API option.
    Last edited by Shaggy Hiker; Jan 23rd, 2021 at 03:34 PM. Reason: Removed inflammatory stuff.

  30. #30
    Super Moderator Shaggy Hiker's Avatar
    Join Date
    Aug 2002
    Location
    Idaho
    Posts
    38,988

    Re: Fix the TwipsPerPixel rounding?

    You two are flint and steel. Knock it off.
    My usual boring signature: Nothing

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

    Re: Fix the TwipsPerPixel rounding?

    Er, are you asking them to take a knap?

  32. #32
    Super Moderator Shaggy Hiker's Avatar
    Join Date
    Aug 2002
    Location
    Idaho
    Posts
    38,988

    Re: Fix the TwipsPerPixel rounding?

    Well, that could make a good point.
    My usual boring signature: Nothing

  33. #33
    PowerPoster yereverluvinuncleber's Avatar
    Join Date
    Feb 2014
    Location
    Norfolk UK (inbred)
    Posts
    2,235

    Re: Fix the TwipsPerPixel rounding?

    You are sparking tonight.

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