Toggle menu
Toggle personal menu
Not logged in
Your IP address will be publicly visible if you make any edits.

MFCStudy 2001/MMTimer: Difference between revisions

From ZeroWiki
imported>Unknown
No edit summary
 
(Repair MoniWiki formatting after migration)
 
Line 1: Line 1:
__TOC__
__TOC__
= MultiMedia Timer =
= MultiMedia Timer =
  멀티미디어 타이머에 대한 설명을 적게 되었습니다.
  멀티미디어 타이머에 대한 설명을 적게 되었습니다.<br />
  저는 ZP 01 이선호 입니다.
  저는 ZP 01 이선호 입니다.<br />
  저는 ZP 01 강인수 입니다.
  저는 ZP 01 강인수 입니다.<br />


= 기본 개념 =
= 기본 개념 =
Line 16: Line 16:


== 기본 사용법 ==
== 기본 사용법 ==
  멀티미디어 타이머에 관련된 함수는 여러가지이나, 타이머를 구현하는데 필요한 함수는 세개입니다.  
  멀티미디어 타이머에 관련된 함수는 여러가지이나, 타이머를 구현하는데 필요한 함수는 세개입니다. <br />
  ! 그러나 그전에 추가시켜줘야할 게 있습니다.
  ! 그러나 그전에 추가시켜줘야할 게 있습니다.<br />
  첫째는 WINMM.LIB를 추가시켜줘야 하고
  첫째는 WINMM.LIB를 추가시켜줘야 하고<br />
  둘째는 MMSYSTEM.H 를 인클루드 시켜줘야 합니다.
  둘째는 MMSYSTEM.H 를 인클루드 시켜줘야 합니다.<br />
  *추가하는법 :
  *추가하는법 :
  소스에 #include <mmsystem.h> 를 넣고
  소스에 #include <mmsystem.h> 를 넣고<br />
  Project(P) - Setting(S, ALT+F7)을 눌러 Link탭의 Object/Library modules:란에 winmm.lib를 적어줍니다.
  Project(P) - Setting(S, ALT+F7)을 눌러 Link탭의 Object/Library modules:란에 winmm.lib를 적어줍니다.
=== timeSetEvent ===
=== timeSetEvent ===
타이머를 발동시키는 함수입니다.
타이머를 발동시키는 함수입니다.<br />
  MMRESULT timeSetEvent(UINT uDelay, UINT uResolution, LPTIMECALLBACK lpTimeProc, DWORD_PTR dwUser, UINT fuEvent);
  MMRESULT timeSetEvent(UINT uDelay, UINT uResolution, LPTIMECALLBACK lpTimeProc, DWORD_PTR dwUser, UINT fuEvent);
----
----
Line 37: Line 37:


===  TimeProc ===
===  TimeProc ===
타이머로 불러내어 직접 실행되는 함수부분입니다
타이머로 불러내어 직접 실행되는 함수부분입니다<br />
  void CALLBACK TimeProc(UINT uID, UINT uMsg, DWORD dwUser, DWORD dw1, DWORD dw2)
  void CALLBACK TimeProc(UINT uID, UINT uMsg, DWORD dwUser, DWORD dw1, DWORD dw2)
----
----
Line 46: Line 46:


=== timeKillEvent ===
=== timeKillEvent ===
사용이 끝난 타이머를 죽이는 부분입니다.
사용이 끝난 타이머를 죽이는 부분입니다.<br />
  MMRESULT timeKillEvent(UINT uTimerID);
  MMRESULT timeKillEvent(UINT uTimerID);
----
----
Line 65: Line 65:
      pDlg-&gt;SendMessage(WM_MYMSG,0,0);
      pDlg-&gt;SendMessage(WM_MYMSG,0,0);
       }
       }
* 콜백 함수를 정의한것입니다. 콜백 함수내에서는 복잡한 일은 하지 않는게 정신건강에 좋다고 합니다.
* 콜백 함수를 정의한것입니다. 콜백 함수내에서는 복잡한 일은 하지 않는게 정신건강에 좋다고 합니다.<br />
     그래서 메시지로 날려 봤습니다. 그런데 전 별루 차이점을 못느끼겠더군요..--;
     그래서 메시지로 날려 봤습니다. 그런데 전 별루 차이점을 못느끼겠더군요..--;<br />
     고칠것 있으면 고쳐 주시길...
     고칠것 있으면 고쳐 주시길...
  CAlcaDlg *pDlg = (CAlcaDlg*)AfxGetMainWnd();
  CAlcaDlg *pDlg = (CAlcaDlg*)AfxGetMainWnd();
Line 73: Line 73:
         // 타이머 종료
         // 타이머 종료
----
----
  CALLBACK 함수를 클래스 함수로 선언한 경우
  CALLBACK 함수를 클래스 함수로 선언한 경우<br />
  클래스 선언시 timeproc함수는 static 으로 선언해야 합니다.
  클래스 선언시 timeproc함수는 static 으로 선언해야 합니다.
----
----
Line 89: Line 89:
   setTimerEvent때 얻은 타이머의 번호를 집어넣어 타이머를 죽입니다.
   setTimerEvent때 얻은 타이머의 번호를 집어넣어 타이머를 죽입니다.
== 주의점 ==
== 주의점 ==
* CALLBACK 함수를 사용할때의 주의점. (in MSDN)
* CALLBACK 함수를 사용할때의 주의점. (in MSDN)<br />
* Applications should not call any system-defined functions from inside a callback function, except for PostMessage, timeGetSystemTime, timeGetTime, timeSetEvent, timeKillEvent, midiOutShortMsg, midiOutLongMsg, and OutputDebugString.
* Applications should not call any system-defined functions from inside a callback function, except for PostMessage, timeGetSystemTime, timeGetTime, timeSetEvent, timeKillEvent, midiOutShortMsg, midiOutLongMsg, and OutputDebugString.<br />
* 어플리케이션은 콜백 함수 내부로부터 다음 함수를 제외하고는 시스템 정의 함수를 부를 수가 없다. : PostMessage, timeGetSystemTime, timeGetTime, timeSetEvent, timeKillEvent, midiOutShortMsg, midiOutLongMsg, and OutputDebugString.
* 어플리케이션은 콜백 함수 내부로부터 다음 함수를 제외하고는 시스템 정의 함수를 부를 수가 없다. : PostMessage, timeGetSystemTime, timeGetTime, timeSetEvent, timeKillEvent, midiOutShortMsg, midiOutLongMsg, and OutputDebugString.<br />
  왠만한 함수들은 Callback함수 내에서 부르면 안됩니다.
  왠만한 함수들은 Callback함수 내에서 부르면 안됩니다.
* KB문서 Q130866번을 참고했습니다.
* KB문서 Q130866번을 참고했습니다.
Line 114: Line 114:
----
----
[[MFCStudy_2001]]
[[MFCStudy_2001]]

Latest revision as of 14:01, 26 March 2026

MultiMedia Timer

멀티미디어 타이머에 대한 설명을 적게 되었습니다.
저는 ZP 01 이선호 입니다.
저는 ZP 01 강인수 입니다.

기본 개념

  • OnTimer와 SetTimer의 조합으로 구현되는 가장 일반적인 타이머는 정확하지 않습니다.
이게 메시지 방식으로 구동되기 때문에 메시지 큐에 다른 메시지가 쌓이면 그 만큼
조금씩 늦어지게 된다고 합니다. 실제로도 공이 움직이는 동안에 막대기를 막 움직이
면 공이 미세하게 느려지는 것을 볼 수 있습니다.(나만 그런가?--;)
  • 이것을 해결하기 위해 MultiMedia Timer를 쓰게 됩니다. Devpia에서 본 바에 의하면
MultiMedia Timer는 자체적으로 스레드를 만든다네요. 그래서 메시지가 쌓이든 말든
자기 혼자 할 짓을 다 한대네요.

기본 사용법

멀티미디어 타이머에 관련된 함수는 여러가지이나, 타이머를 구현하는데 필요한 함수는 세개입니다. 
! 그러나 그전에 추가시켜줘야할 게 있습니다.
첫째는 WINMM.LIB를 추가시켜줘야 하고
둘째는 MMSYSTEM.H 를 인클루드 시켜줘야 합니다.
*추가하는법 : 소스에 #include <mmsystem.h> 를 넣고
Project(P) - Setting(S, ALT+F7)을 눌러 Link탭의 Object/Library modules:란에 winmm.lib를 적어줍니다.

timeSetEvent

타이머를 발동시키는 함수입니다.

MMRESULT timeSetEvent(UINT uDelay, UINT uResolution, LPTIMECALLBACK lpTimeProc, DWORD_PTR dwUser, UINT fuEvent);

  • MMRESULT에는 타이머의 번호가 리턴됩니다. NULL일 경우에는 실패한 경우입니다.
  • uDelay : 타이머가 호출될 간격을 넣습니다. 단위는 ms입니다.
  • uResolution : 대개 0을 넣습니다만... 정확도 같다고 합니다.
  • lpTimeProc : CALLBACK함수의 이름을 넣습니다.
  • dwUser : CALLBACK함수에 전달할 인자를 넣습니다.
  • fuEvent : 타이머가 호출되는 방법을 넣습니다.
    • TIME_ONESHOT : CALLBACK함수가 딱 한번만 실행됩니다.
    • TIME_PERIODIC : uDelay시간이 지날 때마다 CALLBACK함수가 실행됩니다.

TimeProc

타이머로 불러내어 직접 실행되는 함수부분입니다

void CALLBACK TimeProc(UINT uID, UINT uMsg, DWORD dwUser, DWORD dw1, DWORD dw2)

  • uID : 타이머의 번호가 넘어옵니다
  • dwUser : timeSetEvent 함수의 dwUser값이 넘어옵니다.
  • 나머지 두 변수는 쓰지 않습니다.
  • 이것은 콜백 함수라서 전역 변수로 해야된다네요. 굳이 클래스 안에 넣고 싶다면 static으로 선언해야 합니다.

timeKillEvent

사용이 끝난 타이머를 죽이는 부분입니다.

MMRESULT timeKillEvent(UINT uTimerID);

  • uTimerID 에는 타이머의 번호를 넣습니다.

이상이 기본 사용법이었습니다.

예제

CALLBACK 함수를 전역으로 선언한 경우

m_TimerID=timeSetEvent(20,1,&TimerProc,(DWORD)this,TIME_PERIODIC);
  • 타이머를 시작하는 부분입니다.
  • m_TimerID는 UINT형 입니다.
void CALLBACK TimerProc(UINT uiID,UINT uiMsg,DWORD dwUser,DWORD dw1,DWORD dw2)
      {
             CAlcaDlg *pDlg=(CAlcaDlg*)AfxGetMainWnd();

	    pDlg->SendMessage(WM_MYMSG,0,0);
      }
  • 콜백 함수를 정의한것입니다. 콜백 함수내에서는 복잡한 일은 하지 않는게 정신건강에 좋다고 합니다.
   그래서 메시지로 날려 봤습니다. 그런데 전 별루 차이점을 못느끼겠더군요..--;
고칠것 있으면 고쳐 주시길... CAlcaDlg *pDlg = (CAlcaDlg*)AfxGetMainWnd(); // 메인 윈도우의 포인터를 얻어와서 timeKillEvent(pDlg->m_TimerID); // 타이머 종료

CALLBACK 함수를 클래스 함수로 선언한 경우
클래스 선언시 timeproc함수는 static 으로 선언해야 합니다.

  • CALLBACK 함수는 클래스 내에서 선언 될 경우에는 static으로 선언 되어야합니다.
m_nTimerID = timeSetEvent(5, 0, (LPTIMECALLBACK)timeproc, (DWORD)this, TIME_PERIODIC);
  • m_nTimerID는 UINT형 입니다. 성공할 경우에는 타이머의 번호가 넘어옵니다.
  • 5는 타이머가 호출될 간격입니다. 역시 단위는 ms(1/1000초)입니다.
  • this는 이 클래스 인스턴스의 값을 넘겨줍니다. 클래스 내부 함수로 선언했을 경우네는 중요한 인자값입니다.
void CALLBACK CMyDlg::timeproc(UINT uID, UINT uMsg, DWORD dwUser, DWORD dw1, DWORD dw2){
 CMyDlg *pDlg = (CMyDlg *)dwUser;
 pDlg->......
 dwUser는 timeSetEvent의 this값을 인자로 받아 pDlg에 현재 인스턴스의 주소를 넣습니다.
 pDlg를 통해서 원래 클래스의 모든 메소드와 변수를 사용할 수 있습니다.
timeKillEvnet(m_nTimerID);
 setTimerEvent때 얻은 타이머의 번호를 집어넣어 타이머를 죽입니다.

주의점

  • CALLBACK 함수를 사용할때의 주의점. (in MSDN)
  • Applications should not call any system-defined functions from inside a callback function, except for PostMessage, timeGetSystemTime, timeGetTime, timeSetEvent, timeKillEvent, midiOutShortMsg, midiOutLongMsg, and OutputDebugString.
  • 어플리케이션은 콜백 함수 내부로부터 다음 함수를 제외하고는 시스템 정의 함수를 부를 수가 없다. : PostMessage, timeGetSystemTime, timeGetTime, timeSetEvent, timeKillEvent, midiOutShortMsg, midiOutLongMsg, and OutputDebugString.
왠만한 함수들은 Callback함수 내에서 부르면 안됩니다.
  • KB문서 Q130866번을 참고했습니다.
CALLBACK함수 내부에서 화면을 갱신할 때에는 Invalidte()함수나 user 메세지를 만들어서 날려주면 됩니다.
void CALLBACK EXPORT CTmrprocView::TimerProc(HWND hwnd, UINT msg, UINT idTimer, DWORD dwTime)
{
    CTmrprocView * pThis;
    
    if (m_thisList.Lookup(idTimer, (LPVOID &) pThis))
    {
        ASSERT(pThis->GetSafeHwnd());
        
        CDC* pDC = pThis->GetDC();
        
        wsprintf((LPSTR) pThis->m_strOutput, "CTmrprocView::TimerProc() Called. Count = %ld", ++pThis->m_cCount);
        pThis->Invalidate(TRUE);
    }
}

MFCStudy_2001