Pintar texto de abajo a arriba, un posible bug y un workaround

Pues eso.


Para pintar texto en vertical, es necesario pasar al método DrawString un último parámetro, una instancia de StringFormat con lo siguiente:



m_stringFormat=gcnew StringFormat();
m_stringFormat->FormatFlags=StringFormatFlags::DirectionVertical;



Pero esto nos dibuja el texto de arriba hacia abajo y mirando hacia la izquierda. Si nosotros queremos hacerlo justo al revés, de abajo hacia arriba, y mirando hacia la derecha, hasta donde he podido llegar, no se puede hacer directamente.

La solución obvia consiste en cambiar las coordenadas del dispositivo, rotándolas 180 grados, y pintar. En mi caso, sobre la propia ficha. Pero no he conseguido que funcione, si toco las rotaciones o las traslaciones, pese a lo que dice la documentación y el Petzold, no se pinta nada (y no porque me salga de la superficie, no).


Así que debemos optar por la solución más compleja, que consiste en pintar sobre un bitmap oculto y luego copiarlo a la superficie de la ficha:



Bitmap ^bmp=gcnew Bitmap(m_editNumberRect[m_idxCurrentEditing].Width,m_editNumberRect[m_idxCurrentEditing].Height,e->Graphics);
Graphics ^g=Graphics::FromImage(bmp);
g->TranslateTransform((
float)(m_editNumberRect[m_idxCurrentEditing].Width+15),(float)m_editNumberRect[m_idxCurrentEditing].Height);
g
->ScaleTransform(-1,-1);
g->DrawString(m_editNumber[m_idxCurrentEditing],m_textFont,Brushes::Black,0,0,m_stringFormat);
e->Graphics->DrawImage(bmp,m_editNumberRect[m_idxCurrentEditing]);


Creamos un bitmap de las dimensiones deseadas compatible con la pantalla actual. Luego obtenemos la superficie para pintar sobre el propio bitmap. La tercera línea (TranslateTransform) desplaza el origen de coordenadas para que al hacer la inversión mediante ScaleTransform pintemos el texto mediante DrawString en el mismo sitio que antes de rotar. De este modo, hemos pintado el texto rotado 180 grados.



Hacerlo de la forma fácil, es decir:


g->TranslateTransform(…);
e->Graphics->ScaleTransform(-1,-1);
e->Graphics->DrawString(m_editNumber[m_idxCurrentEditing],m_textFont,Brushes::Black,m_editNumberRect[m_idxCurrentEditing],m_stringFormat);


simplemente no funciona, quizás porque se me escape algo.


En el código de ejemplo, el que el ancho esté desplazado 15 píxeles no es otra cosa que el desplazamiento causado por la altura de la letra; como la aplicación va a ir en un ordenador replicado, no es necesario liarse con las métricas de las fuentes.


Y eso es todo, que no siempre es cuestión de despotricar. 😛

4 comentarios sobre “Pintar texto de abajo a arriba, un posible bug y un workaround”

  1. Has probado a utilizar las matrices de transformación junto con la clase Graphics? Si pintas en horizontal, pero antes de pintar le aplicas una transformación para que gire 90º (o son 270º?), y luego restauras la matriz (para que no te salga girado) debería de funcionar sin problemas…

  2. Por último, y perdón por ser tan pesao…

    Si quieres que funcione la rotación, lo que tendrías que hacer es lo siguiente:

    Si quieres pintar el texto en la coordenada (x,y), girándolo n grados:

    1.- Aplicar una traslación a (-x, -y).
    2.- Aplicar una rotación a n grados.
    3.- Pintar
    4.- Aplicar una rotación a -n grados.
    5.- Aplicar una traslación a (x,y).

    El orden ha de ser ese. De otro modo, no se hará correctamente…

    Saludos, y siento no haber puesto todo en un mismo comentario. Si lo puedes moderar y arrejuntarlo todo…. Pues mejor 😉

  3. Tranquilo, lo que haré es escribir una nueva entrada con las cosas bien hechas en cuanto tenga un rato… que será después de navidades.

    Da por supuesto que citaré tu método (Y a ti como su autor).

    La cuestión es que eso mismo que comentas no me está funcionando (de hecho no consigo pintar nada), y ya lo he resuelto de la otra forma. Si tengo tiempo, que pienso que no, lo corregiré en mi aplicación y volveré a poner la entrada, y si no, cuando acabe lo que tengo entre manos, entonces lo probaré con cuidado.

Responder a aruiz Cancelar respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *