Dudes, I did that!
I kept an ID for each class instance, and before calling any OpenGL function, I check if the GLWindow object is the "current" object, if not I made it current with the wglMakeCurrent() function.
GLWindow.h
Code:
#ifndef GLWINDOW_H
#define GLWINDOW_H
#include <Windows.h>
#include <gl/GL.h>
class GLWindow
{
public:
GLWindow(HWND hWindowHandle, UINT uiPixelWidth, UINT uiPixelHeight);
~GLWindow(){};
// Thrown exception values and their meanings:
// 1: Failed: GetDC()
// 2: Failed: ChoosePixelFormat()
// 3: Failed: SetPixelFormat()
// 4: Failed: wglCreateContext()
// 5: Failed: wglMakeCurrent()
void Initialize() throw(int);
// Thrown exception values and their meanings:
// 1: Failed: wglMakeCurrent()
// 2: Failed: wglDeleteContext()
void Destroy() throw(int);
void SetColor(GLubyte ubRed, GLubyte ubGreen, GLubyte ubBlue) const;
void PutPixel(UINT x, UINT y) const;
void ClearScreen() const;
// Thrown exception values and their meanings:
// 1: Failed: SwapBuffers()
void SwapBuffers() const throw(int);
protected:
double m_dbWidth;
double m_dbHeight;
HWND m_hWnd;
HDC m_hDC;
HGLRC m_hGLRC;
static unsigned int LAST_OBJECT_ID;
static unsigned int ACTIVE_OBJECT_ID;
unsigned int m_uiObjectId;
bool MakeCurrent() const;
};
#endif
GLWindow.cpp
Code:
#include "GLWindow.h"
#include <gl/GL.h>
unsigned int GLWindow::LAST_OBJECT_ID = 0;
unsigned int GLWindow::ACTIVE_OBJECT_ID = 0;
GLWindow::GLWindow(HWND hWindowHandle, UINT uiPixelWidth, UINT uiPixelHeight)
{
m_hWnd = hWindowHandle;
m_dbWidth = static_cast<double>(uiPixelWidth);
m_dbHeight = static_cast<double>(uiPixelHeight);
LAST_OBJECT_ID++;
m_uiObjectId = LAST_OBJECT_ID;
}
void GLWindow::Initialize() throw(int)
{
m_hDC = GetDC(m_hWnd);
if (m_hDC == NULL) throw(1);
PIXELFORMATDESCRIPTOR Pfd;
ZeroMemory(&Pfd, sizeof(Pfd));
Pfd.nSize = sizeof(Pfd);
Pfd.nVersion = 1;
Pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER;
Pfd.iPixelType = PFD_TYPE_RGBA;
Pfd.cColorBits = 24;
Pfd.cDepthBits = 16;
Pfd.iLayerType = PFD_MAIN_PLANE;
int iFormat = ChoosePixelFormat(m_hDC, &Pfd);
if (iFormat == 0) throw(2);
if (SetPixelFormat(m_hDC, iFormat, &Pfd) == FALSE) throw(3);
m_hGLRC = wglCreateContext(m_hDC);
if (m_hGLRC == NULL) throw(4);
if (this->MakeCurrent() == FALSE) throw(5);
////////////////
glEnable(GL_DEPTH_TEST);
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
glPushMatrix();
glLoadIdentity();
glScaled(2.0 / m_dbWidth, 2.0 / m_dbHeight, 1.0);
glTranslated(-m_dbWidth / 2.0, -m_dbHeight / 2.0, 0.0);
glBegin(GL_POINTS);
}
void GLWindow::Destroy() throw(int)
{
glEnd();
glPopMatrix();
glFlush();
if (wglMakeCurrent(m_hDC, NULL) == FALSE) throw(1);
ACTIVE_OBJECT_ID = 0;
if (wglDeleteContext(m_hGLRC) == FALSE) throw(2);
}
void GLWindow::SetColor(GLubyte ubRed, GLubyte ubGreen, GLubyte ubBlue) const
{
this->MakeCurrent();
glColor3ub(ubRed, ubGreen, ubBlue);
}
void GLWindow::PutPixel(UINT x, UINT y) const
{
this->MakeCurrent();
glVertex3i(static_cast<GLint>(x), static_cast<GLint>(y), 0);
}
void GLWindow::ClearScreen() const
{
this->MakeCurrent();
glEnd();
glClearColor(0.0f, 0.0f, 0.0f, 1.0f );
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glBegin(GL_POINTS);
}
void GLWindow::SwapBuffers() const throw(int)
{
this->MakeCurrent();
glEnd();
if (::SwapBuffers(m_hDC) == FALSE) throw(1);
glBegin(GL_POINTS);
}
bool GLWindow::MakeCurrent() const
{
bool bReturn;
if (ACTIVE_OBJECT_ID == m_uiObjectId) return true;
bReturn = wglMakeCurrent(m_hDC, m_hGLRC);
if (bReturn) ACTIVE_OBJECT_ID = m_uiObjectId;
return bReturn;
}
main.cpp
Code:
#include <Windows.h>
#include <string>
#include <gl/GL.h>
#include <math.h>
#include "GLWindow.h"
HWND g_hWnd;
const UINT WIN_WIDTH = 600;
const UINT WIN_HEIGHT = 400;
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd)
{
std::string ClassName("MyWindowClass");
WNDCLASSEX wcx;
wcx.cbSize = sizeof(wcx);
wcx.style = 0;
wcx.lpfnWndProc = DefWindowProc;
wcx.cbClsExtra = 0;
wcx.cbWndExtra = 0;
wcx.hInstance = hInstance;
wcx.hIcon = NULL;
wcx.hCursor = LoadCursor(NULL, IDC_ARROW);
wcx.hbrBackground = (HBRUSH) 1;
wcx.lpszMenuName = NULL;
wcx.lpszClassName = ClassName.c_str();
wcx.hIconSm = NULL;
ATOM Atom = RegisterClassEx(&wcx);
std::string WindowName("GLWindow Test");
g_hWnd = CreateWindowEx(0,
ClassName.c_str(),
WindowName.c_str(),
WS_OVERLAPPED | WS_VISIBLE | WS_TILEDWINDOW,
1300, 650,
WIN_WIDTH, WIN_HEIGHT,
HWND_DESKTOP,
(HMENU) NULL,
hInstance,
(LPVOID) NULL);
const UINT STATIC1_WIDTH = WIN_WIDTH / 2;
const UINT STATIC1_HEIGHT = WIN_HEIGHT / 2;
HWND hWndStatic1 = CreateWindowEx( 0,
"STATIC",
"My Static #1",
WS_VISIBLE | WS_CHILD,
0, 0,
WIN_WIDTH/2, WIN_HEIGHT/2,
g_hWnd,
(HMENU) NULL,
hInstance,
(LPVOID) NULL);
GLWindow glWnd1(hWndStatic1, WIN_WIDTH/2, WIN_HEIGHT/2);
glWnd1.Initialize();
const UINT STATIC2_WIDTH = WIN_WIDTH / 2;
const UINT STATIC2_HEIGHT = WIN_HEIGHT / 2;
HWND hWndStatic2 = CreateWindowEx( 0,
"STATIC",
"My Static #2",
WS_VISIBLE | WS_CHILD,
WIN_WIDTH/2, WIN_HEIGHT/2,
WIN_WIDTH/2, WIN_HEIGHT/2,
g_hWnd,
(HMENU) NULL,
hInstance,
(LPVOID) NULL);
GLWindow glWnd2(hWndStatic2, WIN_WIDTH/2, WIN_HEIGHT/2);
glWnd2.Initialize();
///////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////
//////////////// MY CODE STARTS HERE //////////////////////////////////
//////////////// STATIC CONTROL #1 ////////////////////////////////////
// Draw a diagonal line
for (UINT x=0, y; x<STATIC1_WIDTH; x++)
{
glWnd1.SetColor(255, (GLbyte) (255.0 * x / (double) STATIC1_WIDTH),
(GLbyte) (255.0 * x / (double) STATIC1_WIDTH));
y = ((double) STATIC1_HEIGHT / STATIC1_WIDTH) * x;
glWnd1.PutPixel(x, y);
}
// Display it on the screen
glWnd1.SwapBuffers();
// Draw a quarter of a circle
UINT x, y;
for (double teta=0.0; teta<1.5708 /* PI/2 */; teta+=0.001)
{
x = STATIC1_HEIGHT * cos(teta);
y = STATIC1_HEIGHT * sin(teta);
glWnd1.SetColor((GLbyte) (150.0 * teta),
(GLbyte) (256.0 - 150.0 * teta),
128.0);
glWnd1.PutPixel(x, y);
}
//////////////// STATIC CONTROL #2 ////////////////////////////////////
// Draw a rectangle
for (UINT x=STATIC2_WIDTH/4; x<3*STATIC2_WIDTH/4; x++)
{
glWnd2.SetColor(255, 128, 0);
glWnd2.PutPixel(x, STATIC2_HEIGHT/4);
glWnd2.SetColor(0, 128, 255);
glWnd2.PutPixel(x, 3*STATIC2_HEIGHT/4);
}
for (UINT y=STATIC2_HEIGHT/4; y<3*STATIC2_HEIGHT/4; y++)
{
glWnd2.SetColor(192, 128, 0);
glWnd2.PutPixel( STATIC2_WIDTH/4, y);
glWnd2.SetColor(0, 128, 192);
glWnd2.PutPixel(3*STATIC2_WIDTH/4, y);
}
// Display it on the screen
glWnd2.SwapBuffers();
// Draw a filled rectangle
for (UINT x=STATIC2_WIDTH/4; x<3*STATIC2_WIDTH/4; x++)
{
for (UINT y=STATIC2_HEIGHT/4; y<3*STATIC2_HEIGHT/4; y++)
{
glWnd2.SetColor(rand() % 256, rand() % 256, rand() % 256);
glWnd2.PutPixel(x, y);
}
}
/////////////// FINALIZE //////////////////////////////////////////////
// Switch between line and circle several times
for (UINT i=0; i<10; i++)
{
glWnd1.SwapBuffers();
glWnd2.SwapBuffers();
Sleep(1000);
}
// Close OpenGL engines
glWnd1.Destroy();
glWnd2.Destroy();
// Quit the program
PostQuitMessage(0);
/////////////// MY CODE ENDS HERE /////////////////////////////////////
///////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////
MSG Msg;
const UINT wMsgFilterMin = 0;
const UINT wMsgFilterMax = 0;
while (GetMessage(&Msg, (HWND) NULL, wMsgFilterMin, wMsgFilterMax) > 0)
{
TranslateMessage(&Msg);
DispatchMessage(&Msg);
}
return 0;
}
In this code, I'm running OpenGL on two independent STATIC windows. The code and its exe file are attached.