나도 프로그래머 라자러스 이벤트란?

2021. 6. 5. 22:42 컴퓨터/프로그래밍

윈도우 프로그램의 이벤트 이해

오픈 소스 통합 개발 환경 라자루스의 3 번째 글입니다. 이번에는 라자루스 프로그램의 중요한 개념 중에 하나인 이벤트에 대해서 알아 보겠습니다. 이벤트는 매우 중요하지만, 내용은 쉽습니다. 이벤트 뜻 그대로 사건입니다. 이전 글의 예제를 이해하셨다면 이미 이벤트에 대해 알고 계십니다. 다만, 이벤트 단어를 사용하지 않았을 뿐입니다.

▲ 이전 글에서 만든 예제입니다. 1초마다 타이머가 발생하면 현재 시간을 Label3에 입력하도록 했습니다. 또한, Button1을 마우스로 클릭하면 프로그램이 종료됩니다. 여기서 1초마다 발생하는 타이머와 마우스 버튼을 눌러서 발생하는 클릭을 이벤트라고 합니다.

폼 위에 올려 놓은 Label, Edit, Button, Timer를 컴포넌트라고 하는데요, 컴포넌트는 공통의 속성과 이벤트를 가지고 있으면서 고유의 기능에 따라 독자작인 속성과 이벤트를 갖습니다. Button에는 OnClick 이벤트가 있다면 Timer에는 OnTimer 이벤트가 있습니다.

이벤트와 이벤트 핸들러

여기서 생소한 단어 하나를 더 알고 가겠습니다. 버튼을 마우스로 클릭하는 것과 타이머에서 시간에 따라 주기적으로 발생하는 타이머를 이벤트라고 한다면, 그 이벤트가 발생했을 때 어떻게 처리하라는 코드를 이벤트 핸들러라고 합니다.

procedure TForm1.Timer1Timer(Sender: TObject);
begin

end;

▲ 타이머 컴포넌트를 더블 클릭하면 라자루스는 위와 같은 코드를 자동으로 만들어 줍니다. 생성된 코드는 타이머 이벤트가 발생했을 때 호출할 수 있도록 함수 형태입니다. 그리고 이렇게 이벤트가 발생하는 것을 대비하여 만들어진 함수를 이벤트 핸들러라고 합니다.

procedure TForm1.Timer1Timer(Sender: TObject);
begin
  Label3.Caption := FormatDateTime( 'hh:nn:ss', Now);
end;

▲ 이 이벤트 핸들러에 이벤트 처리 코드를 넣어서 완성합니다.

프로그래머처럼 말하기

자, 그러면 "타이머가 발생할 때 처리하기 위해 만들어진 함수"라고 말하는 대신에 "타이머 이벤트 핸들러"라고 간략히 말할 수 있겠죠? 또는 "타이머 핸들러"라고 더욱 짧게 말할 수 있습니다.

그래서 위 코드는 타이머 핸들러에 현재 시간을 Label3에 대입하도록 코딩했다 라고 해석할 수 있습니다.

그런데 타이머 핸들러에 표시된 Sender:TObject는 무슨 뜻일까요? Sender는 TObject의 한 종류라는 뜻인데요, 결론부터 말씀드리면 타이머 이벤트가 발생한 Timer1을 가르킵니다. Timer1에서 타이머 이벤트가 발생해서 타이머 이벤트 핸들러가 호출되었는데 굳이 Timer1이라는 것을 알려주는 이유가 무엇일까요?

폼에 타이머 컴포넌트를를 여러 개 놓아도 한 개의 이벤트 핸들러로 모두 처리하고 싶을 때 사용합니다. 즉, Timer1이면 현재 시간을 대압하고, Timer2이면 그림을 깜빡이고, Timer3이면 10초 후에 프로그램을 종료하도록 할 수 있습니다.

procedure TForm1.Timer1Timer(Sender: TObject);
begin
  if TTimer( Sender).Name = 'Timer1'
  then begin
    Label3.Caption := FormatDateTime( 'hh:nn:ss', Now);
  end
  else if TTimer( Sender).Name = 'Timer2'
  then begin
    FlickeringImage;
  end
  else if TTimer( Sender).Name = 'Timer3'
  then begin
    if is10sec
    then begin
      Close;
    end;
  end;
end;

▲ 이렇게 처리할 수 있도록 타이머 이벤트를 어느 타이머가 발생했는지를 알려 주는 것입니다.

폼(TForm)의 이벤트 종류

property OnActivate;
property OnChangeBounds;
property OnClick;
property OnClose;
property OnCloseQuery;
property OnConstrainedResize;
property OnContextPopup;
property OnCreate;
property OnDblClick;
property OnDeactivate;
property OnDestroy;
property OnDockDrop;
property OnDockOver;
property OnDragDrop;
property OnDragOver;
property OnDropFiles;
property OnEndDock;
property OnGetSiteInfo;
property OnHelp;
property OnHide;
property OnKeyDown;
property OnKeyPress;
property OnKeyUp;
property OnMouseDown;
property OnMouseEnter;
property OnMouseLeave;
property OnMouseMove;
property OnMouseUp;
property OnMouseWheel;
property OnMouseWheelDown;
property OnMouseWheelUp;
property OnMouseWheelHorz;
property OnMouseWheelLeft;
property OnMouseWheelRight;
property OnPaint;
property OnResize;
property OnShortCut;
property OnShow;
property OnShowHint;
property OnStartDock;
property OnUnDock;
property OnUTF8KeyPress;
property OnWindowStateChange;

폼에도 여러가지 이벤트가 있습니다. 이중에 OnCreate 이벤트는 폼이 윈도우로 생성될 때 발생합니다. 그래서 폼이 윈도우로 생성되어 화면에 출력되기 전에 윈도우를 초기화 작업하는데 유용합니다. 예를 들어 폼의 Caption 문자열을 바꿀 수 있습니다.

procedure TForm1.FormCreate(Sender: TObject);
begin
  Caption := 'badayak.com';
end;

▲ 폼의 생성 이벤트 핸들러에 Caption 문장을 바꾸는 코드를 넣어 주었습니다.

▲ 프로그램을 실행하면 캡션 내용이 바뀐 것을 볼 수 있습니다.

OnClose는 윈도우를 닫을 때 발생합니다. 테이터를 저장하지 않았다면 이 때 처리할 수 있습니다. OnCloseQuery는 OnClose 이벤트가 발생하기 전에 정말 윈도우를 닫을 지 미리 확인하는 이벤트입니다. 아직 처리할 내용이 있는데 윈도우를 닫을 때 취소 여부를 사용자에게 확인할 수 있습니다.

OnDestory는 윈도우가 메모리에서 제거 될 때 발생합니다. OnCreate와 반대되는 이벤트입니다.

메모리 관리의 중요성

혹시 OnClose가 있는데 OnDestory는 왜 있을까 궁굼하자 않으세요?

폼은 디자인할 때의 모습이고 프로그램이 실행되면 폼을 디자인한 모습 그대로 윈도우로 생성(OnCreate)되어 화면에 출력(OnShow)됩니다. 폼을 바탕으로 윈도우가 생성되었다는 것은 컴퓨터가 처리하기 위해 메모리에 올려졌다는 뜻이며 , 다쓴 윈도우는 메모리에서 제거해야 메모리를 다른 윈도우나 프로그램이 사용할 수 있습니다.

프로그래밍에서 메모리 관리는 매우 중요합니다. 메모리는 유한한 자원이므로 잘못 관리하면 프로그램이 이상해질 뿐만 아니라 윈도우 시스템 전반적으로 악영향을 끼칠 수 있습니다. 기본 규칙은 필요 없는 요소는 메모리에서 제거하는 것 입니다.

메인 폼은 실행될 때 화면에 보여지다가 닫으면 프로그램이 종료돼서 다른 폼의 윈도우도 닫으면 메모리에서 사라질 것 같지만, 실은 그렇지 않습니다. 메인 윈도우는 프로그램의 몸통이라서 닫히면 자동으로 소멸하도록 처리되지만, 다른 폼의 윈도우는 Close로 닫아도 화면에만 보이지 않을 뿐 메모리에 남아 있습니다. 윈도우를 직접 메모리에서 제거(Free) 해야 OnDestory 이벤트가 발생한 후 메모리에서도 사라집니다.

▲ 라자러스 디버그서버 툴로 메시지를 캡처한 화면입니다. 시간의 역순으로 표시됨음 참고하여 주십시오.

아이, 뭐가 이렇게 복잡해? 그냥 화면에 보여 주었다가 닫으면 없어졌다가 또 필요해지면 그 때 다시 만들면 되지 이렇게 생각할 수 있는데요, 맞는 말씀이고 또 그렇게 많이 코딩합니다. 다만, 생성할 때 많은 작업이 필요한 윈도우는 화면에서 닫았다가 필요해지면 다시 여는 것이 좋습니다. 새로 만드는 것보다 빠르게 실행되니까요.

▲ 메인 폼에 Button 컴포넌트를 이용해서 Button2를 폼에 배치합니다. 그리고 Button2의 Caption을 "복사"라고 입력하고 Button2를 더블 클릭한 후 OnButton 이벤트 핸들러에 아래와 같이 입력합니다.

▲ 복사 버튼인 Button2를 클릭하면 메인폼인 TForm1을 생성(Create)해서 화면에 출력(Show)합니다.

▲ 프로그램을 실행하면 똑 같은 메인 윈도우가 복사됩니다. 같은 위치에 복사 되어서 생성된지도 모를 수 있습니다. 복사 버튼을 클릭한 후에 윈도우를 옆으로 이동 시키면 똑 같이 복사된 윈도우라는 것을 알 수 있습니다. 복사된 윈도우는 메인 윈도우와 똑 같이 생기고 기능도 똑 같지만, "종료" 버튼을 누른다고 해서 프로그램이 종료되지 않습니다. 첫 번째로 실행된 메인 윈도우를 종료해야 프로그램이 종료됩니다.

어떻습니까? 아직은 라자루스가 익숙하지 않아서 이해하기 힘든 부분이 있지만, 재미있지요?

이 댓글을 비밀 댓글로

티스토리 로그인이 풀리면 여기를 클릭하세요.

error: Content is protected !!