文章目录
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动画文件格式加载
- 水面效果
- 第三方界面集成