FAB en bBrowser, twee waardevolle libraries voor Visual Objects

Visual Objects beschikt over de databrowser voor het kolomsgewijs weergeven van veldinformatie. Gebruikt u die nog steeds? En heeft u Visual Objects 2.6? Dan is het de hoogste tijd de databrowser aan de kant te zetten. Bij uw 2.6 VO zit een rijk uitgerust gratis versie van bBrowser, een uit Duitsland afkomstige 'third party browser'. Zoals de meeste gratis meegeleverde third party tools is er tegen een geringe meerprijs (39,-) een versie met nog meer features te koop. Deze features zijn Drag & Drop, Info Values, Multiple Selection, Owner Draw Support en Variable Row Height. Bovendien is er technische support bij inbegrepen. Daarnaast kan voor 79 euro de Professional versie, met een SDK en dus source code, worden gekocht. Maar wie het bij de standaard versie wil laten heeft al enorm veel functionaliteit tot de beschikking. Je ziet, dat bBrowser een de facto standaard aan het worden is bij de ontwikkelaars, net zoals de meeste ontwikkelaars CA's standaard rapport generator al vervangen hebben door Report Pro of Crystal Reports.

 

Een andere tool is eveneens gratis en wordt ook intensief gebruikt. Het is de FabPaintControl van de Fransman Fabrice Foray. Deze programmeur heeft op zijn website http://www.fabtoys.net een indrukwekkend aantal voor Cavo geschikte utilities gezet. En het zijn nogal wat utilities die een programmeur met gemiddelde kennis niet zomaar maken kan, zoals Fab Twain (om scans via een Twain driver in te lezen) Fab Zip (om zipbestanden te maken en te lezen) of Fab Paint.

 

Sneller inzetten

 

Het nadeel van dit soort tools is dat je tijd moet besteden om ze te leren kennen en vooral: om ze in je bestaande applicatie te implementeren. In een nieuwe reeks webartikelen, waarvan ondergetekende een deel gaat schrijven, proberen wij u door de valkuilen van bepaalde Cavo classes te loodsen zodat u deze met minimale inspanning en eenvoudig te begrijpen voorbeeldcode kunt implementeren. Als eerste volgt een inleidend bBrowser artikel. Hiermee kunt u snel een browser opzetten en ook snel de standaard Cavo browser weergave vervangen door de bBrowser. Vooral dat laatste is een minder bekende mogelijkheid. Daarna volgt een artikel over het toepassen van de Fab Paint control, de FabTwain library en de FabZip library.

 

De Fab Paint control

 

Op genoemde website is dit allemaal niet zo snel terug te vinden. Gebruik hiervoor de Search keuze van de site en type in Fab. Alle downloads zijn dan wel zo'n beetje terug te vinden. De Paint control kan dynamisch worden toegewezen aan uw eigen scherm. Vervolgens kunt u er diverse grafische bestanden in weergeven met een aantal handige opties. Om de Fab Paint lib te gebruiken moet u eerst de library Fab PaintLib inlezen, gevolgd door Fab PaintLib Control. Laatst genoemde library gebruik Fab PaintLib en op uw beurt include u weer Fab PaintLib Control in uw applicatie. In dit specifieke geval beschikt u echter niet over de gehele source. U moet namelijk een DLL meeleveren FabPaint.DLL of FabPaintGif.DLL als u ook het GIF formaat wilt ondersteunen. Deze DLL's zijn niet bijgewerkt bij het uitkomen van versie 2.6 van Cavo. In dit geval is dat geen probleem. Een blik op de DLL's via Windows 2000 Support Tools' Dependency Walker leert, dat de ge-include libraries uitsluitend Microsoft Windows producten zijn. De DLL wordt geacht de CaPaint.dll te vervangen.

 

De implementatie is zeer eenvoudig. In uw applicatie schrijft u:

 

LOCAL oPLC AS FabPaintLibCtrl

 

gevolgd door

 

oPlc:=FabPaintLibCtrl{SELF,199,Point{},Dimension{},,TRUE)

 

en voor het weergeven van een bepaalde afbeelding cFile (pad+bestandsnaam):

 

oPlc:Image:=FabPaintLib{ cFile, SELF }

 

bBrowser

 

De bBrowser installatiebestanden moeten niet van de Cavo26 CD worden gehaald. Hierin zit namelijk een fout. Ga hiervoor naar de website

 

http://www.bBrowser.com/english/bBrowser/patches.htm.

 

Installatie

 

De patch voor 1.4 limited is in feite het volledige programma - en bevat ook de laatste bug fixes (in dit geval t/m februari 2003). Na installatie van deze bBrowser is er een subdirectory bBrowser gemaakt waar in de subdirectory source staat met de prototype libraries en nog enkele subdirectories (samples, help). Deze libraries moeten in uw project worden ingelezen, in de volgorde bDefines, bSystem, bServer, bGui, bBrowser. Die volgorde kunt u natuurlijk ook aan het VOPP overlaten. De bijbehorende DLL's (bSystem, bServer, bGui, bBrowser). staan ook al gereed, in de BIN subdirectory van uw Cavo 26 installatie. Deze DLL's moeten aan de klant worden meegeleverd. Het programma Wedsetup.exe (met daarbij een .sysbestand) staat ook in die BIN subdirectory en past het bestand Cavowed.inf aan met een sectie 

 

[CONTROL:CUSTOMCONTROL:BBrowser].

 

Het gevolg van het draaien van Wedsetup ziet u direct bij het opstarten van Cavo. Het pallet met controls is achteraan met een uitgebreid, namelijk de bBrowser. De eerste toepassing bestaat dan ook uit het maken van een window, waarin u ergens dit bBrowser control zet, op dezelfde wijze waarop u een sle of een subdatawindow zou plaatsen. Uw applicatie moet wel de bBrowser libraries includen via Properties/Libraries. Daarna kijken we hoe we een bBrowser kunnen toepassen zonder eerst een control te hoeven plaatsen, dat ter vervanging van de BrowseView.

 

De bBrowser control toepassen

                                                                       

Nu doet de bBrowser control op zichzelf niets. Dus gaan we wat code schrijven die we gemakkelijk kunnen gebruiken voor alle genoemde toepassingen. Om te beginnen subclassen we de bBrowser en laten we het control erven van deze subclass:

 

CLASS IC2bDataBrowser INHERIT bBrowser

 

We kunnen dan een init method schrijven. Deze ziet er zo uit:

 

METHOD Init(oOwner, uID, oOrigin, oDimension, kStyle) CLASS IC2bDataBrowser

       IF PCount()<>1

              SUPER:Init(oOwner, uID, oOrigin, oDimension, kStyle)

       ELSE

              IF IsInstanceOf(oOwner, #DataWindow) .or. ;

                     IsInstanceOf(oOwner, #DataDialog)

SUPER:Init(oOwner:__FormWindow, 1000, Point{0, 0},;                           Dimension{0, 0}, WS_CHILD+WS_TABSTOP)

                     SELF:CommandOwner := oOwner

              ELSE

                     SUPER:Init(oOwner, 1000, Point{0, 0}, Dimension{0, 0}, WS_CHILD+WS_TABSTOP)

              ENDIF

              SELF:SetDefaults()

       ENDIF

 

 

In het geval van een control doet deze init method overigens effectief niets meer dan self:SetDefaults aanroepen, want in de 3e regel wordt namelijk slechts de super:init aangeroepen. Zelfs de SetDefaults zou kunnen worden overgeslagen. Deze ziet er als volgt uit:

 

METHOD SetDefaults CLASS IC2bDataBrowser

      

       SELF:Editable := TRUE

       SELF:HorizontalScrollbarMode:=#Auto

       SELF:VerticalScrollbarMode  :=#Auto

       SELF:ViewLogicAs    :=#Checkbox

       SELF:CurrentMode    :=#Line

       SELF:GridInEmptyArea  :=FALSE

 

       SELF:EnableSelector(FALSE)

       SELF:EnableColumnMove(TRUE)

       SELF:EnableColumnResize(TRUE)

       SELF:EnableCaptionClick(TRUE)

       SELF:EnableRowResize(FALSE)

       SELF:EnableRowHeightVariable(FALSE)

       SELF:AutoClose:=FALSE

 

 

En daarmee zien we gelijk wat voor eigenschappen er zoal aan de bBrowser control kunnen worden toegekend. De meeste opdrachten spreken voor zich. Laat u deze intialisatie weg, dan worden de bBrowser defaults gebruikt; u kunt uiteraard een of meerdere eigenschappen na de initialisatie aanpassen, zowel direct  in de eigenschappen van het control via de editor, of via code.

 

Velden weergeven

 

De weer te geven velden zijn eenvoudig door te geven.  Zo maak ik gebruik van 3 arrays, die ik aan een zelfgeschreven method toevoeg. De array aSymFields bevat de symbolic names (dus met een # ervoor) van de direct weer te geven veldnamen. De array aSymLogicFields bevat eventueel op de gewenste plaatsen enkele extra velden, waarvan de inhoud niet rechtstreeks uit de database komt, bijvoorbeeld omdat er mee gerekend moet worden, of dat ze via een keyveld uit de weergegeven database uit een andere database moeten komen. Ook de kopjes staan in een array. Dus bijvoorbeeld:

 

       aSymFields:={#Roepnaam,#Toestel}

       aSymLogicFields:={#Roepnaam,#Naam,#Toestel}

               

 

Nu nemen we de database t.b.v. de bBrowser control in gebruik (zet eventueel eerst de database odbcontact in de juiste order):

 

SELF:oDCbBContact:Use(odbContact,aSymFields)

 

SELF:oDCbBContact is de naam van de bBrowser control in het scherm.  Use is een standaard method van de class bBrowser. Hiermee zijn de database en 2 velden beschikbaar in de bBrowser control. In deze (contactpersonen) database is de naam in stukjes opgebouwd. We willen ook de volledige naam zien, en daarvoor is het logische veld #naam toegevoegd. Die naam willen we tussen de roepnaam en het toestel zien. We gebruiken hiervoor de opdracht:

 

SELF:oDCbBContact:InsertNewColumn(#Naam,2,{"o"o:ReturnName(o:recno)})

 

#Naam is de in aSymLogicFields opgegeven symbolische naam van het invoegveld en 2 de positie waar we het veld willen zien. Het codeblok waarin ReturnName geeft als returnvalue de volledige contactpersoonsnaam terug. ReturnName kan zowel een functie zijn, als een method van de class van de databaseserver die we bij Use hebben opgegeven. Er kunnen ook paramaters worden meegegeven, in dit voorbeeld is dat het actuele recordnummer, zodat direct in een locale instantiatie van de contactendatabase in ReturnName ook het afgebeelde record kan worden opgezocht.

 

De method InsertNewColumn ziet er als volgt uit:

 

METHOD InsertNewColumn(sLabel,nPos,oBlok) CLASS IC2bDataBrowser

       LOCAL oColumn AS bDataColumn  

              oColumn := bDataColumn{SELF,SELF:Server,oBlok,#Expression)

              oColumn:HyperLabel := HyperLabel{sLabel}

              oColumn:CalculateWidth()         // calculate width of column

              SELF:AddColumn(oColumn)          // add column in browser

              SELF:OpenColumn(oColumn, nPos)       // show column at first

 

 

De kopjes erboven geven we als volgt op.

 

              SELF:oDCbBContact:SetCaptions,aSymLogicFields,{;

              {"Voornaam",90},;

              {"Naam contact",200},;

              {"Tel.",120},       })

 

Met de paramaters aSymLogicFields en een array met kopjes en breedtes worden de kopjes geplaatst. De breedte moet in points worden opgegeven.

 

Deze method ziet er weer als volgt uit:

 

METHOD SetCaptions(aufield,auInfo) CLASS IC2bDataBrowser

       LOCAL oColumn AS bDataColumn

       LOCAL nField AS DWORD

       LOCAL nWidth AS DWORD

       LOCAL lWidth AS LOGIC

       LOCAL cCaption AS STRING

 

              // Loop alle velden af

              FOR nField:=1 UPTO ALen(auField)                     // Set the vars

                     nWidth :=0

                     lWidth :=FALSE

                     cCaption:=auInfo[nField,1]

                     nWidth:=auInfo[nField,2]

                     oColumn   :=SELF:GetColumn(auField[nField])       // Get the column

                     IF !Empty(oColumn)

                            IF Empty(cCaption)                                 // Set caption

                                   IF oServer:FieldPos(auField[nField])<>0

                                          oColumn:Caption :=SELF:Server:Fieldspec(auField[nField]):Caption

                                   END

                            ELSE

                                   oColumn:Caption:=cCaption

                            END

 

                            IF !Empty(nWidth)                                                             

                                   oColumn:Width:=nWidth            // Set width

                            END

                     END

              NEXT nField

 

              IF lWidth                      // Did the width change?

                     SELF:Recalculate()

              END

RETURN

 

Het feest kan beginnen! De daadwerkelijke weergave van de browser regelen we als volgt:

 

       SELF:oDCbBContact:DisplayTheColumns(aSymLogicFields)

 

Waarbij die method er als volgt uitziet:

 

METHOD DisplayTheColumns(aFields) CLASS IC2bDataBrowser

       SELF:Clear(FALSE)

       SELF:OpenColumn(aFields)

 

Bovenstaande regels laten zich het handigst verzamelen in een method, die u bijvoorbeeld in de postinit aanroept van het scherm, waarin de bBrowser control staat:

 

METHOD DefineContactBrowser(oBrowser) CLASS RelatieVenster

LOCAL aSymFields AS ARRAY

LOCAL aSymLogicFields AS ARRAY

       aSymFields:={#Roepnaam,#Toestel}

       aSymLogicFields:={#Roepnaam,#Naam,#Toestel}

       SELF:oDCbBContact:Use(oas:odbContact,aSymFields)

SELF:oDCbBContact:Server:OrderScope(TOPSCOPE,SELF:Server:groep+SELF:Server:nr)

SELF:oDCbBContact:Server:OrderScope(BOTTOMSCOPE,SELF:Server:groep+SELF:Server:nr)

              SELF:oDCbBContact:SetCaptions,aSymLogicFields,{;

              {"Voornaam",90},;

              {"Naam contact",200},;

              {"Tel.",120},;

       })

 

       SELF:oDCbBContact:DisplayTheColumns(aSymLogicFields)

 

 

In een vervolgartikel zien we hoe we kolommen of inhoud kunnen kleuren, icons aanbrengen en bijzondere inhoud tonen.

 

De databrowser vervangen

 

Maar wat te doen als we niet eerst een control willen neerzetten en gewoon een bBrowser willen zien als we de TableView kiezen? Ook dat kan! De stappen zijn als volgt:

 

- Voeg per datawindow een autocreatebrowser toe. Zodra alle databrowsers vervangen zijn kunt u de class vervangen door uw eigen subclass waarvan uw datawindows erven zodat er maar een method over hoeft te blijven. Zie de code hieronder. Deze code zorgt ervoor, dat de ViewTable wordt 'omgeleid' naar uw DefineBrowser method per venster.

- Plaats de opdracht

       SELFBrowserClass = #IC2bDataBrowser

in de postinit van het tabwindow of datawindow (dus het window waarin de standaard browser gedefinieerd staat).

- Haal de oude browser en eventuele daarop betrekking hebbende opdrachten, zoals GBSREADONLY, weg.

- Schrijf een vergelijkbare initialisatie als bovengenoemde DefineBrowser. Gebruik bijvoorbeeld DefineBrowser voor de default tabelweergave en voeg DefineXXbrowser methods toe voor iedere control xx en roep dit aan in de postinit

- Voeg in de QueryClose toe:

 

       IF IsInstanceOf(SELFbrowser,#ic2bdatabrowser)

              SELFBrowserDestroy()          // Nodig ivm bBrowser 7-3-2003

       ENDIF 

 

- Een eventuele SetOrderScope zet u in de DefineBrowser en ook in de Notify method.

 

METHOD __AutoCreateBrowser() CLASS RelatieTab

// DEZE WEGHALEN ALS ALLE BROWSERS VERVANGEN ZIJN EN 1 METHOD // VAN ICDW OVERHOUDEN

                                  

       // create browser

       IF IsNil(oGBrowse)    

              SELF:oGBrowse := CreateInstance(symBrowserClass, SELF)

       ENDIF

 

       IF SELF:sCurrentView=#ViewSwitch

              Send(SELF:oGBrowse, #__NOTIFYChanges, GBNFY_VIEWSWITCH)

       ELSEIF SELF:sCurrentView=#BrowseView

              Send(SELF:oGBrowse, #__NOTIFYChanges, GBNFY_VIEWASBROWSER)

       ELSEIF SELF:sCurrentView=#FormView

              Send(SELF:oGBrowse ,#__NOTIFYChanges, GBNFY_VIEWASFORM)

       ENDIF

 

       IF SELF:lLinked .and. IsInstanceOfUsual(SELF:oAttachedServer, #DataServer)

              IF IsAccess(SELF:oGBrowse, #Server) .and. IsMethod(SELF:oGBrowse, #Use)

                     IF IsMethod(SELF,#DefineBrowser)

                            Send(SELF,#DefineBrowser,SELF:oGBrowse)

                     ENDIF

              ENDIF

       ENDIF

RETURN SELF

 

 

Ik hoop dat bovenstaande voorbeelden voldoende houvast bieden snel aan de slag te gaan met bBrowser en/of Fab en ga m’n best doen dit artikel in de loop van het jaar op te volgen.

 

 

Commentaar van anderen:
ChristianLouboutin op 14-8-2010 om 11:27
Christian Louboutin Shoes, Christian Louboutin, Christian Louboutin Shoes, Wedding Shoes, Christian Louboutin Copyright 2010, Chemicals Chemistry via VerticalNews. Christian Louboutin Shoes, Wedding Shoes Pattinson great actorly virtue is that he wears clothes well, so it too bad he slackered-out in cargo pants here. Christian Louboutin, Christian Louboutin Shoes, Wedding Shoes, Discount Christian Louboutin, Manolo Blahnik Shoes Tyler is less revealed than telegraphed through accessories a dead brother depth, a pack-a-day habit angst, a bookstore job smart, Discount Christian Louboutin, Louboutin, Christian Louboutin Sale, Louboutin Shoes, Sale Christian Louboutin Rodita zip sandals New style Black 14 a rich, aloof, and permanently disappointed daddy Pierce Brosnan. Louboutin Sale, Herve Leger Bandage Dress, Herve Leger Dress, Herve Leger V Neck Dress, Herve Leger Bandage Dress Falling for You Love, angst, and something else is in the air in Remember Me Remember Me Herve Leger Dress, Chanel Shoes, Yves Saint Laurent Shoes, Manolo Blahnik Shoes Platform Cage Sandal 13 by Allen Coulter Summit Entertainment Opens March 12 Putatively a new romance starring Robert Pattinson, Remember Me begins like a vigilante movie Alexander Wang Shoes, Louboutin Shoes, Louboutin Sale, Louboutin, Christian Louboutin Sale, Buy Christian Louboutin A Brooklyn subway platform, a racially charged stickup girl watches her mother get shot. Christian, Christian Louboutin Discount, Christian Dior Shoes, Christian Louboutin Pumps Pattinson great actorly virtue is that he wears clothes well, so it too bad he slackered-out in cargo pants here.
Geef feedback:

CAPTCHA image
Vul de bovenstaande code hieronder in
Verzend Commentaar