-
Notifications
You must be signed in to change notification settings - Fork 1
/
resizable.p
214 lines (163 loc) · 7.29 KB
/
resizable.p
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
/*------------------------------------------------------------------------
Name : Resizable.p
Desc : Library to make any ABL window resizable
Notes:
1. make sure 'resize' is checked in your window properties
2. run this library persistent from the main block of your program
3. have fun!
More info: https://github.com/patrickTingen/ResizABLe
Parameters:
phWindow : handle to your window
History:
08-03-2018 PT Created
11-03-2018 PT Resize rules for LABELS and TEXT Widgets #1
----------------------------------------------------------------------*/
DEFINE INPUT PARAMETER phWindow AS HANDLE NO-UNDO.
DEFINE TEMP-TABLE ttWidget NO-UNDO
FIELD ttHandle AS HANDLE
FIELD ttX AS DECIMAL /* calculated x-position in pixels */
FIELD ttY AS DECIMAL /* calculated y-position in pixels */
FIELD ttWidth AS DECIMAL /* calculated width in pixels */
FIELD ttHeight AS DECIMAL /* calculated height in pixels */
INDEX iPrim IS PRIMARY UNIQUE ttHandle.
DEFINE VARIABLE giMinFactorHor AS INTEGER NO-UNDO INITIAL 1.
DEFINE VARIABLE giMinFactorVer AS INTEGER NO-UNDO INITIAL 1.
DEFINE VARIABLE giOrgHeight AS INTEGER NO-UNDO.
DEFINE VARIABLE giOrgWidth AS INTEGER NO-UNDO.
DEFINE VARIABLE gdPrevFactorHor AS DECIMAL NO-UNDO.
DEFINE VARIABLE gdPrevFactorVer AS DECIMAL NO-UNDO.
/* Init */
ASSIGN
giOrgHeight = phWindow:HEIGHT-PIXELS
giOrgWidth = phWindow:WIDTH-PIXELS
phWindow:MAX-WIDTH-PIXELS = SESSION:WIDTH-PIXELS
phWindow:MAX-HEIGHT-PIXELS = SESSION:HEIGHT-PIXELS.
/* Trap resize actions */
ON 'WINDOW-RESIZED' OF phWindow ANYWHERE PERSISTENT
RUN WindowResized IN THIS-PROCEDURE
( INPUT phWindow ).
PROCEDURE maximizeWindow:
/* Resize a window to its maximum dimensions
*/
DEFINE INPUT PARAMETER phWindow AS HANDLE NO-UNDO.
phWindow:MOVE-TO-TOP().
phWindow:WINDOW-STATE = 1. /* Maximized */
RUN WindowResized(phWindow).
END PROCEDURE. /* maximizeWindow */
PROCEDURE setMinimalResizeFactor:
/* Set the minimal resizing factor for the window
** For ADM windows this seems to be 1, for plain ABL windows 0
*/
DEFINE INPUT PARAMETER piMinHor AS DECIMAL NO-UNDO.
DEFINE INPUT PARAMETER piMinVer AS DECIMAL NO-UNDO.
ASSIGN
giMinFactorHor = piMinHor
giMinFactorVer = piMinVer.
END PROCEDURE. /* setMinimalResizeFactor */
PROCEDURE windowResized:
/* Resize the frame and all the widget it contains to the new window size
*/
DEFINE INPUT PARAMETER phWindow AS HANDLE NO-UNDO.
DEFINE VARIABLE dFactorHor AS DECIMAL NO-UNDO.
DEFINE VARIABLE dFactorVer AS DECIMAL NO-UNDO.
/* Calculate resizing factor relative to starting size */
dFactorHor = MAXIMUM(giMinFactorHor, phWindow:WIDTH-PIXELS / giOrgWidth).
dFactorVer = MAXIMUM(giMinFactorVer, phWindow:HEIGHT-PIXELS / giOrgHeight).
RUN lockWindow(phWindow, YES).
phWindow:WIDTH-PIXELS = giOrgWidth * dFactorHor.
phWindow:HEIGHT-PIXELS = giOrgHeight * dFactorVer.
RUN resizeFrame(phWindow, phWindow:FIRST-CHILD, dFactorHor, dFactorVer).
RUN lockWindow(phWindow, NO).
gdPrevFactorHor = dFactorHor.
gdPrevFactorVer = dFactorVer.
END PROCEDURE. /* windowResized */
PROCEDURE resizeFrame:
/* Resize contents of a frame
*/
DEFINE INPUT PARAMETER phParent AS HANDLE NO-UNDO.
DEFINE INPUT PARAMETER phFrame AS HANDLE NO-UNDO.
DEFINE INPUT PARAMETER pdFactorHor AS DECIMAL NO-UNDO.
DEFINE INPUT PARAMETER pdFactorVer AS DECIMAL NO-UNDO.
DEFINE VARIABLE hWidget AS HANDLE NO-UNDO. /* general purpose widget handle */
DEFINE BUFFER bWidget FOR ttWidget.
/* prevent errors when resizing to too small sizes */
IF pdFactorHor < 0.15 OR pdFactorVer < 0.15 THEN RETURN.
ASSIGN phFrame:SCROLLABLE = TRUE NO-ERROR.
/* If the window grows, resize the frame as well */
IF pdFactorHor > gdPrevFactorHor THEN
ASSIGN phFrame:WIDTH-PIXELS = phParent:WIDTH-PIXELS
phFrame:VIRTUAL-WIDTH-PIXELS = phParent:WIDTH-PIXELS NO-ERROR.
IF pdFactorVer > gdPrevFactorVer THEN
ASSIGN phFrame:HEIGHT-PIXELS = phParent:HEIGHT-PIXELS
phFrame:VIRTUAL-HEIGHT-PIXELS = phParent:HEIGHT-PIXELS NO-ERROR.
/* Walk the widgets of the frame */
ASSIGN hWidget = phFrame:FIRST-CHILD:FIRST-CHILD. /* first field-level widget */
DO WHILE VALID-HANDLE(hWidget):
FIND bWidget WHERE bWidget.ttHandle = hWidget NO-ERROR.
IF NOT AVAILABLE bWidget THEN
DO:
CREATE bWidget.
ASSIGN bWidget.ttHandle = hWidget
bWidget.ttX = hWidget:X
bWidget.ttY = hWidget:Y
bWidget.ttWidth = hWidget:WIDTH-PIXELS
bWidget.ttHeight = hWidget:HEIGHT-PIXELS.
END.
ASSIGN hWidget:X = TRUNCATE(bWidget.ttX * pdFactorHor,0)
hWidget:Y = TRUNCATE(bWidget.ttY * pdFactorVer,0).
/* Resize embedded frame */
IF hWidget:TYPE = 'frame' THEN
RUN resizeFrame(phFrame, hWidget, pdFactorHor, pdFactorVer).
IF LOOKUP(hWidget:TYPE,"text,literal") = 0 THEN
ASSIGN hWidget:WIDTH-PIXELS = TRUNCATE(bWidget.ttWidth * pdFactorHor,0).
/* Reposition labels */
IF CAN-QUERY(hWidget,'SIDE-LABEL-HANDLE')
AND VALID-HANDLE(hWidget:SIDE-LABEL-HANDLE) THEN
hWidget:SIDE-LABEL-HANDLE:X = hWidget:X - FONT-TABLE:GET-TEXT-WIDTH-PIXELS(hWidget:SIDE-LABEL-HANDLE:SCREEN-VALUE,hWidget:FONT) - 6.
IF LOOKUP(hWidget:TYPE,"fill-in,text,literal,button") = 0 THEN
hWidget:HEIGHT-PIXELS = TRUNCATE(bWidget.ttHeight * pdFactorVer,0) NO-ERROR.
ASSIGN hWidget = hWidget:NEXT-SIBLING.
END. /* WHILE VALID-HANDLE(hWidget) */
/* If the window shrinked, resize the frame as well */
IF pdFactorHor < gdPrevFactorHor THEN
ASSIGN phFrame:WIDTH-PIXELS = phParent:WIDTH-PIXELS
phFrame:VIRTUAL-WIDTH-PIXELS = phParent:WIDTH-PIXELS NO-ERROR.
IF pdFactorVer < gdPrevFactorVer THEN
ASSIGN phFrame:HEIGHT-PIXELS = phParent:HEIGHT-PIXELS
phFrame:VIRTUAL-HEIGHT-PIXELS = phParent:HEIGHT-PIXELS NO-ERROR.
phFrame:SCROLLABLE = NO.
END PROCEDURE. /* resizeFrame */
PROCEDURE lockWindow:
/* Lock / unlock updates that Windows does to windows.
*/
DEFINE INPUT PARAMETER phWindow AS HANDLE NO-UNDO.
DEFINE INPUT PARAMETER plLock AS LOGICAL NO-UNDO.
DEFINE VARIABLE iRet AS INTEGER NO-UNDO.
/* Locking / unlocking windows */
&GLOBAL-DEFINE WM_SETREDRAW 11
&GLOBAL-DEFINE RDW_ALLCHILDREN 128
&GLOBAL-DEFINE RDW_ERASE 4
&GLOBAL-DEFINE RDW_INVALIDATE 1
IF NOT VALID-HANDLE(phWindow) THEN RETURN.
IF plLock THEN
RUN SendMessageA(phWindow:HWND, {&WM_SETREDRAW}, 0, 0, OUTPUT iRet).
ELSE
DO:
RUN SendMessageA(phWindow:HWND, {&WM_SETREDRAW}, 1, 0, OUTPUT iRet).
RUN RedrawWindow(phWindow:HWND, 0, 0, {&RDW_ALLCHILDREN} + {&RDW_ERASE} + {&RDW_INVALIDATE}, OUTPUT iRet).
END.
END PROCEDURE. /* lockWindow */
PROCEDURE SendMessageA EXTERNAL "user32.dll":
DEFINE INPUT PARAMETER hwnd AS long NO-UNDO.
DEFINE INPUT PARAMETER wmsg AS long NO-UNDO.
DEFINE INPUT PARAMETER wparam AS long NO-UNDO.
DEFINE INPUT PARAMETER lparam AS long NO-UNDO.
DEFINE RETURN PARAMETER rc AS long NO-UNDO.
END PROCEDURE.
PROCEDURE RedrawWindow EXTERNAL "user32.dll":
DEFINE INPUT PARAMETER v-hwnd AS LONG NO-UNDO.
DEFINE INPUT PARAMETER v-rect AS LONG NO-UNDO.
DEFINE INPUT PARAMETER v-rgn AS LONG NO-UNDO.
DEFINE INPUT PARAMETER v-flags AS LONG NO-UNDO.
DEFINE RETURN PARAMETER v-ret AS LONG NO-UNDO.
END PROCEDURE.