Gracias a Carlos Atúncar Hernandez
MANUAL DE REFERENCIA
TXBrowse / XBrowse
FiveWin para Harbour
Propiedades · Métodos · Eventos · Columnas
Basado en ejemplos oficiales de FiveWin
1\. Introducción
TXBrowse (invocado mediante el comando @ X,Y XBROWSE o XBROWSER) es el control de grilla más potente de FiveWin para Harbour. Permite mostrar y editar datos provenientes de tablas DBF/RDD, RecordSets ADO, arrays, objetos TDatabase, árboles (TTree) y archivos de texto.
1.1 Fuentes de Datos Soportadas
Propiedad / EventoTipoDescripción y Uso
ALIAS / DATASOURCERDDTabla DBF abierta. Uso: ALIAS 'CUST' o DATASOURCE "CUSTOMER"
RECORDSET / RECSETADORecordSet ADO. Uso: RECSET oRs o RECORDSET oRs
ARRAYArrayArray bidimensional. Uso: ARRAY aData
OBJECTObjetoObjeto TDatabase u otro con interfaz similar. Uso: OBJECT oCust
DATASOURCE oTreeTTreeÁrbol de nodos TTree para browse jerárquico
1.2 Formas de Crear el Browse
Comando declarativo
@ nRow, nCol XBROWSE oBrw OF oParent ALIAS 'CUST' AUTOCOLS LINES CELL
Programático (clase)
oBrw := TXBrowse():New( oWnd )
oBrw:SetRDD() // o :SetArray( aData ) / :SetRecordSet( oRs )
oBrw:CreateFromCode()
NOTA: Siempre llamar :CreateFromCode() al final de la configuración, antes de activar el diálogo/ventana.
2\. Propiedades del Browse (TXBrowse)
2.1 Apariencia y Estilo
Propiedad / EventoTipoDescripción y Uso
nMarqueeStyleNuméricoEstilo del selector de fila/celda. Ver constantes MARQSTYLE\_\* (sección 7\)
nRowDividerStyleNuméricoEstilo de línea divisoria entre filas. Ver LINESTYLE\_\* (sección 7\)
nColDividerStyleNuméricoEstilo de línea divisoria entre columnas. Ver LINESTYLE\_\*
lColDividerCompleteLógicoSi .T., la línea de columna se extiende hasta el encabezado. Default: .F.
nRowHeightNuméricoAltura de cada fila en píxeles. Ej: oBrw:nRowHeight := 40
nHeaderHeightNuméricoAltura del encabezado en píxeles. Ej: oBrw:nHeaderHeight := 30
nDataLinesNuméricoNúmero de líneas de texto por fila de datos. Ej: := 2 para multilinea
nHeaderLinesNuméricoNúmero de líneas del encabezado. Ej: := 2 para encabezados de 2 líneas
nFooterLinesNuméricoNúmero de líneas del pie de columna
l2007LógicoActiva el estilo visual Office 2007\. Ej: oBrw:l2007 := .T.
nWidthsNuméricoAncho uniforme para todas las columnas en píxeles
2.2 Desplazamiento y Columnas
Propiedad / EventoTipoDescripción y Uso
nStretchColNuméricoColumna que se expande para llenar el espacio disponible. Ver STRETCHCOL\_\* (sección 7\)
nFreezeNuméricoNúmero de columnas congeladas (no se desplazan horizontalmente). Ej: oBrw:nFreeze := 2
lHScrollLógicoMuestra/oculta la barra de desplazamiento horizontal. Default: .T.
lVScrollLógicoMuestra/oculta la barra de desplazamiento vertical. Default: .T.
lRecordSelectorLógicoMuestra/oculta el selector de registro (columna izquierda). Default: .T.
nColSelNuméricoNúmero de columna actualmente seleccionada (lectura)
2.3 Colores
Propiedad / EventoTipoDescripción y Uso
bClrStdBloqueColor estándar de celdas. {{ nColorTexto, nColorFondo } }. Ej: {{CLR\_BLACK, CLR\_WHITE}}
bClrRowFocusBloqueColor de la fila con foco. Ej: {{CLR\_BLACK, RGB(185,220,255)}}
bClrSelFocusBloqueColor de la celda/fila seleccionada con foco. Igual formato que bClrStd
bClrHeaderBloqueColor del encabezado. Ej: {{CLR\_WHITE, RGB(134,219,9)}}
oDataFontsObjeto/BloqueFuente para datos. Puede ser objeto font o bloque {If(cond, oFontA, oFontB)}
oFooterFontsObjetoFuente para los pies de columna
NOTA: Los bloques de color devuelven un array de 2 elementos: { nColorTexto, nColorFondo }. El fondo puede ser un color RGB o incluso un array de gradiente.
2.4 Fondo (Background)
Propiedad / EventoTipoDescripción y Uso
SetBackGround(cRes)MétodoEstablece imagen de fondo. Ej: oBrw:SetBackGround("PAPER")
SetBackGround(aGrad, lVert)MétodoFondo degradado. aGrad es array de tramos, lVert orienta vertical/horizontal
oBrushObjetoBrush actual del fondo. oBrw:oBrush:nResizeMode para el modo (BCK\_TILED, etc.)
Ejemplo de gradiente
local aGrad := {{ .5, CLR\_BLUE, RGB(202,202,255) }, { .5, RGB(202,202,255), CLR\_BLUE }}
// En el comando XBROWSE: BACKGROUND aGrad VERTICAL
// O en código: oBrw:SetBackGround( aGrad, .T. )
2.5 Edición
Propiedad / EventoTipoDescripción y Uso
nEditTypesNuméricoTipo de edición para TODAS las columnas de una vez. Ej: oBrw:nEditTypes := EDIT\_GET
lFastEditLógicoPermite edición rápida sin necesidad de pulsar Enter primero. Ej: := .T.
lFormulaEditLógicoActiva edición de fórmulas en las celdas. Ej: oBrw:lFormulaEdit := .T.
bEditWhensBloqueCondición global de cuándo permitir edición. {oColcondicion}
lAutoAppendLógicoPermite agregar filas automáticamente al llegar al final del array
bPastEofBloqueBloque ejecutado al intentar ir más allá del último registro
2.6 Pies de Columna (Footers)
Propiedad / EventoTipoDescripción y Uso
lFooterLógicoActiva/desactiva la fila de pie. Ej: oBrw:lFooter := .T.
cFootersArrayArray con textos de pie para todas las columnas
MakeTotals(\[oCol\])MétodoRecalcula los totales/agregados de los pies. Se llama tras configurar columnas
2.7 Ordenamiento y Búsqueda
Propiedad / EventoTipoDescripción y Uso
bSeekBloqueBloque para búsqueda incremental. {cDbSeek(Upper(c))}
nArrayAtNuméricoÍndice de la fila actual en el array (sólo para fuente ARRAY)
aArrayDataArrayReferencia al array de datos (fuente ARRAY)
aRowArrayArray con los valores de la fila actual
BookMarkVariosBookmark del registro actual (RDD/ADO)
nLenNuméricoNúmero total de registros/filas del browse
2.8 Multiselección
Propiedad / EventoTipoDescripción y Uso
aSelectedArrayArray con los bookmarks de las filas seleccionadas (multiselect)
SelectAll()MétodoSelecciona todas las filas
SelectNone()MétodoDeselecciona todas las filas
nMarqueeStyle := MARQSTYLE\_HIGHLROWMSConstanteActiva modo multiselección con Ctrl+clic
2.9 Grupos de Cabecera (Group Headers)
Propiedad / EventoTipoDescripción y Uso
SetGroupHeader(cTxt,n1,n2,oFont)MétodoDefine un encabezado de grupo que abarca columnas n1 a n2. Ej: :SetGroupHeader('EMPLOYEE'+CRLF+'NAME', 1, 2, oBold)
lAllowColReGroupLógicoPermite reordenar columnas dentro de un grupo. Ej: := .T.
Ejemplo
oBrw:SetGroupHeader( 'EMPLOYEE' \+ CRLF \+ 'NAME', 1, 2, oBold )
oBrw:SetGroupHeader( 'ADDRESS', 3, 6, oBold )
2.10 Árbol (Tree Browse)
Propiedad / EventoTipoDescripción y Uso
DATASOURCE oTreeTTreeFuente de datos tipo árbol para browse jerárquico
oTreeItemTTreeItemNodo actualmente seleccionado en el árbol
oTreeTTreeReferencia al árbol de datos del browse
SetTree(nil, aBmps)MétodoConvierte un browse normal en árbol automático
nDataTypeNuméricoTipo de datos. DATATYPE\_TREE si es árbol
2.11 Estado y Persistencia
Propiedad / EventoTipoDescripción y Uso
SaveState()MétodoGuarda el estado actual (columnas, orden, etc.) en una cadena
RestoreState(cState)MétodoRestaura el estado guardado con SaveState()
lKineticBrwLógicoActiva el desplazamiento cinético (táctil). Ej: := .T.
2.12 Tooltip de Celda
Propiedad / EventoTipoDescripción y Uso
bCellToolTipsBloqueTooltip genérico para cualquier celda. {oCol{oCol:Value, oCol:cHeader}}
cToolTipCadenaTooltip simple del browse completo. Ej: oBrw:cToolTip := 'Texto'
NOTA: bCellToolTips aplica a todas las columnas, pero puede sobrescribirse por columna con oCols\[n\]:bCellToolTip
3\. Eventos del Browse (TXBrowse)
Propiedad / EventoTipoDescripción y Uso
bChangeBloqueSe ejecuta al cambiar de fila. Ej: {oCol:RefreshFooter() }
bRClickedBloqueClic derecho sobre datos. {nRow, nColShowPopup(nRow,nCol,oBrw)}
bLDClickDataBloqueDoble clic izquierdo sobre datos
bKeyDownBloqueTecla presionada. {oDlg:SetText(Str(oBrw:nColSel))}
bKeyCharBloqueCarácter tecleado. {kIf(k==VK\_RETURN, ..., nil)}
bPopUpBloqueMenú popup al hacer clic derecho. {oColMenu(o)}
bSeekBloqueBúsqueda incremental al escribir. {cDbSeek(Upper(c))}
bClrSelFocusBloqueColor de fila/celda con foco y selección activa
4\. Propiedades de la Columna (TXBrowseCol)
4.1 Identificación y Encabezado
Propiedad / EventoTipoDescripción y Uso
cHeaderCadenaTexto del encabezado. Puede incluir CRLF para multilínea. Ej: "Nombre" \+ CRLF \+ "Empleado"
nHeadStrAlignNuméricoAlineación del texto del encabezado. AL\_LEFT / AL\_CENTER / AL\_RIGHT
oHeaderFontObjeto fontFuente especial para el encabezado. Puede ser fuente vertical (NESCAPEMENT 900\)
nCreationOrderNuméricoOrden de creación de la columna. Útil con nStretchCol
nPosNuméricoPosición visible actual de la columna
nWidthNuméricoAncho de la columna en píxeles. Ej: :nWidth := 80
nArrayColNuméricoÍndice de columna en el array fuente (para fuente ARRAY)
4.2 Datos y Formato
Propiedad / EventoTipoDescripción y Uso
cEditPictureCadenaMáscara de formato/edición. Ej: :HireDate:cEditPicture := 'dd mmm yyyy'
bStrDataBloqueBloque que devuelve el texto de la celda. {\_FIELD-\>First}
bEditValueBloqueBloque que devuelve el valor editable. {\_FIELD-\>Married}
ValueVariosValor actual de la celda (lectura/escritura). oBrw:oCol("City"):Value
lDisplayZerosLógicoSi .F., no muestra ceros. Ej: oBrw:lDisplayZeros := .F.
nDataStrAlignsNuméricoAlineación de datos para TODAS las columnas a la vez (propiedad del browse)
nDataStrAlignNuméricoAlineación de datos de la columna. AL\_LEFT / AL\_CENTER / AL\_RIGHT
bDataStrAlignBloqueAlineación dinámica. {oIf(o:oBrw:aRow\[1\]==0, AL\_CENTER, AL\_LEFT)}
nDataStyleNuméricoEstilo de dibujo del texto en la celda
4.3 Colores de Columna
Propiedad / EventoTipoDescripción y Uso
bClrStdBloqueColor de la columna. Sobrescribe el bClrStd del browse. {{nTxt, nFondo}}
bClrEditBloqueColor al editar la celda. Ej: oBrw:aCols\[1\]:bClrEdit := oBrw:bClrStd
oBrushObjetoBrush (fondo imagen/color) propio de la columna
bExtendBloqueExtensión de celda (merge): {oIf(cond, nCols, 0)}. Simula fusión de celdas
4.4 Imágenes y Bitmaps en Columna
Propiedad / EventoTipoDescripción y Uso
AddBmpFile(cFile)MétodoAgrega un bitmap desde archivo a la lista de imágenes de la columna
AddResource(cRes)MétodoAgrega un bitmap desde recurso. Ej: :AddResource("GREEN")
AddBitmap(aNames)MétodoAgrega array de bitmaps. Ej: :AddBitmap({"OPEN","CLOSE","GREEN"})
nHeadBmpNoNumérico/BloqueNúmero del bitmap a mostrar en el encabezado. 1-based. Puede ser bloque
nHeadBmpAlignNuméricoAlineación del bitmap en el encabezado. AL\_LEFT / AL\_RIGHT / AL\_CENTER
nGrpBmpNoNuméricoNúmero de bitmap para el encabezado de grupo
bBmpDataBloqueBloque que devuelve el número de bitmap a mostrar en datos. {If(cond,1,2)}
nDataBmpAlignNuméricoAlineación del bitmap en datos. AL\_LEFT / AL\_CENTER / AL\_RIGHT
lBmpStretchLógicoSi .T., estira el bitmap para llenar la celda
lBmpTransparentLógicoSi .T., renderiza el bitmap con transparencia alfa
bStrImageBloqueBloque que devuelve la ruta de imagen para la celda. {oCol,oBrwoBrw:aRow\[2\]}
bAlphaLevelBloqueNivel de transparencia alfa (0-255). {oo:oBrw:aRow\[3\]}
nFootBmpNoNuméricoNúmero del bitmap a mostrar en el pie de la columna
NOTA: Para imágenes transparentes tipo PNG con canal alfa, usar lBmpTransparent := .T. combinado con bAlphaLevel.
4.5 Pie de Columna (Footer)
Propiedad / EventoTipoDescripción y Uso
cFooterCadenaTexto estático del pie. Ej: oCols\[1\]:cFooter := "TOTAL"
bFooterBloqueBloque dinámico para el pie. {LTrim(Str(oTxt:RecCount()))}
nFooterTypeNuméricoTipo de agregado automático. Ver AGGR\_\* (sección 7\)
bSumConditionBloqueCondición para incluir fila en el total. {u,oo:oBrw:aRow\[1\]\>0}
bLClickFooterBloqueClic izquierdo en el pie. {r,c,f,oFooterAggrClick(r,c,f,o)}
bRClickFooterBloqueClic derecho en el pie
RefreshFooter()MétodoRefresca el pie de la columna
lTotalLógicoActiva el total automático en el pie. Ej: oCol:lTotal := .T.
nTotalNuméricoValor del total acumulado (lectura/escritura)
4.6 Edición de Columna
Propiedad / EventoTipoDescripción y Uso
nEditTypeNuméricoTipo de editor. Ver EDIT\_\* (sección 7). Ej: := EDIT\_GET
bOnPostEditBloqueSe ejecuta tras confirmar la edición. {oCol, xVal, nKey...}
bEditBlockBloqueBloque del botón de edición (EDIT\_GET\_BUTTON). {r,c,oCol...}
aEditListTxtArrayTextos del listbox de edición (EDIT\_GET\_LISTBOX)
aEditListBoundArrayValores correspondientes a los textos del listbox
cEditPictureCadenaMáscara de entrada al editar. Ej: "@K \!\!\!\!\!\!\!\!\!\!"
lAutoSaveLógicoSi .T., guarda automáticamente al salir de la celda sin necesidad de bOnPostEdit
SetCheck(aBmps, xEdit)MétodoConvierte la columna en checkbox. aBmps puede ser {"GREEN","RED"}
nBtnBmpCadenaRuta del bitmap para el botón de edición. Ej: "c:\\fwh\\bitmaps\\browse.bmp"
bPaintTextBloqueOwner-draw del texto de la celda. {oCol,hDC,cText,aCoordDrawText(...)}
4.7 Eventos de Columna
Propiedad / EventoTipoDescripción y Uso
bLClickHeaderBloqueClic izquierdo en encabezado. {r,c,f,oCol...}
bRClickHeaderBloqueClic derecho en encabezado
bLDClickDataBloqueDoble clic izquierdo en datos
blDClickDatasBloqueAlias de bLDClickData en algunos contextos
bRClickDataBloqueClic derecho en datos
bLClickFooterBloqueClic izquierdo en el pie
bRClickFooterBloqueClic derecho en el pie
bCellToolTipBloqueTooltip específico de la celda. {oColTRIM(FIELD-\>FIRST)+CRLF+TRIM(FIELD-\>LAST)}
cToolTipArrayTooltip de la columna como array {cTexto, cTítulo}. Ej: {'Col: '+cHeader,'Tip'}
bPopUpBloqueMenú contextual de la columna. {oColMenu(o)}
4.8 Anclaje (AnchorToCell)
Propiedad / EventoTipoDescripción y Uso
AnchorToCell(oDlg)MétodoPosiciona un diálogo anclado a la celda actual. Ideal para popups de búsqueda
Ejemplo
oDlg:bInit := { || oCol:AnchorToCell( oDlg ) }
5\. Métodos Principales del Browse
Propiedad / EventoTipoDescripción y Uso
CreateFromCode()MétodoFinaliza la construcción del browse. Siempre llamar al final de la configuración
SetArray(aData)MétodoEstablece o cambia el array de datos. Ej: oBrw:SetArray( aDatos )
SetRDD()MétodoConfigura el browse para usar el área RDD activa
Refresh(\[lFull\])MétodoRedibuja el browse. lFull=.T. para reconstrucción completa
SetFocus()MétodoDa el foco al browse
Edit(\[lNew\])MétodoAbre el editor para el registro actual. lNew=.T. para nuevo registro
Delete()MétodoElimina el registro actual
GoBottom()MétodoVa al último registro/fila
GoTop()MétodoVa al primer registro/fila
InsCol(nPos)MétodoInserta una columna en la posición nPos. Retorna el objeto columna
AddCol()MétodoAgrega una columna al final. Retorna el objeto columna
MoveCol(oColA, oColB)MétodoMueve la columna oColA antes de oColB
oCol(cNombre)MétodoRetorna la columna por nombre. Ej: oBrw:oCol("Salary")
GetVisibleCols()MétodoRetorna array con las columnas visibles
MakeTotals(\[oCol\])MétodoRecalcula totales de footer
DataRect()MétodoRetorna array {nTop,nLeft,nBottom,nRight} del área de datos
FontSize(nDelta)MétodoAumenta o disminuye el tamaño de fuente. Ej: :FontSize(+1)
SelFont()MétodoAbre diálogo para seleccionar fuente
SetAlign(nAlign)MétodoCambia la alineación de la columna activa
ToExcel(\[lTitle,nMode\])MétodoExporta el browse a Excel
Report(\[...\])MétodoGenera un reporte impreso o PDF del browse
SaveState()MétodoGuarda el estado del browse (columnas, orden, anchos)
RestoreState(cState)MétodoRestaura un estado previamente guardado
SelectAll()MétodoSelecciona todas las filas (modo multiselect)
SelectNone()MétodoDeselecciona todas las filas
SetBackGround(xBkg, nMode)MétodoEstablece el fondo del browse
SetGroupHeader(c, n1, n2, oF)MétodoDefine encabezado de grupo para columnas n1 a n2
SetTree(nil, aBmps)MétodoActiva modo árbol automático
6\. Acceso Dinámico a Columnas
XBrowse permite acceder a las columnas del browse por nombre directamente como propiedad del browse, gracias a la magia de \_\_GetProperty:
6.1 Por nombre (acceso directo)
oBrw:Salary:nFooterType := AGGR\_TOTAL
oBrw:Married:SetCheck( { "GREEN", "RED" }, .T. )
oBrw:HireDate:cEditPicture := 'dd mmm yyyy'
6.2 Por método oCol()
if \!Empty( oCol := oBrw:oCol( "Salary" ) )
oCol:lTotal := .T.
oCol:nEditType := EDIT\_GET
endif
6.3 Por índice en aCols
oBrw:aCols\[ 1 \]:bClrStd := {|| {CLR\_WHITE, CLR\_RED} }
oBrw:aCols\[ 2 \]:nHeadStrAlign := AL\_CENTER
6.4 Columna computada (fórmula)
// Agrega columna nueva basada en otra
oBrw:NewSalary := { || oBrw:Salary:Value \* 1.1 }
WITH OBJECT oBrw:NewSalary
:cHeader := 'NewSalary'
:nFooterType := AGGR\_TOTAL
END
6.5 ADD TO (comando)
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\. Constantes de Referencia
7.1 MARQSTYLE\_\* — Estilo del Selector
Propiedad / EventoTipoDescripción y Uso
MARQSTYLE\_DOTCELL (1)ConstanteMarco punteado en la celda activa
MARQSTYLE\_SOLIDCELL (2)ConstanteMarco sólido en la celda activa
MARQSTYLE\_HIGHLCELL (3)ConstanteResalta la celda activa con color
MARQSTYLE\_HIGHLROWRC (4)ConstanteResalta fila y columna activa
MARQSTYLE\_HIGHLROW (5)ConstanteResalta la fila completa activa
MARQSTYLE\_HIGHLROWMS (6)ConstanteResalta fila con soporte multiselección
MARQSTYLE\_HIGHLWIN7ConstanteEstilo barra degradada Windows 7/10
7.2 LINESTYLE\_\* — Estilo de Líneas Divisorias
Propiedad / EventoTipoDescripción y Uso
LINESTYLE\_NONE (0)ConstanteSin líneas divisorias
LINESTYLE\_BLACK (1)ConstanteLíneas negras
LINESTYLE\_DARKGRAY (2)ConstanteLíneas gris oscuro
LINESTYLE\_FORECOLOR (3)ConstanteLíneas del color de texto del browse
LINESTYLE\_LIGHTGRAY (4)ConstanteLíneas gris claro
LINESTYLE\_INSET (5)ConstanteLíneas estilo inset (hundido)
LINESTYLE\_RAISED (6)ConstanteLíneas estilo raised (realzado)
7.3 STRETCHCOL\_\* — Columna Elástica
Propiedad / EventoTipoDescripción y Uso
STRETCHCOL\_NONEConstanteSin columna elástica
STRETCHCOL\_LASTConstanteLa última columna ocupa el espacio sobrante
STRETCHCOL\_WIDESTConstanteLa columna más ancha se estira
nCreationOrderNuméricoSe puede usar el nCreationOrder de una columna específica
7.4 EDIT\_\* — Tipos de Editor
Propiedad / EventoTipoDescripción y Uso
EDIT\_NONE (0)ConstanteSin edición
EDIT\_GET (1)ConstanteGET estándar (cuadro de texto)
EDIT\_LISTBOXConstanteListbox desplegable
EDIT\_GET\_LISTBOXConstanteGET combinado con listbox
EDIT\_BUTTONConstanteBotón de acción al lado del GET
EDIT\_GET\_BUTTONConstanteGET combinado con botón
TYPE\_IMAGEConstanteImagen editable en la celda
7.5 AGGR\_\* — Tipos de Agregado en Footer
Propiedad / EventoTipoDescripción y Uso
AGGR\_TOTAL / AGGR\_SUMConstanteSuma de todos los valores de la columna
AGGR\_AVERAGE / AGGR\_AVGConstantePromedio de los valores
AGGR\_MAXConstanteValor máximo
AGGR\_MINConstanteValor mínimo
AGGR\_COUNTConstanteCuenta de registros
AGGR\_STDEVConstanteDesviación estándar
AGGR\_STDEVPConstanteDesviación estándar poblacional
7.6 AL\_\* — Alineación
Propiedad / EventoTipoDescripción y Uso
AL\_LEFTConstanteAlineación izquierda
AL\_CENTERConstanteAlineación centrada
AL\_RIGHTConstanteAlineación derecha
8\. Ejemplos Completos
8.1 Browse básico sobre 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 sobre Array con edición
@ 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 con colores dinámicos
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 con footer y totales
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 Multiselección con 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, ;
END
8.6 Group Headers con fuente bold
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 Imagen con transparencia alfa
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 Tooltip de celda
oBrw:bCellToolTips := {|oCol| {oCol:Value, oCol:cHeader}}
oBrw:aCols\[1\]:bCellToolTip := {|oCol| TRIM(FIELD-\>FIRST) \+ CRLF \+ TRIM(FIELD-\>LAST)}
8.9 Merge de celdas (bExtend)
WITH OBJECT :aCols\[ 1 \]
:bExtend := {|o| If(o:oBrw:aRow\[1\]==0, 2, 0)} // extiende 2 cols si es 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 con fondo degradado
local aGrad := {{ .5, CLR\_BLUE, RGB(202,202,255) }, { .5, RGB(202,202,255), CLR\_BLUE }}
@ 10,10 XBROWSE oBrw ... BACKGROUND aGrad VERTICAL
// O dinámicamente:
oBrw:SetBackGround( aGrad, .T. ) // .T. \= vertical
oBrw:SetBackGround( "PAPER" ) // Recurso de imagen
oBrw:SetBackGround() // Limpiar el fondo
9\. Patrón de Uso Recomendado
El siguiente es el orden típico para configurar un XBrowse de forma completa y correcta:
Definir la fuente de datos (ALIAS, ARRAY, RECSET, OBJECT)
Crear el browse con @ X,Y XBROWSE ... o TXBrowse():New()
Configurar propiedades del browse (estilos, colores, marquee, scroll)
Configurar propiedades de columnas (encabezados, edición, colores, bitmaps)
Definir group headers si aplica (SetGroupHeader)
Llamar MakeTotals() si hay footers con agregados
Llamar CreateFromCode() — SIEMPRE el último paso
Asignar oWnd:oClient := oBrw (para ventanas)
Activar la ventana o diálogo con ON INIT oBrw:SetFocus()
NOTA: CreateFromCode() SIEMPRE debe ser la última llamada de configuración. Cualquier propiedad o método de configuración llamado después de CreateFromCode() puede no tener efecto.
10\. Record Selector Avanzado
El selector de registro (la columna izquierda gris) puede personalizarse completamente para mostrar números de fila, nombres, iconos y menús contextuales.
10.1 Propiedades del Record Selector
Propiedad / EventoTipoDescripción y Uso
bRecSelDataBloqueContenido de la celda del selector. {brwbrw:KeyNo} muestra número secuencial
bRecSelHeaderCadena/BloqueEncabezado del selector. Ej: oBrw:bRecSelHeader := "SlNo"
bRecSelFooterCadena/BloquePie del selector. {brwbrw:nLen} muestra total de registros
nRecSelWidthNumérico/CadenaAncho del selector. Si es cadena, se usa como modelo: "9999" → ancho para 4 dígitos
nRecSelHeadBmpNoNumérico/Cadena/ArrayBitmap en el encabezado del selector. Puede ser ruta, número o descriptor de líneas
bRecSelClickBloqueClic en el encabezado del selector. {RecSelPopUp(oBrw)}
SetRecSelBmp(xBmp)MétodoEstablece bitmap personalizado en el selector. nil=default, 0=sin bitmap, cFile=imagen
lRecordSelectorLógicoMuestra/oculta el selector completo. Default: .T.
RecSelShowRecNo()MétodoMuestra el número de registro en el selector (atajo conveniente)
SetChecks()MétodoConfigura todos los campos lógicos como checkboxes en el browse
SetMultiSelectCol()MétodoAgrega columna checkbox de multiselección automática
oMultiSelColObjetoReferencia a la columna de multiselección creada por SetMultiSelectCol()
SelectRow()MétodoRetorna .T. si la fila actual está seleccionada (para uso con bSumCondition)
oRightColObjetoColumna congelada por la DERECHA. Ej: oBrw:oRightCol := oBrw:Salary
KeyNoNuméricoNúmero secuencial de la fila actual (como propiedad de lectura del browse)
Ejemplo: Selector con número de fila
WITH OBJECT oBrw
:bRecSelData := { |brw| brw:KeyNo }
:bRecSelFooter := { |brw| brw:nLen }
:bRecSelHeader := "SlNo"
:nRecSelWidth := "9999"
END
Ejemplo: Selector con nombre de región (Array)
WITH OBJECT oBrw
:bRecSelData := { |brw| brw:aRow\[ 1 \] } // nombre en col 1
:bRecSelFooter := "Totals"
:bRecSelHeader := "Region"
:nRecSelWidth := "Americas" // ancho para el texto más largo
END
Ejemplo: Multiselección con totales condicionales
WITH OBJECT oBrw
:SetMultiSelectCol()
:bClrStd := { || { CLR\_BLACK, If( oBrw:SelectRow(), 0x88EDFB, CLR\_WHITE ) } }
:Salary:bSumCondition := { || oBrw:SelectRow() }
:Salary:nFooterType := AGGR\_SUM
:MakeTotals()
END
11\. Barra de Gets (GetBar) y Filtro Incremental
11.1 GetBar — Gets bajo encabezados
Permite mostrar campos de entrada directamente debajo de los encabezados de columna para filtrar el browse en tiempo real.
Propiedad / EventoTipoDescripción y Uso
lGetBarLógicoActiva/desactiva la barra de GETs bajo los encabezados. Ej: oBrw:lGetBar := .T.
uBarGetValVariosValor inicial del GET de la columna. Ej: oCol:uBarGetVal := Space(10)
cBarGetPicCadenaMáscara del GET en la barra. Ej: oCol:cBarGetPic := NumPict(FieldLen(n), FieldDec(n))
bClrEditsBloqueColor de los GETs de la barra. {{CLR\_BLACK, CLR\_YELLOW}}
oHeaderFontsObjetoFuente para los encabezados. Ej: oBrw:oHeaderFonts := oBold
AutoFit()MétodoAjusta automáticamente el ancho de columnas al contenido
Ejemplo
for n := 1 to Len( oBrw:aCols )
WITH OBJECT oBrw:aCols\[ n \]
Code: Select all | Expand
if FieldType( n ) \!= 'L'
:uBarGetVal := uValBlank( fieldGet( n ) )
if FieldType( n ) \== 'N'
:cBarGetPic := NumPict( FieldLen(n), FieldDec(n) )
endif
END
END
next
oBrw:lGetBar := .T.
oBrw:bClrEdits := { || { CLR\_BLACK, CLR\_YELLOW } }
11.2 Filtro Incremental
Permite filtrar el browse mientras el usuario escribe, sin necesidad de presionar Enter.
Propiedad / EventoTipoDescripción y Uso
lIncrFilterLógicoActiva filtro incremental en tiempo real. Ej: oBrw:lIncrFilter := .T.
lSeekWildLógicoSi .T., filtra por contenido (contiene). Si .F., filtra por inicio (empieza con)
cFilterFldCadenaNombre del campo a filtrar. Ej: oBrw:cFilterFld := "FIRST"
cSeekCadenaTexto de búsqueda actual (lectura)
oSeekObjeto SAYControl SAY que muestra el texto de búsqueda actual
Seek(cText)MétodoEjecuta la búsqueda. Ej: oBrw:Seek("") para limpiar
Ejemplo
WITH OBJECT oBrw
:lIncrFilter := .T.
:lSeekWild := .T. // contiene (wildcard)
:cFilterFld := "FIRST"
END
// Combo para cambiar campo de filtro:
@ 10,10 COMBOBOX oBrw:cFilterFld ITEMS aHeaders ;
ON CHANGE ( oBrw:Seek(""), oBrw:SetFocus() )
12\. Barra de Botones Interna (nTopBarHeight / bOnAdjust)
XBrowse permite incorporar una barra de botones directamente dentro del propio browse, encima de los datos, sin necesidad de un ButtonBar externo.
Propiedad / EventoTipoDescripción y Uso
nTopBarHeightNuméricoAltura en píxeles de la barra interna. Ej: oBrw:nTopBarHeight := 30
bOnAdjustBloqueBloque ejecutado al crear/ajustar el browse. Aquí se crean los botones internos
EditSource(\[lNew\])MétodoAbre editor para el registro actual. lNew=.T. para nuevo. Alias de Edit()
Ejemplo completo
oBrw:nTopBarHeight := 30
oBrw:bOnAdjust := \<||
local oBtn
@ 05,05 BTNBMP oBtn FILE "new.bmp" SIZE 30,20 PIXEL OF oBrw NOBORDER ;
@ 05,45 BTNBMP oBtn FILE "edit.bmp" SIZE 30,20 PIXEL OF oBrw NOBORDER ;
@ 05,85 BTNBMP oBtn FILE "delete.bmp" SIZE 30,20 PIXEL OF oBrw NOBORDER ;
return nil
\>
13\. Fuentes y Colores por Línea (Multiline avanzado)
XBrowse permite asignar fuentes y colores distintos a cada línea de texto dentro de una celda multilinea, usando las propiedades aDataFont y aClrText de la columna.
Propiedad / EventoTipoDescripción y Uso
aDataFontArray de fontsArray de objetos font por línea. La línea N usa aDataFont\[N\]. Ej: oCols\[1\]:aDataFont := {oFont1, oFont2}
aClrTextArray de coloresArray de colores de texto por línea. nil \= color default. Ej: {CLR\_HBLUE, CLR\_HRED}
nDataStrAlignNuméricoPuede combinar AL\_CENTER \+ AL\_BOTTOM para alineación vertical+horizontal
aImgRectArrayRecorte de imagen en celda: {nTop%, nLeft%, nBottom%, nRight%, cShape}. Shape: "CIRCLE", nil=rect
lFitGridHeightLógicoAjusta la altura del browse para que quepa exactamente N filas completas
nHeadStrAlignsNuméricoAlineación de TODOS los encabezados a la vez (propiedad del browse)
nWidthsArray/NuméricoSi es array, establece anchos individuales: {200, 250, 150}. Si es numérico, ancho uniforme
Ejemplo: distintas fuentes y colores por línea
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
Ejemplo: imagen recortada en forma circular
WITH OBJECT oBrw:aCols\[ 3 \]
:bStrImage := { || "c:\\images\\foto.jpg" }
:aImgRect := { nil, 0.3, 0.7, nil, "CIRCLE" }
// nil \= borde completo, 0.3 \= 30% desde izquierda, 0.7 \= 70% desde izquierda
END
14\. Herencia — Clases Derivadas de TXBrowse
Es posible crear clases derivadas de TXBrowse y TXBrwColumn para personalizar el comportamiento a nivel de clase, aplicando los cambios a todos los browses del mismo tipo automáticamente.
14.1 Crear una clase derivada de TXBrowse
CLASS MyBrowse FROM TXBrowse
CLASSDATA lRegistered AS LOGICAL // OBLIGATORIO
DATA bColClass INIT { || MyXBrCol() } // clase columna propia
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 Clase derivada de TXBrwColumn
CLASS MyXbrCol FROM TXBrwColumn
METHOD Adjust()
ENDCLASS
METHOD Adjust() CLASS MyXBrCol
if ::cDataType \== 'D'
endif
Super:Adjust()
return Self
14.3 Activar la clase derivada
Propiedad / EventoTipoDescripción y Uso
CLASS MyBrowse() en comandoCláusula@ X,Y XBROWSE oBrw CLASS MyBrowse() ... — sólo ese browse usa la clase
SET XBROWSE TO MyBrowse()ComandoTodos los browses creados a partir de aquí usan MyBrowse()
SET XBROWSE TO bXBrComandoRestaura la clase anterior (guardada con SAVE PREVIOUS TO bXBr)
SetXBrowse({MyBrowse() })FunciónEquivalente programático a SET XBROWSE TO
lRegisteredCLASSDATAOBLIGATORIO en clases derivadas. Declara la clase como registrada en FWH
bColClassDATABloque que instancia la clase columna. INIT {TXBrwColumn() } por default
cDataTypeCadenaTipo de datos de la columna: 'C', 'N', 'D', 'L', 'M', 'F' (imagen)
Ejemplo con SAVE PREVIOUS
SET XBROWSE TO MyBrowse() SAVE PREVIOUS TO bXBr
// ... crear browses que usarán MyBrowse ...
SET XBROWSE TO bXBr // restaurar clase original
15\. Totales de Grupo (SetGroupTotal)
Además de los encabezados de grupo, es posible mostrar totales automáticos por grupo y un gran total consolidado.
Propiedad / EventoTipoDescripción y Uso
SetGroupTotal(cGrp, cHdr)MétodoAgrega fila de total para un grupo. cGrp \= nombre del grupo, cHdr \= texto encabezado
SetGroupTotal(aGrps, cHdr, nAggr, oFont)MétodoGrand total de múltiples grupos. nAggr \= AGGR\_SUM (default)
nFooterTypesNuméricoTipo de agregado para TODAS las columnas numéricas de una vez
RefreshFooters()MétodoRefresca todos los pies de columna
bOnChangeBloqueEvento de columna al cambiar valor. {oBrw:MakeTotals(), oBrw:RefreshFooters()}
lAllowColReGroupLógicoPermite mover columnas entre grupos. Ej: := .T.
Ejemplo completo
: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\. Control de Movimiento entre Celdas (nMoveType)
La propiedad nMoveType controla cómo se desplaza el cursor al presionar Enter o Tab después de editar una celda.
Propiedad / EventoTipoDescripción y Uso
nMoveTypeNuméricoDirección del movimiento al confirmar edición. Ver constantes MOVE\_\*
MOVE\_RIGHTConstanteMueve al cursor a la celda de la derecha (default para edición)
MOVE\_LEFTConstanteMueve al cursor a la celda de la izquierda
MOVE\_UPConstanteMueve al cursor a la celda de arriba
MOVE\_DOWNConstanteMueve al cursor a la celda de abajo
MOVE\_NONEConstanteNo mueve el cursor al confirmar
MOVE\_FAST\_RIGHTConstanteIgual que MOVE\_RIGHT pero con comportamiento rápido
MOVE\_FAST\_LEFTConstanteIgual que MOVE\_LEFT pero con comportamiento rápido
nRowSelNuméricoNúmero de fila actualmente seleccionada (visible)
nColSelNuméricoNúmero de columna actualmente seleccionada
lColChangeNotifyLógicoSi .T., dispara bChange también al cambiar de columna
lRelyOnKeyNoLógicoSi .F., usa posición física en lugar de KeyNo para posicionamiento
Ejemplo
oBrw:nMoveType := MOVE\_RIGHT // al confirmar, ir a la derecha
// o dinamicamente:
oBrw:nMoveType := MOVE\_DOWN // comportamiento tipo planilla de cálculo
17\. Propiedades Adicionales y Técnicas Avanzadas
17.1 Resaltado de Texto (FW\_SayTextHilite)
Permite resaltar palabras específicas dentro del texto de una celda con fuente y color diferente, usando bPaintText.
oBrw:aCols\[ 2 \]:bPaintText := {|oCol, hDC, cText, aRect, aColors|
FW\_SayTextHilite( hDC, cText, aRect, oFont, aColors\[1\], aColors\[2\],
Code: Select all | Expand
{ { AllTrim(cWordHL), oBold, CLR\_HRED, CLR\_HGREEN } } )
return nil
}
NOTA: FW\_SayTextHilite toma un array de {cPalabra, oFont, nClrTexto, nClrFondo} por cada palabra a resaltar.
17.2 DropFile — Arrastrar archivos sobre el browse
Propiedad / EventoTipoDescripción y Uso
DropFile(nRow, nCol, cFile)MétodoManeja el drop de un archivo sobre una celda específica del browse
lCanPasteLógicoHabilita la opción de pegar (Ctrl+V) en el browse. Ej: oBrw:lCanPaste := .T.
Ejemplo
if oBrw:DropFile( nRow, nCol, cFile )
// archivo aceptado
else
MsgInfo( 'Archivo no válido' )
endif
17.3 Generación de Código Fuente (PrgCode)
Propiedad / EventoTipoDescripción y Uso
PrgCode()MétodoGenera el código fuente PRG del browse actual. Retorna array de 4 elementos con distintos estilos
RptCode()Método (columna)Genera código de reporte para la columna
cColCadenaNombre de campo original de la columna (para generación de código)
Ejemplo
aCode := oBrw:PrgCode()
// aCode\[1\] \= estilo ListBox
// aCode\[2\] \= estilo Command
// aCode\[3\] \= estilo Oops
// aCode\[4\] \= código de reporte
17.4 Métodos de Navegación (bGoTop, bGoBottom, bSkip)
En clases derivadas o browses con fuentes de datos personalizadas, se pueden sobreescribir los bloques de navegación:
Propiedad / EventoTipoDescripción y Uso
bGoTopBloqueBloque para ir al primer registro. Ej: := {::nArrayAt := 1 }
bGoBottomBloqueBloque para ir al último registro
bSkipBloqueBloque para saltar N registros. Recibe nSkip, devuelve registros realmente saltados
bEofBloqueBloque que indica fin de datos. Ej: := {::nArrayAt \> ::nRows }
bKeyCountBloqueBloque que devuelve el total de registros. Ej: := {::nRows }
bKeyNoBloqueBloque para obtener/establecer la posición actual (KeyNo)
bBookMarkBloqueBloque para obtener/establecer el bookmark del registro actual
GoLeft(), GoRight()MétodosNavegar a columna izquierda/derecha. Sobreescribibles en clases derivadas
GoUp(\[n\]), GoDown(\[n\])MétodosNavegar filas arriba/abajo. Sobreescribibles
GetDisplayColsWidth()MétodoRetorna el ancho total de las columnas visibles
BrwWidth()MétodoRetorna el ancho del área de datos del browse
aCellCoor()MétodoRetorna coordenadas {nTop,nLeft,nBottom,nRight} de la celda activa
SetHScroll(l)MétodoMuestra/oculta scrollbar horizontal. Devuelve el nuevo estado
lAdjustedLógicoIndica si CreateFromCode() ya fue llamado (.T. después de crear)
17.5 Vista Grid/List (TXbrGrid)
Es posible crear un browse que alterne entre vista de lista (una columna por fila) y vista de cuadrícula (múltiples columnas por fila), similar a un explorador de archivos.
Propiedad / EventoTipoDescripción y Uso
lListViewLógico (ASSIGN)Activa vista de lista. Ej: oBrw:lListView := .T.
lGridViewLógico (ASSIGN)Activa vista de cuadrícula. Ej: oBrw:lGridView := .T.
CLASS TXbrGrid()ClaseClase derivada de ejemplo que implementa la vista grid. Ver xblstgrd.prg
lHeader, lFooterLógicoOcultar encabezado/pie: oBrw:lHeader := oBrw:lFooter := .F.
cDataType := 'F'CadenaTipo 'F' en la columna indica que el dato es una ruta de archivo de imagen
17.6 Arrays Irregulares (Ragged Arrays)
XBrowse puede navegar arrays irregulares (donde las filas tienen distinto número de columnas o tipos mezclados) usando XBROWSER directamente:
aData := { { 'Ragged Array' },
XBROWSER aData TITLE 'XBrowse Ragged Arrays' FASTEDIT
17.7 Clase TXBrCode — Browse de Código
Propiedad / EventoTipoDescripción y Uso
SET XBROWSE TO TXBrCode()ComandoActiva un browse especial con capacidad de generar código. Usado en el XBrowse Designer
18\. Barras de Progreso en Celdas (SetProgBar)
XBrowse permite mostrar una barra de progreso directamente dentro de una celda numérica, visualizando el valor como porcentaje de un máximo dado. Ideal para dashboards y procesos en cola.
Propiedad / EventoTipoDescripción y Uso
SetProgBar(uMax, nHeight, bClr)Método (col)Activa barra de progreso. uMax=valor máximo (número o bloque), nHeight=alto barra (nil=auto), bClr=bloque {nFill, nBack}
uMax como bloqueBloque{nMaxSal } — el máximo se recalcula dinámicamente en cada pintado
uMax como númeroNumérico100 — porcentaje fijo, el valor de la celda se toma como % de 100
RefreshCurrent()MétodoRefresca sólo la fila actual. Mucho más eficiente que Refresh() en procesos en curso
CargoVariosPropiedad de propósito general. Ej: oBrw:Cargo := .F. para señal de cancelación
bClrSelBloqueColor fila seleccionada sin foco. := :bClrSelFocus para igualar ambos estados
lDisplayZerosLógicoSi .F., celdas con valor 0 se muestran vacías. Útil al inicio de barras de progreso
Ejemplo — barra proporcional al máximo del campo
DBEval( { || nMaxSal := Max( nMaxSal, FIELD-\>Salary ) } )
WITH OBJECT oBrw:Salary
:SetProgBar( { nMaxSal },, { { RGB(161,224,255), CLR\_WHITE } } )
:nDataStrAlign := AL\_RIGHT
END
Ejemplo — barras dinámicas (proceso en cola con cancelación)
WITH OBJECT oBrw:aCols\[ 2 \]
:SetProgBar( 100,, { || { nProgClr, CLR\_WHITE } } )
:cEditPicture := "999.99 %"
:bClrSel := :bClrSelFocus := oBrw:bClrStd // sin resaltar fila activa
END
oBrw:lDisplayZeros := .F.
// Dentro del proceso:
oBrw:nArrayAt := n
oBrw:aArrayData\[ n, 2 \] := i / nTotal \* 100
oBrw:RefreshCurrent()
if oBrw:Cargo \== .F. ; EXIT ; endif // chequeo de cancelación
19\. Painting Avanzado (bPaintRow / bPaintHeader / bPaintFooter)
XBrowse expone hooks de pintado a nivel de fila, encabezado y pie completos, permitiendo control total del aspecto visual usando GDI.
19.1 bPaintRow — Pintar filas completas
Propiedad / EventoTipoDescripción y Uso
bPaintRowBloque{brw,nRow,nCol,nHt,lHL,lSel,nRowPos,nColSel,oColSel... } — hook de pintado por fila
Retorno .T.LógicoSi retorna .T., XBrowse no pinta esa fila (la pintó el bloque completamente)
Retorno .F.LógicoSi retorna .F., XBrowse pintará normalmente encima del trabajo del bloque
GetDC()MétodoObtiene el Device Context del browse para dibujar con GDI
ReleaseDC()MétodoLibera el DC obtenido con GetDC()
SayText(cText,aRect,cAlign,oFont,nClr)MétodoDibuja texto con el DC interno del browse
ReadImage(cFile)MétodoCarga imagen desde archivo. Retorna handle
DrawImage(aBmp, aRect)MétodoDibuja una imagen en el rectángulo indicado
lDrawBorderLógicoSi .T., dibuja borde alrededor del browse
nColorBoxNuméricoColor del borde del marquee. Ej: oBrw:nColorBox := CLR\_HRED
lHoverSelectLógicoSi .T., selecciona el registro al pasar el mouse (sin clic)
AddVar(cName, xVal)MétodoAgrega variable accesible dentro de los bloques como ::cName. Ej: oBrw:AddVar("oFntLarge", oLarge)
oFontObjetoFuente del browse. Accesible desde TDataRow: oRow:oBrw:oFont
Ejemplo bPaintRow
oBrw:bPaintRow := { |brw,nRow,nCol,nHt,lHL,lSel,nRowPos,nColSel,oColSel|
PaintRow( brw, nRow, nCol, nHt, lHL, lSel, nRowPos, nColSel, oColSel ) }
static function PaintRow( Self, nRow, nCol, nHeight, lHighLite, lSelect, nRowPos, nColSel, oColSel )
if Empty( ::aRow\[ 1 \] ) ; return .T. ; endif // fila vacía: no pintar
hDC := ::GetDC()
FillRectEx( hDC, { nRow,nCol,nRow+nHeight, ::aCols\[6\]:nDisplayCol }, aColor )
::SayText( ::aRow\[3\]+" : bPaintRow", { nRow,nCol,nRow+nHeight, ::BrwWidth() },
::aCols\[6\]:PaintData( nRow, nil, nHeight, lHighLite, lSelect, 6, nRowPos )
::ReleaseDC()
return .F.
19.2 bPaintHeader y bPaintFooter
Propiedad / EventoTipoDescripción y Uso
bPaintHeaderBloque{brw,hDC,aCols,nLast,hWPen,hGPen,hCPenBrwHeader(...) } — pinta el encabezado completo
bPaintFooterBloque{brw,hDC,aCols,nLast,nGridW,nBrwH,hWPen,hGPenBrwFooter(...) } — pinta el pie completo
oCol:PaintHeader(nRow,nil,nHt,lSel,hDC)Método (col)Pinta encabezado estándar de UNA columna dentro del hook personalizado
oCol:PaintFooter(nRow,nil,nHt)Método (col)Pinta pie estándar de UNA columna
oCol:PaintData(nRow,nil,nHt,lHL,lSel,n,nPos)Método (col)Pinta celda de datos de UNA columna — útil en bPaintRow
oCol:nDisplayColNuméricoPosición X izquierda de la columna (px desde borde izquierdo del browse)
oCol:oHeaderFontObjetoFuente del encabezado de la columna
oCol:oFooterFontObjetoFuente del pie de la columna
nHeadStrAlignsArrayAlineaciones del encabezado por columna: { AL\_RIGHT, AL\_LEFT, AL\_RIGHT }
nFootStrAlignsArrayAlineaciones del pie por columna
lAllowColSwappingLógicoSi .F., impide reordenar columnas arrastrando el encabezado
Ejemplo bPaintHeader con imagen y texto
oBrw:bPaintHeader := { |brw,hDC,aCols,nLast,...| BrwHeader( brw, hDC, aCols, nLast ) }
function BrwHeader( Self, hDC, aCols, nLast )
FillRect( hDC, { 1,1,::nHeaderHeight,::BrwWidth() }, ::oHeadBrush:hBrush )
::SayText( "MI EMPRESA", aRect, "T", ::oFntLarge, CLR\_HRED )
aBmp := ::ReadImage( "logo.png" ) ; ::DrawImage( aBmp, { 1,1,::nHeaderHeight-24,64 } ) ; PalBmpFree( aBmp )
for n := 1 to Len( ::aCols )
Code: Select all | Expand
::aCols\[n\]:PaintHeader( ::nHeaderHeight-30, nil, 26, .F., hDC ) // enc. estándar abajo
next
return nil
19.3 bPaintText — Pintado individual de celda con GDI
oBrw:aCols\[1\]:bPaintText := { |oCol, hDC, cText, aCoors, aColors, lHighlight|
if lHighlight
Code: Select all | Expand
GradientFill( hDC, aCoors\[1\]+10, aCoors\[2\]+10, aCoors\[3\]-10, aCoors\[4\]-10,
{ {2/5, RGB(253,212,168), RGB(251,178,99)}, {3/5, RGB(250,157,52), RGB(252,234,163)} } )
else
Code: Select all | Expand
GradientFill( hDC, aCoors\[1\]+10, aCoors\[2\]+10, aCoors\[3\]-10, aCoors\[4\]-10,
{ {2/5, RGB(223,236,255), RGB(197,222,255)}, {3/5, RGB(173,209,255), RGB(189,217,255)} } )
endif
RoundBox( hDC, aCoors\[2\]+10, aCoors\[1\]+10, aCoors\[4\]-10, aCoors\[3\]-10, 20, 20, CLR\_BLUE )
DrawBitmap( hDC, hBmp, aCoors\[1\]+18, aCoors\[2\]+23 )
DrawText( hDC, cText, aCoors )
return nil }
NOTA: En bPaintText: aColors\[1\]=color texto, aColors\[2\]=color fondo. lHighlight indica celda seleccionada con foco.
20\. Edición Avanzada
20.1 EDIT\_BUTTON — Editor popup personalizado
Propiedad / EventoTipoDescripción y Uso
nEditType := EDIT\_BUTTONConstante (col)Muestra botón en la celda al entrar en modo edición
bEditBlockBloque (col){nRow, nCol, oColEditFunc(nRow,nCol,oCol) } — invocado al hacer clic en el botón
bOnPostEditBloque (col){oCol, xVal, nKey... } — post-edit. xVal=nuevo valor, nKey=tecla de confirmación
EDIT\_LISTBOXConstante (col)Muestra un listbox desplegable como editor de celda
aEditListTxtArray (col)Ítems para EDIT\_LISTBOX: { {1,'uno',10}, {2,'dos',20} }
nLbxAtNumérico (col)Índice de la selección actual en aEditListTxt (sólo lectura útil en bOnChange)
bClrEditBloque (col)Color de edición para UNA columna: {{ CLR\_BLACK, CLR\_YELLOW } }
bClrEditsBloque (browse)Color de edición para TODAS las columnas del browse
bOnChangeBloque (col)Ejecutado al cambiar el valor durante la edición de esa columna
bOnChangesBloque (browse)Ejecutado cuando cualquier columna cambia. Global para todo el browse
Ejemplo EDIT\_BUTTON con popup memo
oCol:nEditType := EDIT\_BUTTON
oCol:bEditBlock := { |nRow, nCol, oCol| EditNotes( nRow, nCol, oCol ) }
oCol:bOnPostEdit := { |oCol, cVal| If( cVal \!= nil, FIELD-\>Notes := cVal, ) }
static function EditNotes( nRow, nCol, oCol )
aPoint := ClientToScreen( oCol:oBrw:hWnd, { nRow, nCol } )
DEFINE DIALOG oDlg FROM aPoint\[1\], aPoint\[2\] TO aPoint\[1\]+230, aPoint\[2\]+200 PIXEL STYLE WS\_POPUP
@ 2,2 GET oGet VAR cNotes TEXT SIZE 96,96 PIXEL OF oDlg
ACTIVATE DIALOG oDlg
return If( lEdited, cNotes, nil )
Ejemplo EDIT\_LISTBOX con nLbxAt
WITH OBJECT oBrw:Item
:nEditType := EDIT\_LISTBOX
:aEditListTxt := { {1,'uno',10}, {2,'dos',20}, {3,'tres',30} }
:bOnChange := { |oCol| oBrw:aRow\[2\] := aList\[ oCol:nLbxAt, 3 \] }
END
20.2 CurrentRow() — Edición en diálogo independiente
Propiedad / EventoTipoDescripción y Uso
CurrentRow()MétodoRetorna objeto TDataRow de la fila actual. Campos accesibles como oRow:First, oRow:Salary
oRow:Modified()MétodoRetorna .T. si hay cambios no guardados
oRow:Save()MétodoGuarda cambios del TDataRow en la fuente original
oRow:Undo()MétodoDescarta los cambios pendientes
oRow:oBrwObjetoReferencia al browse padre. Ej: oRow:oBrw:oFont, oRow:oBrw:Age:cEditPicture
ON DBLCLICKCláusula@ X,Y XBROWSE ... ON DBLCLICK RowEdit( oBrw:CurrentRow() )
DATABASE oObjComandoCrea un objeto TDatabase desde el área activa
ROWS {10,5,30}Cláusula@ X,Y XBROWSE oBrw OBJECT oDbf ROWS {10,5,30} — sólo muestra esos recnos
SelectCol(nPos, lCenter)MétodoMueve foco a columna. lCenter=.T. centra la columna en vista
ColPos(oCol)MétodoRetorna posición visible de una columna
SelectedCol()MétodoRetorna el objeto columna actualmente con foco
nCreationOrderNumérico (col)Orden de creación de la columna (no cambia al reordenar en pantalla)
Ejemplo CurrentRow con diálogo no-modal
@ 10,10 XBROWSE oBrw ... ON DBLCLICK RowEdit( oBrw:CurrentRow() )
static function RowEdit( oRow )
DEFINE DIALOG oDlg SIZE 300,200 PIXEL FONT oRow:oBrw:oFont
@ 10,60 GET oRow:First SIZE 80,12 PIXEL OF oDlg UPDATE
@ 40,60 GET oRow:Age SIZE 40,12 PIXEL OF oDlg PICTURE oRow:oBrw:Age:cEditPicture UPDATE
@ 80,78 BUTTON 'Save' WHEN oRow:Modified() ACTION oRow:Save()
@ 80,10 BUTTON 'Undo' WHEN oRow:Modified() ACTION ( oRow:Undo(), oDlg:Update() )
ACTIVATE DIALOG oDlg CENTERED NOMODAL
return nil
21\. Combo de Ordenamiento (oSortCbx / cSortOrder)
XBrowse puede vincularse automáticamente a un ComboBox externo para que el usuario cambie el orden de visualización sin código adicional.
Propiedad / EventoTipoDescripción y Uso
oSortCbxObjetoReferencia a un ComboBox externo. XBrowse lo rellena con los índices disponibles y cambia el orden al seleccionar
cSortOrderCadenaNombre del orden activo. Vinculable al VAR del ComboBox
AUTOSORTCláusulaHabilita ordenamiento por clic en encabezado de columna
nColorBoxNuméricoColor del recuadro de selección (estilo MARQSTYLE\_SOLIDCELL). Ej: CLR\_HRED
cHeadersArrayArray de encabezados asignado vía código. Ej: oBrw:cHeaders := { "Nombre", "Apellido" }
lExcelCellWiseLógicoSi .T., la exportación a Excel mantiene estructura celda a celda
Uso 1 — Combo integrado (más simple)
oBrw:nMarqueeStyle := MARQSTYLE\_SOLIDCELL
oBrw:nColorBox := CLR\_HRED
oBrw:CreateFromCode()
@ 10,20 COMBOBOX oBrw:oSortCbx VAR oBrw:cSortOrder SIZE 100,400 PIXEL OF oDlg
Uso 2 — Combo externo vinculado después
@ 10,20 COMBOBOX oCbx VAR cOrder SIZE 100,400 PIXEL OF oDlg
WITH OBJECT oBrw
:oSortCbx := oCbx
:CreateFromCode()
END
22\. Intercambiar Browses (Swap), SetRDD y TPages
22.1 Mostrar/ocultar browses alternativos
Propiedad / EventoTipoDescripción y Uso
Hide()MétodoOculta el browse sin destruirlo
Show()MétodoMuestra un browse oculto
Enable()MétodoHabilita el browse para interacción del usuario
Disable()MétodoDeshabilita el browse (sin respuesta a teclado/mouse)
SetRDD()MétodoCambia la fuente de datos RDD al área activa en ese momento. Ej: Customer-\>( oBrw:SetRDD() )
REDEFINE XBROWSEComandoVincula browse de un resource a un objeto. Ej: REDEFINE XBROWSE oBrw ID 10 OF oDlg
Ejemplo swap con tabs
aBrw\[1\]:CreateFromCode() ; aBrw\[2\]:CreateFromCode()
aBrw\[2\]:Hide() // ocultar al inicio
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