Creo preferible el usar cadenas en vez de números para identificar facilmente el contenido:
MsgStop( "Preview.dll not found", "Error" )
Sería:
MsgStop( FWString( "Preview.dll not found" ), FWString( "Error" ) )
Creo preferible el usar cadenas en vez de números para identificar facilmente el contenido:
MsgStop( "Preview.dll not found", "Error" )
Sería:
MsgStop( FWString( "Preview.dll not found" ), FWString( "Error" ) )
Antonio Linares wrote:Creo que la solución es usar una función FWString( "nombre_literal" ) que así permitiría reeemplazar la función por una propia facilmente sin tener que recompilar todo
Para establecer el lenguaje podriamos usar otra función como FWSetLanguage( "español" ), etc.
Comentarios ?
Un Saludo
Carlos G.
FiveWin 25.12 + Harbour 3.2.0dev (r2502110321), BCC 7.7 Windows 11 Home
#include "hashmsg.ch"#ifndef _HASHMSG_
#define _HASHMSG_
static FWMsgs := {=>}
#xtranslate TRICH_S_PRINTER_NOT_READY => FW_getMessages( "TRICH_S_PRINTER_NOT_READY" )
#xtranslate TRICH_V_FILE => FW_getMessages( "TRICH_V_FILE" )
#xtranslate TRICH_T_UNDO => FW_getMessages( "TRICH_T_UNDO" )
#xtranslate TRICH_T_REDO => FW_getMessages( "TRICH_T_REDO" )
#xtranslate TRICH_T_COPY => FW_getMessages( "TRICH_T_COPY" )
#xtranslate TRICH_T_CUT => FW_getMessages( "TRICH_T_CUT" )
#xtranslate TRICH_T_PASTE => FW_getMessages( "TRICH_T_PASTE" )
#xtranslate TRICH_T_DELETE => FW_getMessages( "TRICH_T_DELETE" )
#xtranslate TRICH_T_FONT => FW_getMessages( "TRICH_T_FONT" )
#xtranslate TRICH_T_ALIGN => FW_getMessages( "TRICH_T_ALIGN" )
#xtranslate TRICH_T_LEFT => FW_getMessages( "TRICH_T_LEFT" )
#xtranslate TRICH_T_CENTER => FW_getMessages( "TRICH_T_CENTER" )
#xtranslate TRICH_T_RIGHT => FW_getMessages( "TRICH_T_RIGHT" )
#xtranslate TRICH_T_JUSTIFY => FW_getMessages( "TRICH_T_JUSTIFY" )
#xtranslate TRICH_T_PRINT => FW_getMessages( "TRICH_T_PRINT" )
#xtranslate TRICH_T_SELECTALL => FW_getMessages( "TRICH_T_SELECTALL" )
#xtranslate TRICH_A_NOFILE_PROVIDE => FW_getMessages( "TRICH_A_NOFILE_PROVIDE" )
#xtranslate TRICH_Q_OVERWRITE => FW_getMessages( "TRICH_Q_OVERWRITE" )
#xtranslate TRICH_I_FOUND => FW_getMessages( "TRICH_I_FOUND" )
#xtranslate $_ => FW_getMessages()
#endif//----------------------------------------------------------------------------//
function FW_setMessages( h )
local hOld
hOld = FWMsgs
if h != NIL
FWMsgs = h
elseif( Len( FWMsgs ) == 0 )
FW_defMessages()
endif
return hOld
//----------------------------------------------------------------------------//
function FW_getMessages( c )
local cRet := "[]"
if c == NIL
return FWMsgs
endif
#ifdef __HARBOUR__
#ifndef __XHARBOUR__
if hb_HHASKEY( FWMsgs, c )
cRet = FWMsgs[ c ]
#else
if HHASKEY( FWMsgs, c )
#endif
cRet = FWMsgs[ c ]
endif
#endif
return cRet
//----------------------------------------------------------------------------//
static function FW_defMessages()
FWMsgs[ "FWMSG_PRUEBA1" ] = "Printer not ready!"
FWMsgs[ "TRICH_S_PRINTER_NOT_READY" ] = "Printer not ready!"
FWMsgs[ "TRICH_V_FILE" ] = "FWH RICHEDIT FILE"
FWMsgs[ "TRICH_T_UNDO" ] = "&Undo"
FWMsgs[ "TRICH_T_REDO" ] = "&Redo"
FWMsgs[ "TRICH_T_COPY" ] = "&Copy"
FWMsgs[ "TRICH_T_CUT" ] = "Cu&t"
FWMsgs[ "TRICH_T_PASTE" ] = "&Paste"
FWMsgs[ "TRICH_T_DELETE" ] = "&Delete"
FWMsgs[ "TRICH_T_FONT" ] = "&Font..."
FWMsgs[ "TRICH_T_ALIGN" ] = "A&lign"
FWMsgs[ "TRICH_T_LEFT" ] = "&Left"
FWMsgs[ "TRICH_T_CENTER" ] = "&Center"
FWMsgs[ "TRICH_T_RIGHT" ] = "&Right"
FWMsgs[ "TRICH_T_JUSTIFY" ] = "&Justify"
FWMsgs[ "TRICH_T_PRINT" ] = "P&rint"
FWMsgs[ "TRICH_T_SELECTALL" ] = "Select &All"
FWMsgs[ "TRICH_A_NOFILE_PROVIDE" ] = "No filename provided to save the richedit text"
FWMsgs[ "TRICH_Q_OVERWRITE" ] = "[FILENAME] already exists" + CRLF + "Do you want to overwrite it ?"
FWMsgs[ "TRICH_I_FOUND" ] = "something found"
return nil
//----------------------------------------------------------------------------//function SetWndDefault( oWnd )
oWndDefault := oWnd
FW_setMessages()
return nilMETHOD RButtonDown( nRow, nCol, nFlags ) CLASS TRichEdit
local oMenu, oClp
if GetFocus() != ::hWnd
::SetFocus()
SysRefresh()
if GetFocus() != ::hWnd
RETURN NIL
endif
endif
#ifdef __XPP__
#undef New
#endif
if ::bRClicked != NIL
return Eval( ::bRClicked, nRow, nCol, nFlags )
endif
DEFINE CLIPBOARD oClp OF Self FORMAT TEXT
MENU oMenu POPUP
#ifndef __XPP__
MENUITEM TRICH_T_UNDO ACTION ::UnDo() RESOURCE "UnDo" ;
WHEN ::CanUndo()
#else
MENUITEM TRICH_T_UNDO ACTION ::TRichEdit:UnDo() RESOURCE "UnDo" ;
WHEN ::CanUndo()
#endif
#ifndef __XPP__
MENUITEM TRICH_T_REDO ACTION ::ReDo() RESOURCE "ReDo" ;
WHEN ::CanRedo()
#else
MENUITEM TRICH_T_REDO ACTION ::TRichEdit:ReDo() RESOURCE "ReDo" ;
WHEN ::CanRedo()
#endif
SEPARATOR
#ifndef __XPP__
MENUITEM TRICH_T_CUT ACTION ::Cut() RESOURCE "Cut" ;
WHEN ::CanCut()
#else
MENUITEM TRICH_T_CUT ACTION ::TRichEdit:Cut() RESOURCE "Cut" ;
WHEN ::CanCut()
#endif
#ifndef __XPP__
MENUITEM TRICH_T_COPY ACTION ::Copy() RESOURCE "Copy" ;
WHEN ::CanCopy()
#else
MENUITEM TRICH_T_COPY ACTION ::TRichEdit:Copy() RESOURCE "Copy" ;
WHEN ::CanCopy()
#endif
#ifndef __XPP__
MENUITEM TRICH_T_PASTE ACTION ::Paste() RESOURCE "Paste" ;
WHEN ::CanPaste()
#else
MENUITEM TRICH_T_PASTE ACTION ::TRichEdit:Paste() RESOURCE "Paste" ;
WHEN ::CanPaste()
#endif
#ifndef __XPP__
MENUITEM TRICH_T_DELETE ACTION ::Del() RESOURCE "Del" ;
WHEN ::CanDel()
#else
MENUITEM TRICH_T_DELETE ACTION ::TRichEdit:Del() RESOURCE "Del" ;
WHEN ::CanDel()
#endif
SEPARATOR
#ifndef __XPP__
MENUITEM TRICH_T_FONT ACTION ::SetCharFormat() RESOURCE "Font" ;
WHEN !::lReadOnly
#else
MENUITEM TRICH_T_FONT ACTION ::TRIchEdit:SetCharFormat() RESOURCE "Font" ;
WHEN !::lReadOnly
#endif
MENUITEM TRICH_T_ALIGN WHEN !::lReadOnly
MENU
#ifndef __XPP__
MENUITEM TRICH_T_LEFT ACTION ::SetAlign( PFA_LEFT ) RESOURCE "Left" ;
WHEN !::lReadOnly
MENUITEM TRICH_T_CENTER ACTION ::SetAlign( PFA_CENTER ) RESOURCE "Center" ;
WHEN !::lReadOnly
MENUITEM TRICH_T_RIGHT ACTION ::SetAlign( PFA_RIGHT ) RESOURCE "Right" ;
WHEN !::lReadOnly
if ::lRE30
MENUITEM TRICH_T_JUSTIFY ACTION ::SetAlign( PFA_JUSTIFY ) RESOURCE "Justify" ;
WHEN !::lReadOnly
endif
#else
MENUITEM TRICH_T_LEFT ACTION ::TRichEdit:SetAlign( PFA_LEFT ) RESOURCE "Left" ;
WHEN !::lReadOnly
MENUITEM TRICH_T_CENTER ACTION ::TRichEdit:SetAlign( PFA_CENTER ) RESOURCE "Center" ;
WHEN !::lReadOnly
MENUITEM TRICH_T_RIGHT ACTION ::TRichEdit:SetAlign( PFA_RIGHT ) RESOURCE "Right" ;
WHEN !::lReadOnly
if ::lRE30
MENUITEM TRICH_T_JUSTIFY ACTION ::TRichEdit:SetAlign( PFA_JUSTIFY ) RESOURCE "Justify" ;
WHEN !::lReadOnly
endif
#endif
ENDMENU
SEPARATOR
#ifndef __XPP__
MENUITEM TRICH_T_PRINT ACTION ::Print() RESOURCE "Printer"
#else
MENUITEM TRICH_T_PRINT ACTION ::TRichEdit:Print() RESOURCE "Printer"
#endif
SEPARATOR
#ifndef __XPP__
MENUITEM TRICH_T_SELECTALL ACTION ::SelectAll() RESOURCE "SelAll"
#else
MENUITEM TRICH_T_SELECTALL ACTION ::TRichEdit:SelectAll() RESOURCE "SelAll"
#endif
ENDMENU
ACTIVATE POPUP oMenu AT nRow, nCol OF Self
return 0METHOD SaveToFile( cFileName ) CLASS TRichEdit
DEFAULT cFileName := ::cFileName
if Empty( cFileName )
MsgAlert( TRICH_A_NOFILE_PROVIDE )
return nil
endif
if File( cFileName )
if MsgYesNo( StrTran( TRICH_Q_OVERWRITE, "[FILENAME]", cFileName ) )
MemoWrit( cFileName, ::GetText() )
endif
else
MemoWrit( cFileName, ::GetText() )
endif
return nilMETHOD Search( cSearch ) CLASS TRichEdit
local nIndex := REFindText( ::hWnd, cSearch, .t. )
local nLine
if nIndex == -1
nLine = 0
else
MsgInfo( TRICH_I_FOUND )
nLine = ::SendMsg( EM_EXLINEFROMCHAR, 0, nIndex )
endif
MsgInfo( nLine )
return nLineMETHOD Print( cName ) CLASS TRichEdit
local aMargins := PageGetMargins()
local oPrn
DEFAULT cName := TRICH_V_FILE
if ::IsSelection()
PRINT oPrn NAME cName FROM USER SELECTION
else
PRINT oPrn NAME cName FROM USER
endif
if Empty( oPrn:hDC )
MsgStop( TRICH_S_PRINTER_NOT_READY )
return Self
endif
CursorWait()
AEval( aMargins, { |x,y| aMargins[ y ] := x * 1440 / 2540 } )
REPrint( ::hWnd, cName, oPrn:hDC, PrnGetPagNums(), PrnGetSelection(), ;
PrnGetCollate(), PrnGetPages(), PrnGetCopies(), aMargins )
CursorArrow()
ENDPRINT
return nil// FWH and FW++ RichEdit sample
#include "FiveWin.ch"
//----------------------------------------------------------------------------//
function Main()
local oDlg, oRich
local hRichDLL := LoadLibrary( "riched20.dll" )
local lSyntaxHL := .f.
//hay dos opciones
//1) llenamos primero nosotros el hash
// y despues lo modificamos antes de crear el Main Window
//2) Modificamos el hash despues de crear el Main Window
//descomentar para usar opcion 1
//FW_defMessages()
//ChangeFWMsg()
DEFINE DIALOG oDlg NAME "Test"
//Usando metodo 2
//comentar estas linea si va a usar el metodo 1
ChangeFWMsg()
oRich = TRichEdit():Redefine( 100, { || "" }, oDlg )
oRich:lHighLight = .f.
REDEFINE BUTTON ID 110 ;
ACTION oRich:SetText( MemoRead( "TestRich.prg" ) )
REDEFINE CHECKBOX lSyntaxHL ID 115 OF oDlg ;
ON CHANGE ( oRich:lHighLight := lSyntaxHL,;
oRich:SetText( oRich:GetText() ) )
REDEFINE BUTTON ID 120 ;
ACTION oRich:LoadFromRTFFile( cGetFile( "RTF file (*.rtf) | *.rtf" ) )
REDEFINE BUTTON ID 130 ;
ACTION oRich:SaveToRTFFile( cGetFile( "RTF file (*.rtf) | *.rtf",;
"Please write a filename", "test" ) )
REDEFINE BUTTON ID 998 ACTION ( oRich:GoToLine( 10 ), oRich:SetFocus() )
ACTIVATE DIALOG oDlg CENTERED ;
// ON INIT oRich:AutoURLDetect( .t. )
FreeLibrary( hRichDLL )
return nil
//----------------------------------------------------------------------------//
function ChangeFWMsg()
$_[ "TRICH_S_PRINTER_NOT_READY" ] = "El Impresor no está Listo!"
$_[ "TRICH_T_UNDO" ] = "&Reversar"
$_[ "TRICH_T_REDO" ] = "Re&hacer"
$_[ "TRICH_T_COPY" ] = "&Copiar"
$_[ "TRICH_T_CUT" ] = "C&ortar"
$_[ "TRICH_T_PASTE" ] = "&Pegar"
$_[ "TRICH_T_DELETE" ] = "&Borrar"
$_[ "TRICH_T_FONT" ] = "&Letra"
$_[ "TRICH_T_ALIGN" ] = "&Alineación"
$_[ "TRICH_T_LEFT" ] = "&Izquierda"
$_[ "TRICH_T_CENTER" ] = "C&entro"
$_[ "TRICH_T_RIGHT" ] = "&Derecha"
$_[ "TRICH_T_JUSTIFY" ] = "&Justificado"
$_[ "TRICH_T_PRINT" ] = "I&mprimir"
$_[ "TRICH_T_SELECTALL"] = "Seleccionar &Todo"
return nil
//----------------------------------------------------------------------------//lucasdebeltran wrote:Pero, ¿y no sería más sencillo MsgStop( FWString( "Preview.dll not found" ), FWString( "Error" ) ) ?.
$_[ "TRICH_T_UNDO" ] = "&Reversar"Daniel,
Muchas gracias por tu atención. Sin dudas, como ya comenté, tu solución es muy superior y la mía es muy sencillita y fácil de implementar. Además, hoy en día no hay problema para procesar un DO CASE/IF ENDIF con el Hardware actual, y además teniendo en cuenta que este proceso sólo se realiza en el caso de producirse un error, y afortunadamente no es siempre.
En todo caso, lo importante es poder disponer del resultado en todas las clases, sea cual fuere el método empleado. Si puede hacerse con tu solución pues estupendo. Va a ser una característica muy importante de la librería.
La idea de Lucas se puede implementar usando Hashes en lugar de DO/CASE o SWITH, con lo que desaparecería el problema de performance.
Cosas que son interesantes para tener:
1) Que me genere un log con las strings que no ha sabido traducir.
2) Se pueden usar las funciones de Harbour para interpretar archivos INI que te los deja transformados en Hashes para almacenar el texto traducido.
i18n es un término a buscar, de ahi podemos sacar ideas de como lo han resuelto en otros ámbitos (incluyendo Harbour, creo)
Hola,
¿Se sabe cuándo estará lista esta característica?. Pense qué iba a estar en esta nueva build.
Muchas gracias por vuestra atención.
Buenas tardes
Creo que, al margen de las soluciones propuestas, muy acertadas, quizás no estaría de más incluir como DATA bMnuRDown o algo así
Así en el METHOD RButtonDown( nRow, nCol, nFlags )
Entre ENDMENU y el Activate Menu oMenu POPUP AT .......
Se podría incluir el código:
ENDMENU
if !empty( ::bMnuRDown ) .and. Valtype( ::bMnuRDown ) = "B"
oMenu := Nil // Se podría guardar el menú ("oMenu") antes
oMenu := Eval( ::bMnuRDown, Self )
endif
ACTIVATE POPUP oMenu AT nRow, nCol OF Self
Para que cada uno pueda definir el Menú según sus necesidades, tanto de opciones, como otros aspectos ya comentados y, de momento también podría servir
Incluso se podría guardar el valor del objeto oMenu ya definido en una variable local para que si se devuelve a oMenu un valor <> "O", se restaure el menú por defecto.
Esta característica entiendo que podría extenderse a todos los controles que puedan usar un menú contextual ( METHOD RButtonDown ) si la DATA es añadida en Clases superiores
y poder definir el Menú contextual del cualquier control según tus necesidades.
Disculpen mi ignorancia, si esa posibilidad ya existe, ya que llevo distanciado de la programación cierto tiempo y no he podido conocer aún todos los avances que a día de hoy, ha tenido FW
Un saludo
Cristobal Navarro
Amigos de Fivetech,
Sí, por favor, necesitaría tener traducido de serie el menú de RichEdit.
Muy agradecida
![]()