2012-03-06 38 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); 
    } 
}