Jose,
Excellent work on your FreeBasic include files.
I am a bit out of practice but the one item I would like to see and did not find in the help file is a control layout operation. I've seen some of your PB code where you do it manually in the WM_SIZE event but this is way too tedious for any window with more than a coulple of controls.
Maybe Paul could adapt or add to cMaker to provide this capacity?
James
Dominic uses the Jeffrey Richter's layout algorithm, but I have been unable to find Richter's code.
I have found UILayout.h in a Chinese site, with comments in Chinese. I will try to adapt it to FreeBASIC.
Jose,
Attached is an exe that uses the original "c" code compiled with the TDM-GCC-64 compiler. It has the same problem all approaches I have tried except one. I tried Patrice's code and it has the same issue. IUP is the only one I've found where frame text does not flicker
Most mail hosts whine on included exe's so I posted here.
Watch your email from my jcfuller22 gmail account for more info
James
Well, I have done the translation from the code found in the Chinese site.
This is the first test, with a button, that works fine. We may need to do more tests.
You will find the class in the attached .rar file.
' ########################################################################################
' Microsoft Windows
' File: CW_LAYOUT_Button.fbtpl
' Contents: CWindow layout button example
' Compiler: FreeBasic 32 & 64 bit
' Copyright (c) 2016 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.
' ########################################################################################
#INCLUDE ONCE "windows.bi"
#INCLUDE ONCE "Afx/CWindow.inc"
#INCLUDE ONCE "Afx/CUILayout.inc"
USING Afx.CWindowClass
USING Afx.CUILayoutClass
DIM SHARED g_UILayout AS CUILayout PTR
DECLARE FUNCTION WinMain (BYVAL hInstance AS HINSTANCE, _
BYVAL hPrevInstance AS HINSTANCE, _
BYVAL szCmdLine AS ZSTRING PTR, _
BYVAL nCmdShow AS LONG) AS LONG
END WinMain(GetModuleHandleW(NULL), NULL, COMMAND(), SW_NORMAL)
' ========================================================================================
' Window procedure
' ========================================================================================
FUNCTION WndProc (BYVAL hWnd AS HWND, BYVAL uMsg AS UINT, BYVAL wParam AS WPARAM, BYVAL lParam AS LPARAM) AS LRESULT
SELECT CASE uMsg
CASE WM_CREATE
EXIT FUNCTION
CASE WM_COMMAND
SELECT CASE LOWORD(wParam)
CASE IDCANCEL
' // If ESC key pressed, close the application sending an WM_CLOSE message
IF HIWORD(wParam) = BN_CLICKED THEN
SendMessageW hwnd, WM_CLOSE, 0, 0
EXIT FUNCTION
END IF
END SELECT
CASE WM_SIZE
g_UILayout->AdjustControls(LOWORD(lParam), HIWORD(lParam))
EXIT FUNCTION
CASE WM_DESTROY
PostQuitMessage(0)
EXIT FUNCTION
END SELECT
FUNCTION = DefWindowProcW(hWnd, uMsg, wParam, lParam)
END FUNCTION
' ========================================================================================
' ========================================================================================
' Main
' ========================================================================================
FUNCTION WinMain (BYVAL hInstance AS HINSTANCE, _
BYVAL hPrevInstance AS HINSTANCE, _
BYVAL szCmdLine AS ZSTRING PTR, _
BYVAL nCmdShow AS LONG) AS LONG
' // Set process DPI aware
AfxSetProcessDPIAware
DIM pWindow AS CWindow
pWindow.Create(NULL, "CWindow with a button", @WndProc)
pWindow.SetClientSize(500, 320)
pWindow.Center
' // Add a button
pWindow.AddControl("Button", pWindow.hWindow, IDCANCEL, "&Close", 350, 250, 75, 23)
g_UILayout = NEW CUILayout(pWindow.hWindow, 100, 100)
g_UILayout->AnchorControl(AP_BOTTOMRIGHT, AP_BOTTOMRIGHT, IDCANCEL, FALSE)
FUNCTION = pWindow.DoEvents(nCmdShow)
IF g_UILayout THEN Delete g_UILayout
END FUNCTION
' ========================================================================================
Jose,
It's a no-go here compiled as 64bit on Win10
Compiles fine but nothing shows when run.
James
I dont have Windows 10 to test.
BTW the HandleMinMax procedure was missing, although I don't know what it is his purpose, because it is not used in the class.
I tried the exe compiled on Win10 on a Win7 box and it failed there also.
I'm not set up to compile on Win7.
If I comment out the call in WM_SIZE the window shows.
James
Attached is the compiled test. It works in my computer with Windows 7.
Runs fine on Win7 does not on Win10.
James
There is nothing I can't do. As I said, I don't have Windows 10. You have the source code, try to find where it fails.
Quote from: Jose Roca on May 28, 2016, 05:19:34 PM
There is nothing I can't do. As I said, I don't have Windows 10. You have the source code, try to find where it fails.
I have Windows 10. I will try to debug the problem now. I will report back soon.
Seems like the problem is with WM_SIZE. That message is sent during your window creation but of course the pointer has not been initialized until a short time later. When the second WM_SIZE arrives then the pointer is okay. It seems that the GPF occurs on the first null pointer during the first WM_SIZE. Just need to test for a null pointer I think.
CASE WM_SIZE
If g_UILayout Then
g_UILayout->AdjustControls(Loword(lParam), Hiword(lParam))
End If
Exit Function
For some unknown reason, it doesn't GPF in my computer, when it should. Now the question is if it works in Windows 10 after adding the check or not.
It works for me on Windows 10 when I add the check. It GPF's when the check is omitted. Let's see if James experiences the same as I do.
Then I can continue experimenting, because it is easy to use. It would we great if we can offer a resize engine. The code that James has sent to me, originally written for Windows 95, looks complicated, but to translate the one that I have found in the Chinese site I only have need half an hour, much less than googling to find it.
Works fine for me with the check.
The code does not look anything like the original Richter code.
The Richter code lets you use other controls as references.
Paul I'll send it along to you also.
James
Quote from: Jose Roca on May 28, 2016, 11:57:26 PM
It has the same problem all approaches I have tried except one. I tried Patrice's code and it has the same issue.
Windows group boxes flicker when resized.
Quote
IUP is the only one I've found where frame text does not flicker
Must be using a custom control.
Here is a nice one: http://www.codeproject.com/Articles/12421/The-Grouper-A-Custom-Groupbox-Control
Another one: http://www.codeproject.com/Articles/29016/XGroupBox-an-MFC-groupbox-control-to-display-text
Well, works fine for what I need. I have removed the width and height parameters of the constructor, that were not being used for nothing useful. I don't need the complexity of adding support for dialogs and dialog units, other metrics, etc. I don't like overdoing.
I also have modified this code
DIM hdc AS HDC = GetDC(m_hwndParent)
DIM hbrColor AS HBRUSH = CreateSolidBrush(GetSysColor(COLOR_3DFACE))
FillRgn(hdc, hrgnPaint, hbrColor)
DeleteObject(hbrColor)
ReleaseDC(m_hwndParent, hdc)
DeleteObject(hrgnPaint)
that was using a COLOR_3DFACE brush and, of course, was not adequate if the main window is using a different background color.
Replacement:
DIM hdc AS HDC = GetDC(m_hwndParent)
FillRgn(hdc, hrgnPaint, CAST(HBRUSH, GetClassLongPtr(GetParent(m_hwndParent), GCLP_HBRBACKGROUND)))
ReleaseDC(m_hwndParent, hdc)
DeleteObject(hrgnPaint)
InvalidateRect(m_hwndParent, NULL, TRUE)
UpdateWindow(m_hwndParent)
The repainting of the parent window is needed because there was a repainting problem if the user maximizes and then restores the window.
Jose,
Would you please upload you latest CUILayout.inc that you used with TestLayout3?
Thank you,
James
Sorry, I always forget something.
Jose,
Would you put together a more complex example or instructions or something because my old brain just doesn't get it :)
James
My brain is old too. I don't have documentation, so I still have to figure how it works.
This is a nightmare. If I don't repaint the background, there are artifacts and other repainting problems; if I do, controls with the WS_EX_TRANSPARENT extended style don't are visible. We will have to look for another way.
You might have to scan the controls array and move the WS_EX_TRANSPARENT last maybe after the repaint?
I'm not comfortable using code that I don't fully understand how it works.
What about Patrice's code? Can we use it?
(https://www.planetsquires.com/code.jpg)
I may try another approach using Richter code.
I think this is the correct transltion to access from Fb.
#define IDD_LAYOUT 101
#define IDI_LAYOUT 102
#define IDC_B1 1001
#define IDC_B2 1002
#define IDC_B3 1003
#define IDC_E1 2001
#define IDC_E2 2002
#define IDC_G1 3001
#define IDC_STATIC -1
#define lPARENT 65536
'------------------------------------------------------------------------------
enum lPART
lpLEFT = 0
lpTOP
lpRIGHT
lpBOTTOM
lpWIDTH
lpHEIGHT
lpGROUP
End Enum
'------------------------------------------------------------------------------
enum lACTION
lSTRETCH = 0
lMOVE
lVCENTER
lHCENTER
lEND
End Enum
Type lActionInfo
union
Dim nPart As long
Dim nMetric As long
Dim nSide As long
end union
union
Dim idc As long
Dim idcfirst As long
end union
union
Dim nPercent As long
Dim idcLast As long
end union
End Type
'------------------------------------------------------------------------------
Type RULE
Dim Action As lACTION
Dim ActOn As lACTIONINFO
Dim RelTo As lACTIONINFO
Dim nOffset As long
Dim fState As UINT
Dim nPixelOffset As long
End Type
'------------------------------------------------------------------------------
#define lLEFT(idc) lpLEFT, idc, 0
#define lTOP(idc) lpTOP, idc, 0
#define lRIGHT(idc) lpRIGHT, idc, 0
#define lBOTTOM(idc) lpBOTTOM, idc, 0
#define lWIDTH(idc) lpWIDTH, idc, 100
#define lHEIGHT(idc) lpHEIGHT, idc, 100
#define lWIDTHOF(idc, percent) lpWIDTH, idc, percent
#define lHEIGHTOF(idc, percent) lpHEIGHT, idc, percent
#define lCHILD(idc) lpGROUP, idc, idc
#define lGROUP(idcFirst, idcLast) lpGROUP, idcFirst, idcLast
Dim As RULE _rule(14)= _
{(lMOVE, lRIGHT(IDC_B1), lRIGHT(lPARENT), -8), _
(lSTRETCH, lWIDTH(IDC_B1), lWIDTHOF(lPARENT, 15), +0), _
(lMOVE, lTOP(IDC_B2), lBOTTOM(IDC_B1), +8), _
(lMOVE, lLEFT(IDC_B2), lLEFT(IDC_B1), +0), _
(lSTRETCH, lWIDTH(IDC_B2), lWIDTH(IDC_B1), +0), _
(lVCENTER, lCHILD(IDC_B3), lCHILD(IDC_G1), +2), _
(lHCENTER, lCHILD(IDC_B3), lCHILD(IDC_G1), +0), _
(lVCENTER, lGROUP(IDC_B1, IDC_B2), lCHILD(IDC_E2), +0), _
(lSTRETCH, lWIDTH(IDC_E1), lWIDTHOF(IDC_E2, 50), +0), _
(lSTRETCH, lBOTTOM(IDC_E2), lBOTTOM(lPARENT), -8), _
(lSTRETCH, lRIGHT(IDC_E2), lLEFT(IDC_B1), -8), _
(lMOVE, lLEFT(IDC_G1), lRIGHT(IDC_E1), +8), _
(lSTRETCH, lRIGHT(IDC_G1), lRIGHT(lPARENT), -8), _
(lEND)}
Now if I can compile the actual "DOIT" code to a static library so it can be linked ?
James
I have adapted Patrice's code into a class, CLayout, and seems to work fine. However, in the call to MoveWindow, I have needed to set the redraw flag to true.
' ########################################################################################
' Microsoft Windows
' File: CW_Layout.fbtpl - Template
' Contents: Demonstrates the use of the Layout manager
' Compiler: FreeBasic 32 & 64 bit
' Copyright (c) 2016 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.
' ########################################################################################
#INCLUDE ONCE "Afx/CWindow.inc"
#INCLUDE ONCE "Afx/CLayout.inc"
USING Afx.CWindowClass
USING Afx.CLayoutClass
CONST IDC_EDIT1 = 1001
CONST IDC_EDIT2 = 1002
CONST IDC_GROUPBOX = 1003
CONST IDC_COMBOBOX = 1004
DECLARE FUNCTION WinMain (BYVAL hInstance AS HINSTANCE, _
BYVAL hPrevInstance AS HINSTANCE, _
BYVAL szCmdLine AS ZSTRING PTR, _
BYVAL nCmdShow AS LONG) AS LONG
END WinMain(GetModuleHandleW(NULL), NULL, COMMAND(), SW_NORMAL)
' ========================================================================================
' Window procedure
' ========================================================================================
FUNCTION WndProc (BYVAL hWnd AS HWND, BYVAL uMsg AS UINT, BYVAL wParam AS WPARAM, BYVAL lParam AS LPARAM) AS LRESULT
SELECT CASE uMsg
CASE WM_COMMAND
SELECT CASE LOWORD(wParam)
' // If ESC key pressed, close the application sending an WM_CLOSE message
CASE IDCANCEL
IF HIWORD(wParam) = BN_CLICKED THEN
SendMessageW hwnd, WM_CLOSE, 0, 0
EXIT FUNCTION
END IF
END SELECT
CASE WM_GETMINMAXINFO
' Set the pointer to the address of the MINMAXINFO structure
DIM ptmmi AS MINMAXINFO PTR = CAST(MINMAXINFO PTR, lParam)
' Set the minimum and maximum sizes that can be produced by dragging the borders of the window
DIM pWindow AS CWindow PTR = CAST(CWindow PTR, GetWindowLongPtr(hwnd, 0))
IF pWindow THEN
ptmmi->ptMinTrackSize.x = 300 * pWindow->rxRatio
ptmmi->ptMinTrackSize.y = 180 * pWindow->ryRatio
END IF
EXIT FUNCTION
CASE WM_SIZE
' // Adjusts the controls
DIM pLayout AS CLayout PTR = CAST(CLayout PTR, GetPropW(hwnd, "CLAYOUTPTR"))
IF pLayout THEN pLayout->AdjustControls
EXIT FUNCTION
CASE WM_DESTROY
RemovePropW hwnd, "CLAYOUTPTR"
PostQuitMessage(0)
EXIT FUNCTION
END SELECT
FUNCTION = DefWindowProcW(hWnd, uMsg, wParam, lParam)
END FUNCTION
' ========================================================================================
' ========================================================================================
' Main
' ========================================================================================
FUNCTION WinMain (BYVAL hInstance AS HINSTANCE, _
BYVAL hPrevInstance AS HINSTANCE, _
BYVAL szCmdLine AS ZSTRING PTR, _
BYVAL nCmdShow AS LONG) AS LONG
' // Set process DPI aware
AfxSetProcessDPIAware
DIM pWindow AS CWindow
pWindow.Create(NULL, "Layout manager", @WndProc)
' pWindow.Brush = GetStockObject(WHITE_BRUSH)
pWindow.SetClientSize 455, 180
pWindow.Center
' // Add an Edit control
DIM hEdit AS HWND = pWindow.AddControl("Edit", pWindow.hWindow, IDC_EDIT1, "", 20, 15, 305, 23)
' // Add a multiline Edit control
pWindow.AddControl("EditMultiline", pWindow.hWindow, IDC_EDIT2, "", 20, 45, 305, 80)
' // Alternate way
' pWindow.AddControl("Edit", pWindow.hWindow, IDC_EDIT2, "", 20, 50, 300, 80, _
' WS_VISIBLE OR WS_TABSTOP OR ES_LEFT OR ES_AUTOHSCROLL OR ES_MULTILINE OR ES_NOHIDESEL OR ES_WANTRETURN)
' // Set the focus in the first edit control
SetFocus hEdit
' // Add more controls
pWindow.AddControl("GroupBox", pWindow.hWindow, IDC_GROUPBOX, "GroupBox", 340, 8, 100, 155)
pWindow.AddControl("Button", pWindow.hWindow, IDCANCEL, "&Close", 250, 140, 75, 23)
' // Add a combobox control
DIM hCombobox AS HWND = pWindow.AddControl("ComboBox", pWindow.hWindow, IDC_COMBOBOX, "", 350, 30, 80, 100)
' // Fill the control with some data
DIM i AS LONG = 1, wszText AS WSTRING * 260
FOR i = 1 TO 9
wszText = "Item " & RIGHT("00" & STR(i), 2)
SendMessageW(hComboBox, CB_ADDSTRING, 0, CAST(LPARAM, @wszText))
NEXT
' // Anchor the controls
DIM pLayout AS CLayout = pWindow.hWindow
SetPropW pWindow.hWindow, "CLAYOUTPTR", @pLayout
pLayout.AnchorControl(GetDlgItem(pWindow.hWindow, IDC_EDIT1), AFX_ANCHOR_WIDTH)
pLayout.AnchorControl(GetDlgItem(pWindow.hWindow, IDC_EDIT2), AFX_ANCHOR_HEIGHT_WIDTH)
pLayout.AnchorControl(GetDlgItem(pWindow.hWindow, IDCANCEL), AFX_ANCHOR_BOTTOM_RIGHT)
pLayout.AnchorControl(GetDlgItem(pWindow.hWindow, IDC_GROUPBOX), AFX_ANCHOR_HEIGHT_RIGHT)
pLayout.AnchorControl(GetDlgItem(pWindow.hWindow, IDC_COMBOBOX), AFX_ANCHOR_RIGHT)
' // Process Windows messages
FUNCTION = pWindow.DoEvents(nCmdShow)
END FUNCTION
' ========================================================================================
Jose
Yes, you have my permission.
I am using it in both WinLIFT and GDImage (even to anchor sprites), it has been modeled on the anchor properties provided by WinDev.
I sent a copy of that code to Paul a few years ago at the time of FF3, but he chooses another solution.
This code served me well for years and to avoid flickering you should use a double buffer, and refresh the whole window only once, like what DWM does.
Quote from: Patrice Terrier on May 31, 2016, 04:24:56 AM
Jose
Yes, you have my permission.
I am using it in both WinLIFT and GDImage (even to anchor sprites), it has been modeled on the anchor properties provided by WinDev.
I sent a copy of that code to Paul a few years ago at the time of FF3, but he chooses another solution.
This code served me well for years and to avoid flickering you should use a double buffer, and refresh the whole window only once, like what DWM does.
Patrice,
Does the ability with this method work for an application like your SDK address book:
http://www.jose.it-berater.org/smfforum/index.php?topic=5018.0
I could not figure out how to approach the Last - First items!
James