ATL Timer 쓰기
오후 2:21 2000-04-25 조경민
---------------------------------------------------------
ATL Full Control을 만들때 타이머를 쓰고 싶을때 다음과 같이
한다.

내 임플레멘트 클래스 헤더에 놓고
class CAtlButton :
        public CComObjectRoot,
        public CTimer<CAtlButton, IAtlButton, &IID_IAtlButton>,

이렇게 논후
        STDMETHOD(_OnTimer)()
        {
                POINT pos;
                GetCursorPos(&pos);
                if (m_bInPlaceActive)
                {
                        HWND hwnd;
                        m_spInPlaceSite->GetWindow(&hwnd);
                        ::ScreenToClient(hwnd, &pos);

                        if (!PtInRect(&m_rcPos, pos))
                        {
                                if (m_nEntry > 0)
                                {
                                        m_nEntry = 0;
                                        FireViewChange();
                                }
                        }
                }

                return S_OK;
        }
이렇게 쓰면 된다.

TimerOn(5);
그러면 _OnTimer()가 호출된다.


//////////////////////////////////////////////////////////////////////////////////////////////////
// CTimer
template <class Derived, class T, const IID* piid>
class CTimer
{
public:

        CTimer()
        {
                m_bTimerOn = FALSE;
        }

        HRESULT TimerOn(DWORD dwTimerInterval)
        {
                Derived* pDerived = ((Derived*)this);

                m_dwTimerInterval = dwTimerInterval;
                if (m_bTimerOn) // already on, just change interval
                        return S_OK;

                m_bTimerOn = TRUE;
                m_dwTimerInterval = dwTimerInterval;
                m_pStream = NULL;

                HRESULT hRes;

                hRes = CoMarshalInterThreadInterfaceInStream(*piid, (T*)pDerived, &m_pStream);

                // Create thread and pass the thread proc the this ptr
                m_hThread = CreateThread(NULL, 0, &_Apartment, (void*)this, 0, &m_dwThreadID);

                return S_OK;
        }

        void TimerOff()
        {
                if (m_bTimerOn)
                {
                        m_bTimerOn = FALSE;
                        AtlWaitWithMessageLoop(m_hThread);
                }
        }


// Implementation
private:
        static DWORD WINAPI _Apartment(void* pv)
        {
                CTimer<Derived, T, piid>* pThis = (CTimer<Derived, T, piid>*) pv;
                pThis->Apartment();
                return 0;
        }

        DWORD Apartment()
        {
                CoInitialize(NULL);
                HRESULT hRes;

                m_spT.Release();

                if (m_pStream)
                        hRes = CoGetInterfaceAndReleaseStream(m_pStream, *piid, (void**)&m_spT);

                while(m_bTimerOn)
                {
                        Sleep(m_dwTimerInterval);
                        if (!m_bTimerOn)
                                break;

                        m_spT->_OnTimer();
                }
                m_spT.Release();

                CoUninitialize();
                return 0;
        }

// Attributes
public:
        DWORD m_dwTimerInterval;

// Implementation
private:
        HANDLE m_hThread;
        DWORD m_dwThreadID;
        LPSTREAM m_pStream;
        CComPtr<T> m_spT;
        BOOL m_bTimerOn;
};

+ Recent posts