本节主要讲一下如何在MFC窗口中使用cocos2dx

  在做比较复杂的游戏,有时需要通过一些工具来编辑生成关卡或者特效,技能等的配置文件。为了方便配置,需要可以通过修改参数直观得到显示的效果。这就需要将引擎加载到工具中进行效果显示,这里我们将cocos2dx应用到MFC,得到最终效果如下:

一、通过HWND创建cocos2dx窗口View

  通过参考 GLViewImpl 及 GLView 创建MFC中可以使用的 CMyEGLView 。在GLView中我们可以看到如下所示,Win32中实际使用的窗口指针就是HWND。

    

同时,继承GLView时有4个必须重载实现的函数如下:

  

因此,我们自己实现的 CMyEGLView 需要 接口如下:

class /*CC_DLL*/ CMyEGLView : public cocos2d::GLView
{
public:
static CMyEGLView* createWithRect(const std::string& viewName, Rect size, HWND handle, float frameZoomFactor = 1.0f); bool initWithRect(const std::string& viewName, Rect rect, HWND handle, float frameZoomFactor);/* override functions */
virtual bool isOpenGLReady() override;
virtual void end() override;
virtual void swapBuffers() override;
virtual void setIMEKeyboardState(bool bOpen) override; virtual LRESULT WindowProc(UINT message, WPARAM wParam, LPARAM lParam); #if (CC_TARGET_PLATFORM == CC_PLATFORM_WIN32)
HWND getWin32Window() { return m_hWnd; }
#endif /* (CC_TARGET_PLATFORM == CC_PLATFORM_WIN32) */ protected: CMyEGLView();
virtual ~CMyEGLView(); bool initGlew(); float _frameZoomFactor;
HDC m_hDC;
HGLRC m_hRC;
HWND m_hWnd; bool _captured;
};

由上述代码可以看到,这里多出了一个WindowProc接口,这是用来将MFC窗口的指令传入cocos2dx中并对应转成相应的消息。主要通过参考GLViewImpl 中的回调实现,详细可以参考文章结尾的源码。

  同时在initWithRect中通过窗口指针 m_hWnd 取得窗口 m_hDC 并通过SetupPixelFormat中设置如下代码实现窗口对Opengl的支持。

static void SetupPixelFormat(HDC hDC)
{
int pixelFormat; PIXELFORMATDESCRIPTOR pfd =
{
sizeof(PIXELFORMATDESCRIPTOR), // size
1, // version
PFD_SUPPORT_OPENGL | // OpenGL window
PFD_DRAW_TO_WINDOW | // render to window
PFD_DOUBLEBUFFER, // support double-buffering
PFD_TYPE_RGBA, // color type
, // preferred color depth
0, 0, 0, 0, 0, 0, // color bits (ignored)
, // no alpha buffer
0, // alpha bits (ignored)
0, // no accumulation buffer
0, 0, 0, 0, // accum bits (ignored)
24, // depth buffer
8, // no stencil buffer
0, // no auxiliary buffers
PFD_MAIN_PLANE, // main layer
0, // reserved
0, 0, 0, // no layer, visible, damage masks
}; pixelFormat = ChoosePixelFormat(hDC, &pfd);
SetPixelFormat(hDC, pixelFormat, &pfd);
}

其余初始化opengl es等同样直接参考GLViewImpl 中实现。

二、在AppDelegate中创建CMyEGLView 

  参考Application::run() 实现并将其拆成3部分在AppDelegate中实现,添加如下接口:

   // 传入窗口指针并创建
virtual void CreateWnd(HWND hwnd); // 刷新显示
virtual void Run2(); // 窗口大小变化
void Resize(int width, int height); // MFC 消息
LRESULT WindowProc(UINT message, WPARAM wParam, LPARAM lParam);

1、CreateWnd用于传入MFC窗口指针,同时调用applicationDidFinishLaunching来实现View的创建等;

2、Run2用于原来run中的while循环部分,即执行 director->mainLoop();

3、在析构函数中添加对view释放等操作。

详细可以参考文章结尾的源码。

三、在MFCAPPView中使用AppDelegate

1、首先在cocos2dx项目中添加一个MFC项目,如下图所示:  

  

2、添加MFC项目对cocos2dx的项目引用

  右键属性->通用属性->引用->添加新引用->libcocos2d

3、在视图->属性管理器中添加现有的cocos2dx属性表,如下:

  右键添加现有属性表,在~/cocos2d/cocos/2d 目录找到对应的属性表进行添加,注意先后顺序。

  

  然后在项目的属性页->C/C++->常规->附加包含目录中添加如下头文件引用目录:

$(EngineRoot)cocos\editor-support;$(EngineRoot)cocos;$(EngineRoot)cocos\platform;$(EngineRoot)cocos\platform\desktop;$(EngineRoot)external\glfw3\include\win32;$(EngineRoot)external\win32-specific\gles\include\OGLES;$(EngineRoot)external\freetype2\include\win32\freetype2;$(EngineRoot)external\freetype2\include\win32\;$(EngineRoot)external

4、然后对应的在MFCApplicationView.h中添加如下:

// 操作
public:
afx_msg void OnTimer(UINT_PTR nIDEvent);
virtual LRESULT WindowProc(UINT message, WPARAM wParam, LPARAM lParam);
afx_msg void OnSize(UINT nType, int cx, int cy);
protected:
AppDelegate m_app;
bool m_bCreated;

  在MFCApplicationView.cpp中添加对应的消息映射

BEGIN_MESSAGE_MAP(CMFCApplicationView, CView)
// 标准打印命令
ON_COMMAND(ID_FILE_PRINT, &CView::OnFilePrint)
ON_COMMAND(ID_FILE_PRINT_DIRECT, &CView::OnFilePrint)
ON_COMMAND(ID_FILE_PRINT_PREVIEW, &CMFCApplicationView::OnFilePrintPreview)
ON_WM_CONTEXTMENU()
ON_WM_RBUTTONUP() ON_WM_TIMER()
ON_WM_SIZE()
END_MESSAGE_MAP()

  同时实现.h中的三个函数,如下:

void CMFCApplicationView::OnTimer(UINT_PTR nIDEvent)
{
// TODO: 在此添加消息处理程序代码和/或调用默认值
if (m_bCreated)
{
m_app.Run2();
}
}
void CMFCApplicationView::OnSize(UINT nType, int cx, int cy)
{
CView::OnSize(nType, cx, cy);
// TODO: 在此处添加消息处理程序代码 if (cx != && cy != )
{ if (!m_bCreated)
{
m_app.CreateWnd(m_hWnd);
SetTimer(, , NULL);
m_bCreated = true;
} m_app.Resize(cx, cy);
}
}
LRESULT CMFCApplicationView::WindowProc(UINT message, WPARAM wParam, LPARAM lParam)
{
// TODO: 在此添加专用代码和/或调用基类
if ( == m_app.WindowProc(message, wParam, lParam))
return ;
return CView::WindowProc(message, wParam, lParam);
}

到这里,即可以在MFC中正常使用cocos2dx了,同时还可以正常响应点击等消息。

5、编译后发现MFC中定义OS_WINDOWS冲突,在stdafx.h添加如下:

//去除MFC中与cocos2dx冲突的默认定义
#ifdef OS_WINDOWS
#undef OS_WINDOWS
#endif

四、其他

  然而同这里 http://www.cnblogs.com/GuyaWeiren/p/4600937.html 通过glfw创建一个新的窗口一样,我这里测试最新cocos2dx-3.9版本同样存在内存泄漏。经测试,直接用cocos2dx源码也一样,只要在MFC中用了AppDelegate就存在泄漏。暂无解决办法,希望有同学知道的可以知会一下~~

完整代码地址:https://github.com/mydishes/cocos2dx-Ex/tree/master/MFCView

cocos2dx - 在MFC中使用cocos2dx的更多相关文章

  1. 强行在MFC窗体中渲染Cocos2d-x 3.6

    [前言] 把Cocos2dx渲染到另一个应用程序框架中的方法,在2.x时代有很多大神已经实现了,而3.x的做法网上几乎找不着.这两天抽空强行折腾了一下,不敢独享,贴出来供大家参考. [已知存在的问题] ...

  2. 使用“Cocos引擎”创建的cpp工程如何在VS中调试Cocos2d-x源码

    前段时间Cocos2d-x更新了一个Cocos引擎,这是一个集合源码,IDE,Studio这一家老小的整合包,我们可以使用这个Cocos引擎来创建我们的项目. 在Cocos2d-x被整合到Cocos引 ...

  3. cocos2dx 3.7中 AppDelegate.h的class TestController;这种写法的具体意思不太明白,只能猜是类似于外部定义的东西。

    cocos2dx 3.7中 AppDelegate.h的class TestController;这种写法的具体意思不太明白,只能猜是类似于外部定义的东西.

  4. 解决cocos2dx在Xcode中运行时报:convert: iCCP: known incorrect sRGB profile 的问题

    解决cocos2dx在Xcode中运行时报:convert: iCCP: known incorrect sRGB profile 的问题 本文的实践来源是参照了两个帖子完成的: http://dis ...

  5. cocos2d-x 3.0rc2中读取sqlite文件

    cocos2d-x 3.0rc2中读取sqlite文件的方式,在Android中直接读取软件内的会失败.须要复制到可写的路径下 sqlite3* dbFile = NULL; std::string ...

  6. ios怎样实现快速将显卡中数据读出压缩成视频在cocos2dx扩展开发中

    如果解决ios怎样实现快速将显卡中数据读出压缩成视频在cocos2dx扩展开发中 手机平台性能是个关键问题. 压缩视频分成3个步骤: 读取显卡数据, 使用编码器压缩,保存文件. 使用libav 压缩的 ...

  7. Cocos2d-x游戏开发中的消息机制:CCNotificationCenter的使用

    在HTML5游戏开发中,js可以使用Event对象的addEventListener(添加事件监听).dispatchEvent(触发事件)实现监听机制,如果在coocos2d-x中,去实现这种机制该 ...

  8. 深入分析Cocos2d-x 2.0中的“纹理”

    对CCImage的绘制是通过CCTexture2D来实现的(OPENGL es)通过纹理绘制到某个面. (本文中所提到的方法在cocos2d2.0中部分有调整,请应用时候具体察看源码)1. 首先来了解 ...

  9. lua 中处理cocos2dx 的button 事件

    lua 中处理cocos2dx 的button 事件 2014-05-08 09:44:32|  分类: lua |举报 |字号 订阅   1.引入这个类:require "GuiConst ...

随机推荐

  1. SNS团队Beta阶段第三次站立会议(2017.05.24)

    1.立会照片 2.每个人的工作 成员 今天已完成的工作 明天计划完成的工作 罗于婕 辅助完善生词本 辅助完成生词本功能 龚晓婷 辅助开发历史记录功能 辅助完善历史记录功能 林仕庄 开发历史记录功能 完 ...

  2. 个人作业(3)----个人总结(Alpha阶段)

    一.个人总结. 个人完成的任务:在此阶段我完成了用户调研.部分测试以及部分博客书写. 个人及团队心得:经过几周Alpha阶段开发后,我大致了解了开发软件的过程,开发一个软件并没有以往想象中那么简易,在 ...

  3. Swing-JList选择事件监听器ListSelectionListener-入门

    当JList中的元素被选中时,选择事件将被触发.对于JTable也是一样,你可以把它看做是多个并列的JList.那么,如果程序需要对该事件做出响应,需要以下步骤: (1)创建一个实现了 ListSel ...

  4. 201521123059 《Java程序设计》第八周学习总结

    1. 本周学习总结 1.1 以你喜欢的方式(思维导图或其他)归纳总结集合与泛型相关内容. 1.2 选做:收集你认为有用的代码片段 简单泛型定义: public class Pair<T> ...

  5. 201521123009 《Java程序设计》第7周学习总结

    1. 本周学习总结 2. 书面作业 Q1:ArrayList代码分析 1.1 解释ArrayList的contains源代码 //contains()方法 public boolean contain ...

  6. 201521123010 《Java程序设计》第4周学习总结

    1.本周学习总结 1.1 尝试使用思维导图总结有关继承的知识点. 1.2 使用常规方法总结其他上课内容. 这周上课主要学了继承,在打代码的时候对各个关键字(除了super关键字)的用法有一点混乱.对多 ...

  7. MyBatis学习(五)resultMap测试

    resultMap是MyBatis最强大的元素,它的作用是告诉MyBatis将从结果集中取出的数据转换成开发者所需要得对象. 接下来我们对resultMap进行一个简单测试.(当所需要返回的对象是一个 ...

  8. 开发中mysql和oracle的区别

    首先就不描述mysql与oracle在整个数据库系统上的区别了,仅从程序员开发的角度来说: 1.主键: mysql一般会用到一个自增的属性,例如设置一个id字段,类型设置为auto increment ...

  9. angular directive自定义指令

    先来看一下自定义指令的写法 app.directive('', ['', function(){ // Runs during compile return { // name: '', // pri ...

  10. 内核对象 windows操作系统

    问题: 什么是内核对象? 答:内核对象实际上时由内核分配的一块内存,而且只能由内核来访问.它时一个数据结构,成员包含有关于该对象的信息.一些成员对于所有对象类型都是一样的,比如对象名称.安全描述.使用 ...