C++ – Rotate Text by 90 degrees with GDI

cgdi+winapiwindows

I want to draw text to a GDI Surface and rotate this text by 90 degrees counter clockwise. I would prefer to use DrawText to draw the text because it supports carriage return. I tried to use a font with lfEscapement (see the code below) but the line is not rotated – one line gets rendered over the other. Is there any possibility to rotate the text? Or to render without rotation and rotate the whole device context?


Normal text layout:

alt text


Rotated (desired result):

alt text

    case WM_PAINT:
    {
        hdc = BeginPaint(hWnd, &ps);

        LOGFONT lf = {0};
        HANDLE hFont;
        ZeroMemory(&lf, sizeof(LOGFONT));

        lf.lfWeight = FW_NORMAL;
        lstrcpy(lf.lfFaceName, _T("Tahoma"));
        lf.lfEscapement = 90;
        lf.lfHeight = 30;
        hFont = CreateFontIndirect (&lf);
        hFont = (HFONT)SelectObject (ps.hdc, hFont);

        RECT RectBody = {10,lf.lfHeight+10,::GetSystemMetrics(SM_CXSCREEN)-10,::GetSystemMetrics(SM_CYSCREEN)-lf.lfHeight-20};
        {
            ScopedLock lock(me->m_mutex);
            DrawText (ps.hdc, me->GetMessageString().c_str(), (int)me->GetMessageString().length(), &RectBody, 0);
        }

        hFont = (HFONT)SelectObject (ps.hdc, hFont);
        DeleteObject (hFont);

        EndPaint(hWnd, &ps);
        break;
    }

Best Answer

   lf.lfEscapement = 90;

That should be 900 to get the text vertical, units are 0.1 degrees.

Your plan to let DrawText take care of the line breaks is going to fall flat I'm afraid. I could not convince it to align the text properly. It aligns on the last line, not the first. Some code to play with:

    wchar_t* msg = L"Hello\r\nworld";
    RECT rcMeasure = {0, 0, 400, 0};
    DrawTextEx(hdc, msg, -1, &rcMeasure, DT_CALCRECT, 0);
    RECT rcDraw = {10, 30, 10 + rcMeasure.bottom - rcMeasure.top, 30 + rcMeasure.right - rcMeasure.left };
    FillRect(hdc, &rcDraw, (HBRUSH) (COLOR_WINDOW+2));
    SetTextAlign(hdc, TA_TOP | TA_CENTER);
    DrawTextEx(hdc, msg, -1, &rcDraw, DT_BOTTOM, 0);

I think I tried all alignment options.