MFC and OpenGL Programming Snippets Reference
MFC Metafile Operations
Metafile Handling: HENHMETAFILE fork; ENHMETAHEADER forkHeader; Constructor: fork = GetEnhMetaFile(_T("viljuska.emf"));
If the fork is not null:
if (fork != NULL)
{
GetEnhMetaFileHeader(fork, sizeof(ENHMETAHEADER), &forkHeader);
}Destructor:
if (met)
{
DeleteEnhMetaFile(met);
met = NULL;
}Dimensions and Playback:
int w = forkHeader.rclBounds.right;
int h = forkHeader.rclBounds.bottom;
pDC->PlayMetaFile(fork, CRect(0, 0, w, h));Saving Metafiles:
ONSAVE()
{
CRect rect(0, 0, 1000, 1000);
HDC hdcMeta = CreateEnhMetaFile(NULL, _T("img.emf"), &rect, _T("PUT\SLIKE"));
if (hdcMeta) {
CDC dc;
dc.Attach(hdcMeta);
dc.Rectangle();
// ...
dc.Ellipse();
HENHMETAFILE hmf = CloseEnhMetaFile(hdcMeta);
DeleteEnhMetaFile(hmf);
}
}Anti-Flicker Techniques in MFC
CRect rect;
GetClientRect(&rect);
CDC memDC;
memDC.CreateCompatibleDC(pDC);
CBitmap bmp;
bmp.CreateCompatibleBitmap(pDC, rect.Width(), rect.Height());
CBitmap* oldbmp = memDC.SelectObject(&bmp);
int oldmode = memDC.SetGraphicsMode(GM_ADVANCED);
XFORM form;
memDC.GetWorldTransform(&form);
// ...
memDC.SetWorldTransform(&form);
memDC.SetGraphicsMode(oldmode);
pDC->BitBlt(0, 0, rect.Width(), rect.Height(), &memDC, 0, 0, SRCCOPY);
memDC.SelectObject(oldbmp);
memDC.DeleteDC();
BOOL CGDIView::OnEraseBkgnd(CDC* pDC) {
return TRUE;
}Keyboard Events and Transformations
OnKeyDown Event
afx_msg void OnKeyDown (UINT nChar, UINT nRepCnt, UINT nFlags) Ctrl + Shift + X
if (nChar == 'R' || nChar == 'r') {
angle += 5;
Invalidate();
}
CView::OnKeyDown(nChar, nRepCnt, nFlags);Supported Virtual Keys: VK_LEFT, Return, Space, Escape, Tab, 'A', Add, Subtract
Transformations
#define _USE_MATH_DEFINES
#include <cmath>
float toRad(float angle) {
return angle * M_PI / 180;
}
void Translate(CDC* pDC, float x, float y, bool rightMultiply) {
XFORM xform{1, 0, 0, 1, x, y};
pDC->ModifyWorldTransform(&xform, rightMultiply ? MWT_RIGHTMULTIPLY : MWT_LEFTMULTIPLY);
}
// Rotate
float rad = toRad(angle);
// {cos(rad), sin(rad), -sin(rad), cos(rad), 0, 0}
// Scale
// {x, 0, 0, y}
// Mirror
// {x ? -1 : 1, 0, 0, y ? -1 : 1}Draw Transparent Images
void DImage::DrawTransparent(CDC* pDC, DImage* pImage) {
int w = pImage->Width();
int h = pImage->Height();
CRect rect(0, 0, w, h);
CDC* srcDC = new CDC();
srcDC->CreateCompatibleDC(pDC);
CDC* dstDC = new CDC();
dstDC->CreateCompatibleDC(pDC);
CBitmap* src = new CBitmap();
src->CreateCompatibleBitmap(pDC, w, h);
CBitmap* dst = new CBitmap();
dst->CreateBitmap(w, h, 1, 1, nullptr);
CBitmap* srcOld = srcDC->SelectObject(src);
CBitmap* dstOld = dstDC->SelectObject(dst);
pImage->Draw(srcDC, rect, rect); // dest, target, source
srcDC->SetBkColor(srcDC->GetPixel(0, 0));
dstDC->BitBlt(0, 0, w, h, srcDC, 0, 0, SRCCOPY); // Copies color image to mono DC. All BkColor becomes WHITE, rest BLACK.
srcDC->SetBkColor(RGB(0, 0, 0)); // Background black
srcDC->SetTextColor(RGB(255, 255, 255)); // Text white
srcDC->BitBlt(0, 0, w, h, dstDC, 0, 0, SRCAND); // Background becomes black
pDC->BitBlt(0, 0, w, h, dstDC, 0, 0, SRCAND); // Creates black hole in object shape
pDC->BitBlt(0, 0, w, h, srcDC, 0, 0, SRCPAINT); // Paints the object
dstDC->SelectObject(dstOld);
srcDC->SelectObject(srcOld);
dstDC->DeleteDC();
delete dstDC;
srcDC->DeleteDC();
delete srcDC;
delete src;
delete dst;
}OpenGL Renderer Setup and Scene Management
Prepare Scene
glClearColor(1.0, 1.0, 1.0, 1.0);
glEnable(GL_DEPTH_TEST);
glEnable(GL_TEXTURE_2D);
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
glEnable(GL_LIGHT1);
glEnable(GL_NORMALIZE);
glEnable(GL_COLOR_MATERIAL);
glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE);
float amb[] = { 0.5, 0.5, 0.5, 1.0 };
float diff[] = { 1.0, 1.0, 1.0, 1.0 };
float spec[] = { 1.0, 1.0, 1.0, 1.0 };
glLightfv(GL_LIGHT0, GL_AMBIENT, amb);
glLightfv(GL_LIGHT0, GL_DIFFUSE, diff);
glLightfv(GL_LIGHT0, GL_SPECULAR, spec);
glLightfv(GL_LIGHT1, GL_AMBIENT, amb);
glLightfv(GL_LIGHT1, GL_DIFFUSE, diff);
glLightfv(GL_LIGHT1, GL_SPECULAR, spec);
texLamp = LoadTexture("lamp.jpg");
texBot = LoadTexture("bot.jpg");
texSide = LoadTexture("side.jpg");
texTop = LoadTexture("top.jpg");Draw Scene
void CGLRenderer::DrawScene(CDC *pDC) {
wglMakeCurrent(pDC->m_hDC, m_hrc);
// -----------------------------
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
float globalAmb[] = { 0.3, 0.3, 0.3, 1.0 };
glLightModelfv(GL_LIGHT_MODEL_AMBIENT, globalAmb);
float pos0[] = { 0.0, 0.0, 1.0, 0.0 };
glLightfv(GL_LIGHT0, GL_POSITION, pos0);
X = r * cos(toRad(ang)) * cos(angY);
Z = r * sin(toRad(ang)) * cos(angY);
Y = r * sin(angY);
gluLookAt(X, Y, Z, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);
glTranslated(0.0, 150.0, 0.0);
DrawEnvCube(300);
glTranslated(0.0, -149.0, 0.0);
DrawAxes();
float pos1[] = { 0.0, 1.0, 1.0, 0.0 };
glLightfv(GL_LIGHT1, GL_POSITION, pos1);
DrawLamp();
glFlush();
SwapBuffers(pDC->m_hDC);
// -----------------------------
wglMakeCurrent(NULL, NULL);
}Reshape and Destroy Scene
void CGLRenderer::Reshape(CDC *pDC, int w, int h) {
glViewport(0, 0, (GLsizei)w, (GLsizei)h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(50, (double)w / (double)h, 0.1, 2000.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
wglMakeCurrent(NULL, NULL);
}
void CGLRenderer::DestroyScene(CDC *pDC) {
wglMakeCurrent(pDC->m_hDC, m_hrc);
// ...
glDeleteTextures(1, &texBot);
glDeleteTextures(1, &texLamp);
glDeleteTextures(1, &texSide);
glDeleteTextures(1, &texTop);
wglMakeCurrent(NULL, NULL);
if (m_hrc) {
wglDeleteContext(m_hrc);
m_hrc = NULL;
}
}GluLookAt Configuration
- eyeX, eyeY, eyeZ: Camera position (lens location).
- centerX, centerY, centerZ: Target point the camera is looking at.
- upX, upY, upZ: Camera rotation orientation (e.g., 0, 1, 0).
- Axis Colors: X is Blue, Y is Red, Z is Green.
Load Texture
UINT CGLRenderer::LoadTexture(char* fileName) {
UINT texID;
DImage img;
img.Load(CString(fileName));
glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
glGenTextures(1, &texID);
glBindTexture(GL_TEXTURE_2D, texID);
glTexParameteri(GL_TEXTURE_2D, TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, TEXTURE_WRAP_T, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
gluBuild2DMipmaps(GL_TEXTURE_2D, GL_RGBA, img.Width(), img.Height(), GL_BGRA_EXT, GL_UNSIGNED_BYTE, img.GetDIBBits());
return texID;
}OpenGL 3D Primitive Shapes
Draw Sphere
void DrawSphere(float r, int nSeg) {
float a1, a2, a3, c1, s1, c2, s2, c3, s3;
for (int i = 0; i < nSeg; i++) {
a1 = -1.57079f + i * 3.14159f / nSeg;
a2 = a1 + 3.14159f / nSeg;
s1 = sin(a1); c1 = cos(a1);
s2 = sin(a2); c2 = cos(a2);
glBegin(GL_QUAD_STRIP);
for (int j = 0; j <= 2 * nSeg; j++) {
a3 = j * 3.14159f / nSeg;
s3 = sin(a3); c3 = cos(a3);
glNormal3f(c1 * c3, s1, c1 * s3);
glTexCoord2f((float)j / (2 * nSeg), (float)i / nSeg);
glVertex3f(c1 * c3 * r, s1 * r, c1 * s3 * r);
glNormal3f(c2 * c3, s2, c2 * s3);
glTexCoord2f((float)j / (2 * nSeg), (float)(i + 1) / nSeg);
glVertex3f(c2 * c3 * r, s2 * r, c2 * s3 * r);
}
glEnd();
}
}Draw Cylinder
void DrawCylinder(float r, float h, int nSeg) {
float a, c, s, u;
glBegin(GL_QUAD_STRIP); // Body
for (int i = 0; i <= nSeg; i++) {
a = 2.0f * M_PI * i / nSeg;
c = cos(a);
s = sin(a);
u = (float)i / nSeg;
glNormal3f(c, 0.0f, s);
glTexCoord2f(u, 0.0f);
glVertex3f(c * r, -h / 2.0f, s * r);
glTexCoord2f(u, 1.0f);
glVertex3f(c * r, h / 2.0f, s * r);
}
glEnd();
glNormal3f(0.0f, 1.0f, 0.0f);
glBegin(GL_TRIANGLE_FAN); // Top cap
glTexCoord2f(0.5f, 0.5f);
glVertex3f(0, h / 2.0f, 0);
for (int i = 0; i <= nSeg; i++) {
a = 2.0f * M_PI * i / nSeg;
glTexCoord2f(0.5f + cos(a) * 0.5f, 0.5f + sin(a) * 0.5f);
glVertex3f(cos(a) * r, h / 2.0f, sin(a) * r);
}
glEnd();
glNormal3f(0.0f, -1.0f, 0.0f);
glBegin(GL_TRIANGLE_FAN); // Bottom cap
glTexCoord2f(0.5f, 0.5f);
glVertex3f(0, -h / 2.0f, 0);
for (int i = 0; i <= nSeg; i++) {
a = -2.0f * 3.14159f * i / nSeg;
glTexCoord2f(0.5f + cos(a) * 0.5f, 0.5f + sin(a) * 0.5f);
glVertex3f(cos(a) * r, -h / 2.0f, sin(a) * r);
}
glEnd();
}Draw Cone
void DrawCone(float r, float h, int nSeg) {
float a, c, s, u;
glBegin(GL_TRIANGLE_FAN); // Body
glNormal3f(0.0f, 1.0f, 0.0f); // Approximate normal for the tip
glTexCoord2f(0.5f, 1.0f);
glVertex3f(0, h / 2.0f, 0); // Cone tip
for (int i = 0; i <= nSeg; i++) {
a = 2.0f * 3.14159f * i / nSeg;
c = cos(a);
s = sin(a);
glNormal3f(c, h / r, s); // Normal tilted along cone side
glTexCoord2f((float)i / nSeg, 0.0f);
glVertex3f(c * r, -h / 2.0f, s * r);
}
glEnd();
glNormal3f(0.0f, -1.0f, 0.0f);
glBegin(GL_TRIANGLE_FAN); // Bottom cap
glTexCoord2f(0.5f, 0.5f);
glVertex3f(0, -h / 2.0f, 0);
for (int i = 0; i <= nSeg; i++) {
a = -2.0f * 3.14159f * i / nSeg;
glTexCoord2f(0.5f + cos(a) * 0.5f, 0.5f + sin(a) * 0.5f);
glVertex3f(cos(a) * r, -h / 2.0f, sin(a) * r);
}
glEnd();
}
English with a size of 10.48 KB