델파이 타이머
델파이에서 컴포넌트로 제공되는
TTimer의 경우에는 정확한 시간에 맞게 콜백을 하지 않는다.
Interval 을 1/1000 초까지 조정할 수 있지만
실제로 호출되는 것은 1/18.2 초 단위로 끊어 지게 되기때문이다.
만약 TTimer로 MP3 플레이어나 동영상 재생기를 만든다면 어떻게 될까 ?
MP3 음향이 정확한 박자로 재생하지 못할 것이고 동영상도
프레임이 정확하지 못해서 눈이 상당히 피로해질 거다.
하지만 지금 소개하는 타이머를 쓰게 되면
1ms 의 오차정도만을 허용하는 고급의 타이머가 생성되게 됩니다.
어려운 내용이 아니기 때문에 그냥 소스에
주석을 붙이는 차원으로 끝내겠습니다.
그리고 dfm 의 내용도 Text 로 뒤에 첨가하였으니
직접 폼을 만들어서 테스트 해보면 된다 폼에서
마우스 오른쪽 버튼을 누른후 제일 아래의 View As Text 를 선택하고
그 내용을 아래의 dfm 의 Text로 바꾸면 된다
타이머 소스
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls,
Forms, Dialogs, ExtCtrls, StdCtrls, mmSystem;
const
USR_TIMER_ELAPSED = WM_USER+100;
type
TForm1 = class(TForm)
Edit1 : TEdit; // 타이머 콜백된 회수 출력
Edit2 : TEdit; // 초당 콜백 회수
Button1 : TButton; // 타이머 종료 버튼
StaticText1 : TStaticText; // 라벨 1
StaticText2 : TStaticText; // 라벨 2
Panel1 : TPanel; // 현재 설정된 콜백 주기 출력
procedure FormShow(Sender: TObject);
procedure FormDestroy(Sender: TObject);
procedure Button1Click(Sender: TObject);
private
FTimerID: UINT;
Fms : UINT;
FCouter : integer; FTime : longint;
procedure EditCallback(var M : TMessage); message USR_TIMER_ELAPSED;
// 사용자 메시지를 받기 위한 메시지 처리 루틴
end;
var
Form1 : TForm1;
implementation
{$R *.DFM}
procedure TForm1.EditCallback(var M : TMessage);
var
f : real;
s : string;
begin
inc(Form1.FCouter);
str(Form1.FCouter,s);
Form1.Edit1.Text := s;
f := (Form1.FCouter * 1000) / (GetCurrentTime - Form1.FTime);
str(f : 6 : 3,s);
Form1.Edit2.Text := s; // 초당 콜백 회수 출력
if Form1.FCouter = 0 then
begin
Form1.FTime := GetCurrentTime; // 콜백 카운트의 초기화 end;
end;
procedure TimerProc(uTimer, uMessage : UNIT; dwUser, dw1, dw2 : DWORD); stdcall;
begin
PostMessage(dwUser,USR_TIMER_ELAPSED,0,0); // 멀티미디어 타이머 콜백 함수에는 대부분의 API가 사용 불가하다.
// 그러므로 다시 메시지를 사용자 메시지 루틴으로 돌려야 한다.
end;
procedure TForm1.FormShow(Sender: TObject);
var
s : string;
TimeCaps : TTimeCaps;
begin
Fms := 100; // 타이머 주기를 100ms 마다 한 번씩 호출되게 한다.
if timeGetDevCaps(@TimeCaps,sizeof(TimeCaps)) <> TIMERR_NOERROR then
raise Exception.Create(' Error !!'); // 타이머 디바이스에 대한 정보를 얻어 온다.
if Fms < TimeCaps.wPeriodMin then
Fms := TimeCaps.wPeriodMin; // 실제 가능한 호출 주기보다 작으면
if Fms > TimeCaps.wPeriodMax then
Fms := TimeCaps.wPeriodMax; // 실제 가능한 호출 주기보다 크면
timeBeginPeriod(Fms); // 타이머 주기를 지정한다.
FTimerID := timeSetEvent(Fms,Fms,@TimerProc,integer(handle), TIME_PERIODIC);
// 타이머를 설정한다. 콜백 함수를 지정하고, TIME_PERIODIC를 사용하여
// 주기적으로 계속 호출되게 만든다.
if FTimerID = 0 then
begin
timeEndPeriod(Fms);
raise Exception.Create(' Error !!');
Close;
Exit; // 에러 처리 루틴
end;
str(Fms,s);
Panel1.Caption := '타이머 설정 :' + s + 'ms'; FCouter := -1;
end;
procedure TForm1.FormDestroy(Sender: TObject);
begin
if FTimerID <> 0 then
begin
timeKillEvent(FTimerID); // 타이머를 해제한다.
timeEndPeriod(Fms); // 타이머 주기를 해제한다.
end;
end;
procedure TForm1.Button1Click(Sender: TObject);
begin
Close;
end;
end.
화면 소스
object Form1: TForm1
Left = 276
Top = 145
Width = 124
Height = 214
Caption = 'Form1'
Font.Charset = DEFAULT_CHARSET
Font.Color = clWindowText
Font.Height = -11
Font.Name = 'MS Sans Serif'
Font.Style = [] OnDestroy = FormDestroy OnShow = FormShow PixelsPerInch = 96 TextHeight = 13
object
Edit1: TEdit
Left = 0
Top = 56
Width = 113
Height = 21
ImeName = '한국어(한글)'
TabOrder = 0
end
object Edit2: TEdit
Left = 0
Top = 104
Width = 113
Height = 21
ImeName = '한국어(한글)'
TabOrder = 1
end
object Button1: TButton
Left = 24
Top = 144
Width = 75
Height = 25
Caption = 'Stop !!'
TabOrder = 2
OnClick = Button1Click end
object StaticText1: TStaticText
Left = 0
Top = 40
Width = 116
Height = 17
Alignment = taCenter
Caption = '타이머 콜백 호출'
Font.Charset = HANGEUL_CHARSET
Font.Color = clWindowText
Font.Height = -13
Font.Name = '돋움체'
Font.Style = []
ParentFont = False
TabOrder = 3
end
object StaticText2: TStaticText
Left = 8
Top = 88
Width = 102
Height = 17
Caption = '초당 콜백 회수'
Font.Charset = HANGEUL_CHARSET
Font.Color = clWindowText
Font.Height = -13
Font.Name = '돋움체'
Font.Style = []
ParentFont = False
TabOrder = 4
end
object Panel1: TPanel
Left = 0
Top = 0
Width = 116
Height = 25
Align = alTop
BevelInner = bvLowered
Font.Charset = HANGEUL_CHARSET
Font.Color = clWindowText
Font.Height = -11
Font.Name = '돋움체'
Font.Style = []
ParentFont = False
TabOrder = 5
end
end
위의 소스를 실행해 보면 항상 0.005 초 정도의
오차만을 가지고 초당 10 회라는 콜백 회수를 계속 유지한다.
( 10.000 초를 기준으로 진동한다고 보는 게 나을 것 같죠 ? )
'Delphi Tip > 컴포넌트' 카테고리의 다른 글
동적으로 메뉴(TMenuItem) 만들고 클릭 이벤트 만들기 (0) | 2023.10.31 |
---|---|
델파이 콤보박스(TComboBox)의 팝업리스트 가로폭 늘리기 (0) | 2023.10.26 |
델파이 컨트롤 반투명 드래그 이동 (0) | 2023.09.12 |
델파이 컴포넌트(Component) 마무리 (0) | 2023.07.25 |
델파이 컴포넌트(Component) 7편 (0) | 2023.07.24 |
댓글