Coloured multine browse with icons, sample from the DevCon
Coloured multine browse with icons, sample from the DevCon
The attached sample presented on the 2015 eXpress++ DevCon can be compiled and linked with 1.9 SL1 or 2.0 (use "od.bat" for this if you like). It shows a DCBROWSE that uses ownerdrawing in a subclass, where a text containing (multiple) CR/LF is translated into multiple coloured lines reflecting the color codeblocks and icons added to the cell text are shown below the text. This is not a very generic sample, but it can be used as a base for almost anything you want to paint in a browse cell. Switch the text colors for the links, add boxes or whatever.
If the browse comes up, it will not use ownerdrawing. Click on "Use ownerdrawing", which toggles an iVar of the subclass. The browse is repainted using "InvalidateRect" (a refresh is not needed, since the cell contens remains the same!). Please don't deliver the icons I added. Those are from a library I bought. Thanks.
The screenshot shows what you should see if "Use ownerdrawing" was clicked.
If the browse comes up, it will not use ownerdrawing. Click on "Use ownerdrawing", which toggles an iVar of the subclass. The browse is repainted using "InvalidateRect" (a refresh is not needed, since the cell contens remains the same!). Please don't deliver the icons I added. Those are from a library I bought. Thanks.
The screenshot shows what you should see if "Use ownerdrawing" was clicked.
- Attachments
-
- DevCon_Ownerdrawing.zip
- (51.44 KiB) Downloaded 896 times
-
- screenshot.jpg (111.61 KiB) Viewed 15407 times
Best regards,
Tom
"Did I offend you?"
"No."
"Okay, give me a second chance."
Tom
"Did I offend you?"
"No."
"Okay, give me a second chance."
- obelix
- Posts: 48
- Joined: Tue Dec 03, 2013 7:44 am
- Location: Villingen-Schwenningen, Black Forest, Germany
Re: Coloured multine browse with icons, sample from the DevC
Many thanks, Tom
quiet old but still young and unskilled in express++
Re: Coloured multine browse with icons, sample from the DevC
Tom,
Looks great as always and as expected by you.
Now if we could get a glimpse of Bobby's colored tab pages within the printed report the moons would align.
Rick
Looks great as always and as expected by you.
Now if we could get a glimpse of Bobby's colored tab pages within the printed report the moons would align.
Rick
Re: Coloured multine browse with icons, sample from the DevC
This is a very elegant method of using owner-drawing and it inspired me to create a "generic" owner-drawing method for DC_XbpBrowse() that will use either an array or an object that is put into each cell in DCBROWSECOL. In addition, I would like to "style" it using CSS style rules.
Thanks again, Tom, for donating this sample.
Thanks again, Tom, for donating this sample.
The eXpress train is coming - and it has more cars.
Re: Coloured multine browse with icons, sample from the DevC
Fantastic - thanks Tom.
- sdenjupol148
- Posts: 151
- Joined: Thu Jan 28, 2010 10:27 am
- Location: NYC
Re: Coloured multine browse with icons, sample from the DevC
Hey Rick,
I will work on a sample of how it's done.
Bobby Drakos
I will work on a sample of how it's done.
Bobby Drakos
Re: Coloured multine browse with icons, sample from the DevC
Tom -
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.
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.
The eXpress train is coming - and it has more cars.
Re: Coloured multine browse with icons, sample from the DevC
I added a new feature to DCBROWSE and DCBROWSECOL that now lets you use a single record object to access the data in a browse. The navigation code blocks of the browse force a DC_DbScatter() of the record into the record object before each row is painted.
Copy the attached _DCXBROW.PRG to \expd20\source\dclipx and DCDIALOG.CH to \expd20\include.
Run BUILD19_SL1.BAT or BUILD20.BAT to rebuild DCLIPX.dll.
Here is the usage:
Copy the attached _DCXBROW.PRG to \expd20\source\dclipx and DCDIALOG.CH to \expd20\include.
Run BUILD19_SL1.BAT or BUILD20.BAT to rebuild DCLIPX.dll.
Here is the usage:
Code: Select all
oRecord := CUSTOMER->(DC_DbRecord():new())
@ 0,0 DCBROWSE oBrowse ALIAS 'CUSTOMER' SIZE 96,25 PRESENTATION aPres FIT ;
SUBCLASS 'XbpOwnerDrawBrowse()' USEVISUALSTYLE NOHSCROLL ;
RECORDOBJECT oRecord ;
PREEVAL {|o|o:stdFontCompoundName := '10.Tahoma', ;
o:boldFontCompoundName := '10.Tahoma '+FONTBOLD, ;
o:boldItalicFontCompoundName := '12.Tahoma '+FONTBOLD+' '+FONTITALIC}
DCBROWSECOL DATA {|o|{o:cust_nmbr}} ;
HEADER 'ID' WIDTH 5 PARENT oBrowse ;
OWNERDRAW
DCBROWSECOL DATA {|o|{o:bill_name, ;
o:bill_strt, ;
Trim(o:bill_city)+' '+o: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 {|o|{o:contact, ;
o:email, ;
'[' + IF(o:cont_gend=='m',GENDER_MALE,GENDER_FEMALE) + ']'}} ;
HEADER 'Contact' WIDTH 15 PARENT oBrowse ;
COLOR {||{GRA_CLR_DARKRED,oBrowse:rowColor()[2]}} ;
OWNERDRAW
DCBROWSECOL DATA {|o|{CustInfo(o:cust_val), ;
IF(o:cust_val==0,'['+BAD_VALUE+']',Replicate('['+GOOD_VALUE+']',o:cust_val))}} ;
HEADER 'Info/Rating' WIDTH 10 PARENT oBrowse ;
COLOR {||{GRA_CLR_DARKBLUE,GRA_CLR_YELLOW}} ;
OWNERDRAW
DCBROWSECOL DATA {|o|o:phone} HEADER 'Phone' WIDTH 10 PARENT oBrowse
- Attachments
-
- recordobject.zip
- (72.75 KiB) Downloaded 843 times
The eXpress train is coming - and it has more cars.
Re: Coloured multine browse with icons, sample from the DevC
Here is one more fix:
The ::DC_XbpBrowse:init() must be called last to insure that the PREEVAL overrides the font settings.
The ::DC_XbpBrowse:init() must be called last to insure that the PREEVAL overrides the font settings.
Code: Select all
INLINE METHOD 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
::DC_XbpBrowse:init( oParent, oOwner, aPos, aSize, aPP, lVisible, oGetList )
RETURN self
The eXpress train is coming - and it has more cars.