OpenGL GLCallList在Windows 7上绘制不正确的字符 我有一个用Visual C++ 6编写的旧应用程序。这个应用程序的一部分是将文本绘制成位图。这在Windows XP上运行得很好,但是当在Windows 7上运行相同的代码时,所有文本在ASCII表中移动一个位置
例如,OpenGL GLCallList在Windows 7上绘制不正确的字符 我有一个用Visual C++ 6编写的旧应用程序。这个应用程序的一部分是将文本绘制成位图。这在Windows XP上运行得很好,但是当在Windows 7上运行相同的代码时,所有文本在ASCII表中移动一个位置,c++,opengl,windows-7,C++,Opengl,Windows 7,例如,“Category”变成了“B'sdfnqx” 你知道是什么原因造成的,以及如何修复吗 编辑:抱歉,上面的内容有点不正确。当我在代码中看到DrawText函数时,我假设它是GDI函数。当我进入它时,发现作者已经创建了自己的DrawText函数,它使用的是OpenGL。我不知道任何OpenGL,所以这已经失控了。它调用glCallLists,将文本(存储在CString中)传递到此函数 下面是完整的课程代码。注意:导致问题的是DrawText函数中的GLCallList函数 OGLFontC
“Category”
变成了“B'sdfnqx”
你知道是什么原因造成的,以及如何修复吗
编辑:抱歉,上面的内容有点不正确。当我在代码中看到DrawText函数时,我假设它是GDI函数。当我进入它时,发现作者已经创建了自己的DrawText
函数,它使用的是OpenGL
。我不知道任何OpenGL
,所以这已经失控了。它调用glCallLists
,将文本(存储在CString
中)传递到此函数
下面是完整的课程代码。注意:导致问题的是DrawText函数中的GLCallList函数
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位操作系统可能会有什么不同
这是否显示出一个更明显的问题?我发现了这一点,因为这正是我所怀疑的。我实际上怀疑这是一个UNICODE的东西。几年前,我注意到我试图移到Visual C++的后期版本。问题很可能是2003年以后的编译器自动将cstring类型化为wchar\t。请看下面的链接项
这一行显然没有做到其评论所说的:
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);
这两种情况都会发生,而且在Windows7上应该都很好。但是XP会崩溃
一个更好的解决方案是,如附带的注释所示,实际上只生成可打印的字符。如果其中一台计算机缺少非打印字符,则不会出现问题。从XP更改为Windows 7后,我可以确认此错误。 如果使用windows中的本机opengl32.dll驱动程序(没有grahpicscard中的驱动程序,如RDP下的驱动程序),则glNewList/glEndList之间的GLCallList()存在问题 见Lession 13 von NeHe 并更改glPrint()以写入一行,在ASCII表中移位一位,然后写入第二行。(使用带RDP屏幕的Windows 7) 此故障的迹象: glCallList和glCallList可以输入到显示列表中。 即使列表创建模式为“GLU编译”和“GLU执行”,由glCallList或glCallList执行的一个或多个显示列表中的命令也不包括在正在创建的显示列表中 这在Windows XP上运行良好,但在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)复制到您的程序文件夹中这是一个多么棘手的问题啊。我想自己知道答案,尽管它不会影响我:-)。谢谢。希望我能得到一个很好的答案;)当然,这个问题与所使用的字体无关。@Sachin:不,最低级别的问题似乎是对字体字形的索引不正确(一个接一个),因此字体技术可能非常相关。一个完整的例子甚至比知道哪种字体更好。我猜传递给glCallLists的基本列表号是硬编码的,而不是使用glGenLists返回的值。而且glGenLists在不同的PC上返回不同的值。您可能需要检查。代码不会在较新的编译器中重新编译。它是在XP上运行良好的可执行文件,而不是在Win7上运行。这似乎与unicode无关。不过还是要谢谢你。事实上,考虑到所有的底层DLL很可能在XP和7之间发生了变化,它仍然是可能的。考虑到输出功能只是通过更改正在运行的操作系统而无需重新编译来更改,这一点非常明显。DrawText例程中正在进行字符串复制。强制使用相同的DLL没有任何区别。实际上,原始代码没有那个字符串副本。只是我把代码弄得乱七八糟,我在这里发布之前忘了把它放回去。因此,字符串副本与问题无关。只是出于好奇,DrawText例程的较短版本(没有r、g、b)是否正常工作?我知道。我想写这段代码的人是从互联网上下载下来的,他在没有修改注释的情况下修改了值。正如我所说,这不是我的代码。身份证很好。它们是正确的值。我检查了又检查了一遍。@Jonnster:如果你做
wglUseFontBitmaps(hDC,'a',26,m_id+'a')代码>在现有的wgluseFontBitmap
之后?您是否尝试过在每次使用控制台时将m_id
打印到控制台?可能您有一个无效的此
指针,导致使用的m\u id
的副本已损坏。m\u id始终有效且始终是正确的值。我尝试将其更改为m_id+1,并且打印的字符完全相同。这很奇怪,但我不懂OpenGL,所以没有什么会让我感到惊讶;)@琼斯特:首先,两个DrawText
函数中哪一个表现不好?较长的DrawText函数。我添加了WgluseFontBitmap(hDC,'a',26,m_id+'a');代码,它仍然打印与以前相同的字符。
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
}