你在做什麼是錯誤的,並且比在OpenGL中做這些都難。爲了解決向OpenGL繪製的窗口添加文本的問題,最好讓OpenGL繪製文本。當你處理WM_CREATE,在DC中選擇字體並調用wglUseFontBitmaps時,甚至可以使用與MFC中使用的字體完全相同的字體,這將創建一系列可與glCallLists一起使用的柵格化位圖。 (當你在這,分別調用GetCharABCWidths和GetTextMetrics來確定每個字形的寬度和高度。)
ABC glyphInfo[256]; // for font widths
TEXTMETRIC tm; // for font heights
// create a bitmap font
CFont myFont;
myFont.CreateFont(
16, // nHeight
0, // nWidth
0, // nEscapement
0, // nOrientation
FW_NORMAL, // nWeight
FALSE, // bItalic
FALSE, // bUnderline
0, // cStrikeOut
ANSI_CHARSET, // nCharSet
OUT_DEFAULT_PRECIS, // nOutPrecision
CLIP_DEFAULT_PRECIS, // nClipPrecision
DEFAULT_QUALITY, // nQuality
DEFAULT_PITCH | FF_SWISS, // nPitchAndFamily
_T("Arial") // lpszFacename
);
// change the current font in the DC
CDC* pDC = CDC::FromHandle(hdc);
// make the system font the device context's selected font
CFont *pOldFont = (CFont *)pDC->SelectObject (&myFont);
// the display list numbering starts at 1000, an arbitrary choice
wglUseFontBitmaps (hdc, 0, 255, 1000);
VERIFY(GetCharABCWidths (hdc, 0, 255, &glyphInfo[0]));
pDC->GetTextMetrics(&tm);
if(pOldFont)
pDC->SelectObject(pOldFont);
myFont.DeleteObject();
然後,當你處理WM_PAINT,重置矩陣並使用glRasterPos2d把文本你需要它去的地方。我建議使用類似於下面的代碼來計算字符串的確切寬度,如果你想要水平居中。
// indicate start of glyph display lists
glListBase (1000);
CRect r;
GetWindowRect(r);
glMatrixMode(GL_PROJECTION);
glPushMatrix();
glLoadIdentity();
gluOrtho2D(0, r.Width(), 0, r.Height());
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
glLoadIdentity();
CString formattedString;
formattedString.Format("Pi is about %1.2f", 3.1415);
int stringWidth=0; // pixels
for(int j=0; j < formattedString.GetLength(); ++j)
stringWidth += glyphInfo[ formattedString.GetAt(j) ].abcA + glyphInfo[ formattedString.GetAt(j) ].abcB + glyphInfo[ formattedString.GetAt(j) ].abcC;
double textXPosition, textYPosition;
textXPosition = r.Width()/2-stringWidth/2; // horizontally centered
textYPosition = r.Height()/2-tm.tmHeight/2; // vertically centered
glRasterPos2d(textXPosition,textYPosition);
// this is what actually draws the text (as a series of rasterized bitmaps)
glCallLists (formattedString.GetLength(), GL_UNSIGNED_BYTE, (LPCSTR)formattedString);
glMatrixMode(GL_MODELVIEW);
glPopMatrix();
glMatrixMode(GL_PROJECTION);
glPopMatrix();
雖然設置很煩人,但你只需要做一次,而且我認爲這不會比處理GDI更令人沮喪。混合使用GDI和OpenGL真的很麻煩,而且OpenGL在顯示文本方面做得非常好 - 您可以免費獲得亞像素精度,以及其他好處。爲了響應您對包含GUI元素的請求,我將假設您的意思是您希望同時擁有OpenGL繪製的窗口和標準Windows控件(編輯框,複選框,按鈕,列表控件)。等等)在同一個父窗口內。我還會假設你打算OpenGL只繪製窗口的一部分,而不是窗口的背景。
既然你說過使用MFC,我建議你創建一個對話框窗口,將所有的標準Windows控件添加到它,然後添加一個CWnd派生類,在其中處理WM_PAINT。使用資源編輯器將控件移動到您想要的位置。實際上,您在OpenGL正在執行繪圖時正在製作自定義控件。所以OpenGL將繪製該窗口,標準的MFC類(CEdit,CButton等)將繪製它們自己。這在我的經驗中效果很好,與GDI在所有者繪製控制中的作用沒有多大區別。
如果您希望OpenGL繪製窗口的背景,並且希望標準Windows控件出現在窗口的頂部,會怎麼樣?我不認爲這是一個好主意,但是你可以爲你的CDialog派生類處理WM_PAINT和WM_ERASE。在WM_ERASE中,調用OpenGL繪製3D內容,當WM_PAINT被調用時,將被標準Windows控件覆蓋。另外在WM_PAINT中,你可以在調用CDialog :: OnDraw之前調用OpenGL,這會很相似。
請澄清一下你的陳述「我想添加一些2s圖形覆蓋(如標籤,GUI元素)」如果你想我寫更多。
哪裏是opengl渲染代碼?應該在WM_PAINT,但我不能在你的代碼摘錄中看到它... –
@Felice Pollano:我想它是從空閒循環中調用的。 – datenwolf