我有一个用Visual C ++ 6编写的旧应用程序。此应用程序的一部分是将文本绘制到位图中。这在Windows XP上运行正常,但是当在Windows 7上运行相同的代码时,所有文本都会在ASCII表中移动一个位置。
例如,"Category"
变为"B'sdfnqx"
。
任何想法导致了这个以及如何解决它?
编辑:抱歉,但上面的内容稍有不正确。当我在代码中看到DrawText函数时,我认为它是GDI函数。当我进入它时,结果是作者创建了他们自己的DrawText
函数,该函数正在使用OpenGL
。我不知道任何OpenGL
所以现在已经失控了。它调用glCallLists
将文本(存储在CString
中)传递给此函数。
下面的完整课程代码。注意:它是DrawText函数中的glCallLists函数导致问题。
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;
}
现在我根本不知道openGL,但我假设因为glCallLists
只是将字符串重新解释为字节数组,因此Windows XP和Windows 7之间出现了问题。也许是unicode问题或者其他的东西? 32位Windows操作系统与64位操作系统可能吗?
现在这会出现更明显的问题吗?
答案 0 :(得分:1)
这一行显然不符合其评论所说的内容:
wglUseFontBitmaps(hDC, 0, 255, m_id ); // Builds 96 Characters Starting At Character 32
这也不是:
glListBase(m_id); // Sets The Base Character to 32 ( NEW )
不知何故,你的m_id
变量与它应该是一个偏离。用
glListBase(m_id+1);
它发生的两个地方,并且在Windows 7上都应该很好。但是XP会破坏。
更好的解决方法是实际生成仅可打印的字符,如随附的评论所示。如果其中一台计算机缺少非打印字符,则不会出现问题。
答案 1 :(得分:0)
我发现了这个,因为这是我怀疑的。我实际上怀疑它是UNICODE的东西。我注意到这几年前我试图转向Visual C ++的更高版本。问题很可能是2003年以后的编译器自动将CStrings类型化为wchar_t。看看下面的链接项目。
http://social.msdn.microsoft.com/forums/en-US/vclanguage/thread/fa43f4aa-1822-405e-a95f-9b6377b64352
答案 2 :(得分:0)
从XP更改为Windows 7后,我可以确认此错误。 如果你从windows使用本机opengl32.dll驱动程序(没有来自你的grahpics卡的驱动程序,比如在RDP下),那么glNewList / glEndList之间的glCallLists()就会出现问题。
见第13课von NeHe http://nehe.gamedev.net/tutorial/bitmap_fonts/17002 并更改glPrint()以写入在ASCII表中移位一个位置的行和第二个正确的行。 (使用带有RDP屏幕的Windows 7)
GLvoid glPrint(const char *fmt, ...) // Custom GL "Print" Routine
{
char text[256]; // Holds Our String
va_list ap; // Pointer To List Of Arguments
if (fmt == NULL) // If There's No Text
return; // Do Nothing
va_start(ap, fmt); // Parses The String For Variables
vsprintf_s(text, fmt, ap); // And Converts Symbols To Actual Numbers
va_end(ap); // Results Are Stored In Text
//first text line
glRasterPos2f(-0.8f, 0);
GLuint List1 = glGenLists (1);
glNewList(List1, GL_COMPILE);
glPushAttrib(GL_LIST_BIT); // Pushes The Display List Bits
glListBase(base1); // Sets The Base Character to 32
glCallLists(strlen(text), GL_UNSIGNED_BYTE, text); // Draws The Display List Text
glPopAttrib(); // Pops The Display List Bits
glEndList();
glCallList(List1);
//second text line
glRasterPos2f(-0.8f, -0.2f);
glPushAttrib(GL_LIST_BIT); // Pushes The Display List Bits
glListBase(base1); // Sets The Base Character
glCallLists(strlen(text), GL_UNSIGNED_BYTE, text); // Draws The Display List Text
glPopAttrib(); // Pops The Display List Bits
}
这种麻烦的迹象: http://www.opengl.org/sdk/docs/man2/xhtml/glNewList.xml 可以将glCallList和glCallLists输入到显示列表中。 glCallList或glCallLists执行的显示列表或列表中的命令不包括在正在创建的显示列表中,即使列表创建模式为GL_COMPILE_AND_EXECUTE。
答案 3 :(得分:0)
这在Windows XP上工作正常,但运行相同的代码时 Windows 7中的所有文本在ASCII表中移动了一个位置。
来自Windows 7和Windows 8的opengl32.dll在glNewList / glEndList之间显示列表调用有问题
使用示例“glCallLists(strlen(text),GL_UNSIGNED_BYTE,text)查看答案;”
我的解决方案:
将“旧”opengl32.dll从XP(windows \ system32)简单复制到程序文件夹