buf

BE something YOU love and understand
posts - 94, comments - 35, trackbacks - 0, articles - 2
   :: 首页 :: 新随笔 :: 联系 ::  :: 管理

vega prime - 在MFC窗口中嵌入vp的基类

Posted on 2012-04-22 13:40 buf 阅读(1440) 评论(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(250025000);
        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;

>>完整工程下载<<
只有注册用户登录后才能发表评论。