FiveTech Support Forums

FiveWin / Harbour / xBase community
Board index FiveWin para Harbour/xHarbour XBrowse edicci贸n en celda multilinea
Posts: 170
Joined: Mon Dec 12, 2005 09:56 AM

XBrowse edicci贸n en celda multilinea

Posted: Tue Jul 28, 2026 05:46 PM

Hola,
Estoy haciendo un XBrowse que en la segunda columna tiene que admitir varias l铆neas por celda porque se pueden escribir hasta 250 caracteres.

Es sobre un array y la segunda posici贸n del array tiene 250 caracteres, pero a la hora de escribir permite escribir cualquier cantidad de caracteres, hasta que le das Intro y entonces solo almacena los primeros 250 caracteres.

He probado con oBrwgest:acols[2]:cEditPicture := replicate('X',250) . Pero entonces al escribir no salta autom谩ticamente de linea al llegar el cursor a la derecha de la celda y hay que introducir el texto en una unica l铆nea aunque luego de dar intro ya salga bien.

Es decir, de que manera puedo hacer que salte de linea mientras se escribe y a la vez que no pueda escribir m谩s de 250 caracteres.

Saludos

 REDEFINE Xbrowse oBrwgest ARRAY alingest;
                              COLUMNS 1, 2, 3, 4;
                              COLSIZES 58,710,58,140;
                              HEADERS 'Contacto','MNEMO DE GESTION','Aplazado','Usuario'; //Contacto es una fecha
                              ID 103 OF oDlg  LINES CELL FASTEDIT
                              

oBrwgest:lVScroll := .T.

AEval( oBrwgest:aCols, {|o| o:nEditType := EDIT_GET} )
oBrwgest:nDataLines := 3

oBrwgest:bonchanges := {|| lcambiado := .t.}
oBrwgest:lautoappend := .t.
Posts: 8716
Joined: Tue Dec 20, 2005 07:36 PM

Re: XBrowse edicci贸n en celda multilinea

Posted: Tue Jul 28, 2026 06:03 PM

驴Estableciste:

   oBrw:lFastEdit := .t.

?

Saludos.

Jo茫o Santos - S茫o Paulo - Brasil - Phone: +55(11)95150-7341
Posts: 44508
Joined: Thu Oct 06, 2005 05:47 PM

Re: XBrowse edicci贸n en celda multilinea

Posted: Wed Jul 29, 2026 09:55 AM

Estimado Sebastian,

Aqui tienes un ejemplo funcionando:

// xbrml250.prg
// Verifies XBrowse multi-line cell edit with a hard 250-character limit.
//
// Why picture fails for multi-line:
//   cEditPicture forces TGet (single line) instead of TMultiGet.
// Correct approach:
//   nDataLines >= 2 + no picture  -> TMultiGet (auto word-wrap)
//   bOnPreEdit -> RTrim + LimitText( 250 )
//
// IMPORTANT:
//   If the array cell is already PadR(..., 250) / Space(250), Len() is already
//   250. LimitText(250) then blocks every keystroke because the control is full
//   (and TMultiGet does NOT SelectAll like TGet). Always RTrim before LimitText.

#include "FiveWin.ch"
#include "XBrowse.ch"

#define MAX_MNEMO  250

//----------------------------------------------------------------------------//

function Main()

   local oWnd, oBar, oBrw, oMsg
   local aData := SampleData()
   local cInfo := ""

   DEFINE WINDOW oWnd TITLE "XBrowse multi-line + LimitText(250)" ;
      FROM 1, 1 TO 28, 100

   DEFINE BUTTONBAR oBar OF oWnd SIZE 70, 22

   DEFINE BUTTON OF oBar PROMPT "Check" ;
      TOOLTIP "Show Len() of current MNEMO cell" ;
      ACTION ShowLen( oBrw )

   DEFINE BUTTON OF oBar PROMPT "Fill 250" ;
      TOOLTIP "Put exactly 250 real chars (no trailing pad)" ;
      ACTION FillMnemo( oBrw, aData, MAX_MNEMO, .F. )

   DEFINE BUTTON OF oBar PROMPT "Pad 250" ;
      TOOLTIP "PadR to 250 spaces 脭脟枚 shows the classic 'cannot type' bug if you drop RTrim" ;
      ACTION FillMnemo( oBrw, aData, 0, .T. )

   DEFINE BUTTON OF oBar PROMPT "Help" ;
      ACTION MsgInfo( ;
         "1. Click MNEMO and type 脭脟枚 text wraps at the cell edge (soft wrap)." + CRLF + ;
         "2. You cannot type/paste more than 250 characters." + CRLF + ;
         "3. ENTER          = end cell edit (save)." + CRLF + ;
         "4. Ctrl+ENTER or Shift+ENTER = one real line break." + CRLF + ;
         "5. ESC            = cancel edit." + CRLF + ;
         "6. 'Check' shows Len() of stored value." + CRLF + CRLF + ;
         "Soft wrap is only visual. Real newlines need Ctrl/Shift+ENTER.", ;
         "How to test" )

   @ 4.5, 0.5 XBROWSE oBrw OF oWnd ;
      ARRAY aData ;
      COLUMNS 1, 2, 3, 4 ;
      COLSIZES 80, 480, 70, 100 ;
      HEADERS "Contacto", "MNEMO DE GESTION", "Aplazado", "Usuario" ;
      LINES CELL FASTEDIT ;
      SIZE 700, 340 PIXEL

   oWnd:oClient = oBrw
   oBrw:lVScroll    := .T.
   oBrw:nDataLines  := 3
   oBrw:lAutoAppend := .T.

   AEval( oBrw:aCols, {| o | o:nEditType := EDIT_GET } )

   // Column 2: multi-line + max 250 chars
   // Leave cEditPicture empty so XBrowse creates TMultiGet
   oBrw:aCols[ 2 ]:bOnPreEdit := {| oCol | LimitMnemoEdit( oCol ) }

   // Keep stored value at most 250; optional PadR if you need fixed length
   oBrw:aCols[ 2 ]:bOnPostEdit := {| oCol, xVal, nKey | ;
      If( nKey != VK_ESCAPE .and. xVal != nil, ;
         oCol:Value := Left( xVal, MAX_MNEMO ), ) }

   oBrw:bOnChange := {|| ;
      cInfo := "Row " + LTrim( Str( oBrw:nArrayAt ) ) + ;
         "  |  Len = " + LTrim( Str( Len( oBrw:aRow[ 2 ] ) ) ) + ;
         "  RTrim = " + LTrim( Str( Len( RTrim( oBrw:aRow[ 2 ] ) ) ) ) + ;
         " / " + LTrim( Str( MAX_MNEMO ) ), ;
      If( oMsg != nil, oMsg:SetText( cInfo ), ) }

   oBrw:CreateFromCode()

   DEFINE MSGBAR oMsg PROMPT "Edit MNEMO: wrap + max 250 (RTrim before LimitText)" OF oWnd

   ACTIVATE WINDOW oWnd ;
      ON INIT ( oBrw:SetFocus(), oBrw:GoTop() )

return nil

//----------------------------------------------------------------------------//
// Called when the in-cell editor is ready (after TMultiGet is created).

static function LimitMnemoEdit( oCol )

   local oGet  := oCol:oEditGet
   local bOrig
   local c

   if oGet == nil
      return nil
   endif

   // Must free trailing spaces BEFORE LimitText, or Len is already 250
   // and the user cannot type a single character.
   if oGet:IsKindOf( "TMULTIGET" )
      c := RTrim( oGet:cText )
      oGet:cText := c
      oGet:LimitText( MAX_MNEMO )
      oGet:SetPos( Len( c ) )   // caret at end

  // XBrowse: plain ENTER ends edit (EditGetkeyDown).
  // Ctrl+ENTER / Shift+ENTER must NOT end edit and must insert ONE newline.
  // Do NOT call Replace(CRLF): the multiline EDIT already inserts a line
  // break via WM_CHAR (ES_WANTRETURN). Doing both produces two breaks.
  bOrig := oGet:bKeyDown
  oGet:bKeyDown := {| nKey | ;
     If( nKey == VK_RETURN .and. ;
        ( GetKeyState( VK_CONTROL ) .or. GetKeyState( VK_SHIFT ) ), ;
        nil, ;  // keep editing; let TMultiGet insert a single newline
        If( bOrig != nil, Eval( bOrig, nKey ), nil ) ) }

   elseif oGet:IsKindOf( "TGET" )
      oGet:LimitText( MAX_MNEMO )
   endif

return nil

//----------------------------------------------------------------------------//

static function SampleData()

   local a := {}

   // Store only real text (no PadR to 250). Pad only if your backend needs it,
   // and always RTrim in bOnPreEdit before LimitText.
   AAdd( a, { Date(), "Short note", .F., "ANA" } )
   AAdd( a, { Date() - 1, ;
      "This cell already holds a longer text so you can see multi-line display " + ;
      "with nDataLines = 3. Click to edit: typing wraps at the cell edge and " + ;
      "cannot exceed 250 characters thanks to LimitText in bOnPreEdit.", ;
      .T., "PEPE" } )
   AAdd( a, { Date() - 3, "", .F., "LUIS" } )
   // Row that mimics a fixed-length field (250 spaces / padded) 脭脟枚 still editable
   AAdd( a, { Date() - 5, PadR( "Padded field", MAX_MNEMO ), .F., "TEST" } )

return a

//----------------------------------------------------------------------------//

static function ShowLen( oBrw )

   local cText, nLen, nAt

   if oBrw:nLen < 1
      MsgInfo( "Browse is empty" )
      return nil
   endif

   nAt   := oBrw:nArrayAt
   cText := cValToChar( oBrw:aRow[ 2 ] )
   nLen  := Len( cText )

   MsgInfo( ;
      "Row: " + LTrim( Str( nAt ) ) + CRLF + ;
      "Len( MNEMO )       = " + LTrim( Str( nLen ) ) + CRLF + ;
      "Len( RTrim(MNEMO)) = " + LTrim( Str( Len( RTrim( cText ) ) ) ) + CRLF + CRLF + ;
      "First 80 chars:" + CRLF + Left( cText, 80 ), ;
      "Stored length" )

return nil

//----------------------------------------------------------------------------//

static function FillMnemo( oBrw, aData, nLen, lPadOnly )

   local c

   DEFAULT lPadOnly := .F.

   if oBrw:nLen < 1
      return nil
   endif

   if lPadOnly
      c := PadR( "Padded to 250", MAX_MNEMO )
   else
      c := Replicate( "X", nLen )
   endif

   aData[ oBrw:nArrayAt, 2 ] := c
   oBrw:RefreshCurrent()
   MsgInfo( "Assigned Len=" + LTrim( Str( Len( c ) ) ) + ;
      "  RTrim=" + LTrim( Str( Len( RTrim( c ) ) ) ) + CRLF + ;
      "Click the cell and type 脭脟枚 should accept input up to 250.", ;
      "Fill MNEMO" )

return nil

//----------------------------------------------------------------------------//
regards, saludos

Antonio Linares
www.fivetechsoft.com
Posts: 170
Joined: Mon Dec 12, 2005 09:56 AM

Re: XBrowse edicci贸n en celda multilinea

Posted: Wed Jul 29, 2026 04:09 PM

Perfecto Antonio, funciona muy bien. Lo del codebloq bOnPreEdit no lo conoc铆a. Muchas gracias.

Continue the discussion