То, что вы делаете, неправильно и также сложнее, чем делать все это в OpenGL. Чтобы решить проблему добавления текста в нарисованное OpenGL окно , лучше просто заставить OpenGL рисовать текст. Вы даже можете использовать тот же шрифт, который вы использовали в MFC, создав экземпляр CFont при обработке WM_CREATE, выбрав шрифт в DC и вызвав wglUseFontBitmaps, который создаст серию растровых растровых изображений, которые вы можете использовать с glCallLists. (Пока вы это делаете, вызовите GetCharABCWidths и GetTextMetrics, чтобы определить ширину и высоту каждого глифа соответственно.)
</p>
<pre class="lang-cpp prettyprint-override"><code>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, чтобы поместить текст туда, куда вам нужно. Я предлагаю рассчитать точную ширину вашей строки, используя код, подобный приведенному ниже, если вы хотите, чтобы он был горизонтально центрирован.
</p>
<pre class="lang-cpp prettyprint-override"><code>// 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 отлично справляется с отображением текста - вы получаете бесплатную субпиксельную точность, помимо других преимуществ.
Редактировать: В ответ на ваш запрос о включении элементов графического интерфейса, я предполагаю, что вы имели в виду, что вы хотите иметь как нарисованные OpenGL окна, так и стандартные элементы управления Windows (поля редактирования, флажки, кнопки , список элементов управления и т. д.) в том же родительском окне. Я также предполагаю, что вы намерены OpenGL нарисовать только часть окна, а не фон окна.
Поскольку вы сказали, что используете MFC, я предлагаю создать диалоговое окно, добавить в него все свои стандартные элементы управления Windows, а затем добавить класс, производный от CWnd, где вы обрабатываете WM_PAINT. Используйте редактор ресурсов, чтобы переместить элемент управления туда, куда вы хотите. По сути, вы создаете пользовательский элемент управления для рисования, где OpenGL выполняет рисование. Таким образом, OpenGL нарисует это окно, и стандартные классы MFC (CEdit, CButton и т. Д.) Начнут рисовать сами. По моему опыту, это хорошо работает и на самом деле мало чем отличается от того, что GDI делает в элементе управления для рисования владельцем.
Что если вместо этого вы хотите, чтобы OpenGL рисовал фон окна, и чтобы стандартные элементы управления Windows отображались поверх него? Я не думаю, что это отличная идея, но вы можете обрабатывать WM_PAINT и WM_ERASE для своего класса, производного от CDialog. В WM_ERASE вызовите OpenGL, чтобы нарисовать ваш 3D-контент, который будет перезаписан стандартными элементами управления Windows при вызове WM_PAINT. В качестве альтернативы в WM_PAINT вы можете вызвать OpenGL перед вызовом CDialog :: OnDraw, что будет аналогично.
Пожалуйста, уточните ваше утверждение «Я хочу добавить несколько оверлеев графики 2s (например, метки, элементы графического интерфейса)», если вы хотите, чтобы я написал больше.