您的位置:首页 > 移动开发 > Cocos引擎

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

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

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


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

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

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

[cpp] view
plaincopy





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;

}

2. 于是我们查看AppDelegate::applicationDidFinishLaunching() 代码:

[cpp] view
plaincopy





bool AppDelegate::applicationDidFinishLaunching() {

// initialize director

auto director = Director::getInstance();

auto glview = director->getOpenGLView();

if(!glview) {

[cpp] view
plaincopy





//第一次运行肯定会进入这里,这个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;

3. 我们看看GLView::create函数代码

[cpp] view
plaincopy





GLView* GLView::create(const std::string& viewName)

{

auto ret = new GLView;

[cpp] view
plaincopy





//调用了initWithRect()</span>

if(ret && ret->initWithRect(viewName, Rect(0, 0, 960, 640), 1)) {

ret->autorelease();

return ret;

}

return nullptr;

}

4.initWithRect 代码

[html] view
plaincopy





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

{

setViewName(viewName);

_frameZoomFactor = frameZoomFactor;

glfwWindowHint(GLFW_RESIZABLE,GL_FALSE);

[html] view
plaincopy





//找到了,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;

}

5. 有个API 函数glfwGetWin32Window() 可以取得窗口句柄。(由于不了解glfw 网上搜了半天才找到这个。。。)

参考: http://www.glfw.org/docs/3.0/group__native.html
6.下面开始修改代码

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

[cpp] view
plaincopy





#define GLFW_EXPOSE_NATIVE_WIN32

#define GLFW_EXPOSE_NATIVE_WGL

#include "glfw3native.h"

给GLView类添加成员:

[cpp] view
plaincopy





HWND getHwnd();

void closeWindow();

HWND m_hwnd;

[cpp] view
plaincopy





HWND GLView::getHwnd()

{

return m_hwnd;

}

void GLView::closeWindow()

{

glfwSetWindowShouldClose(_mainWindow, 1);

}

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

在函数最后添加

[cpp] view
plaincopy





m_hwnd = glfwGetWin32Window(_mainWindow);

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

[cpp] view
plaincopy





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成员函数

[cpp] view
plaincopy





void Application::closeWindow()

{

auto director = cocos2d::Director::getInstance();

auto glview = director->getOpenGLView();

glview->closeWindow();

}

9. 给类 AppDelegate添加 成员

[cpp] view
plaincopy





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

[cpp] view
plaincopy





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;

}

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

[cpp] view
plaincopy





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消息响应函数:

[cpp] view
plaincopy





void CCocosEditorDlg::OnClose()

{

cocos2d::Application::getInstance()->closeWindow();

CDialogEx::OnClose();

}

13.编译运行程序:



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

[cpp] view
plaincopy





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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: