第十四篇:在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在大部分情況下都是夠用的了。

高8位中保留最高位設置為1,用來區別直接使用::SetTimer創建的定時器(不可以把最高位置1)。

剩下7位用於SWindow中作為定時器ID。因此在SOUI中,一個SWindow最多可以創建0-127個定時器。

創建定時器:

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);

銷毀定時器:

  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);實現。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM