I have been experimenting with ways to make this more generic.
You can now give it an array of data as an option. This eliminates the need to concatenate everything with CRLF and make a tokenized string.
Also, the fonts can be defined in the DCBROWSE command.
Notice that you only need to use the OWNERDRAW clause on DCBROWSECOL commands.
My next experiment will be to use objects instead of arrays in the DCBROWSECOL DATA clauses.
Code: Select all
#INCLUDE "dcdialog.CH"
#define FONTBOLD "Bold" // change to "Fett" for German versions
#define FONTITALIC "Italic" // change to "Kursiv" for German versions
#define CRLF Chr(13)+Chr(10)
#define GENDER_MALE 'agent.ico'
#define GENDER_FEMALE 'she_user.ico'
#define GOOD_VALUE 'online.ico'
#define BAD_VALUE 'offline.ico'
#pragma library("dclipx.lib")
#pragma library("dclip1.lib") // for DC_LoadRdds()
FUNCTION Main()
LOCAL GetList := {}, GetOptions := {}, oBrowse, ;
aPres := ;
{ { XBP_PP_COL_DA_ROWHEIGHT, 48 }, ; // rows are 48 pixels high
{ XBP_PP_COL_DA_CELLHEIGHT, 48 } ,;
{ XBP_PP_COL_DA_HILITE_BGCLR, GRA_CLR_PALEGRAY },; // Hilite BG color
{ XBP_PP_COL_DA_CELLFRAMELAYOUT, XBPFRAME_BOX } ,;
{ XBP_PP_COL_DA_FRAMELAYOUT, XBPFRAME_NONE} ,;
{ XBP_PP_COL_DA_ROWSEPARATOR, XBPCOL_SEP_LINE }, /* Row Sep */ ;
{ XBP_PP_COL_DA_COLSEPARATOR, XBPCOL_SEP_LINE } }, /* Col Sep */ ;
lOwnerDraw := .F.
DCGETOPTIONS AUTORESIZE
DC_LoadRdds()
DC_BrowseColor( { nil, GRA_CLR_WHITE, nil, GraMakeRGBColor( {214,243,244} ) } )
USE customer VIA 'FOXCDX'
@ 0,0 DCBROWSE oBrowse ALIAS 'CUSTOMER' SIZE 96,25 PRESENTATION aPres FIT ;
SUBCLASS 'XbpOwnerDrawBrowse()' USEVISUALSTYLE NOHSCROLL ;
PREEVAL {|o|o:stdFontCompoundName := '10.Tahoma', ;
o:boldFontCompoundName := '10.Tahoma '+FONTBOLD, ;
o:boldItalicFontCompoundName := '12.Tahoma '+FONTBOLD+' '+FONTITALIC}
DCBROWSECOL DATA {||{CUSTOMER->cust_nmbr}} ;
HEADER 'ID' WIDTH 5 PARENT oBrowse ;
OWNERDRAW
DCBROWSECOL DATA {||{CUSTOMER->bill_name, ;
CUSTOMER->bill_strt, ;
Trim(CUSTOMER->bill_city)+' '+CUSTOMER->bill_zip}} ;
HEADER 'Name/Address' WIDTH 25 PARENT oBrowse ;
COLOR {||{IF('Software'$CUSTOMER->bill_name,GraMakeRGBColor( { 253, 120, 41 } ),GRA_CLR_DARKGREEN),oBrowse:rowColor()[2]}} ;
OWNERDRAW
DCBROWSECOL DATA {||{CUSTOMER->contact, ;
CUSTOMER->email, ;
'[' + IF(CUSTOMER->cont_gend=='m',GENDER_MALE,GENDER_FEMALE) + ']'}} ;
HEADER 'Contact' WIDTH 15 PARENT oBrowse ;
COLOR {||{GRA_CLR_DARKRED,oBrowse:rowColor()[2]}} ;
OWNERDRAW
DCBROWSECOL DATA {||{CustInfo(CUSTOMER->cust_val), ;
IF(CUSTOMER->cust_val==0,'['+BAD_VALUE+']',Replicate('['+GOOD_VALUE+']',CUSTOMER->cust_val))}} ;
HEADER 'Info/Rating' WIDTH 10 PARENT oBrowse ;
COLOR {||{GRA_CLR_DARKBLUE,GRA_CLR_YELLOW}} ;
OWNERDRAW
DCBROWSECOL FIELD CUSTOMER->phone HEADER 'Phone' WIDTH 10 PARENT oBrowse
@ 26,0 DCCHECKBOX lOwnerDraw PROMPT 'Use ownerdrawing' ;
ACTION {||oBrowse:lOwnerDraw := lOwnerDraw,oBrowse:InvalidateRect()}
DCREAD GUI FIT TITLE 'Ownerdrawing sample' ADDBUTTONS OPTIONS GetOptions
CLOSE ALL
RETURN nil
STATIC FUNCTION CustInfo(nValue)
DO CASE
CASE nValue == 0
RETURN 'bad'
CASE nValue == 1
RETURN 'ok'
CASE nValue == 2
RETURN 'good'
CASE nValue == 3
RETURN 'very good'
CASE nValue == 4
RETURN 'excellent'
CASE nValue == 5
RETURN 'best ever'
ENDCASE
RETURN 'not known'
PROC appsys ; RETURN
* ============
CLASS XbpOwnerDrawBrowse FROM DC_XbpBrowse
PROTECTED:
VAR oIcon, aLineAttrs, aBoxAttrs, oStdFont, oBoldFont, oBoldItalicFont
EXPORTED:
VAR lOwnerDraw
VAR stdFontCompoundName, boldFontCompoundName, boldItalicFontCompoundName
METHOD CustomDrawCell
INLINE METHOD destroy
::DC_XbpBrowse:destroy()
RETURN self
INLINE METHOD init( oParent, oOwner, aPos, aSize, aPP, lVisible, oGetList )
::DC_XbpBrowse:init( oParent, oOwner, aPos, aSize, aPP, lVisible, oGetList )
::drawMode:= XBP_DRAW_OWNER
::oIcon := XbpIcon():New():Create()
::lOwnerDraw := .F.
::aLineAttrs := ARRAY( GRA_AL_COUNT )
::aBoxAttrs := ARRAY( GRA_AA_COUNT )
::aLineAttrs [ GRA_AL_COLOR ] := GRA_CLR_BLACK
::aLineAttrs [ GRA_AL_TYPE ] := GRA_LINETYPE_SOLID
::stdFontCompoundName := '10.Tahoma'
::boldFontCompoundName := '10.Tahoma '+FONTBOLD
::boldItalicFontCompoundName := '10.Tahoma '+FONTBOLD+' '+FONTITALIC
RETURN self
INLINE METHOD create( oParent, oOwner, aPos, aSize, aPP, lVisible )
*******************************************************************
::oStdFont := XbpFont():New():Create(::stdFontCompoundName)
::oBoldFont := XbpFont():New():Create(::boldFontCompoundName)
::oBoldItalicFont := XbpFont():New():Create(::boldItalicFontCompoundName)
::DC_XbpBrowse:create( oParent, oOwner, aPos, aSize, aPP, lVisible )
RETURN self
ENDCLASS
METHOD XbpOwnerDrawBrowse:customDrawCell( oPS, aInfo )
******************************************
LOCAL xData, aPP, nFound, nAlign, nLine, nFgCol := GRA_CLR_BLACK, nBgCol := GRA_CLR_WHITE,;
aText, aIcons, nIcons, nHeight
IF !::lOwnerDraw // ownerdrawing is switched off, let the system draw
RETURN .T.
ENDIF
* get column data
xData:= aInfo[ XBP_DRAWINFO_AREA ]:getCell( aInfo[ XBP_DRAWINFO_ITEM ] )
IF xData == NIL // empty row
RETURN .F.
ENDIF
* get cell alignment
aPP := aInfo[ XBP_DRAWINFO_COLUMN ]:presArray
nFound := AScan(aPP,{|a|Valtype(a[1])=='N'.AND. ;
(a[1]==XBPCOL_DA_CELLALIGNMENT .OR. ;
a[1]==XBP_PP_COL_DA_CELLALIGNMENT) } )
IF nFound > 0
nAlign := aPP[nFound,2]
ELSE
nAlign := XBPALIGN_VCENTER
ENDIF
* get cell height
nHeight := Int((aInfo[ XBP_DRAWINFO_RECT, 4 ]-aInfo[ XBP_DRAWINFO_RECT, 2 ])/3)
* get cell colors
aInfo[ XBP_DRAWINFO_AREA ]:getCellColor( aInfo[ XBP_DRAWINFO_ITEM ],@nFgCol, @nBgCol )
IF nFgCol # nil
oPS:setColor( nFgCol, nBgCol )
ENDIF
IF Valtype(xData) # 'A'
xData := Var2Char(xData)
ENDIF
IF Valtype(xData) == 'C' .AND. !CRLF $ xData
* no line break, just paint the text
GraCaptionStr( oPS, aInfo[ XBP_DRAWINFO_RECT ], { aInfo[ XBP_DRAWINFO_RECT, 3 ], aInfo[ XBP_DRAWINFO_RECT, 4 ] }, xData, nAlign )
ELSE
IF Valtype(xData) == 'C'
aText := DC_TokenArray(xData,CRLF)
ELSE
aText := xData
ENDIF
FOR nLine := 1 TO Len(aText)
IF nLine = 1
IF BAnd(aInfo[XBP_DRAWINFO_STATE],XBP_DRAWSTATE_SELECTED) = 0 // cell is NOT selected
oPS:SetFont(::oBoldFont)
ELSE
oPS:SetFont(::oBoldItalicFont)
ENDIF
ELSE
oPS:SetFont(::oStdFont)
ENDIF
IF Left(aText[nLine],1) == '[' .AND. Right(aText[nLine],1) == ']' // paint at least one icon!
aIcons := DC_TokenArray(aText[nLine],']') // array of icon filenames will contain at least one
FOR nIcons := 1 TO Len(aIcons)
aIcons[nIcons] := StrTran(StrTran(aIcons[nIcons],'[',''),']','') // remove brackets
::oIcon:LoadFile(aIcons[nIcons],nHeight,nHeight) // load icon in line height
::oIcon:Draw(oPs,{ aInfo[ XBP_DRAWINFO_RECT, 1 ]+(nHeight*(nIcons-1)), aInfo[ XBP_DRAWINFO_RECT, 2 ], aInfo[ XBP_DRAWINFO_RECT, 1 ]+(nHeight*nIcons), aInfo[ XBP_DRAWINFO_RECT, 2 ]+nHeight })
NEXT
ELSE
GraCaptionStr( oPS, { aInfo[ XBP_DRAWINFO_RECT,1 ], aInfo[ XBP_DRAWINFO_RECT,4 ]-(nHeight*(nLine-1))},;
{ aInfo[ XBP_DRAWINFO_RECT, 3 ], aInfo[ XBP_DRAWINFO_RECT, 4 ]-(nHeight*nLine) }, aText[nLine], nAlign )
ENDIF
NEXT
ENDIF
RETURN .F.