在MFC 窗口中运行 cocos2d-x 3.2 (二) 让其在MFC picture控件中运行

上一篇我们配置了运行环境,但是并不完美,MFC窗口 和 cosos2d 窗口是分开运行的。 如果用来做工具 看起来不太好看,这一篇我们将修改cocos2d 代码,让其运行在MFC控件上

参考:http://blog.csdn.net/akof1314/article/details/8133800


要把cocos2d 窗口运行在 MFC 控件上, 我们就要找到这个窗口的句柄,下面我们来一步步找,看看怎样得到这个窗口句柄


1.首先我们来分析cocos2d的运行机制

打开cocos2d::Application::getInstance()->run(); run()函数的源码:

[cpp]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. int Application::run()  
  2. {  
  3.     PVRFrameEnableControlWindow(false);  
  4.   
  5.     // Main message loop:  
  6.     LARGE_INTEGER nFreq;  
  7.     LARGE_INTEGER nLast;  
  8.     LARGE_INTEGER nNow;  
  9.   
  10.     QueryPerformanceFrequency(&nFreq);  
  11.     QueryPerformanceCounter(&nLast);  
  12.     //这里调用了AppDelegate中的<span style="font-family: Arial, Helvetica, sans-serif;">applicationDidFinishLaunching()  
  13.   
  14.     // Initialize instance and cocos2d.  
  15.     if (!applicationDidFinishLaunching())  
  16.     {  
  17.         return 0;  
  18.     }  
  19.     //那么游戏窗口一定是在这之前创建的</span>  
  20.     auto director = Director::getInstance();  
  21.     auto glview = director->getOpenGLView();  
  22.   
  23.     // Retain glview to avoid glview being released in the while loop  
  24.     glview->retain();  
  25.    //下面是游戏主循环</span>  
  26.     while(!glview->windowShouldClose())  
  27.     {  
  28.         QueryPerformanceCounter(&nNow);  
  29.         if (nNow.QuadPart - nLast.QuadPart > _animationInterval.QuadPart)  
  30.         {  
  31.             nLast.QuadPart = nNow.QuadPart;  
  32.               
  33.             director->mainLoop();  
  34.             glview->pollEvents();  
  35.         }  
  36.         else  
  37.         {  
  38.             Sleep(0);  
  39.         }  
  40.     }  
  41.   
  42.     // Director should still do a cleanup if the window was closed manually.  
  43.     if (glview->isOpenGLReady())  
  44.     {  
  45.         director->end();  
  46.         director->mainLoop();  
  47.         director = nullptr;  
  48.     }  
  49.     glview->release();  
  50.     return true;  
  51. }  
2. 于是我们查看AppDelegate::applicationDidFinishLaunching() 代码:

[cpp]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. bool AppDelegate::applicationDidFinishLaunching() {  
  2.     // initialize director  
  3.     auto director = Director::getInstance();  
  4.     auto glview = director->getOpenGLView();  
  5.     if(!glview) {  
[cpp]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. //第一次运行肯定会进入这里,这个create函数创建了GLView对象  
  2.     glview = GLView::create("My Game");  
  3.     director->setOpenGLView(glview);  
  4. }  
  5.   
  6. // turn on display FPS  
  7. director->setDisplayStats(true);  
  8.   
  9. // set FPS. the default value is 1.0/60 if you don't call this  
  10. director->setAnimationInterval(1.0 / 60);  
  11.   
  12. // create a scene. it's an autorelease object  
  13. auto scene = HelloWorld::createScene();  
  14.   
  15. // run  
  16. director->runWithScene(scene);  
  17.   
  18. return true;  
3. 我们看看GLView::create函数代码

[cpp]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. GLView* GLView::create(const std::string& viewName)  
  2. {  
  3.     auto ret = new GLView;  
[cpp]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1.  //调用了initWithRect()</span>  
  2.     if(ret && ret->initWithRect(viewName, Rect(0, 0, 960, 640), 1)) {  
  3.         ret->autorelease();  
  4.         return ret;  
  5.     }  
  6.   
  7.     return nullptr;  
  8. }  


4.initWithRect 代码

[html]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. bool GLView::initWithRect(const std::string& viewName, Rect rect, float frameZoomFactor)  
  2. {  
  3.     setViewName(viewName);  
  4.   
  5.     _frameZoomFactor = frameZoomFactor;  
  6.   
  7.     glfwWindowHint(GLFW_RESIZABLE,GL_FALSE);  
[html]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. //找到了,glfwCreateWindow 这个函数就是创建窗口的(我只知道glfw是个open gl 的库,想了解的可以去搜一下),下面我们来取窗口句柄  
  2.   
  3.     _mainWindow = glfwCreateWindow(rect.size.width * _frameZoomFactor,  
  4.                                    rect.size.height * _frameZoomFactor,  
  5.                                    _viewName.c_str(),  
  6.                                    _monitor,  
  7.                                    nullptr);  
  8.     glfwMakeContextCurrent(_mainWindow);  
  9.   
  10.     glfwSetMouseButtonCallback(_mainWindow, GLFWEventHandler::onGLFWMouseCallBack);  
  11.     glfwSetCursorPosCallback(_mainWindow, GLFWEventHandler::onGLFWMouseMoveCallBack);  
  12.     glfwSetScrollCallback(_mainWindow, GLFWEventHandler::onGLFWMouseScrollCallback);  
  13.     glfwSetCharCallback(_mainWindow, GLFWEventHandler::onGLFWCharCallback);  
  14.     glfwSetKeyCallback(_mainWindow, GLFWEventHandler::onGLFWKeyCallback);  
  15.     glfwSetWindowPosCallback(_mainWindow, GLFWEventHandler::onGLFWWindowPosCallback);  
  16.     glfwSetFramebufferSizeCallback(_mainWindow, GLFWEventHandler::onGLFWframebuffersize);  
  17.     glfwSetWindowSizeCallback(_mainWindow, GLFWEventHandler::onGLFWWindowSizeFunCallback);  
  18.   
  19.     setFrameSize(rect.size.width, rect.size.height);  
  20.   
  21.     // check OpenGL version at first  
  22.     const GLubyte* glVersion = glGetString(GL_VERSION);  
  23.   
  24.     if ( utils::atof((const char*)glVersion) < 1.5 )  
  25.     {  
  26.         char strComplain[256] = {0};  
  27.         sprintf(strComplain,  
  28.                 "OpenGL 1.5 or higher is required (your version is %s). Please upgrade the driver of your video card.",  
  29.                 glVersion);  
  30.         MessageBox(strComplain, "OpenGL version too old");  
  31.         return false;  
  32.     }  
  33.   
  34.     initGlew();  
  35.   
  36.     // Enable point size by default.  
  37.     glEnable(GL_VERTEX_PROGRAM_POINT_SIZE);  
  38.   
  39.     return true;  
  40. }  
5. 有个API 函数glfwGetWin32Window() 可以取得窗口句柄。(由于不了解glfw 网上搜了半天才找到这个。。。)

参考: http://www.glfw.org/docs/3.0/group__native.html


6.下面开始修改代码

在CCGLView.cpp 前面添加(头文件一定要在宏定义后面

[cpp]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. #define GLFW_EXPOSE_NATIVE_WIN32  
  2. #define GLFW_EXPOSE_NATIVE_WGL  
  3. #include "glfw3native.h"  

给GLView类添加成员:

[cpp]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. HWND getHwnd();  
  2. void closeWindow();  
  3. HWND   m_hwnd;  

[cpp]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. HWND GLView::getHwnd()  
  2. {  
  3.     return m_hwnd;  
  4. }  
  5.   
  6. void GLView::closeWindow()  
  7. {  
  8.     glfwSetWindowShouldClose(_mainWindow, 1);  
  9. }  


修改函数 bool GLView::initWithRect(const std::string& viewName, Rect rect, float frameZoomFactor)

在函数最后添加

[cpp]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. m_hwnd = glfwGetWin32Window(_mainWindow);  


7.  打开Application 类添加一个 int cocosrun()  public成员函数

[cpp]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. int Application::cocosrun()  
  2. {  
  3.     PVRFrameEnableControlWindow(false);  
  4.   
  5.     // Main message loop:  
  6.     LARGE_INTEGER nFreq;  
  7.     LARGE_INTEGER nLast;  
  8.     LARGE_INTEGER nNow;  
  9.   
  10.     QueryPerformanceFrequency(&nFreq);  
  11.     QueryPerformanceCounter(&nLast);  
  12.   
  13.     // Initialize instance and cocos2d.  
  14.     if (!applicationDidFinishLaunching())  
  15.     {  
  16.         return 0;  
  17.     }  
  18.   
  19.     auto director = Director::getInstance();  
  20.     auto glview = director->getOpenGLView();  
  21.   
  22.     // Retain glview to avoid glview being released in the while loop  
  23.     glview->retain();  
  24.   
  25. ShowWindow(glview->getHwnd(), SW_SHOW);  
  26.   
  27.     while(!glview->windowShouldClose())  
  28.     {  
  29.         QueryPerformanceCounter(&nNow);  
  30.         if (nNow.QuadPart - nLast.QuadPart > _animationInterval.QuadPart)  
  31.         {  
  32.             nLast.QuadPart = nNow.QuadPart;  
  33.               
  34.             director->mainLoop();  
  35.             glview->pollEvents();  
  36.         }  
  37.         else  
  38.         {  
  39.             Sleep(0);  
  40.         }  
  41.     }  
  42.   
  43.     // Director should still do a cleanup if the window was closed manually.  
  44.     if (glview->isOpenGLReady())  
  45.     {  
  46.         director->end();  
  47.         director->mainLoop();  
  48.         director = nullptr;  
  49.     }  
  50.     glview->release();  
  51.     return true;  
  52. }  

8.  打开Application 类添加一个 void  closeWindow() public成员函数

[cpp]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. void  Application::closeWindow()  
  2. {  
  3.     auto director = cocos2d::Director::getInstance();  
  4.     auto glview = director->getOpenGLView();  
  5.     glview->closeWindow();  
  6. }  

9. 给类 AppDelegate添加 成员 

[cpp]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. HWND m_hwnd;  
  2. RECT m_parentRect;  
  3. void AppDelegate::setParent(HWND hwnd,RECT rect)  
  4. {  
  5.     m_hwnd = hwnd;  
  6.     m_parentRect.left = rect.left;  
  7.     m_parentRect.top  = rect.top;  
  8.     m_parentRect.right = rect.right;  
  9.     m_parentRect.bottom = rect.bottom;  
  10. }  

10 修改AppDelegate::applicationDidFinishLaunching()  函数

[cpp]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. bool AppDelegate::applicationDidFinishLaunching() {  
  2.     // initialize director  
  3.     auto director = Director::getInstance();  
  4.     auto glview = director->getOpenGLView();  
  5.     if(!glview) {  
  6.         glview = GLView::create("My Game");  
  7.         director->setOpenGLView(glview);  
  8.     }  
  9.   
  10. ::SetParent(glview->getHwnd(), m_hwnd);  
  11.     SetWindowLong(glview->getHwnd(), GWL_STYLE, GetWindowLong(glview->getHwnd(), GWL_STYLE) & ~WS_CAPTION );  
  12.     ::SetWindowPos(glview->getHwnd(), HWND_TOP, m_parentRect.left, m_parentRect.top, m_parentRect.right - m_parentRect.left, m_parentRect.bottom - m_parentRect.top, SWP_NOCOPYBITS | SWP_HIDEWINDOW);  
  13.       
  14.     // turn on display FPS  
  15.     director->setDisplayStats(true);  
  16.   
  17.     // set FPS. the default value is 1.0/60 if you don't call this  
  18.     director->setAnimationInterval(1.0 / 60);  
  19.   
  20.     // create a scene. it's an autorelease object  
  21.     auto scene = HelloWorld::createScene();  
  22.   
  23.     // run  
  24.     director->runWithScene(scene);  
  25.   
  26.     return true;  
  27. }  


11. 给对话框添加一个 Picture 控件(注意更改默认 ID),并为其添加Control 类型成员变量 m_cocosWin , 修改上篇中button的消息响应函数

[cpp]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. void CCocosEditorDlg::OnBnClickedButton1()  
  2. {  
  3.     AppDelegate app;  
  4.     RECT rc;  
  5.     m_cocos2dWin.GetClientRect(&rc);  
  6.     app.setParent(m_cocos2dWin.m_hWnd, rc);  
  7.     cocos2d::Application::getInstance()->cocosrun();  
  8. }  

12. 关闭cocos2d窗口, 在类向导中 给MFC对话框窗口添加 WM_CLOSE消息响应函数:

[cpp]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. void CCocosEditorDlg::OnClose()  
  2. {  
  3.     cocos2d::Application::getInstance()->closeWindow();  
  4.     CDialogEx::OnClose();  
  5. }  

13.编译运行程序:




14 .运行时会发现 cocos2d窗口闪了下,这个原因是cocos2d先创建,然后移到了Picture控件上,那我们让Cocos2d的窗口创建时 先不可见:

[cpp]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. bool GLView::initWithRect(const std::string& viewName, Rect rect, float frameZoomFactor)  
  2. {  
  3.     setViewName(viewName);  
  4.   
  5.     _frameZoomFactor = frameZoomFactor;  
  6.   
  7.     glfwWindowHint(GLFW_RESIZABLE,GL_FALSE);  
  8.     glfwWindowHint(GLFW_VISIBLE , GL_FALSE);  
  9.     _mainWindow = glfwCreateWindow(rect.size.width * _frameZoomFactor,  
  10.                                    rect.size.height * _frameZoomFactor,  
  11.                                    _viewName.c_str(),  
  12.                                    _monitor,  
  13.                                    nullptr);  
  14.     glfwMakeContextCurrent(_mainWindow);  
  15.   
  16.     glfwSetMouseButtonCallback(_mainWindow, GLFWEventHandler::onGLFWMouseCallBack);  
  17.     glfwSetCursorPosCallback(_mainWindow, GLFWEventHandler::onGLFWMouseMoveCallBack);  
  18.     glfwSetScrollCallback(_mainWindow, GLFWEventHandler::onGLFWMouseScrollCallback);  
  19.     glfwSetCharCallback(_mainWindow, GLFWEventHandler::onGLFWCharCallback);  
  20.     glfwSetKeyCallback(_mainWindow, GLFWEventHandler::onGLFWKeyCallback);  
  21.     glfwSetWindowPosCallback(_mainWindow, GLFWEventHandler::onGLFWWindowPosCallback);  
  22.     glfwSetFramebufferSizeCallback(_mainWindow, GLFWEventHandler::onGLFWframebuffersize);  
  23.     glfwSetWindowSizeCallback(_mainWindow, GLFWEventHandler::onGLFWWindowSizeFunCallback);  
  24.   
  25.     setFrameSize(rect.size.width, rect.size.height);  
  26.   
  27.     // check OpenGL version at first  
  28.     const GLubyte* glVersion = glGetString(GL_VERSION);  
  29.   
  30.     if ( utils::atof((const char*)glVersion) < 1.5 )  
  31.     {  
  32.         char strComplain[256] = {0};  
  33.         sprintf(strComplain,  
  34.                 "OpenGL 1.5 or higher is required (your version is %s). Please upgrade the driver of your video card.",  
  35.                 glVersion);  
  36.         MessageBox(strComplain, "OpenGL version too old");  
  37.         return false;  
  38.     }  
  39.   
  40.     initGlew();  
  41.   
  42.     // Enable point size by default.  
  43.     glEnable(GL_VERTEX_PROGRAM_POINT_SIZE);  
  44.   
  45. m_hwnd = glfwGetWin32Window(_mainWindow);</span>  
  46.   
  47.     return true;  
  48. }  

这样就解决闪一下的问题


转载请注明出处。


Test下载地址:点击打开链接



转子:

http://blog.csdn.net/greatchina01/article/details/39580767



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值