Cocos2d-X 2.2嵌入MFC的子窗口

时间:2022-12-10 00:21:27

1.在cocos2dx目录下创建基于对话框的MFC工程,对话框中间放一个Picture控件

Cocos2d-X 2.2嵌入MFC的子窗口

2.添加cocos2dx的相关头文件包含路径、库包含路径和依赖项,可以参考其他cocos工程设置

3.选中Picture控件后右键单击,在弹出菜单中找到“添加变量”。为Picture控件生成一个控件变量。这里命名为m_cocosWin,并点击完成

4.右击工程添加MFC类,类名里输入“CCocos2dXWin”,并选择基类CWnd。把上面的m_cocosWin变量类型改为CCocoWin 然后点击“完成”并做如下修改。

 4.1头文件添加变量和函数

    //是否已经初始化

BOOL m_bInitCocos2dX;
//创建Cocos2dX窗口
BOOL CreateCocos2dXWindow();

4.2 cpp添加COCOS的头文件,并加入一个全局变量

#include "AppDelegate.h"
#include
"cocos2d.h"

USING_NS_CC;

AppDelegate CocoApp;

 

 

4.3函数实现

 

//创建Cocos2dX窗口
BOOL CCocoWin::CreateCocos2dXWindow()
{
//新建一个CRect变量获取窗口的客户区大小
CRect tClientRect;
GetClientRect(
&tClientRect);
//取得使用的OpenGL视窗
CCEGLView* eglView = CCEGLView::sharedOpenGLView(false,GetSafeHwnd());
//指定客户区大小。
eglView->setFrameSize(tClientRect.Width(),tClientRect.Height());
//调用程序的运行函数,增加参数bool型变量控制是否进行消息循环。因为MFC控件本身有自已的消息响应处理。如果不改动的话,这里就会进入死循环。
cocos2d::CCApplication::sharedApplication()->run();
//这里将变量设置为TRUE
m_bInitCocos2dX = TRUE;

SetTimer(
1,15,NULL);

return TRUE;
}

 4.4在CCocoToolDlg的OnInitDialog()方法中调用 CreateCocos2dXWindow()

m_cocosWin.CreateCocos2dXWindow();

 

5.利用类视图为CCocoWin添加如下方法

Cocos2d-X 2.2嵌入MFC的子窗口

 

代码实现如下:

void CCocoWin::OnTimer(UINT_PTR nIDEvent)
{
//我们写一个renderWorld函数代表Cocos2d-x的世界渲染
cocos2d::CCApplication::sharedApplication()->renderWorld();
CWnd::OnTimer(nIDEvent);
}


void CCocoWin::OnDestroy()
{
//在Cocos2d-x的引擎文件CCEGLView_win32.cpp中CCEGLView::release()会再次发送调用DestroyWindow,所以这里用变量m_bInitCocos2dX做下判断,避免二次销毁
if(TRUE == m_bInitCocos2dX)
{
//退出将m_bInitCocos2dX设为FALSE
m_bInitCocos2dX = FALSE;
//释放定时器资源
KillTimer(1);
//调用显示设备单件实例对象的end函数
CCDirector::sharedDirector()->end();
//处理一次下一帧,必须调用.
CCDirector::sharedDirector()->mainLoop();
CWnd::OnDestroy();
}
}


void CCocoWin::OnSize(UINT nType, int cx, int cy)
{
CWnd::OnSize(nType, cx, cy);
// TODO: 在此处添加消息处理程序代码
if(TRUE == m_bInitCocos2dX)
{
CRect tClientRect;
GetClientRect(
&tClientRect);
//重新设置窗口大小及投影矩阵
CCEGLView::sharedOpenGLView()->resize(tClientRect.Width(),tClientRect.Height());
CCDirector::sharedDirector()
->reshapeProjection(CCSizeMake(tClientRect.Width(),tClientRect.Height()));

}
}

 

6.CCEGLView做如下修改

 头文件

    virtual bool Create(bool bCreateWin=true,HWND hWnd=NULL);
public:
bool m_bIsSelfCreWin;//是否cocos自己创建了窗口

static CCEGLView* sharedOpenGLView(bool bCreateWin=true,HWND hWnd=NULL);//bCreateWin是否自己创建窗口,hWnd已有的MFC窗口句柄

cpp

void CCEGLView::centerWindow()
{
if (! m_hWnd||!m_bIsSelfCreWin)
{
return;
}
....

}


bool CCEGLView::Create(bool bCreateWin,HWND hWnd)
{
bool bRet = false;
do
{
CC_BREAK_IF(m_hWnd);

m_bIsSelfCreWin
=bCreateWin;

if (bCreateWin)
{

HINSTANCE hInstance
= GetModuleHandle( NULL );
WNDCLASS wc;
// Windows Class Structure

// Redraw On Size, And Own DC For Window.
wc.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
wc.lpfnWndProc
= _WindowProc; // WndProc Handles Messages
wc.cbClsExtra = 0; // No Extra Window Data
wc.cbWndExtra = 0; // No Extra Window Data
wc.hInstance = hInstance; // Set The Instance
wc.hIcon = LoadIcon( NULL, IDI_WINLOGO ); // Load The Default Icon
wc.hCursor = LoadCursor( NULL, IDC_ARROW ); // Load The Arrow Pointer
wc.hbrBackground = NULL; // No Background Required For GL
wc.lpszMenuName = m_menu; //
wc.lpszClassName = kWindowClassName; // Set The Class Name

CC_BREAK_IF(
! RegisterClass(&wc) && 1410 != GetLastError());

// center window position
RECT rcDesktop;
GetWindowRect(GetDesktopWindow(),
&rcDesktop);

WCHAR wszBuf[
50] = {0};
MultiByteToWideChar(CP_UTF8,
0, m_szViewName, -1, wszBuf, sizeof(wszBuf));

// create window
m_hWnd = CreateWindowEx(
WS_EX_APPWINDOW
| WS_EX_WINDOWEDGE, // Extended Style For The Window
kWindowClassName, // Class Name
wszBuf, // Window Title
WS_CAPTION | WS_POPUPWINDOW | WS_MINIMIZEBOX, // Defined Window Style
0, 0, // Window Position
//TODO: Initializing width with a large value to avoid getting a wrong client area by 'GetClientRect' function.
1000, // Window Width
1000, // Window Height
NULL, // No Parent Window
NULL, // No Menu
hInstance, // Instance
NULL );


}
else
{
m_hWnd
=hWnd;
}

CC_BREAK_IF(
! m_hWnd);

bRet
= initGL();
if(!bRet) destroyGL();
CC_BREAK_IF(
!bRet);

s_pMainWindow
= this;
bRet
= true;
}
while (0);

#if(_MSC_VER >= 1600)
m_bSupportTouch
= CheckTouchSupport();
if(m_bSupportTouch)
{
m_bSupportTouch
= (s_pfRegisterTouchWindowFunction(m_hWnd, 0) != 0);
}
#endif /* #if(_MSC_VER >= 1600) */

return bRet;
}



CCEGLView
* CCEGLView::sharedOpenGLView(bool bCreateWin,HWND hWnd)
{

if (s_pEglView == NULL)
{
s_pEglView
= new CCEGLView();
if(!s_pEglView->Create(bCreateWin,hWnd))
{
delete s_pEglView;
s_pEglView
= NULL;
}
}

return s_pEglView;
}

 

7.CCEGLView做如下修改

头文件添加方法

    //帧循环调用渲染  
virtual bool renderWorld();

cpp

bool CCApplication::renderWorld()
{
static LARGE_INTEGER nFreq;
static LARGE_INTEGER nLast;
static LARGE_INTEGER nNow;
static bool sbinit=true;

//只执行一次
if (sbinit)
{
QueryPerformanceFrequency(
&nFreq);
QueryPerformanceCounter(
&nLast);
sbinit
=false;
}
// Get current time tick.
QueryPerformanceCounter(&nNow);

// If it's the time to draw next frame, draw it, else sleep a while.
if (nNow.QuadPart - nLast.QuadPart > m_nAnimationInterval.QuadPart)
{
nLast.QuadPart
= nNow.QuadPart;
CCDirector::sharedDirector()
->mainLoop();

return true;
}


return false;

}
int CCApplication::run()
{
PVRFrameEnableControlWindow(
false);


// Main message loop:
MSG msg;
LARGE_INTEGER nFreq;
LARGE_INTEGER nLast;
LARGE_INTEGER nNow;

QueryPerformanceFrequency(
&nFreq);
QueryPerformanceCounter(
&nLast);

// Initialize instance and cocos2d.
if (!applicationDidFinishLaunching())
{
return 0;
}

CCEGLView
* pMainWnd = CCEGLView::sharedOpenGLView();
//pMainWnd->centerWindow();
ShowWindow(pMainWnd->getHWnd(), SW_SHOW);

//cocos自己创建的窗口才要循环处理消息
bool bloop=CCEGLView::sharedOpenGLView()->m_bIsSelfCreWin;
if (bloop)
{
while (1)
{
if (! PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
{
// Get current time tick.
QueryPerformanceCounter(&nNow);

// If it's the time to draw next frame, draw it, else sleep a while.
if (nNow.QuadPart - nLast.QuadPart > m_nAnimationInterval.QuadPart)
{
nLast.QuadPart
= nNow.QuadPart;
CCDirector::sharedDirector()
->mainLoop();
}
else
{
Sleep(
0);
}
continue;
}

if (WM_QUIT == msg.message)
{
// Quit message loop.
break;
}

// Deal with windows message.
if (! m_hAccelTable || ! TranslateAccelerator(msg.hwnd, m_hAccelTable, &msg))
{
TranslateMessage(
&msg);
DispatchMessage(
&msg);
}
}

return (int) msg.wParam;
}


return 0;
}

8.新建个Classes文件夹,并把AppDelegate两个文件复制过去,在VS中右击包含到工程里

Cocos2d-X 2.2嵌入MFC的子窗口

 

 

 9.把工程的工作目录指向Resources文件夹,可以是以前的COCOS工程的Resources目录

 

如果出现类似 error LNK2005: "void * __cdecl operator new(unsigned int)的错误,参考

http://m.blog.csdn.net/blog/dotphoenix/13511863

运行效果:

Cocos2d-X 2.2嵌入MFC的子窗口

 

具体修改的思路不做详细说明,具体请参考

http://blog.csdn.net/honghaier/article/details/8009046