I have an old application written in Visual C++ 6. Part of this app is drawing text into a bitmap. This works fine on Windows XP but when the same code is run on Windows 7 all the text is shifted by one place in the ASCII table.
For example, "Category"
becomes "B'sdfnqx"
.
Any ideas what is causing this and how to fix it?
Edit: Sorry but the above is slightly incorrect. When I saw the DrawText function in the code I assumed it was the GDI function. When I step into it, it turns out that the author has created their own DrawText
function which is using OpenGL
. I don't know any OpenGL
so this has now got out of hand. It calls glCallLists
which passes the text (stored in a CString
) into this function.
Full class code below. Note: it is the glCallLists function in the DrawText function causing the problem.
OGLFontClass::OGLFontClass()
{
m_id = -1;
}
OGLFontClass::~OGLFontClass()
{
Clear();
}
void OGLFontClass::Clear()
{
if( m_id != -1 )
{
glDeleteLists(m_id,255);
m_id = -1;
}
}
void OGLFontClass::Initialise(CString fontname, int size, HDC hDC)
{
m_HDC = hDC;
m_id = glGenLists(255);
::DeleteObject( m_FONT );
m_FONT = CreateFont( -size, // Height Of Font ( NEW )
0, // Width Of Font
0, // Angle Of Escapement
0, // Orientation Angle
FW_NORMAL, // Font Weight
FALSE, // Italic
FALSE, // Underline
FALSE, // Strikeout
ANSI_CHARSET, // Character Set Identifier
OUT_TT_PRECIS, // Output Precision
CLIP_DEFAULT_PRECIS, // Clipping Precision
ANTIALIASED_QUALITY, // Output Quality
FF_DONTCARE|DEFAULT_PITCH, // Family And Pitch
fontname); // Font Name
HFONT oldfont = (HFONT)SelectObject(hDC, m_FONT); // Selects The Font We Want
wglUseFontBitmaps(hDC, 0, 255, m_id ); // Builds 96 Characters Starting At Character 32
::SelectObject( hDC, oldfont );
}
void OGLFontClass::DrawText( float x, float y, CString str )
{
glRasterPos3f(x,y, 0);
glPushAttrib(GL_LIST_BIT);
glListBase(m_id);
glCallLists(str.GetLength(), GL_UNSIGNED_BYTE, str.GetBuffer(0));
glPopAttrib();
}
void OGLFontClass::DrawText(int x, int y, int r, int g, int b, CString text)
{
glMatrixMode(GL_PROJECTION);
glPushMatrix();
glLoadIdentity();// Reset The View
HWND hWnd = ::WindowFromDC(wglGetCurrentDC() );
RECT rc;
::GetClientRect( hWnd, &rc );
int CX = rc.right;//::GetSystemMetrics( SM_CXSCREEN );
int CY = rc.bottom;//::GetSystemMetrics( SM_CYSCREEN );
gluOrtho2D (0,::GetSystemMetrics(SM_CXSCREEN),::GetSystemMetrics(SM_CYSCREEN), 0);
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
glLoadIdentity();
glColor3ub(r,g,b);
glRasterPos2d( x, y ); // had to do this to get the text to line up where i want it
//glDisable(GL_TEXTURE_2D);
glPushAttrib(GL_LIST_BIT); // Pushes The Display List Bits ( NEW )
glListBase(m_id); // Sets The Base Character to 32 ( NEW )
unsigned char* szTemp = new unsigned char[text.GetLength()+1];
strcpy((char*)szTemp, text);
glCallLists(strlen((char*)szTemp), GL_UNSIGNED_BYTE, szTemp); // Draws The Display List Text ( NEW )
delete[] szTemp;
glPopAttrib(); // Pops The Display List Bits ( NEW )
glPopMatrix();
glMatrixMode(GL_PROJECTION);
glPopMatrix();
glMatrixMode(GL_MODELVIEW);
}
void OGLFontClass::DrawRightText( int x, int y, int r, int g, int b, CString text )
{
glMatrixMode(GL_PROJECTION);
glPushMatrix();
glLoadIdentity();// Reset The View
HWND hWnd = ::WindowFromDC(wglGetCurrentDC() );
RECT rc;
::GetClientRect( hWnd, &rc );
float CX = (float)::GetSystemMetrics( SM_CXSCREEN );
float CY = (float)::GetSystemMetrics( SM_CYSCREEN );
float fMultiplier = CX / CY;
gluOrtho2D (0,::GetSystemMetrics(SM_CXSCREEN),::GetSystemMetrics(SM_CYSCREEN), 0);
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
glLoadIdentity();
int nPos = x;
glColor3ub(r,g,b);
//glDisable(GL_TEXTURE_2D);
glPushAttrib(GL_LIST_BIT); // Pushes The Display List Bits ( NEW )
glListBase(m_id); // Sets The Base Character to 32 ( NEW )
for( int i = text.GetLength() - 1; i >= 0; i-- )
{
CString sChar = text.GetAt(i);
glRasterPos2d(nPos,y); // had to do this to get the text to line up where i want it
glCallLists(1, GL_UNSIGNED_BYTE, sChar); // Draws The Display List Text ( NEW )
if ( i > 0 )
{
CString sNextChar = text.GetAt(i-1);
SIZE szWidth = GetTextExtent(sNextChar);
szWidth.cx += 1;
szWidth.cx *= fMultiplier;
szWidth.cx += 1;
nPos -= szWidth.cx;
}
}
//glCallLists(strlen(text), GL_UNSIGNED_BYTE, text); // Draws The Display List Text ( NEW )
glPopAttrib(); // Pops The Display List Bits ( NEW )
glPopMatrix();
glMatrixMode(GL_PROJECTION);
glPopMatrix();
glMatrixMode(GL_MODELVIEW);
}
CSize OGLFontClass::GetTextExtent(CString text, float fFactor)
{
SIZE sz;
HFONT oldfont = (HFONT) SelectObject(m_HDC, m_FONT);
GetTextExtentPoint32(m_HDC,text,strlen(text),&sz);
SelectObject(m_HDC, oldfont);
sz.cx *= 0.2;
sz.cy *= 0.2;
return sz;
}
Now I don't know openGL at all but I'm assuming that as glCallLists
just reinterprets the string as a byte array there is something going wrong in this between Windows XP and Windows 7. Perhaps a unicode issue or something? 32-bit Windows OS versus 64-bit OS maybe?
Does this now show up a more obvious problem?
This line clearly doesn't do what its comment says:
wglUseFontBitmaps(hDC, 0, 255, m_id ); // Builds 96 Characters Starting At Character 32
Nor does this:
glListBase(m_id); // Sets The Base Character to 32 ( NEW )
Somehow, your m_id
variable is off by one from what it should be. Replace this line by
glListBase(m_id+1);
both places it occurs, and all should be well on Windows 7. But XP will break.
A better fix would be to actually generate only the printable characters, as the accompanying comments suggest. Then you'll not have issues if one of the computers is missing a non-printing character.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With