2009-11-23 31 views
8

Tengo problemas para obtener un control RichEdit para mostrar texto RTF Unicode. Mi aplicación es Unicode, por lo que todas las cadenas son cadenas wchar_t.
Si creo el control como "RichEdit20A" puedo usar, p. SetWindowText, y el texto se muestra con el formato adecuado. Si creo el control como "RichEdit20W", usar SetWindowText muestra el texto textualmente, es decir, se muestra todo el código RTF. Lo mismo ocurre si uso el parámetro EM_SETTEXTEX, especificando la página de códigos 1200 que me dice MSDN que se usa para indicar unicode.
He intentado utilizar la función StreamIn, pero esto parece funcionar solo si transmito en texto ASCII. Si conecto en modo ancho, obtengo texto vacío en el control. Yo uso los indicadores SF_RTF | SF_UNICODE, y MSDN insinúa que esta combinación puede no estar permitida.Texto RTF Unicode en RichEdit

¿Qué hacer? ¿Hay alguna forma de convertir Widechars en un RichEdit sin perder la interpretación de RTF, o debo codificarlo? He pensado en probar UTF-8, o quizás usar las funciones de codificación en RTF, pero no estoy seguro de cuál es la mejor opción.

Respuesta

10

Tuve que hacer esto recientemente, y noté el mismo tipo de observaciones que estás haciendo.

Parece que, a pesar de lo que MSDN casi sugiere, el analizador "RTF" solo funcionará con codificaciones de 8 bits. Entonces, lo que terminé haciendo fue usar UTF-8, que es una codificación de 8 bits, pero aún puede representar toda la gama de caracteres Unicode. Puede obtener UTF-8 de un PWSTR través WideCharToMultiByte():

PWSTR WideString = /* Some string... */; 
DWORD WideLength = wcslen(WideString) + 1; 
PSTR Utf8; 
DWORD Length; 
INT ReturnedLength; 

// A utf8 representation shouldn't be longer than 4 times the size 
// of the utf16 one. 
Length = WideLength * 4; 
Utf8 = malloc(Length); 
if (!Utf8) { /* TODO: handle failure */ } 

ReturnedLength = WideCharToMultiByte(CP_UTF8, 
            0, 
            WideString, 
            WideLength-1, 
            Utf8, 
            Length-1, 
            NULL, 
            NULL); 
if (ReturnedLength) 
{ 
    // Need to zero terminate... 
    Utf8[ReturnedLength] = 0; 
} 
else { /* TODO: handle failure */ } 

Una vez que lo tienes en UTF-8, que puede hacer:

SETTEXTEX TextInfo = {0}; 

TextInfo.flags = ST_SELECTION; 
TextInfo.codepage = CP_UTF8; 

SendMessage(hRichText, EM_SETTEXTEX, (WPARAM)&TextInfo, (LPARAM)Utf8); 

Y, por supuesto (me dejó esto en un principio, pero mientras yo estoy siendo explícita ...):

free(Utf8); 
+0

Funciona perfectamente. ¡Muchas gracias! –

1

RTF es ASCII, cualquier Charactor de ASCII se codifica mediante la secuencia de escape. RTF 1.9.1 specification (March 2008)

+0

La especificación de formato de archivo puede decir eso, pero puede obtener el control RichEdit para cargar RTF con cualquier codificación de varios bytes, incluido CP_UTF8 como se muestra en mi respuesta. – asveikau

1

Tome un vistazo a \ uN literal en la especificación RTF lo que tiene que convertir su amplia cadena a cadena de caracteres Unicode, como \ u902? \ U300? \ U888? http://www.biblioscape.com/rtf15_spec.htm#Heading9 Los números en este caso representan el código decimal de caracteres y el signo de interrogación es el carácter que reemplazará el carácter unicode en caso de que RichEdit no admita unicode (RichEdit v1.0).

Por ejemplo, para la cadena Unicode L "TIME" los datos rtf serán "\ u84? \ U73? \ U77? \ U69?"

+0

Es una de las soluciones que he probado con éxito, pero no muy conveniente. En este caso, la cadena rtf como, por ejemplo, "{\\ rtf1 bla bla \\ u931?}" (La sintaxis del lenguaje C++ se usa para codificar caracteres de barra diagonal inversa) se puede codificar en UTF-16 y se mostrará correctamente. Cuando se codifica en UTF-16 directamente (sin palabra de control \ uN), es decir "{\\ rtf1 bla bla Σ}", la letra griega sigma (código 0x03A3) se mostrará en libras £ (código 0xA3). – truthseeker