Otto
Otto wrote:
the problem I have is „modern“ look and different form factors.
Now I started working on responsive dialogs.
I don’t found a way to get such a design with available resource editors.
If you resize a dialog font should change and not only the size of the controls but also the controls should switch to the next row if necessary.
I use a similar concept as Antonio suggested above.
I think we should look into responsive web design an copy those concepts.
I'm working in web projects, and i feel more or less confortable doing responsive in html. Responsive, there is no doubt, is a good thing. But we don't feel forced to become "all the way" responsive in desktop apps, mostly because we write bussines programs, and noone will try to use such software in his/her 3" mobile phone screen.
Probably we can have the best of 2 worlds with simple ideas:
1) Design your form at it's minimun size. That will impose the minimun size of the form/dialog, It won't be resize to less than that size.
2) For each control, define its behavoir on resize:
2a) For top and bottom: Anchored to the top edge of its container, anchored to the bottom, move proportionally.
2b) For left and right: Anchored to the left edge, to the right edge, move proportionally.
3) At the init of the dialog, right after creating it, record the original controls position and size.
4) On dlg/win resize, change control's coordinates acodingly.
With that we get a very good solution. It is not responsive in the HTML sense, but it will behave a lot better in bussines apps.
As an example, in the following DIALOG :
https://prnt.sc/g4shyt1 Controls anchored to the top left corner. their position doesnt change when dialog is resized, neither its size
2 Browse, top left corner anchored to the original position, bottom right corner moves with the forms corner
3 form buttons that move with the bottom right corner as form is resized.
In this example there is no proportional sizing, but is another posibility.
That's that way I see responsiveness applied to desktop forms.
Not limiting to word, a little bit of code.
- Code: Select all Expand view
/*
I've been working some time ago with the control resizing issue. After thinking a little bit about what behavoir would be wanted in every control, it can be resumed in 3 types:
1: No Change: the control's coordinates are hooked or anchored to the top/left window/dialog coordinates, so no change is made when windows is resized (e.g. left toolbar)
2: Proportional: used mostly with graphic controls, every control coordinate is changed proportionally to the dialog size.
3: Anchored: one ore more control's coordinates are hooked to the bottom/right edges, so control's size and/or position are changed acording to the new dialog size. This is the kind of behavoir Rick is looking for.
To achieve this, we need to know:
a) Window/Dialog and controls original sizes,
b) For every control, what behavoir is desired,
and then activate our new resizing strategy on windows/dlg resize, usually using bResize.
So immidiately the dialog is activated, we are going to pass throw every single child control to obtain it's starting position, and store it somewhere in the window.
Then store in every control wich will be it's behavoir at resizing time.
Sth interesting is that you can, in addition to control resize, set lower limits to windows resize so the dialog never gets under this values. Check :aMinMaxInfo var at windows class.
for controls there was used a RSZ attribute, encoding desired control behavoir.
the rest of info (original sizes, etc ) stored at CARGO instvar
*/
#define GW_CHILD 5
#define GW_HWNDNEXT 2
FUNCTION PreResize( oDlg )
LOCAL hWnd:= oDlg:hWnd
LOCAL aSize, aChildren, aSizeWnd
LOCAL hCtrl
IF !Empty( hWnd )
aSizeWnd:= GetClientRect( hWnd )
aSize:= GetWndRect( hWnd )
aChildren:= {}
hCtrl := GetWindow( hWnd, GW_CHILD )
While hCtrl != 0
aSize:= GetWndRect( hCtrl )
aSize[3]-= aSize[1]
aSize[4]-= aSize[2]
ScreenToClient( hWnd, ASize )
AAdd( aChildren, { hCtrl, aSize } )
hCtrl = GetWindow( hCtrl, GW_HWNDNEXT )
END
// We need to store this somewhere, if you feel you have a better place please share it
oDlg:Cargo:= { aSizeWnd, aChildren }
// This could be another option... We can use this function to setup the min/Max info...
oDlg:aMinMaxInfo = { GetSysMetrics(0), GetSysMetrics(1),; // xMaxSize, yMaxSize
0, 0 /*GetSysMetrics(0), GetSysMetrics(1) */ ,; // xMaxPosition, yMaxPosition
oDlg:nWidth, oDlg:nHeight,; // xMinTrackSize, yMinTrackSize
GetSysMetrics(0), GetSysMetrics(1), ; // xMaxTrackSize, yMaxTrackSize
aSizeWnd, aChildren }
ENDIF
RETURN NIL
FUNCTION DlgResizeCtrl( oDlg, nWidth, nHeight, nSizeType )
LOCAL hWnd, oCtrl, nPos
LOCAL aSize, aChildren, aSizeWnd, aCargo
LOCAL hCtrl, aCtrl
LOCAL nTop, nLeft, nOrigWidth, nOrigHeight, nBottom, nRight
LOCAL nStyle, nKV, nKH // keep, Proporcional, bound to bottom,
IF ValType(oDlg:Cargo) == 'A'
nTop:= oDlg:Cargo[1][1]
nLeft:= oDlg:Cargo[1][2]
nOrigHeight := oDlg:Cargo[1][3] - nTop
nOrigWidth := oDlg:Cargo[1][4] - nLeft
aSizeWnd:= GetClientRect( oDlg:hWnd )
nHeight:= aSizeWnd[3]
nWidth := aSizeWnd[4]
nKH:= nWidth / nOrigWidth
nKV:= nHeight / nOrigHeight
nDH:= nWidth - nOrigWidth
nDV:= nHeight - nOrigHeight
aChildren:= oDlg:Cargo[2]
FOR EACH aCtrl IN aChildren
IF ( nPos:= GetProp( aCtrl[1], "RSZ" ) ) != 0
nStyle:= nPos % 256
nPos:= Int( nPos / 256 )
nTop := (nPos % 16) >= 8
nLeft := (nPos % 8) >= 4
nBottom := (nPos % 4) >= 2
nRight := (nPos % 2) == 1
Do Case
Case nStyle == 0 // keep, do nothing
// SetWindowPos( aCtrl[1], 0, aCtrl[2][1], aCtrl[2][2], aCtrl[2][4], aCtrl[2][3], 4 )
Case nStyle == 1 // Proportional
SetWindowPos( aCtrl[1], 0, Int( aCtrl[2][1] * nKV ), Int( aCtrl[2][2] * nKH ), Int( aCtrl[2][4] * nKH ), Int( aCtrl[2][3] * nKV ), 4 )
Case nStyle == 2 // Anchors
SetWindowPos( aCtrl[1], 0, ;
If( nTop, aCtrl[2][1]+nDV, aCtrl[2][1] ), ;
If( nLeft, aCtrl[2][2]+nDH, aCtrl[2][2] ), ;
If( nRight, aCtrl[2][4]+nDH, aCtrl[2][4] ), ;
If( nBottom, aCtrl[2][3]+nDV, aCtrl[2][3] ), ;
4 )
EndCase
ENDIF
EndFor
oDlg:Refresh()
ENDIF
RETURN NIL
To be used in code sth like:
- Code: Select all Expand view
oDlg:bResized := {|nSizeType, nWidth, nHeight| DlgResizeCtrl( oDlg, nWidth, nHeight, nSizeType ) }
ACTIVATE DIALOG oDlg CENTERED ;
ON INIT ( PreResize( oDlg ), SetProp( oBrowse:hWnd, 'RSZ', 0x302 ), SetProp( oBtn1:hWnd, 'RSZ', 0xf02 ), SetProp( oBtn2:hWnd, 'RSZ', 0xf02 ), SetProp( oBtn3:hWnd, 'RSZ', 0xf02 ) )
It may look a little bit cryptic but it could be a good starting point