Al hacer Copy/Paste desde un campo a otro, o desde el block de notas a un campo, me aparece un caracter extraño.

Alguien puede indicar la solución? Uso FW2407
Lima PERU
Fwh 24.07, xHb123_10193, MySQL 8.x, BCC 7.3

Buenos días. Muéstrenos cómo se ve su MENÚ PRINCIPAL y la configuración de inicio del programa.
Gracias, tks.
Regards, saludos.
Adjunto un pequeño test.
Si copian desde el block de notas la palabra "NAVIDEÑO" sobre el get, sale el caracter extraño.
Si copian sobre el campo memo, sale correcto.
#include "FiveWin.ch"
function Main()
local oDlg, oGet1, oGet2, v1 := space(50), v2 := space(100)
DEFINE DIALOG oDlg TITLE "Testing Gets"
@ 1, 1 GET oGet1 VAR v1 SIZE 90, 11
@ 2.5, 1 GET oGet2 VAR v2 SIZE 90, 40 MEMO
@ 3, 20 BUTTON "Ok" ACTION oDlg:End()
ACTIVATE DIALOG oDlg CENTERED
return nil
Hay algun cambio en la clase TGET que da ese problema.
HOla amigos----
incluye este codigo antes del Main()
HB_LANGSELECT( 'ES' ) //Selecciona lenguaje español
HB_SETCODEPAGE( 'ESWIN' )
HB_CDPSELECT("ESWIN")
HB_LangSelect( "ES" )
HB_CODEPAGE_ESWIN() //FW_SetUnicode( .t. )Ralph, I’m sure that in the end you will have to create a function manually, similar to this one – it’s only a template and for a different purpose. But with the codepages it never works for me.
Best regards,
Otto
function convertUmlaute( cVData )
local cTest := ""
local i := 0
// Beispiel zur Analyse einzelner Zeichen
// for i := 1 to Len( cVData )
// ? ( cVData + CRLF + SubStr( cVData, i, 1 ) + " # " + Str( Asc( SubStr( cVData, i, 1 ) ) ) )
// next
// Umlaute klein
cVData := StrTran( cVData, Chr( 228 ), "ä" )
cVData := StrTran( cVData, Chr( 132 ), "ä" )
cVData := StrTran( cVData, Chr( 246 ), "ö" )
cVData := StrTran( cVData, Chr( 148 ), "ö" )
cVData := StrTran( cVData, Chr( 252 ), "ü" )
cVData := StrTran( cVData, Chr( 129 ), "ü" )
// Umlaute groß
cVData := StrTran( cVData, Chr( 196 ), "Ä" )
cVData := StrTran( cVData, Chr( 142 ), "Ä" )
cVData := StrTran( cVData, Chr( 214 ), "Ö" )
cVData := StrTran( cVData, Chr( 153 ), "Ö" )
cVData := StrTran( cVData, Chr( 220 ), "Ü" )
cVData := StrTran( cVData, Chr( 154 ), "Ü" )
// ß
cVData := StrTran( cVData, Chr( 223 ), "ß" )
cVData := StrTran( cVData, Chr( 225 ), "ß" )
// Weitere Akzente
cVData := StrTran( cVData, Chr( 224 ), "à" )
cVData := StrTran( cVData, Chr( 225 ), "á" )
return cVData
//----------------------------------------------------------------------------//Willy, probé con tu codigo, sin exito. Reitero el problema: Si se puede escribir directamente en el Get los caracteres "Ñ" o con tilde. El problema es con el PASTE en la clase Tget.
Solo tienes que convertir la cadena del portapapeles con la función que te di. Así de simple. Comenta los caracteres de arriba para que puedas ver qué valores llegan desde el portapapeles
Puedes simplemente llamar a tu función de conversión desde ON CHANGE. No importa si el texto se introduce con el teclado o desde el portapapeles: ON CHANGE captura ambos casos.
Ralph:
Yo lo tengo así:
Antes del MAI() REQUEST HB_LANG_ES REQUEST HB_CODEPAGE_ESWIN
Dentro del MAIN HB_CDPSELECT("ESWIN") HB_LangSelect( "ESWIN" )
SET( _SET_CODEPAGE, "ESWIN" )
Ojalá te sirva
Saludos
Why clipboard text in Harbour/FiveWin often produces wrong characters
Many developers believe that clipboard issues can be solved by selecting the correct Harbour codepage (e.g., ESWIN, DEWIN, UTF8, etc.).
In practice, this does not work reliably.
Modern applications almost always copy text in UTF-8:
UTF-8 uses multiple bytes per character (for example, “ä” = C3 A4).
Harbour/FiveWin GETs, however, expect ANSI (Windows-1252) or OEM (CP850).
Result:
UTF-8 is mistakenly interpreted as ANSI → broken characters (“ä” instead of “ä”).
No Harbour codepage setting can prevent this.
For a Harbour codepage to work correctly, the following would have to be true:
Today, this is rarely the case.
The internet and modern software deliver UTF-8, not ANSI.
Therefore, these settings do not work reliably:
HB_CDPSELECT("ESWIN")
HB_LANGSELECT("ES")
SET( _SET_CODEPAGE, "ESWIN" )
Many developers solve the problem pragmatically:
cVData := StrTran( cVData, Chr(228), "ä" )
This works because it replaces byte-by-byte, independent of:
This has nothing to do with codepages – it is a manual mini-conversion that works reliably.
The “correct” solution would be:
Read clipboard data as UNICODE (CF_UNICODETEXT)
Then convert it manually to ANSI/UTF-8
FiveWin/Harbour GETs do not do this by default.
That’s why the well-known problems occur.
Con ayuda de Claude.ia encontré la solución a este problema en la clase tGet.
revisa la clase tGet de Fivewin/Harbour adjunta. Sucede lo siguiente:
- al hacer Copy/Paste desde un block de notas, las tildes y "ñ" se copian mal
- si copio desde una pagina web, hay veces en que se copian caracteres no visibles como saltos de linea
Puedes corregir esos problemas?
La solución de Claude:
1. Reemplazar el método Paste() de la clase tGet (la que uso es FWH2407)
2. Agregar 2 funciones a la clase tGet
Lo he probado y FUNCIONA!!!!
@AntonioLinares, puedes considerar esta corrección en las próximas versiones de FW
// =============================================================================
// PATCH para METHOD Paste() en tget.prg
// Fecha: 2026-03-11
//
// Problemas corregidos:
// 1. Tildes y "ñ" se corrompían al pegar desde Notepad (Windows 11)
// CAUSA: FW_GetClipBoardData( 13, .f. ) pedía CF_TEXT (formato ANSI),
// pero Notepad copia en CF_UNICODETEXT (Unicode).
// Al convertir Unicode→ANSI internamente Windows usaba la
// codepage del sistema (a veces CP1252) y se perdían los
// caracteres con acento.
// FIX: Leer primero el portapapeles en formato Unicode
// (FW_GetClipBoardData( 13, .T. ) o ClipboardGetText() en Wide),
// y luego convertir a UTF-8 si el GET es WideChar, o a ANSI si no.
//
// 2. Caracteres invisibles (CR, LF, TAB, etc.) al pegar desde el navegador
// CAUSA: Las páginas web copian texto con saltos de línea y otros
// caracteres de control que un GET de una sola línea no debería
// aceptar.
// FIX: Limpiar la cadena pegada con FW_CleanPaste() antes de usarla.
// =============================================================================
// ----------------------------------------------------------------------------
// Función auxiliar: limpia la cadena que viene del portapapeles
// Elimina caracteres de control invisibles (CR, LF, TAB, etc.)
// y normaliza espacios múltiples opcionales.
// ----------------------------------------------------------------------------
static function FW_CleanPaste( cText )
local i, c, cOut := ""
local nLen := Len( cText )
for i := 1 to nLen
c := SubStr( cText, i, 1 )
// Conservar solo caracteres imprimibles (>= Chr(32)) o caracteres UTF-8
// de alto byte (>= Chr(128)) que son parte de tildes/ñ en UTF-8.
// Descartar: Chr(0..31) salvo ninguno (incluye CR=13, LF=10, TAB=9, etc.)
if Asc( c ) >= 32 .or. Asc( c ) >= 128
cOut += c
endif
next
return cOut
// ----------------------------------------------------------------------------
// Función auxiliar: obtiene texto del portapapeles preferiendo Unicode
// para preservar tildes, ñ y otros caracteres especiales.
// Retorna la cadena en UTF-8 si lWideChar=.T., o en ANSI si lWideChar=.F.
// ----------------------------------------------------------------------------
static function FW_GetClipText( lWideChar )
local cText := ""
local oClp
// Intentar leer en Unicode (CF_UNICODETEXT) primero
// FW_GetClipBoardData( 13, .T. ) devuelve UTF-8 en FWH con Harbour
cText := FW_GetClipBoardData( 13, .T. ) // .T. = Unicode/Wide
if Empty( cText )
// Fallback: leer en ANSI
cText := FW_GetClipBoardData( 13, .F. )
if !Empty( cText ) .and. lWideChar
// Convertir ANSI → UTF-8 para GETs WideChar
cText := AnsiToUtf8( cText )
endif
else
if !lWideChar
// Convertir UTF-8 → ANSI para GETs normales
cText := Utf8ToAnsi( cText )
endif
endif
return cText
// ----------------------------------------------------------------------------
// METHOD Paste() - versión corregida
// Reemplaza el METHOD Paste() CLASS TGet existente en tget.prg
// ----------------------------------------------------------------------------
METHOD Paste( cPaste ) CLASS TGet
local cText, nLen, nPos, nDel
local nStart, nEnd // selection if any
local uOrgl, lAccept, V
local lChanged := .f.
if !( GetFocus() == ::hWnd )
return nil
endif
// *** FIX 1: Leer portapapeles preservando Unicode (tildes, ñ, etc.) ***
if cPaste == nil
cPaste := FW_GetClipText( ::IsWideChar )
endif
// *** FIX 2: Limpiar caracteres invisibles (CR, LF, TAB, etc.) ***
if !Empty( cPaste )
cPaste := FW_CleanPaste( cPaste )
endif
if !Empty( cPaste )
if ::bPaste != nil
return Eval( ::bPaste, cPaste, Self )
endif
uOrgl := ::cText
nLen := Len( ::oGet:Buffer )
nPos := ::oGet:Pos
nDel := If( ::oGet:Type $ "CM", 0, Len( cPaste ) )
::GetSelPos( @nStart, @nEnd )
if nEnd > nStart
nPos := nStart + 1
nDel := nEnd - nStart
endif
cText := HB_UTF8STUFF( ::oGet:Buffer, nPos, nDel, cPaste )
do case
case ::oGet:Type $ "CM"
cText := ::PadText( cText, nLen )
::cText := cText
::SetPos( Min( HB_UTF8LEN( cText ), nPos + HB_UTF8LEN( cPaste ) ) )
lChanged := .t.
case ::oGet:Type == "N"
if ( V := nStrToNum( cPaste, If( ::cPicture == nil, nil, "@E" $ ::cPicture ), .t. ) ) != nil
::cText := v
lChanged := .f.
endif
case ::oGet:Type == "D"
if !Empty( v := CTOD( cText ) )
::cText := v
lChanged := .t.
elseif !Empty( v := CTOD( cPaste ) )
::cText := v
lChanged := .t.
endif
case ::oGet:Type == "T"
#ifdef __XHARBOUR__
if !Empty( v := CTOT( cText ) )
#else
if !Empty( v := HB_CTOT( cText ) )
#endif
::cText := v
lChanged := .t.
endif
endcase
if lChanged .and. ::bChange != nil
lAccept := Eval( ::bChange,,, Self )
if HB_ISLOGICAL( lAccept ) .AND. !lAccept
::cText := uOrgl
::SetPos( nPos )
endif
endif
if ::oBtn != nil
::oBtn:Refresh()
endif
if ::oBtnLeft != nil
::oBtnLeft:Refresh()
endif
endif
return nilProbaste asi?
// C:\FWH\SAMPLES\RALPH01.PRG
#include "FiveWin.ch"
REQUEST HB_LANG_ES
REQUEST HB_CODEPAGE_ESWIN
#ifNdef __XHARBOUR__ // HARBOUR
REQUEST HB_CODEPAGE_UTF8
REQUEST HB_CODEPAGE_UTF8EX
#endif
FUNCTION Main()
LOCAL oDlg, oGet1, oGet2, v1 := space(50), v2 := space(100)
HB_CDPSELECT("ESWIN")
HB_LangSelect( "ESWIN" )
SET( _SET_CODEPAGE, "ESWIN" )
HB_SETCODEPAGE( "UTF8" )
HB_CDPSELECT( "UTF8EX" )
HB_CDPSELECT( "PTISO" )
V1 := "ARBOL NAVIDEÑO"
V2 := "ARBOL NAVIDEÑO"
DEFINE DIALOG oDlg TITLE "Testing Gets"
@ 1, 1 GET oGet1 VAR v1 SIZE 90, 11
@ 2.5, 1 GET oGet2 VAR v2 SIZE 90, 40 MEMO
@ 3, 20 BUTTON "Ok" ACTION oDlg:End()
ACTIVATE DIALOG oDlg CENTERED
RETURN NILRegards, saludos.
karinha wrote:Probaste asi?
si lo probé, pero no funcionó.
ralph wrote:Probaste asi?
si lo probé, pero no funcionó.
Cual FWH, BCC y Harbour ó xHarbour?
Gracias.
Regards, saludos.
Estimado Ralph,
Por lo visto parece que hay una solución más simple :)
El
DEFAULT cPaste := FW_GetClipBoardData( 13, .f. )Entonces
El método
Curiosamente, el manejador WM_PASTE con
Pero el
El parche tiene la intención correcta y funciona en la práctica, pero tiene algunos problemas técnicos:
El segundo parámetro de
Entonces en
cText := FW_GetClipBoardData( 13, .T. ) // .T. = Unicode/Wide ← comentario INCORRECTOif Asc( c ) >= 32 .or. Asc( c ) >= 128El
La corrección real es la conversión
La corrección puede ser mucho más simple — solo agregar unas líneas al
METHOD Paste( cPaste ) CLASS TGet
...
if cPaste == nil
cPaste := FW_GetClipBoardData( 13, .f. )
// FIX 1: Convertir UTF-8 → ANSI para GETs no-WideChar
if !Empty( cPaste ) .and. !::IsWideChar
cPaste := Utf8ToAnsi( cPaste )
endif
endif
// FIX 2: Eliminar caracteres de control (CR, LF, TAB, etc.)
if !Empty( cPaste )
cPaste := FW_CleanPaste( cPaste )
endif
...Esto evita el wrapper
La función estática
static function FW_CleanPaste( cText )
local i, c, cOut := ""
local nLen := Len( cText )
for i := 1 to nLen
c := SubStr( cText, i, 1 )
if Asc( c ) >= 32
cOut += c
endif
next
return cOut| Problema | Causa | Corrección |
|---|---|---|
| Tildes y ñ corruptas | Agregar | |
| Caracteres invisibles de web | CR, LF, TAB copiados del navegador | Filtrar con |