第十四篇:在SOUI中使用定時器

前言

定時器是win32編程中經常使用的製做動畫效果的手段。在Win32編程中,可使用::SetTimer來建立定時器,定時器消息會被會發到調用SetTimer時指定的HWND。編程

在SOUI中通常來講只有一個宿主窗口有HWND,全部的SWindow都屬於一個宿主窗口,如此一來直接使用::SetTimer建立的定時器就難以直接分發到SWindow對象了。函數

在SOUI的控件中使用定時器

爲了可以方便的在SWindow中使用定時器,在SOUI系統中,咱們經過將定時器ID(共32位)按位進行分解:動畫

    class SOUI_EXP STimerID
    {
    public:
        DWORD    Swnd:24;        //窗口句柄,若是窗口句柄超過24位範圍,則不能使用這種方式設置定時器
        DWORD    uTimerID:7;        //定時器ID,一個窗口最多支持128個定時器。
        DWORD    bSwndTimer:1;    //區別通用定時器的標誌,標誌爲1時,表示該定時器爲SWND定時器

        STimerID(SWND hWnd,char id)
        {
            SASSERT(hWnd<0x00FFFFFF && id>=0);
            bSwndTimer=1;
            Swnd=hWnd;
            uTimerID=id;
        }
        STimerID(DWORD dwID)
        {
            memcpy(this,&dwID,sizeof(DWORD));
        }
        operator DWORD &() const
        {
            return *(DWORD*)this;
        }
    };

低24位用來存儲SWindow的窗口ID(swnd)。swnd是一個SWindow建立序號,在一個應用中,一般很難產生超過0xFFFFFF(16777215)個窗口對象,所以使用低24位來存儲窗口ID在大部分狀況下都是夠用的了。this

高8位中保留最高位設置爲1,用來區別直接使用::SetTimer建立的定時器(不能夠把最高位置1)。spa

剩下7位用於SWindow中做爲定時器ID。所以在SOUI中,一個SWindow最多能夠建立0-127個定時器。code

建立定時器:對象

SWindow::SetTimer(0~127);
        /**
        * SWindow::SetTimer
        * @brief    利用窗口定時器來設置一個ID爲0-127的SWND定時器
        * @param    char id --  定時器ID
        * @param    UINT uElapse --  延時(MS)
        * @return   BOOL 
        *
        * Describe  參考::SetTimer
        */
        BOOL SWindow::SetTimer(char id,UINT uElapse);

銷燬定時器:blog

  SWindow::KillTimer;接口

        /**
        * KillTimer
        * @brief    刪除一個SWND定時器
        * @param    char id --  定時器ID
        * @return   void 
        *
        * Describe  
        */
        void KillTimer(char id);

 

響應定時器消息:開發

在消息映射表中使用MSG_WM_TIMER_EX。參見:SGifPlayer.h

        SOUI_MSG_MAP_BEGIN()    
            MSG_WM_TIMER_EX(OnTimer)    //定時器消息
            MSG_WM_PAINT_EX(OnPaint)    //窗口繪製消息
            MSG_WM_SHOWWINDOW(OnShowWindow)//窗口顯示狀態消息
        SOUI_MSG_MAP_END()    

若是在一個窗口中必需要建立使用32位的定時器ID,在SOUI中可使用另外一個接口來實現:

        /**
        * SetTimer2
        * @brief    利用函數定時器來模擬一個兼容窗口定時器
        * @param    UINT_PTR id --  定時器ID
        * @param    UINT uElapse --  延時(MS)
        * @return   BOOL 
        *
        * Describe  因爲SetTimer只支持0-127的定時器ID,SetTimer2提供設置其它timerid
        *           可以使用SetTimer時儘可能不用SetTimer2,在Kill時效率會比較低
        */
        BOOL SetTimer2(UINT_PTR id,UINT uElapse);

        /**
        * KillTimer2
        * @brief    刪除一個SetTimer2設置的定時器
        * @param    UINT_PTR id --  SetTimer2設置的定時器ID
        * @return   void 
        *
        * Describe  須要枚舉定時器列表
        */
        void KillTimer2(UINT_PTR id);

響應定時器:

使用SWindow::SetTimer2建立的定時器,最後會經過一個消息:WM_TIMER2來分發到SWindow。

#define WM_TIMER2    (WM_USER+5432)    //定義一個與HWND定時器兼容的SOUI定時器

#define MSG_WM_TIMER2(func) \
    if (uMsg == WM_TIMER2) \
{ \
    SetMsgHandled(TRUE); \
    func(wParam); \
    lResult = 0; \
    if(IsMsgHandled()) \
    return TRUE; \
}

在應用程序中使用定時器

前面兩種定時器都是在控件開發的時候使用定時器的方法。而在應用層,還能夠爲宿主窗口直接使用::SetTimer或者宿主窗口的基類:CSimpleWnd::SetTimer來建立定時器(注意最高位必須是0)。

在響應這類定時器時,同樣能夠在宿主窗口的消息映射表中使用MSG_WM_TIMER來響應定時器消息。可是須要注意的是,這個映射宏會截獲全部分發給宿主窗口的定時器,若是不是本身建立的定時器,則須要繼續交給基類處理。

能夠調用:SetMsgHandled(FALSE); 或者:SHostWnd::OnTimer(UINT_PTR idEvent);實現。

相關文章
相關標籤/搜索