FiveTech Support Forums

FiveWin / Harbour / xBase community
Board index FiveWin for Harbour/xHarbour Manual TXBrowse
Posts: 44158
Joined: Thu Oct 06, 2005 05:47 PM
Manual TXBrowse
Posted: Mon Mar 09, 2026 04:15 PM

Thanks to Carlos Atúncar Hernandez

REFERENCE MANUAL

TXBrowse / XBrowse

FiveWin for Harbour

Properties · Methods · Events · Columns

Based on official FiveWin examples


---

1. Introduction

TXBrowse (invoked via the command @ X,Y XBROWSE or XBROWSER) is the most powerful grid control in FiveWin for Harbour. It allows displaying and editing data from DBF/RDD tables, ADO RecordSets, arrays, TDatabase objects, trees (TTree), and text files.

1.1 Supported Data Sources

Property / EventTypeDescription and Usage
ALIAS / DATASOURCERDDOpen DBF table. Usage: ALIAS 'CUST' or DATASOURCE "CUSTOMER"
RECORDSET / RECSETADOADO RecordSet. Usage: RECSET oRs or RECORDSET oRs
ARRAYArrayTwo-dimensional array. Usage: ARRAY aData
OBJECTObjectTDatabase object or similar. Usage: OBJECT oCust
DATASOURCE oTreeTTreeTTree node tree for hierarchical browsing

1.2 Methods of Creating the Browse

Declarative Command

@ nRow, nCol XBROWSE oBrw OF oParent ALIAS 'CUST' AUTOCOLS LINES CELL

Programmatic (Class)

oBrw := TXBrowse():New( oWnd )
oBrw:SetRDD() // or :SetArray( aData ) / :SetRecordSet( oRs )
oBrw:CreateFromCode()

📌 NOTE: Always call :CreateFromCode() at the end of the configuration, before activating the dialog/window.


---

2. Browse Properties (TXBrowse)

2.1 Appearance and Style

PropertyTypeDescription and Usage
nMarqueeStyleNumericRow/cell selector style. See MARQSTYLE_* (Section 7)
nRowDividerStyleNumericDivider line style between rows. See LINESTYLE_* (Section 7)
nColDividerStyleNumericDivider line style between columns. See LINESTYLE_*
lColDividerCompleteLogicalIf .T., column lines extend to the header. Default: .F.
nRowHeightNumericRow height in pixels. e.g.: oBrw:nRowHeight := 40
nHeaderHeightNumericHeader height in pixels. e.g.: oBrw:nHeaderHeight := 30
nDataLinesNumericText lines per data row. e.g.: := 2 for multiline
nHeaderLinesNumericNumber of header lines. e.g.: := 2
nFooterLinesNumericNumber of footer lines
l2007LogicalEnables Office 2007 visual style. e.g.: oBrw:l2007 := .T.
nWidthsNumericUniform width for all columns in pixels

2.2 Scrolling and Columns

PropertyTypeDescription and Usage
nStretchColNumericColumn that expands to fill space. See STRETCHCOL_* (Section 7)
nFreezeNumericNumber of frozen columns. e.g.: oBrw:nFreeze := 2
lHScrollLogicalShow/hide horizontal scrollbar. Default: .T.
lVScrollLogicalShow/hide vertical scrollbar. Default: .T.
lRecordSelectorLogicalShow/hide record selector (left column). Default: .T.
nColSelNumericCurrently selected column index (read-only)

2.3 Colors

PropertyTypeDescription and Usage
bClrStdBlockStandard cell colors. { || { nTextColor, nBackColor } }
bClrRowFocusBlockColor of the row with focus. e.g.: {|| {CLR_BLACK, RGB(185,220,255)}}
bClrSelFocusBlockColor of selected cell/row with focus.
bClrHeaderBlockHeader color. e.g.: {|| {CLR_WHITE, RGB(134,219,9)}}
oDataFontsObj/BlockFont for data. Can be a font object or a block
oFooterFontsObjectFont for footers

📌 NOTE: Color blocks return an array: { nTextColor, nBackColor }. Background can be RGB or a gradient array.

2.4 Background

Method / PropertyTypeDescription and Usage
SetBackGround(cRes)MethodSets background image. e.g.: oBrw:SetBackGround("PAPER")
SetBackGround(aGrad, lVert)MethodGradient background. aGrad is the array, lVert is orientation
oBrushObjectCurrent background brush

---

3. Browse Events (TXBrowse)

EventTypeDescription and Usage
bChangeBlockExecuted on row change. e.g.: {|| oCol:RefreshFooter() }
bRClickedBlockRight-click on data. {|nRow, nCol| ShowPopup(nRow,nCol,oBrw)}
bLDClickDataBlockLeft double-click on data
bKeyDownBlockKey pressed
bKeyCharBlockCharacter typed
bPopUpBlockRight-click popup menu
bSeekBlockIncremental search while typing

---

4. Column Properties (TXBrwColumn)

4.1 Identification and Header

PropertyTypeDescription and Usage
cHeaderStringHeader text. Supports CRLF for multiline
nHeadStrAlignNumericHeader alignment: AL_LEFT / AL_CENTER / AL_RIGHT
oHeaderFontFont ObjSpecial font for header (e.g., vertical)
nPosNumericCurrent visible position
nWidthNumericColumn width in pixels

4.2 Data and Formatting

PropertyTypeDescription and Usage
cEditPictureStringFormat/Edit mask. e.g.: :HireDate:cEditPicture := 'dd mmm yyyy'
bStrDataBlockBlock returning cell text. {|| _FIELD->First}
ValueVariousCurrent cell value (read/write). oBrw:oCol("City"):Value
lDisplayZerosLogicalIf .F., hides zeros
nDataStrAlignNumericData alignment: AL_LEFT / AL_CENTER / AL_RIGHT

4.3 Images and Bitmaps

Method / PropertyTypeDescription and Usage
AddResource(cRes)MethodAdd bitmap from resource
nHeadBmpNoNum/BlockBitmap index for header
bBmpDataBlockBlock returning bitmap index for data
lBmpTransparentLogicalEnables alpha transparency
bStrImageBlockBlock returning image path

---

5. Main Methods

MethodDescription
CreateFromCode()Finalizes browse construction. Mandatory as the last step.
SetArray(aData)Sets or changes the data array
SetRDD()Configures browse for the active RDD area
Refresh([lFull])Redraws browse. lFull=.T. for complete reconstruction
Edit([lNew])Opens editor for current record. lNew=.T. for new record
ToExcel()Exports browse to Excel
Report()Generates a report or PDF
SaveState()Saves columns/order/widths to a string
RestoreState(c)Restores saved state

---

6. Dynamic Column Access

XBrowse allows accessing columns by name directly as a property:

  • Direct: oBrw:Salary:nFooterType := AGGR_TOTAL
  • Via Method: oBrw:oCol("Salary"):lTotal := .T.
  • Computed Column: oBrw:NewSalary := { || oBrw:Salary:Value * 1.1 }

---

7. Reference Constants

7.1 MARQSTYLE_* (Selector Style)

  • MARQSTYLE_DOTCELL (1): Dotted frame.
  • MARQSTYLE_SOLIDCELL (2): Solid frame.
  • MARQSTYLE_HIGHLCELL (3): Highlight cell.
  • MARQSTYLE_HIGHLROW (5): Highlight full row.
  • MARQSTYLE_HIGHLWIN7: Win7/10 gradient style.

7.2 EDIT_* (Editor Types)

  • EDIT_NONE (0): No editing.
  • EDIT_GET (1): Standard Textbox.
  • EDIT_LISTBOX: Dropdown list.
  • EDIT_GET_BUTTON: GET with action button.

7.3 AGGR_* (Footer Aggregates)

  • AGGR_TOTAL / AGGR_SUM: Sum.
  • AGGR_AVERAGE: Mean.
  • AGGR_COUNT: Count.

---

8. Recommended Usage Pattern

  1. Define Data Source (ALIAS, ARRAY, etc.).
  2. Create browse via @ X,Y XBROWSE or New().
  3. Set Browse properties (Styles, Marquee, Colors).
  4. Configure Column properties (Headers, Editing, Bitmaps).
  5. Call MakeTotals() if using footers.
  6. Call CreateFromCode() (Always the last configuration step).
  7. Assign oWnd:oClient := oBrw.
  8. Activate window and call oBrw:SetFocus().

---

9. Advanced Features

9.1 Incremental Filter

Code (harbour): Select all Collapse
WITH OBJECT oBrw
   :lIncrFilter := .T.
   :lSeekWild   := .T. // "Contains" search
   :cFilterFld  := "FIRST"
END
regards, saludos

Antonio Linares
www.fivetechsoft.com
Posts: 44158
Joined: Thu Oct 06, 2005 05:47 PM
Re: Manual TXBrowse
Posted: Mon Mar 09, 2026 05:27 PM

REFERENCE MANUAL

TXBrowse / XBrowse

FiveWin for Harbour

Properties · Methods · Events · Columns

Based on official FiveWin examples

1\. Introduction

TXBrowse (invoked via the @ X,Y XBROWSE or XBROWSER command) is the most powerful grid control in FiveWin for Harbour. It allows displaying and editing data from DBF/RDD tables, ADO RecordSets, arrays, TDatabase objects, trees (TTree), and text files.

1.1 Supported Data Sources

Property / EventTypeDescription and Usage
ALIAS / DATASOURCERDDOpen DBF table. Usage: ALIAS 'CUST' or DATASOURCE "CUSTOMER"
RECORDSET / RECSETADOADO RecordSet. Usage: RECSET oRs or RECORDSET oRs
ARRAYArrayTwo-dimensional array. Usage: ARRAY aData
OBJECTObjectTDatabase object or another with similar interface. Usage: OBJECT oCust
DATASOURCE oTreeTTreeTTree node tree for hierarchical browse

1.2 Ways to Create the Browse

Declarative command

@ nRow, nCol XBROWSE oBrw OF oParent ALIAS 'CUST' AUTOCOLS LINES CELL

Programmatic (class)

oBrw := TXBrowse():New( oWnd )

oBrw:SetRDD() // or :SetArray( aData ) / :SetRecordSet( oRs )

oBrw:CreateFromCode()

📌 NOTE: Always call :CreateFromCode() at the end of configuration, before activating the dialog/window.

2\. Browse Properties (TXBrowse)

2.1 Appearance and Style

Property / EventTypeDescription and Usage
nMarqueeStyleNumericRow/cell selector style. See MARQSTYLE\_\* constants (section 7\)
nRowDividerStyleNumericDividing line style between rows. See LINESTYLE\_\* (section 7\)
nColDividerStyleNumericDividing line style between columns. See LINESTYLE\_\*
lColDividerCompleteLogicalIf .T., the column line extends to the header. Default: .F.
nRowHeightNumericHeight of each row in pixels. Ex: oBrw:nRowHeight := 40
nHeaderHeightNumericHeader height in pixels. Ex: oBrw:nHeaderHeight := 30
nDataLinesNumericNumber of text lines per data row. Ex: := 2 for multiline
nHeaderLinesNumericNumber of header lines. Ex: := 2 for 2-line headers
nFooterLinesNumericNumber of column footer lines
l2007LogicalActivates Office 2007 visual style. Ex: oBrw:l2007 := .T.
nWidthsNumericUniform width for all columns in pixels

2.2 Scrolling and Columns

Property / EventTypeDescription and Usage
nStretchColNumericColumn that expands to fill available space. See STRETCHCOL\_\* (section 7\)
nFreezeNumericNumber of frozen columns (don't scroll horizontally). Ex: oBrw:nFreeze := 2
lHScrollLogicalShows/hides horizontal scrollbar. Default: .T.
lVScrollLogicalShows/hides vertical scrollbar. Default: .T.
lRecordSelectorLogicalShows/hides the record selector (left column). Default: .T.
nColSelNumericCurrently selected column number (read)

2.3 Colors

Property / EventTypeDescription and Usage
bClrStdBlockStandard cell color. {{ nTextColor, nBkgColor } }. Ex: {{CLR\_BLACK, CLR\_WHITE}}
bClrRowFocusBlockColor of the focused row. Ex: {{CLR\_BLACK, RGB(185,220,255)}}
bClrSelFocusBlockColor of the selected cell/row with focus. Same format as bClrStd
bClrHeaderBlockHeader color. Ex: {{CLR\_WHITE, RGB(134,219,9)}}
oDataFontsObject/BlockFont for data. Can be a font object or block {If(cond, oFontA, oFontB)}
oFooterFontsObjectFont for column footers

📌 NOTE: Color blocks return a 2-element array: { nTextColor, nBkgColor }. The background can be an RGB color or even a gradient array.

2.4 Background

Property / EventTypeDescription and Usage
SetBackGround(cRes)MethodSets background image. Ex: oBrw:SetBackGround("PAPER")
SetBackGround(aGrad, lVert)MethodGradient background. aGrad is an array of segments, lVert sets vertical/horizontal orientation
oBrushObjectCurrent background brush. oBrw:oBrush:nResizeMode for mode (BCK\_TILED, etc.)

Gradient example

local aGrad := {{ .5, CLR\_BLUE, RGB(202,202,255) }, { .5, RGB(202,202,255), CLR\_BLUE }}

// In the XBROWSE command: BACKGROUND aGrad VERTICAL

// Or in code: oBrw:SetBackGround( aGrad, .T. )

2.5 Editing

Property / EventTypeDescription and Usage
nEditTypesNumericEdit type for ALL columns at once. Ex: oBrw:nEditTypes := EDIT\_GET
lFastEditLogicalAllows fast editing without needing to press Enter first. Ex: := .T.
lFormulaEditLogicalEnables formula editing in cells. Ex: oBrw:lFormulaEdit := .T.
bEditWhensBlockGlobal condition for when to allow editing. {oColcondition}
lAutoAppendLogicalAllows automatically adding rows when reaching the end of the array
bPastEofBlockBlock executed when trying to go beyond the last record

2.6 Column Footers

Property / EventTypeDescription and Usage
lFooterLogicalActivates/deactivates the footer row. Ex: oBrw:lFooter := .T.
cFootersArrayArray with footer texts for all columns
MakeTotals(\[oCol\])MethodRecalculates totals/aggregates for footers. Called after configuring columns

2.7 Sorting and Searching

Property / EventTypeDescription and Usage
bSeekBlockBlock for incremental search. {cDbSeek(Upper(c))}
nArrayAtNumericIndex of the current row in the array (only for ARRAY source)
aArrayDataArrayReference to the data array (ARRAY source)
aRowArrayArray with values of the current row
BookMarkVariousBookmark of the current record (RDD/ADO)
nLenNumericTotal number of records/rows in the browse

2.8 Multi-Selection

Property / EventTypeDescription and Usage
aSelectedArrayArray with bookmarks of selected rows (multiselect)
SelectAll()MethodSelects all rows
SelectNone()MethodDeselects all rows
nMarqueeStyle := MARQSTYLE\_HIGHLROWMSConstantEnables multi-selection mode with Ctrl+click

2.9 Group Headers

Property / EventTypeDescription and Usage
SetGroupHeader(cTxt,n1,n2,oFont)MethodDefines a group header spanning columns n1 to n2. Ex: :SetGroupHeader('EMPLOYEE'+CRLF+'NAME', 1, 2, oBold)
lAllowColReGroupLogicalAllows reordering columns within a group. Ex: := .T.

Example

oBrw:SetGroupHeader( 'EMPLOYEE' \+ CRLF \+ 'NAME', 1, 2, oBold )

oBrw:SetGroupHeader( 'ADDRESS', 3, 6, oBold )

2.10 Tree Browse

Property / EventTypeDescription and Usage
DATASOURCE oTreeTTreeTree-type data source for hierarchical browse
oTreeItemTTreeItemCurrently selected node in the tree
oTreeTTreeReference to the browse data tree
SetTree(nil, aBmps)MethodConverts a normal browse to an automatic tree
nDataTypeNumericData type. DATATYPE\_TREE if tree

2.11 State and Persistence

Property / EventTypeDescription and Usage
SaveState()MethodSaves the current state (columns, order, etc.) to a string
RestoreState(cState)MethodRestores the state saved with SaveState()
lKineticBrwLogicalEnables kinetic scrolling (touch). Ex: := .T.

2.12 Cell Tooltip

Property / EventTypeDescription and Usage
bCellToolTipsBlockGeneric tooltip for any cell. {oCol{oCol:Value, oCol:cHeader}}
cToolTipStringSimple tooltip for the entire browse. Ex: oBrw:cToolTip := 'Text'

📌 NOTE: bCellToolTips applies to all columns, but can be overridden per column with oCols\[n\]:bCellToolTip

3\. Browse Events (TXBrowse)

Property / EventTypeDescription and Usage
bChangeBlockExecuted when changing rows. Ex: {oCol:RefreshFooter() }
bRClickedBlockRight-click on data. {nRow, nColShowPopup(nRow,nCol,oBrw)}
bLDClickDataBlockLeft double-click on data
bKeyDownBlockKey pressed. {oDlg:SetText(Str(oBrw:nColSel))}
bKeyCharBlockCharacter typed. {kIf(k==VK\_RETURN, ..., nil)}
bPopUpBlockPopup menu on right-click. {oColMenu(o)}
bSeekBlockIncremental search while typing. {cDbSeek(Upper(c))}
bClrSelFocusBlockColor of row/cell with focus and active selection

4\. Column Properties (TXBrowseCol)

4.1 Identification and Header

Property / EventTypeDescription and Usage
cHeaderStringHeader text. Can include CRLF for multi-line. Ex: "Name" \+ CRLF \+ "Employee"
nHeadStrAlignNumericAlignment of header text. AL\_LEFT / AL\_CENTER / AL\_RIGHT
oHeaderFontFont objectSpecial font for the header. Can be a vertical font (NESCAPEMENT 900\)
nCreationOrderNumericColumn creation order. Useful with nStretchCol
nPosNumericCurrent visible position of the column
nWidthNumericColumn width in pixels. Ex: :nWidth := 80
nArrayColNumericColumn index in the source array (for ARRAY source)

4.2 Data and Formatting

Property / EventTypeDescription and Usage
cEditPictureStringFormat/edit mask. Ex: :HireDate:cEditPicture := 'dd mmm yyyy'
bStrDataBlockBlock that returns the cell text. {\_FIELD-\>First}
bEditValueBlockBlock that returns the editable value. {\_FIELD-\>Married}
ValueVariousCurrent cell value (read/write). oBrw:oCol("City"):Value
lDisplayZerosLogicalIf .F., does not display zeros. Ex: oBrw:lDisplayZeros := .F.
nDataStrAlignsNumericData alignment for ALL columns at once (browse property)
nDataStrAlignNumericData alignment of the column. AL\_LEFT / AL\_CENTER / AL\_RIGHT
bDataStrAlignBlockDynamic alignment. {oIf(o:oBrw:aRow\[1\]==0, AL\_CENTER, AL\_LEFT)}
nDataStyleNumericDrawing style for text in the cell

4.3 Column Colors

Property / EventTypeDescription and Usage
bClrStdBlockColumn color. Overrides browse bClrStd. {{nText, nBkg}}
bClrEditBlockColor when editing the cell. Ex: oBrw:aCols\[1\]:bClrEdit := oBrw:bClrStd
oBrushObjectOwn brush (image/color background) for the column
bExtendBlockCell extension (merge): {oIf(cond, nCols, 0)}. Simulates cell merging

4.4 Images and Bitmaps in Column

Property / EventTypeDescription and Usage
AddBmpFile(cFile)MethodAdds a bitmap from file to the column image list
AddResource(cRes)MethodAdds a bitmap from resource. Ex: :AddResource("GREEN")
AddBitmap(aNames)MethodAdds bitmap array. Ex: :AddBitmap({"OPEN","CLOSE","GREEN"})
nHeadBmpNoNumeric/BlockBitmap number to show in the header. 1-based. Can be a block
nHeadBmpAlignNumericBitmap alignment in header. AL\_LEFT / AL\_RIGHT / AL\_CENTER
nGrpBmpNoNumericBitmap number for group header
bBmpDataBlockBlock that returns the bitmap number to show in data. {If(cond,1,2)}
nDataBmpAlignNumericBitmap alignment in data. AL\_LEFT / AL\_CENTER / AL\_RIGHT
lBmpStretchLogicalIf .T., stretches the bitmap to fill the cell
lBmpTransparentLogicalIf .T., renders the bitmap with alpha transparency
bStrImageBlockBlock that returns the image path for the cell. {oCol,oBrwoBrw:aRow\[2\]}
bAlphaLevelBlockAlpha transparency level (0-255). {oo:oBrw:aRow\[3\]}
nFootBmpNoNumericBitmap number to show in the column footer

📌 NOTE: For transparent PNG images with alpha channel, use lBmpTransparent := .T. combined with bAlphaLevel.

4.5 Column Footer

Property / EventTypeDescription and Usage
cFooterStringStatic footer text. Ex: oCols\[1\]:cFooter := "TOTAL"
bFooterBlockDynamic block for footer. {LTrim(Str(oTxt:RecCount()))}
nFooterTypeNumericType of automatic aggregate. See AGGR\_\* (section 7\)
bSumConditionBlockCondition to include row in total. {u,oo:oBrw:aRow\[1\]\>0}
bLClickFooterBlockLeft-click on footer. {r,c,f,oFooterAggrClick(r,c,f,o)}
bRClickFooterBlockRight-click on footer
RefreshFooter()MethodRefreshes the column footer
lTotalLogicalActivates automatic total in footer. Ex: oCol:lTotal := .T.
nTotalNumericValue of accumulated total (read/write)

4.6 Column Editing

Property / EventTypeDescription and Usage
nEditTypeNumericEditor type. See EDIT\_\* (section 7). Ex: := EDIT\_GET
bOnPostEditBlockExecuted after confirming the edit. {oCol, xVal, nKey...}
bEditBlockBlockBlock for the edit button (EDIT\_GET\_BUTTON). {r,c,oCol...}
aEditListTxtArrayTexts for the edit listbox (EDIT\_GET\_LISTBOX)
aEditListBoundArrayValues corresponding to the listbox texts
cEditPictureStringInput mask when editing. Ex: "@K \!\!\!\!\!\!\!\!\!\!"
lAutoSaveLogicalIf .T., saves automatically when leaving the cell without needing bOnPostEdit
SetCheck(aBmps, xEdit)MethodConverts column to checkbox. aBmps can be {"GREEN","RED"}
nBtnBmpStringBitmap path for the edit button. Ex: "c:\\\\fwh\\\\bitmaps\\\\browse.bmp"
bPaintTextBlockOwner-draw for cell text. {oCol,hDC,cText,aCoordDrawText(...)}

4.7 Column Events

Property / EventTypeDescription and Usage
bLClickHeaderBlockLeft-click on header. {r,c,f,oCol...}
bRClickHeaderBlockRight-click on header
bLDClickDataBlockLeft double-click on data
blDClickDatasBlockAlias of bLDClickData in some contexts
bRClickDataBlockRight-click on data
bLClickFooterBlockLeft-click on footer
bRClickFooterBlockRight-click on footer
bCellToolTipBlockCell-specific tooltip. {oColTRIM(FIELD-\>FIRST)+CRLF+TRIM(FIELD-\>LAST)}
cToolTipArrayColumn tooltip as array {cText, cTitle}. Ex: {'Col: '+cHeader,'Tip'}
bPopUpBlockColumn context menu. {oColMenu(o)}

4.8 Cell Anchoring (AnchorToCell)

Property / EventTypeDescription and Usage
AnchorToCell(oDlg)MethodPositions a dialog anchored to the current cell. Ideal for search popups

Example

oDlg:bInit := { || oCol:AnchorToCell( oDlg ) }

5\. Main Browse Methods

Property / EventTypeDescription and Usage
CreateFromCode()MethodFinalizes the browse construction. Always call at the end of configuration
SetArray(aData)MethodSets or changes the data array. Ex: oBrw:SetArray( aData )
SetRDD()MethodConfigures the browse to use the active RDD area
Refresh(\[lFull\])MethodRedraws the browse. lFull=.T. for full rebuild
SetFocus()MethodSets focus to the browse
Edit(\[lNew\])MethodOpens the editor for the current record. lNew=.T. for new record
Delete()MethodDeletes the current record
GoBottom()MethodGoes to the last record/row
GoTop()MethodGoes to the first record/row
InsCol(nPos)MethodInserts a column at position nPos. Returns the column object
AddCol()MethodAdds a column at the end. Returns the column object
MoveCol(oColA, oColB)MethodMoves column oColA before oColB
oCol(cName)MethodReturns column by name. Ex: oBrw:oCol("Salary")
GetVisibleCols()MethodReturns array with visible columns
MakeTotals(\[oCol\])MethodRecalculates footer totals
DataRect()MethodReturns array {nTop,nLeft,nBottom,nRight} of the data area
FontSize(nDelta)MethodIncreases or decreases font size. Ex: :FontSize(+1)
SelFont()MethodOpens dialog to select font
SetAlign(nAlign)MethodChanges alignment of the active column
ToExcel(\[lTitle,nMode\])MethodExports the browse to Excel
Report(\[...\])MethodGenerates a printed or PDF report of the browse
SaveState()MethodSaves browse state (columns, order, widths)
RestoreState(cState)MethodRestores a previously saved state
SelectAll()MethodSelects all rows (multiselect mode)
SelectNone()MethodDeselects all rows
SetBackGround(xBkg, nMode)MethodSets the browse background
SetGroupHeader(c, n1, n2, oF)MethodDefines group header for columns n1 to n2
SetTree(nil, aBmps)MethodActivates automatic tree mode

6\. Dynamic Column Access

XBrowse allows accessing browse columns by name directly as a browse property, thanks to the magic of \_\_GetProperty:

6.1 By name (direct access)

oBrw:Salary:nFooterType := AGGR\_TOTAL

oBrw:Married:SetCheck( { "GREEN", "RED" }, .T. )

oBrw:HireDate:cEditPicture := 'dd mmm yyyy'

6.2 Via oCol() method

if \!Empty( oCol := oBrw:oCol( "Salary" ) )

oCol:lTotal := .T.

oCol:nEditType := EDIT\_GET

endif

6.3 By index in aCols

oBrw:aCols\[ 1 \]:bClrStd := {|| {CLR\_WHITE, CLR\_RED} }

oBrw:aCols\[ 2 \]:nHeadStrAlign := AL\_CENTER

6.4 Computed column (formula)

// Adds new column based on another

oBrw:NewSalary := { || oBrw:Salary:Value \* 1.1 }

WITH OBJECT oBrw:NewSalary

:cHeader := 'NewSalary'

:nFooterType := AGGR\_TOTAL

END

6.5 ADD TO (command)

ADD TO oBrw DATA (cAlias)-\>CITY HEADER "City" CARGO { 1, 2 }

ADD TO oBrw DATA oRs:Fields("TotSalary"):Value / oRs:Fields("Employees"):Value ;

HEADER "AVERAGE" PICTURE "999,999,999"

7\. Reference Constants

7.1 MARQSTYLE\_\* — Selector Style

ConstantTypeDescription and Usage
MARQSTYLE\_DOTCELL (1)ConstantDotted frame on the active cell
MARQSTYLE\_SOLIDCELL (2)ConstantSolid frame on the active cell
MARQSTYLE\_HIGHLCELL (3)ConstantHighlights the active cell with color
MARQSTYLE\_HIGHLROWRC (4)ConstantHighlights active row and column
MARQSTYLE\_HIGHLROW (5)ConstantHighlights the entire active row
MARQSTYLE\_HIGHLROWMS (6)ConstantHighlights row with multi-selection support
MARQSTYLE\_HIGHLWIN7ConstantWindows 7/10 gradient bar style

7.2 LINESTYLE\_\* — Divider Line Style

ConstantTypeDescription and Usage
LINESTYLE\_NONE (0)ConstantNo divider lines
LINESTYLE\_BLACK (1)ConstantBlack lines
LINESTYLE\_DARKGRAY (2)ConstantDark gray lines
LINESTYLE\_FORECOLOR (3)ConstantLines in the browse text color
LINESTYLE\_LIGHTGRAY (4)ConstantLight gray lines
LINESTYLE\_INSET (5)ConstantInset-style lines (sunken)
LINESTYLE\_RAISED (6)ConstantRaised-style lines

7.3 STRETCHCOL\_\* — Elastic Column

ConstantTypeDescription and Usage
STRETCHCOL\_NONEConstantNo elastic column
STRETCHCOL\_LASTConstantLast column fills remaining space
STRETCHCOL\_WIDESTConstantWidest column stretches
nCreationOrderNumericThe nCreationOrder of a specific column can also be used

7.4 EDIT\_\* — Editor Types

ConstantTypeDescription and Usage
EDIT\_NONE (0)ConstantNo editing
EDIT\_GET (1)ConstantStandard GET (text box)
EDIT\_LISTBOXConstantDrop-down listbox
EDIT\_GET\_LISTBOXConstantGET combined with listbox
EDIT\_BUTTONConstantAction button beside the GET
EDIT\_GET\_BUTTONConstantGET combined with button
TYPE\_IMAGEConstantEditable image in the cell

7.5 AGGR\_\* — Footer Aggregate Types

ConstantTypeDescription and Usage
AGGR\_TOTAL / AGGR\_SUMConstantSum of all column values
AGGR\_AVERAGE / AGGR\_AVGConstantAverage of values
AGGR\_MAXConstantMaximum value
AGGR\_MINConstantMinimum value
AGGR\_COUNTConstantRecord count
AGGR\_STDEVConstantStandard deviation
AGGR\_STDEVPConstantPopulation standard deviation

7.6 AL\_\* — Alignment

ConstantTypeDescription and Usage
AL\_LEFTConstantLeft alignment
AL\_CENTERConstantCenter alignment
AL\_RIGHTConstantRight alignment

8\. Complete Examples

8.1 Basic browse over DBF

@ 0,0 XBROWSE oBrw OF oWnd ALIAS 'CUSTOMER' AUTOCOLS LINES CELL

oBrw:nMarqueeStyle := MARQSTYLE\_HIGHLROW

oBrw:nRowDividerStyle := LINESTYLE\_BLACK

oBrw:CreateFromCode()

oWnd:oClient := oBrw

8.2 Browse over Array with editing

@ 0,0 XBROWSE oBrw OF oDlg ARRAY aData AUTOCOLS LINES CELL FASTEDIT

oBrw:lHScroll := .F.

oBrw:lVScroll := .F.

AEval( oBrw:aCols, {|o| o:nEditType := EDIT\_GET} )

oBrw:CreateFromCode()

8.3 Browse with dynamic colors

oBrw:bClrStd := {|| {CLR\_WHITE, iif(Field-\>Married, CLR\_RED, CLR\_GREEN)} }

oBrw:aCols\[10\]:bClrStd := {|| {iif(Field-\>Salary\>100000, CLR\_HRED, CLR\_HBLUE), CLR\_GRAY}}

8.4 Browse with footer and totals

WITH OBJECT oBrw:Salary

:nFooterType := AGGR\_TOTAL

:bLClickFooter := {|r,c,f,o| FooterAggrClick(r,c,f,o)}

END

oBrw:lFooter := .T.

oBrw:MakeTotals()

oBrw:CreateFromCode()

8.5 Multi-selection with Windows 7 style

oBrw:nMarqueeStyle := MARQSTYLE\_HIGHLWIN7

WITH OBJECT oBrw:InsCol( 1 )

:cHeader := " "

:bEditValue := {|| If(AScan(oBrw:aSelected, oBrw:BookMark)\>0, .T., nil)}

:SetCheck()

:nHeadBmpNo := {|| If(Len(oBrw:aSelected)==oBrw:nLen, 1, 2)}

:bLClickHeader := {|r,c,f,oCol| If(Len(oBrw:aSelected)==oBrw:nLen, ;

  oBrw:SelectNone(), oBrw:SelectAll())}

END

8.6 Group Headers with bold font

DEFINE FONT oBold NAME 'VERDANA' SIZE 0,-14 BOLD

oBrw:SetGroupHeader( 'EMPLOYEE' \+ CRLF \+ 'NAME', 1, 2, oBold )

oBrw:SetGroupHeader( 'ADDRESS', 3, 6, oBold )

oBrw:SetGroupHeader( 'OTHER', 8, 9, oBold )

oBrw:lAllowColReGroup := .T.

8.7 Image with alpha transparency

oBrw:aCols\[ 1 \]:nEditType := TYPE\_IMAGE

oBrw:aCols\[ 1 \]:lBmpStretch := .F.

oBrw:aCols\[ 1 \]:lBmpTransparent := .T.

oBrw:aCols\[ 1 \]:bStrImage := {|oCol, oBrw| oBrw:aRow\[ 2 \]}

oBrw:aCols\[ 1 \]:nDataBmpAlign := AL\_CENTER

oBrw:aCols\[ 1 \]:bAlphaLevel := {|o| o:oBrw:aRow\[ 3 \]}

8.8 Cell tooltip

oBrw:bCellToolTips := {|oCol| {oCol:Value, oCol:cHeader}}

oBrw:aCols\[1\]:bCellToolTip := {|oCol| TRIM(FIELD-\>FIRST) \+ CRLF \+ TRIM(FIELD-\>LAST)}

8.9 Cell merging (bExtend)

WITH OBJECT :aCols\[ 1 \]

:bExtend := {|o| If(o:oBrw:aRow\[1\]==0, 2, 0)} // extends 2 cols if subtotal

:bDataStrAlign := {|o| If(o:oBrw:aRow\[1\]==0, AL\_CENTER, AL\_LEFT)}

:bClrStd := {|| {CLR\_BLACK, If(oBrw:aRow\[1\]==0, CLR\_YELLOW, CLR\_WHITE)}}

END

8.10 Browse with gradient background

local aGrad := {{ .5, CLR\_BLUE, RGB(202,202,255) }, { .5, RGB(202,202,255), CLR\_BLUE }}

@ 10,10 XBROWSE oBrw ... BACKGROUND aGrad VERTICAL

// Or dynamically:

oBrw:SetBackGround( aGrad, .T. ) // .T. \= vertical

oBrw:SetBackGround( "PAPER" ) // Image resource

oBrw:SetBackGround() // Clear background

regards, saludos

Antonio Linares
www.fivetechsoft.com
Posts: 44158
Joined: Thu Oct 06, 2005 05:47 PM
Re: Manual TXBrowse
Posted: Mon Mar 09, 2026 05:27 PM

9\. Recommended Usage Pattern

The following is the typical order for configuring an XBrowse completely and correctly:

  1. 1\. Define the data source (ALIAS, ARRAY, RECSET, OBJECT)

  2. 2\. Create the browse with @ X,Y XBROWSE ... or TXBrowse():New()

  3. 3\. Configure browse properties (styles, colors, marquee, scroll)

  4. 4\. Configure column properties (headers, editing, colors, bitmaps)

  5. 5\. Define group headers if applicable (SetGroupHeader)

  6. 6\. Call MakeTotals() if there are footers with aggregates

  7. 7\. Call CreateFromCode() — ALWAYS the last step

  8. 8\. Assign oWnd:oClient := oBrw (for windows)

  9. 9\. Activate the window or dialog with ON INIT oBrw:SetFocus()

📌 NOTE: CreateFromCode() MUST always be the last configuration call. Any property or method called after CreateFromCode() may have no effect.

10\. Advanced Record Selector

The record selector (the left gray column) can be fully customized to show row numbers, names, icons, and context menus.

10.1 Record Selector Properties

Property / EventTypeDescription and Usage
bRecSelDataBlockContent of the selector cell. {brwbrw:KeyNo} shows sequential number
bRecSelHeaderString/BlockSelector header. Ex: oBrw:bRecSelHeader := "SlNo"
bRecSelFooterString/BlockSelector footer. {brwbrw:nLen} shows total records
nRecSelWidthNumeric/StringSelector width. If string, used as model: "9999" → width for 4 digits
nRecSelHeadBmpNoNumeric/String/ArrayBitmap in selector header. Can be path, number, or line descriptor
bRecSelClickBlockClick on selector header. {RecSelPopUp(oBrw)}
SetRecSelBmp(xBmp)MethodSets custom bitmap in selector. nil=default, 0=no bitmap, cFile=image
lRecordSelectorLogicalShows/hides entire selector. Default: .T.
RecSelShowRecNo()MethodDisplays the record number in the selector (convenient shortcut)
SetChecks()MethodConfigures all logical fields as checkboxes in the browse
SetMultiSelectCol()MethodAdds automatic multi-selection checkbox column
oMultiSelColObjectReference to the multi-selection column created by SetMultiSelectCol()
SelectRow()MethodReturns .T. if the current row is selected (for use with bSumCondition)
oRightColObjectColumn frozen on the RIGHT. Ex: oBrw:oRightCol := oBrw:Salary
KeyNoNumericSequential number of the current row (read property of the browse)

Example: Selector with row number

WITH OBJECT oBrw

:bRecSelData := { |brw| brw:KeyNo }

:bRecSelFooter := { |brw| brw:nLen }

:bRecSelHeader := "SlNo"

:nRecSelWidth := "9999"

END

Example: Selector with region name (Array)

WITH OBJECT oBrw

:bRecSelData := { |brw| brw:aRow\[ 1 \] } // name in col 1

:bRecSelFooter := "Totals"

:bRecSelHeader := "Region"

:nRecSelWidth := "Americas" // width for the longest text

END

Example: Multi-selection with conditional totals

WITH OBJECT oBrw

:SetMultiSelectCol()

:bClrStd := { || { CLR\_BLACK, If( oBrw:SelectRow(), 0x88EDFB, CLR\_WHITE ) } }

:Salary:bSumCondition := { || oBrw:SelectRow() }

:Salary:nFooterType := AGGR\_SUM

:MakeTotals()

END

11\. GetBar and Incremental Filter

11.1 GetBar — Gets below headers

Allows displaying input fields directly below column headers to filter the browse in real time.

Property / EventTypeDescription and Usage
lGetBarLogicalActivates/deactivates the GETs bar below headers. Ex: oBrw:lGetBar := .T.
uBarGetValVariousInitial value of the column GET. Ex: oCol:uBarGetVal := Space(10)
cBarGetPicStringMask of the GET in the bar. Ex: oCol:cBarGetPic := NumPict(FieldLen(n), FieldDec(n))
bClrEditsBlockColor of bar GETs. {{CLR\_BLACK, CLR\_YELLOW}}
oHeaderFontsObjectFont for headers. Ex: oBrw:oHeaderFonts := oBold
AutoFit()MethodAutomatically adjusts column width to content

11.2 Incremental Filter

Allows filtering the browse while the user types, without needing to press Enter.

Property / EventTypeDescription and Usage
lIncrFilterLogicalActivates real-time incremental filter. Ex: oBrw:lIncrFilter := .T.
lSeekWildLogicalIf .T., filters by content (contains). If .F., filters by beginning (starts with)
cFilterFldStringName of the field to filter. Ex: oBrw:cFilterFld := "FIRST"
cSeekStringCurrent search text (read)
oSeekSAY ObjectSAY control showing current search text
Seek(cText)MethodExecutes the search. Ex: oBrw:Seek("") to clear

12\. Internal Button Bar (nTopBarHeight / bOnAdjust)

XBrowse allows embedding a button bar directly inside the browse itself, above the data, without needing an external ButtonBar.

Property / EventTypeDescription and Usage
nTopBarHeightNumericHeight in pixels of the internal bar. Ex: oBrw:nTopBarHeight := 30
bOnAdjustBlockBlock executed when creating/adjusting the browse. Internal buttons are created here
EditSource(\[lNew\])MethodOpens editor for current record. lNew=.T. for new. Alias of Edit()

Complete example

oBrw:nTopBarHeight := 30

oBrw:bOnAdjust := \<||

local oBtn

@ 05,05 BTNBMP oBtn FILE "new.bmp" SIZE 30,20 PIXEL OF oBrw NOBORDER ;

  ACTION oBrw:EditSource( .T. ) TOOLTIP "Add"

@ 05,45 BTNBMP oBtn FILE "edit.bmp" SIZE 30,20 PIXEL OF oBrw NOBORDER ;

  ACTION oBrw:EditSource() TOOLTIP "Edit"

@ 05,85 BTNBMP oBtn FILE "delete.bmp" SIZE 30,20 PIXEL OF oBrw NOBORDER ;

  ACTION oBrw:Delete() TOOLTIP "Delete"

return nil

\>

13\. Fonts and Colors per Line (Advanced Multiline)

XBrowse allows assigning different fonts and colors to each line of text within a multiline cell, using the aDataFont and aClrText properties of the column.

Property / EventTypeDescription and Usage
aDataFontArray of fontsArray of font objects per line. Line N uses aDataFont\[N\]. Ex: oCols\[1\]:aDataFont := {oFont1, oFont2}
aClrTextArray of colorsArray of text colors per line. nil \= default color. Ex: {CLR\_HBLUE, CLR\_HRED}
nDataStrAlignNumericCan combine AL\_CENTER \+ AL\_BOTTOM for vertical+horizontal alignment
aImgRectArrayImage crop in cell: {nTop%, nLeft%, nBottom%, nRight%, cShape}. Shape: "CIRCLE", nil=rect
lFitGridHeightLogicalAdjusts browse height to fit exactly N complete rows
nHeadStrAlignsNumericAlignment of ALL headers at once (browse property)
nWidthsArray/NumericIf array, sets individual widths: {200, 250, 150}. If numeric, uniform width

Example: different fonts and colors per line

DEFINE FONT aFont1\[ 1 \] NAME "VIVALDI" SIZE 0,-30

DEFINE FONT aFont1\[ 2 \] NAME "Verdana" SIZE 0,-20

WITH OBJECT oBrw:Name

:aDataFont := aFont1

:aClrText := { CLR\_HBLUE, CLR\_HRED }

END

Example: image cropped in circular shape

WITH OBJECT oBrw:aCols\[ 3 \]

:bStrImage := { || "c:\\\\images\\\\photo.jpg" }

:aImgRect := { nil, 0.3, 0.7, nil, "CIRCLE" }

// nil \= full edge, 0.3 \= 30% from left, 0.7 \= 70% from left

END

14\. Inheritance — Derived Classes from TXBrowse

It is possible to create classes derived from TXBrowse and TXBrwColumn to customize behavior at the class level, automatically applying changes to all browses of the same type.

14.1 Creating a derived class from TXBrowse

CLASS MyBrowse FROM TXBrowse

CLASSDATA lRegistered AS LOGICAL // MANDATORY

DATA bColClass INIT { || MyXBrCol() } // own column class

METHOD New( oWnd ) CONSTRUCTOR

ENDCLASS

METHOD New( oWnd ) CLASS MyBrowse

Super:New( oWnd )

::nMarqueeStyle := MARQSTYLE\_HIGHLROWMS

::bClrStd := { || { CLR\_BLACK, RGB(255,255,206) } }

::bClrSelFocus := { || { CLR\_WHITE, CLR\_BLUE } }

::bClrRowFocus := { || { CLR\_BLACK, RGB(150,231,255) } }

return Self

14.2 Derived class from TXBrwColumn

CLASS MyXbrCol FROM TXBrwColumn

METHOD Adjust()

ENDCLASS

METHOD Adjust() CLASS MyXBrCol

if ::cDataType \== 'D'

  ::cEditPicture := 'dd-mmm-yyyy'

endif

Super:Adjust()

return Self

14.3 Activating the derived class

Property / EventTypeDescription and Usage
CLASS MyBrowse() in commandClause@ X,Y XBROWSE oBrw CLASS MyBrowse() ... — only that browse uses the class
SET XBROWSE TO MyBrowse()CommandAll browses created from here use MyBrowse()
SET XBROWSE TO bXBrCommandRestores the previous class (saved with SAVE PREVIOUS TO bXBr)
SetXBrowse({MyBrowse() })FunctionProgrammatic equivalent of SET XBROWSE TO
lRegisteredCLASSDATAMANDATORY in derived classes. Declares the class as registered in FWH
bColClassDATABlock that instantiates the column class. INIT {TXBrwColumn() } by default
cDataTypeStringColumn data type: 'C', 'N', 'D', 'L', 'M', 'F' (image)

Example with SAVE PREVIOUS

SET XBROWSE TO MyBrowse() SAVE PREVIOUS TO bXBr

// ... create browses that will use MyBrowse ...

SET XBROWSE TO bXBr // restore original class

15\. Group Totals (SetGroupTotal)

In addition to group headers, it is possible to show automatic totals per group and a consolidated grand total.

Property / EventTypeDescription and Usage
SetGroupTotal(cGrp, cHdr)MethodAdds a total row for a group. cGrp \= group name, cHdr \= header text
SetGroupTotal(aGrps, cHdr, nAggr, oFont)MethodGrand total of multiple groups. nAggr \= AGGR\_SUM (default)
nFooterTypesNumericAggregate type for ALL numeric columns at once
RefreshFooters()MethodRefreshes all column footers
bOnChangeBlockColumn event when value changes. {oBrw:MakeTotals(), oBrw:RefreshFooters()}
lAllowColReGroupLogicalAllows moving columns between groups. Ex: := .T.

Complete example

:SetGroupHeader( 'Americas', 2, 3, oBold )

:SetGroupHeader( 'Europe', 4, 5, oBold )

:lAllowColReGroup := .T.

:SetGroupTotal( 'Americas', 'Total' )

:SetGroupTotal( 'Europe', 'Total' )

:SetGroupTotal( { 'Americas\_Total', 'Europe\_Total' }, 'Grand' \+ CRLF \+ 'Total', AGGR\_SUM, oBold )

AEval( oBrw:aCols, { |o| o:bOnChange := { || oBrw:MakeTotals(), oBrw:RefreshFooters() } }, 2 )

16\. Cell Movement Control (nMoveType)

The nMoveType property controls how the cursor moves when pressing Enter or Tab after editing a cell.

Property / EventTypeDescription and Usage
nMoveTypeNumericMovement direction when confirming edit. See MOVE\_\* constants
MOVE\_RIGHTConstantMoves cursor to the right cell (default for editing)
MOVE\_LEFTConstantMoves cursor to the left cell
MOVE\_UPConstantMoves cursor to the cell above
MOVE\_DOWNConstantMoves cursor to the cell below
MOVE\_NONEConstantDoes not move cursor when confirming
MOVE\_FAST\_RIGHTConstantSame as MOVE\_RIGHT but with fast behavior
MOVE\_FAST\_LEFTConstantSame as MOVE\_LEFT but with fast behavior
nRowSelNumericCurrently selected row number (visible)
nColSelNumericCurrently selected column number
lColChangeNotifyLogicalIf .T., fires bChange also when changing columns
lRelyOnKeyNoLogicalIf .F., uses physical position instead of KeyNo for positioning

Example

oBrw:nMoveType := MOVE\_RIGHT // on confirm, go right

// or dynamically:

oBrw:nMoveType := MOVE\_DOWN // spreadsheet-style behavior

17\. Additional Properties and Advanced Techniques

17.1 Text Highlighting (FW\_SayTextHilite)

Allows highlighting specific words within cell text with a different font and color, using bPaintText.

oBrw:aCols\[ 2 \]:bPaintText := {|oCol, hDC, cText, aRect, aColors|

FW\_SayTextHilite( hDC, cText, aRect, oFont, aColors\[1\], aColors\[2\],

  { { AllTrim(cWordHL), oBold, CLR\_HRED, CLR\_HGREEN } } )

return nil

}

📌 NOTE: FW\_SayTextHilite takes an array of {cWord, oFont, nTextClr, nBkgClr} for each word to highlight.

17.2 DropFile — Dragging files onto the browse

Property / EventTypeDescription and Usage
DropFile(nRow, nCol, cFile)MethodHandles dropping a file onto a specific browse cell
lCanPasteLogicalEnables the paste option (Ctrl+V) in the browse. Ex: oBrw:lCanPaste := .T.

17.3 Source Code Generation (PrgCode)

Property / EventTypeDescription and Usage
PrgCode()MethodGenerates the PRG source code of the current browse. Returns array of 4 elements with different styles
RptCode()Method (column)Generates report code for the column
cColStringOriginal field name of the column (for code generation)

17.4 Navigation Methods (bGoTop, bGoBottom, bSkip)

Property / EventTypeDescription and Usage
bGoTopBlockBlock to go to the first record. Ex: := {::nArrayAt := 1 }
bGoBottomBlockBlock to go to the last record
bSkipBlockBlock to skip N records. Receives nSkip, returns records actually skipped
bEofBlockBlock that indicates end of data. Ex: := {::nArrayAt \> ::nRows }
bKeyCountBlockBlock that returns total records. Ex: := {::nRows }
bKeyNoBlockBlock to get/set the current position (KeyNo)
bBookMarkBlockBlock to get/set the current record bookmark
GoLeft(), GoRight()MethodsNavigate to left/right column. Overridable in derived classes
GoUp(\[n\]), GoDown(\[n\])MethodsNavigate rows up/down. Overridable
GetDisplayColsWidth()MethodReturns total width of visible columns
BrwWidth()MethodReturns the width of the browse data area
aCellCoor()MethodReturns coordinates {nTop,nLeft,nBottom,nRight} of active cell
SetHScroll(l)MethodShows/hides horizontal scrollbar. Returns the new state
lAdjustedLogicalIndicates if CreateFromCode() has already been called (.T. after creation)

18\. Progress Bars in Cells (SetProgBar)

XBrowse allows displaying a progress bar directly within a numeric cell, visualizing the value as a percentage of a given maximum. Ideal for dashboards and queued processes.

Property / EventTypeDescription and Usage
SetProgBar(uMax, nHeight, bClr)Method (col)Activates progress bar. uMax=max value (number or block), nHeight=bar height (nil=auto), bClr=block {nFill, nBack}
uMax as blockBlock{nMaxSal } — maximum is dynamically recalculated on each paint
uMax as numberNumeric100 — fixed percentage, cell value taken as % of 100
RefreshCurrent()MethodRefreshes only current row. Much more efficient than Refresh() in ongoing processes
CargoVariousGeneral-purpose property. Ex: oBrw:Cargo := .F. for cancellation signal
bClrSelBlockSelected row color without focus. := :bClrSelFocus to equalize both states
lDisplayZerosLogicalIf .F., cells with value 0 are displayed empty. Useful at start of progress bars

19\. Advanced Painting (bPaintRow / bPaintHeader / bPaintFooter)

XBrowse exposes painting hooks at the row, header, and full footer level, allowing full visual control using GDI.

19.1 bPaintRow — Painting complete rows

Property / EventTypeDescription and Usage
bPaintRowBlock{brw,nRow,nCol,nHt,lHL,lSel,nRowPos,nColSel,oColSel... } — row painting hook
Return .T.LogicalIf returns .T., XBrowse does not paint that row (the block painted it completely)
Return .F.LogicalIf returns .F., XBrowse will paint normally over the block's work
GetDC()MethodGets the Device Context of the browse for GDI drawing
ReleaseDC()MethodReleases the DC obtained with GetDC()
SayText(cText,aRect,cAlign,oFont,nClr)MethodDraws text with the internal browse DC
ReadImage(cFile)MethodLoads image from file. Returns handle
DrawImage(aBmp, aRect)MethodDraws an image in the indicated rectangle
lDrawBorderLogicalIf .T., draws border around the browse
nColorBoxNumericMarquee border color. Ex: oBrw:nColorBox := CLR\_HRED
lHoverSelectLogicalIf .T., selects the record when hovering the mouse (without clicking)
AddVar(cName, xVal)MethodAdds variable accessible within blocks as ::cName
oFontObjectBrowse font. Accessible from TDataRow: oRow:oBrw:oFont

19.2 bPaintHeader and bPaintFooter

Property / EventTypeDescription and Usage
bPaintHeaderBlock{brw,hDC,aCols,nLast,hWPen,hGPen,hCPenBrwHeader(...) } — paints the complete header
bPaintFooterBlock{brw,hDC,aCols,nLast,nGridW,nBrwH,hWPen,hGPenBrwFooter(...) } — paints the complete footer
oCol:PaintHeader(nRow,nil,nHt,lSel,hDC)Method (col)Paints standard header of ONE column within the custom hook
oCol:PaintFooter(nRow,nil,nHt)Method (col)Paints standard footer of ONE column
oCol:PaintData(nRow,nil,nHt,lHL,lSel,n,nPos)Method (col)Paints data cell of ONE column — useful in bPaintRow
oCol:nDisplayColNumericLeft X position of the column (px from browse left edge)
lAllowColSwappingLogicalIf .F., prevents reordering columns by dragging the header

20\. Advanced Editing

20.1 EDIT\_BUTTON — Custom popup editor

Property / EventTypeDescription and Usage
nEditType := EDIT\_BUTTONConstant (col)Shows button in cell when entering edit mode
bEditBlockBlock (col){nRow, nCol, oColEditFunc(nRow,nCol,oCol) } — invoked on button click
bOnPostEditBlock (col){oCol, xVal, nKey... } — post-edit. xVal=new value, nKey=confirm key
EDIT\_LISTBOXConstant (col)Shows a drop-down listbox as cell editor
aEditListTxtArray (col)Items for EDIT\_LISTBOX: { {1,'one',10}, {2,'two',20} }
nLbxAtNumeric (col)Index of current selection in aEditListTxt (read-only useful in bOnChange)
bClrEditBlock (col)Edit color for ONE column: {{ CLR\_BLACK, CLR\_YELLOW } }
bClrEditsBlock (browse)Edit color for ALL browse columns
bOnChangeBlock (col)Executed when value changes during editing of that column
bOnChangesBlock (browse)Executed when any column changes. Global for the entire browse

20.2 CurrentRow() — Editing in independent dialog

Property / EventTypeDescription and Usage
CurrentRow()MethodReturns TDataRow object of the current row. Fields accessible as oRow:First, oRow:Salary
oRow:Modified()MethodReturns .T. if there are unsaved changes
oRow:Save()MethodSaves TDataRow changes to the original source
oRow:Undo()MethodDiscards pending changes
oRow:oBrwObjectReference to the parent browse. Ex: oRow:oBrw:oFont, oRow:oBrw:Age:cEditPicture
ON DBLCLICKClause@ X,Y XBROWSE ... ON DBLCLICK RowEdit( oBrw:CurrentRow() )
DATABASE oObjCommandCreates a TDatabase object from the active area
SelectCol(nPos, lCenter)MethodMoves focus to column. lCenter=.T. centers the column in view

21\. Sort Combo (oSortCbx / cSortOrder)

XBrowse can be automatically linked to an external ComboBox so the user can change the display order without additional code.

Property / EventTypeDescription and Usage
oSortCbxObjectReference to an external ComboBox. XBrowse fills it with available indexes and changes order on selection
cSortOrderStringName of the active order. Can be bound to the ComboBox VAR
AUTOSORTClauseEnables sorting by clicking on the column header
nColorBoxNumericSelection box color (MARQSTYLE\_SOLIDCELL style). Ex: CLR\_HRED
cHeadersArrayArray of headers assigned via code. Ex: oBrw:cHeaders := { "Name", "Last Name" }
lExcelCellWiseLogicalIf .T., the Excel export maintains cell-by-cell structure

22\. Swapping Browses, SetRDD and TPages

22.1 Showing/hiding alternate browses

Property / EventTypeDescription and Usage
Hide()MethodHides the browse without destroying it
Show()MethodShows a hidden browse
Enable()MethodEnables the browse for user interaction
Disable()MethodDisables the browse (no keyboard/mouse response)
SetRDD()MethodChanges the RDD data source to the active area at that moment. Ex: Customer-\>( oBrw:SetRDD() )
REDEFINE XBROWSECommandLinks browse from a resource to an object. Ex: REDEFINE XBROWSE oBrw ID 10 OF oDlg

Example: swap with tabs

aBrw\[1\]:CreateFromCode() ; aBrw\[2\]:CreateFromCode()

aBrw\[2\]:Hide() // hide at start

static function ChangeBrw( nNew, nOld, aBrw )

aBrw\[ nOld \]:Hide()

aBrw\[ nNew \]:oWnd:oClient := aBrw\[ nNew \]

aBrw\[ nNew \]:Enable() ; aBrw\[ nNew \]:Show() ; aBrw\[ nNew \]:oWnd:Resize()

return nil

22.2 Browse as page selector (TPages)

@ 10,20 XBROWSE oXBrw DATASOURCE { "First", "Second" } AUTOCOLS HEADERS "Page" NOBORDER

oXBrw:bChange := { || oPages:SetOption( oXBrw:BookMark ) }

oXBrw:CreateFromCode()

oPages := TPages():New( 10, 200, 380, 580, oDlg )

23\. Gradient in Selected Rows

XBrowse supports gradient arrays in selection color blocks, creating Office/Vista-style visual effects.

Property / EventTypeDescription and Usage
bClrSelFocus with aGradBlock{{ CLR\_BLACK, aSelGrad } } — gradient in focused row
bClrRowFocus with aGradBlock{{ CLR\_BLACK, aRowGrad } } — gradient in visible rows without focus
aRowGrad (example)Array{ {.5, RGB(232,241,252), RGB(232,241,252)}, {.5, RGB(210,225,244), RGB(235,243,253)} }
aSelGrad (example)Array{ {.5, RGB(255,255,251), RGB(255,237,178)}, {.5, RGB(255,218,103), RGB(255,233,162)} }

24\. Advanced Images — Image \+ Text and SetColsAsRows

24.1 Image and text in the same cell

Property / EventTypeDescription and Usage
aImgRect := { nil,nil,-40,nil }ArrayReserves 40px at the bottom for text. The image occupies the rest
aImgRect := "CIRCLE"StringCircular-shaped image centered in cell
aImgRect := "ELLIPSE"StringElliptical-shaped image
nCellHeightNumeric (col)Height dedicated to this cell within a multiline row (with SetColsAsRows)
SetColsAsRows(aColNos)Method (col)Stacks columns in the same visual cell in separate rows. Ex: :SetColsAsRows( {2,3} )
oDataFontObject (col)Font for the data text of an individual column
nDataStrAlign := AL\_TOPNumericAligns text to the top of cell
nDataStrAlign := AL\_BOTTOMNumericAligns text to the bottom (useful with image above)

25\. Miscellaneous: UTF-8, Excel, Synchronized DBF Structure

25.1 UTF-8 Support

Property / EventTypeDescription and Usage
UTF8TOUTF16(field)ExpressionConverts UTF-8 text to UTF-16 for correct display in XBrowse
lExcelCellWiseLogicaloBrw:lExcelCellWise := .T. — cell-by-cell Excel export
SetFont(oFont)MethodAssigns Unicode font to the browse. Ex: "Segoe UI" for Unicode languages
nWidths as numberNumericoBrw:nWidths := 230 — same width for all columns

25.2 Excel sheet browse (oRange)

oRange := GetExcelRange( cFile, "Customers", "A1:E12" )

@ 0,0 XBROWSE oBrw OF oWnd AUTOCOLS DATASOURCE oRange CELL LINES FOOTERS

oBrw:Sales:bFooter := { || oRange:Application:WorkSheetFunction:Sum( oRange:Columns(5) ) }

26\. Insertable Dynamic Subtotals (Array)

It is possible to insert subtotal rows within an array browse, calculated via blocks that are automatically re-evaluated when the user edits data.

Property / EventTypeDescription and Usage
IsTotalRow(aRow)Own functionDetects if current row is a subtotal. Ex: Empty( aRow\[1\] ) → is total row
bEditWhenBlock (col){\!IsTotalRow( oBrw:aRow ) } — disables editing in subtotal rows
bSumConditionBlock (col){n,o\!IsTotalRow( o:oBrw:aRow ) } — excludes subtotal rows from footer total
bEditValue with blockBlock (col)If array value is a block ('{...}'), it is evaluated with XEval(). Useful for dynamic subtotals
MakeSumBlock(aData,nCol,nFrom,nLast)Own functionCreates a block {FW\_ArrSum(...) } that dynamically sums the indicated range
AIns(aData, nPos, xVal, .T.)FunctionInserts an element at position nPos of the array, shifting others
FW\_ArrSum(aData, nCol)FWH FunctionSums the values of column nCol from array aData

27\. Transparent Watermark (bPaintBack / lTransparent)

XBrowse allows drawing an image as a semi-transparent watermark behind the data, using the bPaintBack hook and the lTransparent property.

Property / EventTypeDescription and Usage
lTransparentLogicalIf .T., the browse uses transparent background (bPaintBack hook controls the background)
bPaintBackBlock{Self... } — background painting hook. Self \= the browse. Must paint background and maintain lTransparent := .T.
hDCHandle (internal)::hDC — browse Device Context accessible inside bPaintBack
oBrush:hBrushHandle::oBrush:hBrush — browse background brush handle
DataRect():aRectArrayBrowse data area rectangle. Useful for scaling the watermark image
DrawImage(aImage, aRect, nil, nil, nAlpha)MethodDraws image with alpha transparency level (0=opaque, 255=invisible). Ex: nAlpha=64
oWnd:ReadImage(cFile,,lAlpha)MethodReads image with alpha support (.T.). Returns handle for use with DrawImage
PalBmpFree(aImage)FunctionFrees memory of image loaded with ReadImage

28\. Advanced XBROWSER: CALC, Internal Buttons and SETUP

The XBROWSER command has additional options for displaying quick-start browses with extended functionality.

Property / EventTypeDescription and Usage
XBROWSER aData CALCCommandOpens XBROWSER with a built-in editable spreadsheet (calculator mode)
XBROWSER aData COLUMNS {1,2,3}CommandShows only the indicated columns
XBROWSER ... SETUP codeblockCommandExecutes a code block after creating the browse. oBrw available as variable
BUTTON\_PRINTConstantIndex of the print button in the XBROWSER bar. oBrw:oWnd:aControls\[BUTTON\_PRINT\]
BUTTON\_SHEETConstantIndex of the sheet/export button in the XBROWSER bar
oBtn:cCaptionStringChanges the button text
oBtn:bActionBlockChanges the button action

29\. Exporting Selected Records to Excel (aSelected)

XBrowse allows exporting to Excel only a subset of records by specifying an array of record numbers in the aSelected property before calling ToExcel().

Property / EventTypeDescription and Usage
aSelectedArrayArray of RecNos to export. Ex: oBrw:aSelected := { 10, 25, 30 }. Must be cleared after ToExcel()
ToExcel()MethodExports browse data to Excel. If aSelected is not empty, exports only those records
DBEVAL(bBlock, bCond)FunctionTraverses records of the active area evaluating bBlock only when bCond is .T.
cAliasStringAlias of the RDD data source of the browse. Ex: (oBrw:cAlias)-\>( DBEVAL(...) )

Example: export only records from State X

// 1\. Build array of RecNos that meet the condition

local aRecNo := {}

local bCondi := { || (oBrw:cAlias)-\>STATE \== cState }

(oBrw:cAlias)-\>( DBEVAL( { || AAdd( aRecNo, RECNO() ) }, bCondi ) )

// 2\. Position on first matching record and refresh

(oBrw:cAlias)-\>( DBSeek( cState, .T. ) )

oBrw:Refresh()

// 3\. Assign, export and clear

oBrw:aSelected := aRecNo

oBrw:ToExcel()

oBrw:aSelected := {}

Appendix A — Complete Reference Examples

This section contains complete, functional examples extracted directly from the FiveWin/XBrowse example files. They are the most direct reference for implementing each feature.

A.1 Basic browse with RDD, editing and footer (testxbr3.prg)

\#include 'fivewin.ch'

\#include 'xbrowse.ch'

USE CUSTOMER NEW ALIAS CUST SHARED VIA "DBFCDX"

SET ORDER TO TAG FIRST

GO TOP

DEFINE FONT oFont NAME "TAHOMA" SIZE 0,-12

DEFINE DIALOG oDlg SIZE 700,400 PIXEL FONT oFont TITLE "XBrowse RDD"

@ 10,10 XBROWSE oBrw SIZE \-10,-10 PIXEL OF oDlg ;

DATASOURCE "CUST" AUTOCOLS AUTOSORT ;

CELL LINES NOBORDER FOOTERS

WITH OBJECT oBrw

:nEditTypes := EDIT\_GET

:Married:SetCheck()

:Salary:nFooterType := AGGR\_SUM

:nStretchCol := STRETCHCOL\_WIDEST

:MakeTotals()

:CreateFromCode()

END

ACTIVATE DIALOG oDlg CENTERED ON INIT ( CUST-\>(dbGoTop()), oBrw:SetFocus(), .F. )

A.2 Array browse with internal button bar (xbrbar.prg)

@ 20,20 XBROWSE oBrw SIZE \-20,200 PIXEL OF oDlg ;

DATASOURCE "STATES" AUTOCOLS CELL LINES NOBORDER

oBrw:nTopBarHeight := 30

oBrw:bOnAdjust := \<||

@ 05,05 BTNBMP oBtn FILE "new.bmp" SIZE 30,20 PIXEL OF oBrw NOBORDER ;

  ACTION oBrw:EditSource( .T. ) TOOLTIP "Add"

@ 05,45 BTNBMP oBtn FILE "edit.bmp" SIZE 30,20 PIXEL OF oBrw NOBORDER ;

  ACTION oBrw:EditSource() TOOLTIP "Edit"

@ 05,85 BTNBMP oBtn FILE "delete.bmp" SIZE 30,20 PIXEL OF oBrw NOBORDER ;

  ACTION oBrw:Delete() TOOLTIP "Delete"

return nil

\>

oBrw:nEditTypes := EDIT\_GET

oBrw:CreateFromCode()

A.3 Record selector with row number and popup (xbrecsel.prg)

WITH OBJECT oBrw

:nHeaderHeight := 60

:SetChecks()

:bRecSelData := { |brw| brw:KeyNo }

:bRecSelFooter := { |brw| brw:nLen }

:bRecSelHeader := "SlNo"

:bRecSelClick := { || RecSelPopUp( oBrw ) }

:nRecSelWidth := "9999"

:AutoFit()

:CreateFromCode()

END

A.4 Group totals with grand total (xbgrpsum.prg)

WITH OBJECT oBrw

:SetGroupHeader( 'Americas', 2, 3, oBold )

:SetGroupHeader( 'Europe', 4, 5, oBold )

:lAllowColReGroup := .T.

:SetGroupTotal( 'Americas', 'Total' )

:SetGroupTotal( 'Europe', 'Total' )

:SetGroupTotal( { 'Americas\_Total', 'Europe\_Total' }, 'Grand' \+ CRLF \+ 'Total', AGGR\_SUM, oBold )

END

AEval( oBrw:aCols, { |o|

o:cEditPicture := '99,999.99'

o:nFooterType := AGGR\_SUM

o:bOnChange := { || oBrw:MakeTotals(), oBrw:RefreshFooters() } }, 2 )

oBrw:MakeTotals()

oBrw:CreateFromCode()

A.5 Incremental filter with wildcard (xbincflt.prg)

WITH OBJECT oBrw

:lIncrFilter := .T.

:lSeekWild := .T. // search 'contains'

:cFilterFld := "FIRST"

:nStretchCol := STRETCHCOL\_WIDEST

END

@ 10,10 COMBOBOX oBrw:cFilterFld ITEMS aHdrs ;

ON CHANGE ( oBrw:Seek(""), oBrw:SetFocus() )

@ 10,70 COMBOBOX nWild ITEMS { "Starts with", "Contains" } ;

ON CHANGE ( oBrw:lSeekWild := (nWild==2), oBrw:Seek(""), oBrw:SetFocus() )

A.6 Dynamic progress bars with cancellation (xbrprogd.prg)

WITH OBJECT oBrw:aCols\[ 2 \]

:SetProgBar( 100,, { || { RGB(161,224,255), CLR\_WHITE } } )

:cEditPicture := "999.99 %"

:bClrSel := :bClrSelFocus := oBrw:bClrStd

END

oBrw:lDisplayZeros := .F.

oBrw:nStretchCol := 2

oBrw:CreateFromCode()

// Process with row-by-row update:

for n := 1 to oBrw:nLen

nTotal := HB\_RandomInt( 100, 2000 )

oBrw:aArrayData\[ n, 4 \] := nTotal

oBrw:RefreshCurrent()

for i := 1 to nTotal STEP 10

  SysWait( 0.01 )

  oBrw:nArrayAt := n

  oBrw:aArrayData\[ n, 2 \] := i / nTotal \* 100

  oBrw:aArrayData\[ n, 3 \] := i

  oBrw:RefreshCurrent()

  if oBrw:Cargo \== .F. ; EXIT ; endif

next

if oBrw:Cargo \== .F. ; EXIT ; endif

next

A.7 Watermark with alpha PNG image (xbwaterm.prg)

aImage := oWnd:ReadImage( "c:\\\\fwh\\\\bitmaps\\\\pngs\\\\logo.png",, .T. ) // .T. \= with alpha

@ 20,20 XBROWSE oBrw ... DATASOURCE "CUSTOMER" AUTOCOLS NOBORDER CELL LINES

WITH OBJECT oBrw

:lTransparent := .T.

:bPaintBack := { |Self|

  FillRect( ::hDC, GetClientRect(::hWnd), ::oBrush:hBrush )

  ::DrawImage( aImage, ::DataRect():aRect, nil, nil, 64 ) // 64 \= 25% opaque

  ::lTransparent := .T.

  return nil }

:CreateFromCode()

END

// When done:

PalBmpFree( aImage )

A.8 Dynamic subtotals in array (xbsubtot.prg)

// Subtotal rows: aRow\[1\] empty \= is subtotal

oBrw:bClrStd := { || { CLR\_BLACK, If( Empty(oBrw:aRow\[1\]), CLR\_YELLOW, CLR\_WHITE ) } }

WITH OBJECT oBrw:aCols\[ nCol \]

:bEditValue := { |x,o| If( x==nil .or. ValType(oBrw:aRow\[o:nArrayCol\])=='B',

  XEval( oBrw:aRow\[o:nArrayCol\] ),

  oBrw:aRow\[o:nArrayCol\] := x ) }

:bEditWhen := { || \!Empty( oBrw:aRow\[1\] ) }

:bSumCondition := { |n,o| \!Empty( o:oBrw:aRow\[1\] ) }

:bOnChange := { || oBrw:Refresh() }

:nFooterType := AGGR\_SUM

END

// Insert the subtotal row:

AIns( oBrw:aArrayData, nRowLast+1, Array(Len(oBrw:aRow)), .T. )

oBrw:aArrayData\[nRowLast+1, nCol\] := { || FW\_ArrSum( aRows, nCol ) } // dynamic block

A.9 Export filtered records to Excel (xbxlsel.prg)

// Build array of RecNos meeting the condition

local aRecNo := {}

(oBrw:cAlias)-\>( DBEVAL( { AAdd( aRecNo, RECNO() ) }, { STATE \== cState } ) )

(oBrw:cAlias)-\>( DBSeek( cState, .T. ) )

oBrw:Refresh()

// Export only those records

oBrw:aSelected := aRecNo

oBrw:ToExcel()

oBrw:aSelected := {}

A.10 Derived class with column and own behavior (xbrchild.prg)

CLASS MyBrowse FROM TXBrowse

CLASSDATA lRegistered AS LOGICAL

DATA bColClass INIT { || MyXBrCol() }

METHOD New( oWnd ) CONSTRUCTOR

ENDCLASS

METHOD New( oWnd ) CLASS MyBrowse

Super:New( oWnd )

::nMarqueeStyle := MARQSTYLE\_HIGHLROWMS

::bClrStd := { || { CLR\_BLACK, RGB(255,255,206) } }

::bClrSelFocus := { || { CLR\_WHITE, CLR\_BLUE } }

::bClrRowFocus := { || { CLR\_BLACK, RGB(150,231,255) } }

return Self

CLASS MyXbrCol FROM TXBrwColumn

METHOD Adjust()

ENDCLASS

METHOD Adjust() CLASS MyXBrCol

if ::cDataType \== 'D'

  ::cEditPicture := 'dd-mmm-yyyy'

endif

Super:Adjust()

return Self

// Specific use:

@ 10,10 XBROWSE oBrw CLASS MyBrowse() OF oDlg ALIAS 'SALES' AUTOCOLS SIZE 200,70 PIXEL

// Global use:

SET XBROWSE TO MyBrowse() SAVE PREVIOUS TO bXBr

regards, saludos

Antonio Linares
www.fivetechsoft.com
Posts: 300
Joined: Wed Jul 11, 2007 11:06 AM
Re: Manual TXBrowse
Posted: Tue Mar 10, 2026 07:33 AM

Great, Philippe

Continue the discussion