上一篇我们配置了运行环境,但是并不完美,MFC窗口 和 cosos2d 窗口是分开运行的。 如果用来做工具 看起来不太好看,这一篇我们将修改cocos2d 代码,让其运行在MFC控件上
参考:http://blog.csdn.net/akof1314/article/details/8133800
要把cocos2d 窗口运行在 MFC 控件上, 我们就要找到这个窗口的句柄,下面我们来一步步找,看看怎样得到这个窗口句柄
1.首先我们来分析cocos2d的运行机制
打开cocos2d::Application::getInstance()->run(); run()函数的源码:
- int Application::run()
- {
- PVRFrameEnableControlWindow(false);
- // Main message loop:
- LARGE_INTEGER nFreq;
- LARGE_INTEGER nLast;
- LARGE_INTEGER nNow;
- QueryPerformanceFrequency(&nFreq);
- QueryPerformanceCounter(&nLast);
- //这里调用了AppDelegate中的<span style="font-family: Arial, Helvetica, sans-serif;">applicationDidFinishLaunching()
- // Initialize instance and cocos2d.
- if (!applicationDidFinishLaunching())
- {
- return 0;
- }
- //那么游戏窗口一定是在这之前创建的</span>
- auto director = Director::getInstance();
- auto glview = director->getOpenGLView();
- // Retain glview to avoid glview being released in the while loop
- glview->retain();
- //下面是游戏主循环</span>
- while(!glview->windowShouldClose())
- {
- QueryPerformanceCounter(&nNow);
- if (nNow.QuadPart - nLast.QuadPart > _animationInterval.QuadPart)
- {
- nLast.QuadPart = nNow.QuadPart;
- director->mainLoop();
- glview->pollEvents();
- }
- else
- {
- Sleep(0);
- }
- }
- // Director should still do a cleanup if the window was closed manually.
- if (glview->isOpenGLReady())
- {
- director->end();
- director->mainLoop();
- director = nullptr;
- }
- glview->release();
- return true;
- }
- bool AppDelegate::applicationDidFinishLaunching() {
- // initialize director
- auto director = Director::getInstance();
- auto glview = director->getOpenGLView();
- if(!glview) {
- //第一次运行肯定会进入这里,这个create函数创建了GLView对象
- glview = GLView::create("My Game");
- director->setOpenGLView(glview);
- }
- // turn on display FPS
- director->setDisplayStats(true);
- // set FPS. the default value is 1.0/60 if you don't call this
- director->setAnimationInterval(1.0 / 60);
- // create a scene. it's an autorelease object
- auto scene = HelloWorld::createScene();
- // run
- director->runWithScene(scene);
- return true;
- GLView* GLView::create(const std::string& viewName)
- {
- auto ret = new GLView;
- //调用了initWithRect()</span>
- if(ret && ret->initWithRect(viewName, Rect(0, 0, 960, 640), 1)) {
- ret->autorelease();
- return ret;
- }
- return nullptr;
- }
- bool GLView::initWithRect(const std::string& viewName, Rect rect, float frameZoomFactor)
- {
- setViewName(viewName);
- _frameZoomFactor = frameZoomFactor;
- glfwWindowHint(GLFW_RESIZABLE,GL_FALSE);
- //找到了,glfwCreateWindow 这个函数就是创建窗口的(我只知道glfw是个open gl 的库,想了解的可以去搜一下),下面我们来取窗口句柄
- _mainWindow = glfwCreateWindow(rect.size.width * _frameZoomFactor,
- rect.size.height * _frameZoomFactor,
- _viewName.c_str(),
- _monitor,
- nullptr);
- glfwMakeContextCurrent(_mainWindow);
- glfwSetMouseButtonCallback(_mainWindow, GLFWEventHandler::onGLFWMouseCallBack);
- glfwSetCursorPosCallback(_mainWindow, GLFWEventHandler::onGLFWMouseMoveCallBack);
- glfwSetScrollCallback(_mainWindow, GLFWEventHandler::onGLFWMouseScrollCallback);
- glfwSetCharCallback(_mainWindow, GLFWEventHandler::onGLFWCharCallback);
- glfwSetKeyCallback(_mainWindow, GLFWEventHandler::onGLFWKeyCallback);
- glfwSetWindowPosCallback(_mainWindow, GLFWEventHandler::onGLFWWindowPosCallback);
- glfwSetFramebufferSizeCallback(_mainWindow, GLFWEventHandler::onGLFWframebuffersize);
- glfwSetWindowSizeCallback(_mainWindow, GLFWEventHandler::onGLFWWindowSizeFunCallback);
- setFrameSize(rect.size.width, rect.size.height);
- // check OpenGL version at first
- const GLubyte* glVersion = glGetString(GL_VERSION);
- if ( utils::atof((const char*)glVersion) < 1.5 )
- {
- char strComplain[256] = {0};
- sprintf(strComplain,
- "OpenGL 1.5 or higher is required (your version is %s). Please upgrade the driver of your video card.",
- glVersion);
- MessageBox(strComplain, "OpenGL version too old");
- return false;
- }
- initGlew();
- // Enable point size by default.
- glEnable(GL_VERTEX_PROGRAM_POINT_SIZE);
- return true;
- }
参考: http://www.glfw.org/docs/3.0/group__native.html
6.下面开始修改代码
在CCGLView.cpp 前面添加(头文件一定要在宏定义后面)
- #define GLFW_EXPOSE_NATIVE_WIN32
- #define GLFW_EXPOSE_NATIVE_WGL
- #include "glfw3native.h"
给GLView类添加成员:
- HWND getHwnd();
- void closeWindow();
- HWND m_hwnd;
- HWND GLView::getHwnd()
- {
- return m_hwnd;
- }
- void GLView::closeWindow()
- {
- glfwSetWindowShouldClose(_mainWindow, 1);
- }
在函数最后添加
- m_hwnd = glfwGetWin32Window(_mainWindow);
- int Application::cocosrun()
- {
- PVRFrameEnableControlWindow(false);
- // Main message loop:
- LARGE_INTEGER nFreq;
- LARGE_INTEGER nLast;
- LARGE_INTEGER nNow;
- QueryPerformanceFrequency(&nFreq);
- QueryPerformanceCounter(&nLast);
- // Initialize instance and cocos2d.
- if (!applicationDidFinishLaunching())
- {
- return 0;
- }
- auto director = Director::getInstance();
- auto glview = director->getOpenGLView();
- // Retain glview to avoid glview being released in the while loop
- glview->retain();
- ShowWindow(glview->getHwnd(), SW_SHOW);
- while(!glview->windowShouldClose())
- {
- QueryPerformanceCounter(&nNow);
- if (nNow.QuadPart - nLast.QuadPart > _animationInterval.QuadPart)
- {
- nLast.QuadPart = nNow.QuadPart;
- director->mainLoop();
- glview->pollEvents();
- }
- else
- {
- Sleep(0);
- }
- }
- // Director should still do a cleanup if the window was closed manually.
- if (glview->isOpenGLReady())
- {
- director->end();
- director->mainLoop();
- director = nullptr;
- }
- glview->release();
- return true;
- }
8. 打开Application 类添加一个 void closeWindow() public成员函数
- void Application::closeWindow()
- {
- auto director = cocos2d::Director::getInstance();
- auto glview = director->getOpenGLView();
- glview->closeWindow();
- }
9. 给类 AppDelegate添加 成员
- HWND m_hwnd;
- RECT m_parentRect;
- void AppDelegate::setParent(HWND hwnd,RECT rect)
- {
- m_hwnd = hwnd;
- m_parentRect.left = rect.left;
- m_parentRect.top = rect.top;
- m_parentRect.right = rect.right;
- m_parentRect.bottom = rect.bottom;
- }
10 修改AppDelegate::applicationDidFinishLaunching() 函数
- bool AppDelegate::applicationDidFinishLaunching() {
- // initialize director
- auto director = Director::getInstance();
- auto glview = director->getOpenGLView();
- if(!glview) {
- glview = GLView::create("My Game");
- director->setOpenGLView(glview);
- }
- ::SetParent(glview->getHwnd(), m_hwnd);
- SetWindowLong(glview->getHwnd(), GWL_STYLE, GetWindowLong(glview->getHwnd(), GWL_STYLE) & ~WS_CAPTION );
- ::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);
- // turn on display FPS
- director->setDisplayStats(true);
- // set FPS. the default value is 1.0/60 if you don't call this
- director->setAnimationInterval(1.0 / 60);
- // create a scene. it's an autorelease object
- auto scene = HelloWorld::createScene();
- // run
- director->runWithScene(scene);
- return true;
- }
- void CCocosEditorDlg::OnBnClickedButton1()
- {
- AppDelegate app;
- RECT rc;
- m_cocos2dWin.GetClientRect(&rc);
- app.setParent(m_cocos2dWin.m_hWnd, rc);
- cocos2d::Application::getInstance()->cocosrun();
- }
12. 关闭cocos2d窗口, 在类向导中 给MFC对话框窗口添加 WM_CLOSE消息响应函数:
- void CCocosEditorDlg::OnClose()
- {
- cocos2d::Application::getInstance()->closeWindow();
- CDialogEx::OnClose();
- }
13.编译运行程序:
14 .运行时会发现 cocos2d窗口闪了下,这个原因是cocos2d先创建,然后移到了Picture控件上,那我们让Cocos2d的窗口创建时 先不可见:
- bool GLView::initWithRect(const std::string& viewName, Rect rect, float frameZoomFactor)
- {
- setViewName(viewName);
- _frameZoomFactor = frameZoomFactor;
- glfwWindowHint(GLFW_RESIZABLE,GL_FALSE);
- glfwWindowHint(GLFW_VISIBLE , GL_FALSE);
- _mainWindow = glfwCreateWindow(rect.size.width * _frameZoomFactor,
- rect.size.height * _frameZoomFactor,
- _viewName.c_str(),
- _monitor,
- nullptr);
- glfwMakeContextCurrent(_mainWindow);
- glfwSetMouseButtonCallback(_mainWindow, GLFWEventHandler::onGLFWMouseCallBack);
- glfwSetCursorPosCallback(_mainWindow, GLFWEventHandler::onGLFWMouseMoveCallBack);
- glfwSetScrollCallback(_mainWindow, GLFWEventHandler::onGLFWMouseScrollCallback);
- glfwSetCharCallback(_mainWindow, GLFWEventHandler::onGLFWCharCallback);
- glfwSetKeyCallback(_mainWindow, GLFWEventHandler::onGLFWKeyCallback);
- glfwSetWindowPosCallback(_mainWindow, GLFWEventHandler::onGLFWWindowPosCallback);
- glfwSetFramebufferSizeCallback(_mainWindow, GLFWEventHandler::onGLFWframebuffersize);
- glfwSetWindowSizeCallback(_mainWindow, GLFWEventHandler::onGLFWWindowSizeFunCallback);
- setFrameSize(rect.size.width, rect.size.height);
- // check OpenGL version at first
- const GLubyte* glVersion = glGetString(GL_VERSION);
- if ( utils::atof((const char*)glVersion) < 1.5 )
- {
- char strComplain[256] = {0};
- sprintf(strComplain,
- "OpenGL 1.5 or higher is required (your version is %s). Please upgrade the driver of your video card.",
- glVersion);
- MessageBox(strComplain, "OpenGL version too old");
- return false;
- }
- initGlew();
- // Enable point size by default.
- glEnable(GL_VERTEX_PROGRAM_POINT_SIZE);
- m_hwnd = glfwGetWin32Window(_mainWindow);</span>
- return true;
- }
这样就解决闪一下的问题
转载请注明出处。
Test下载地址:点击打开链接
转子:
http://blog.csdn.net/greatchina01/article/details/39580767