Click here to Skip to main content
15,893,722 members
Articles / Web Development / IIS

An OpenGL ActiveX Control Developed with MFC

Rate me:
Please Sign up or sign in to vote.
4.80/5 (11 votes)
22 Nov 19993 min read 294.2K   8K   58  
// GL3dOcxCtl.cpp : Implementation of the CGL3dOcxCtrl ActiveX Control class.

#include "stdafx.h"
#include "GL3dOcx.h"
#include "GL3dOcxCtl.h"
#include "GL3dOcxPpg.h"


#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif


IMPLEMENT_DYNCREATE(CGL3dOcxCtrl, COleControl)


/////////////////////////////////////////////////////////////////////////////
// Message map

BEGIN_MESSAGE_MAP(CGL3dOcxCtrl, COleControl)
	//{{AFX_MSG_MAP(CGL3dOcxCtrl)
	ON_WM_CREATE()
	ON_WM_DESTROY()
	ON_WM_PAINT()
	ON_WM_LBUTTONDBLCLK()
	ON_WM_PALETTECHANGED()
	ON_WM_QUERYNEWPALETTE()
	//}}AFX_MSG_MAP
	ON_OLEVERB(AFX_IDS_VERB_PROPERTIES, OnProperties)
END_MESSAGE_MAP()


/////////////////////////////////////////////////////////////////////////////
// Dispatch map

BEGIN_DISPATCH_MAP(CGL3dOcxCtrl, COleControl)
	//{{AFX_DISPATCH_MAP(CGL3dOcxCtrl)
	DISP_PROPERTY_EX(CGL3dOcxCtrl, "Content", GetContent, SetContent, VT_BSTR)
	DISP_FUNCTION(CGL3dOcxCtrl, "GLRender", GLRender, VT_EMPTY, VTS_NONE)
	DISP_FUNCTION(CGL3dOcxCtrl, "SetStrText", SetStrText, VT_EMPTY, VTS_BSTR)
	DISP_STOCKPROP_READYSTATE()
	//}}AFX_DISPATCH_MAP
	DISP_FUNCTION_ID(CGL3dOcxCtrl, "AboutBox", DISPID_ABOUTBOX, AboutBox, VT_EMPTY, VTS_NONE)
END_DISPATCH_MAP()


/////////////////////////////////////////////////////////////////////////////
// Event map

BEGIN_EVENT_MAP(CGL3dOcxCtrl, COleControl)
	//{{AFX_EVENT_MAP(CGL3dOcxCtrl)
	EVENT_CUSTOM("GLDraw", FireGLDraw, VTS_NONE)
	EVENT_STOCK_READYSTATECHANGE()
	//}}AFX_EVENT_MAP
END_EVENT_MAP()


/////////////////////////////////////////////////////////////////////////////
// Property pages

// TODO: Add more property pages as needed.  Remember to increase the count!
BEGIN_PROPPAGEIDS(CGL3dOcxCtrl, 1)
	PROPPAGEID(CGL3dOcxPropPage::guid)
END_PROPPAGEIDS(CGL3dOcxCtrl)


/////////////////////////////////////////////////////////////////////////////
// Initialize class factory and guid

IMPLEMENT_OLECREATE_EX(CGL3dOcxCtrl, "GL3DOCX.GL3dOcxCtrl.1",
	0xa015e022, 0x7691, 0x11d3, 0x95, 0x5d, 0x84, 0x22, 0xf5, 0xc0, 0, 0)


/////////////////////////////////////////////////////////////////////////////
// Type library ID and version

IMPLEMENT_OLETYPELIB(CGL3dOcxCtrl, _tlid, _wVerMajor, _wVerMinor)


/////////////////////////////////////////////////////////////////////////////
// Interface IDs

const IID BASED_CODE IID_DGL3dOcx =
		{ 0xa015e020, 0x7691, 0x11d3, { 0x95, 0x5d, 0x84, 0x22, 0xf5, 0xc0, 0, 0 } };
const IID BASED_CODE IID_DGL3dOcxEvents =
		{ 0xa015e021, 0x7691, 0x11d3, { 0x95, 0x5d, 0x84, 0x22, 0xf5, 0xc0, 0, 0 } };


/////////////////////////////////////////////////////////////////////////////
// Control type information

static const DWORD BASED_CODE _dwGL3dOcxOleMisc =
	OLEMISC_ACTIVATEWHENVISIBLE |
	OLEMISC_IGNOREACTIVATEWHENVISIBLE |
	OLEMISC_SETCLIENTSITEFIRST |
	OLEMISC_INSIDEOUT |
	OLEMISC_CANTLINKINSIDE |
	OLEMISC_RECOMPOSEONRESIZE;

IMPLEMENT_OLECTLTYPE(CGL3dOcxCtrl, IDS_GL3DOCX, _dwGL3dOcxOleMisc)


/////////////////////////////////////////////////////////////////////////////
// CGL3dOcxCtrl::CGL3dOcxCtrlFactory::UpdateRegistry -
// Adds or removes system registry entries for CGL3dOcxCtrl

BOOL CGL3dOcxCtrl::CGL3dOcxCtrlFactory::UpdateRegistry(BOOL bRegister)
{
	// TODO: Verify that your control follows apartment-model threading rules.
	// Refer to MFC TechNote 64 for more information.
	// If your control does not conform to the apartment-model rules, then
	// you must modify the code below, changing the 6th parameter from
	// afxRegApartmentThreading to 0.

	if (bRegister)
		return AfxOleRegisterControlClass(
			AfxGetInstanceHandle(),
			m_clsid,
			m_lpszProgID,
			IDS_GL3DOCX,
			IDB_GL3DOCX,
			afxRegApartmentThreading,
			_dwGL3dOcxOleMisc,
			_tlid,
			_wVerMajor,
			_wVerMinor);
	else
		return AfxOleUnregisterClass(m_clsid, m_lpszProgID);
}


/////////////////////////////////////////////////////////////////////////////
// CGL3dOcxCtrl::CGL3dOcxCtrl - Constructor

CGL3dOcxCtrl::CGL3dOcxCtrl()
{
	InitializeIIDs(&IID_DGL3dOcx, &IID_DGL3dOcxEvents);

	m_lReadyState = READYSTATE_LOADING;
	// TODO: Call InternalSetReadyState when the readystate changes.

	// TODO: Initialize your control's instance data here.
    m_String = "3DOCX"; 

	m_shininess = 10.0f;
	m_Lightposition[0] = 100.0f;
	m_Lightposition[1] = 0.0f;
	m_Lightposition[2] = 0.0f;
	m_Lightposition[3] = 0.0f;
	m_Lightspecular[0] = 0.3f;
	m_Lightspecular[1] = 0.3f;
	m_Lightspecular[2] = 0.1f;
	m_Lightspecular[3] = 1.0f;
	m_Lightdiffuse[0] = 0.1f;
	m_Lightdiffuse[1] = 0.1f;
	m_Lightdiffuse[2] = 0.1f;
	m_Lightdiffuse[3] = 1.0f;
	m_Lightambient[0] = 0.3f;
	m_Lightambient[1] = 0.3f;
	m_Lightambient[2] = 0.3f;
	m_Lightambient[3] = 1.0f;

	m_cx = 0;
	m_cy = 0;
}


/////////////////////////////////////////////////////////////////////////////
// CGL3dOcxCtrl::~CGL3dOcxCtrl - Destructor

CGL3dOcxCtrl::~CGL3dOcxCtrl()
{
	// TODO: Cleanup your control's instance data here.
}


/////////////////////////////////////////////////////////////////////////////
// CGL3dOcxCtrl::OnDraw - Drawing function

void CGL3dOcxCtrl::OnDraw(
			CDC* pdc, const CRect& rcBounds, const CRect& rcInvalid)
{
	// TODO: Replace the following code with your own drawing code.
    FireGLDraw();
}


void CGL3dOcxCtrl::OnPaint() 
{
	CPaintDC dc(this); // device context for painting
	
	// TODO: Add your message handler code here
    FireGLDraw();
	
	// Do not call COleControl::OnPaint() for painting messages
}



/////////////////////////////////////////////////////////////////////////////
// CGL3dOcxCtrl::DoPropExchange - Persistence support

void CGL3dOcxCtrl::DoPropExchange(CPropExchange* pPX)
{
	ExchangeVersion(pPX, MAKELONG(_wVerMinor, _wVerMajor));
	COleControl::DoPropExchange(pPX);

	// TODO: Call PX_ functions for each persistent custom property.

}


/////////////////////////////////////////////////////////////////////////////
// CGL3dOcxCtrl::GetControlFlags -
// Flags to customize MFC's implementation of ActiveX controls.
//
// For information on using these flags, please see MFC technical note
// #nnn, "Optimizing an ActiveX Control".
DWORD CGL3dOcxCtrl::GetControlFlags()
{
	DWORD dwFlags = COleControl::GetControlFlags();


	// The control will not be redrawn when making the transition
	// between the active and inactivate state.
	dwFlags |= noFlickerActivate;

	// The control can receive mouse notifications when inactive.
	// TODO: if you write handlers for WM_SETCURSOR and WM_MOUSEMOVE,
	//		avoid using the m_hWnd member variable without first
	//		checking that its value is non-NULL.
	dwFlags |= pointerInactive;
	return dwFlags;
}


/////////////////////////////////////////////////////////////////////////////
// CGL3dOcxCtrl::OnResetState - Reset control to default state

void CGL3dOcxCtrl::OnResetState()
{
	COleControl::OnResetState();  // Resets defaults found in DoPropExchange

	// TODO: Reset any other control state here.
}


/////////////////////////////////////////////////////////////////////////////
// CGL3dOcxCtrl::AboutBox - Display an "About" box to the user

void CGL3dOcxCtrl::AboutBox()
{
	CDialog dlgAbout(IDD_ABOUTBOX_GL3DOCX);
	dlgAbout.DoModal();
}


/////////////////////////////////////////////////////////////////////////////
// CGL3dOcxCtrl message handlers

void CGL3dOcxCtrl::GLRender() 
{
	// TODO: Add your dispatch handler code here
	int cx, cy;
	GetControlSize(&cx, &cy);
	if(m_cx != cx || m_cy != cy)
	{
	   m_cx = cx;
	   m_cy = cy;
	   SetViewPort();
	}

	dcRender();

}

int CGL3dOcxCtrl::OnCreate(LPCREATESTRUCT lpCreateStruct) 
{
	lpCreateStruct->style |= (WS_CLIPCHILDREN | WS_CLIPSIBLINGS | CS_OWNDC);
	
	if (COleControl::OnCreate(lpCreateStruct) == -1)
		return -1;
	
	// TODO: Add your specialized creation code here
	SetupEnv();

    Refresh();

	return 0;
}


void CGL3dOcxCtrl::OnDestroy() 
{
	COleControl::OnDestroy();
	
	// TODO: Add your message handler code here
	wglDeleteContext(m_hRC);
    m_Palette.DeleteObject();
    ReleaseDC(m_pDC);
}


void CGL3dOcxCtrl::SetupEnv(void)
{
	PIXELFORMATDESCRIPTOR pfd =
	{
		sizeof(PIXELFORMATDESCRIPTOR),
		1,
		PFD_DRAW_TO_WINDOW|
		PFD_SUPPORT_OPENGL|
		PFD_DOUBLEBUFFER,  
		PFD_TYPE_RGBA,
		24,
		0,0,0,0,0,0,
        0,0,0,0,0,0,0,
		32,
		0,0,
		PFD_MAIN_PLANE,
		0,
		0,0,0
	};

	//get device context 
	//m_hDC = ::GetDC(this->m_hWnd);
	m_pDC = GetDC();

	int pixelFormat =
		ChoosePixelFormat(m_pDC->m_hDC, &pfd);
	BOOL success = 
		SetPixelFormat(m_pDC->m_hDC, pixelFormat, &pfd);

	DescribePixelFormat(m_pDC->m_hDC, pixelFormat,
		  sizeof(pfd), &pfd);

	if(pfd.dwFlags & PFD_NEED_PALETTE)
        SetupPalette();

	m_hRC = wglCreateContext(m_pDC->m_hDC);

	wglMakeCurrent(m_pDC->m_hDC,m_hRC);

	m_Font.SetXOffset(-0.30f);
	m_Font.SetXScale(1.2f);
	m_Font.SetYScale(1.5f);
	m_Font.SetZScale(1.0f);
	m_Font.SetXRotate(25.0f);
	//m_Font.SetZRotate(-1.0f);

	m_Font.SetFontType(GL_FONT_SOLID);
	m_Font.SetText(m_String);
	m_Font.CreateFont(m_pDC, "Arial Black");

    SetupFontColor();		  

    wglMakeCurrent(m_pDC->m_hDC, NULL);
}


void CGL3dOcxCtrl::SetupPalette(void)
{
	PIXELFORMATDESCRIPTOR pfd;  // Pixel Format Descriptor         
	LOGPALETTE *pPal;			// Pointer to memory for logical palette
	int PixelFormat;			// Pixel format index
    int paletteSize;            // Number of entries in palette 
	BYTE RedMask;               // Range for each color entry (7,7,and 3)
	BYTE GreenMask;
	BYTE BlueMask;

	// Get the pixel format index and retrieve the pixel format description
    PixelFormat = GetPixelFormat(m_pDC->m_hDC);
    DescribePixelFormat(m_pDC->m_hDC, PixelFormat, sizeof(PIXELFORMATDESCRIPTOR), &pfd);
    
	

	// Get the number of entries in palette. 256 colors for 8 bits 
    paletteSize = 1 << pfd.cColorBits;
    
	// Allocate for the logical palette
	pPal = (LOGPALETTE*)
	malloc(sizeof(LOGPALETTE) + paletteSize * sizeof(PALETTEENTRY));
    
	
	// Fill the logical palette header information 
	pPal->palVersion = 0x300;            //support Windows3.0
    pPal->palNumEntries = paletteSize;   //number of colors entries

    // Set the 1st entries of logical palette with the current system palette 
    (void) GetSystemPaletteEntries(m_pDC->m_hDC, 0, paletteSize, &pPal->palPalEntry[0]);

	//Set the RGB mask
	RedMask = (1 << pfd.cRedBits) - 1;
	GreenMask = (1 << pfd.cGreenBits) - 1;
	BlueMask = (1 << pfd.cBlueBits) - 1;

	//Set all entries of the logical palette 
    for (int i=0; i<paletteSize; ++i) 
	{
	    pPal->palPalEntry[i].peRed =
		    (((i >> pfd.cRedShift) & RedMask) * 255) / RedMask;
	    pPal->palPalEntry[i].peGreen =
		    (((i >> pfd.cGreenShift) & GreenMask) * 255) / GreenMask;
	    pPal->palPalEntry[i].peBlue =
		    (((i >> pfd.cBlueShift) & BlueMask) * 255) / BlueMask;
	    pPal->palPalEntry[i].peFlags = 0;
    }

	//Create the palette
    m_Palette.CreatePalette(pPal);

	m_pDC->SelectPalette(&m_Palette, FALSE);
	m_pDC->RealizePalette();

	//Free the memory allocated for the logical palette 
    free(pPal);
}

void CGL3dOcxCtrl::SetupFontColor(void)
{
	float fv[4];
	
	fv[0] = 0.3;
	fv[1] = 0.3;
	fv[2] = 0.3;
	fv[3] = 1.0;
	m_Font.SetEmission(fv);

	fv[0] = 0.4;
	fv[1] = 0.4;
	fv[2] = 0.4;
	fv[3] = 1.0;
	m_Font.SetSpecular(fv);

	fv[0] = 0.4;
	fv[1] = 1.0;
	fv[2] = 0.4;
	fv[3] = 1.0;
	m_Font.SetAmbient(fv);

	fv[0] = 0.3;
	fv[1] = 0.3;
	fv[2] = 0.3;
	fv[3] = 1.0;
	m_Font.SetDiffuse(fv);

	m_Font.SetShininess(0.1f);
}

void CGL3dOcxCtrl::dcRender(void)
{
	wglMakeCurrent(m_pDC->m_hDC, m_hRC);
	glShadeModel(GL_SMOOTH);
	glEnable(GL_DEPTH_TEST);
	
	//clear color buffer
	glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
	
	//set light model
	glLightfv(GL_LIGHT0, GL_AMBIENT, m_Lightambient);//set light ambient
	glLightfv(GL_LIGHT0, GL_DIFFUSE, m_Lightdiffuse);//set light specular
	glLightfv(GL_LIGHT0, GL_SPECULAR, m_Lightspecular);//set light specular
	glLightfv(GL_LIGHT0, GL_POSITION, m_Lightposition);//set light position

	glEnable(GL_LIGHTING);
    glEnable(GL_LIGHT0);

    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();

    glTranslatef(-1.2f, -0.1f, -4.2f);
	
    m_Font.GLDrawText();

	glFlush();


	SwapBuffers(m_pDC->m_hDC);
    wglMakeCurrent(m_pDC->m_hDC, NULL);

}


void CGL3dOcxCtrl::SetViewPort(void)
{
	wglMakeCurrent(m_pDC->m_hDC, m_hRC);
	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();
	glFrustum(-1.0, 1.0, -1.0, 1.0, 2.0, 7.0);
	glViewport(0, 0, m_cx, m_cy);
	wglMakeCurrent(m_pDC->m_hDC, NULL);
}

/**********************************************/
/* Property                                   */
/**********************************************/

/* The property of string which is shown */
BSTR CGL3dOcxCtrl::GetContent() 
{
	// TODO: Add your property handler here
	CString strResult = m_Font.GetText();

	return strResult.AllocSysString();
}

void CGL3dOcxCtrl::SetContent(LPCTSTR lpszNewValue) 
{
	// TODO: Add your property handler here
	wglMakeCurrent(m_pDC->m_hDC, m_hRC);
	m_Font.SetText(lpszNewValue);
	m_Font.CreateFont(m_pDC, "Arial Black");
	wglMakeCurrent(m_pDC->m_hDC, NULL);
    Refresh();
}


/**********************************************/
/* Method                                     */
/**********************************************/

/* The property of string which is shown */
void CGL3dOcxCtrl::SetStrText(LPCTSTR strText) 
{
	// TODO: Add your dispatch handler code here
	wglMakeCurrent(m_pDC->m_hDC, m_hRC);
	m_Font.SetText(strText);
	m_Font.CreateFont(m_pDC, "Arial Black");
	wglMakeCurrent(m_pDC->m_hDC, NULL);
    Refresh();
}



void CGL3dOcxCtrl::OnLButtonDblClk(UINT nFlags, CPoint point) 
{
	// TODO: Add your message handler code here and/or call default
    Refresh();
	
	COleControl::OnLButtonDblClk(nFlags, point);
}

void CGL3dOcxCtrl::OnPaletteChanged(CWnd* pFocusWnd) 
{
	COleControl::OnPaletteChanged(pFocusWnd);
	
	// TODO: Add your message handler code here
    Refresh();

}

BOOL CGL3dOcxCtrl::OnQueryNewPalette() 
{
	// TODO: Add your message handler code here and/or call default
    Refresh();
	
	return COleControl::OnQueryNewPalette();
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.


Written By
Canada Canada
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions