2012-03-06 66 views
1

我有一个使用Ogre3D创建多个渲染窗口的应用程序,并且我使用发布的解决方案here来支持对这些窗口的非独占鼠标输入。但是,我发现在重新获得焦点之前,我必须物理地点击一个渲染窗口,而我真的很喜欢渲染窗口关注于鼠标悬停事件。是否有可能在Ogre3D/OIS中未聚焦的渲染窗口上捕获鼠标悬停事件,然后为渲染窗口设置焦点?使用Ogre3D专注于Windows中的MouseOver

+1

注意,在许多风管理者,获得关注也意味着将窗口带入字体。对于习惯了窗口管理器的用户来说,这种行为可能非常不寻常。 – 2012-03-06 23:19:08

+0

正式指出 - 在我的特殊应用中,窗户是平铺的,并且具有静态位置,并且您建议的行为实际上是需要的... – hatboyzero 2012-03-07 02:39:47

+0

如果这是真的,那么他们为什么是窗户?你不能只渲染单独的平铺视口吗? – 2012-03-07 02:47:37

回答

0

为了在Windows中使用Ogre3D来支持这种功能,我必须实现一个单例对象,它保存了所有实例化显示的集合。

class InputProcessor 
{ 
    /// @name Types 
    /// @{ 
public: 
    /// @} 

    /// @name InputProcessor implementation 
    /// @{ 
public: 
    void addDisplay(Display* _pDisplay); 

    bool processMouseMoved(int _x, int _y, int _z, int _keyModifier); 
    bool processMousePressed(int _keyModifier, int _id); 
    bool processMouseReleased(int _keyModifier, int _id); 

    static InputProcessor& getSingleton(); 
    /// @} 

    /// @name 'Structors 
    /// @{ 
private: 
    InputProcessor(); 
    ~InputProcessor(); 
    /// @} 

    /// @name Member Variables 
    /// @{ 
private: 
    typedef std::set<Display*>  Displays_type; 
    Displays_type     m_displays; 
    /// @} 

}; // class InputProcessor 

然后,在我的UIFrameListener(从OGRE3D的ExampleFrameListener派生),我改变鼠标的窗口坐标全球屏幕坐标。如果鼠标恰好位于窗口区域之外,我将相对鼠标移动应用到最后记录的鼠标位置;否则,我简单地应用窗口内的绝对鼠标位置:

bool 
UIFrameListener::mouseMoved(const OIS::MouseEvent& e) 
{ 
    int keyModifierState = GetKeyModifierState(); 
    int windowLeft = m_display.getLeft(); 
    int windowTop = m_display.getTop(); 
    int windowWidth = m_display.m_pWindow->getWidth(); 
    int windowHeight = m_display.m_pWindow->getHeight(); 

    if (e.state.X.abs != 0 && e.state.X.abs != windowWidth) 
    { 
     m_lastX = e.state.X.abs; 
    } 
    else 
    { 
     m_lastX += e.state.X.rel; 
    } 
    int x = windowLeft + (m_display.m_width * m_lastX)/windowWidth; 

    if (e.state.Y.abs != 0 && e.state.Y.abs != windowHeight) 
    { 
     m_lastY = e.state.Y.abs; 
    } 
    else 
    { 
     m_lastY += e.state.Y.rel; 
    } 
    int y = windowTop + (m_display.m_height * m_lastY)/windowHeight; 

    int z = 0; 
    if (e.state.Z.rel != 0) 
    { 
     z = e.state.Z.rel/-120; 
    } 

    return InputProcessor::getSingleton().processMouseMoved(x, y, z, keyModifierState); 
} 

而在InputProcessor::processMouseMoved(),我确定鼠标光标是在其中窗口(如果有的话),然后适当地设定焦点,即

bool 
InputProcessor::processMouseMoved(int _x, 
            int _y, 
            int _z, 
            int _keyModifier) 
{ 
    bool found = false; 

    Displays_type::iterator iter = m_displays.begin(); 
    while (iter != m_displays.end() && !found) 
    { 
     int left = (*iter)->getLeft(); 
     int top = (*iter)->getTop(); 
     int width = (*iter)->m_pWindow->getWidth(); 
     int height = (*iter)->m_pWindow->getHeight(); 

     if (left <= _x && left + width > _x && 
      top <= _y && top + height > _y) 
     { 
      found = true; 
     } 
     else 
     { 
      iter++; 
     } 
    } 

    if (iter != m_displays.end()) 
    { 
     int left = (*iter)->getLeft(); 
     int top = (*iter)->getTop(); 

     (*iter)->m_pContext->ProcessMouseMove(
      _x - left, _y - top, _keyModifier 
     ); 

     (*iter)->m_pContext->ProcessMouseWheel(_z, _keyModifier); 

     if (!(*iter)->hasFocus()) 
     { 
      (*iter)->setFocus(true); 
     } 
    } 

    return true; 
} 

而且在Display实施,我有一个方法Display::setFocus()将焦点设置适当的窗口:

void 
Display::setFocus(bool _hasFocus) 
{ 
    if (m_handle != NULL && _hasFocus) 
    { 
     SetFocus(m_handle); 
    } 
}