6

Visual C++ 6 で記述された古いアプリケーションがあります。このアプリケーションの一部は、テキストをビットマップに描画することです。これは Windows XP では問題なく動作しますが、同じコードを Windows 7 で実行すると、すべてのテキストが ASCII テーブル内で 1 箇所シフトされます。

たとえば、 に"Category"なり"B'sdfnqx"ます。

これを引き起こしている原因とそれを修正する方法はありますか?

編集:申し訳ありませんが、上記は少し間違っています。コードで DrawText 関数を見たとき、それは GDI 関数だと思いました。私がそれに足を踏み入れると、作成者がDrawTextを使用している独自の関数を作成したことがわかりましたOpenGL。私は何も知らないOpenGLので、これは手に負えなくなりました。glCallListsテキスト( a に格納されている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の間で何か問題が発生していると思います.おそらくユニコードの問題か何か? 32 ビット Windows OS と 64 ビット OS の違いでしょうか。

これはより明白な問題を示していますか?

4

4 に答える 4

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変数は本来あるべきものから1つずれています。この行を次のように置き換えます

glListBase(m_id+1);

両方の場所で発生し、Windows 7 ではすべて問題ないはずです。ただし、XP は壊れます。

より良い修正は、付随するコメントが示唆するように、実際に印刷可能な文字のみを生成することです。そうすれば、コンピュータの 1 つに非印刷文字がなくても問題は発生しません。

于 2012-05-30T13:25:40.713 に答える
0

疑問に思っていたので見つけました。私は実際にそれがUNICODEのものであると疑っています。数年前、Visual C++ の新しいバージョンに移行しようとしたときに気付きました。問題は、2003 年以降のコンパイラが CString を wchar_t に自動的に typedef することである可能性が最も高いです。以下のリンク先の項目を見てください。

http://social.msdn.microsoft.com/forums/en-US/vclanguage/thread/fa43f4aa-1822-405e-a95f-9b6377b64352

于 2012-05-30T13:12:19.457 に答える
0

これは Windows XP では問題なく動作しますが、同じコードを Windows 7 で実行すると、すべてのテキストが ASCII テーブル内で 1 箇所シフトされます。

Windows 7 および Windows 8 の opengl32.dll では、glNewList/glEndList 間の表示リストの呼び出しに問題があります。

サンプル「glCallLists(strlen(text), GL_UNSIGNED_BYTE, text);」の回答を参照してください。

私の解決策:

「古い」opengl32.dllをXP(windows\system32)からプログラムフォルダーにコピーするだけです

于 2013-08-27T12:51:38.060 に答える
0

XP から Windows 7 に変更した後、このバグを確認できます。Windows からネイティブの opengl32.dll ドライバーを使用する場合 (RDP のように、グラフィックス カードのドライバーを使用しない場合)、glNewList/glEndList 間の glCallLists() に問題があります。

Lession 13 von NeHe http://nehe.gamedev.net/tutorial/bitmap_fonts/17002 を参照し、glPrint() を変更して、ASCII テーブルで 1 桁ずれた行と 2 番目の正しい行を書き込みます。(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 を表示リストに入力できます。リスト作成モードが GL_COMPILE_AND_EXECUTE であっても、表示リスト内のコマンドまたは glCallList または glCallLists によって実行されるリストは、作成中の表示リストには含まれません。

于 2013-08-18T14:55:27.810 に答える