Posted on 2012-04-22 13:40
buf 阅读(1489)
评论(0) 编辑 收藏 引用 所属分类:
Graphics
简单来看,将vp窗口嵌入MFC只需调用vpWindow::setParent()就可以了。实际上,还有vp线程管理、鼠标/键盘IO、重设窗口大小等工作/事件需要处理,于是想到设计一个用于在MFC窗口中运行vp的基类,考虑到vp的初始化、帧循环有独立的线程(另一种方式是使用定时器),将这个基类命名为CThreadingVP。
这个基类的定义如下,使用static方法实现所有与具体应用无关的功能:
class CThreadingVP : public vpApp
{
VP_DECLARE_DYNACREATE(CThreadingVP)
public:
CThreadingVP(void);
virtual ~CThreadingVP(void);
// 模块的加载/卸载
virtual int LoadModules();
virtual int UnLoadModules();
// 重设vp窗口大小
static void Reshape(int cx, int cy);
// 获取焦点
static void SetFocus();
// 设置ACF文件路径
static void SetACFFile(const char *acfFile);
// 设置vp初始化状态
static void SetInitialized(BOOL fInit) { m_fInitialized = fInit; }
// 设置父窗口
static void SetParentWindow(HWND hParent);
// 启动vp线程
static void StartVP(LPVOID param);
// 终止vp线程
static void StopVP();
// 获取ACF路径
static vuString GetACFFile() { return m_acfFile; }
// 获取父窗口
static HWND ParentWindow() { return m_hParent; }
// 查询vp运行状态
static BOOL ContinueRunning() { return m_fContinueRunning; }
// 查询vp初始化状态
static BOOL IsInitialized() { return m_fInitialized; }
protected:
static DWORD WINAPI vpThreadProc(LPVOID param); // vp线程函数
static HANDLE m_hThread; // vp线程句柄
static HWND m_hParent; // 父窗口
static vuString m_acfFile; // ACF文件路径
static BOOL m_fInitialized; // vp初始化状态
static BOOL m_fContinueRunning; // vp运行状态
};
CThreaingVP的使用非常简单,可以直接使用,也可以创建子类,重载vpApp的configure等方法,用于完成具体应用相关的初始化等:
class CSomeVP : public CThreadingVP, public vpKernel::Subscriber
{
VP_DECLARE_DYNACREATE(CSomeVP)
public:
CSomeVP(void)
{
}
virtual ~CSomeVP(void)
{
}
int configure()
{
int ret = CThreadingVP::configure();
assert(ret == vsgu::SUCCESS);
m_pTank = vpObject::find("tank");
assert(m_pTank != NULL);
m_pTank->setPosition(2500, 2500, 0);
m_pTank->setRotateH(-90.0);
return ret;
}
private:
vpObject *m_pTank;
};
vp的创建可以在view窗口的OnCreate回调中完成:
int CChildView::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
if (CWnd::OnCreate(lpCreateStruct) == -1)
return -1;
CSomeVP::SetACFFile("vp_simple.acf");
CSomeVP::SetParentWindow(GetSafeHwnd());
CSomeVP::StartVP(CSomeVP::pfnCreate);
return 0;
}
另外,还需要处理重设窗口大小和输入焦点问题:
void CChildView::OnSize(UINT nType, int cx, int cy)
{
CSomeVP::Reshape(cx, cy);
}
void CChildView::OnSetFocus(CWnd* pOldWnd)
{
TRACE0("view got focus\n");
CSomeVP::SetFocus();
}
至于VP_DECLARE_DYNACREATE这个宏定义,是出于在基类的静态方法(CThreading::vpThreadProc)中创建子类实例的需要。也不知道这类需求是否有标准做法,参考MFC中动态创建的思路做了这个简单的实现:
#define VP_DECLARE_DYNACREATE(vp_class) \
private:\
static CThreadingVP* CreateObject();\
public:\
typedef CThreadingVP* (* PFNCREATE)();\
static PFNCREATE pfnCreate;
#define VP_IMPLEMENT_DYNACREATE(vp_class) \
CThreadingVP* vp_class::CreateObject() { return (new vp_class); }\
vp_class::PFNCREATE vp_class::pfnCreate = vp_class::CreateObject;
>>完整工程下载<<