-
为描述方便一下简称渲染窗口即cocos2d-x的渲染窗口
-
前沿
最近在论坛上发现有不少同学想用MFC开发cocos2d-x相关编辑器或工具,却因不止如何嵌入而苦恼,而在论坛中也没发现真正的关于将cocos2d-x渲染窗口嵌入到MFC SDI/MDI的方法或教程
于是本人决定将方法分享出来,希望能帮到需要的同学。
2.概要
想要将cocos2d-x渲染窗口嵌入MFC SDI/MDI中使用,其实说难不难,说简单也简单,本分享将以MFC 单文档界面和cocos2d-x-3.5为例。
先总结一下嵌入步骤和思路:
(1)适当修改cocos2d-x CCGLViewImpl-desktop 使之支持作为子窗口创建。
(2)适当修改glfw源码(是否需要修改,有待验证,但修改后是一定可行的),使之支持作为子窗口创建。
(3)新建MFC SDI工程,添加添加cocos2d-x使用附加包含目录和附加库目录。
(4)在通过CCGLView创建渲染窗口时传入 MFC view窗口句柄
3.详细步骤,先上效果展示:http://www.x-studio365.com/
step1: 还是本着世事皆明澈的心里还是先来验证一下能否不修改glfw源码,创建完cocos2d-x渲染窗口后,通过API: SetParent来将渲染窗口设为MFC view的子窗口:如截图
注释的参数作为父窗口句柄传入后,GLViewImpl以子窗口样式创建cocos2d-x渲染窗口:
图:
来看一下执行结果:
图:
由截图可以看出,看来不需要改glfw3和GLViewImpl也是可行的,只是在渲染到MFC View的时候需要稍微修改一下GLView窗口的样式值, 把WS_CAPTION WS_POPUPWINDOW WS_MINIMIZEBOX样式移除,代码:
SetWindowLong(glview->getWin32Window(), GWL_STYLE, GetWindowLong(glew->getWin32Window(), GWL_STYLE) & ~(WS_CAPTION | WS_POPUPWINDOW | WS_MINIMIZEBOX);
再看下执行结果:
图: <img title = 'QQ图片20150416233246.png' src='http://cdn.cocimg.com/bbs/attachment/Fid_41/41_332399_1cf28eada1bdfcb.png' >
看来结果令人失望,这里右上放略有缺陷,也许是还有什么地方没注意到吧,暂时先不研究了,有兴趣爱折腾的同学可以研究下
step2: 修改glfw3代码, 使之支持作为子窗口创建
由于需要修改glfw3源码,因此需要去官网下载源码,本教程我直接下载最新版作为尝试, 这里我直接附上带VS2013工程的glfw3.1.1源码: 附件: glfw-3.1.1.7z (507 KB)
由cocos2d-x GLViewImpl-desktop.cpp中源码可知,渲染窗口的创建时通过glfw3提供的接口glfwCreateWindow实现:
图: <img title = 'QQ图片20150417101026.png' src='http://cdn.cocimg.com/bbs/attachment/Fid_41/41_332399_64fc42fb3d00a6c.png' >
而该接口不支持传入父窗口句柄,因此我们添加一个名为
glfwCreateWindowEx,只增加一个参数即父窗口句柄:
图: <img title = 'QQ图片20150417165516.png' src='http://cdn.cocimg.com/bbs/attachment/Fid_41/41_332399_2fb7e5108f8b998.png' >
接下来定位到glfwCreateWindow实现的地方,然后拷贝一下,改为glfwCreateWindowEx并添加HWND hWndParent参数:
图:<img title = 'QQ图片20150417170402.png' src='http://cdn.cocimg.com/bbs/attachment/Fid_41/41_332399_1fba078a2c7ec0e.png' >
由于函数glfwCreateWindow到最终Windows API创建窗口函数CreateWindowEx的调用层级较多,接下来通过在win32_platform.h中_GLFWwindowWin32的结构体中添加HWND handleParent成员来传递父窗口句柄:
图: <img title = 'QQ图片20150417173838.png' src='http://cdn.cocimg.com/bbs/attachment/Fid_41/41_332399_38cf482f429c12f.png' >
然后在glfwCreateWindowEx函数调用_glfwPlatformCreateWindow之前对使用handleParent保存父窗口句柄
图: <img title = 'QQ图片20150417174219.png' src='http://cdn.cocimg.com/bbs/attachment/Fid_41/41_332399_a4484cf621ad717.png' >
最后一步,直接搜索到调用CreateWindowEx位置修改如下
图: <img title = 'QQ图片20150417174925.png' src='http://cdn.cocimg.com/bbs/attachment/Fid_41/41_332399_22bacec29bdb64e.png' >
OK,收工,至此glfw3源码修改完毕,
特别注意:以最小代码修改为原则,这里glfwCreateWindowEx参数类型如果是HWND,则需要在glfw3.h中包含Windows相关头文件,因此这里请将参数类型修改为void*
,最后附上修改后的源码: glfw-3.1.1-mod.7z (507 KB)
step3. 修改cocos2d-x GLViewImpl-desktop源码(待续,tips:其实至此大家可以参照glfw3修改的方式继续这一步的源码修改,行动吧,只有大胆修改才能满足你的需求
)
同样在GLViewImpl-destop实现中,增加一个函数void setGLViewParent,具体实现和代码修改如下:


至此GLViewImpl-desktop代码修改完成
特别注意,当将cocos2d-x用于MFC程序的时候,在CCApplicationProtocol.h文件中枚举值OS_WINDOWS和Windows系统头文件shlwapi.h中的定义冲突, 因此请修改,这里我
是直接将OS_WINDOWS 整个cocos2d-x项目替换为OS_WINDOWS_SPEC,这个问题我去年跟在github提过,不知道为何一直保留到目前的3.5版本,其实cocos2d-x CCCommon.h
还有一个函数MessageBox也是和系统API冲突的(希望cocos2d-x引擎团队早日优化,何必和操作系统对着干呢),本人通常将其修改为showMsgBox
step4. 接下来,大家就可以在MFC工程中愉快地以MFC View的子窗口形式创建cocos2d-x渲染窗口了。这里MFC SDI的集成就不详述了,想必什么附加包含路径,附加库路径,大家都能解决,网上教程已一大把。
最后附上调用demo工程(MFC SDI界面): http://pan.baidu.com/s/1hqxmy1m
运行效果:




!