WinFBX window client area width
-
- Posts: 4313
- Joined: Jan 02, 2017 0:34
- Location: UK
- Contact:
WinFBX window client area width
@JosepRoca
Hi José
Have you imposed a limit on the width of the client area of a window.
pWindow.SetClientSize( x, y )
x = 150 => width of 150
x = 140 => width of 140
x = 130 => width of 136
x = 120 => width of 136
x = 110 => width of 136
I hit a barrier at 136.
Thanks.
Hi José
Have you imposed a limit on the width of the client area of a window.
pWindow.SetClientSize( x, y )
x = 150 => width of 150
x = 140 => width of 140
x = 130 => width of 136
x = 120 => width of 136
x = 110 => width of 136
I hit a barrier at 136.
Thanks.
-
- Posts: 564
- Joined: Sep 27, 2016 18:20
- Location: Valencia, Spain
Re: WinFBX window client area width
I don't, but Windows does. It needs a minimum width to display things such the application icon and, depending of the styles used, the maximize/minimize button and the close button.
The SetClientSize calls the wrapper procedure AfxSetWindowClientSize (see below), which calls the API function AdjustWindowRectEx and does some tweaks to solve limitations of AdjustWindowRectEx regarding wrapped menus and scrollbars and the fact that it is not DPI aware. See: AdjustWindowRectEx function ( https://docs.microsoft.com/en-us/window ... ndowrectex )
The SetClientSize calls the wrapper procedure AfxSetWindowClientSize (see below), which calls the API function AdjustWindowRectEx and does some tweaks to solve limitations of AdjustWindowRectEx regarding wrapped menus and scrollbars and the fact that it is not DPI aware. See: AdjustWindowRectEx function ( https://docs.microsoft.com/en-us/window ... ndowrectex )
Code: Select all
' ========================================================================================
' Adjusts the bounding rectangle of a window based on the desired size of the client area.
' Parameters:
' - hwnd = The window handle.
' - nWidth and nHeight = The desired size of the client area.
' - rxRatio and ryRatio = Scaling ratios.
' ========================================================================================
PRIVATE SUB AfxSetWindowClientSize (BYVAL hwnd AS HWND, BYVAL nWidth AS LONG, BYVAL nHeight AS LONG, BYVAL rxRatio AS SINGLE = 1, BYVAL ryRatio AS SINGLE = 1)
DIM rc AS RECT, rcTemp AS RECT
' // Convert the client rectangle to a window rectangle.
' // The AdjustWindowRectEx function cannot take menu wrapping into account
' // because it doesn't know which menu we are using.
SetRect(@rc, 0, 0, nWidth * rxRatio, nHeight * ryRatio)
DIM hMenu AS HANDLE = GetMenu(hwnd)
DIM dwStyle AS DWORD = GetWindowLongPtrW(hwnd, GWL_STYLE)
AdjustWindowRectEx(@rc, dwStyle, (hMenu <> NULL), GetWindowLongPtrW(hwnd, GWL_EXSTYLE))
' // If there is a menu, we need to check how much wrapping occurs when we set
' // the window to the width specified by AdjustWindowRectEX and an infinite
' // amount of height. An infinite height allows us to see every single menu wrap.
IF hMenu <> NULL THEN
rcTemp = rc
rcTemp.Bottom = &H7FFF ' // "Infinite" height
SendMessageW(hwnd, WM_NCCALCSIZE, 0, CAST(LPARAM, @rcTemp))
' // Adjust our previous calculation to compensate for menu wrapping.
rc.Bottom = rc.Bottom + rcTemp.Top
END IF
' // The AdjustWindowRectEx function does not take the WS_VSCROLL or WS_HSCROLL
' // styles into account. To account for the scroll bars, we need to call the
' // GetSystemMetrics function with SM_CXVSCROLL or SM_CYHSCROLL.
IF (dwStyle AND WS_HSCROLL) = WS_HSCROLL THEN
rc.Bottom = rc.Bottom + GetSystemMetrics(SM_CYHSCROLL)
END IF
IF (dwStyle AND WS_VSCROLL) = WS_VSCROLL THEN
rc.Right = rc.Right + GetSystemMetrics(SM_CXVSCROLL)
END IF
DIM cx AS LONG = rc.Right - rc.Left
DIM cy AS LONG = rc.Bottom - rc.Top
SetWindowPos(hwnd, NULL, 0, 0, cx, cy, SWP_NOZORDER OR SWP_NOMOVE OR SWP_NOACTIVATE)
END SUB
' ========================================================================================
-
- Posts: 4313
- Joined: Jan 02, 2017 0:34
- Location: UK
- Contact:
Re: WinFBX window client area width
Thanks José.
I found some code by Paul Squires, and he was setting 120 and getting 120. When he created the window he used WS_POPUP among the styles whereas I did not.
With PowerBASIC WS_POPUP is included as a default style.
I ported a function from PowerBASIC. What with parameters being ByRef by default in PowerBASIC and ByVal by default in FreeBASIC and FreeBASIC's strong type casting it took me half a morning to get no errors and, just as important, get the correct results. I am still getting seven warnings five of which are 'Passing scalar as pointer' and I reckon none of them are true. So how big is this function? Ten lines! Seven warnings in ten lines must be a record. Is the application working? Yep!
How you and Paul manage to write Windows GUIs in FreeBASIC and maintain your sanity is beyond me. It probably explains why there not many members writing Windows GUIs in FreeBASIC.
Added: I have decided to use '-w none' and be damned.
I found some code by Paul Squires, and he was setting 120 and getting 120. When he created the window he used WS_POPUP among the styles whereas I did not.
With PowerBASIC WS_POPUP is included as a default style.
I ported a function from PowerBASIC. What with parameters being ByRef by default in PowerBASIC and ByVal by default in FreeBASIC and FreeBASIC's strong type casting it took me half a morning to get no errors and, just as important, get the correct results. I am still getting seven warnings five of which are 'Passing scalar as pointer' and I reckon none of them are true. So how big is this function? Ten lines! Seven warnings in ten lines must be a record. Is the application working? Yep!
How you and Paul manage to write Windows GUIs in FreeBASIC and maintain your sanity is beyond me. It probably explains why there not many members writing Windows GUIs in FreeBASIC.
Added: I have decided to use '-w none' and be damned.
-
- Posts: 564
- Joined: Sep 27, 2016 18:20
- Location: Valencia, Spain
Re: WinFBX window client area width
> With PowerBASIC WS_POPUP is included as a default style.
PowerBASIC uses the Windows Dialog Engine, which is intended for dialog boxes, and defaults to a WS_POPUP style. SDK programmers use WS_OVERLAPPED for main windows. Of course, you can use WS_POPUP with CWindow by specifying this style in the Create method of by calling the WindowStyle property after Create.
> What with parameters being ByRef by default in PowerBASIC and ByVal by default in FreeBASIC [...]
I always have specified BYVAL or BYREF in all parameters, even with PowerBASIC.
> I am still getting seven warnings five of which are 'Passing scalar as pointer'
If you can post the code, I'm sure there is an easy solution. PBer's are used to always declare variables as LONG or DWORD. The key is to declare the variables with the appropriate type to match the API declarations.
> How you and Paul manage to write Windows GUIs in FreeBASIC and maintain your sanity is beyond me. It probably explains why there not many members writing Windows GUIs in FreeBASIC.
It was very annoying at the beginning, but you get used to it. Your main problem is that all that DDT stuff that you have learned is totally useless with SDK programming.
PowerBASIC uses the Windows Dialog Engine, which is intended for dialog boxes, and defaults to a WS_POPUP style. SDK programmers use WS_OVERLAPPED for main windows. Of course, you can use WS_POPUP with CWindow by specifying this style in the Create method of by calling the WindowStyle property after Create.
> What with parameters being ByRef by default in PowerBASIC and ByVal by default in FreeBASIC [...]
I always have specified BYVAL or BYREF in all parameters, even with PowerBASIC.
> I am still getting seven warnings five of which are 'Passing scalar as pointer'
If you can post the code, I'm sure there is an easy solution. PBer's are used to always declare variables as LONG or DWORD. The key is to declare the variables with the appropriate type to match the API declarations.
> How you and Paul manage to write Windows GUIs in FreeBASIC and maintain your sanity is beyond me. It probably explains why there not many members writing Windows GUIs in FreeBASIC.
It was very annoying at the beginning, but you get used to it. Your main problem is that all that DDT stuff that you have learned is totally useless with SDK programming.
-
- Posts: 4313
- Joined: Jan 02, 2017 0:34
- Location: UK
- Contact:
Re: WinFBX window client area width
I returned to the function above where I had seven warnings. I am no longer getting any warnings and this is the result.
Cast(hWnd, hWnd) and Cast(hFont, hFont)
The mind boggles.
I have been reading the source code in WinFBE and did a 'containing text' search on Cast in the inc files and found reams of them, about 3% of the lines with some files.
Cast(hWnd, hWnd) and Cast(hFont, hFont)
The mind boggles.
I have been reading the source code in WinFBE and did a 'containing text' search on Cast in the inc files and found reams of them, about 3% of the lines with some files.
Code: Select all
FUNCTION GetTextWidth (BYVAL hWnd AS Dword, BYVAL txt AS WSTRING Ptr) AS LONG
Dim hDC AS HDC, hFont AS DWORD, sz AS SIZE
hDC = GetDc(Cast(hWnd, hWnd))
hFont = SendMessage(Cast(Hwnd, hWnd), WM_GETFONT, 0, 0)
Cast(hFont, hFont) = SelectObject(hDC, Cast(hFont, hFont))
GetTextExtentPoint32 hDC, txt, LEN(*txt), @sz
SelectObject hDC, Cast(hFont, hFont)
ReleaseDC Cast(hWnd, hWnd), hDC
FUNCTION = sz.cx
END FUNCTION
-
- Posts: 564
- Joined: Sep 27, 2016 18:20
- Location: Valencia, Spain
Re: WinFBX window client area width
You don't need so many casts if you write the code properly, i.e.
Besides, it will work with both 32 and 64-bit compilers.
Using hWnd AS Dword instead of hWnd AS HWND and hFont AS DWORD instead of hFont AS HFONT means that the code won't work in 64-bit, because handles are 4 bits in 32 bit, but 8 bytes in 64 bit. HWND is a typedef that evaluates to 4 or 8 bytes depending of the compiler. Same with HFONT. As I said above, "The key is to declare the variables with the appropriate type to match the API declarations."
The only time that we need to use CAST is in hFont = CAST(HFONT, SendMessage(hWnd, WM_GETFONT, 0, 0)), because SendMessage is a generic function that retuns an LRESULT.
Code: Select all
FUNCTION GetTextWidth (BYVAL hWnd AS HWND, BYVAL txt AS WSTRING Ptr) AS LONG
Dim hDC AS HDC, hFont AS HFONT, sz AS SIZE
hDC = GetDc(hWnd)
hFont = CAST(HFONT, SendMessage(hWnd, WM_GETFONT, 0, 0))
hFont = SelectObject(hDC, hFont)
GetTextExtentPoint32 hDC, txt, LEN(*txt), @sz
SelectObject hDC, hFont
ReleaseDC hWnd, hDC
FUNCTION = sz.cx
END FUNCTION
Using hWnd AS Dword instead of hWnd AS HWND and hFont AS DWORD instead of hFont AS HFONT means that the code won't work in 64-bit, because handles are 4 bits in 32 bit, but 8 bytes in 64 bit. HWND is a typedef that evaluates to 4 or 8 bytes depending of the compiler. Same with HFONT. As I said above, "The key is to declare the variables with the appropriate type to match the API declarations."
The only time that we need to use CAST is in hFont = CAST(HFONT, SendMessage(hWnd, WM_GETFONT, 0, 0)), because SendMessage is a generic function that retuns an LRESULT.
-
- Posts: 4313
- Joined: Jan 02, 2017 0:34
- Location: UK
- Contact:
Re: WinFBX window client area width
Hmmm, I now get five warnings.
-
- Posts: 564
- Joined: Sep 27, 2016 18:20
- Location: Valencia, Spain
Re: WinFBX window client area width
Five warning in this function (I don't think so, because I don't get any) or in other parts of the code? Maybe you have handles declared as DWORD or something like that.
-
- Posts: 4313
- Joined: Jan 02, 2017 0:34
- Location: UK
- Contact:
Re: WinFBX window client area width
I don't now.José wrote:(I don't think so, because I don't get any)
I still had
Code: Select all
Declare FUNCTION GetTextWidth ( As Dword, As WSTRING Ptr) As LONG
Code: Select all
Declare FUNCTION GetTextWidth ( As hWnd, As WSTRING Ptr) As LONG
With Encrypternet, which is only a 1066 line source code, I used Cast 32 times, 3% of the code, and that compiled in 32-bit and 64-bit without errors or warnings, so I obviously got that right.
However, an inordinate amount of time was spent getting the casting right in addition to reading up on some APIs at MSDN which I had never used before.
I don't care what anyone says writing Windows GUIs in FreeBASIC is torturous.
Let the machine do the dirty work. -- Kernighan and Ritchie, "Elements of Programming Style"
I have a computer in front of me, and I am having to do the dirty work.
> there was another warning with some later code.
I used 'Dim hMutex As Long' and I should have used 'Dim hMutex As Handle'. So it is not just parameters we need to watch but the API's return value as well. That line was ported from PowerBASIC.
-
- Posts: 564
- Joined: Sep 27, 2016 18:20
- Location: Valencia, Spain
Re: WinFBX window client area width
> With Encrypternet, which is only a 1066 line source code, I used Cast 32 times
You must be doing something wrong. I don't need to use cast so often.
You must be doing something wrong. I don't need to use cast so often.
-
- Posts: 4313
- Joined: Jan 02, 2017 0:34
- Location: UK
- Contact:
Re: WinFBX window client area width
Clearly there is an art to it that few of us have managed to fully grasp.Yours truly wrote:I have been reading the source code in WinFBE and did a 'containing text' search on Cast in the inc files and found reams of them, about 3% of the lines with some files.
-
- Posts: 564
- Joined: Sep 27, 2016 18:20
- Location: Valencia, Spain
Re: WinFBX window client area width
To avoid many of the casting problems, declare the variables as the same type that you will find in the declarations in MSDN or in the FB .bi files. Just be aware that C++ INT does not traslate to FB INTEGER, but to INT_ or LONG, and UINT does not translate to FB UINTEGER, but to UINT_ or DWORD. This is because a peculiarity of FB INTEGER/UINTEGER data types that are interpreted as 32bit or 64-bit depending of the compiler that you're using.
If you declare handles and/or pointers as DWORD/LONG, you're going to have many problems, not only casting, but it won't work with 64-bit. It is not the same to work with a 32-bit only compiler like PB, that to write applications that can be compiled to 32 or 64 bit without changes in the code. If one day PB released a 64-bit compiler, trying to adapt existing PB applications would be a nightmare.
If you declare handles and/or pointers as DWORD/LONG, you're going to have many problems, not only casting, but it won't work with 64-bit. It is not the same to work with a 32-bit only compiler like PB, that to write applications that can be compiled to 32 or 64 bit without changes in the code. If one day PB released a 64-bit compiler, trying to adapt existing PB applications would be a nightmare.
-
- Posts: 4313
- Joined: Jan 02, 2017 0:34
- Location: UK
- Contact:
Re: WinFBX window client area width
The phrase "rude awakening" comes to mind. I wonder if anyone over there has thought about that.José wrote:If one day PB released a 64-bit compiler, trying to adapt existing PB applications would be a nightmare.