TextOutW unicode support depends on the length of the text

Zoltán Hegedüs 101 Reputation points
2021-03-23T11:16:52.027+00:00

My English is not perfect, sorry.

I am using Visual C++ 2019 16.9.2 Community, and MFC. At debug mode, at the start of my program, there is an assertion error in a file what is part of MFC, at the line 666. So, I used release mode, IA-32 and AMD64 CPU architecture. I am using Consolas font, with size 9. At Visual Studio text editor, and at LibreOffice Writer (a word processor), this works correct. The most characters have the same width, some have not, but the cursor is always between 2 characters. Wide characters for example:

∧∨∃∄∀∈∉∌∋∪⊂⊆⊄⊈⊃⊅⊇⊉⇒⇔≪≫∇⊥▲▼◆◇

I tried CDC::GetCharWidth, CDC::GetOutputCharWidth, CDC::GetCharABCWidths. The most chacters are 20 pixel wide (3-times scale: 3*96 dpi = 288 dpi at Windows's setting), 6 characters have 0 width (not ABC-width). The ABC widths of the characters I wrote have 20 pixel width. I tried 0 instead of a negative A, C, width, but this did not help. But there is a bigger problem. These characters look correct if there are other characters after them. If has not, these are unknown unicodes:

const wchar_t text[] = L"∧∨∃∄∀∈∉∌∋∪⊂⊆⊄⊈⊃⊅⊇⊉⇒⇔≪≫∇⊥▲▼◆◇";  
pDC->TextOutW(4, 0, text);  
pDC->TextOutW(4, 60, L"0000000000000000000000000000");  
for (int i = 0, pos = 4; text[i]; pos += 20, ++i)  
    pDC->TextOutW(pos, 120, text+i, 1);  
// ::TextOutW((HDC) *pDC, pos, 120, text+i, 1);  

I tried CDC:: and global form of TextOutW so. This can not display these characters correctly. The number of 0s is 28 = number of special characters in text[].

Windows API - Win32
Windows API - Win32
A core set of Windows application programming interfaces (APIs) for desktop and server applications. Previously known as Win32 API.
2,430 questions
C++
C++
A high-level, general-purpose programming language, created as an extension of the C programming language, that has object-oriented, generic, and functional features in addition to facilities for low-level memory manipulation.
3,546 questions
0 comments No comments
{count} votes

Accepted answer
  1. Viorel 112.7K Reputation points
    2021-03-24T16:43:20.05+00:00

    To solve the drawing problem of TextOut, consider a powerful alternative — DrawText:

    for( int i = 0, pos = 4; text[i]; pos += 20, ++i )
    {
       pDC->DrawText( text + i, 1, CRect( CPoint( pos, 120 ), CSize( 0, 0 ) ), DT_LEFT | DT_TOP | DT_NOCLIP | DT_NOPREFIX );
    }
    

1 additional answer

Sort by: Most helpful
  1. Zoltán Hegedüs 101 Reputation points
    2021-03-23T15:49:56.167+00:00

    Workaround: write 2 characters: what must, and after it, what's code is 0 (space is not suit):

    pDC->SetTextAlign(TA_UPDATECP);
    pDC->MoveTo(4, 120);
    wchar_t tt[2] = {0, 0};
    for (int i = 0; text; ++i) {
        tt[0] = text[i];
        pDC->TextOutW(0, 0, tt, 2);
        CPoint const xy = pDC->GetCurrentPosition();
        pDC->MoveTo(xy.x-20, xy.y);  // 20 is the width of the character of code 0
    }
    

    There are project files so, so there are a lot of files, and I can not upload a .zip to here: not allowed. I tried to rename to .pdf, but the websize analyzes the content of the file.