• Welcome to PlanetSquires Forums.
 

3.51 increases Form size after compile

Started by Eddy Van Esch, January 25, 2012, 08:01:26 AM

Previous topic - Next topic

Eddy Van Esch

Hi,

Maybe this issue has already been addressed before, but I couldn't find anything about it on these forums, so here goes:

I recompiled an old(er) project, originally designed with FF 3.10, again with FF 3.51.
I noticed that the form size is larger when you run the compiled exe, then it is in the visual designer. (see screenshots).

I recompiled with the 'old' FF 3.10 and there the form size is correct.

I have my desktop resulotion normallyset to 120 DPI. I changed it back to the default resulotion of 96 DPI, but the result remained the same (I didn't reboot though).
Could this be the result of some feature added in FF 3.51 that I overlooked?

Kind regards
Eddy

Eddy

Paul Squires

It could be the DPI issue. I am working on that problem/fix/hack for the next update.
Paul Squires
PlanetSquires Software
WinFBE Editor and Visual Designer

Eddy Van Esch

Ok, thanks Paul!

How is everyone else dealing with this for the moment? (work-around...?)
Or am I the only one seeing this issue?

Kind regards
Eddy
Eddy

Paul Squires

Hi Eddy,

Please download and try the new FireFly35.exe found in the zip file at this link:
http://www.planetsquires.com/protect/download/FireFly_DPI_Test.zip

Please let me know if it fixes your problem.

Paul Squires
PlanetSquires Software
WinFBE Editor and Visual Designer

Eddy Van Esch

#4
Paul,

I'm afraid the problem remains the same....  :(

Kind regards
Eddy
Eddy

Eddy Van Esch

#5
Paul

I did a little more testing on another pc that always has been on 'normal' (96) DPI.
On that pc, the problem did not show.

I set DPI to 120, rebooted and the problem now also appeared here.

I set DPI again to 96, rebooted and the problem disappeared. So this issue is definitely DPI related (although your last build of 3.51 did not solve it).

PS. I also reset DPI again to 96 (coming from 120), without rebooting and the problem remained (although the desktop fonts returned to 96 size).
PPS. On this test pc, I just ran the program, I compiled it on my dev pc.

Hope this helps.

Kind regards
Eddy


Eddy

Paul Squires

I'm still having trouble with this. The XP scaling (or Win7 "Use Windows XP DPI style scaling") is causing a lot of problems. Could be because some of FF's internal code is using Jose's cWindow and others are using simple CreateWindowEx calls. For example, the "Form" that you see displayed in the FF designer (the one with the grab handles around it) was created with CreateWindowEx. When you compile/run the project, you see the Form created using Jose's cWindow.

To fix, I need to do one of the following:
(1) Disable all scaling in cWindow code.
(2) Ensure that all FireFly internal code uses cWindow rather than a mix of CreateWindowEx and cWindow.
(3) Find a way to make the WinXP stlye DPI scaling work similar to Win7, or vise versa.

I still need to keep looking into this. Tough problem.

Jose mention in another thread that simply adding pWindow.DPI = 96 to the generated code would fix the problem. That's what I did for the exe I posted in the earlier post, and that didn't fix the problem.

Stay tuned.

Paul Squires
PlanetSquires Software
WinFBE Editor and Visual Designer

Eddy Van Esch

Paul,

Thanks for explaining in such detail.
I indeed forgot to mention that I am using XP SP3.
If you would like me to test something, just let me know.

Kind regards
Eddy
Eddy

José Roca

#8
High DPI and visual designers is a problem hard to solve. Not even Micrsoft has managed to solve it. His visual designer for Visual Studio uses High DPI for its interface (menus, toolbars and all this), but when you try to build a form dragging and dropping controls using pixels, for a SDK application, not for WinForms or wathever they use now, they become so small that are impossible to read, and if you increase the size, then when you will run the application they will look oversized. I guess that his solution is: don't use SDK.

FireFly is running in virtualized mode, so the size of the windows, controls and images look correct because the system is rendering them as if you were using 96 DPI instead of, e.g. 120 DPI. If you don't do any scaling, and your application will run in virtualized mode only, it will look correct in Windows 7 and Aero mode, although in many cases you will get artifacts, fuzzy fonts, drag and drop not working correctly, etc. But if you make the application High DPI aware, either by calling SetProcessDPIAware, adding an appropriate manifest, or selecting in Windows 7 a mode such Windows 7 Basic, that doesn't use virtualizacion to save resources, your GUI will look very small if you are using a high resolution. Why? Simply because pixels in a high resolution screen are smaller than in a lower resolution one. As you can't increase the size of the pixels, you have to do scaling. Same for images, graphics and fonts (the standard font for Windows 7 is SegoeUI). Your icons that will look correct when used in virtualized mode, will look tiny in a high resolution monitor and High DPI, so you have to use several icons or image lists of different sizes and choose the most appropriate at run time, or use one and stretch it. And do it well, because, otherwise, a GUI that looks fine in your system can look terrible in the system of another user using different settings and/or resolution.

Virtualized mode is a workaround used by Microsoft to allow legacy applications to run more or less well in Vista/Windows 7. Otherwise, all these applications would have become unusable. But is just a workaround intended to give time to developers to adapt his applications or rewrite them.

So which could be the solution? A hard one. As I see it, the visual designer should be fully High DPI aware and the forms and controls scaled according the DPI settings of the user, but not only when the application runs, but also at design time.

Currently, and I have tried it with hundreds of tests and have written complex applications such the CSED editor, the only open known issue is with a later addition of a method called AddTabPage, designed to easily use the tab control when coding by hand, that is what I do in my examples and tools to no force the use of a particular designer, because not all the members of my forum are FireFly users. This problem is making me mad because only happens when you add a button to the main form, not the tab pages. Use any other type of control and works perfectly. Anyway, this method is not being used by FireFly.

My CSED editor has been written entirely using CWindow and works perfectly in all resolutions, DPIs and Windows modes. Also drag and drop works perfectly, something that does not happen with SED, that was written the old way, before the popularization of high resolution monitors. I designed CWindow in part because the alternative is to do all the scaling by yourself, calculating the ratios and multiply all the values and variables that use pixels by them. It also allows to make your application fully unicode aware by simply declaring %UNICODE = 1 before any #INCLUDEs, although FireFly is till not using this feature.

DDT applications mostly work if you use unit dialogs instead of pixels, because they are scaled by Windows, the same that my CWindow class does, although there are some problems because it uses LONGs and there are rounding differences. This is why I have used SINGLEs instead of LONGs in CWindow. I even had a hard time to resolve a problem when using the WebBrowser control because the text, graphics and maps appeared tiny, and had to solve it using the zoom property of Internet Explorer 9, It would not work with old versions like IE 6 because they used a different zooming schema.

But above all, make sure that you fully understand everything involved. One of the few interesting articles that I have found is this one:

http://msdn.microsoft.com/en-us/library/windows/desktop/dd464660%28v=vs.85%29.aspx

Don't read it quickly, but make sure that you fully understand everything. And FF customers too, because some things can't be resolved automatically and will require their intervention and changes in their code.

You asked for high resolution monitors, don't you? Now you have to pay the price...

Paul Squires

Thanks Jose for the awesome explanation! Really appreciate it. I have also printed off that MSDN article and will read and digest it.

Looks like I will have to start going through the internal FireFly codebase and start ensuring that everything is converted over to cWindow. That is a pretty big undertaking. I'll study up on everything first though just so I fully understand the implications of what is involved.

Thanks again,

Paul

Paul Squires
PlanetSquires Software
WinFBE Editor and Visual Designer

Eddy Van Esch

Paul,

I can imagine it 's a huge undertaking and I am sure you will bring it to a good end.
Meanwhile, could this be a related problem?
http://www.planetsquires.com/protect/forum/index.php?topic=3041.new#new

Kind regards
Eddy
Eddy

José Roca

#11
Quote
Jose mention in another thread that simply adding pWindow.DPI = 96 to the generated code would fix the problem. That's what I did for the exe I posted in the earlier post, and that didn't fix the problem.

Setting DPI = 96 disables scaling, but only if your application is High DPI aware or you are running in Vista/Windows 7 using a mode that doesn't use virtualization. When the program is being running virtualized by Windows, if you query for the DPI value it returns 96, no matter if you're using 120 or 200, so it does nothing.

I have difficulties to explain complex things in English, so I will show some pictures.


José Roca

#12
All the three images of the listboxes have been produced using Windows 7 with a screen resolution of 1680x1050, Aero and a DPI of 175%.

In the first one I'm using this code:


' ########################################################################################
' Microsoft Windows
' File: CW_ListBox.pbtpl
' Contents: Template - CWindow with a ListBox
' Compilers: PBWIN 10.02+, PBCC 6.02+
' Headers: Windows API headers 2.03+
' Copyright (c) 2011 Jose Roca. Freeware. Use at your own risk.
' THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER
' EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF
' MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE.
' ########################################################################################
#COMPILE EXE
#DIM ALL
%UNICODE = 1

' // Include files for external files
#INCLUDE ONCE "CWindow.inc"        ' // CWindow class
#INCLUDE ONCE "ListBoxCtrl.inc"    ' // ListBox wrappers

%IDC_LISTBOX = 1001

' ========================================================================================
' Main
' ========================================================================================
FUNCTION WinMain (BYVAL hInstance AS DWORD, BYVAL hPrevInstance AS DWORD, BYVAL lpszCmdLine AS WSTRINGZ PTR, BYVAL nCmdShow AS LONG) AS LONG

   ' // Create an instance of the class
   LOCAL pWindow AS IWindow
   pWindow = CLASS "CWindow"
   IF ISNOTHING(pWindow) THEN EXIT FUNCTION

   ' // Create the main window
   LOCAL hwndMain AS DWORD
   hwndMain = pWindow.CreateWindow(%NULL, "CWindow with a ListBox", 0, 0, 0, 0, 0, 0, CODEPTR(WindowProc))
   ' // Change the window style to avoid flicker
   pWindow.ClassStyle = %CS_DBLCLKS
   ' // Set the client size
   pWindow.SetClientSize(320, 375)
   ' // Center the window
   pWindow.CenterWindow

   ' // Add a listbox
   LOCAL hListBox AS DWORD
   hListBox = pWindow.AddListbox(hwndMain, %IDC_LISTBOX, "", 0, 0, 0, 0)
   pWindow.SetWindowPos hListBox, %NULL, 8, 8, 300, 320, %SWP_NOZORDER

   ' // Fill the list box
   LOCAL i AS LONG
   FOR i = 1 TO 50
      ListBox_AddString(hListBox, "Item " & FORMAT$(i, "00"))
   NEXT

   ' // Select the first item
   ListBox_SetCurSel hListBox, 0

   ' // Add a cancel button
   pWindow.AddButton(hwndMain, %IDCANCEL, "&Cancel", 233, 338, 75, 23)

   ' // Default message pump (you can replace it with your own)
   pWindow.DoEvents(nCmdShow)

END FUNCTION
' ========================================================================================

' ========================================================================================
' Main callback function.
' ========================================================================================
FUNCTION WindowProc (BYVAL hwnd AS DWORD, BYVAL uMsg AS DWORD, BYVAL wParam AS DWORD, BYVAL lParam AS LONG) AS LONG

   ' // Process window mesages
   SELECT CASE uMsg

      CASE %WM_COMMAND
         SELECT CASE LO(WORD, wParam)

            CASE %IDCANCEL
               ' // If the Escape key has been pressed...
               IF HI(WORD, wParam) = %BN_CLICKED THEN
                  ' // ... close the application by sending a WM_CLOSE message
                  SendMessage hwnd, %WM_CLOSE, 0, 0
                  EXIT FUNCTION
               END IF

            CASE %IDC_LISTBOX
               SELECT CASE HI(WORD, wParam)
                  CASE %LBN_DBLCLK
                     ' // Get the handle of the Listbox
                     LOCAL hListBox AS DWORD
                     hListBox = GetDlgItem(hwnd, %IDC_LISTBOX)
                     ' // Get the current selection
                     LOCAL curSel AS LONG
                     curSel = ListBox_GetCurSel(hListBox)
                     MSGBOX ListBox_GetText(hListBox, curSel)
                     EXIT FUNCTION
               END SELECT

         END SELECT

      CASE %WM_DESTROY
         ' // End the application
         PostQuitMessage 0
         EXIT FUNCTION

   END SELECT

   ' // Pass unprocessed messages to Windows
   FUNCTION = DefWindowProc(hwnd, uMsg, wParam, lParam)

END FUNCTION
' ========================================================================================


being run in virtualized mode by Windows. If you query by the DPI value, Windows returns 96 despite I'm using 175.

The second one uses the same code but I have added a call to SetProcessDPIAware. Now Windows runs it non virtualized and CWindow takes kare of the scaling. The size is the same, but you will notice that the font is now the same that the one used by Windows in the window caption, and that the button and the scrollbar are rendered slightly different.


' ########################################################################################
' Microsoft Windows
' File: CW_ListBox.pbtpl
' Contents: Template - CWindow with a ListBox
' Compilers: PBWIN 10.02+, PBCC 6.02+
' Headers: Windows API headers 2.03+
' Copyright (c) 2011 Jose Roca. Freeware. Use at your own risk.
' THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER
' EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF
' MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE.
' ########################################################################################
#COMPILE EXE
#DIM ALL
%UNICODE = 1

' // Include files for external files
#INCLUDE ONCE "CWindow.inc"        ' // CWindow class
#INCLUDE ONCE "ListBoxCtrl.inc"    ' // ListBox wrappers

%IDC_LISTBOX = 1001

' ========================================================================================
' Main
' ========================================================================================
FUNCTION WinMain (BYVAL hInstance AS DWORD, BYVAL hPrevInstance AS DWORD, BYVAL lpszCmdLine AS WSTRINGZ PTR, BYVAL nCmdShow AS LONG) AS LONG

   ' // Set process DPI aware
   SetProcessDPIAware

   ' // Create an instance of the class
   LOCAL pWindow AS IWindow
   pWindow = CLASS "CWindow"
   IF ISNOTHING(pWindow) THEN EXIT FUNCTION

   ' // Create the main window
   LOCAL hwndMain AS DWORD
   hwndMain = pWindow.CreateWindow(%NULL, "CWindow with a ListBox", 0, 0, 0, 0, 0, 0, CODEPTR(WindowProc))
   ' // Change the window style to avoid flicker
   pWindow.ClassStyle = %CS_DBLCLKS
   ' // Set the client size
   pWindow.SetClientSize(320, 375)
   ' // Center the window
   pWindow.CenterWindow

   ' // Add a listbox
   LOCAL hListBox AS DWORD
   hListBox = pWindow.AddListbox(hwndMain, %IDC_LISTBOX, "", 0, 0, 0, 0)
   pWindow.SetWindowPos hListBox, %NULL, 8, 8, 300, 320, %SWP_NOZORDER

   ' // Fill the list box
   LOCAL i AS LONG
   FOR i = 1 TO 50
      ListBox_AddString(hListBox, "Item " & FORMAT$(i, "00"))
   NEXT

   ' // Select the first item
   ListBox_SetCurSel hListBox, 0

   ' // Add a cancel button
   pWindow.AddButton(hwndMain, %IDCANCEL, "&Cancel", 233, 338, 75, 23)

   ' // Default message pump (you can replace it with your own)
   pWindow.DoEvents(nCmdShow)

END FUNCTION
' ========================================================================================

' ========================================================================================
' Main callback function.
' ========================================================================================
FUNCTION WindowProc (BYVAL hwnd AS DWORD, BYVAL uMsg AS DWORD, BYVAL wParam AS DWORD, BYVAL lParam AS LONG) AS LONG

   ' // Process window mesages
   SELECT CASE uMsg

      CASE %WM_COMMAND
         SELECT CASE LO(WORD, wParam)

            CASE %IDCANCEL
               ' // If the Escape key has been pressed...
               IF HI(WORD, wParam) = %BN_CLICKED THEN
                  ' // ... close the application by sending a WM_CLOSE message
                  SendMessage hwnd, %WM_CLOSE, 0, 0
                  EXIT FUNCTION
               END IF

            CASE %IDC_LISTBOX
               SELECT CASE HI(WORD, wParam)
                  CASE %LBN_DBLCLK
                     ' // Get the handle of the Listbox
                     LOCAL hListBox AS DWORD
                     hListBox = GetDlgItem(hwnd, %IDC_LISTBOX)
                     ' // Get the current selection
                     LOCAL curSel AS LONG
                     curSel = ListBox_GetCurSel(hListBox)
                     MSGBOX ListBox_GetText(hListBox, curSel)
                     EXIT FUNCTION
               END SELECT

         END SELECT

      CASE %WM_DESTROY
         ' // End the application
         PostQuitMessage 0
         EXIT FUNCTION

   END SELECT

   ' // Pass unprocessed messages to Windows
   FUNCTION = DefWindowProc(hwnd, uMsg, wParam, lParam)

END FUNCTION
' ========================================================================================


In the 3rd one, I'm using SetProcessDPIAware but tellig CWindow to not do scalign by setting DPI = 96. The look is the same than in the 2nd example, but the size of the Windows and the controls are much smaller since they haven't been scaled.


' ########################################################################################
' Microsoft Windows
' File: CW_ListBox.pbtpl
' Contents: Template - CWindow with a ListBox
' Compilers: PBWIN 10.02+, PBCC 6.02+
' Headers: Windows API headers 2.03+
' Copyright (c) 2011 Jose Roca. Freeware. Use at your own risk.
' THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER
' EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF
' MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE.
' ########################################################################################
#COMPILE EXE
#DIM ALL
%UNICODE = 1

' // Include files for external files
#INCLUDE ONCE "CWindow.inc"        ' // CWindow class
#INCLUDE ONCE "ListBoxCtrl.inc"    ' // ListBox wrappers

%IDC_LISTBOX = 1001

' ========================================================================================
' Main
' ========================================================================================
FUNCTION WinMain (BYVAL hInstance AS DWORD, BYVAL hPrevInstance AS DWORD, BYVAL lpszCmdLine AS WSTRINGZ PTR, BYVAL nCmdShow AS LONG) AS LONG

   ' // Set process DPI aware
   SetProcessDPIAware

   ' // Create an instance of the class
   LOCAL pWindow AS IWindow
   pWindow = CLASS "CWindow"
   IF ISNOTHING(pWindow) THEN EXIT FUNCTION
   pWindow.DPI = 96

   ' // Create the main window
   LOCAL hwndMain AS DWORD
   hwndMain = pWindow.CreateWindow(%NULL, "CWindow with a ListBox", 0, 0, 0, 0, 0, 0, CODEPTR(WindowProc))
   ' // Change the window style to avoid flicker
   pWindow.ClassStyle = %CS_DBLCLKS
   ' // Set the client size
   pWindow.SetClientSize(320, 375)
   ' // Center the window
   pWindow.CenterWindow

   ' // Add a listbox
   LOCAL hListBox AS DWORD
   hListBox = pWindow.AddListbox(hwndMain, %IDC_LISTBOX, "", 0, 0, 0, 0)
   pWindow.SetWindowPos hListBox, %NULL, 8, 8, 300, 320, %SWP_NOZORDER

   ' // Fill the list box
   LOCAL i AS LONG
   FOR i = 1 TO 50
      ListBox_AddString(hListBox, "Item " & FORMAT$(i, "00"))
   NEXT

   ' // Select the first item
   ListBox_SetCurSel hListBox, 0

   ' // Add a cancel button
   pWindow.AddButton(hwndMain, %IDCANCEL, "&Cancel", 233, 338, 75, 23)

   ' // Default message pump (you can replace it with your own)
   pWindow.DoEvents(nCmdShow)

END FUNCTION
' ========================================================================================

' ========================================================================================
' Main callback function.
' ========================================================================================
FUNCTION WindowProc (BYVAL hwnd AS DWORD, BYVAL uMsg AS DWORD, BYVAL wParam AS DWORD, BYVAL lParam AS LONG) AS LONG

   ' // Process window mesages
   SELECT CASE uMsg

      CASE %WM_COMMAND
         SELECT CASE LO(WORD, wParam)

            CASE %IDCANCEL
               ' // If the Escape key has been pressed...
               IF HI(WORD, wParam) = %BN_CLICKED THEN
                  ' // ... close the application by sending a WM_CLOSE message
                  SendMessage hwnd, %WM_CLOSE, 0, 0
                  EXIT FUNCTION
               END IF

            CASE %IDC_LISTBOX
               SELECT CASE HI(WORD, wParam)
                  CASE %LBN_DBLCLK
                     ' // Get the handle of the Listbox
                     LOCAL hListBox AS DWORD
                     hListBox = GetDlgItem(hwnd, %IDC_LISTBOX)
                     ' // Get the current selection
                     LOCAL curSel AS LONG
                     curSel = ListBox_GetCurSel(hListBox)
                     MSGBOX ListBox_GetText(hListBox, curSel)
                     EXIT FUNCTION
               END SELECT

         END SELECT

      CASE %WM_DESTROY
         ' // End the application
         PostQuitMessage 0
         EXIT FUNCTION

   END SELECT

   ' // Pass unprocessed messages to Windows
   FUNCTION = DefWindowProc(hwnd, uMsg, wParam, lParam)

END FUNCTION
' ========================================================================================


But if I use pWindow.DPI = 96 as in the 3rd example in a program that is going to be run virtualized, as you did try, the result will be the same as in the first example because Windows is already running it as if you were using 96 DPI instead of 175.


José Roca

But there are further complications, depending if Aero is activated or not, if you are using Windows 7 Basic Theme or one of the contrast themes, if in Windows 7 you have checked the option "Use windows xp style DPI scaling", if you are using XP with large or custom fonts, etc. A truly nightmare.

Even some Microsoft programmers seem not to kown all the rules, because in my monitor some of the dialogs of Windows itself appear oversized and the Accept, Cancel buttons can't be clicked because they are rendered outside the screen.


José Roca

There are some oddities with scrollbars. You will notice that in the 3rd example the size of the window and the controls are smaller, but the width of the scrollbar is the same that in the 2nd example. This doesn't happen with the WebBrowser control and .chm files (that use the WebBrowser control to render the html pages), but this control has a different problem: the scrollbar doesn't become wider when you scale the control.

Ownerdrawn scrollbars used by some legacy programs/controls also look funny. See picture below.