|
MS Windows TAB-control emuliacija PROGRESS 4GL kalba
Paskirtis
Tai alternatyvi MS Windows Tab-control realizacija,
parašyta gryna 4GL kalba, nenaudojant Active-X ar COM objektų.
Aprašymas
Šis alternatyvus sprendimas panaudoja persidengiančius
iš anksto apibrežtus statinius freimus ir statinius vidžetus jų viduje,
t.y. preišingai negu gerai žinomas sprendimas, kuris naudoja standartinį
MS Windows Tab-control objektą.
MS Tab control varianto pagrindinis trūkumas yra tas, kad reikia realizuoti specialų
įvykių apdorojimą (message handling) pagrindiniame PROGRESS pranešimų apdorojimo cikle (WAIT-FOR),
kuris numato kreipimąsi į eilę papildomų Windows API funkcijų.
Kartu tai sudaro problemų, kūriant didesnes aplikacijas, nes reikia pastoviai turėti
omeny šį nestandartinį įvykių apdorojimą, kas įneša tam tikrą nelankstumo elementą
į programavimą (prisimenate, - one world - one WAIT-FOR?).
Mūsų alternatyvus sprendimas yra tiesiog pilna loginė tab-control elgesio imitacija,
kuri panaudoja tik standartinius PROGRESS vidžetus (mygtukus, stačiakampius ir freimus).
Be to ji ir atrodo labai panašiai į tikrą MS Windows Tab control'ą.
Žemiau pateikiamas programos skeletas, kuriame galima pamatyti visą tab-control
sudarymo ir valdymo techniką, o jo implementacija galite pamatyti
create_tab.i faile.
Iš pradžių Jūs sukūriate statinius freimus ir vidžetus juose. Aišku galima kurti
ir dinaminius vidžetus, bet jie turi būti aktyvuojami prieš iškviečiant "tab"ų sudarymo
(gf_create_tab) funkciją (žr. žemiau).
Visas visų vidžetų tūrinys yra prieinamas tiesiogiai ir jį galimą valdyti iš bet kurio programos taško
bet kuriuo momentu.
Jūs taip pat galite valdyti visus vidžetus (pvz. enable ir disable) bet kuriuo metu,
dar daugiau - Jūs galite netgi tiesiogiai valdyti pačius "tab"us.
Žemiau patekiamas statinių vidžetų ir freimų, kurie sudaro "tab"ų tūrinį, kodo pavyzdys
(po vieną freimą kiekvienam "tab"ui):
/* asmfr.i
*/
/* Frame 1 */
DEFINE VARIABLE t-adrreg AS CHARACTER FORMAT "X(256)":U
LABEL "Region"
VIEW-AS COMBO-BOX INNER-LINES 5
LIST-ITEM-PAIRS ""
SORT
DROP-DOWN-LIST
SIZE-PIXELS 126 BY 24 NO-UNDO.
DEFINE VARIABLE t-ctr AS CHARACTER FORMAT "X(256)":U
LABEL "Country"
VIEW-AS COMBO-BOX INNER-LINES 10
LIST-ITEM-PAIRS ""
SORT
DROP-DOWN-LIST
SIZE-PIXELS 133 BY 26 NO-UNDO.
DEFINE VARIABLE t-doctip AS CHARACTER FORMAT "X(256)":U
LABEL "Document"
VIEW-AS COMBO-BOX INNER-LINES 5
LIST-ITEM-PAIRS ""
SORT
DROP-DOWN-LIST
SIZE-PIXELS 154 BY 24 NO-UNDO.
DEFINE VARIABLE t-sex AS CHARACTER FORMAT "X(256)":U
LABEL "Sex"
VIEW-AS COMBO-BOX INNER-LINES 5
LIST-ITEM-PAIRS ""
SORT
DROP-DOWN-LIST
SIZE-PIXELS 133 BY 26 NO-UNDO.
DEFINE VARIABLE t-abbr AS CHARACTER FORMAT "X(256)":U
LABEL "ShortName"
VIEW-AS FILL-IN NATIVE
SIZE-PIXELS 336 BY 26 NO-UNDO.
DEFINE VARIABLE t-birthday AS DATE FORMAT "9999/99/99":U
LABEL "Birth date"
VIEW-AS FILL-IN NATIVE
SIZE-PIXELS 98 BY 26 NO-UNDO.
DEFINE VARIABLE t-cod AS CHARACTER FORMAT "X(256)":U
LABEL "Personal ID"
VIEW-AS FILL-IN NATIVE
SIZE-PIXELS 154 BY 26 NO-UNDO.
DEFINE VARIABLE t-doccod AS CHARACTER FORMAT "X(256)":U
LABEL "Nr"
VIEW-AS FILL-IN NATIVE
SIZE-PIXELS 154 BY 26 NO-UNDO.
DEFINE VARIABLE t-fname AS CHARACTER FORMAT "X(256)":U
LABEL "First Name"
VIEW-AS FILL-IN NATIVE
SIZE-PIXELS 231 BY 26 NO-UNDO.
DEFINE VARIABLE t-sname AS CHARACTER FORMAT "X(256)":U
LABEL "Last Name"
VIEW-AS FILL-IN NATIVE
SIZE-PIXELS 231 BY 26 NO-UNDO.
/* ************************ Frame Definitions *********************** */
DEFINE FRAME FR_1
t-sname AT Y 63 X 112 COLON-ALIGNED
t-fname AT Y 98 X 112 COLON-ALIGNED
t-abbr AT Y 133 X 112 COLON-ALIGNED
t-ctr AT Y 168 X 112 COLON-ALIGNED
t-adrreg AT Y 168 X 322 COLON-ALIGNED
t-cod AT Y 203 X 112 COLON-ALIGNED
t-birthday AT Y 238 X 112 COLON-ALIGNED
t-sex AT Y 238 X 315 COLON-ALIGNED
t-doctip AT Y 275 X 112 COLON-ALIGNED
t-doccod AT Y 275 X 294 COLON-ALIGNED
WITH 1 DOWN NO-BOX KEEP-TAB-ORDER OVERLAY
SIDE-LABELS THREE-D
AT X 5 Y 5
.
FRAME FR_1:FRAME = FRAME tabframe:handle.
FRAME FR_1:VISIBLE = false.
/* Frame 2 */
/* ..... widget definitions */
DEFINE FRAME FR_2
.... widgets
....
WITH 1 DOWN NO-BOX KEEP-TAB-ORDER OVERLAY
SIDE-LABELS NO-UNDERLINE THREE-D
AT X 5 Y 5
.
FRAME FR_2:FRAME = FRAME tabframe:handle.
FRAME FR_2:VISIBLE = false.
/* Frame 3 */
.....
/* Frame 4 */
DEFINE BUTTON bt-ca-del
LABEL "Delete"
SIZE-PIXELS 105 BY 26.
DEFINE BUTTON bt-ca-edit
LABEL "Edit"
SIZE-PIXELS 105 BY 26.
DEFINE BUTTON bt-ca-new
LABEL "New"
SIZE-PIXELS 105 BY 26.
DEFINE BUTTON bt-ca-view
LABEL "Go to companies registry ..."
SIZE-PIXELS 183 BY 26.
DEFINE BUTTON bt-ca-cmp
IMAGE-UP FILE "icons/cbbtn.bmp":U
LABEL "Button 1"
SIZE-PIXELS 21 BY 26.
DEFINE VARIABLE ca-tip AS CHARACTER FORMAT "X(256)":U
VIEW-AS COMBO-BOX INNER-LINES 5
LIST-ITEM-PAIRS "Item 1","Item 1"
DROP-DOWN-LIST
SIZE-PIXELS 144 BY 24 NO-UNDO.
DEFINE VARIABLE ca-cmp AS CHARACTER FORMAT "X(256)":U
VIEW-AS FILL-IN NATIVE
SIZE-PIXELS 98 BY 24 NO-UNDO.
DEFINE VARIABLE ca-ikits AS DATE FORMAT "9999.99.99":U
VIEW-AS FILL-IN NATIVE
SIZE-PIXELS 98 BY 24 NO-UNDO.
DEFINE VARIABLE ca-nuots AS DATE FORMAT "9999.99.99":U INITIAL ?
VIEW-AS FILL-IN NATIVE
SIZE-PIXELS 98 BY 24 NO-UNDO.
DEFINE RECTANGLE fr-4-rc-1
EDGE-PIXELS 2 GRAPHIC-EDGE NO-FILL
SIZE 70.43 BY 1.58.
/* Query definitions */
DEFINE QUERY cmpasm-br FOR
tt-cmpasmb SCROLLING.
/* Browse definitions */
DEFINE BROWSE cmpasm-br
QUERY cmpasm-br DISPLAY
tt-cmpasmb.del COLUMN-LABEL "" FORMAT "x/ "
tt-cmpasmb.cmpname COLUMN-LABEL "Company" FORMAT "x(15)"
tt-cmpasmb.tipname COLUMN-LABEL "Role " FORMAT "x(20)"
tt-cmpasmb.nuots COLUMN-LABEL "Worked from " FORMAT "xxxx.xx.xx "
tt-cmpasmb.ikits COLUMN-LABEL "to " FORMAT "xxxx.xx.xx"
ENABLE tt-cmpasmb.del
WITH NO-ROW-MARKERS SEPARATORS
SIZE-PIXELS 487 BY 161
TITLE "Person's occupations"
EXPANDABLE.
/* ************************ Frame Definitions *********************** */
DEFINE FRAME fr_4
cmpasm-br AT Y 23 X 18
bt-ca-cmp AT Y 205 X 119
ca-cmp AT Y 206 X 7 COLON-ALIGNED NO-LABEL
ca-tip AT Y 206 X 129 COLON-ALIGNED NO-LABEL
ca-nuots AT Y 206 X 274 COLON-ALIGNED NO-LABEL
ca-ikits AT Y 206 X 375 COLON-ALIGNED NO-LABEL
bt-ca-new AT Y 264 X 21
bt-ca-edit AT Y 264 X 139
bt-ca-del AT Y 264 X 381
bt-ca-view AT Y 318 X 303
fr-4-rc-1 AT ROW 8.65 COL 2.86
WITH 1 DOWN NO-BOX KEEP-TAB-ORDER OVERLAY
SIDE-LABELS NO-UNDERLINE THREE-D
AT X 5 Y 5
.
FRAME FR_4:FRAME = FRAME tabframe:handle.
FRAME FR_4:VISIBLE = false.
/* Frame 5 */
/* .... */
/* Frame 6 */
/* .... */
/* end of frames source */
|
Jūs galite kurti kiekvieno freimo turinį, naudodami UIB (User Interface Builder),
sukurdami netikrą atitinkamo dydžio dialogą (freimą), ir po to visus vidinius vidžetus jame.
Sukurus tokį freimą, sugeneruotą kodą galimą pernešti į galutinį failą, turintį visų reikalingų
freimų vidžetus.
Sekantis žingsnis - pagrindinio lango sudarymas, kuriame turi būti sukurtas "tab"us apimantis freimas.
Toliau sukūriami patys "tab"ai nuosekliai iškviečiant gf_create_tab funkcijas.
Šie funkcijos iškvietimai turi būti UIB standartinėje procedūroje Enable_UI, arba
Jūsų sudarytoje ekvivalentiškoje procedūroje. Kiekvienas "tab" sudarymo funkcijos
iškvietimas grąžina "tab"o kontroliuojančio vidžeto handlerį, kuris iš tikrųjų yra
pusiau paslėptas mygtuko (button) vidžetas. Vėliau galima panaudoti šį handlerį įvykių
apdorojimo trigeriuose ("ON" frazėje), arba tiesiogiai valdyti pačius "tab"us, keičiant
jų savybes (properties).
Naudojant ketvirtą gf_create_tab funkcijos parametrą, galima nurodyti išorines
arba vidines procedūras, kurios bus iškviestos paspaudus "tab"ą prieš jo pasirodymą ir po to.
Pre- ir post- processingo procedūrų pavadinimai skiriami kableliu ir sudaro vieną eilutę.
Penktas (paskutinis) parametras skirtas nurodyti procedūros handleriui, kurios kode
randasi pre- ir post- procedūros.
Žemiau pateikiamas galimos programos skeletas:
/*------------------------------------------------------------------------
File: _asm.p
Description: Personnel registry
Author: Vladas Saulis (PRODATA)
Created: 2001.06.20
*/
{ create_tab.i } /* This can also be put into global persistent section */
DEF VAR hTabFrame as handle.
DEF VAR hBut1 as widget-handle.
DEF VAR hBut2 as widget-handle.
DEF VAR hBut3 as widget-handle.
DEF VAR hBut4 as widget-handle.
DEF VAR hBut5 as widget-handle.
DEF VAR hBut6 as widget-handle.
/* *********************** Control Definitions ********************** */
/* Define the widget handle for the window */
DEFINE VAR C-Win AS WIDGET-HANDLE NO-UNDO.
/* Widget definitions goes here
....
*/
/* ************************ Frame Definitions *********************** */
DEFINE FRAME asm-fr
..... widgets
.....
WITH 1 DOWN NO-BOX KEEP-TAB-ORDER
SIDE-LABELS NO-UNDERLINE THREE-D
AT X 0 Y 0
SIZE-PIXELS 760 BY 470.
/* Example of container frame - the parent of all "tab" frames */
DEFINE FRAME tabframe
WITH THREE-D
.
FRAME tabframe:frame = FRAME asm-fr:handle.
ASSIGN
hTabFrame = FRAME tabframe:handle
htabFrame:WIDTH-PIX = 545
hTabFrame:HEIGHT-PIX = 425
hTabFrame:X = 215
hTabFrame:Y = 40
hTabFrame:BOX = false
.
{ asmfr.i } /* All "tabs" content */
/* Main window */
CREATE WINDOW C-Win
ASSIGN
TITLE = "Personnel registry"
....
....
SENSITIVE = yes
.
/* Event processing */
{ events.i }
/* The placeholder for event processing */
PROCEDURE enable_UI : /* This is a part of UIB code */
ENABLE ......
WITH FRAME asm-fr IN WINDOW C-Win.
VIEW C-Win.
/* gf_create_tab parameters:
1. The "tab" element screen label
2. Container frame handle
3. "tab's" frame handle
4. Optional: Pre- and post-processing
procedures' names
(separated by comma)
5. Optional: Procedure handle of pre-/post- procedures.
Returns: Controlling "tab" button handle.
*/
hBut1 = gf_create_tab("Main info", FRAME tabframe:HANDLE,
FRAME FR_1:HANDLE, ?, ?).
hBut2 = gf_create_tab("Extra info", FRAME tabframe:HANDLE,
FRAME FR_2:HANDLE, ?, ?).
hBut3 = gf_create_tab("Addresses", FRAME tabframe:HANDLE,
FRAME FR_3:HANDLE, "init_3_tab", THIS-PROCEDURE).
hBut4 = gf_create_tab("Occupation", FRAME tabframe:HANDLE,
FRAME FR_4:HANDLE, "init_4_tab", THIS-PROCEDURE).
hBut5 = gf_create_tab("Events", FRAME tabframe:HANDLE,
FRAME FR_5:HANDLE, "init_5_tab", THIS-PROCEDURE).
hBut6 = gf_create_tab("Other", FRAME tabframe:HANDLE,
FRAME FR_6:HANDLE, "init_6_tab", THIS-PROCEDURE).
ENABLE ALL WITH FRAME tabframe.
/* enable widgets in some (or all) "tabs" */
ENABLE ALL WITH FRAME FR_2.
ENABLE ALL WITH FRAME FR_1.
/* you can hide some frames */
FRAME fr_4:VISIBLE = FALSE.
FRAME fr_3:VISIBLE = FALSE.
run dis_frames_content. /* optionally disable all frames content */
END PROCEDURE.
/* Enable_UI */
|
Procedūros kodo atsisiuntimas
Jūs galite parsisiųsti arba peržiūrėti šį create_tab.i išeities tekstą.
Ekrano vaizdų pavyzdžiai
Čia Jūs galite pamatyti pavyzdynės personalo valdymo programos ekrano vaizdus
Čia pavaizduotas pradinis "tab"as, kuris atsiranda kada sukūriama arba koreguojama
asmens informacija. Galima pastebėti, kad kai kurie "tab"ai gali būti neprieinami.
Sąrašas šiame "tab"e nereikalauja specialaus apdorojimo, todėl kad jis yra statinis,
ir dirba kartu su visais kitais interfeiso elementais.
Papildomos pastabos apie 4GL "tab-control" užprogramuotas savybes
Kaip visada būna, šis "tab_control" variantas turi ir savo apribojimų.
Pagrindinis apribojimas yra glaudžiai susijęs su PROGRESS r-kodo dydžio apribojimu.
Jis atsiranda dėl to, kad visų "tab"ų visų elementų įvykiai turi būti apdorojami
vieno kodo segmeto ribose. Aišku galima šiek tiek sušvelninti situaciją, iškarto iškviečiant
vidines procedūras iš įvykių apdorojimo trigerių, bet realiame gyvenime šis variantas
taip pat gali nepadėti, jeigu programa yra pakankamai didelė.
Galimas ir kitas šios problemos sprendimas - kiekvieną "tab"ą apdoroti atskiroje
"persistent" procedūroje. Bet šis sprendimas iškelia kitą gana sudėtingą problemą -
taisyklingą šių procedūrų tarpusavio bendravimo užtikrinimą.
Kitas apribojimas yra ribotas horizontalus visų "tab"ų ilgis, ypač jeigu norima turėti
daugiau "tab"ų arba turėti ilgas antraštes ant jų. Egzistuoja galimybė realizuoti
"prasukamą tab"ą. Mes paliekam šios galimybės realizaciją Jums ir tikimės, kad Jūs
pasidalinsite su mumis savo idėjomis.
Kai kuriais atvejais reikalinga kurti "tab"us dinamiškai, priklausomai nuo programos
eigos. Šis variantas leidžia padaryti tai, bet pareikalaus iš Jūsų kiek įmantresnės
programavimo technikos.
Autoriai
Originali 4GL "tab-control" idėja ir realizacija priklauso
Vladui Sauliui (PRODATA) ir Sauliui Sakarauskui (Baltic Amadeus).
Jūs galite laisvai naudoti šį kodą Jūsų projektuose su sąlyga,
kad bus nurodyta šio kodo autorystė.
Klausimai ir komentarai priimami adresais, nurodytais kontaktų puslapyje.
|
|