【小沐学C++】ActiveX控件的MFC实现(VS2017,OpenGL)

22 篇文章 3 订阅
5 篇文章 0 订阅

1、简介

ActiveX 控件是允许网站提供视频和游戏等内容的小应用。 浏览 Web 时,你也可以使用这些小应用与工具栏和股票代码等内容进行交互。 但是,这些应用有时可能出现问题,或者向你提供不需要的内容。 在某些情况下,这些应用可以用来从你的电脑收集信息、破坏电脑上的信息、在未获得你同意的情况下在你的电脑上安装软件或允许其他人远程控制你的电脑。
在这里插入图片描述

2、代码编写

打开VS2017,新建一个MFC ActiveX控件工程,如下图所示:
在这里插入图片描述
在这里插入图片描述

  • (1)FxActiveXMfcGLFont.idl, 在里面定义接口和事件。
// FxActiveX_MfcGLFont.idl : ActiveX 控件项目的类型库源。

// 此文件将由 MIDL 编译器工具处理以
// 产生类型库(FxActiveX_MfcGLFont.tlb),该类型库将成为
// FxActiveX_MfcGLFont.ocx.

#include <olectl.h>
#include <idispids.h>

[ uuid(14E52866-4696-4AE1-B160-D87C2158871E), version(1.0),
  helpfile("FxMfcGLFont.hlp"),
  helpstring("FxMfcGLFont Control"),
  control ]
library FxActiveX_MfcGLFontLib
{
	importlib(STDOLE_TLB);

	//  CFxMfcGLFontCtrl 的主调度接口

	[ uuid(943FC7F4-152F-4FC9-AD11-C05AD35720A1),
	  helpstring("FxMfcGLFont 控件的调度接口")]
	dispinterface _DFxActiveX_MfcGLFont
	{
		properties:
			[id(DISPID_READYSTATE), readonly] long ReadyState;
			[id(DISPID_BACKCOLOR), bindable, requestedit] OLE_COLOR BackColor;
			[id(0)] OLE_COLOR _BackColor;
			[id(1)] BSTR Content;
			[id(2)] long Interval;
			[id(3)] double SeeAngle;
			[id(4)] double SeeNearest;
			[id(5)] double SeeFarthest;
			[id(6)] boolean WireVisible;
			[id(7)] OLE_COLOR FogColor;
			[id(8)] float FogDensity;
			[id(9)] boolean LightEnable;
			[id(10)] double CamPosX;
			[id(11)] double CamPosY;
			[id(12)] double CamPosZ;
			[id(13)] double CamAxz;
			[id(14)] double CamAzy;

		methods:
			[id(DISPID_ABOUTBOX)] void AboutBox();

			[id(15)] OLE_HANDLE GetHandleActiveWindow();
			[id(16)] void GLRender();
			[id(17)] void SetText(BSTR strText);
			[id(18)] void SetType(short type);
			[id(19)] void StopPlayMidi();
			[id(20)] void PlayMidiFile(BSTR filename);
			[id(DISPID_REFRESH)] void Refresh();
	};

	//  CFxMfcGLFontCtrl 的事件调度接口

	[ uuid(55074D60-EA2A-41BE-91CC-201E278C3B52),
	  helpstring("FxMfcGLFont 控件的事件接口") ]
	dispinterface _DFxActiveX_MfcGLFontEvents
	{
		properties:
			//  事件接口没有任何属性

		methods:
			[id(DISPID_READYSTATECHANGE)] void ReadyStateChange();
			[id(DISPID_MOUSEDOWN)] void MouseDown(short Button, short Shift, OLE_XPOS_PIXELS x, OLE_YPOS_PIXELS y);
			[id(DISPID_MOUSEUP)] void MouseUp(short Button, short Shift, OLE_XPOS_PIXELS x, OLE_YPOS_PIXELS y);
			[id(DISPID_MOUSEMOVE)] void MouseMove(short Button, short Shift, OLE_XPOS_PIXELS x, OLE_YPOS_PIXELS y);
			[id(DISPID_KEYDOWN)] void KeyDown(short* KeyCode, short Shift);
			[id(DISPID_KEYUP)] void KeyUp(short* KeyCode, short Shift);
			[id(DISPID_DBLCLICK)] void DblClick();
			[id(1)] void GLDraw();
			[id(2)] void Timer();
			[id(3)] void EndPlayMidi();

			[id(4)] void VcKeyDown(long KeyCode, short flags);
			[id(5)] void VcKeyUp(long KeyCode, short flags);
			[id(6)] void LeftButtonDown(long x, long y, boolean control, boolean shift);
			[id(7)] void RightButtonDown(long x, long y, boolean control, boolean shift);
	};

	//  CFxMfcGLFontCtrl 的类信息

	[ uuid(9EF03850-F171-4DB2-BCC6-243AF84EEAF9),
	  helpstring("FxMfcGLFont Control"), control ]
	coclass FxActiveX_MfcGLFont
	{
		[default] dispinterface _DFxActiveX_MfcGLFont;
		[default, source] dispinterface _DFxActiveX_MfcGLFontEvents;
	};

};

  • (2)FxActiveXMfcGLFontCtrl.cpp,在里面编写控件的具体实现。其主要代码如下所示:
// FxMfcGLFontCtrl.cpp : CFxMfcGLFontCtrl ActiveX 控件类的实现。

#include "stdafx.h"
#include "FxActiveX_MfcGLFont.h"
#include "FxMfcGLFontCtrl.h"
#include "FxActiveX_MfcGLFontPropPage.h"
#include <Mmsystem.h>
#include "PlayMidi.h"
#include "app.h"
#include "./GLScene.h"
#include "./GLTest_BaseFactory.h"
#include "./GLTest_Base.h"

extern CFxActiveX_MfcGLFontApp theApp;
#define TIMER_ID1 1000
#define WM_MENU_START (WM_USER + 100)
#define WM_MENU_END (WM_MENU_START + 100)

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

IMPLEMENT_DYNCREATE(CFxMfcGLFontCtrl, COleControl)

// 消息映射

BEGIN_MESSAGE_MAP(CFxMfcGLFontCtrl, COleControl)
	ON_OLEVERB(AFX_IDS_VERB_EDIT, OnEdit)
	ON_OLEVERB(AFX_IDS_VERB_PROPERTIES, OnProperties)
	ON_WM_CREATE()
	ON_WM_DESTROY()
	ON_WM_PAINT()
	ON_WM_TIMER()
	ON_WM_LBUTTONDBLCLK()
	ON_WM_QUERYNEWPALETTE()
	ON_WM_PALETTECHANGED()
	ON_MESSAGE(OCM_COMMAND, OnOcmCommand)
	ON_MESSAGE(MM_MCINOTIFY, OnMciNotify)
	ON_WM_LBUTTONDOWN()
	ON_WM_RBUTTONDOWN()
	ON_WM_SIZE()
	ON_WM_DROPFILES()
	ON_WM_CONTEXTMENU()
	ON_UPDATE_COMMAND_UI_RANGE(WM_MENU_START, WM_MENU_END, OnUpdateMenuRanges)
END_MESSAGE_MAP()
 
// 调度映射

BEGIN_DISPATCH_MAP(CFxMfcGLFontCtrl, COleControl)
	/* yub提示:一定按照idl文件的接口id顺序放置每行语句 */

	DISP_PROPERTY_EX(CFxMfcGLFontCtrl, "Content", GetContent, SetContent, VT_BSTR)
	DISP_PROPERTY_NOTIFY(CFxMfcGLFontCtrl, "Interval", m_interval, OnIntervalChanged, VT_I4)
	DISP_PROPERTY_NOTIFY(CFxMfcGLFontCtrl, "SeeAngle", m_seeAngle, OnSeeAngleChanged, VT_R8)
	DISP_PROPERTY_NOTIFY(CFxMfcGLFontCtrl, "SeeNearest", m_seeNearest, OnSeeNearestChanged, VT_R8)
	DISP_PROPERTY_NOTIFY(CFxMfcGLFontCtrl, "SeeFarthest", m_seeFarthest, OnSeeFarthestChanged, VT_R8)
	DISP_PROPERTY_NOTIFY(CFxMfcGLFontCtrl, "WireVisible", m_wireVisible, OnWireVisibleChanged, VT_BOOL)
	DISP_PROPERTY_NOTIFY(CFxMfcGLFontCtrl, "FogColor", m_fogColor, OnFogColorChanged, VT_COLOR)
	DISP_PROPERTY_NOTIFY(CFxMfcGLFontCtrl, "FogDensity", m_fogDensity, OnFogDensityChanged, VT_R4)
	DISP_PROPERTY_NOTIFY(CFxMfcGLFontCtrl, "LightEnable", m_lightEnable, OnLightEnableChanged, VT_BOOL)
	DISP_PROPERTY_NOTIFY(CFxMfcGLFontCtrl, "CamPosX", m_camPosX, OnCamPosXChanged, VT_R8)
	DISP_PROPERTY_NOTIFY(CFxMfcGLFontCtrl, "CamPosY", m_camPosY, OnCamPosYChanged, VT_R8)
	DISP_PROPERTY_NOTIFY(CFxMfcGLFontCtrl, "CamPosZ", m_camPosZ, OnCamPosZChanged, VT_R8)
	DISP_PROPERTY_NOTIFY(CFxMfcGLFontCtrl, "CamAxz", m_camAxz, OnCamAxzChanged, VT_R8)
	DISP_PROPERTY_NOTIFY(CFxMfcGLFontCtrl, "CamAzy", m_camAzy, OnCamAzyChanged, VT_R8)

	DISP_FUNCTION(CFxMfcGLFontCtrl, "GetHandleActiveWindow", GetHandleActiveWindow, VT_HANDLE, VTS_NONE)
	DISP_FUNCTION(CFxMfcGLFontCtrl, "GLRender", GLRender, VT_EMPTY, VTS_NONE)
	DISP_FUNCTION(CFxMfcGLFontCtrl, "SetText", SetContent, VT_EMPTY, VTS_BSTR)
	DISP_FUNCTION(CFxMfcGLFontCtrl, "SetType", SetType, VT_EMPTY, VTS_I2)
	DISP_FUNCTION(CFxMfcGLFontCtrl, "StopPlayMidi", StopPlayMidi, VT_EMPTY, VTS_NONE)
	DISP_FUNCTION(CFxMfcGLFontCtrl, "PlayMidiFile", PlayMidiFile, VT_EMPTY, VTS_BSTR)

	DISP_DEFVALUE(CFxMfcGLFontCtrl, "BackColor")
	DISP_STOCKPROP_BACKCOLOR()
	DISP_STOCKPROP_READYSTATE()
	DISP_FUNCTION_ID(CFxMfcGLFontCtrl, "Refresh", DISPID_REFRESH, Refresh, VT_EMPTY, VTS_NONE)
	DISP_FUNCTION_ID(CFxMfcGLFontCtrl, "AboutBox", DISPID_ABOUTBOX, AboutBox, VT_EMPTY, VTS_NONE)
END_DISPATCH_MAP()

// 事件映射

BEGIN_EVENT_MAP(CFxMfcGLFontCtrl, COleControl)
	EVENT_STOCK_READYSTATECHANGE()
	EVENT_STOCK_KEYDOWN()
	EVENT_STOCK_KEYUP()
// 	EVENT_STOCK_MOUSEDOWN()
// 	EVENT_STOCK_MOUSEUP()
// 	EVENT_STOCK_MOUSEMOVE()
	EVENT_STOCK_DBLCLICK()
	EVENT_CUSTOM("GLDraw", FireGLDraw, VTS_NONE)
	EVENT_CUSTOM("Timer", FireTimer, VTS_NONE)
	EVENT_CUSTOM("EndPlayMidi", FireEndPlayMidi, VTS_NONE)
	EVENT_CUSTOM("VcKeyDown", FireVcKeyDown, VTS_I4  VTS_I2)
	EVENT_CUSTOM("VcKeyUp", FireVcKeyUp, VTS_I4  VTS_I2)
	EVENT_CUSTOM("LeftButtonDown", FireLeftButtonDown, VTS_I4  VTS_I4  VTS_BOOL  VTS_BOOL)
	EVENT_CUSTOM("RightButtonDown", FireRightButtonDown, VTS_I4  VTS_I4  VTS_BOOL  VTS_BOOL)
END_EVENT_MAP()

// 属性页

// TODO: 按需要添加更多属性页。请记住增加计数!
BEGIN_PROPPAGEIDS(CFxMfcGLFontCtrl, 1)
	PROPPAGEID(CFxActiveX_MfcGLFontPropPage::guid)
END_PROPPAGEIDS(CFxMfcGLFontCtrl)

// 初始化类工厂和 guid

IMPLEMENT_OLECREATE_EX(CFxMfcGLFontCtrl, "FxFishSoft.FxMfcGLFontCtrl.1",
	0x9ef03850, 0xf171, 0x4db2, 0xbc, 0xc6, 0x24, 0x3a, 0xf8, 0x4e, 0xea, 0xf9)

// 键入库 ID 和版本
IMPLEMENT_OLETYPELIB(CFxMfcGLFontCtrl, _tlid, _wVerMajor, _wVerMinor)

// 接口 ID
const IID BASED_CODE IID_DFxActiveX_MfcGLFont =
		{ 0x943FC7F4, 0x152F, 0x4FC9, { 0xAD, 0x11, 0xC0, 0x5A, 0xD3, 0x57, 0x20, 0xA1 } };
const IID BASED_CODE IID_DFxActiveX_MfcGLFontEvents =
		{ 0x55074D60, 0xEA2A, 0x41BE, { 0x91, 0xCC, 0x20, 0x1E, 0x27, 0x8C, 0x3B, 0x52 } };

// 控件类型信息
static const DWORD BASED_CODE _dwFxActiveX_MfcGLFontOleMisc =
	OLEMISC_ACTIVATEWHENVISIBLE |
	OLEMISC_SETCLIENTSITEFIRST |
	OLEMISC_INSIDEOUT |
	OLEMISC_CANTLINKINSIDE |
	OLEMISC_RECOMPOSEONRESIZE;

IMPLEMENT_OLECTLTYPE(CFxMfcGLFontCtrl, IDS_FXACTIVEX_MFCGLFONT, _dwFxActiveX_MfcGLFontOleMisc)

// CFxMfcGLFontCtrl::CFxMfcGLFontCtrlFactory::UpdateRegistry -
// 添加或移除 CFxMfcGLFontCtrl 的系统注册表项

BOOL CFxMfcGLFontCtrl::CFxMfcGLFontCtrlFactory::UpdateRegistry(BOOL bRegister)
{
	// TODO: 验证您的控件是否符合单元模型线程处理规则。
	// 有关更多信息,请参考 MFC 技术说明 64。
	// 如果您的控件不符合单元模型规则,则
	// 必须修改如下代码,将第六个参数从
	// afxRegInsertable | afxRegApartmentThreading 改为 afxRegInsertable。

	if (bRegister)
		return AfxOleRegisterControlClass(
			AfxGetInstanceHandle(),
			m_clsid,
			m_lpszProgID,
			IDS_FXACTIVEX_MFCGLFONT,
			IDB_FXACTIVEX_MFCGLFONT,
			afxRegInsertable | afxRegApartmentThreading,
			_dwFxActiveX_MfcGLFontOleMisc,
			_tlid,
			_wVerMajor,
			_wVerMinor);
	else
		return AfxOleUnregisterClass(m_clsid, m_lpszProgID);
}

// CFxMfcGLFontCtrl::CFxMfcGLFontCtrl - 构造函数
CFxMfcGLFontCtrl::CFxMfcGLFontCtrl() 
: CGLScene() 
{
	InitializeIIDs(&IID_DFxActiveX_MfcGLFont, &IID_DFxActiveX_MfcGLFontEvents);
	// TODO: 在此初始化控件的实例数据。
	
	m_lReadyState = READYSTATE_LOADING;
	m_String = "Hello Fish!"; 

	SetInitialSize(800, 290);
}

// CFxMfcGLFontCtrl::~CFxMfcGLFontCtrl - 析构函数
CFxMfcGLFontCtrl::~CFxMfcGLFontCtrl()
{
	// TODO: 在此清理控件的实例数据。
}

// CFxMfcGLFontCtrl::OnDraw - 绘图函数
void CFxMfcGLFontCtrl::OnDraw(
			CDC* pdc, const CRect& rcBounds, const CRect& rcInvalid)
{
	if (!pdc)
		return;

	/*// TODO: 用您自己的绘图代码替换下面的代码。
	pdc->FillRect(rcBounds, CBrush::FromHandle((HBRUSH)GetStockObject(WHITE_BRUSH)));
	pdc->Ellipse(rcBounds);

	GLRender();
	FireGLDraw();*/

	DoSuperclassPaint(pdc, rcBounds);
}

// CFxMfcGLFontCtrl::DoPropExchange - 持久性支持
void CFxMfcGLFontCtrl::DoPropExchange(CPropExchange* pPX)
{
	ExchangeVersion(pPX, MAKELONG(_wVerMinor, _wVerMajor));
	COleControl::DoPropExchange(pPX);

	// TODO: 为每个持久的自定义属性调用 PX_ 函数。
	long nInterval = m_interval;
	PX_Long(pPX,"Interval",m_interval, 0);
	PX_Double(pPX,"SeeAngle", m_seeAngle, 45.0);
	PX_Double(pPX,"SeeNearest", m_seeNearest, 0.1f);
	PX_Double(pPX,"SeeFarthest", m_seeFarthest, 100.0);
	PX_Bool(pPX,"WireVisible", m_wireVisible, TRUE);

	PX_Color(pPX,"FogColor", m_fogColor,0x00808080);
//	PX_Long(pPX, _T("FogColor"), (long &)m_fogColor, RGB(0xFF, 0x00, 0x00));
	PX_Float(pPX,"FogDensity", m_fogDensity, 0);

	PX_Bool(pPX,"LightEnable", m_lightEnable, FALSE);
	PX_Color(pPX,"BackColor", m_clrBackColor, 0x00808080);

	PX_Double(pPX,"CamPosX", m_camPosX,0.0);
	PX_Double(pPX,"CamPosY", m_camPosY,0.0);
	PX_Double(pPX,"CamPosZ", m_camPosZ,-8.0);
	PX_Double(pPX,"CamAxz", m_camAxz,3.1415/2);
	PX_Double(pPX,"CamAzy", m_camAzy,0.0);

	if (pPX->GetVersion() == (DWORD)MAKELONG(_wVerMinor, _wVerMajor)){

	}
	else if (pPX->IsLoading()) {
		CFontHolder& stockFont = InternalGetFont();
		stockFont.InitializeFont();

		if (nInterval != m_interval)
			OnIntervalChanged();    // Force timer to recreate w/ correct interval
	}
}

// CFxMfcGLFontCtrl::OnResetState - 将控件重置为默认状态
void CFxMfcGLFontCtrl::OnResetState()
{
	COleControl::OnResetState();  // 重置 DoPropExchange 中找到的默认值

	// TODO: 在此重置任意其他控件状态。
}

// CFxMfcGLFontCtrl::AboutBox - 向用户显示“关于”框

void CFxMfcGLFontCtrl::AboutBox()
{
// 	CDialog dlgAbout(IDD_ABOUTBOX);
// 	dlgAbout.DoModal();
	extern void DoAboutBox(HINSTANCE hInst, HWND hWnd);
	extern App* pApp;
	DoAboutBox(pApp->GetInstance(), m_hWnd);
}

// For information on using these flags, please see MFC technical note
// #nnn, "Optimizing an ActiveX Control".
DWORD CFxMfcGLFontCtrl::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;
}

// CFxMfcGLFontCtrl 消息处理程序
int CFxMfcGLFontCtrl::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
	// TODO 
	lpCreateStruct->style |= (WS_CLIPCHILDREN | WS_CLIPSIBLINGS | CS_OWNDC);

	if (COleControl::OnCreate(lpCreateStruct) == -1)
		return -1;

	/*--------------------------------------------------*/
	m_pDC = new CClientDC(this);
	HDC hdc = m_pDC->GetSafeHdc();

	RECT rt;
	GetClientRect(&rt);
	
	CGLScene::Init(theApp.m_hInstance, hdc, m_hWnd, rt);

	SetType(0);
	Refresh();
	/*--------------------------------------------------*/

	// TODO:  在此添加您专用的创建代码
	DragAcceptFiles();
	SetFocus();

	m_interval = 5;
	if (m_interval != 0) SetTimer(TIMER_ID1,m_interval,NULL);
	
	return 0;
}

void CFxMfcGLFontCtrl::OnDestroy()
{
	COleControl::OnDestroy();

	// TODO: 在此处添加消息处理程序代码
	KillTimer(TIMER_ID1);

	m_Palette.DeleteObject();
	ReleaseDC(m_pDC);
	if (m_pDC) delete m_pDC;
	m_pDC = NULL;

	DeleteGLTest();
}

void CFxMfcGLFontCtrl::OnTimer(UINT nIDEvent) 
{
	// TODO: Add your message handler code here and/or call default
	if(nIDEvent==TIMER_ID1)
	{
//		FireTimer();
		RedrawWindow();
	}
	
	// Eat spurious WM_TIMER messages
	MSG msg;
	while(::PeekMessage(&msg, m_hWnd, WM_TIMER, WM_TIMER, PM_REMOVE));

	COleControl::OnTimer(nIDEvent);
}

void CFxMfcGLFontCtrl::OnPaint()
{
	CPaintDC dc(this); // device context for painting
	// TODO: 在此处添加消息处理程序代码
	// 不为绘图消息调用 COleControl::OnPaint()

	GLRender();
//	FireGLDraw();
}

void CFxMfcGLFontCtrl::OnLButtonDblClk(UINT nFlags, CPoint point)
{
	// TODO: 在此添加消息处理程序代码和/或调用默认值
	Refresh();

	COleControl::OnLButtonDblClk(nFlags, point);
}

BOOL CFxMfcGLFontCtrl::OnQueryNewPalette()
{
	// TODO: 在此添加消息处理程序代码和/或调用默认值
	Refresh();

	return COleControl::OnQueryNewPalette();
}

void CFxMfcGLFontCtrl::OnPaletteChanged(CWnd* pFocusWnd) 
{
	COleControl::OnPaletteChanged(pFocusWnd);

	// TODO: Add your message handler code here
	Refresh();

}

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

/* The property of string which is shown */
BSTR CFxMfcGLFontCtrl::GetContent() 
{
	// TODO: Add your property handler here
	CString strResult = GetGLTest()->getTitle();
	return strResult.AllocSysString();
}

void CFxMfcGLFontCtrl::SetContent(LPCTSTR lpszNewValue) 
{
	// TODO: Add your property handler here
	if(GetGLTest()) GetGLTest()->setTitle(lpszNewValue);
	Refresh();
}


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

void CFxMfcGLFontCtrl::OnIntervalChanged() 
{
	// TODO: Add notification handler code
	KillTimer(TIMER_ID1);
	if (m_interval)	SetTimer(TIMER_ID1,m_interval,NULL);

	SetModifiedFlag();
}

OLE_HANDLE CFxMfcGLFontCtrl::GetHandleActiveWindow() 
{
	// TODO: Add your dispatch handler code here
	CWnd *w=GetActiveWindow();
	if(w==NULL) return NULL;

	return (OLE_HANDLE)w->m_hWnd;
}

void CFxMfcGLFontCtrl::Refresh() 
{
	// TODO: Add your dispatch handler code here
	RedrawWindow();

}

void CFxMfcGLFontCtrl::PlayMidiFile(LPCTSTR filename) 
{
	// TODO: Add your dispatch handler code here
	PlayMusic(m_hWnd,filename);

}

void CFxMfcGLFontCtrl::StopPlayMidi() 
{
	// TODO: Add your dispatch handler code here
	CloseMusic();

}

LRESULT CFxMfcGLFontCtrl::OnMciNotify(WPARAM w,LPARAM l)
{
	if (w == MCI_NOTIFY_SUCCESSFUL) FireEndPlayMidi();
	return 0;
}


LRESULT CFxMfcGLFontCtrl::OnOcmCommand(WPARAM wParam, LPARAM lParam)
{
#ifdef _WIN32
	WORD wNotifyCode = HIWORD(wParam);
#else
	WORD wNotifyCode = HIWORD(lParam);
#endif

	// TODO: Switch on wNotifyCode here.

	return 0;
}

/
// CFxMfcGLFontCtrl::IsSubclassedControl - This is a subclassed control

BOOL CFxMfcGLFontCtrl::IsSubclassedControl()
{
	return TRUE;
}

LRESULT CFxMfcGLFontCtrl::WindowProc( UINT message, WPARAM wParam, LPARAM lParam )
{
	LRESULT ret = CGLScene::WindowProc(message, wParam, lParam);
	
	return COleControl::WindowProc(message, wParam, lParam);
}

BOOL CFxMfcGLFontCtrl::PreTranslateMessage(MSG* pMsg) 
{
	// TODO: Add your specialized code here and/or call the base class
	switch (pMsg->message)
	{
	case WM_KEYDOWN:
		if ((pMsg->lParam&0x40000000)==0) {
			UINT nChar = pMsg->wParam;
			FireVcKeyDown(nChar, 0);

			if (nChar == VK_ESCAPE // 27
				|| nChar == VK_TAB // 9
				|| nChar == VK_DELETE ) //46
			{  
				GetGLTest()->onKeyDown(pMsg->wParam);
				return TRUE;
			}
		}
		break;
	case WM_KEYUP:
		{
			FireVcKeyUp(pMsg->wParam,0);

			UINT nChar = pMsg->wParam;
			if (nChar == VK_ESCAPE // 27
				|| nChar == VK_TAB // 9
				|| nChar == VK_DELETE ) //46
			{  
				GetGLTest()->onKeyUp(pMsg->wParam);
				return TRUE;
			}
		}
		break;
	case WM_SYSKEYDOWN:
		if(pMsg->wParam == VK_MENU) {
			GetGLTest()->onKeyDown(VK_MENU);
			return TRUE;
		}
		break;
	case WM_SYSKEYUP:
		if(pMsg->wParam == VK_MENU) {
			GetGLTest()->onKeyUp(VK_MENU);
			return TRUE;
		}
		break;
	}

	return COleControl::PreTranslateMessage(pMsg);
}
void CFxMfcGLFontCtrl::OnLButtonDown(UINT nFlags, CPoint point)
{
	// TODO: 在此添加消息处理程序代码和/或调用默认值
// 	if (point.x>=0 && point.x<=m_glObj.getWidth() && point.y>=0 && point.y<=m_glObj.getHeight())
// 		FireLeftButtonDown(point.x,point.y,(nFlags&MK_CONTROL)?TRUE:FALSE,(nFlags&MK_SHIFT)?TRUE:FALSE);

	COleControl::OnLButtonDown(nFlags, point);
}

void CFxMfcGLFontCtrl::OnRButtonDown(UINT nFlags, CPoint point)
{
	// TODO: 在此添加消息处理程序代码和/或调用默认值
 	//if (point.x>=0 && point.x<=m_pGLTest->getWidth() && point.y>=0 && point.y<=m_pGLTest->getHeight())
 	//	FireRightButtonDown(point.x,point.y,(nFlags&MK_CONTROL)?TRUE:FALSE,(nFlags&MK_SHIFT)?TRUE:FALSE);
	
	COleControl::OnRButtonDown(nFlags, point);
}

void CFxMfcGLFontCtrl::OnSize(UINT nType, int cx, int cy)
{
	COleControl::OnSize(nType, cx, cy);
	
	m_width = cx;
	m_height = cy;

	// TODO: 在此处添加消息处理程序代码
	if (GetGLTest()) {
		GetGLTest()->onResize(cx, cy);
	}

/*
	int cx, cy;
	GetControlSize(&cx, &cy);
*/	
}

void CFxMfcGLFontCtrl::GLRender() 
{
	// Process Application Loop
	DWORD tickCount = GetTickCount ();				// Get The Tick Count
	Update (tickCount - _window.lastTickCount);	// Update The Counter
	_window.lastTickCount = tickCount;

	if (GetGLTest() && GetGLTest()->isRendering()) {
		GetGLTest()->onBeforeRender();
		GetGLTest()->onRender();
		GetGLTest()->onIdle();
		GetGLTest()->onAfterRender();
	}
}

void CFxMfcGLFontCtrl::RefreshSize()
{	
	if (GetGLTest()) {
		GetGLTest()->onResize();
		_ArcBall.setBounds((GLfloat)m_width, (GLfloat)m_height);
	}
}

void CFxMfcGLFontCtrl::OnBackColorChanged()
{
	GetGLTest()->setBackColor(TranslateColor(GetBackColor()));

	COleControl::OnBackColorChanged();
}

void CFxMfcGLFontCtrl::OnSeeAngleChanged() 
{
	// TODO: Add notification handler code
	RefreshSize();

	SetModifiedFlag();
}

void CFxMfcGLFontCtrl::OnSeeNearestChanged() 
{
	// TODO: Add notification handler code
	RefreshSize();

	SetModifiedFlag();
}

void CFxMfcGLFontCtrl::OnSeeFarthestChanged() 
{
	// TODO: Add notification handler code
	RefreshSize();

	SetModifiedFlag();
}

void CFxMfcGLFontCtrl::OnWireVisibleChanged() 
{
	// TODO: Add notification handler code

	SetModifiedFlag();
}


void CFxMfcGLFontCtrl::OnFogColorChanged() 
{
	// TODO: Add notification handler code
	SetModifiedFlag();
}

void CFxMfcGLFontCtrl::OnFogDensityChanged() 
{
	// TODO: Add notification handler code
	SetModifiedFlag();
}

void CFxMfcGLFontCtrl::OnLightEnableChanged() 
{
	// TODO: Add notification handler code
	SetModifiedFlag();
}


void CFxMfcGLFontCtrl::OnCamPosXChanged() 
{
	// TODO: Add notification handler code
	SetModifiedFlag();
}

void CFxMfcGLFontCtrl::OnCamPosYChanged() 
{
	// TODO: Add notification handler code
	SetModifiedFlag();
}

void CFxMfcGLFontCtrl::OnCamPosZChanged() 
{
	// TODO: Add notification handler code
	SetModifiedFlag();
}

void CFxMfcGLFontCtrl::OnCamAxzChanged() 
{
	// TODO: Add notification handler code
	UpdateCamDir();

	SetModifiedFlag();
}

void CFxMfcGLFontCtrl::OnCamAzyChanged() 
{
	// TODO: Add notification handler code
	UpdateCamDir();

	SetModifiedFlag();
}

double CFxMfcGLFontCtrl::GetCamDirX() 
{
	// TODO: Add your dispatch handler code here
	return m_camDirX;

}

double CFxMfcGLFontCtrl::GetCamDirY() 
{
	// TODO: Add your dispatch handler code here
	return m_camDirY;

	return 0.0;
}

double CFxMfcGLFontCtrl::GetCamDirZ() 
{
	// TODO: Add your dispatch handler code here
	return m_camDirZ;

	return 0.0;
}

void CFxMfcGLFontCtrl::SetType( short type )
{
	RECT rt;
	GetClientRect(&rt);
	
	CGLScene::SetGLType(type);
}

void CFxMfcGLFontCtrl::OnDropFiles(HDROP hDropInfo)
{
	// TODO: 在此添加消息处理程序代码和/或调用默认值
	if ( ::GetActiveWindow() == NULL ) {
		::SetActiveWindow(m_hWnd);
	}

	char path[MAX_PATH];
	int count = DragQueryFile(hDropInfo, -1, NULL, 0);
	if (count > 0) {
		DragQueryFile(hDropInfo, 0, path, sizeof(path));
		if (GetGLTest()) {
			GetGLTest()->onDropFiles(path);
		}
	}
		
	__super::OnDropFiles(hDropInfo);
}


void CFxMfcGLFontCtrl::OnContextMenu(CWnd* /*pWnd*/, CPoint point)
{
	// TODO: 在此处添加消息处理程序代码
	UINT idStart = WM_MENU_START;

	if (GetGLTest()) {
		std::string text;
		int n = GetGLTest()->getMenuCount();
		if(n == 0) return;

		CMenu menu;
		menu.CreatePopupMenu();
		menu.AppendMenu(MF_STRING , WM_MENU_END, _T("关于"));
		menu.AppendMenu(MF_SEPARATOR);

		for (int i = 0; i <n ;i++) {
			GetGLTest()->getMenuText(i, text);
			if (!text.compare("-") || text.empty()) {
				menu.AppendMenu(MF_SEPARATOR);
			}
			else {
				menu.AppendMenu(MF_STRING , idStart+i, text.c_str());
			}
		}

		menu.TrackPopupMenu(TPM_LEFTALIGN | TPM_RIGHTBUTTON, point.x, point.y, this);
	}
}

void CFxMfcGLFontCtrl::OnUpdateMenuRanges(CCmdUI* pCmdUI)
{
	pCmdUI->Enable();
}

BOOL CFxMfcGLFontCtrl::OnCommand(WPARAM wParam, LPARAM lParam)
{
	// TODO: 在此添加专用代码和/或调用基类
	if (wParam == WM_MENU_START + 100) {
		AboutBox();
	}
	else if (GetGLTest()) {
		GetGLTest()->onMenu(wParam - WM_MENU_START);
	}

	return __super::OnCommand(wParam, lParam);
}

3、注册控件

使用管理员权限打开命令行界面,通过如下的命令注册上面的控件。

regsvr32  FxActiveX_MfcGLFont.ocx

在这里插入图片描述

4、结果运行

新建一个C#工程加载上面的控件,如下图所示:
在这里插入图片描述
在这里插入图片描述

  • 天空盒
    在这里插入图片描述
  • 法线贴图
    在这里插入图片描述
  • 阴影效果
    在这里插入图片描述
  • 骨骼动画
    在这里插入图片描述
  • 文字打印
    在这里插入图片描述
  • 3ds动画文件格式加载
    在这里插入图片描述
  • 水面效果
    在这里插入图片描述
  • 第三方界面集成
    在这里插入图片描述

后记

如果你觉得该方法或代码有一点点用处,可以给作者点个赞、赏杯咖啡;╮( ̄▽ ̄)╭
如果你感觉方法或代码不咋地//(ㄒoㄒ)//,就在评论处留言,作者继续改进。o_O???
谢谢各位童鞋们啦( ´ ▽´ )ノ ( ´ ▽´)っ!!!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值