PlanetSquires Forums

Support Forums => General Board => Topic started by: James Fuller on May 28, 2016, 11:15:47 AM

Title: requested item
Post by: James Fuller on May 28, 2016, 11:15:47 AM
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
Title: Re: requested item
Post by: José Roca on May 28, 2016, 11:31:16 AM
Dominic uses the Jeffrey Richter's layout algorithm, but I have been unable to find Richter's code.
Title: Re: requested item
Post by: José Roca on May 28, 2016, 01:47:00 PM
I have found UILayout.h in a Chinese site, with comments in Chinese. I will try to adapt it to FreeBASIC.
Title: Re: requested item
Post by: James Fuller on May 28, 2016, 01:52:34 PM
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
Title: Re: requested item
Post by: José Roca on May 28, 2016, 03:48:25 PM
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
' ========================================================================================

Title: Re: requested item
Post by: James Fuller on May 28, 2016, 04:18:55 PM
Jose,
It's a no-go here compiled as 64bit on Win10
Compiles fine but nothing shows when run.

James
Title: Re: requested item
Post by: José Roca on May 28, 2016, 04:22:45 PM
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.
Title: Re: requested item
Post by: James Fuller on May 28, 2016, 04:40:26 PM
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
Title: Re: requested item
Post by: José Roca on May 28, 2016, 04:42:52 PM
Attached is the compiled test. It works in my computer with Windows 7.
Title: Re: requested item
Post by: James Fuller on May 28, 2016, 05:06:05 PM
Runs fine on Win7 does not on Win10.

James
Title: Re: requested item
Post by: José 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.
Title: Re: requested item
Post by: Paul Squires on May 28, 2016, 06:12:52 PM
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.
Title: Re: requested item
Post by: Paul Squires on May 28, 2016, 06:32:41 PM
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

Title: Re: requested item
Post by: José Roca on May 28, 2016, 06:56:48 PM
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.
Title: Re: requested item
Post by: Paul Squires on May 28, 2016, 07:01:23 PM
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.
Title: Re: requested item
Post by: José Roca on May 28, 2016, 07:10:46 PM
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.
Title: Re: requested item
Post by: James Fuller on May 28, 2016, 08:20:40 PM
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
Title: Re: requested item
Post by: José Roca on May 28, 2016, 11:57:55 PM
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
Title: Re: requested item
Post by: José Roca on May 29, 2016, 12:12:56 AM
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.
Title: Re: requested item
Post by: James Fuller on May 29, 2016, 07:41:44 AM
Jose,
  Would you please upload you latest CUILayout.inc that you used with TestLayout3?
Thank you,
James

Title: Re: requested item
Post by: José Roca on May 29, 2016, 12:07:30 PM
Sorry, I always forget something.
Title: Re: requested item
Post by: James Fuller on May 30, 2016, 03:24:09 PM
Jose,
  Would you put together a more complex example or instructions or something because my old brain just doesn't get it :)

James
Title: Re: requested item
Post by: José Roca on May 30, 2016, 03:35:31 PM
My brain is old too. I don't have documentation, so I still have to figure how it works.
Title: Re: requested item
Post by: José Roca on May 30, 2016, 05:57:38 PM
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.
Title: Re: requested item
Post by: Paul Squires on May 30, 2016, 06:19:22 PM
You might have to scan the controls array and move the WS_EX_TRANSPARENT last maybe after the repaint?
Title: Re: requested item
Post by: José Roca on May 30, 2016, 06:32:42 PM
I'm not comfortable using code that I don't fully understand how it works.

What about Patrice's code? Can we use it?
Title: Re: requested item
Post by: Paul Squires on May 30, 2016, 07:42:12 PM
(https://www.planetsquires.com/code.jpg)
Title: Re: requested item
Post by: James Fuller on May 30, 2016, 08:42:20 PM
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
Title: Re: requested item
Post by: José Roca on May 30, 2016, 10:10:36 PM
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
' ========================================================================================

Title: Re: requested item
Post by: 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.
Title: Re: requested item
Post by: James Fuller on May 31, 2016, 08:21:36 AM
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