Vor einiger Zeit benötigte ich eine einblendbare
Buttonleiste die ich, ohne Programmänderungen und neukompilieren, an sich
ändernde Bedürfnisse anpassen/erweitern konnte.
Heraus kam ein Prototyp basierend auf einer XML Datei die
problemlos durch neue Datensätze erweitert werden konnte.
Die XML Daten sahen wie folgt aus:
Name:
crsDynamic.xml
Struktur:
dyn_id I Interne
Satznummer
dyn_description C(25) Beschriftung
dyn_code m Auszuführender Code
bei CLICK
dyn_picpath C(250) Pfad und Name einer zu
verwendenden Bitmap
Aus Sicherheitsgründen kann der Inhalt des Feldes dyn_code einfach
mit STRCONV() nach Hexbinary gewandelt werden oder die XML Daten werden einfach
in einer Datenbanktabelle hinterlegt.
Der untenstehende Mustercode nutzt insgesamt 5 Grafiken die
im Code entsprechend Eurem Bildarchiv angepasst werden sollten. Sucht im Code
(oder ladet die XML Datei in einen Cursor) nach und passt
den dort befindlichen relativen Pfad und Dateinamen an.
Im u.a. Mustercode wird keine XML Datei gelesen sondern der
XML Stream der Einfachheit wegen im Form.LOAD generiert.
Zum Testen bauen wir eine Form auf der sich Labels, Textboxen u.ä. Zeug befinden:
Code in FORM.LOAD:
* // Create a Datasource so we have something to work with
* // In a real app this data should be stored in 1 or more tables
USE IN SELECT( [crsDynamic] )
TEXT TO lcXML TEXTMERGE NOSHOW PRETEXT 2
<?xml version = "1.0" encoding="Windows-1252" standalone="yes"?>
<VFPData>
<xsd:schema id="VFPData" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:element name="VFPData" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="crsdynamic" minOccurs="0" maxOccurs="unbounded">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="dyn_id" type="xsd:int"></xsd:element>
<xsd:element name="dyn_description">
<xsd:simpleType>
<xsd:restriction base="xsd:string">
<xsd:maxLength value="25"></xsd:maxLength>
</xsd:restriction>
</xsd:simpleType>
</xsd:element>
<xsd:element name="dyn_code">
<xsd:simpleType>
<xsd:restriction base="xsd:string">
<xsd:maxLength value="2147483647"></xsd:maxLength>
</xsd:restriction>
</xsd:simpleType>
</xsd:element>
<xsd:element name="dyn_picpath">
<xsd:simpleType>
<xsd:restriction base="xsd:string">
<xsd:maxLength value="250"></xsd:maxLength>
</xsd:restriction>
</xsd:simpleType>
</xsd:element>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
</xsd:choice>
<xsd:anyAttribute namespace="http://www.w3.org/XML/1998/namespace" processContents="lax"></xsd:anyAttribute>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<crsdynamic>
<dyn_id>1</dyn_id>
<dyn_description>Change Forms FontColor</dyn_description>
<dyn_code><![CDATA[* // Formreference to current form is _SCREEN.ActiveForm
PUBLIC piRGB as integer
piRGB = GETCOLOR()
IF piRGB >= 0 AND piRGB <> _SCREEN.ActiveForm.BackColor
_SCREEN.ActiveForm.SetAll( [ForeColor] , piRGB )
ELSE
MESSAGEBOX( [BackColor and ForeColor would be identical],0,[Incorrect Color Selection] )
ENDIF]]></dyn_code>
<dyn_picpath>.\_iconex\bmp\16x16\inf_rt_selectcolor.bmp</dyn_picpath>
</crsdynamic>
<crsdynamic>
<dyn_id>2</dyn_id>
<dyn_description>Change Forms BackColor</dyn_description>
<dyn_code><![CDATA[* // Formreference to current form is _SCREEN.ActiveForm
PUBLIC piRGB as integer
piRGB = GETCOLOR()
IF piRGB >= 0 and piRGB <> _SCREEN.ActiveForm.ForeColor
_SCREEN.ActiveForm.BackColor = piRGB
ELSE
MESSAGEBOX( [BackColor and ForeColor would be identical],0,[Incorrect Color Selection] )
ENDIF
RELEASE piRGB]]></dyn_code>
<dyn_picpath>.\_iconex\bmp\16x16\inf_rt_selectcolor.bmp</dyn_picpath>
</crsdynamic>
<crsdynamic>
<dyn_id>3</dyn_id>
<dyn_description>Switch Forms Label Align</dyn_description>
<dyn_code><![CDATA[* // Formreference to current form is _SCREEN.ActiveForm
LOCAL liLoop As Integer
FOR liLoop = 1 to _SCREEN.ActiveForm.ControlCount
IF _SCREEN.ActiveForm.Controls( liLoop ).BaseClass = [Label]
_SCREEN.ActiveForm.Controls( liLoop ).Alignment = IIF( _SCREEN.ActiveForm.Controls( liLoop ).Alignment = 0 , 1 , 0 )
ENDIF
ENDFOR
RELEASE liLoop]]></dyn_code>
<dyn_picpath>.\_iconex\bmp\16x16\inf_rt_alignright.bmp</dyn_picpath>
</crsdynamic>
<crsdynamic>
<dyn_id>4</dyn_id>
<dyn_description>Decrease Label Fontsize</dyn_description>
<dyn_code><![CDATA[* // Formreference to current form is _SCREEN.ActiveForm
LOCAL liLoop As Integer
FOR liLoop = 1 to _SCREEN.ActiveForm.ControlCount
IF _SCREEN.ActiveForm.Controls( liLoop ).BaseClass = [Label]
_SCREEN.ActiveForm.Controls( liLoop ).FontSize = _SCREEN.ActiveForm.Controls( liLoop ).FontSize ;
- IIF( ;
_SCREEN.ActiveForm.Controls( liLoop ).FontSize > 7 , ;
1 , ;
0 ;
)
ENDIF
ENDFOR
RELEASE liLoop
]]></dyn_code>
<dyn_picpath>.\_iconex\bmp\16x16\inf_rt_fontdn.bmp</dyn_picpath>
</crsdynamic>
<crsdynamic>
<dyn_id>5</dyn_id>
<dyn_description>Increase Label Fontsize</dyn_description>
<dyn_code><![CDATA[* // Formreference to current form is _SCREEN.ActiveForm
LOCAL liLoop As Integer
FOR liLoop = 1 to _SCREEN.ActiveForm.ControlCount
IF _SCREEN.ActiveForm.Controls( liLoop ).BaseClass = [Label]
_SCREEN.ActiveForm.Controls( liLoop ).FontSize = _SCREEN.ActiveForm.Controls( liLoop ).FontSize ;
+ IIF( ;
_SCREEN.ActiveForm.Controls( liLoop ).FontSize < 10 , ;
1, ;
0 ;
)
ENDIF
ENDFOR
RELEASE liLoop
]]></dyn_code>
<dyn_picpath>.\_iconex\bmp\16x16\inf_rt_fontup.bmp</dyn_picpath>
</crsdynamic>
</VFPData>
ENDTEXT
XMLTOCURSOR( lcXML , [crsDynamic] )
Code in FORM.INIT:
PUBLIC poMyForm as Form
poMyForm = Thisform
Thisform.CreateButtons()
Code in neuer Methode FORM.CREATEBUTTONS:
IF USED( [crsDynamic] )
Thisform.AddObject( [cmgDynamic] , [commandgroup] )
WITH Thisform.cmgDynamic
.ButtonCount = RECCOUNT( [crsDynamic] )
.Height = Thisform.Height + 1
.Width = 126
.Left = 0
.Top = 0
.BorderStyle = 0
.BackColor = RGB(253,254,216)
.Visible = .F.
BINDEVENT( poMyForm.cmgDynamic , [MouseEnter] , Thisform , [ShowHideDynamic] )
GO TOP IN crsDynamic
FOR liLoop = 1 TO RECCOUNT( [crsDynamic] )
.Buttons( liLoop ).WordWrap = .T.
.Buttons( liLoop ).Width = 120
.Buttons( liLoop ).Height = 45
.Buttons( liLoop ).Left = 2
.Buttons( liLoop ).Top = ( liLoop - 1 ) * .Buttons( liLoop ).Height
.Buttons( liLoop ).Caption = ALLTRIM( crsDynamic.dyn_description )
.Buttons( liLoop ).Picture = FULLPATH( ALLTRIM( crsDynamic.dyn_picpath ) )
.Buttons( liLoop ).FontSize = 8
.Buttons( liLoop ).PicturePosition = 0
loButton = EVALUATE( [poMyForm.cmgDynamic.Command] + TRANSFORM( liLoop ) )
BINDEVENT( loButton , [Click] , Thisform , [ButtonHandler] )
SKIP IN crsDynamic
ENDFOR
ENDWITH
ENDIF
Code in neuer Methode FORM.BUTTONHANDLER:
SELECT crsDynamic
GO ( Thisform.cmgDynamic.Value )
IF NOT EMPTY( crsDynamic.dyn_code )
TRY
EXECSCRIPT( crsDynamic.dyn_code )
CATCH
MESSAGEBOX( [Code incorrect],0,[Error])
ENDTRY
ENDIF
Code in neuer Methode FORM.SHOWHIDEDYNAMIC:
LPARAMETERS nButton, nShift, nXCoord, nYCoord
IF Thisform.cmgDynamic.Visible = .F.
Thisform.cmgDynamic.Visible = .T.
ELSE
Thisform.cmgDynamic.Visible = .F.
ENDIF
Code in Icon linksoben FORM.IMAGE1.CLICK:
Thisform.ShowHideDynamic()
Basierend auf den XML Daten erscheint nach dem Click auf das kleine Icon eine voll funktionstüchtige Buttonleiste:
Keine Kommentare:
Kommentar veröffentlichen