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 / Evento | Tipo | Descripción y Uso |
|---|---|---|
| ALIAS / DATASOURCE | RDD | Tabla DBF abierta. Uso: ALIAS 'CUST' o DATASOURCE "CUSTOMER" |
| RECORDSET / RECSET | ADO | RecordSet ADO. Uso: RECSET oRs o RECORDSET oRs |
| ARRAY | Array | Array bidimensional. Uso: ARRAY aData |
| OBJECT | Objeto | Objeto TDatabase u otro con interfaz similar. Uso: OBJECT oCust |
| DATASOURCE oTree | TTree | Á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()
2\. Propiedades del Browse (TXBrowse)
2.1 Apariencia y Estilo
| Propiedad / Evento | Tipo | Descripción y Uso |
|---|---|---|
| nMarqueeStyle | Numérico | Estilo del selector de fila/celda. Ver constantes MARQSTYLE\_\* (sección 7\) |
| nRowDividerStyle | Numérico | Estilo de línea divisoria entre filas. Ver LINESTYLE\_\* (sección 7\) |
| nColDividerStyle | Numérico | Estilo de línea divisoria entre columnas. Ver LINESTYLE\_\* |
| lColDividerComplete | Lógico | Si .T., la línea de columna se extiende hasta el encabezado. Default: .F. |
| nRowHeight | Numérico | Altura de cada fila en píxeles. Ej: oBrw:nRowHeight := 40 |
| nHeaderHeight | Numérico | Altura del encabezado en píxeles. Ej: oBrw:nHeaderHeight := 30 |
| nDataLines | Numérico | Número de líneas de texto por fila de datos. Ej: := 2 para multilinea |
| nHeaderLines | Numérico | Número de líneas del encabezado. Ej: := 2 para encabezados de 2 líneas |
| nFooterLines | Numérico | Número de líneas del pie de columna |
| l2007 | Lógico | Activa el estilo visual Office 2007\. Ej: oBrw:l2007 := .T. |
| nWidths | Numérico | Ancho uniforme para todas las columnas en píxeles |
2.2 Desplazamiento y Columnas
| Propiedad / Evento | Tipo | Descripción y Uso |
|---|---|---|
| nStretchCol | Numérico | Columna que se expande para llenar el espacio disponible. Ver STRETCHCOL\_\* (sección 7\) |
| nFreeze | Numérico | Número de columnas congeladas (no se desplazan horizontalmente). Ej: oBrw:nFreeze := 2 |
| lHScroll | Lógico | Muestra/oculta la barra de desplazamiento horizontal. Default: .T. |
| lVScroll | Lógico | Muestra/oculta la barra de desplazamiento vertical. Default: .T. |
| lRecordSelector | Lógico | Muestra/oculta el selector de registro (columna izquierda). Default: .T. |
| nColSel | Numérico | Número de columna actualmente seleccionada (lectura) |
2.3 Colores
| Propiedad / Evento | Tipo | Descripción y Uso | ||||
|---|---|---|---|---|---|---|
| bClrStd | Bloque | Color estándar de celdas. { | { nColorTexto, nColorFondo } }. Ej: { | {CLR\_BLACK, CLR\_WHITE}} | ||
| bClrRowFocus | Bloque | Color de la fila con foco. Ej: { | {CLR\_BLACK, RGB(185,220,255)}} | |||
| bClrSelFocus | Bloque | Color de la celda/fila seleccionada con foco. Igual formato que bClrStd | ||||
| bClrHeader | Bloque | Color del encabezado. Ej: { | {CLR\_WHITE, RGB(134,219,9)}} | |||
| oDataFonts | Objeto/Bloque | Fuente para datos. Puede ser objeto font o bloque { | If(cond, oFontA, oFontB)} | |||
| oFooterFonts | Objeto | Fuente para los pies de columna |
2.4 Fondo (Background)
| Propiedad / Evento | Tipo | Descripción y Uso |
|---|---|---|
| SetBackGround(cRes) | Método | Establece imagen de fondo. Ej: oBrw:SetBackGround("PAPER") |
| SetBackGround(aGrad, lVert) | Método | Fondo degradado. aGrad es array de tramos, lVert orienta vertical/horizontal |
| oBrush | Objeto | Brush 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 / Evento | Tipo | Descripción y Uso | ||
|---|---|---|---|---|
| nEditTypes | Numérico | Tipo de edición para TODAS las columnas de una vez. Ej: oBrw:nEditTypes := EDIT\_GET | ||
| lFastEdit | Lógico | Permite edición rápida sin necesidad de pulsar Enter primero. Ej: := .T. | ||
| lFormulaEdit | Lógico | Activa edición de fórmulas en las celdas. Ej: oBrw:lFormulaEdit := .T. | ||
| bEditWhens | Bloque | Condición global de cuándo permitir edición. { | oCol | condicion} |
| lAutoAppend | Lógico | Permite agregar filas automáticamente al llegar al final del array | ||
| bPastEof | Bloque | Bloque ejecutado al intentar ir más allá del último registro |
2.6 Pies de Columna (Footers)
| Propiedad / Evento | Tipo | Descripción y Uso |
|---|---|---|
| lFooter | Lógico | Activa/desactiva la fila de pie. Ej: oBrw:lFooter := .T. |
| cFooters | Array | Array con textos de pie para todas las columnas |
| MakeTotals(\[oCol\]) | Método | Recalcula los totales/agregados de los pies. Se llama tras configurar columnas |
2.7 Ordenamiento y Búsqueda
| Propiedad / Evento | Tipo | Descripción y Uso | ||
|---|---|---|---|---|
| bSeek | Bloque | Bloque para búsqueda incremental. { | c | DbSeek(Upper(c))} |
| nArrayAt | Numérico | Índice de la fila actual en el array (sólo para fuente ARRAY) | ||
| aArrayData | Array | Referencia al array de datos (fuente ARRAY) | ||
| aRow | Array | Array con los valores de la fila actual | ||
| BookMark | Varios | Bookmark del registro actual (RDD/ADO) | ||
| nLen | Numérico | Número total de registros/filas del browse |
2.8 Multiselección
| Propiedad / Evento | Tipo | Descripción y Uso |
|---|---|---|
| aSelected | Array | Array con los bookmarks de las filas seleccionadas (multiselect) |
| SelectAll() | Método | Selecciona todas las filas |
| SelectNone() | Método | Deselecciona todas las filas |
| nMarqueeStyle := MARQSTYLE\_HIGHLROWMS | Constante | Activa modo multiselección con Ctrl+clic |
2.9 Grupos de Cabecera (Group Headers)
| Propiedad / Evento | Tipo | Descripción y Uso |
|---|---|---|
| SetGroupHeader(cTxt,n1,n2,oFont) | Método | Define un encabezado de grupo que abarca columnas n1 a n2. Ej: :SetGroupHeader('EMPLOYEE'+CRLF+'NAME', 1, 2, oBold) |
| lAllowColReGroup | Lógico | Permite 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 / Evento | Tipo | Descripción y Uso |
|---|---|---|
| DATASOURCE oTree | TTree | Fuente de datos tipo árbol para browse jerárquico |
| oTreeItem | TTreeItem | Nodo actualmente seleccionado en el árbol |
| oTree | TTree | Referencia al árbol de datos del browse |
| SetTree(nil, aBmps) | Método | Convierte un browse normal en árbol automático |
| nDataType | Numérico | Tipo de datos. DATATYPE\_TREE si es árbol |
2.11 Estado y Persistencia
| Propiedad / Evento | Tipo | Descripción y Uso |
|---|---|---|
| SaveState() | Método | Guarda el estado actual (columnas, orden, etc.) en una cadena |
| RestoreState(cState) | Método | Restaura el estado guardado con SaveState() |
| lKineticBrw | Lógico | Activa el desplazamiento cinético (táctil). Ej: := .T. |
2.12 Tooltip de Celda
| Propiedad / Evento | Tipo | Descripción y Uso | ||
|---|---|---|---|---|
| bCellToolTips | Bloque | Tooltip genérico para cualquier celda. { | oCol | {oCol:Value, oCol:cHeader}} |
| cToolTip | Cadena | Tooltip simple del browse completo. Ej: oBrw:cToolTip := 'Texto' |
3\. Eventos del Browse (TXBrowse)
| Propiedad / Evento | Tipo | Descripción y Uso | ||
|---|---|---|---|---|
| bChange | Bloque | Se ejecuta al cambiar de fila. Ej: { | oCol:RefreshFooter() } | |
| bRClicked | Bloque | Clic derecho sobre datos. { | nRow, nCol | ShowPopup(nRow,nCol,oBrw)} |
| bLDClickData | Bloque | Doble clic izquierdo sobre datos | ||
| bKeyDown | Bloque | Tecla presionada. { | oDlg:SetText(Str(oBrw:nColSel))} | |
| bKeyChar | Bloque | Carácter tecleado. { | k | If(k==VK\_RETURN, ..., nil)} |
| bPopUp | Bloque | Menú popup al hacer clic derecho. { | o | ColMenu(o)} |
| bSeek | Bloque | Búsqueda incremental al escribir. { | c | DbSeek(Upper(c))} |
| bClrSelFocus | Bloque | Color de fila/celda con foco y selección activa |
4\. Propiedades de la Columna (TXBrowseCol)
4.1 Identificación y Encabezado
| Propiedad / Evento | Tipo | Descripción y Uso |
|---|---|---|
| cHeader | Cadena | Texto del encabezado. Puede incluir CRLF para multilínea. Ej: "Nombre" \+ CRLF \+ "Empleado" |
| nHeadStrAlign | Numérico | Alineación del texto del encabezado. AL\_LEFT / AL\_CENTER / AL\_RIGHT |
| oHeaderFont | Objeto font | Fuente especial para el encabezado. Puede ser fuente vertical (NESCAPEMENT 900\) |
| nCreationOrder | Numérico | Orden de creación de la columna. Útil con nStretchCol |
| nPos | Numérico | Posición visible actual de la columna |
| nWidth | Numérico | Ancho de la columna en píxeles. Ej: :nWidth := 80 |
| nArrayCol | Numérico | Índice de columna en el array fuente (para fuente ARRAY) |
4.2 Datos y Formato
| Propiedad / Evento | Tipo | Descripción y Uso | ||
|---|---|---|---|---|
| cEditPicture | Cadena | Máscara de formato/edición. Ej: :HireDate:cEditPicture := 'dd mmm yyyy' | ||
| bStrData | Bloque | Bloque que devuelve el texto de la celda. { | \_FIELD-\>First} | |
| bEditValue | Bloque | Bloque que devuelve el valor editable. { | \_FIELD-\>Married} | |
| Value | Varios | Valor actual de la celda (lectura/escritura). oBrw:oCol("City"):Value | ||
| lDisplayZeros | Lógico | Si .F., no muestra ceros. Ej: oBrw:lDisplayZeros := .F. | ||
| nDataStrAligns | Numérico | Alineación de datos para TODAS las columnas a la vez (propiedad del browse) | ||
| nDataStrAlign | Numérico | Alineación de datos de la columna. AL\_LEFT / AL\_CENTER / AL\_RIGHT | ||
| bDataStrAlign | Bloque | Alineación dinámica. { | o | If(o:oBrw:aRow\[1\]==0, AL\_CENTER, AL\_LEFT)} |
| nDataStyle | Numérico | Estilo de dibujo del texto en la celda |
4.3 Colores de Columna
| Propiedad / Evento | Tipo | Descripción y Uso | ||
|---|---|---|---|---|
| bClrStd | Bloque | Color de la columna. Sobrescribe el bClrStd del browse. { | {nTxt, nFondo}} | |
| bClrEdit | Bloque | Color al editar la celda. Ej: oBrw:aCols\[1\]:bClrEdit := oBrw:bClrStd | ||
| oBrush | Objeto | Brush (fondo imagen/color) propio de la columna | ||
| bExtend | Bloque | Extensión de celda (merge): { | o | If(cond, nCols, 0)}. Simula fusión de celdas |
4.4 Imágenes y Bitmaps en Columna
| Propiedad / Evento | Tipo | Descripción y Uso | ||
|---|---|---|---|---|
| AddBmpFile(cFile) | Método | Agrega un bitmap desde archivo a la lista de imágenes de la columna | ||
| AddResource(cRes) | Método | Agrega un bitmap desde recurso. Ej: :AddResource("GREEN") | ||
| AddBitmap(aNames) | Método | Agrega array de bitmaps. Ej: :AddBitmap({"OPEN","CLOSE","GREEN"}) | ||
| nHeadBmpNo | Numérico/Bloque | Número del bitmap a mostrar en el encabezado. 1-based. Puede ser bloque | ||
| nHeadBmpAlign | Numérico | Alineación del bitmap en el encabezado. AL\_LEFT / AL\_RIGHT / AL\_CENTER | ||
| nGrpBmpNo | Numérico | Número de bitmap para el encabezado de grupo | ||
| bBmpData | Bloque | Bloque que devuelve el número de bitmap a mostrar en datos. { | If(cond,1,2)} | |
| nDataBmpAlign | Numérico | Alineación del bitmap en datos. AL\_LEFT / AL\_CENTER / AL\_RIGHT | ||
| lBmpStretch | Lógico | Si .T., estira el bitmap para llenar la celda | ||
| lBmpTransparent | Lógico | Si .T., renderiza el bitmap con transparencia alfa | ||
| bStrImage | Bloque | Bloque que devuelve la ruta de imagen para la celda. { | oCol,oBrw | oBrw:aRow\[2\]} |
| bAlphaLevel | Bloque | Nivel de transparencia alfa (0-255). { | o | o:oBrw:aRow\[3\]} |
| nFootBmpNo | Numérico | Número del bitmap a mostrar en el pie de la columna |
4.5 Pie de Columna (Footer)
| Propiedad / Evento | Tipo | Descripción y Uso | ||
|---|---|---|---|---|
| cFooter | Cadena | Texto estático del pie. Ej: oCols\[1\]:cFooter := "TOTAL" | ||
| bFooter | Bloque | Bloque dinámico para el pie. { | LTrim(Str(oTxt:RecCount()))} | |
| nFooterType | Numérico | Tipo de agregado automático. Ver AGGR\_\* (sección 7\) | ||
| bSumCondition | Bloque | Condición para incluir fila en el total. { | u,o | o:oBrw:aRow\[1\]\>0} |
| bLClickFooter | Bloque | Clic izquierdo en el pie. { | r,c,f,o | FooterAggrClick(r,c,f,o)} |
| bRClickFooter | Bloque | Clic derecho en el pie | ||
| RefreshFooter() | Método | Refresca el pie de la columna | ||
| lTotal | Lógico | Activa el total automático en el pie. Ej: oCol:lTotal := .T. | ||
| nTotal | Numérico | Valor del total acumulado (lectura/escritura) |
4.6 Edición de Columna
| Propiedad / Evento | Tipo | Descripción y Uso | ||
|---|---|---|---|---|
| nEditType | Numérico | Tipo de editor. Ver EDIT\_\* (sección 7). Ej: := EDIT\_GET | ||
| bOnPostEdit | Bloque | Se ejecuta tras confirmar la edición. { | oCol, xVal, nKey | ...} |
| bEditBlock | Bloque | Bloque del botón de edición (EDIT\_GET\_BUTTON). { | r,c,oCol | ...} |
| aEditListTxt | Array | Textos del listbox de edición (EDIT\_GET\_LISTBOX) | ||
| aEditListBound | Array | Valores correspondientes a los textos del listbox | ||
| cEditPicture | Cadena | Máscara de entrada al editar. Ej: "@K \!\!\!\!\!\!\!\!\!\!" | ||
| lAutoSave | Lógico | Si .T., guarda automáticamente al salir de la celda sin necesidad de bOnPostEdit | ||
| SetCheck(aBmps, xEdit) | Método | Convierte la columna en checkbox. aBmps puede ser {"GREEN","RED"} | ||
| nBtnBmp | Cadena | Ruta del bitmap para el botón de edición. Ej: "c:\\fwh\\bitmaps\\browse.bmp" | ||
| bPaintText | Bloque | Owner-draw del texto de la celda. { | oCol,hDC,cText,aCoord | DrawText(...)} |
4.7 Eventos de Columna
| Propiedad / Evento | Tipo | Descripción y Uso | ||
|---|---|---|---|---|
| bLClickHeader | Bloque | Clic izquierdo en encabezado. { | r,c,f,oCol | ...} |
| bRClickHeader | Bloque | Clic derecho en encabezado | ||
| bLDClickData | Bloque | Doble clic izquierdo en datos | ||
| blDClickDatas | Bloque | Alias de bLDClickData en algunos contextos | ||
| bRClickData | Bloque | Clic derecho en datos | ||
| bLClickFooter | Bloque | Clic izquierdo en el pie | ||
| bRClickFooter | Bloque | Clic derecho en el pie | ||
| bCellToolTip | Bloque | Tooltip específico de la celda. { | oCol | TRIM(FIELD-\>FIRST)+CRLF+TRIM(FIELD-\>LAST)} |
| cToolTip | Array | Tooltip de la columna como array {cTexto, cTítulo}. Ej: {'Col: '+cHeader,'Tip'} | ||
| bPopUp | Bloque | Menú contextual de la columna. { | o | ColMenu(o)} |
4.8 Anclaje (AnchorToCell)
| Propiedad / Evento | Tipo | Descripción y Uso |
|---|---|---|
| AnchorToCell(oDlg) | Método | Posiciona 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 / Evento | Tipo | Descripción y Uso |
|---|---|---|
| CreateFromCode() | Método | Finaliza la construcción del browse. Siempre llamar al final de la configuración |
| SetArray(aData) | Método | Establece o cambia el array de datos. Ej: oBrw:SetArray( aDatos ) |
| SetRDD() | Método | Configura el browse para usar el área RDD activa |
| Refresh(\[lFull\]) | Método | Redibuja el browse. lFull=.T. para reconstrucción completa |
| SetFocus() | Método | Da el foco al browse |
| Edit(\[lNew\]) | Método | Abre el editor para el registro actual. lNew=.T. para nuevo registro |
| Delete() | Método | Elimina el registro actual |
| GoBottom() | Método | Va al último registro/fila |
| GoTop() | Método | Va al primer registro/fila |
| InsCol(nPos) | Método | Inserta una columna en la posición nPos. Retorna el objeto columna |
| AddCol() | Método | Agrega una columna al final. Retorna el objeto columna |
| MoveCol(oColA, oColB) | Método | Mueve la columna oColA antes de oColB |
| oCol(cNombre) | Método | Retorna la columna por nombre. Ej: oBrw:oCol("Salary") |
| GetVisibleCols() | Método | Retorna array con las columnas visibles |
| MakeTotals(\[oCol\]) | Método | Recalcula totales de footer |
| DataRect() | Método | Retorna array {nTop,nLeft,nBottom,nRight} del área de datos |
| FontSize(nDelta) | Método | Aumenta o disminuye el tamaño de fuente. Ej: :FontSize(+1) |
| SelFont() | Método | Abre diálogo para seleccionar fuente |
| SetAlign(nAlign) | Método | Cambia la alineación de la columna activa |
| ToExcel(\[lTitle,nMode\]) | Método | Exporta el browse a Excel |
| Report(\[...\]) | Método | Genera un reporte impreso o PDF del browse |
| SaveState() | Método | Guarda el estado del browse (columnas, orden, anchos) |
| RestoreState(cState) | Método | Restaura un estado previamente guardado |
| SelectAll() | Método | Selecciona todas las filas (modo multiselect) |
| SelectNone() | Método | Deselecciona todas las filas |
| SetBackGround(xBkg, nMode) | Método | Establece el fondo del browse |
| SetGroupHeader(c, n1, n2, oF) | Método | Define encabezado de grupo para columnas n1 a n2 |
| SetTree(nil, aBmps) | Método | Activa 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 / Evento | Tipo | Descripción y Uso |
|---|---|---|
| MARQSTYLE\_DOTCELL (1) | Constante | Marco punteado en la celda activa |
| MARQSTYLE\_SOLIDCELL (2) | Constante | Marco sólido en la celda activa |
| MARQSTYLE\_HIGHLCELL (3) | Constante | Resalta la celda activa con color |
| MARQSTYLE\_HIGHLROWRC (4) | Constante | Resalta fila y columna activa |
| MARQSTYLE\_HIGHLROW (5) | Constante | Resalta la fila completa activa |
| MARQSTYLE\_HIGHLROWMS (6) | Constante | Resalta fila con soporte multiselección |
| MARQSTYLE\_HIGHLWIN7 | Constante | Estilo barra degradada Windows 7/10 |
7.2 LINESTYLE\_\* — Estilo de Líneas Divisorias
| Propiedad / Evento | Tipo | Descripción y Uso |
|---|---|---|
| LINESTYLE\_NONE (0) | Constante | Sin líneas divisorias |
| LINESTYLE\_BLACK (1) | Constante | Líneas negras |
| LINESTYLE\_DARKGRAY (2) | Constante | Líneas gris oscuro |
| LINESTYLE\_FORECOLOR (3) | Constante | Líneas del color de texto del browse |
| LINESTYLE\_LIGHTGRAY (4) | Constante | Líneas gris claro |
| LINESTYLE\_INSET (5) | Constante | Líneas estilo inset (hundido) |
| LINESTYLE\_RAISED (6) | Constante | Líneas estilo raised (realzado) |
7.3 STRETCHCOL\_\* — Columna Elástica
| Propiedad / Evento | Tipo | Descripción y Uso |
|---|---|---|
| STRETCHCOL\_NONE | Constante | Sin columna elástica |
| STRETCHCOL\_LAST | Constante | La última columna ocupa el espacio sobrante |
| STRETCHCOL\_WIDEST | Constante | La columna más ancha se estira |
| nCreationOrder | Numérico | Se puede usar el nCreationOrder de una columna específica |
7.4 EDIT\_\* — Tipos de Editor
| Propiedad / Evento | Tipo | Descripción y Uso |
|---|---|---|
| EDIT\_NONE (0) | Constante | Sin edición |
| EDIT\_GET (1) | Constante | GET estándar (cuadro de texto) |
| EDIT\_LISTBOX | Constante | Listbox desplegable |
| EDIT\_GET\_LISTBOX | Constante | GET combinado con listbox |
| EDIT\_BUTTON | Constante | Botón de acción al lado del GET |
| EDIT\_GET\_BUTTON | Constante | GET combinado con botón |
| TYPE\_IMAGE | Constante | Imagen editable en la celda |
7.5 AGGR\_\* — Tipos de Agregado en Footer
| Propiedad / Evento | Tipo | Descripción y Uso |
|---|---|---|
| AGGR\_TOTAL / AGGR\_SUM | Constante | Suma de todos los valores de la columna |
| AGGR\_AVERAGE / AGGR\_AVG | Constante | Promedio de los valores |
| AGGR\_MAX | Constante | Valor máximo |
| AGGR\_MIN | Constante | Valor mínimo |
| AGGR\_COUNT | Constante | Cuenta de registros |
| AGGR\_STDEV | Constante | Desviación estándar |
| AGGR\_STDEVP | Constante | Desviación estándar poblacional |
7.6 AL\_\* — Alineación
| Propiedad / Evento | Tipo | Descripción y Uso |
|---|---|---|
| AL\_LEFT | Constante | Alineación izquierda |
| AL\_CENTER | Constante | Alineación centrada |
| AL\_RIGHT | Constante | Alineació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, ;
oBrw:SelectNone(), oBrw:SelectAll())}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()
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 / Evento | Tipo | Descripción y Uso | ||
|---|---|---|---|---|
| bRecSelData | Bloque | Contenido de la celda del selector. { | brw | brw:KeyNo} muestra número secuencial |
| bRecSelHeader | Cadena/Bloque | Encabezado del selector. Ej: oBrw:bRecSelHeader := "SlNo" | ||
| bRecSelFooter | Cadena/Bloque | Pie del selector. { | brw | brw:nLen} muestra total de registros |
| nRecSelWidth | Numérico/Cadena | Ancho del selector. Si es cadena, se usa como modelo: "9999" → ancho para 4 dígitos | ||
| nRecSelHeadBmpNo | Numérico/Cadena/Array | Bitmap en el encabezado del selector. Puede ser ruta, número o descriptor de líneas | ||
| bRecSelClick | Bloque | Clic en el encabezado del selector. { | RecSelPopUp(oBrw)} | |
| SetRecSelBmp(xBmp) | Método | Establece bitmap personalizado en el selector. nil=default, 0=sin bitmap, cFile=imagen | ||
| lRecordSelector | Lógico | Muestra/oculta el selector completo. Default: .T. | ||
| RecSelShowRecNo() | Método | Muestra el número de registro en el selector (atajo conveniente) | ||
| SetChecks() | Método | Configura todos los campos lógicos como checkboxes en el browse | ||
| SetMultiSelectCol() | Método | Agrega columna checkbox de multiselección automática | ||
| oMultiSelCol | Objeto | Referencia a la columna de multiselección creada por SetMultiSelectCol() | ||
| SelectRow() | Método | Retorna .T. si la fila actual está seleccionada (para uso con bSumCondition) | ||
| oRightCol | Objeto | Columna congelada por la DERECHA. Ej: oBrw:oRightCol := oBrw:Salary | ||
| KeyNo | Numérico | Nú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 / Evento | Tipo | Descripción y Uso | ||
|---|---|---|---|---|
| lGetBar | Lógico | Activa/desactiva la barra de GETs bajo los encabezados. Ej: oBrw:lGetBar := .T. | ||
| uBarGetVal | Varios | Valor inicial del GET de la columna. Ej: oCol:uBarGetVal := Space(10) | ||
| cBarGetPic | Cadena | Máscara del GET en la barra. Ej: oCol:cBarGetPic := NumPict(FieldLen(n), FieldDec(n)) | ||
| bClrEdits | Bloque | Color de los GETs de la barra. { | {CLR\_BLACK, CLR\_YELLOW}} | |
| oHeaderFonts | Objeto | Fuente para los encabezados. Ej: oBrw:oHeaderFonts := oBold | ||
| AutoFit() | Método | Ajusta automáticamente el ancho de columnas al contenido |
Ejemplo
for n := 1 to Len( oBrw:aCols )
WITH OBJECT oBrw:aCols\[ n \]
if FieldType( n ) \!= 'L'
:uBarGetVal := uValBlank( fieldGet( n ) )
if FieldType( n ) \== 'N'
:cBarGetPic := NumPict( FieldLen(n), FieldDec(n) )
endif
ENDEND
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 / Evento | Tipo | Descripción y Uso |
|---|---|---|
| lIncrFilter | Lógico | Activa filtro incremental en tiempo real. Ej: oBrw:lIncrFilter := .T. |
| lSeekWild | Lógico | Si .T., filtra por contenido (contiene). Si .F., filtra por inicio (empieza con) |
| cFilterFld | Cadena | Nombre del campo a filtrar. Ej: oBrw:cFilterFld := "FIRST" |
| cSeek | Cadena | Texto de búsqueda actual (lectura) |
| oSeek | Objeto SAY | Control SAY que muestra el texto de búsqueda actual |
| Seek(cText) | Método | Ejecuta 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 / Evento | Tipo | Descripción y Uso |
|---|---|---|
| nTopBarHeight | Numérico | Altura en píxeles de la barra interna. Ej: oBrw:nTopBarHeight := 30 |
| bOnAdjust | Bloque | Bloque ejecutado al crear/ajustar el browse. Aquí se crean los botones internos |
| EditSource(\[lNew\]) | Método | Abre 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 ;
ACTION oBrw:EditSource( .T. ) TOOLTIP "Agregar"@ 05,45 BTNBMP oBtn FILE "edit.bmp" SIZE 30,20 PIXEL OF oBrw NOBORDER ;
ACTION oBrw:EditSource() TOOLTIP "Editar"@ 05,85 BTNBMP oBtn FILE "delete.bmp" SIZE 30,20 PIXEL OF oBrw NOBORDER ;
ACTION oBrw:Delete() TOOLTIP "Eliminar"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 / Evento | Tipo | Descripción y Uso |
|---|---|---|
| aDataFont | Array de fonts | Array de objetos font por línea. La línea N usa aDataFont\[N\]. Ej: oCols\[1\]:aDataFont := {oFont1, oFont2} |
| aClrText | Array de colores | Array de colores de texto por línea. nil \= color default. Ej: {CLR\_HBLUE, CLR\_HRED} |
| nDataStrAlign | Numérico | Puede combinar AL\_CENTER \+ AL\_BOTTOM para alineación vertical+horizontal |
| aImgRect | Array | Recorte de imagen en celda: {nTop%, nLeft%, nBottom%, nRight%, cShape}. Shape: "CIRCLE", nil=rect |
| lFitGridHeight | Lógico | Ajusta la altura del browse para que quepa exactamente N filas completas |
| nHeadStrAligns | Numérico | Alineación de TODOS los encabezados a la vez (propiedad del browse) |
| nWidths | Array/Numérico | Si 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'
::cEditPicture := 'dd-mmm-yyyy'endif
Super:Adjust()
return Self
14.3 Activar la clase derivada
| Propiedad / Evento | Tipo | Descripción y Uso | ||
|---|---|---|---|---|
| CLASS MyBrowse() en comando | Cláusula | @ X,Y XBROWSE oBrw CLASS MyBrowse() ... — sólo ese browse usa la clase | ||
| SET XBROWSE TO MyBrowse() | Comando | Todos los browses creados a partir de aquí usan MyBrowse() | ||
| SET XBROWSE TO bXBr | Comando | Restaura la clase anterior (guardada con SAVE PREVIOUS TO bXBr) | ||
| SetXBrowse({ | MyBrowse() }) | Función | Equivalente programático a SET XBROWSE TO | |
| lRegistered | CLASSDATA | OBLIGATORIO en clases derivadas. Declara la clase como registrada en FWH | ||
| bColClass | DATA | Bloque que instancia la clase columna. INIT { | TXBrwColumn() } por default | |
| cDataType | Cadena | Tipo 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 / Evento | Tipo | Descripción y Uso | ||
|---|---|---|---|---|
| SetGroupTotal(cGrp, cHdr) | Método | Agrega fila de total para un grupo. cGrp \= nombre del grupo, cHdr \= texto encabezado | ||
| SetGroupTotal(aGrps, cHdr, nAggr, oFont) | Método | Grand total de múltiples grupos. nAggr \= AGGR\_SUM (default) | ||
| nFooterTypes | Numérico | Tipo de agregado para TODAS las columnas numéricas de una vez | ||
| RefreshFooters() | Método | Refresca todos los pies de columna | ||
| bOnChange | Bloque | Evento de columna al cambiar valor. { | oBrw:MakeTotals(), oBrw:RefreshFooters()} | |
| lAllowColReGroup | Lógico | Permite 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 / Evento | Tipo | Descripción y Uso |
|---|---|---|
| nMoveType | Numérico | Dirección del movimiento al confirmar edición. Ver constantes MOVE\_\* |
| MOVE\_RIGHT | Constante | Mueve al cursor a la celda de la derecha (default para edición) |
| MOVE\_LEFT | Constante | Mueve al cursor a la celda de la izquierda |
| MOVE\_UP | Constante | Mueve al cursor a la celda de arriba |
| MOVE\_DOWN | Constante | Mueve al cursor a la celda de abajo |
| MOVE\_NONE | Constante | No mueve el cursor al confirmar |
| MOVE\_FAST\_RIGHT | Constante | Igual que MOVE\_RIGHT pero con comportamiento rápido |
| MOVE\_FAST\_LEFT | Constante | Igual que MOVE\_LEFT pero con comportamiento rápido |
| nRowSel | Numérico | Número de fila actualmente seleccionada (visible) |
| nColSel | Numérico | Número de columna actualmente seleccionada |
| lColChangeNotify | Lógico | Si .T., dispara bChange también al cambiar de columna |
| lRelyOnKeyNo | Lógico | Si .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\],
{ { AllTrim(cWordHL), oBold, CLR\_HRED, CLR\_HGREEN } } )return nil
}
17.2 DropFile — Arrastrar archivos sobre el browse
| Propiedad / Evento | Tipo | Descripción y Uso |
|---|---|---|
| DropFile(nRow, nCol, cFile) | Método | Maneja el drop de un archivo sobre una celda específica del browse |
| lCanPaste | Lógico | Habilita 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 / Evento | Tipo | Descripción y Uso |
|---|---|---|
| PrgCode() | Método | Genera 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 |
| cCol | Cadena | Nombre 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 / Evento | Tipo | Descripción y Uso | ||
|---|---|---|---|---|
| bGoTop | Bloque | Bloque para ir al primer registro. Ej: := { | ::nArrayAt := 1 } | |
| bGoBottom | Bloque | Bloque para ir al último registro | ||
| bSkip | Bloque | Bloque para saltar N registros. Recibe nSkip, devuelve registros realmente saltados | ||
| bEof | Bloque | Bloque que indica fin de datos. Ej: := { | ::nArrayAt \> ::nRows } | |
| bKeyCount | Bloque | Bloque que devuelve el total de registros. Ej: := { | ::nRows } | |
| bKeyNo | Bloque | Bloque para obtener/establecer la posición actual (KeyNo) | ||
| bBookMark | Bloque | Bloque para obtener/establecer el bookmark del registro actual | ||
| GoLeft(), GoRight() | Métodos | Navegar a columna izquierda/derecha. Sobreescribibles en clases derivadas | ||
| GoUp(\[n\]), GoDown(\[n\]) | Métodos | Navegar filas arriba/abajo. Sobreescribibles | ||
| GetDisplayColsWidth() | Método | Retorna el ancho total de las columnas visibles | ||
| BrwWidth() | Método | Retorna el ancho del área de datos del browse | ||
| aCellCoor() | Método | Retorna coordenadas {nTop,nLeft,nBottom,nRight} de la celda activa | ||
| SetHScroll(l) | Método | Muestra/oculta scrollbar horizontal. Devuelve el nuevo estado | ||
| lAdjusted | Lógico | Indica 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 / Evento | Tipo | Descripción y Uso |
|---|---|---|
| lListView | Lógico (ASSIGN) | Activa vista de lista. Ej: oBrw:lListView := .T. |
| lGridView | Lógico (ASSIGN) | Activa vista de cuadrícula. Ej: oBrw:lGridView := .T. |
| CLASS TXbrGrid() | Clase | Clase derivada de ejemplo que implementa la vista grid. Ver xblstgrd.prg |
| lHeader, lFooter | Lógico | Ocultar encabezado/pie: oBrw:lHeader := oBrw:lFooter := .F. |
| cDataType := 'F' | Cadena | Tipo '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' },
{ 123, Date(), 'Texto', 349.23 },
345.26,
date()-20 }XBROWSER aData TITLE 'XBrowse Ragged Arrays' FASTEDIT
17.7 Clase TXBrCode — Browse de Código
| Propiedad / Evento | Tipo | Descripción y Uso |
|---|---|---|
| SET XBROWSE TO TXBrCode() | Comando | Activa 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 / Evento | Tipo | Descripció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 bloque | Bloque | { | nMaxSal } — el máximo se recalcula dinámicamente en cada pintado | |
| uMax como número | Numérico | 100 — porcentaje fijo, el valor de la celda se toma como % de 100 | ||
| RefreshCurrent() | Método | Refresca sólo la fila actual. Mucho más eficiente que Refresh() en procesos en curso | ||
| Cargo | Varios | Propiedad de propósito general. Ej: oBrw:Cargo := .F. para señal de cancelación | ||
| bClrSel | Bloque | Color fila seleccionada sin foco. := :bClrSelFocus para igualar ambos estados | ||
| lDisplayZeros | Lógico | Si .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( {
: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 / Evento | Tipo | Descripción y Uso | ||
|---|---|---|---|---|
| bPaintRow | Bloque | { | brw,nRow,nCol,nHt,lHL,lSel,nRowPos,nColSel,oColSel | ... } — hook de pintado por fila |
| Retorno .T. | Lógico | Si retorna .T., XBrowse no pinta esa fila (la pintó el bloque completamente) | ||
| Retorno .F. | Lógico | Si retorna .F., XBrowse pintará normalmente encima del trabajo del bloque | ||
| GetDC() | Método | Obtiene el Device Context del browse para dibujar con GDI | ||
| ReleaseDC() | Método | Libera el DC obtenido con GetDC() | ||
| SayText(cText,aRect,cAlign,oFont,nClr) | Método | Dibuja texto con el DC interno del browse | ||
| ReadImage(cFile) | Método | Carga imagen desde archivo. Retorna handle | ||
| DrawImage(aBmp, aRect) | Método | Dibuja una imagen en el rectángulo indicado | ||
| lDrawBorder | Lógico | Si .T., dibuja borde alrededor del browse | ||
| nColorBox | Numérico | Color del borde del marquee. Ej: oBrw:nColorBox := CLR\_HRED | ||
| lHoverSelect | Lógico | Si .T., selecciona el registro al pasar el mouse (sin clic) | ||
| AddVar(cName, xVal) | Método | Agrega variable accesible dentro de los bloques como ::cName. Ej: oBrw:AddVar("oFntLarge", oLarge) | ||
| oFont | Objeto | Fuente 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() },
nil, ::aCols\[1\]:oHeaderFont )::aCols\[6\]:PaintData( nRow, nil, nHeight, lHighLite, lSelect, 6, nRowPos )
::ReleaseDC()
return .F.
19.2 bPaintHeader y bPaintFooter
| Propiedad / Evento | Tipo | Descripción y Uso | ||
|---|---|---|---|---|
| bPaintHeader | Bloque | { | brw,hDC,aCols,nLast,hWPen,hGPen,hCPen | BrwHeader(...) } — pinta el encabezado completo |
| bPaintFooter | Bloque | { | brw,hDC,aCols,nLast,nGridW,nBrwH,hWPen,hGPen | BrwFooter(...) } — 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:nDisplayCol | Numérico | Posición X izquierda de la columna (px desde borde izquierdo del browse) | ||
| oCol:oHeaderFont | Objeto | Fuente del encabezado de la columna | ||
| oCol:oFooterFont | Objeto | Fuente del pie de la columna | ||
| nHeadStrAligns | Array | Alineaciones del encabezado por columna: { AL\_RIGHT, AL\_LEFT, AL\_RIGHT } | ||
| nFootStrAligns | Array | Alineaciones del pie por columna | ||
| lAllowColSwapping | Lógico | Si .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 )
::aCols\[n\]:PaintHeader( ::nHeaderHeight-30, nil, 26, .F., hDC ) // enc. estándar abajonext
return nil
19.3 bPaintText — Pintado individual de celda con GDI
oBrw:aCols\[1\]:bPaintText := { |oCol, hDC, cText, aCoors, aColors, lHighlight|
if lHighlight
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
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 }
20\. Edición Avanzada
20.1 EDIT\_BUTTON — Editor popup personalizado
| Propiedad / Evento | Tipo | Descripción y Uso | ||
|---|---|---|---|---|
| nEditType := EDIT\_BUTTON | Constante (col) | Muestra botón en la celda al entrar en modo edición | ||
| bEditBlock | Bloque (col) | { | nRow, nCol, oCol | EditFunc(nRow,nCol,oCol) } — invocado al hacer clic en el botón |
| bOnPostEdit | Bloque (col) | { | oCol, xVal, nKey | ... } — post-edit. xVal=nuevo valor, nKey=tecla de confirmación |
| EDIT\_LISTBOX | Constante (col) | Muestra un listbox desplegable como editor de celda | ||
| aEditListTxt | Array (col) | Ítems para EDIT\_LISTBOX: { {1,'uno',10}, {2,'dos',20} } | ||
| nLbxAt | Numérico (col) | Índice de la selección actual en aEditListTxt (sólo lectura útil en bOnChange) | ||
| bClrEdit | Bloque (col) | Color de edición para UNA columna: { | { CLR\_BLACK, CLR\_YELLOW } } | |
| bClrEdits | Bloque (browse) | Color de edición para TODAS las columnas del browse | ||
| bOnChange | Bloque (col) | Ejecutado al cambiar el valor durante la edición de esa columna | ||
| bOnChanges | Bloque (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 / Evento | Tipo | Descripción y Uso |
|---|---|---|
| CurrentRow() | Método | Retorna objeto TDataRow de la fila actual. Campos accesibles como oRow:First, oRow:Salary |
| oRow:Modified() | Método | Retorna .T. si hay cambios no guardados |
| oRow:Save() | Método | Guarda cambios del TDataRow en la fuente original |
| oRow:Undo() | Método | Descarta los cambios pendientes |
| oRow:oBrw | Objeto | Referencia al browse padre. Ej: oRow:oBrw:oFont, oRow:oBrw:Age:cEditPicture |
| ON DBLCLICK | Cláusula | @ X,Y XBROWSE ... ON DBLCLICK RowEdit( oBrw:CurrentRow() ) |
| DATABASE oObj | Comando | Crea 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étodo | Mueve foco a columna. lCenter=.T. centra la columna en vista |
| ColPos(oCol) | Método | Retorna posición visible de una columna |
| SelectedCol() | Método | Retorna el objeto columna actualmente con foco |
| nCreationOrder | Numé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 / Evento | Tipo | Descripción y Uso |
|---|---|---|
| oSortCbx | Objeto | Referencia a un ComboBox externo. XBrowse lo rellena con los índices disponibles y cambia el orden al seleccionar |
| cSortOrder | Cadena | Nombre del orden activo. Vinculable al VAR del ComboBox |
| AUTOSORT | Cláusula | Habilita ordenamiento por clic en encabezado de columna |
| nColorBox | Numérico | Color del recuadro de selección (estilo MARQSTYLE\_SOLIDCELL). Ej: CLR\_HRED |
| cHeaders | Array | Array de encabezados asignado vía código. Ej: oBrw:cHeaders := { "Nombre", "Apellido" } |
| lExcelCellWise | Lógico | Si .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 / Evento | Tipo | Descripción y Uso |
|---|---|---|
| Hide() | Método | Oculta el browse sin destruirlo |
| Show() | Método | Muestra un browse oculto |
| Enable() | Método | Habilita el browse para interacción del usuario |
| Disable() | Método | Deshabilita el browse (sin respuesta a teclado/mouse) |
| SetRDD() | Método | Cambia la fuente de datos RDD al área activa en ese momento. Ej: Customer-\>( oBrw:SetRDD() ) |
| REDEFINE XBROWSE | Comando | Vincula 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
