在MFC 視窗中執行 cocos2d-x 3.2 (二) 讓其在MFC picture控制元件中執行

在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()函式的原始碼:

  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() 程式碼:

  1. bool AppDelegate::applicationDidFinishLaunching() {  
  2.     // initialize director  
  3.     auto director = Director::getInstance();  
  4.     auto glview = director->getOpenGLView();  
  5.     if(!glview) {  
  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函式程式碼

  1. GLView* GLView::create(const std::string& viewName)  
  2. {  
  3.     auto ret = new GLView;  
  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 程式碼

  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);  
  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 前面新增(標頭檔案一定要在巨集定義後面)

  1. #define GLFW_EXPOSE_NATIVE_WIN32  
  2. #define GLFW_EXPOSE_NATIVE_WGL  
  3. #include "glfw3native.h"  

給GLView類新增成員:

  1. HWND getHwnd();  
  2. void closeWindow();  
  3. HWND   m_hwnd;  

  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)

在函式最後新增

  1. m_hwnd = glfwGetWin32Window(_mainWindow);  

7.  開啟Application 類新增一個 int cocosrun()  public成員函式

  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成員函式

  1. void  Application::closeWindow()  
  2. {  
  3.     auto director = cocos2d::Director::getInstance();  
  4.     auto glview = director->getOpenGLView();  
  5.     glview->closeWindow();  
  6. }  

9. 給類 AppDelegate新增 成員 

  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()  函式

  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的訊息響應函式

  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訊息響應函式:

  1. void CCocosEditorDlg::OnClose()  
  2. {  
  3.     cocos2d::Application::getInstance()->closeWindow();  
  4.     CDialogEx::OnClose();  
  5. }  

13.編譯執行程式:


14 .執行時會發現 cocos2d視窗閃了下,這個原因是cocos2d先建立,然後移到了Picture控制元件上,那我們讓Cocos2d的視窗建立時 先不可見:

  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