LazarusCompleteGuide:6.4

From 흡혈양파의 번역工房
Revision as of 01:44, 10 March 2013 by Onionmixer (talk | contribs) (LCG 6.4 이미지 수정)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to navigation Jump to search

컴포넌트 팔레트 소개

컴포넌트 팔레트는 라자루스 IDE의 메인 창인 메뉴 바 바로 아래, 속도버튼의 우측에 위치한다. IDE로 컴파일된 모든 컴포넌트는 팔레트 어딘가에 아이콘으로 표시된다. 정확히 어떤 컴포넌트가 표시되는지는 라자루스 설치 및 운영체제에 따라 다르다.


'make clean all' 명령을 이용해 라자루스가 재컴파일되었다면 컴포넌트 팔레트는 LCL 자체에서 정의된 컴포넌트만 포함할 것이다. LCL 의 컴포넌트를 제외한 컴포넌트는 어떤 것도 설치되지 않을 것이다. 라자루스 일부 버전들은 약간 다른 LCL 컴포넌트 집합을 포함하는데, 일부 컴포넌트들이 모든 플랫폼에서 작동하지는 않기 때문이다. 예를 들어, SQLDB 패키지에는 64 비트 윈도우에선 기능하지 않는 컴포넌트가 몇 개 포함되어 있다.


수많은 컴포넌트들을 쉽게 관리하려면 컴포넌트 팔레트를 여러 탭으로 나눈다. 본장의 나머지 부분에 걸쳐 이러한 탭을 하나씩 차례로 살펴보고자 한다. 추가 컴포넌트가 있는 패키지를 설치하였다면 기존 탭들 중 하나에 표시되거나 패키지의 컴포넌트가 표시되는 새 추가 탭에서 볼 수 있을 것이다.


탭의 위치는 변경될 수 있다. 기본 탭은 (LCL에서 정의한 바와 같이-표준에서 SynEdit까지) 위치가 고정된다. 추가 탭들은 (새 패키지가 설치된 것으로 나타나는) 패키지가 설치된 순서에 따라 다양한 방식으로 정렬될 수 있다. 최근에는 컴포넌트 팔레트에 탭의 순서를 변경하는 것이 불가능하다.


컴포넌트 팔레트의 사용은 꽤 쉽다: 필요한 컴포넌트를 클릭한 후 그 컴포넌트를 위치시키고자 하는 폼을 다시 클릭한다. 컴포넌트는 항상 마우스 클릭이 발생하는 위치에 놓인다. 컴포넌트의 여러 인스턴스를 폼으로 드롭하고 싶다면 컴포넌트 팔레트에서 컴포넌트의 아이콘을 클릭할 때 [Shift] 키를 누른다.


이후에 폼을 클릭할 때마다 폼에 컴포넌트가 복사본이 생성된다.


이 방법이 아니라면, 컴포넌트의 아이콘을 클릭하여 정상적으로 선택한 후 Shift 키를 누른 채 폼을 클릭하는 방법이 있다. [Shift]키를 누르고 있는 한 마우스를 연속 클릭 시 더 많은 컴포넌트 복사본이 폼으로 드롭된다.


비시각적 컴포넌트들의 경우, 폼의 어디에 위치시키는지는 무관하며, 컴포넌트를 나타내는 이미지는 디자이너에서만 볼 수 있다 (런타임이 아닌).


따라서 비시각적 컴포넌트는 폼의 설계를 방해하지 않는 곳에 위치시키는 것이 최선이다.


컴포넌트 팔레트에서 컴포넌트를 선택하자마자 그 아이콘이 눌러진 채로 나타날 것이다. '선택된' 상태는 폼에 컴포넌트가 드롭되는 순간 정상으로 복구될 것이다. 반대로, 컴포넌트를 선택할 때 Shift 버튼을 누르고 있었다면 그 상태는 화살표 아이콘을 (컴포넌트 팔레트의 각 탭에서 항상 가장 좌측에 위치한 부호) 클릭할 때만 정상으로 복구된다 (예: unselected).


라자루스 컴포넌트 팔레트는 델파이 컴포넌트와 가능한 한 비슷하게 행동하도록 설계되었다. 많은 라자루스 개발자들은 델파이를 이용한 작업 또한 계속하기 때문에 델파이의 팔레트 위치와 비슷하게 컴포넌트를 위치시켜 두 가지 환경에서 모두 손쉽게 작업할 수 있을 것이다.


단, 일부 컴포넌트들은 델파이와 호환을 시도 시에만 라자루스에 표시되기 때문에 컴포넌트와 탭의 명명에 일관성 문제가 발생하기도 한다. 그렇긴 해도 모든 델파이 표준 컴포넌트가 라자루스에 중복되는 것은 아니다. 하지만 (상업 라이센스 제약 결과와 Windows API에 대한 델파이 컴넌너트 의존성의 결과로 인한 몇 가지 예외가 가능) 누락된 컴포넌트를 라자루스로 복사하는 것은 가능하다. 컴포넌트 아이콘을 오른쪽 마우스로 클릭하면 그림 6.32와 같은 컨텍스트 메뉴가 표시된다.

그림 6.32: 컴포넌트 팔레트의 컨텍스트 메뉴


첫 번째 팝업 메뉴 엔트리는 패키지 관리자에서 컴포넌트 팔레트에 컴포넌트를 등록시킨 패키지를 연다. 특정 컴포넌트가 선언된 유닛에만 관련이 있다면 두 번째 메뉴를 선택한다. 세 번째 메뉴 옵션을 선택하면 검색 대화창이 열려 (그림 6.33 참고) 컴포넌트의 이름을 입력하여 검색할 수 있도록 해준다. View ⇒ Component 의 메인 메뉴에서도 비슷한 대화창을 찾을 수 있다.

그림 6.33: 컴포넌트 검색 대화창


라자루스는 현재 수 백 개의 컴포넌트를 미리 설치하여 함께 제공한다. 그 중 절반 이상은 TControl 에서 파생된 시각적 컴포넌트에 속한다. 이러한 컨트롤들은 당신의 애플리케이션에 사용자 인터페이스를 형성하며, 사용자와 애플리케이션이 상호작용 방식을 책임진다. 사용자가 소프트웨어와 상호작용하는 방식을 설계하면서 사용자가 툴바 버튼 또는 메뉴 중에 무엇을 이용해 액션을 시작하도록 할 것인지 결정해야 한다.


수년간 훌륭한 사용자 인터페이스 설계를 위한 표준이 개발되어 왔다. 이러한 지침서를 따른다면 프로그램 사용자들이 매우 편안함을 느낄 수 있을 것이다. 따라서 당신은 이용할 수 있는 수많은 컨트롤을 올바로 사용하는 방법을 먼저 알아야 한다. 첫 번째 단계는 자신이 이용할 수 있는 컨트롤과 친해지는 것이다. 수많은 컨트롤을 세 가지 버전(flavour)으로 이용할 수 있다는 점이 처음에는 이상할지 모른다. 우선 일반 컨트롤, 동일한 컨트롤의 데이터 인식 버전, 동일한 컨트롤에 RTTI (런타임 타입 정보) 성능이 있는 버전을 들 수 있겠다.


본장에서는 일반 컨트롤을 논하고자 한다. 나머지 두 가지 버전들은 일반 컨트롤과 정확히 동일하게 기능하지만 데이터베이스로부터(또는 데이터베이스로) 정보나 일부 객체의 published 프로퍼티를 인출(또는 저장)할 수 있는 추가 기능을 가진다. 컴포넌트의 개념에 생소하여 다양한 컨트롤의 성능에 대해 아는 바가 별로 없다면 라자루스에 함께 설치되어 오는 50개 이상의 예제 애플리케이션을 참고하면 이용 가능한 컨트롤의 사용 방식을 대부분 설명해줄 것이다. 예제 프로그램은 라자루스 IDE와 함께 컴파일할 수 있다. 라자루스 팀이 제공하는 makefiles을 이용해 예제를 컴파일할 수도 있다. 예제의 코드를 검사하는 가장 쉬운 방법은 IDE에 예제 프로젝트를 로딩하여 에디터에서 소스 코드를 연구하는 방법이다.


모든 시각적 컨트롤은 TControl 에서 파생된다. 즉, 컨트롤들이 Position, Size, 또는 Anchors 프로퍼티를 포함한 많은 기본 프로퍼티와 OnResize 이벤트를 공유함을 의미한다. 이러한 공통 프로퍼티를 비롯한 시각적 컨트롤들은 표 6.40에 열거된 행위를 제어하는 다수의 프로퍼티들도 가진다.

프로퍼티 설명
Color 컨트롤의 배경 색상.
Cursor 마우스가 컨트롤 위에 있을 때 마우스 커서의 모양.
Enabled False로 설정 시, 컨트롤은 어떠한 이벤트도 받지 않고, 포커스도 받지 않을 것이다. 컨트롤 유형에 따라 보통 다른 색상으로 표시되어, 컨트롤을 이용할 수 없음을 나타낸다 ('회색').
Font 모든 텍스트를 표시하는 데에 사용되는 폰트 (그 컨트롤에 적용 가능 시).
Hint 마우스를 컨트롤 위에서 움직일 때 작은 팝업창에 표시할 수 있는 힌트. 툴팁으로도 알려져 있다.
ShowHint True로 설정 시, 마우스가 컨트롤 위에 있으면 힌트가 뜬다.
False로 설정 시, 어떠한 힌트도 표시되지 않을 것이다.
ParentColor True로 설정 시, 컨트롤의 Color 프로퍼티는 항상 그 부모 컨트롤의 Color 프로퍼티와 동일하다.
ParentFont True로 설정 시, 컨트롤의 Font 프로퍼티는 항상 그 부모 컨트롤의 Font 프로퍼티와 동일하다 (ParentColor와 비슷함). 폰트를 재빠르게 리셋할 때 해당 프로퍼티를 사용하면 된다.
ParentShowHint True로 설정 시 (기본 값), ShowHint 값은 항상 그 부모 컨트롤의 ShowHint 프로퍼티와 동일하다. 즉, 폼의 ShowHint 프로퍼티를 True로 설정하면 폼의 모든 컨트롤에 대한 힌트를 활성화시킴을 의미한다.
표 6.40: 시각적 컨트롤들이 공통으로 가진 프로퍼티


시각적 컨트롤은 표 6.41에 열거된 이벤트들도 공유한다. 이러한 이벤트들은 마우스 움직임과 마우스 이벤트에 응답하는 데에 사용할 수 있다. OnMouseDown 과 OnMouseUp 이벤트는 OnClick 과 OnDblClick 이벤트보다 더 정교한 이벤트이다. 컨트롤은 OnMouseDown 이벤트를 수신할 수는 있지만 OnMouseUp 이벤트를 수신할 수는 없으며, 어떠한 OnClick 이벤트도 생성되지 않을 것이다. 이러한 일은 사용자가 어떤 컨트롤 위에서 마우스 버튼을 누르고 마우스를 다른 컨트롤로 이동한 후에 눌렀던 버튼을 해제 시 발생한다-일반적인 '드래그 앤 드롭' 동작.

이벤트 설명
OnClick 사용자가 왼쪽 마우스 버튼으로 컨트롤을 클릭 시 트리거된다.
OnDblClick 사용자가 왼쪽 마우스 버튼으로 컨트롤을 더블 클릭 시 트리거된다.
OnMouseEnter 마우스가 컨트롤 밖에서 컨트롤 경계를 지나 컨트롤 위에서 이동을 시작할 때 트리거된다.
OnMouseLeave 마우스가 컨트롤 내부로부터 컨트롤 경계를 지나 밖으로 이동시킬 때 트리거된다.
OnMouseMove 마우스를 컨트롤 위에서 움직일 때 트리거된다.
OnMouseDown 마우스가 컨트롤 위에 있을 때 마우스 버튼을 누르면 트리거된다.
OnMouseUp 마우스가 컨트롤 위에 있을 때 눌렀던 마우스 버튼을 해제하면 트리거된다.
표 6.41: 시각적 컨트롤이 공통으로 가진 이벤트


아래 절에서는 라자루스가 제공하는 다양한 기본 컨트롤들을 소개하고자 한다. 컨트롤마다 그에 특정적인 프로퍼티 두 개를 설명하고, 어떻게 사용하도록 만들어졌는지 설명할 것이다. 컴포넌트는 탭 시퀀스(tab sequence)에 포함되며 (표시되는 탭에 따라), 각 탭에서 가장 중요한 컴포넌트들을 먼저 논할 것이다.


표준 탭

컴포넌트 팔레트에서 Standard(표준) 탭은 (그림 6.34) 항상 IDE에 설치되는 LCL의 가장 단순한 컨트롤들을 포함한다. 표 6.42는 이 탭에 있는 컨트롤들을 열거한다.

그림 6.34: 컴포넌트 팔레트의 표준 탭


컴포넌트 설명
TMainMenu 폼의 메인 메뉴를 포함하는 컴포넌트 – 메인 폼 상단에 메뉴 바.
TPopupMenu 애플리케이션 내 팝업 (컨텍스트 민감) 메뉴를 포함하는 컴포넌트. 각 컨트롤은 고유의 팝업 메뉴를 가질 수 있다.
TButton 텍스트 Caption이 있는 단순한 클릭 가능 버튼. 사용자는 액션을 실행하기 위해 마우스로 버튼 위를 클릭한다.
TLabel 해당 컨트롤은 단순히 텍스트를 (컨트롤의 Caption) 표시한다. 텍스트는 단일 행 또는 다중 행일 수 있다. Caption에 문자 중 하나는 핫키(hotkey) 기능을 할 수 있으며, 핫키를 누르면 지정된 TWinControl (FocusControl 프로퍼티에 명시)에 포커스가 설정될 것이다. 핫키 역할을 하는 문자키는 앰퍼샌드(&)가 앞에 붙어야 하며, 밑줄이 표시될 것이다.
TEdit 사용자가 텍스트 단일 행을 입력하도록 허용한다. 텍스트는 길이가 제한되며, 비밀번호 문자로 표시할 수 있다 (텍스트가 화면에 표시되지 않고, 비밀번호 문자가 표시).
TMemo 사용자가 텍스트 행을 하나 이상 입력하도록 허용한다. 메모는 필요 시 자동으로 스크롤바를 표시할 것이다. 텍스트는 동일한 폰트로 표시되며 포매팅에는 어떠한 향상(enhancement)도 불가능하다.
TToggleBox TButton과 비슷하지만, 클릭 시 사용자가 다시 클릭할 때까지 눌러진 채로 유지된다.
TCheckBox 체크표시가 있는 상자와 함께 짧은 라벨이 (Caption) 표시된다. 상자를 클릭하여 사용자는 체크표시의 켜기와 끄기를 토글할 수 있다. 여러 개의 체크상자를 나란히 위치시킬 수 있다. 각 체크상자를 따로 체크 및 해제할 수 있다. 주로 사용자가 프로그램 옵션을 설정할 때 (또는 설정 해제할 때) 사용된다.
TRadioButton TCheckBox 와 비슷하지만 여러 라디오버튼이 하나의 컨트롤에 표시될 경우 한 번에 하나의 라디오버튼만 선택된다는 점에서 다르다. 하나의 라디오버튼을 체크하면 나머지 모든 버튼들은 체크가 해제된다. 사용자가 여러 배타적 (exclusive) 옵션들 중 하나만 선택하도록 할 때 유용하다.
TListBox 다수의 문자열을 표시하며, 사용자가 하나 또는 그 이상의 문자열을 선택하도록 허용한다. 문자열은 다양한 스타일로 그릴 수 있다 (리스트상자의 Style에 따라).
TComboBox TEdit 와 같이 콤보상자는 사용자가 텍스트를 입력하도록 허용하지만 선택할 수 있는 리스트를 제공한다. 가능한 엔트리를 사전에 정의된 항목 중 하나로 제한하거나, 리스트에 없는 텍스트를 사용자가 입력하도록 허용할 수 있다. 항목 리스트는 사용자가 ‘드롭다운’ 버튼을 클릭하면 표시되지만 영구적으로 표시되는 리스트로 만들 수도 있다.
TSCrollBar 바(bar)로서, 바를 따라 드래그가 가능한 작은 손잡이가 있다 ('thumb').
변경된 thumb 위치를 이용해 다른 컨트롤들을 위치시키는 데 사용된다.
TGroupBox 컨트롤 집합을 그룹화하기 위해 사용되는 그룹상자.
컨트롤 주변에 베벨(bevel)을 그리고 Caption을 베벨에 놓는다.
전적으로 겉모양과 관련된 컨트롤이다.
TRadioGroup 라디오그룹은 사실 그룹상자와 라디오버튼 집합을 조합한 것이다. Items 프로퍼티의 각 행에 대해 해당하는 라디오버튼이 그룹에 표시된다. ItemIndex 프로퍼티는 어떤 라디오버튼을 체크할지 결정한다.
TCheckGroup 라디오그룹과 유사하며, 체크그룹은 일련을 체크상자를 표시한다. Checked 배열은 어떤 항목을 체크할지 결정한다.
TPanel 라벨과 유사하지만 둘러싸는 테두리(enclosing border)를 포함하며, 다른 컨트롤들을 포함할 수도 있다. 패널은 다른 컨트롤들을 그룹화하기 위한 상자(container)로 종종 사용되며, 강제로(force) 특정 레이아웃 설계 시 매우 유용하다. 때로는 그림을 그릴 캔버스를 제공하기 때문에 그려진 다른 컨트롤들의 조상으로 사용되기도 한다.
TFrame 다른 컨트롤들을 위한 상자로, 폼에 가깝지만 폼에 드롭되어야 한다.
TActionList 다른 컨트롤로 결합(coupled)될 수 있는 액션 리스트.
표 6.42: 표준 탭에 발견되는 컨트롤


메인 및 팝업 메뉴

모든 애플리케이션이 그런 건 아니지만 대부분은 메인 창 상단에 메뉴 바를 가진다. 메뉴 바는 애플리케이션이 제공하는 액션을 선택 및 실행하는 데에 사용된다. 거의 모든 애플리케이션 메뉴에 나타나는 메뉴 두 가지는 파일과 관련된 액션이 있는 File, 그리고 Cut, Copy, Paste, Undo 와 같은 액션이 포함된 Edit가 된다.


애플리케이션의 다양한 위치에서 로컬 메뉴를 사용하기도 한다ㅡ오른쪽 마우스 버튼을 클릭하면 마우스 위치에 메뉴가 뜨는데, 여기서 메뉴 액션을 선택할 수 있다. 많은 편집 컨트롤들이 팝업 메뉴를 이용해 Select all, Cut, Copy, Pasge, Undo 액션을 제공한다.

Property Items: TMenuItem;


라자루스는 이러한 메뉴들을 두 개의 컴포넌트에 캡슐화한다: 톱 메뉴는 TMainMenu에, 로컬 메뉴엔 TPopMenu. 두 가지 모두 컴포넌트 팔레트의 Standard 탭에 표시된다. 두 컴포넌트는 아래와 같이 정의되는 Items 프로퍼티를 가진다:


TMenuItem 클래스는 메뉴에 단일 항목을 표시한다. TMenuItem 클래스는 하위메뉴의 구성을 허용하는 한 쌍의 프로퍼티를 가진다:

Property Count: Integer;
Property Items[Index: Integer]: TMenuItem;


Count 프로퍼티는 하위메뉴에 나타나는 항목 수를 의미하며, Items 프로퍼티는 이러한 항목 각각에 색인 접근을 제공한다.


Items 프로퍼티는 TMenuItem 타입이므로 트리 구조의 하위메뉴를 빌드하도록 해준다: 각 TMenuItem 인스턴스의 항목들은 하위메뉴 내 항목들을 나타낸다.


TMenuItem 클래스는 그 모양과 행위를 결정하는 다수의 프로퍼티를 가진다. 세 가지 주요 프로퍼티를 들자면 Caption, Shortcut, OnClick 이벤트가 있다. Caption 프로퍼티는 메뉴에 표시되는 텍스트를 포함한다. Caption은 단축키를 포함할 수 있다. 앰퍼샌드 문자(&)가 앞에 붙은 문자는 메뉴가 표시된 상태일 때 메뉴 항목에 대한 단축키 역할을 한다. 예를 들어, 최상위 수준 메뉴에 '&File' 이라는 캡션이 있다면 'F' 는 메뉴에 대한 단축키가 되어 Alt-F (또는 Alt-f)를 누르면 활성화될 것이다. 하위메뉴에서는 F 문자만 (또는 f) 눌러도 활성화될 것이다. 메뉴에는 'File'로 표시된다.


Caption 프로퍼티를 '-' (대시)로 설정할 경우 그 메뉴 항목은 메뉴에서 구분자(separator)로 표시될 것이다.


Shortcut 프로퍼티는 메뉴에 대한 단축키를 설정한다. 단축키는 메뉴 항목이 눈에 보이지 않는 경우에도 메뉴 항목의 액션을 실행 시 사용된다. 예를 들어, 'Ctrl-S'는 종종 Save 메뉴를 활성화 시 사용된다. 메뉴 디스플레이에서 단축키는 메뉴 항목의 Caption 끝에 오른쪽 정렬되어 표시된다.


OnClick 이벤트는 메뉴 항목을 클릭하거나 그 단축키를 이용하여 활성화될 때 트리거되고, 이벤트 핸들러의 Sender 파라미터는 메뉴 항목에 해당한다. 아래는 OnClick 핸들러의 예제이다:

procedure TMainForm.DoMenuClick(Sender: TObject);
begin
  With (Sender as TMenuItem) do
    ShowMessage('Menu item with caption "'+ Caption + '" was chosen');
end;


대부분 메뉴 항목들은 이 세 가지 프로퍼티만 사용한다. 하지만 메뉴 항목의 모양과 행위를 변경하는 데 사용할 수 있는 추가 프로퍼티들도 존재하며, 표 6.43에서 소개하고자 한다.

프로퍼티 설명
Checked 부울(Boolean) 프로퍼티를 True로 설정 시, 메뉴 항목 앞에 체크 부호가 표시된다. 기본적으로 Checked 프로퍼티는 False로 설정되어 있으며, 메뉴 항목을 클릭 시 코드에서 수동으로 설정해야 한다.
AutoCheck 해당 부울 프로퍼티를 설정 시, 메뉴 항목을 클릭하면 Checked 프로퍼티를 설정 또는 해제할 것이다: checked 프로퍼티를 OnClick 이벤트 핸들러에서 설정 또는 해제하지 않아도 된다. 물론 이벤트 핸들러는 여전히 checked 프로퍼티가 변경된 후에 호출된다.
RadioButton 해당 부울 프로퍼티를 설정 시, 동일한 그룹 내 나타나는 모든 메뉴 항목은 라디오버튼 집합의 역할을 할 것이다ㅡ하나의 항목을 체크하면 그룹 내 다른 항목들은 모두 체크 해제될 것이다.
표 6.43: 추가 메뉴 항목 프로퍼티


'Group' 메뉴항목은 (RadioButton property 의 영향을 받는) GroupIndex project 에 의해 결정된다: GroupIndex 는 0보다 큰 숫자여야 한다.


동일한 하위메뉴 내에 다수의 그룹이 존재할 수 있으며, 이러한 경우 동일한 GroupIndex 값을 가진 모든 메뉴 항목들은 동일한 그룹에 속한다.


마지막으로, ImageIndex 프로퍼티를 이용해 메뉴 항목 앞에 이미지를 표시할 수 있다. 값을 -1 이외의 값으로 설정 시, 이미지는 TImageList 컴포넌트 내 이미지로부터 취할 것이다 (컴포넌트 팔레트의 Common 탭에서 찾을 수 있다).


이미지를 표시하기 위해선 TMainMenu 또는 TPopupMenu 의 Image 프로퍼티를 사용할 이미지가 포함된 이미지리스트(imagelist)로 설정해야 한다.


이론상으로는 리스트 내 이미지들에 대해 어떤 크기든 가능하지만 실제로 최상의 결과는 16x16 픽셀일 때이다.


이러한 모든 프로퍼티는 라자루스 메뉴 에디터를 통해 관리할 수 있다. 메뉴 에디터는 TMainmenu 또는 TPopupMenu 인스턴스를 더블 클릭하여 호출하거나, 오브젝트 인스펙터의 Items 프로퍼티로부터 호출할 수도 있다.


그림 6.35에서 볼 수 있듯이 메뉴 에디터는 사용법이 쉽다: 메뉴의 구성은 프로그램에 표시되는 대로 이루어진다. 팝업 메뉴는 어떤 액션을 이용할 수 있는지를 보여주고, 팝업 메뉴를 이용해 최종 프로그램에 전체 메뉴가 어떻게 나타날 것인지를 설계할 수 있다 (그림 6.36 참고).

그림 6.35: 메뉴 에디터


메뉴 항목이 메뉴에 추가되고 나면 항목을 선택하고 그 프로퍼티를 오브젝트 인스펙터에서 설정할 수 있다. OnClick 이벤트 핸들러를 메뉴 에디터의 팝업 메뉴에서 직접 생성하는 빠른 방법도 있다. 폼에 여러 메뉴를 드롭하였다면 메뉴 에디터는 우측 리스트에 이용 가능한 메뉴를 모두 표시할 것이다. 이는 메뉴 에디터를 떠나지 않고 한 번에 모든 메뉴를 관리하도록 해준다.

그림 6.36: 메뉴 설계


메인 메뉴를 표시하려면 폼의 MainMenu 프로퍼티를 설정해야만 한다: 폼은 이 프로퍼티에 메뉴를 표시할 것이다. 첫 번째 TMainMenu 컴포넌트를 폼에 드롭하면 프로퍼티는 자동으로 이 인스턴스로 설정될 것이다. 직후에 메뉴는 폼의 상단에 나타나며, 마우스를 이용해 볼 수 있다-런타임처럼 행동할 것이다 (그림 6.37 참고).

그림 6.37: 새로 설계한 메뉴를 폼 디자이너에서 보기


컨트롤을 오른쪽 마우스로 클릭할 때 팝업 메뉴를 표시하려면 그 컨트롤의 PopupMenu 프로퍼티를 표시하고자 하는 TPopupMenu 인스턴스로 설정해야 한다. 그리고 나면 사용자가 오른쪽 마우스 버튼으로 클릭한 지점에 팝업 메뉴가 표시될 것이다.


팝업 메뉴는 Popup 메소드를 이용해 프로그램에 따라 표시될 수도 있다. 메뉴를 표시할 좌표가 필요하다 (좌표는 폼의 상대적 좌표가 아니라 화면 좌표이다). 마우스를 클릭하는 순간 마우스 위치에서 좌표를 계산하거나 고정된 위치에 팝업을 표시할 수 있다:

Procedure TForm1.MenuClick(Sender: TObject);
  Var X, y : Integer;
begin
// calculate position
  x := Left + PanelLeft.Width+(Sender as TSpeedButton).Left;
  y := Top + TitleBar.Height.Width+(Sender as TSpeedButton).Top+
                                   (Sender as TSpeedButton).Height;
// Show menu:
  if (Sender = BPrg) then
    PMPrg.Popup(X,Y)
  else
    PMHelp.Popup(X,Y);
end;


라자루스 IDE에서는 설계 시 전체 메뉴 구조의 생성이 불가능한 상황이 있다. 예를 들어, 많은 프로그램에는 Recent Files 메뉴가 구비되어 있는데, 그러한 메뉴는 런타임 시 생성되어야 하며, 그 메뉴 항목들은 코드 속 메뉴 구조에 삽입되어야 한다.


아래 코드 조각은 그러한 메뉴 엔트리를 생성하는 방법을 보여준다. 이는 File 메뉴의 OnClick 핸들러에서 구현되어야 한다. 이를 구현하면 Recent Files 메뉴 항목을 (MIRecent) 파일의 더미(dummy) 리스트로 채운다:

procedure TMainForm.MFileClick(Sender: TObject);
  Var I  : integer;
      MI : TMenuItem;
begin
  With MIRecent do
  begin
    Clear;
    For I:= 0 to 10 do
    begin
      MI := TMenuItem.Create(Self);
      MI.Caption := Format('%d: recent file no. %d',[I,I]);
      MI.OnClick := @DoMenuClick;
      Add(MI);
    end;
  end;
end;


첫째, Clear 메소드로 인해 모든 기존 메뉴 항목들이 제거된다. MIRecent 메뉴 항목의 하위메뉴가 루프에 채워진다: 각 항목이 생성되고 (폼을 항목의 소유자로 이용) 로컬 변수(MI)에 저장된다. Caption과 OnClick 프로퍼티들이 제공되며, 마지막으로 TMenuItem.Add() 메소드를 사용해 MIRecent 하위메뉴로 메뉴 항목이 추가된다.


버튼

Button 컨트롤과 (TButton) 그 동료(companion) 컨트롤 BitButton은 (TBitBtn) 간단한 버튼 컨트롤이다. 이들은 간단한 Caption을 표시하고 (BitButton의 경우 이미지도 추가로 표시) 사용자는 해당 컨트롤을 클릭할 수 있다. 텍스트는 Caption 프로퍼티에 명시되며, 버튼의 활성화에 사용 가능한 accelerator 문자를 포함 가능하다. 표준화된 대화창 폼의 구성을 수월하게 만들기 위해 표 6.44에 실린 추가 버튼 프로퍼티들이 제공된다. 이러한 프로퍼티들을 결합하면 사용자가 Escape 또는 Return 버튼을 누를 때 스스로 닫을 수 있는 표준화된 대화창을 수월하게 구성할 수 있다. Escape는 대화창에 일어난 변경내용을 모두 무시하고, Return은 변경내용을 모두 저장한다.

프로퍼티 설명
Cancel 버튼은 폼에서 Cancel(취소) 버튼의 역할을 한다: Escape 키를 누르면 버튼이 활성화되고, 일반적으로 변경내용을 저장하지 않은 채 대화창을 닫을 것이다.
Default 버튼이 폼의 기본 버튼으로 작용한다 (보통 OK 버튼 이용). 사용자가 키보드의 Enter 또는 Return 버튼을 누를 때 활성화될 것이다.
ModalResult mrNone 이외의 값으로 설정될 경우 버튼을 클릭하면 버튼이 위치한 폼의 ModalResult 프로퍼티로 설정되고, 이는 폼이 modal로 표시될 경우 자동으로 폼을 닫을 것이다. OnClick 핸들러는 여전히 실행됨을 명심한다: 필요 시 데이터 저장을 실행하는 데에 사용되기도 한다. 핸들러가 실행을 완료하자마자 폼이 닫힌다.
표 6.44: 대화창 폼을 구성하는 데에 유용한 TButton과 TBitBtn 프로퍼티


TBitBtn 컨트롤은 표 6.45에 열거된 바와 같이 그 레이아웃을 제어하는 추가 프로퍼티를 갖는다. 두 버튼은 모두 windowed 버튼으로, 포커스를 받을 수 있음을 의미한다. 버튼이 라벨의 FocusControl 프로퍼티에 명시된 경우, 라벨의 accelerator 문자를 누르면 버튼에 포커스가 갈 것이며 OnClick 이벤트가 발생(fire)하지 않을 것이다. 반대로 버튼의 Caption에 있는 accelerator 문자는 OnClick 이벤트를 트리거할 것이다.

프로퍼티 설명
Glyph Kind 프로퍼티가 bkCustom 일 경우 버튼에 표시할 이미지. Kind 기본 값은 bkCustom 으로, 커스텀 이미지와 캡션을 명시할 수 있음을 의미한다. 만일 다른 값으로 설정할 경우 (bkOK, bkCancel, bkHelp, bkYes, bkNo, bkClose, bkAbort, bkRetry, bkIgnore, bkAll, bkNoToAll, byYesToall), Glyph, Caption, ModalResult 프로퍼티에 대한 기본 값이 채워진다.
Layout 캡션을 기준으로 글리프의 위치를 결정한다. 다음 값 중 하나를 가질 수 있다: blGlyphBottom, blGlyphLeft, blGlyphRight, blGlyphtop. (하단, 좌측, 우측, 상단)
Margin 버튼 위 이미지와 버튼 경계 간 픽셀 수를 나타낸다. -1로 설정 시 버튼 위 텍스트와 이미지를 중앙으로 모을 것이다.
NumGlyphs Glyph 비트맵에 이미지 수를 나타낸다. 첫 번째는 표준 이미지로서 사용될 것이며, 두 번째는 버튼을 비활성화 시 이미지로 사용될 것이다.
Spacing 버튼 위 이미지와 캡션 사이의 픽셀 수를 나타낸다.
표표 6.45: TBitBtn의 디스플레이 프로퍼티


라자루스 배포판은 TBitBtn 의 프로퍼티를 보여주는 예제 프로그램을 포함하고 있다 (../examples/bitbutton.lpi). 이를 그림 6.38에 실었다 (현재 일반 버튼에는 라자루스 데모 프로그램이 없다).

그림 6.38: 라자루스 TBitBtn 예제 프로그램


Label 컨트롤

라벨 컨트롤(TLabel class)은 텍스트를 단일 색상과 폰트로 표시하는 데 사용된다. 일반적인 사용은 편집, 메모 등과 같은 기타 컨트롤에 이름을 붙이는 것이다.


표 6.46에 열거된 프로퍼티들을 사용한다.

프로퍼티 설명
Alignment 라벨 텍스트를 왼쪽, 오른쪽 또는 중간으로 정렬할 것인지 결정하는 수평 정렬이다. 프로퍼티의 효과는 Autosize 가 True 로 설정 시 표시된다.
Autosize 라벨 크기가 스스로 조정되어 Caption 모두를 표시할 만큼 충분한지를 결정한다. False 로 설정하였는데 Caption 이 너무 길면 표시된 텍스트가 잘려 줄여(truncate)진다.
Caption 라벨이 표시한 텍스트. 텍스트 내 문자 앞에 앰퍼샌드(&)가 붙으면 밑줄이 그어진 상태로 나타날 것이며, accelerator 문자의 기능을 할 것이다 – 따라서 Alt 버튼과 그 문자키를 동시에 누르면 FocusControl 에 명시된 컨트롤에 초점이 전환될 것이다. 이러한 행위는 ShowAccelChar 프로퍼티로 비활성화할 수 있다. 하나의 앰퍼샌드를 실제로 표시하기 위해선 앰퍼샌드를 두 개 연속 입력한다 (&&).
FocusControl Accelerator 키를 누를 때 포커스를 받을 컨트롤을 의미한다. 이는 TWinControl 자손, 예를 들어 포커스를 실제로 받을 수 있는 컨트롤이어야 한다.
Layout 텍스트를 상단, 하단 또는 중간으로 정렬할 것인지 결정하는 수직 정렬을 제어한다. 다시 말하지만 Autosize 프로퍼티가 True로 설정 시, Layout의 설정은 시각적 효과가 없다.
ShowAccelChar Caption 내 앰퍼샌드(&) 문자가 accelerator 키를 나타낼 것인지 결정한다.
Transparent True 일 경우, 라벨을 그리기 전에 배경에 색상이 없으므로 Color 프로퍼티는 무시된다.
WordWrap True 일 경우, 라벨의 너비에 너무 긴 Caption 은 다음 행으로 넘어갈 것이다. 예를 들어, 단일행에 맞지 않는 텍스트는 여러 행으로 나뉜다. 이 프로퍼티는 Autosize 가 True일 경우 어떠한 효과도 없다. WordWrap 이 True일 경우 캡션의 강제 개행(hard linefeed)은 여전히 존중할 것임을 명심한다.
표 6.46: TLabel 프로퍼티


텍스트 엔트리 컨트롤

사용자에게 가장 흔히 사용되는 입력 액션은 아마도 필드에 텍스트를 타이핑하는 일일 것이다. 이는 TEdit 또는 TMemo 컨트롤을 이용해 이루어진다. 두 컨트롤의 차이는 전자의 경우 단일 텍스트 행을 포함하고 후자는 한 줄 이상의 텍스트를 처리할 수 있다는 점이다. 두 컨트롤 모두 TCustomEdit 의 자손이다. TCustomEdit 의 자손으로는 숫자 값을 편집하는 TSpinEdit, TFloatspinEdit 등 많은 컨트롤들이 있다. TEditButton 클래스는 편집 컨트롤 우측에 작은 스피드버튼(speedbutton)을 하나 표시한다. 이 버튼을 이용하면 추가 입력을 위한 대화창을 여는데, TFileNameEdit, TDirectoryEdit, TDateEdit, TCalcEdit 는 이 컨트롤의 자손들로서, 버튼에 이미 만들어진 기능을 제공한다. 이는 텍스트 값을 선택하거나 계산할 수 있는 대화창을 연다. 편집 컨트롤의 계층구조는 그림 6.39에 표시되어 있다.

그림 6.39: 편집 컨트롤의 계층구조


TEdit 컨트롤의 주 프로퍼티는 표 6.47에 열거되어 있다.

프로퍼티 설명
AutoSelect True 로 설정 시, 컨트롤이 포커스를 받으면 편집 컨트롤 내 모든 텍스트가 선택된다. 다시 말해, 사용자가 편집 컨트롤에 타이핑하자마자 새로 타이핑된 텍스트가 이전 텍스트를 (해당 시) 덮어쓴다. False 로 설정 시 (기본 값), 단순히 새로 선택된 텍스트가 커서 위치로 삽입된다.
CharCase 타이핑된 텍스트의 대·소문자를 결정한다: ecNormal 은 타이핑된 문자의 대·소문자를 변경하지 않는다; ecLowercase 는 모든 타이핑을 소문자로 강제 변경한다; ecUppercase 는 모든 타이핑을 대문자로 강제 변경한다.
EchoMode 타이핑된 문자를 편집 컨트롤에 어떻게 표시할지 결정한다. enNormal 은 사용자가 타이핑한 그대로 표시됨을 의미한다. emNone 의 값은 사용자가 내용을 보지 않고 타이핑하고 있음을 의미한다: 따라서 어떤 문자도 화면에 반영되지 않는다. 마지막으로 emPassword 는 사용자가 상자에 타이핑한 모든 문자가 비밀번호 문자로 대신 표시됨을 의미한다.
MaxLength 0보다 큰 값으로 설정 시, 이 값은 사용자가 입력할 수 있는 최대 문자수로 사용된다. 최대 길이에 도달하면 사용자가 입력하는 추가 문자는 무시된다 (복사하기와 붙여넣기 액션도 포함).
PasswordChar EchoMode 를 emPassword 로 설정 시, Text 프로퍼티에 모든 문자는 텍스트로 표시되기 전에 이 문자로 대체될 것이다. Text 프로퍼티는 그 본래 값을 (예: 사용자가 타이핑한) 보유함을 명심한다. 이 프로퍼티는 Text 값이 아니라 디스플레이에 영향을 미친다.
ReadOnly True 로 설정 시, 편집 컨트롤은 읽기만 가능하다. 즉, 사용자는 컨트롤에 어떤 내용도 입력할 수 없다. Enabled 프로퍼티를 False 로 설정하는 것과 다른 점은 컨트롤이 여전히 활성화되어 있으며 포커스를 받을 수 있다는 점이다. 예를 들어, 사용자는 읽기만 허용되는 컨트롤에서 텍스트를 선택할 수 있다.
SelLength 해당 런타임 프로퍼티는 문자에서 선택된 길이를 리턴한다. 프로그램에 따라 설정이 가능하다.
SelStart 해당 런타임 프로퍼티는 선택된 텍스트의 시작 위치를 리턴한다. 설정도 가능하며, 커서의 이동을 야기할 것이다. 위치는 Text 문자열에서 0을 기반으로 한(zero-based) 문자 색인이라는 점을 주목한다.
SelText 편집 컨트롤에 선택된 텍스트이다. 검색 및 설정이 가능하다. 컨트롤이 삽입모드든 겹쳐쓰기 모드든 상관없이 이전에 선택된 내용은 이 프로퍼티의 새 값으로 대체된다.
Text 컨트롤에 표시되는 실제 텍스트이다.
표 6.47: TEdit의 주요 프로퍼티


TEdit 의 주요 이벤트는 표 6.48에 소개되어 있다.

이벤트 설명
OnChange 편집 필드에 텍스트가 변경될 때마다 발생(fire)한다. 예를 들어, 타이핑된 각 문자마다 발생됨을 의미한다.
OnKeyPress 키를 누를 때마다 발생된다. 해당 이벤트는 컨트롤에 타이핑할 때 특정키를 비활성화시키는 데에 사용할 수 있다.
OnEditingDone 사용자가 편집 컨트롤의 내용 편집을 완료했을 때 발생한다. 최근에는 두 가지 액션이 해당 이벤트를 트리거할 것이다: 포커스가 컨트롤을 벗어났을 때, 또는 Enter 키를 눌렀을 때. 해당 이벤트는 OnChange 이벤트보다 덜 자주 발생하므로, 시간이 많이 소요되는 검사를 실행해야 할 경우 해당 이벤트를 이용해 변경내용을 확인하는 방법이 선호된다.
표 6.48: TEdit의 주요 이벤트


편집 컨트롤 내 선택된 텍스트가 하나의 메소드 호출, ClearSelection 으로 제거할 수 있다. 컨트롤의 전체 텍스트는 TEdit 의 Clear method 로 제거 가능하다.


아래 표는 TEditButton 클래스와 그 자손들의 프로퍼티를 열거한다.

프로퍼티 설명
ButtonWidth 속도버튼의 너비. 높이는 항상 편집 컨트롤의 높이와 같다.
ButtonOnlyWhenFocused True 로 설정 시, 속도 버튼은 편집 컨트롤에 포커스를 둔 경우에만 표시된다.
DirectInput True 로 설정 시, 사용자는 편집 컨트롤에 값을 입력할 수 있다.
False 로 설정 시, 편집 컨트롤에 내용을 입력하는 유일한 방법은 속도버튼을 이용하는 것으로, 입력할 값에 대한 제어력을 더 많이 제공한다.
Flat True 로 설정 시, 속도 버튼은 평평한 모양을 한다.
Glyph 버튼에 표시된 이미지를 포함한다.
NumGlyphs 글리프 내 이미지 수.
OnButtonClick 사용자가 속도버튼을 클릭할 때 트리거되는 이벤트.
표 6.49: TEditButton의 프로퍼티


TMemo 는 TEdit 컨트롤과 동일한 기능을 가지지만, 텍스트의 행을 하나 이상 입력하도록 허용한다-허용하는 행의 수는 거의 무제한이다.


행의 길이가 너무 길거나 행의 수가 너무 커서 디스플레이 공간에 맞지 않을 경우 컨트롤은 스크롤바를 표시할 수 있다. 이러한 기능 때문에 TMemo 컨트롤은 TEdit 컨트롤과 다른 프로퍼티를 가진다.


주요 프로퍼티는 Line 이다: 이는 컨트롤에 표시되는 텍스트 행으로, TStrings 인스턴스에 포함된다. 해당 stringlist에 일어나는 변경사항은 즉시 컨트롤에 표시된다.


이러한 점을 감안할 때 Lines 프로퍼티에서의 행과 메모 컨트롤에 실제로 표시되는 행들 간 차이를 이해하는 것이 중요하겠다. 메모 컨트롤은 Lines 프로퍼티에서 각 문자열에 대해 새 행을 시작하지만, 행이 너무 커서 들어맞지 않을 경우 메모 컨트롤은 행을 여러 행으로 넘길 것이다. 기술적으로 TStrings 인스턴스의 전체 텍스트를 고려하면 메모 컨트롤은 CR/LF 쌍 또는 LF 혹은 CR 문자를 마주칠 때마다 새로운 행을 시작한다. (따라서 확인되는 실제 문자는 운영체제에 따라 좌우된다.)

그림 6.40: 행바꿈을 하지 않은 메모 컨트롤


그림 6.41: 행바꿈이 실행된 메모 컨트롤


Memo 컨트롤이 긴 행을 어떻게 표시할 것인지는 Wordwrap 프로퍼티의 값에 따라 달라진다. True로 설정한다면 눈에 보이는 행의 길이보다 긴 텍스트는 다음 행으로 넘겨질 것이다. WordWrap 이 False라면 긴 행은 단일 행으로 표시될 것이며, 행의 끝으로 스크롤하기 위해 커서를 사용해야 한다. 그러한 경우 ScrollBars 프로퍼티는 수평 또는 수직 스크롤바를 언제 표시할 것인지 결정한다. ssBoth (두 개의 스크롤바가 항상 표시), ssAutoBoth (텍스트가 메모에서 너무 커지면 즉시 스크롤바가 표시), ssHorizontal, ssVertical, ssAutoHorizontal, ssAutoVertical, ssNone (수평, 수직, 자동 수평, 자동 수직, 없음) 중 하나의 값을 가질 수 있다. 이러한 값은 이름으로 기능을 추론할 수 있다.


사용자에게 Tab 키를 이용해 탭 문자를 삽입할 수 있는 능력을 부여하고 싶다면 WantTabs 프로퍼티를 True로 설정해야 하며, 이런 경우 탭 문자를 삽입 및 표시하기 위해 메모 컨트롤이 Tab 키를 이용한다. 일반 행위는 (값이 False로 설정 시) Tab 키의 사용을 다음 컨트롤로 포커스를 이동하라는 사용자의 신호로 해석하는 것이다.


TMemo 컨트롤의 내용을 TStringList 인스턴스로 가진다면 내용을 파일로부터 쉽게 로딩할 수 있음을 의미한다:

If OpenDialog1.Execute then
  Memo1.Lines.LoadFromFile(OpenDialog1.FileName)


이와 마찬가지로, 내용을 파일로 저장할 수도 있다:

If SaveDialog1.Execute then
  Memo1.Lines.SaveToFile(SaveDialog1.FileName);

이보다 더 간단할 수는 없다!


ReadOnly, SelText, SelStart, SelLength 프로퍼티는 TEdit 컨트롤에서와 동일한 기능을 하는데, 옵션 원점이 컨트롤 내 첫 행의 첫 문자를 기준으로 하므로 그다지 편리하진 않다. 마찬가지로 TMemo의 Clear, ClearSelection 메소드도 TEdit 에서 메소드와 동일한 행위를 한다.


메모를 텍스트로 채울 때 Lines 프로퍼티가 업데이트된다. 운영체제에 따라 이 동작은 매우 느릴 수도 있는데, 각 행의 수정이나 추가 시 컨트롤이 스스로 다시 그리는 결과를 야기하여 화면에 깜박임이 많아지기 때문이다. 하지만 채우기 루틴을 시작 시 BeginUpdate 를 호출하고 채우기 루틴의 끝에 EndUpdate 의 호출함으로써 이러한 일을 피할 수 있는 방법이 제공된다. 이 둘은 메모의 Lines 프로퍼티의 메소드이다. 그 효과로, 메모가 EndUpdate 호출 시 그 디스플레이를 한 번만 업데이트하는 결과를 낳는다. FillMemo() 라는 이름의 일반 루틴은 아래와 같은 모습이다:

procedure TMainForm.FillMemo(B: Boolean);
  Const LineCount = 50000;
  Var I: Integer; Start: TDateTime; S: String;
begin
  Start := Now;
  With MTest.Lines do begin
    If B then BeginUpdate;
    try
      Clear;
      For I := 1 to LineCount do Add('This is line ' + IntToStr(I));
    Finally
      If B then EndUpdate;
    end;
    S := FormatDateTime('hh:nn:ss.zzz',Now-Start);
    S := Format(SFillTime,[LineCount,S]);
    ShowMessage(S);
  end;
end;


루틴의 끝에는 50,000 행으로 메모를 채우는 데 소요된 시간이 표시된다. 일부 위젯 셋의 경우 BeginUpdate/EndUPdate를 이용한 최적화 루틴과 이러한 호출이 결여된 비최적화 루틴의 차이가 그다지 크지 않다. 하지만 그 외 위젯 셋에서는 그 차이가 현저할 수 있다. 따라서 Lines 프로퍼티의 심한 변경내용(heavy modification)은 항상 BeginUpdate 와 EndUpdate 로의 호출로 둘러쌀 것을 권한다. 이는 예외가 던져졌을 경우 오류를 (lockup) 피하도록 Try…Finally 블록 내에서 실행하는 것이 최선이다.


ToggleBox 컨트롤

ToggleBox 컨트롤은 (TToggleBox) 일반 버튼 컨트롤과 같이 생겼지만 체크상자와 같은 행위를 한다: 사용자가 클릭하면 '체크된' 채로 (눌러진 채로) 유지된다. '체크 해제'하기 위해선 다시 클릭을 해야 한다. 아래에서 다룰 체크상자 컨트롤과 동일한 프로퍼티와 행위를 가진다 (OnChange와 OnClick 핸들러를 포함).


CheckBox 컨트롤

체크상자 컨트롤은 (TCheckBox) 클릭이 가능하다는 점에서 Button 컨트롤과 유사하다. 컨트롤의 OnClick 이벤트는 체크상자에 포커스가 있을 때 체크표시를 클릭하여 (또는 스페이스 바를 눌러) 토글하면 트리거된다. TCheckBox 와 TButton 클래스가 비슷한 이유는 모두 TButtonControl 클래스의 자손이라는 사실 때문이다. 사용자가 프로그램 옵션을 활성화 또는 비활성화해야 할 때마다 프로그래머는 체크상자를 이용할 수 있다. 다중 옵션에는 여러 개의 체크상자가 필요하다.


TCheckBox 는 TButton 과 일반적인 Caption 과 OnClick 프로퍼티를 공유한다. 또한 체크상자에는 행위와 모양을 결정하는 특수 프로퍼티가 몇 가지 있는데, 이는 표 6.50에 실려 있다.

프로퍼티 설명
Autosize TLabel 컨트롤에서와 같이 AutoSize 는 체크상자가 Caption (True)의 크기를 수용하도록 너비를 조정할 것인지, 또는 고정된 크기를 유지할 것인지를 (False) 결정한다.
AllowGrayed 체크상자가 회색 상태로 표시될 수 있는지 결정한다.
Checked 체크상자가 컨트롤에 표시될 것인지 결정한다.
State cbUnchecked, cbChecked, cbGrayed 중 하나의 상태이다.
UseOnChange Checked 프로퍼티가 코드에서 변경될 경우 발생할 일을 결정한다. 일반적으로 체크 표시된 프로퍼티가 변경되면 (사용자 액션이나 코드에 변경) OnClick 이벤트와 OnChange 가 트리거된다. UseOnChange 프로퍼티가 True로 설정 시, Checked 프로퍼티가 코드에서 변경되면 OnChange 이벤트만 트리거된다 (델파이와 호환 가능한 행위).
표 6.50: 특수 TCheckBox 프로퍼티


체크상자의 가장 중요한 프로퍼티는 Checked 와 State 이다. 일반적으로는 체크표시를 처음에 표시할 것인지 말 것인지를 결정하기 위해 Checked 로 작업한 후 프로퍼티를 클릭하여 그 설정을 변경할 수 있다. 세 번째 상태, cbGrayed 는 AllowGrayed 상태가 True 일 경우 사용자가 구축할 수 있다 (기본 값은 False).


체크상자가 cbUnchecked 상태에 있을 때 사용자가 이를 클릭하면 체크된 상태로 넘어가고, 두 번째로 클릭하면 cbUnchecked 상태로 설정될 것이다. 상태의 변경 순서는 사용되는 위젯 셋에 따라 좌우되는데, GTK2 위젯 셋을 사용 시 아래와 같은 기능을 한다:


cbGrayed 의 상태에 있고, Checked 가 False일 경우, 첫 번째 클릭은 체크상자를 활성화시키고 두 번째 클릭은 체크 표시를 표시할 것이다. 따라서 State 프로퍼티는 “어떤 것도 선택되지 않았지만 이것이 기본 설정이다”로 해석될 수 있다. 데이터 인식 체크상자 컨트롤에서 매우 유용한데, 특히 필드 값이 Null 일 때 사용할 수 있다. cbGrayed 상태는 Enabled를 False로 설정했을 때 얻는 ‘비활성화’ 상태와는 다르다는 점을 명심한다. 비활성화된 체크상자는 어떤 State 도 가능하지만 사용자는 변경할 수 없다.

그림 6.42 디자이너에서와 런타임 시 가능한 세 개의 TCheckBox 상태


RadioButton 컨트롤

RadioButton 컨트롤은 (TRadioButton) 체크상자와 비슷하며 Checkbox와 동일한 프로퍼티를 갖는다. 체크상자와 다른 점이라면, 한 번에 하나의 라디오버튼만 체크할 수 있다는 점이다. 라디오버튼 하나를 체크하면 동일한 그룹 내 다른 라디오버튼은 모두 해제될 것이다. 따라서 라디오버튼은 상호 배타적 옵션 중에 사용자가 하나를 선택해야 하는 경우 사용해야 한다. 여러 개의 옵션을 동시에 유효하게 만들기 위해선 일련의 체크상자를 사용해야 한다.


라디오버튼은 동일한 부모 컨트롤을 가진 경우 동일한 그룹에 속한다. 이 부모 컨트롤은 어떤 포함 컨트롤(containing control)이든 가능하다: 폼, 패널, 그룹상자. 직계 부모만 고려한다.


Listbox 컨트롤

리스트상자는 리스트에서 하나 또는 이상의 항목을 선택할 때 사용된다. 옵션의 리스트는 항상 TListBox 컨트롤에서 시각적으로 표시된다. 이 컨트롤의 기능은 (리스트에서 하나 또는 이상의 항목을 선택) 라디오그룹 또는 체크그룹의 기능과 유사하다. 하지만 라디오 그룹 또는 체크그룹은 스크롤이 불가하여 거대한 리스트에는 부적절한 반면 리스트상자는 가능한 한 많은 항목을 표시하여 리스트상자보다 전체 리스트가 더 많은 공간을 차지할 경우 전체 리스트에 걸쳐 스크롤을 허용한다. 콤보상자는 리스트상자와 비슷하다. 두 컨트롤 모두 항목의 리스트를 문자열리스트(stringlist)로 유지하며 (TStrings 인스턴스), 두 컨트롤 모두 항목의 커스텀 그리기를 지원하므로 항목을 좀 더 매력적인 방식으로 그래픽하게 표시하는 것이 가능하다.


리스트상자는 두 컨트롤의 단순한 버전이다. 항목의 리스트만 표시하며, 사용자는 리스트에 항목을 클릭하여 하나를 선택할 수 있다. 리스트상자 행위는 표 6.51의 프로퍼티에 의해 제어된다.

프로퍼티 설명
ExtendedSelect True 로 설정 시 (기본 값), 컨트롤이 다중선택 모드에 있다면 확장된 선택 메커니즘을 이용할 수 있다: Ctrl-클릭을 하면 단일 항목을 선택내용에 추가하고, Shift-클릭을 하면 이웃하는 여러 항목을 추가한다. False로 설정 시, 더블 클릭으로 항목이 선택된다 (또는 선택해제).
IntegralHeight True 로 설정 시, 항목이 리스트상자에 완전히 일치하지 않는 한 항목을 그릴 수 없다.
ItemIndex 제공된 리스트 내 선택 항목의 색인이 다중선택 모드에 있지 않다. 색인은 0을 기점으로 한다.
ItemHeight 항목의 높이 (픽셀).
Items 리스트에 표시되는 문자열 리스트.
MultiSelect True 로 설정 시, 리스트에서 하나 이상의 항목을 선택할 수 있다.
Selected 부울(Boolean) 배열 프로퍼티: 리스트 내 각 항목에 대해, 배열은 그것이 선택되었는지 (True) 아닌지를 (False) 나타낸다. 이 프로퍼티는 리스트가 다중선택 모드일 때에만 사용할 수 있다.
Sorted True 일 경우, 리스트 내 항목들은 정렬된 채로 유지된다.
Style 리스트상자가 일반 리스트상자인지 (lbStandard), 항목의 높이가 고정된 소유자가 그린 리스트상자인지 (lbOwnerDrawFixed), 아니면 가변 높이인지 (lbOwnerDrawVariable) 결정한다. 소유자가 그린 두 가지 경우, 리스트 내 항목을 그릴 때 OnDrawItem 이벤트를 이용해야 한다.
TopIndex 리스트의 상단에 표시되는 항목의 (0을 기점으로 한) 색인.
표 6.51: 중요한 Listbox 프로퍼티


MultiSelect 의 설정에 따라 리스트에서 하나의 항목 또는 여러 개의 항목 선택이 가능해진다. MultiSelect 가 False인 경우, ItemIndex 프로퍼티는 어떤 항목이 선택되었는지를 나타낸다. MultiSelect 가 True인 경우, 선택할 항목을 결정하기 위해선 모든 항목을 순회(traverse)해야 한다. 아래 코드 토막은 MultiSelect의 설정과 상관없이 선택한 항목을 리스트상자에서 제거하는 방법을 보여준다:

  Var I : Integer;
begin
  With ListBox1 do
    if MultiSelect then
    begin
      For I := Items.Count-1 downto 0 do
        If Selected[i] then Items.Delete(I);
    end
    else Items.Delete(ItemIndex);
end;

리스트는 반대 순서로 순회됨을 명심한다.


다수의 항목을 문자열리스트로 추가할 때 메모 컨트롤의 사용을 최적화하는 데 대한 제안(suggestion) 또한 리스트상자에서 이용할 수 있다.


Items 프로퍼티에 긴 변경 리스트를 실행할 때는 BeginUpdate-EndUpdate 문들 내에서 동작을 포괄(enclose)하는 것이 최선의 방법이다.


Combobox 컨트롤

TComboBox 컨트롤은 리스트상자와 같은 목적으로 사용 가능하다. 설계 시 선택한 항목의 전체 리스트가 숨겨진다는 점에서 TListbox 컨트롤과 다르다. 버튼을 이용해 표시할 수 있으며, 이 경우 리스트가 드롭 다운된다. 그 결과 TCombox 컨트롤은 리스트상자나 라디오그룹보다 더 적은 화면공간을 사용한다. 또한 항목의 리스트에 표시되지 않은 항목은 컨트롤의 편집 필드에 이름을 다이핑함으로써 콤보상자에 입력할 수 있다. 이후 콤보상자는 히스토리 리스트와 유사하게 텍스트를 빠르게 설정할 수 있는 사전 정의된 값 리스트가 있다는 점을 제외하면 일반 편집 컨트롤과 같은 역할을 한다. 이러한 행위는 사용자 정의가 가능하다. TComboBox 컨트롤은 행위를 제어하는 프로퍼티를 많이 가진다. 프로퍼티는 표 6.52에 열거되어 있다. 리스트 내 항목들은 어떤 문자열리스트 동작이든 가능한 TStrings 타입의 Items 프로퍼티에 명시된다.

프로퍼티 설명
ArrowKeysTraverseList ArrowKeyTraverseList 가 True 로 설정 시, 컨트롤에 포커스가 있을 때 위와 아래 방향키를 이용하면 리스트의 이전 및 다음 항목이 선택될 것이다. False 로 설정 시, 항목을 선택 시 마우스를 사용해야 한다.
AutoComplete True 로 설정 시, 컨트롤에 텍스트를 타이핑하면 처음 일치하는 항목이 텍스트를 완성할 것이다. 항목이 이미 타이핑한 텍스트와 동일한 문자로 시작될 때 일치결과가 발견된다.

'증분 검색'과 많이 비슷한 행위이다.

AutoCompleteText 자동완성 옵션을 상세히 조정(fine-tune)할 때 사용할 수 있다. 다양한 자체 설명적 값을 가진 집합형(set) 프로퍼티이다. 집합에 첫 항목을 포함시키는 것은 (cbactEnabled) AutoComplete 프로퍼티를 설정하는 것과 동일하다.
AutoDropDown True 로 설정 시, 문자가 콤보상자에 타이핑되는 순간 리스트는 시각적으로 만들어질 것이다.
AutoSelect TEdit 컨트롤과 동일하다-True로 설정 시, 콤보상자가 포커스를 받으면 표시된 전체 텍스트가 선택된다.
CharCase TEdit 컨트롤의 경우, 타이핑된 문자의 대.소문자를 결정한다 (대문자, 소문자 또는 변경하지 않음).
DropDownCount 드롭다운 리스트가 표시될 때 얼마나 많은 항목을 표시할 것인지 결정한다. 리스트에 여기서 설정된 값보다 많은 항목이 있을 경우, 리스트를 스크롤할 수 있도록 스크롤바가 표시될 것이다.
ItemHeight 리스트 내 항목 높이. ItemIndex 는 최근 선택한 항목의 색인이다. 프로그램에 따라 설정 가능하다. 소유주가 그린 스타일이거나 csDropDownList 에 해당할 때만 의미가 있다.
ItemWidth 드롭다운 리스트 너비, 픽셀.
MaxLength 표시할 수 있는 텍스트의 최대 길이. 리스트 내 항목의 길이가 여기에 명시된 값보다 길 경우 텍스트는 잘린다(clip)는 점을 명심한다.
Sorted 리스트 내 항목을 정렬된 채로 표시할 것인지 결정한다.
Style 콤보상자의 스타일을 명시하는 데 사용된다. Style 프로퍼티는 표 6.53에 열거된 여러 값을 가질 수 있다.
표 6.52: TComboBox 프로퍼티


스타일 설명
csDropDown 사용자가 자유롭게 텍스트를 입력할 수 있고, 사전 정의된 값으로 텍스트를 설정할 수 있는 리스트도 사용 가능하다. 새로 입력된 텍스트가 리스트에 자동으로 추가되지는 않는다.
csDropDownList 사용자는 리스트에 나타나는 값만 선택할 수 있다.
csOwnerDrawFixed csDropDownList 와 같지만 항목이 고정된 높이로 OnDrawItem 이벤트에 그려진다는 점이 다르다.
csOwnerDrawVariable csDropDownList 와 같지만 항목이 가변 높이로 OnDrawItem 이벤트에 그려진다는 점이 다르다.
csSimple 윈도우에서 이 스타일은 아래에 리스트상자가 있는 편집 컨트롤의 모양을 콤보상자로 제공한다 (예: 리스트가 항상 표시됨). 이를 제외하면 컨트롤은 csDropDwon 콤보상자와 같은 역할을 한다. 다른 플랫폼에서는 csDropDwon 스타일이 이 값과 동일하다.
표 6.53: Combobox에 이용할 수 있는 스타일


ScrollBar 컨트롤

필요 시 많은 컨트롤들은 스크롤바를 자동으로 표시할 수 있다. 그러한 컨트롤에는 폼, 메모, 격자, 리스트상자가 포함된다. 하지만 모든 상황에서 충분히 제공할 수 있는 것은 아니다. 따라서 TScrollBar 컨트롤을 따로 이용하여 어떤 위치든 스크롤바를 추가할 수 있다 (예: 페인트상자와 함께 사용). 주요 프로퍼티는 스크롤바의 방향을 결정하는 Kind 프로퍼티, 스크롤바의 위치를 결정하고 Min과 Max 프로퍼티의 값 사이에서 다양하게 나타날 수 있는 Position 프로퍼티가 있다. 사용자에 의한 변경사항에 대한 반응에 OnChange 이벤트를 사용할 수 있다.


GroupBox 컨트롤

그룹상자 컨트롤은 (TGroupBox) 베벨 및 패널과 몇 가지 프로퍼티를 공유한다. 이 컨트롤은 프레임을 그리고, 프레임의 좌측 상단 모서리에 캡션을 표시한다. 패널과 같이 컨트롤을 포함 가능하며, 포커스를 받을 수 있다. 보통은 컨트롤을 그룹화하는 데 사용되어 그룹에 대한 제목을 제공한다. 제목은 accelerator 문자를 포함할 수 있으며, 그룹상자로 포커스를 설정하는 데 사용하기도 한다.


그룹상자 컨트롤에는 별도의 특수 프로퍼티가 없다. Caption과 ChildSizing 프로퍼티를 설정하는 일은 컨트롤이 폼 위에 위치된 후에 필요한 사용자 정의(customization)이다.


RadioGroup 컨트롤

라디오그룹 컨트롤은 (TRadioGroup) 결합된 컨트롤이다: 다수의 라디오버튼을 포함하는 그룹상자에 불과하다. 라디오버튼의 캡션은 Items 프로퍼티에 의해 결정된다. 그룹 내 어떤 라디오버튼이 선택되는지는 ItemIndex 프로퍼티에 의해 결정된다.


사용자에 의한 변경사항에 대한 응답은 TRadioButton 컨트롤에서와 마찬가지로 이루어지므로, 사용자가 내용을 변경할 때마다 OnClick 이벤트가 트리거될 것이다.

프로퍼티 설명
AutoSize 옵션이 컨트롤 면의 아래에 균등하게 분산되었는지 결정한다. False 로 설정 시, 옵션은 사이에 공간 없이 잇따라 위치된다. AutoSize 가 True일 경우 (기본 값 0, 라디오버튼 간 충분한 여백이 있어 그룹상자를 완전히 채운다.
ColumnLayout 라디오 버튼 열(column)이 하나 이상일 경우, 이 프로퍼티는 채움 방향을 결정한다-열을 거쳐, 또는 열별로 수직으로.
Columns 라디오그룹 내 열의 수.
표 6.54: TRadioGroup 프로퍼티


CheckGroup 컨트롤

체크그룹 컨트롤은 (TCheckGroup) 라디오버튼 컨트롤과 유사하다. 라디오버튼 대신 체크상자가 사용되므로, 사용자가 체크상자를 전혀 체크하지 않거나, 하나, 여러 개, 또는 전부 체크할 수 있음을 의미한다. 이 시나리오에선 ItemIndex 프로퍼티는 의미가 없다. 대신 어떤 항목이 체크되었는지 찾으려면 Checked 배열 프로퍼티를 사용하라. CheckEnabled 배열 프로퍼티를 이용해 특정 체크상자를 활성화 또는 비활성화시킬 수도 있다 (기본 값: 각 항목이 활성화). 배열은 publish 되지 않으므로, 오브젝트 인스펙터를 통하기보다는 코드에서 접근해야 한다.


Panel 컨트롤

패널 컨트롤은 (TPanel) Caption 을 표시한다는 점에서 TLabel 컨트롤과 비슷하다. 하지만 windowed 컨트롤이어서 더 광범위한 기능을 가진다. 다른 컨트롤들을 여기에 드롭할 수도 있다 (어떤 컨트롤도 라벨로는 드롭할 수 없다). 다른 컨트롤들을 패널로 드롭할 수 있다는 사실은 컴포넌트를 그룹화하거나 특정 레이아웃 효과를 줄 때 매우 유용하다. 추가로, 패널은 그 주위에 경계를 그릴 때 또는 탭의 위치(tab stop)로도 이용할 수 있다.


TPanel 은 많은 TLabel 의 프로퍼티를 공유하지만, 패널의 경계를 구성하는 두 개의 베벨을 제어하는 추가 프로퍼티도 가진다. BevelInner 은 내부 베벨의 외관을 제어하고, BevelOuter 는 외부 베벨의 모양을 제어하며, BevelWidth 는 베벨의 너비를 제어한다. BevelInner 와 BevelOuter 프로퍼티는 bvNone (없음), bvLowered (감소), bvRaised (증가), bvSpace (공간) 의 값을 취할 수 있다.


TPanel 은 windowed 컨트롤이기 때문에 그 위에 다른 컨트롤들을 드롭할 수 있다. 이는, 패널이 포커스를 받을 수 있고, 폼의 탭 순서에 참여할 수 있음을 의미한다. 이러한 행위는 TabStop 프로퍼티로 조절된다: True로 설정되면 사용자가 Tab 키를 누를 때 패널에 포커스를 줄 수 있다. 기본 값으로는 False로 설정된다.


프레임

프레임은 TForm 과 같이 다른 컨트롤들을 위한 상자이다. 프레임은 File→New 대화창에서 Frame 을 선택하여 생성한다. 폼을 생성할 때처럼 설계하면 된다: 또한 Forms 유닛에서 정의되고 TCustomFrame 에서 계승된다. IDE의 New 대화창에서 File ⇒ New... 를 선택하면 새 폼과 마찬가지로 TFrame 자손으로 채워진 새 유닛이 생성된다:

TFrame1 = Class(TFrame)
  BitBtn1 : TBitBtn;
  SubFrame : TFrame2;
 private
   { private declarations }
 public
   { public declarations }
end;

프레임이 생성되고 나면 컴포넌트 팔레트의 Standard 탭에서 프레임 아이콘을 선택하여 폼에 드롭할 수 있다. 이후 IDE는 애플리케이션에 정의된 모든 프레임을 표시하는 대화창을 띄우는데, 그 중 하나를 선택하고 나면 프레임의 인스턴스 하나가 폼으로 드롭될 수 있다 (아니면 패널과 같은 적절한 windowed 컨트롤로 드롭할 수 있다). 프레임은 정확히 같은 컨트롤 집합을 애플리케이션 내 하나 이상의 장소에 표시해야 할 때 일관적인 모양을 유지하는 데 매우 유용하다.


액션 리스트

ActionList 컴포넌트는 TAction 컴포넌트를 위한 상자이다. 액션은 6.3.9절에서 상세히 알아보았다.


Additional 탭

그림 6.43: 컴포넌트 팔레트의 Additional 탭


Bitbutton 컨트롤

비트버튼 컨트롤은 (TBitBtn) 추가로 글리프를 표시할 수 있는 버튼이다 (전적으로 선택적 옵션). 이 컨트롤은 일반 TButton 의 프로퍼티들을 모두 가진다. 이러한 글리프의 사용은 운영체제 의존적이다. Windows에서 흔하게 사용되지만 Mac OS X에서는 그렇지 않다.

이름 설명
TBitBtnLike TButton 이지만 아이콘을 추가 표시.
TSpeedButton 아이콘이 있는 non-windowed 버튼
TStaticText 편집 컨트롤의 모양과 분위기(look and feel)의 라벨.
TImage 이미지 표시에 필요한 내장 기능이 있음.
TShape 간단한 기하학적 형태 그리기용.
TBevel 베벨 그리기용.
TPaintBox 임의 그래픽을 그리도록 허용.
TNotebook TPageControl 과 유사. 호환용으로만 포함.
TLabeledEdit 하나의 컨트롤에 통합된 TLabel 과 TEdit.
TSplitter 사용자가 폼의 부분들을 크기 조정할 수 있도록 해주는 컨트롤.
TTrayIcon 시스템 트레이에 아이콘을 표시하기 위함.
TMaskEdit 키잉되는(Keyed) 입력을 제어하기 위해 마스크(mask)를 제공하는 TEdit 자손.
TCheckListBox TScrollBox
각 항목을 체크상자와 나란히 표시하는 TListbox.
스크롤 가능 영역에 다른 컨트롤들을 표시하기 위한 상자.
TApplicationProperties TApplication 프로퍼티를 설정하거나 애플리케이션 전체에 걸친 이벤트에 반응하기 위한 컴포넌트.
TStringGrid 문자열을 표시하는 TDrawGrid 의 자손.
TDrawGrid 이벤트 핸들러를 이용해 완전히 그려지는 격자.
TPairSplitter 확장된 Tsplitter.
TColorBox 색상을 선택하기 위한 TComboBox 자손.
TColorListbox 색상을 표시하고 선택하기 위한 TListBox 자손
표 6.55: Additional 탭의 컨트롤


SpeedButton 컨트롤

간단한 패널에 속도버튼을 배열하여 중요한 기능 또는 자주 필요한 기능으로 빠르게 접근할 수 있다. 다른 타입의 버튼들과 달리 속도버튼은 windowed 컨트롤이 아니다. 따라서 포커스를 받을 수 없기 때문에 Tab 키를 이용해 활성화할 수 없다. 속도버튼은 툴바 컨트롤이 의도적 사용을 위해 과도하게 조작(over engineered)되었을 때, 즉 소수의 버튼만 필요할 때 사용된다. 많은 버튼이 필요한 경우 TToolbar 컴포넌트가 (본장 후반에서 논함) 적합하다-특히 메인 메뉴에 완전한 툴바를 생성하여 메인 메뉴의 기능이 중복되도록 의도한 경우. 이러한 경우, 모든 액션은 TActionList 컴포넌트를 통해 동기화할 수 있다. 소수의 속도버튼이 필요하다면 TSpeedButton이 적합하다. 라자루스 디렉터리에서 이미지 디렉터리는 속도버튼에 사용할 수 있는 이미지들을 많이 제공한다.


정적 텍스트 컨트롤

이것은 TLabel 컨트롤의 특수 버전으로, 그림을 그리는 데에 고유의 캔버스를 사용하는 TPanel 의 특성을 가지긴 하지만 TLabel 컨트롤은 부모 컨트롤의 캔버스를 사용한다. FocusControl 프로퍼티를 가진다는 점에서 TStaticText 는 TPanel 과 다르며, accelerator 키를 누를 경우 명시된 포커스 컨트롤이 포커스를 받게 된다.


Labeled 편집 컨트롤

TLabeledEdit 는 TEdit 컨트롤의 특수 버전으로, 그와 관련된 TLabel 을 가진다. 편집 컨트롤을 기준으로 한 EditLabel 의 위치는 LabelPosition 프로퍼티를 이용해 조정할 수 있으며, 편집 컨트롤과의 거리는 LabelSpacing 프로퍼티를 이용해 설정할 수 있다.


그 외에 이 컨트롤은 일반 TEdit 컨트롤과 같은 행위를 한다.


이미지 컨트롤

해당 컨트롤은 이미지를 표시하는 데 사용된다. Picture 프로퍼티는 어떤 이미지를 표시해야 하는지 결정한다. Stretch 프로퍼티는 비트맵의 크기 조정을 허용하여 TImage 크기에 일치하도록 해준다. Proportional 프로퍼티와 함께 작업 시 TImage 컨트롤에게 이미지의 크기를 조정 시 왜곡하지 말 것을 알린다. Center 프로퍼티는 작은 비트맵을 컨트롤 중앙에 표시하도록 해준다. TImage 컨트롤은 기본적으로 PNG, BMP, JPG,XPM 등 많이 사용되는 이미지 포맷은 거의 다 읽는다. 그 외 이미지 타입은 IDE에 imageforlazarus 패키지를 포함시켜 추가할 수 있다. 이는 TARGA, PNM, TIFF 지원을 추가한다.


Shape 컨트롤

TShape 컨트롤은 간단한 기하학적 모양을 표시한다. 그 Shape 프로퍼티를 이용해 (모서리가 둥근) 직사각형, 원, 다이아몬드, 타원 또는 (모서리가 둥근) 사각형 중 하나를 선택할 수 있다. 그리기는 Pen 프로퍼티를 통해 조절되고, 모양이 채워지는 방식은 Brush 프로퍼티로 조정한다.


Bevel 컨트롤

베벨 컨트롤은 (TBevel) 시각적으로 패널 컨트롤과 연관이 있다: 테두리, 또는 테두리의 일부를 보여주지만 캡션은 표시하지 않는다. 베벨의 '내부'는 비어 있고, 그 위에 어떠한 컨트롤도 드롭할 수 없다. 테두리를 따라 프레임을 그리는 단순한 컨트롤이다. 다른 컨트롤 주위에 위치시켜 시각적으로 그룹화하기도 한다 (패널과 마찬가지로). 패널과 달리, TBevel 은 windowed 컨트롤이 아니다. 따라서 폼의 탭 순서에 참가하지 않는다. 그 내부의 컨트롤들은 베벨이 위치한 컨트롤의 (주로 폼) 탭 순서의 일부이다.


두 가지 프로퍼티가 베벨의 모양을 제어한다: Shape 은 상자 (bsBox), 프레임 (bsFrame), 또는 경계 사각형의 (bsTopLine 등) 사면 중 하나가 될 수 있다. Style 프로퍼티는 행이 들어간 효과(engraved) 또는 튀어나온 효과(embossed) 중 어떻게 표시할 것인지를 결정하는 bsLowered 와 bsRaised 값 중 하나를 선택한다.


Paintbox 컨트롤

그림상자 컨트롤 TPaintBox 는 shape 컨트롤 또는 이미지 컨트롤로 충분하지 않거나, 기타 일반 컨트롤들이 제공하지 않는 무엇을 그릴 때 사용된다. 폼에서 위치 또는 크기 조정에 반응하는 방식이나 크기를 명시하는 것 외에는 어떤 특정 프로퍼티도 없다.


모든 그림은 컨트롤의 OnPaint 이벤트에서 이루어져야 한다.


Tray 아이콘

TTrayIcon 컨트롤은 그것이 위치한 폼에 표시되지 않는다는 점에서 다른 컨트롤과 꽤 다르다. 오히려 스스로를 트레이 바에 표시한다. Icon 프로퍼티는 트레이 바에 (system tray) 표시해야 하는 아이콘을 설정 시 사용된다. PopupMenu 프로퍼티는 아이콘을 클릭 시 표시되는 TPopupMenu 인스턴스로 설정할 수 있다. 트레이 아이콘은 그것이 위치한 폼의 수명(lifetime) 시에만 표시됨을 주목한다: 폼이 파괴되는 순간 아이콘도 시스템 트레이에서 제거된다. 하지만 폼이 숨겨 있다면 (파괴되지 않고) 트레이 아이콘은 계속 표시될 것이다.


Masked 편집 컨트롤

이것은 TEdit 자손으로, 해당 컨트롤에 타이핑한 내용이 명시된 마스크에 들어맞을 때 편집 마스크를 설정하도록 해주며, 들어맞지 않는다면 거부될 것이다. 이러한 마스크는 일자, 폰 번호, 은행 계좌 번호, 또는 특정 포맷에 따를 필요가 있는 데이터에 대한 엔트리를 조정할 때 적용할 수 있겠다. 마스크를 생성하기 위해서는 오브젝트 인스펙터에서 EditMask 프로퍼티 옆에 있는 생략 부호 […]를 클릭하면 된다. 클릭 시 뜨는 에디터는 당신이 입력한 마스크가 원하는 일을 확실히 하는지 테스트하도록 해준다.


스크롤상자

스크롤상자는 다른 컨트롤들을 드롭할 수 있는 공간을 제공하고, 컨트롤이 차지한 공간이 스크롤바 자체보다 클 때마다 스크롤바가 눈에 보이도록 확보하여 컨트롤을 항상 눈에 보이도록 스크롤 할 수 있도록 만드는 것 외에는 별다른 기능이 없는 작은 아이콘이다.


Grid 컨트롤

많은 양의 데이터를 표(tabular) 형식으로 나타내기 위해 주로 Grid를 사용할 것이다. 이는 일련의 행/열을 표시하는데, 아마도 제목이 있는 행/열일 것이다. 사용자는 화면보다 큰 데이터가 있을 경우 가로와 세로로 스크롤을 이용할 수 있다. Grid 셀에서 데이터를 편집하는 건 선택적이다.


라자루스는 Grid 컴포넌트에 세 가지 버전을 제공한다:

  • TDrawGrid 격자의 모든 셀(cell)을 프로그래머가 칠해야 한다.
    이 Grid 컴포넌트는 셀과 관련된 데이터를 보관할 장소가 없다.
  • TStringGrid 격자 내 각 셀과 문자열을 연관시키는 기능이 있으며, 문자열을 어떻게 표시하는지 안다.
  • TDBGrid 특수 데이터 인식 Grid이다. TDataset 자손으로부터 데이터를 표시하는 방법을 안다.


세 가지 Grid는 모두 TCustomGrid 의 자손들로, 그 기능 대부분은 이 공통 조상에서 구현된다.

프로퍼티 설명
AlternateColor AlternateColor 프로퍼티가 Color 프로퍼티와 다른 색상으로 설정 시, 격자는 행의 색상을 교대로 하여 표시될 것이다: 첫 행은 Color 프로퍼티 색상, 다음 행은 AlternateColor 색상 식으로.
AutoAdvance 셀의 내용이 편집된 경우, 사용자는 Enter 또는 Tab 키를 누르면 해당 프로퍼티는 다음으로 어떤 셀을 선택할 것인지 결정한다. 기본 값으로는 (aaRight) 현재 행에서 다음 셀에 해당하며, 행의 끝에 도달할 때까지 지속된다. aaNone 으로 설정 시 자동 진행(advance)을 비활성화시킨다.
AutoEdit 셀을 클릭하면 편집 모드가 된다. goAlwaysShowEditor 옵션과 주요 차이점은 후자를 이용 시 셀이 항상 편집 모드에 있다는 점이다. AutoEdit 는 셀을 클릭 시 편집 모드가 된다. AutoEdit 이나 goAlwaysShowEditor 둘 다 True 가 아닌 경우, 편집 모드에 들어가려면 셀을 두 번 클릭해야 한다: 첫 클릭은 셀을 선택하고 두 번째 클릭은 편집 모드이다.
AutoFillColumns True 로 설정 시, 열(column)들의 크기가 자동으로 조정되어 격자의 너비를 항상 완전하게 채운다. 모든 열은 균등하게 크기가 조정되지만 아래 설명된 프로퍼티들을 이용할 때와 다르게 정리된다.
ExtendedSelect 편집 가능한 셀에 대해 다중 셀을 선택할 수 있도록 해준다. 델파이에서는 편집 가능한 격자에 대한 범위 선택이 불가능하다.
Flat True 로 선택 시, flat look을 이용해 고정된 셀이 그려질 것이다. (해당 프로퍼티는 추가 TitleStyle 동작으로 대체되어 사라질 수도 있다).
HeaderHotZones 어떤 고정 셀이 핫 트래킹(hottracking)에 응답할 것인지 결정한다.
HeaderPushZones 어떤 고정 셀이 밀기(pushing)에 응답할 것인지 결정한다.
TitleStyle 고정 셀을 어떻게 그릴 것인지 결정한다. tsLazarus, tsNative, tsDefault 중 하나가 될 수 있다. tsLazarus 의 경우 flat look이 사용되고, Flat 프로퍼티는 무시된다.
UseXORFeatures True 로 설정 시, XOR 펜을 이용해 포커스 직사각형이 그려져 배경 색상이 무엇이건 시각적으로 표시될 것이다.
Options 델파이와 호환되는 옵션의 프로퍼티를 설정하며, 추가 가능성으로 확대된다. 값은 표 6.55에 열거되어 있다.
표 6.56: Grid에서 공통되는 프로퍼티


설명
goFixedVertLine 고정 셀 사이에 세로선을 그린다.
goFixedHOrizLine 고정 셀 사이에 가로선을 그린다.
goVertLine 일반 셀 사이에 세로선을 그린다.
goHorzLine 일반 셀 사이에 가로선을 그린다.
goRangeSelect 셀 범위 선택을 허용한다.
goDrawFocusSelected 포커스된 셀 주위에 사각형을 그린다.
goRowSizing 사용자가 개별 행마다 높이를 변경하도록 허용한다.
goColSizing 사용자가 개별 열마다 너비를 변경하도록 허용한다.
goRowMoving 사용자가 행을 이동하도록 허용한다.
goColMoving 사용자가 열을 이동하도록 허용한다.
goEditing 셀 내용의 편집을 허용한다.
goTabs 사용자가 Tab 키를 이용해 다음 셀로 이동하도록 허용한다.
goRowSelect 항상 완전한 행을 선택한다.
goAlwaysShowEditor 선택된 셀은 항상 즉시 편집 가능하다.
goThumbTracking 스크롤바 thumb로부터 위치를 올바르게 계산한다.
goColSpanning 해당 옵션은 Excel에서와 마찬가지로 텍스트가 주위 셀을 덮도록 허용한다. 셀이 그려지면 텍스트 사각형은 셀 텍스트를 모두 표시하기에 필요한 수만큼 열을 걸치도록 확장된다.
goDblClickAutoSize 해당 옵션은 스프레스시트를 가능하게 한다: 두 개의 열 헤더 셀 간 경계를 더블 클릭하면 열이 좌측으로 자동 크기 조절될 것이다. 열 너비는 열 내 가장 넓은 텍스트 엔트리와 일치하도록 변경될 것이다. 해당 옵션이 효과를 발휘하려면 goColSizing 옵션이 True 가 되어야 한다.
goFixedRowNumbering 활성화 시 행 번호가 첫 번째 고정 열에 표시될 것이다.
goHeaderHotTracking 활성화 시, 마우스 포인터가 최근 우치한 헤더 셀이 다른 색상으로 표시될 것이다. 핫 트래킹이 활성화된 셀은 HeaderHotZones 프로퍼티에서 명시할 수 있다.
goHeaderPushedLook 활성화 시 헤더 셀을 클릭하면 클릭 후 눌러진 버튼과 같은 모습일 것이다. 이를 활성화한 고정 셀은 HeaderPushZones 프로퍼티에서 명시할 수 있다.
goRelaxedRowSelect 해당 프로퍼티를 명시할 경우, 최근 선택된 셀이 나머지 행들과 도치되어 그려진다.
goScrollKeepVisible 해당 프로퍼티를 명시할 경우, 선택된 셀은 스크롤바를 스크롤할 때 격자의 상위 위치를 기준으로 동일한 위치에 유지된다. 기본 값으로, 선택된 셀은 다른 셀들을 따라 스크롤될 것이다.
goSmoothScroll 해당 옵션을 설정 시, 격자가 셀별로 스크롤된다. 단, 최상단 행은 항상 완전한 셀을 표시한다. 옵션을 설정 시, 격자는 픽셀별로 스크롤된다. goThumbTracking이 명시될 때만 효과가 나타난다.
표 6.57: Grid의 공통 옵션


TStringGrid 컴포넌트는 가장 쉬우면서 덜 복잡한 격자 컴포넌트이므로, 라자루스 격자의 프로퍼티를 살펴보는 데 사용된다.


격자의 기본 프로퍼티는 행과 열이다. TStringGrid 와 TDrawGrid 컨트롤에서 행의 수는 RowCount 프로퍼티로 결정된다: 이것은 격자에 표시될 행의 수를 나타낸다. 열의 수는 ColCount 프로퍼티에 의해 결정된다. 이러한 프로퍼티들을 설정 시 격자의 크기가 결정되고, 이는 원할 때 언제든 변경할 수 있다.


첫 행이나 열은 제목 행 또는 제목 열로 사용 가능하다. 격자가 너무 커서 사용자가 행이나 열을 스크롤해야 하는 경우, 이 제목 행 또는 열은 스크롤되지 않지만 고정되어 계속 표시된다. 고정된 열의 수는 FixedCol 프로퍼티에 의해 결정되고, 고정된 행의 수는 FixedRows 프로퍼티로 결정된다. 두 프로퍼티의 기본 값은 1이며, 행 또는 열의 수와 동일하거나 그보다 클 수 없다.


TStringGrid 내 데이터는 Cells 프로퍼티에 유지된다. 이는 문자열의 2차원적 배열 프로퍼티로, 아래와 같이 선언된다

Property Cells[ACol, ARow: Integer]: string;


Acol, ARow 색인의 범위는 0부터 각각 ColCount-1과 RowCount-1 까지다. 격자에 데이터를 표시하려면 Cells 프로퍼티를 셀에 표시해야 하는 문자열로 설정하기만 하면 왼다. 이는 코드에서 아래와 같이 선언된다:

  Var I : Integer;
begin
  GDays.Cells[0,0] := 'Year';
  For I := 1 to 12 do
    Gdays.Cells[i,0] := ShortMonthNames[I];


위의 코드는 월(month) 이름으로 된 격자의 첫 행과 'Year' 문자로 된 첫 열에 일치한다.


아래는 첫 번째 열에 연도를 열거할 것이다:

  Var I,R : Integer;
begin
  R := 1;
  For I := 2010 downto 1951 do
  begin
    GDays.Cells[0,R] := IntToStr(I);
    Inc(R);
  end;
end;


나머지 셀은 무작위 데이터로 채워지게 되는데, 그 해 해당 월 중에 비가 온 일수를 예로 들 수 있다:

  Var I,R : Integer;
begin
  For I := 1 to 12 do
    For R := 1 to 60 do
      GDays.Cells[I,R] := IntToStr(Random(MonthDays[False,i]));
end;


행과 열은 단일 할당문으로 설정할 수도 있는데, 이를 위해서 TStrings 인스턴스를 해당 행렬에 할당하면 된다. 예를 들어, Titles 가 만일 첫 (고정된) 행에 표시해야 할 제목을 가진 문자열리스트라면, 아래 코드가 제목을 설정하게 된다:

Titles.Add('Year');
For I := 1 to 12 do
  Titles.Add(ShortMonthNames[I]);
Gdays.Rows[0] := Titles;


이와 비슷하게, 첫 번째 열을 연도로 설정할 수 있다:

Titles.Clear;
Titles.Add('Year');
For I := 2010 downto 1951 do
  Titles.Add(IntToStr(I));
Gdays.Cols[0] := Titles;


효과는 위의 루틴과 동일하다.


격자에는 그 행위를 구성하기 위한 옵션들이 너무 많다. 첫 번째 살펴볼 것은 Options 프로퍼티로, 껐다가 켤 수 있는 옵션의 집합인데, 표 6.57에 설명하겠다. 그 외 옵션으로는 격자의 모양을 결정하기 위한 DefaultColWidth 와 DefaultRowHeight 가 있다. 이들은 격자 내에서 셀의 표준 너비와 높이를 결정한다. 기본적으로 열과 행은 모두 동일한 표준 높이 및 너비로 되어 있다.


goDblClickAutoSize 옵션은 고정 열이 아닌 열에만 적용된다. 다행히도 격자에는 열의 크기를 자동으로 조절하게끔 해주는 메소드가 있다. 아래 코드는 격자 내 모든 열의 크기를 내용의 크기에 알맞도록 조정해준다:

  Var I : integer;
begin
  For I := 0 to SGDemo.FixedCols-1 do
    SGDemo.AutoSizeColumn(i);
end;


격자의 AutoSizeColumns 메소드는 (끝에 's'가 붙어있음을 주목) 격자 내 모든 열의 크기를 자동 조절한다.


델파이의 TStringGrid 에 비할 수 있는 추가 프로퍼티들뿐 아니라 라자루스의 TStringGrid 또한 설계 시 편집할 수 있다. 컴포넌트 에디터를 이용해 격자 내 문자열을 설정할 수도 있는데 (격자 컴포넌트를 오른쪽 마우스로 클릭하여 디자이너 팝업 메뉴에서 이용) 이는 그림 6.44에 표시되어 있다.

그림 6.44: TStringGrid 에디터


델파이의 TStringGrid 와 가장 큰 차이점은 아마도 라자루스 구현이 Columns 프로퍼티를 제공한다는 점일 것이다: 격자 내 열의 프로퍼티들을 설명하는 TGridColumn 항목 집합체, TDBGrid 내에 있는 Columns 프로퍼티와 유사하다. 프로퍼티는 ColCount 프로퍼티와 상호 배타적이다:열이 사용되자마자 ColCount 프로퍼티는 더 이상 설정될 수 없다.


Columns 프로퍼티는 비고정 열만 설명한다. 즉, 2개의 고정 열과 (FixedColCount=2) 3개의 Columns 가 있다면, 격자는 5개의 열을 표시할 것이다. Columns.Enabled 프로퍼티는 열들이 사용 중인지를 결정한다. 아래 코드는 열을 정의하지 않고 격자를 열을 이용하는 격자로 변형한다:

  Var I,ACount : Integer;
begin
  ACount := SGDemo.ColCount-SGDemo.FixedColCount;
  SGDemo.Columns.Clear;
  For I := 1 to ACount do
    With TGridColumn(SGDemo.Columns.Add) do
      Title.Caption := 'Column ' + IntToStr(i);
end;


그림 6.45는 3개의 고정 행과 하나의 고정 열로 구성된, 월별 판매 수치를 보여주는 간단한 격자를 표시한다.

그림 6.45: 판매 수치를 보여주는 문자열 격자


편집하기

라자루스 TStringGrid 는 TInPlaceEditor 클래스를 델파이 격자에서 사용하는 것처럼 사용하지 않는다. 대신 TButton, TMaskEdit, 또는 TComboBox 컨트롤을 직접 사용한다. 이 컨트롤 중 셀에 무엇을 사용하는지는 TGridColumn 의 ButtonStyle 프로퍼티가 제어한다: 사용할 스타일은 격자 내 열별로 설정 가능하다. 편집 컨트롤의 모양은 격자의 프로퍼티에서 설정할 수 없다. 대신 OnSelectEditor 이벤트는 에디터를 표시하기 직전에 사용자가 정의(customize)하도록 해준다. 아래는 OnSelectEditor 이벤트 핸들러의 예제이다:

procedure TMainForm.DoSelectEditor(Sender: TObject;
                                   aCol, aRow: Integer;
  var Editor: TWinControl);
begin
  If Editor is TStringCellEditor then
    CustomizeEdit(aCol,ARow,Editor as TStringCellEditor)
  else
    if Editor is TButtonCellEditor then
      CustomizeButton(aCol,ARow,Editor as TButtonCellEditor)
    else
      if Editor is TPickListCellEditor then
        CustomizePickList(aCol,ARow,Editor as TPickListCellEditor);
end;


실제 에디터는 여러 다른 클래스 중 하나일 수 있기 때문에 Editor 인자(argument)는 TWinControl 타입이므로, 실제 타입으로 타입캐스트할 필요가 있겠다. TStringCellEditor, TButtonCellEditor, TPickListCellEditor 는 격자가 사용하는 TCustomMaskedEdit, TButton, TComboBox 의 자손들이다. 사용자 정의(customization)의 예제는 아래와 같다...

procedure TMainForm.CustomizeEdit(Acol,ARow : Integer;
                                  Editor : TStringCellEditor);
begin
  Editor.PasswordChar := '*';
  Editor.MaxLength := 5;
end;


그리고 이 효과는 그림 6.46처럼 나타난다.

그림 6.46: 사용자 정의 에디터


ColorBox 컨트롤

TColorBox 컨트롤은 TComboBox 의 자손으로, 사전 정의된 시스템 색상 리스트에서 하나의 색상을 선택하도록 해준다 (리스트의 항목 수는 그 Palette 프로퍼티가 결정한다). 각 색상은 이름으로 표시 되는데, 이름 앞에는 해당 색상의 작은 사각형이 붙어 있다. 선택된 색상은 Selection 프로퍼티에서 이용할 수 있으며, 읽기와 설정이 모두 가능하다. TColorListBox 와 마찬가지로 (다음 절에 설명) 표시된 색상은 Colors 배열 프로퍼티에서 이용하면 된다.


ColorListbox 컨트롤

TColorListbox 컨트롤은 TListbox 의 자손으로, 사전 정의된 시스템 색상 리스트에서 한 색상을 선택하도록 해준다 (리스트의 항목 수는 그 Palette 프로퍼티가 결정한다). 각 색상은 이름으로 표시 되는데, 이름 앞에는 해당 색상의 작은 사각형이 붙어 있다. 표시된 색상은 Colors 배열 프로퍼티에서 이용하면 된다ㅡ이는 리스트상자가 다중 색상 선택을 허용할 때 어떤 색을 선택할 것인지 결정 시 유용하다. 하나의 색상만 선택할 수 있다면 선택된 색상은 Selection 프로퍼티에서 이용할 수 있으며, 읽기와 설정이 가능하다. Style 프로퍼티는 특정 색상 그룹의 활성화에 사용되며, 사용자가 커스텀 색상을 정의하도록 허용할 것인지 결정한다.


CheckListBox 컨트롤

TListBox 의 MultiSelect 프로퍼티는 사용자가 리스트상자 내 항목을 하나 이상 선택할 수 있는지 결정한다. 사용자의 관점에서 볼 때는 TCheckGroup 컨트롤과 마찬가지로 자신이 선택하고자 하는 항목 옆에 체크상자를 두는 편이 나을 것이다. TCheckListBox 는 TListBox 의 자손으로, 앞에 체크상자가 있는 항목을 모두 표시한다. Checked 배열 프로퍼티를 이용해 각 체크상자의 상태를 확인할 수 있다. 아래 코드는 메시지 내 checklistbox에서 선택한 모든 항목을 표시한다.

procedure TMainForm.BShowClick(Sender: TObject);
  Var I : Integer;
      S : String;
begin
  S := SCheckedItems;
  For I := 0 to LBTest.Items.Count-1 do
    If LBTest.Checked[i] then
      S := S + sLinebreak+LBTest.Items[i];
  ShowMessage(S);
end;


단순히 모든 항목을 루프를 돌며, 하나씩 체크된 항목들을 저장한다. TCheckListBox 는 여전히 MultiSelect 프로퍼티를 가지며 Selected 배열은 그 조상 TListbox 에 존재함을 명심한다. Checked 와 Selected 프로퍼티는 서로 독립적이며, 같이 사용 가능하다.


Common Controls 탭

그림 6.47: 컴포넌트 팔레트의 Common Controls 탭
이름 설명
TTrackbar 정수 값을 설정하기 위한 트랙바(trackbar)
TProgressBar 진행 표시기.
TTreeview 아이콘과 텍스트로 이루어진 트리형 구조.
TlistView 여러 모드로 리스트를 나타내기 위한 구조.
TstatusBar 상태 표시.
Ttoolbar 버튼 바.
TUpdown 값의 증가/감소를 위한 한 쌍의 화살표.
TPageControl 탭 시트(tab sheet) 집합을 조직하는 컨트롤.
TTabControl 탭의 집합.
THeaderControl 열에 대한 헤더 집합.
TimageList 이미지 집합을 메모리 효율적 방식으로 유지하는 컴포넌트.
TPopupNotifier 툴팁을 표시하기 위한 컴포넌트.
TColorButton 색상 선택을 허용하는 TButton 자손.
TSpinEdit 정수 값의 선택, 증가/감소를 위한 화살표가 있는 편집 컨트롤.
TFloatSpinEdit 부동 소수점(float) 값의 선택, 증가/감소를 위한 화살표가 있는 편집 컨트롤.
TArrow 삼각형 형태로 된 화살표를 그린다.
TCalendar 일자 선택을 위한 달력 컨트롤.
TEditButton 버튼이 부착된 편집 컨트롤.
TFileNameEdit 파일명 선택을 위한 대화창이 뜨는 버튼이 부착된 편집 컨트롤.
TDirectoryEdit 디렉터리 선택을 위한 대화창이 뜨는 버튼이 부착된 편집 컨트롤.
TDateEdit 팝업 달력에서 일자를 선택하기 위한 버튼이 부착된 편집 컨트롤.
TCalcEdit 작은 계산기를 표시하는 버튼이 부착된 편집 컨트롤.
TFileListBox 디렉터리 내 파일의 리스트로부터 파일을 선택하기 위한 리스트상자.
TFilterCombobox 필터를 선택하기 위한 콤보상자.
TXMLPropStorage Published 프로퍼티 값을 XML 파일로 보관하기 위한 컴포넌트.
TINIPropStorage Published 프로퍼티 값을 .INI 파일로 보관하기 위한 컴포넌트.
TBarChart 막대 그래프를 표시하기 위한 컴포넌트 (히스토그램).
TButtonPanel OS 지침서에 따라 대화창에 표준 버튼을 표시하기 위한 패널.
TShellTreeView 디렉터리 구조를 표시하는 트리뷰.
TShellListView 디렉터리의 내용을 표시하는 리스트뷰.
TIDEDialogLayout IDE 대화창을 위한 StorageLayout 보관 상자.
표 6.58: Common Controls 탭의 컴포넌트


Trackbar

TTrackBar 컨트롤은 선택된 값으로 밀 수 있는 슬라이더(slider)를 이용해 정수 숫자를 명시하는 데에 사용할 수 있다. 슬라이더는 Orientation 값에 따라 수직 또는 수평 방향을 취할 수 있다. 선택된 값은 Position 프로퍼티에서 이용 가능하며, 이는 Min 과 Max 프로퍼티의 값 사이에 다양하게 나타날 수 있다. ScalePos 프로퍼티를 이용해 스케일(scale)의 위치를 설정할 수 있다: 슬라이더의 위 또는 아래. OnChange 이벤트는 사용자가 선택된 값을 변경 시 조치를 취하도록 사용할 수도 있다.


Prograssbar

진행 표시줄(progress bar)는 많은 점에서 TTrackBar 컨트롤과 닮았다. 하지만 TTrackBar 는 사용자의 값 설정을 허용하기 위해 사용되는 반면 TProgressBar 는 길 동작 중 얼마만큼의 부분이 완료되었는지를 사용자에게 보고하는 데 사용된다-사용자는 위치를 설정할 수 없다.


TTrackbar 컨트롤과 마찬가지로 진행 표시줄도 Position 프로퍼티의 값을 그래픽하게 표시하는데, 이는 Min과 Max 프로퍼티 사이에 위치한다.


Orientation 프로퍼티는 진행 표시줄의 방향을 결정한다. Smooth 프로퍼티가 False로 설정 시, 진행 바는 위치를 표시하기 위해 좀 더 작은 블록(block)을 사용한다. True 로 설정되었다면 solid bar를 그렸을 것이다. Solid bar가 사용될 경우, BarShowText 프로퍼티는 위치 또한 텍스트로 작성해야 하는지를 나타낸다. 마지막으로, Style 프로퍼티를 이용해 일반 진행 표시줄 또는 마퀴(marquee)의ㅡ이러한 경우 좌측에서 우측으로, 또는 우측에서 좌측으로 연속 이동하는 작은 블록의 역할을 한다ㅡ역할을 하는 진행 표시줄을 만들 수 있다.


Treeview 컨트롤

종종 애플리케이션은 계층적 구조를 표시할 필요가 있다: 로컬 하드 디스크의 디렉터리 구조; 책의 구조 (help 파일); XML 파일의 구조; 메일링 리스트 토론이나 뉴스그룹에서 스레드(thread). 그러한 구조들은 공통적으로 트리에 표시된다. TTreeView 컴포넌트가 그러한 용도로 설계되었는데, 트리 구조를 화면에 표시한다. 사용자는 트리 일부를 선택하거나 트리 내 항목들의 이름을 변경할 수도 있다. 트리의 각 가지 또는 잎은 TTreeNode 인스턴스가 표시한다. TTreeNode 인스턴스는 노드를 화면에 어떻게 표시할 것인지를 정의한다:

  • 노드와 관련된 텍스트.
  • 노드 앞에 표시되는 이미지.
  • 일반 이미지 옆에 표시되는, 노드의 추가적 상태 이미지.


뿐만 아니라, 임시 데이터는 각 TTreeNode 인스턴스와 관련이 있을 수 있다: 예를 들어, 표시되는 XML 문서의 XML 요소를 가리킬 수 있다. TTreeView 의 주요 프로퍼티를 표 6.59에서 설명하겠다.

프로퍼티 설명
AutoExpand 사용자가 트리 노드를 더블 클릭하면 자동으로 확장해야 하는가?
DefaultItemHeight 트리 내 항목의 기본 높이.
ExpandSignColor 노드 앞에 확장 부호의 색상.
ExpandSignType 사용한 확장 부호의 종류. tvestArrow (작은 화살표), tvestPlusMinus (플러스 마이너스 부호), tvestTheme (운영체제 테마에서 사용한 부호) 중 하나이다.
Indent 노드의 새로운 수준에 대한 들여쓰기 너비 (픽셀).
Images 트리노드에 표시되는 이미지를 포함한 이미지리스트.
Items 트리에 표시되는 TTreeNode 인스턴스의 (항목) 리스트.
Options 트리의 행위를 설명하는 옵션 리스트 (아래 표 참고).
ReadOnly True 로 설정 시, 노드의 캡션은 사용자가 변경할 수 없다.
RightClickSelect True 로 설정 시, 항목을 오른쪽 마우스로 클릭하면 선택된다.
RowSelect 항목을 선택할 때 현재 행 전체를 선택한 것으로 표시해야 하는가?
SelectionColor 선택된 노드의 색상.
ShowButtons False 로 설정 시, 확장/축소 부호가 축소 또는 확장 가능한 노드 앞에 그려지지 않을 것이다.
ShowLines 다양한 노드 사이에 선을 그려야 하는가 말아야 하는가?
ShowRoot 트리에서 모든 노드가 파생된 루트 노드를 (상위 노드) 표시해야 하는가?
SortType 트리를 어떻게 정렬할 것인가. stNone, stText, stData, stBoth 중 하나를 선택할 수 있다.
StateImages 노드 앞의 상태 아이콘에 사용할 수 있는 이미지리스트.
TreeLineColor 트리 노드 항목을 연결시키는 선의 색상.
TreeLinePenstyle 트리 노드 항목을 연결시키는 선의 스타일.
표 6.59: TTreeView의 주요 프로퍼티


트리뷰의 Options 프로퍼티는 옵션의 집합으로, 그 중 다수는 TTreeview 컴포넌트의 일반 프로퍼티와 일치한다. 가능한 값을 6.60에 열거하였다.

Options 설명
tvoAllowMultiselect 다중 노드를 선택하도록 해준다 (Ctrl-클릭 이용).
tvoAutoExpand AutoExpand 프로퍼티와 동일하다.
tvoAutoInsertMark 자동으로 마크를 삽입한다.
tvoAutoItemHeight 이미지 높이로부터 항목 높이를 자동으로 선택한다.
tvoHideSelection 트리에 포커스가 없을 때 선택내용을 숨긴다.
tvoHotTrack 트리의 스크롤이 동시에 일어난다.
tvoReadOnly ReadOnly 프로퍼티와 동일하다.
tvoRightClickSelect RightClickSelect 프로퍼티와 동일하다.
tvoRowSelect RowSelect 프로퍼티와 동일하다.
tvoShowButtons ShowButtons 프로퍼티와 동일하다.
tvoShowLines ShowLines 프로퍼티와 동일하다.
tvoShowRoot ShowRoot 프로퍼티와 동일하다.
tvoShowSeparators 노드 간 구분선을 표시한다.
tvoToolTips ShowHint 프로퍼티와 동일하다.
tvoNoDoubleClickExpand 더블 클릭 시 클릭된 노드를 확장 또는 축소하지 않는다.
표 6.60: TreeView의 Options 프로퍼티에 사용 가능한 값


노드 항목은 (TTreeNode 클래스) 그 모양을 제어하는 여러 프로퍼티를 가진다:

프로퍼티 설명
Caption 표시된 텍스트.
Expanded 노드의 확장 여부를 결정한다.
ImageIndex 노드가 정상적으로 표시될 때 표시할 이미지의 색인.
OverlayIndex 정상 이미지 상단에 표시될 이미지의 색인.
SelectedIndex 노드를 선택 시 표시할 이미지의 색인.
StateIndex 노드의 상태 이미지에 대한 색인.
Data 트리 노드와 관련되어야 하는 데이터로의 포인터.
표 6.61: 중요한 TTreeNode 프로퍼티

ImageIndex 와 SelectedIndex 이미지는 이미지리스트로부터 트리뷰의 Images 프로퍼티가 가리키는 것을 취한다. StateIndex 는 트리뷰의 StateImages 프로퍼티가 가리키며, 이미지리스트에 대한 이미지 색인을 의미한다.


StateIMage가 설정 시, 두 번째 이미지는 ImageIndex가 나타내는 이미지 옆에 표시될 것이다.


요소들로 Tree 채우기

Tree를 노드로 채우는 방법에는 두 가지가 있다. 첫째, 설계 시 Tree를 노드로 채우는 방법이다. Items 프로퍼티 에디터는 IDE 에서 Tree를 완전히 설계하도록 해준다. New Item 과 New SubItem 버튼은 각각 현재 수준 또는 그보다 하위 수준에서 새 항목을 생성하도록 해준다. 각 노드마다 세 개의 이미지 색인을 명시할 수 있는데 Apply 커튼을 누르는 즉시 TTreeView 인스턴스가 업데이트된다. 이 방법이 외에는, TTreeNodes 클래스의 메소드를 이용해 코드에서 Tree노드로 Tree를 채우는 방법이 있다. Tree를 채울 때 사용하는 기본 메소드는 AddChild 메소드이다:

function AddChild(ParentNode: TTreeNode; S: string): TTreeNode;


이 메소드는 ParentNode 아래에 캡션 S로 된 자식 노드를 추가하고, 새로 생성된 자식 노드를 리턴한다. ParentNode 가 Nil 일 경우, 노드는 Tree의 최상위 수준에서 추가될 것이다.


AddChild 메소드에 대해 여러 변형(variant)이 있는데, 약간씩 다른 기능을 제공한다:

function AddChildFirst(ParentNode: TTreeNode; S: string): TTreeNode;
function AddChildObject(ParentNode: TTreeNode; S: string; Data: Pointer): TTreeNode;
function AddChildObjectFirst(ParentNode: TTreeNode; S: string; Data: Pointer): TTreeNode;


AddChildFirst 는 새로운 노드를 첫 번째 자식 노드로서 추가한다 (기본 값은 노드를 끝에 추가하는 것이다).


AddChildObject 와 AddChilObjectFirst 는 동일한 작업을 수행하지만 새로 생성된 노드에 대한 Data 포인터를 명시할 수 있도록 해준다. 아래 호출은 SiblingNode 노드와 동일한 수준에서 새 노드를 추가한다:

function Add(SiblingNode: TTreeNode; S: string): TTreeNode;


노드는 마지막 노드로서 추가될 것이다. AddChild 메소드와 비슷하게 Data 포인터를 명시하도록 해주고 새 노드를 첫 노드로서 추가해주는 SiblingNode 변형 메소드가 몇 가지 있다:

function AddObject(SiblingNode: TTreeNode; S: string; Data: Pointer): TTreeNode;
function AddFirst(SiblingNode: TTreeNode; S: string): TTreeNode;
function AddObjectFirst(SiblingNode: TTreeNode; S: string; Data: Pointer): TTreeNode;


아래 코드는 Treeview를 디렉터리 Tree의 내용으로 채우는 방법을 설명한다:

Function TMainForm.ShowDirectory(Const ADir: String; TV: TTreeView;
                                 ParentNode: TTreeNode): Integer;
  Var I,II: Integer;
         N: TTreeNode;
         L: TStringList;
         D: String;
begin
  L := TStringList.Create;
  try
    Result := GetSubDirectories(ADir,L);
    if result > 0 then
    begin
      TV.Items.BeginUpdate;
      try
        For I := 0 to L.Count-1 do
        begin
          D := L[i];
          N := TV.Items.AddChild(ParentNode,D);
          D := IncludeTrailingPathDelimiter(ADir) + D;
          if ShowDirectory(D,TV,N) > 0 then
            II := 1
          else
            II := 0;
          N.ImageIndex := II;
          N.SelectedIndex := II;
        end;
      finally
      TV.Items.EndUpdate;
    end;
  end;
  finally
    L.free;
  end;
end;


TTreeNodes 클래스의 BeginUpdate 와 EnUpdate 메소드는 Tree 채우기를 최적화하는 데 사용되는데, 노드가 추가될 때 Tree가 스스로 다시 그리기 때문이다. (위의 예제에서와 같이) 많은 노드가 한 번에 추가되면 많은 깜박임이 일어나기 때문에 다시 그리기가 상당히 지체될 수 있다. BeginUpdate 와 EndUpdate 는 이를 막아준다. BeginUpate 를 호출하고 나면 EndUpdate 가 호출될 때까지 Tree 다시 그리기가 연기된다. BeginUpdate 를 한 번 이상 호출 시 EndUpdate 도 동일한 횟수로 호출되어야 한다.


위의 예제 코드는 ParentNode 노드 아래 노드에 주어진 디렉터리의 모든 하위디렉터리를 표시하기 위해 재귀적 기법을 사용한다. 그리고 결과적으로 하위디렉터리의 수를 리턴한다. 이 수는 각 디렉터리 노드에 표시된 이미지를 변경할 때 사용할 수 있다. 디렉터리가 자신의 하위디렉터리들을 포함한 경우, 노드에 대해 다른 이미지를 표시할 수 있다. SelectedIndex 는 ImageIndex 프로퍼티와 동일한 값으로 설정됨을 명심한다: 이를 어길 시 노드를 클릭하면 이미지가 사라진다. 결과는 그림 6.48과 같다.

그림 6.48: 디렉터리가 포함된 트리뷰 데모


Tree 순회하기

가끔씩은 Tree의 모든 노드를 순회할 필요가 있다-예를 들어 파일 또는 디렉터리가 변경되거나 사라졌는지 검사하거나, 각 노드로부터 데이터를 수집 하는 경우등.


TTreeNode 클래스는 이를 실행하는 다양한 메소드를 포함한다. 메소드들은 현재 코드와 동일한 수준에 있는 노드와 자식 노드들의 순회를 기반으로 한다:

function GetFirstChild: TTreeNode;
function GetNextSibling: TTreeNode;


첫 번째 자식은 현재 노드 아래의 첫 번째 노드이며, 다음 형제(sibling)는 동일한 수준에서 다음 노드를 가리킨다. 이 호출에 몇 가지 변형(variant)이 있다:

function GetLastChild: TTreeNode;
function GetLastSibling: TTreeNode;


이들은 현재 노드의 마지막 자식 노드를 리턴하거나, 현재 노드와 동일한 수준에서 마지막 노드를 리턴한다. 이 함수에 몇 가지 변형(variant)이 더 있지만 앞서 제공한 변형이 자주 사용하게 될 것들이다.


아래 간단한 코드에서는 이러한 메소드를 이용해 트리뷰에서 표시된 디렉터리 트리를 순회하고, 그것이 나타내는 디렉터리에 관한 통계를 이용해 각 노드를 업데이트한다:

procedure TMainForm.ShowDirectoryStatistics(ADir: String;
                                   N: TTreeNode; Var D,F: Integer);
  Var ND,NF : Integer;
       NDir : String;
begin
  While N <> Nil do
  begin
    NDir := ADir + N.Text;
    GetDirStats(NDir,ND,NF);
    N.Text := Format('%s (Files: %d, Dirs: %d)',[N.Text,NF,ND]);
    D := D + ND;
    F := F + NF;
    ShowDirectoryStatistics(NDir,N.GetFirstChild,D,F);
    N := N.GetNextSibling;
  end;
end;


부모 노드를 이용해 현재 노드의 전체 디렉터리명을 정할 수 있다:

Function TMainForm.GetPath(Node: TTreeNode): String;
begin
  Result := '';
  While ( Node <> Nil) do
  begin
    If (Result <> '') then
      Result := '/' + Result;
    Result := Node.Text + Result;
    Node := Node.Parent;
  end;
  Result := DEShow.Directory + Result;
end;


이를 이용하면 노드를 선택하자마자 폼의 캡션을 업데이트할 수 있다. 노드 선택이 변경되면 Treeiview 의 OnSelectionChange 이벤트가 트리거된다:

procedure TMainForm.TVDirsSelectionChanged(Sender: TObject);
  Var S : String;
begin
  S := GetPath(TVDirs.Selected);
  Caption := Format('%s : %s',[SCaption,S]);
end;


위에서 볼 수 있듯이, 트리뷰의 Selected 프로퍼티는 선택된 노드를 검색 시 사용된다. Selected 프로퍼티는 트리뷰에서 선택된 노드를 설정할 때 사용되기도 한다. Options 프로퍼티에서 tvoAllowMultiselect 가 선택된 경우 하나 이상의 노드를 선택할 수 있다. 각 노드는 부울(boolean) 프로퍼티 MultiSelected 를 가지는데, 이는 다중 선택을 이용해 하나의 노드만 선택할 경우 True 로 설정된다. 선택된 노드의 전체 리스트는 모든 노드를 살펴봄으로써 구성할 수 있다:

  Var I : Integer; Dirs : TStringList;
begin
  Dirs := TStringList.Create;
  Try
    For I := 0 to TVDirs.Items.Count - 1 do
      if TVDirs.Items[i].MultiSelected then
        Dirs.Add(GetPath(TVDirs.Items[i]));
    ShowMessage(SSelectedDirs + Dirs.Text);
  Finally
    Dirs.Free;
  end;
end;


Items 프로퍼티는 모든 노드를 포함하며 (Tree에서 자신의 구조와 상관없이), 자신의 MultiSelected 프로퍼티를 검사함으로써 선택된 노드의 리스트를-혹은 그들이 나타내는 디렉터리-구성할 수 있다. 이를 실행한 결과를 그림 6.49에 소개하겠다.

그림 6.49: 트리뷰에서 하나 이상의 디렉터리를 선택한 모습


사용자가 최근 선택된 노드를 변경하지 못하게 만드는 것도 가능한데, 이때는 OnChanging 이벤트를 사용하라. 이는 False 로 설정할 수 있는 AllowChange 파라미터를 가진다. False 로 설정 시, 최근 선택된 노드는 선택된 채로 남게 되며, 새 노드를 선택하더라도 마찬가지다:

procedure TMainForm.TVDirsChanging(Sender: TObject; Node: TTreeNode; var AllowChange: Boolean);
begin
  AllowChange := CheckAllowChangeGetPath(Node));
end;


AllowChangeDir 메소드는 선택된 디렉터리로 변경을 허용할 것인지 결정한다. Treeview의 편집에도 마찬가지다. 읽기 전용이 아니라면 (ReadOnly 프로퍼티는 기본적으로 False 로 설정) 사용자는 노드를 선택할 때 두 번째 클릭 시 노드의 텍스트를 편집할 수 있다. 그 때 OnEditing 이벤트가 트리거될 것인데, 이는 AllowEdit 파라미터를 가진다: 핸들러에서 False 로 설정 시, 트리뷰는 노드의 편집을 시작하지 않을 것이다. 만일 True 로 설정 시 (핸들러가 호출되었을 때 값), 트리뷰는 노드의 편집을 시작한다. 아래 이벤트 핸들러는 잎 노드에 해당하는 노드만 편집하도록 해주는데, 잎 노드는 자식 노드가 없는 노드를 일컫는다:

procedure TMainForm.TVDirsEditing(Sender: TObject; Node: TTreeNode; var AllowEdit: Boolean);
begin
  AllowEdit := (Node.GetFirstChild = Nil);
end;


사용자가 노드를 편집하고 나면 OnEdited 이벤트가 호출되고, 편집되던 노드뿐 아니라 노드의 새 텍스트 값이 전달된다. 이는 승인(confirmation)과 같은 액션을 실행 시 사용할 수 있다:

procedure TMainForm.TVDirsEdited(Sender: TObject; Node: TTreeNode;
                                                  var S: string );
  Var OldDir, NewDir, Msg: String;
begin
  OldDir := GetPath(Node);
  NewDir := ExtractFilePath(OldDir) + S;
  MSg := Format(SRenameDir,[OldDir,NewDir]);
  If Not ((mrYes = MessageDLG(Msg,mtConfirmation, [mbYes,mbNo],0))
     and RenameFile(OldDir,NewDir)) then
    S := Node.Text;
end;


위의 코드는 '디렉터리의 이름을 정말 변경할까요?'와 같은 승인을 요청할 것이다. 승인하지 않거나 재명명이 성공하지 않은 경우, 새로 입력한 값은 편집 동작 전에 다음 노드 값으로 리셋할 것이다.


The ListView

Treeview 컴포넌트의 동료(companion)로, Listview 컨트롤을 들 수 있다. 이는 윈도우 파일 익스플로러(Windows File Explorer)에 원점을 가지는데, 디렉터리 트리를 표시하기 위해 트리뷰가 사용되는 디렉터리의 내용을 표시하기 위해 리스트뷰를 사용하였다. 일반적으로 해당 컨트롤은 항목이 이름, 아이콘, 그리고 어쩌면 다른 속성(하위항목이라 불리는) 집합을 가진 항목의 리스트를 표시하는 데 사용된다. 본래 윈도우 익스플로러는 디렉터리의 내용을 볼 수 있는 보기 모드를 4가지 제공하였다 (최신 버전에선 더 많은 모드를 이용 가능). 이러한 모드 각각은 표시된 디렉터리에서 서로 다른 파일 세부내용을 열거하였다. 네 가지 보기 모드는 Listview 컨트롤의 ViewStyle에 가능한 값에서 선택한다: vsIcon (큰 아이콘 표시); vsSmallIcon (작은 아이콘 표시), vsList (간단한 리스트), vsReport (상세 보고서).

그림 6.50: 디렉터리 내용을 표시하는 TListView 컨트롤


리스트뷰 컨트롤을 사용하기 위해선 두 개의 클래스, TListView 컨트롤과 TListItem 클래스가 필요하다. TListItem 클래스는 리스트에 표시할 수 있는 항목을 나타낸다. TListItem 의 주요 프로퍼티를 표 6.62에 열거한다.

프로퍼티 설명
Caption 항목과 관련된 텍스트 (주로 파일명).
ImageIndex 이미지리스트에서 이미지의 색인.
SubItems 문자열 배열. vsList 또는 vsReport 모드일 때 구분된 열에 표시.
Data 포인터를 임시 데이터에 저장 시 사용됨.
Checked Listview 가 True 로 설정된 Checkboxes 프로퍼티를 가진 경우, 이 프로퍼티는 항목에 대한 체크상자가 체크되었는지 여부를 나타낸다.
표 6.62: TListItems의 주요 프로퍼티


위의 프로퍼티들은 이름만으로 기능이 어느 정도 설명된다.


TListView 컨트롤은 더 많은 프로퍼티들을 포함한다.

프로퍼티 설명
CheckBoxes 체크상자를 각 항목 앞에 표시하여 선택할 수 있도록 해야 하는가?
ColumnClick True 로 설정 시, 열 헤더의 클릭이 가능해지고, 클릭하면 OnColumnClick 이벤트가 트리거된다.
Columns 열 정의의 집합체. 리스트가 vsLIst 또는 vsReport 모드에 있을 때 해당 프로퍼티는 어떤 열을 실제로 리스트뷰에 표시할 것인지 정의한다. 정의된 내용이 없을 시 리스트 항목의 아이콘과 캡션만 표시될 것이다.
HideSelection True 로 설정 시, 리스트뷰에 포커스가 없다면 선택 내용은 하이라이트로 표시되지 않을 것이다.
Items 리스트뷰에 표시될 항목의 리스트 (각각 TListItem 항목).
LargeImages ViewStyle 이 vsIcon 일 때 사용할 이미지의 리스트. 리스트항목의 ImageIndex 프로퍼티는 리스트에 대한 색인이다.
MultiSelect True 로 설정 시, 리스트에서 다중 항목을 선택할 수 있다.
RowSelect True 로 설정 시, 세부내용(details) 또는 보고서 보기(report view)에서 전체 행이 선택된 것으로 표시된다.
False 로 설정 시, 캡션만 선택된 것으로 표시된다.
ShowColumnHeader 열 헤더를 보고서 보기(report view)에 표시해야 하는가?
SmallImages ViewStyle이 vsSmallIcon 일 때 사용해야 하는 이미지의 리스트.
Listitem의 ImageIndex 프로퍼티는 이 리스트에 대한 색인이다.
SortColumn 정렬해야 하는 열의 수.
SortType 사용할 정렬 방법. stText, stData, stBoth, stNone 중 하나를 선택 가능하다.
StateImages StateIndex 프로퍼티에서 참조하는 이미지리스트.
ViewStyle 사용할 뷰(view) 스타일.
표 6.63: TListView의 주요 프로퍼티


리스트뷰의 Items 프로퍼티는 프로퍼티 에디터를 이용해 설치 가능하다. 해당 프로퍼티 에디터는 그림 6.48과 같이 직관적이고 쉬운 인터페이스와 함께 Items 를 미리 준비할 수 있도록 해준다. 리스트의 모든 부분을 다룰 수 있다.

그림 6.51: 라자루스 IDE 내 Listview 에디터


실습에서 Items 프로퍼티는 코드에 주로 설치된다: Items 프로퍼티는 이에 필요한 메소드를 포함한다. 리스트뷰의 리스트 구조는 트리뷰의 트리 구조보다 더 간단하므로 그 인터페이스부도 더 단순하다:

function  Add: TListItem;
procedure AddItem(AItem: TListItem);
function  Insert(const AIndex: Integer): TListItem;
procedure InsertItem(AItem: TListItem; const AIndex: Integer);


Add 의 호출은 새 항목을 생성하여 리스트로 추가한다. 새로 생성된 항목이 리턴된다. AddItem 호출은 기존 항목을 리스트에 추가할 것이다. 두 번의 Insert 호출도 동일한 작업을 수행하지만, 단, 리스트 내 특정 위치에 항목을 추가한다. 항목의 삭제는 Delete 또는 Clear 호출을 이용한다:

procedure Clear;
procedure Delete(const AIndex: Integer);


업데이트를 많이 실행한 경우, BeginUpdate, EndUpdate 한 쌍의 호출에서 업데이트 동작을 포괄(enclose)하는 것은 훌륭한 실습이 된다:

procedure BeginUpdate;
procedure EndUpdate;


이는 항목이 추가되거나 제거될 때마다 리스트뷰가 스스로를 다시 그리지 않도록 만들어준다. 간단한 리스트와 같은(list-like) 인터페이스를 이용해 리스트뷰의 항목을 살펴볼 수 있다:

property Count: Integer;
property Item[const AIndex: Integer]: TListItem;


최종적으로, 아래 세 개의 호출을 이용해 리스트를 검색하는 것도 가능하다:

function FindCaption(StartIndex: Integer; Value: string; Partial, Inclusive, Wrap: Boolean; PartStart: Boolean = True): TListItem;
function FindData (const AData: Pointer): TListItem;
function IndexOf  (const AItem: TListItem): Integer;


첫 번째 호출 FindCaption 은 Value 와 동일한 캡션의 항목을 검색하는데, 검색은 StartIndex 항목에서 (Inclusive 가 True 로 설정 시) 시작되고, Inclusive 가 False 라면 그 다음 항목에서 시작된다. Partial 파라미터는 캡션이 부분적으로 일치할 수 있음을 명시하는 반면 Wrap 은 검색을 순환(wrap around)시키고 리스트 처음부터 새로 시작한다. PartStart 파라미터가 True 로 설정 시, 일치부분이 Caption 의 문자 위치 1부터 시작할 때에만 부분 일치를 일치로 간주한다.


FindData 호출은 AData 와 동일한 Data 포인터의 항목을 검색하고, 마지막으로 IndexOf 는 주어진 리스트항목의 색인을 리턴한다.


아래 코드 예제는 디렉터리의 내용을 표시한다. 각 파일에 대한 이름, 확장자, 마지막 수정일, 파일 크기, 파일 속성을 표시한다. 즉, 디렉터리 내용을 리스트나 보고서 보기(report view) 스타일로 표시하려면 5개의 열이 필요함을 의미한다. 이 열들은 Columns 프로퍼티 에디터를 이용하여 정의할 수 있는데, 각 열에 적절한 너비와 캡션을 할당하여 정의한다.

procedure TMainForm.ShowDirectory(ADir: String);
Var Info: TSearchRec;
begin
  Caption := Format(SCaption,[ADir]);
  ADir := IncludeTrailingPathDelimiter(ADir);
  With LVDemo.Items do
  begin
    BeginUpdate;
    try
      Clear;
      if FindFirst(ADir + AllFilesMask,faAnyFile,Info) = 0 then
        try
          Repeat AddFile(Info);
          Until (FindNext(Info) <> 0) ;
        finally
          FindClose(Info);
        end;
    finally
      EndUpdate;
    end;
  end;
end;


BeginUpdate/EndUpdate 두개의 사용을 주목하라. 항목을 리스트뷰로 실제 추가되는 것은 AddFile 호출에서 일어난다:

Function TMainForm.AddFile(Const Info: TSearchRec): TListItem;
begin
  Result := LVDemo.Items.Add;
  Result.Caption := Info.Name;
  LVDemo.ColumnClick;
  Result.ImageIndex := Ord((Info.Attr and faDirectory) = 0);
  With Result.SubItems do
  begin
    Add(ExtractFileExt(info.Name));
    Add(DateTimeToStr(FileDateToDateTime(Info.Time)));
    Add(AttrToStr(Info.Attr));
    Add(IntToStr(Info.Size));
  end;
end;


SubItems 프로퍼티는 TStrings 타입으로, 이를 채운다는 것은 다양한 파일 프로퍼티를 적절한 문자열로 변환하여 SubItems 리스트로 추가함을 의미한다. ListView는 그와 관련해 두 개의 이미지리스트를 가지는데, 하나는 작은 아이콘 뷰, 나머지는 아이콘 뷰에 해당한다. 각 이미지리스트는 두 개의 아이콘을 포함하는데, 하나는 디렉터리용, 하나는 일반 파일용이다 (실생활 애플리케이션에선 이미지 종류는 물론 파일 타입, 즉 그 확장자에 의해 결정된다).


=상태표시줄(Statusbar)

상태 표시줄Statusbar은 상태 정보, 즉 텍스트에서 커서의 현재 위치, 에디터의 삽입 또는 덮어쓰기 모드, 추가힌트와 같은 정보를 표시하기 위해 폼의 하단에 위치하는 것이 보통이다. 폼에 상태 표시줄을 드롭하면 폼의 하단에 자동으로 위치할 것이다. 툴바 컴포넌트와 마찬가지로 기본 위치일 뿐이다: 상태 표시줄은 Align 프로퍼티를 alNone 으로 설정한 후 위치 및 크기 프로퍼티를 설정함으로써 폼의 어떤 위치로든 설정 가능하다.


상태창에 관한 프로퍼티는 매우 소수에 불과한데 이를 표 6.64에 싣고자 한다. 가장 흥미로운 프로퍼티는 아마도 SimplePanel 일 것이다: True 로 설정 시, 상태 표시줄은 단일 패널의 역할을 하여 SimpleText 프로퍼티의 값을 표시한다. False 로 설정 시, Panels 프로퍼티에 정의된 바와 같이 패널이 표시된다; 이 패널들은 패널 에디터에서 정의되어야 하고 (간단한 집합체), 각 패널의 텍스트는 패널로의 색인 접근을 통해 설정 가능한데, Text 프로퍼티의 설정은 아래와 같다.

프로퍼티 설명
Panels 패널의 집합체로 (TStatusPanel 타입), 상태 표시줄에 표시된다. 각 패널은 Text 프로퍼티에 명시된 짧은 텍스트 문자열을 포함할 수 있다. 패널들은 디자이너에서 상태 표시줄을 더블 클릭하여 편집하면 된다. 이 프로퍼티는 패널 에디터를 표시하는데, 그림 6.52와 같다.
AutoHint True 로 설정 시, 해당 패널에 대한 ShowHint 의 설정 유무와 상관없이 현재 컨트롤의 힌트 프로퍼티가 상태 표시줄의 첫 패널에 표시될 것이다. 기본 값은 False 로 설정된다.
SimpleText SimplePanel 이 True 로 설정 시 패널에 표시되는 텍스트.
SizeGrip 해당 프로퍼티는 창 크기 손잡이(grip)를 상태 표시줄 하단 우측 모서리에 표시할 것인지를 결정한다. 창의 크기 조정에 사용되기도 한다.
표 6.64: TStatusBar의 프로퍼티


그림 6.52: IDE에서 상태 표시줄 에디터


때로는 애플리케이션에서 현재 활성 컨트롤 또는 창에 관한 힌트와 팁을 제공하는 데 패널이 사용되기도 한다. 각 컨트롤은 Hint 프로퍼티를 가지는데, 이 프로퍼티를 이용해 상태 표시줄에 정보를 표시할 수 있다. 전역 Application 객체의 OnHint 이벤트 핸들러를 이용해 상태 표시줄에 힌트를 표시하기도 한다. 마우스가 힌트가 있는 컨트롤 위에서 움직일 때마다 LCL는 이벤트 핸들러를 호출한다: Application.Hint 프로퍼티는 컨트롤에 대한 힌트를 포함하며, 아래와 같다:

procedure TMainForm.DoApplicationHint(Sender: TObject);
begin
  SBMain.Panels[1].Text := Application.Hint;
end;


위에서 볼 수 있듯이 두 번째 패널의 Text 프로퍼티는 (패널에는 0부터 번호가 매겨져 있다) 애플리케이션 힌트로 설정된다.

그림 6.53: 오브젝트 인스펙터에 표시된 상태 표시줄 패널의 프로퍼티


LCL의 훌륭한 기능으로, 컨트롤의 Hint 프로퍼티를 막대 | (파이프) 문자로 구분하여 두 부분으로 나눌 수 있다는 점을 들 수 있다: 파이프 문자 앞부분은 툴팁 풍선말로 표시된다. 문자 뒷부분은 Application.Hint 로 전달된다. 하나의 부분만 있을 경우 툴팁 풍선말과 애플리케이션 힌트 모두에 사용된다. 예를 들어, 아래의 힌트는:

'Save file|Save the file in the currently open window'


툴팁에 "Save file"을 표시하지만 상태 표시줄에는 "Save the file in the currently open window" 를 표시할 것이다.


툴바

메뉴에 더해 대부분 애플리케이션은 툴바를 포함하고 있다: 툴바는 메인 메뉴바 아래에 위치한 일련의 버튼들로 (각 버튼은 아이콘으로 표시), 가장 자주 사용되는 일부 액션으로 빠른 접근을 제공한다 (보통은 메뉴 어딘가에서 찾을 수 있는 액션). 보통은 버튼 이미지와 메뉴에 나타난 액션에 표시되는 이미지가 동일하다. 폼에 툴바를 드롭하면 자동으로 창의 윗면을 따라 정렬된다. 이를 변경하려면 Align 프로퍼티의 기본 값 aTop 에서 다른 정렬 값으로 변경하면 된다. 다른 컨트롤과 같이 툴바 또한 폼의 어디든 위치할 수 있지만, 기본 값은 창의 상단이다.


툴바에 버튼을 추가하려면 툴바를 오른쪽 마우스로 클릭하여 컨텍스트 메뉴에서 New button 항목을 선택하면 되는데, 이를 그림 6.54에 소개하겠다. 이를 실행하면 툴바에 버튼이 추가된다.

그림 6.54: 툴바에 관련된 IDE 컨텍스트 메뉴
스타일 설명
tbsButton 해당 툴버튼은 일반 속도버튼의 역할을 한다.
tbsCheck 해당 스타일로 된 버튼은 체크상자 역할을 한다. 예: 눌러진 채로 남는다.
tbsSeparator 클릭할 수 있는 버튼이 아니며, 버튼들 사이에 빈 공간이다.
tbsDivider tbsSeparator 와 유사하다. 빈 공간과 비슷하며 버튼들을 구분하는 데 사용된다. tbsSeparator 와 차이점은 시각적 모양이 다르다는 점으로, 기능은 정확히 동일하다.
tbsDropDown 해당 스타일로 된 버튼은 TPopupMenu 인스턴스가 있는 DropDownMenu 프로퍼티를 통해 연관된다. 버튼은 작은 화살표 이미지를 표시하고, 클릭하면 버튼 아래 팝업메뉴를 표시할 것이다.
표 6.65: TToolbarButton에 가능한 스타일


메뉴와 마찬가지로 툴버튼에 이미지를 설정할 수 있으려면 툴바의 Images 프로퍼티를 이미지리스트로 설정하고, 툴바버튼의 ImageIndex 프로퍼티를 리스트의 적절한 이미지에 대한 색인으로 설정해야 한다.


툴바는 버튼의 상태에 따라 다른 이미지를 표시할 수 있다: HotImages 프로퍼티는 마우스 커서를 여러 버튼 중 어떤 한 버튼 위에 있을 때 사용할 이미지의 리스트를 명시하고, DisabledImages 프로퍼티는 버튼이 비활성화되었을 때 표시해야 하는 이미지를 포함한다: 툴바 버튼의 ImageIndex 프로퍼티는 각 이미지리스트에 이미지를 위치시킬 때 사용된다.


툴바의 모양과 행위를 제어하는 프로퍼티들이 더 있다. 가장 중요한 프로퍼티를 표 6.66에 열거하겠다.

프로퍼티 설명
Flat True 로 설정 시, 버튼은 flat look(평평한 모양)을 가지고, 마우스를 위에 위치시켰을 때에만 입체적으로 바뀔 것이다.
EdgeBorders 해당 프로퍼티는 어떤 경계가 경사 (beveled) 모양을 하는지 결정한다. EdgeInner 와 EdgeOuter 프로퍼티는 베벨의 모양을 결정한다.
ShowCaptions 툴버튼의 Captions 의 표시 여부를 결정한다.
표 6.66: TToolBar의 주요 프로퍼티


코드를 이용해 툴버튼을 툴바로 추가할 수도 있다. 아래에 표시한 CreateExtraButtons 라 불리는 메소드는 이것이 어떻게 실행되는지를 보여준다. 툴바에 첫 번째 free 위치를 계산하면서 시작된다. 툴버튼은 툴바에 있는 컨트롤에 불과하므로, 툴바의 Controls array 프로퍼티에서 작은 루프를 돌리는 것만으로 첫 번째 free 위치를 결정하기에 충분함을 의미한다: 맨 오른쪽 버튼의 위치에 그 버튼의 너비를 더하면 된다.

procedure TMainForm.CreateExtraButtons;
  Var I,P : Integer;
        C : TControl;
        B : TToolbutton;
begin
  P := 0;
 // Calculate width of existing buttons. TBMain is the TToolbar instance
  For I := 0 to TBMain.ControlCount-1 do
  begin
    C := TBMain.Controls[i];
    If C.Left + C.Width > P then
    P := C.Left + C.Width;
  end;
 // Now create the new buttons starting at position P
  For I := 1 to 4 do
  begin
    B := TToolButton.Create(Self);
    B.Name := 'TBExtra' + IntToStr(i);
 // This places the toolbutton on the toolbar:
    B.Parent := TBMain;
    B.Left := P;
    B.Width :=TBMain.ButtonWidth; // Standard width
    B.ImageIndex := 4 + I;
    B.Caption := 'B' + IntToStr(i);
 // Eventhandler, executed when button is clicked
    B.OnClick := @ButtonClick;
    B.Tag := -1;
 // Go to next position.
    P := P + B.Width;
  end;
end;

버튼을 생성하여 툴바를 새 버튼의 부모로 설정함으로써 툴바에 버튼을 추가하는 방법도 있다. 나머지 코드는 오브젝트 인스펙터에서 설정하는 것과 마찬가지로 코드에 모든 프로퍼티를 설정하기만 하면 된다.


UpDown 컨트롤

TUpDown 는 사용자가 정수 값을 증가 또는 감소시킬 때 사용할 수 있는 화살표 버튼 한 쌍으로 구성된다. 화살표 방향은 Orientation 프로퍼티로 설정할 수 있다. 이는 Position 프로퍼티를 통해 값을 추적하는데, 이 값은 Min 과 Max 프로퍼티 사이의 값으로 다양하다. Increment 프로퍼티 값은 사용자가 위 또는 아래 방향 화살표를 클릭하면 얼마만큼 Position 을 증가시킬 것인지 결정한다. 폼에서 Associate 프로퍼티를 이용하는 컨트롤이라면 이 기능과 상관될 수 있는데, 항상 이 컨트롤에 스스로 정렬하게 될 것을 의미한다. AlignButton 프로퍼티는 관련 컨트롤의 어떤 면을 따라 스스로 정렬할 것인지를 결정한다.


Pages 컨트롤

TPageControl 컨트롤은 탭 시트(tab sheet)를 생성 시 사용된다. 각 탭 시트에서 (TTabSheet 클래스의 컨트롤) 탭은 Caption 과 함께 표시된다. 사용자가 탭을 클릭하면 관련 시트가 나타나면서 해당 탭 시트가 포함하는 컨트롤들을 표시한다.


폼에서 허용하는 양보다 표시할 정보가 더 많을 때 유용하다 (정보를 다수의 탭 시트에 분배할 수 있다). 예를 들어, 각 탭 시트를 이용해 하나의 문서에 관한 정보를 표시한다고 치자. 문서를 더 많이 열면 TPageControl 로 더 많은 탭 시트를 추가할 수 있다. 오늘날 대부분 인터넷 브라우저는 탭 시트를 이용해 여러 웹 페이지를 보유하는데, 적절한 탭을 클릭하여 한 번에 하나씩 표시할 수 있다.


페이지를 추가하려면 폼 디자이너에서 팝업 메뉴를 사용해야 한다. 활성 페이지를 리스트 내 다음 또는 이전 페이지로 전환할 때도 사용된다. 활성 탭 시트는 ActivePage 프로퍼티나 ActivePageIndex 프로퍼티를 이용해 설정할 수도 있다: 전자는 실제 TTabSheet 인스턴스를 포함하며, 후자는 단순히 탭 시트의 색인 번호만 포함한다. 사용자가 활성 탭을 변경하면 OnChange 이벤트가 호출된다 (ActivePage 프로퍼티는 이미 새 탭을 포함하고 있을 것이다). OnChange 이벤트 핸들러가 실행되기 전에 OnChanging 이베트 핸들러를 이용해 사용자가 실제로 탭을 변경하지 못하도록 막을 수 있다.


Tabs 컨트롤

TTabControl 컨트롤은 TPageControl 과 비슷하다. TPageControl 과 다른 점은 탭의 리스트만 표시한다는 점이다: 어떤 시트도 표시되지 않는다. 표시할 탭의 리스트는 단순한 문자열리스트로서, 리스트 내 각 행은 탭을 생성하는 데에 사용될 것이다.


사용자가 탭을 클릭하면 무엇이 실행되는지는 전적으로 프로그래머에게 달려 있다.


Header 컨트롤

THeaderControl 은 열 헤더의 폼을 표시하는 데 사용된다. Sections 프로퍼티는 표시할 헤더의 집합체이다. 각 THeaderSection 마다 ImageIndex, Text, test Alignment, Width, MinWidth, MaxWidth 를 명시할 수 있다. 사용자는 언제든 모든 열의 크기를 조정할 수 있다. THeaderControl 의 DragReorder 프로퍼티가 True 로 설정 시, 사용자는 헤더컨트롤의 열을 드래그해 재정리(reorder)할 수 있다. 헤더의 크기조정 또는 드래그에 응답하기 위한 여러 이벤트가 제공된다.


팝업 알림

TPopupNotifier 컨트롤은 그 자체가 컨트롤은 아니다ㅡ오히려 알림(notification) 팝업을 표시하여 (툴팁과 비슷하지만 더 크다) 알림 메시지를 나타내는 데 사용되는데, 가령 TTrayIcon 컨트롤과 함께 사용할 수 있겠다. 팝업은 작은 Icon 뿐만 아니라 Title, Text 도 가질 수 있으며, 화면 좌표를 X, Y 좌표로 둔 ShowAtPos (X,Y) 메소드로 나타낼 수도 있다. 작은 '닫기' 버튼을 포함하므로, 사용자는 알림을 닫을 수 있다 (또는 타이머를 사용해 주어진 시간 후 자동으로 닫을 수 있다).


Dialogs 탭

그림 6.55: 컴포넌트 팔레트의 Dialogs 탭


LCL은 네이티브 운영체제 대화창을 이용한다. 고유의 대화창을 생성하지 않는다. 따라서 사용자는 친숙한 대화창을 제공 받으므로 직관적으로 사용할 수 있다는 장점이 있다.


운영체제마다 많은 표준 대화창이 있는데, 가장 눈에 띄는 것은 파일과 디렉터리 선택 대화창이다. LCL은 이러한 대화창을 대화창 컴포넌트 집합에 캡슐화한다. 이용 가능한 대화창은 표 6.67에 소개되어 있다.


이들 각각은 최종 사용자에게 제공되는 특정 가능성과 시각적 모양을 제어하는 프로퍼티의 특정 집합을 가진다. 모두 TCommonDialog 컴포넌트의 자손들로, 아래와 같은 public 인터페이스를 가진다:

TCommonDialog = Class(TLCLComponent)
  function Execute: boolean; virtual;
  procedure Close; virtual;
published
  property OnClose: TNotifyEvent;
  property OnCanClose: TCloseQueryEvent;
  property OnShow: TNotifyEvent;
  property HelpContext: THelpContext;
  property Width: integer;
  property Height: integer;
  property Title: string;
end;


프로퍼티와 이벤트의 의미가 명확해야 하므로 Title 의 사용이 가장 유용할 것이다. 가장 중요한 메소드는 함수이다:

Function Execute: Boolean;


위의 함수는 사용자에게 대화창을 표시한다. 그리고 사용자가 대화창을 닫으면 리턴한다. 대화창이 적절하게 닫히면 True 를 리턴하고, 대화창을 취소하면 False 를 리턴한다.

컴포넌트 설명
TOpenDialog 디스크로부터 대화창을 선택하기 위한 대화창.
TSaveDialog 데이터를 저장할 파일명을 입력하기 위한 대화창.
TSelectDirectoryDialog 기존 디렉터리를 선택하기 위한 대화창.
TColorDialog 색상을 선택하기 위한 대화창.
TFontDialog 폰트를 선택하기 위한 대화창.
TFindDialog 검색 용어를 입력하기 위한 대화창.
TReplaceDialog 찾기와 바꾸기 용어를 입력하기 위한 대화창.
TOpenPictureDialog 디스크로부터 그림 파일을 선택하기 위한 대화창.
그림의 미리보기를 표시한다.
TSavePictureDialog 그림을 저장할 파일명을 명시하기 위한 대화창.
기존 그림의 미리보기를 표시한다.
TCalendarDialog 달력을 표시하여 사용자가 일자를 선택하도록 해주는 대화창.
TCalculatorDialog 계산기를 표시하기 위한 대화창.
사용자는 결과를 리턴하는 계산을 실행한다.
TPrinterSetupDialog 프린터 설치 대화창을 표시해 사용자가 프린터에 대한 다양한 프로퍼티를 설정하도록 해준다.
TPrintDialog 인쇄 대화창을 표시해 사용자가 사용할 프린터, 인쇄할 페이지 수, 그 외 인쇄 세부설정을 명시하도록 해준다.
TPageSetupDialog 인쇄 페이지 설정을 조작할 수 있는 대화창이 표시된다.
표 6.67: Dialogs 탭에서 찾을 수 있는 라자루스의 대화창 컴포넌트


Execute 메소드 대화창의 결과가 True 일 경우, 대화창의 프로퍼티는 사용자의 선택을 반영해 변경된다. 다양한 대화창 컴포넌트에 관련된 프로퍼티는 아래 표에 열거되어 있다:

컴포넌트 설명
TOpenDialog Filename
TSaveDialog Filename
TSelectDirectoryDialog Filename
TColorDialog Color
TFontDialog Font
TFindDialog FindText
TReplaceDialog FindText, ReplaceText
TOpenPictureDialog Filename
TSavePictureDialog Filename
TCalendarDialog Date
TCalculatorDialog Value
TPrinterSetupDialog 없음. 선택된 프린터는 Printers 유닛에서 설정됨.
TPrintDialog Copies, FromPage, ToPage, PrintRange, Collate
TPageSetupDialog 없음.페이지 설정은 Printers 유닛에서 설정됨.
표 6.68: 대화창이 닫힐 때 사용자 선택이 저장되는 대화창 프로퍼티


TOpenDialog 컴포넌트는 File→Open 메뉴 항목의 OnClick 핸들러에서 주로 사용될 것이며, 모양은 아래와 같을 것이다:

Procedure TMainForm.FileOpen(Sender: TObject);
begin
  If OpenDIalog1.Execute then
    OpenFile(OpenDialog1.FileName);
end;


이는 사용자에게 'Open file' 대화창을 표시할 것이며, 사용자가 파일을 선택하면 실제로 파일을 열기 위해 OpenDialog1 컴포넌트의 FileName 프로퍼티-이 프로퍼티가 실제로 선택된 파일을 포함한다-를 이용해 OpenFile() 메소드를 (프로그래머가 구현해야 하는) 호출할 것이다.


FileName 프로퍼티는 대화창을 표시하기 전에 설정할 수 있음을 명심한다. 이후 기본 파일명으로 제시될 것이다 (처음에 표시되는 디렉터리도 설정할 것이다). Open 과 Save 대화창에서는 파일 포맷을 선택하는 것이 일반적이다. 이는 대화창 내 콤보상자를 통해 이루어진다. 콤보상자의 내용은 Filter 프로퍼티가 결정한다. Filter 프로퍼티는 파일 확장자에 대한 하나 또는 이상의 파일 마스크를 포함한다. 마스크 중 하나를 선택하면 파일 대화창은 선택된 마스크에 일치하는 파일만 열거한다.


Filters 프로퍼티는 일련의 FileDescription | SearchMask 항목을 통해 구성된다. 파이프(|)부호 앞의 텍스트는 콤보상자에 표시되고, 두 번째 부분은 파일을 필터링하는 데 사용된다. 다중 파일 마스크를 명시하는 것도 가능한데, 그런 경우 세미콜론으로 (;) 구분되어야 한다. 다중 마스크를 명시해야 하는 경우 파이프(|) 부호로 구분된다. 가장 간단한 마스크는 아래와 같다:

OpenDialog1.Filter := 'All files|' + AllFilesMask;


AllFilesMask 상수는 시스템 유닛에서 정의된다: 윈도우의 경우 '*.*'를 포함하는데, 모든 파일을 의미한다. 유닉스와 같은 운영체제에선 '*'를 포함하는데, '*.*' 를 이용해 모든 파일을 표시하지 않기 때문이다.


두 타입의 파일을 표시하기 위해 결합된 필터를 아래와 같이 구성할 수도 있다:

OpenDialog1.Filter := 'Firebird and Interbase databases|*.gdb; *.fdb';


검색 대화창이 한 번에 하나의 타입으로 된 파일만 표시해야 하는 경우, 아래와 같이 Filter 프로퍼티를 구성해야 한다:

Opendialog1.Filter:='Firebird databases|*.fdb|Interbase Databases|*.gdb';


파일 기술에 파일 확장자를 표시하는 것도 유용하겠다:

OpenDialog1.Filter:='GIF images (*.gif)|*.gif'
  +'JPEG images (*.jpg/*.jpeg)|*.jpg;*.jpeg|'
  +'Tagged Image Format (*.tif/*.tiff)|*.tif;*.tiff'
  +'All files|' + AllFilesMask;


FilterIndex 프로퍼티를 이용해 기본 파일 필터 포맷을 선택할 수 있다. 다른 대부분 LCL 리스트와 달리 FilterIndex는 1을 기점으로 한다(1-based). 대화창을 열기 전에 설정 가능하며, 대화창이 닫힐 때 사용자가 선택한 필터로 설정될 것이다. 이와 같이 필터를 구성하는 것은 꽤 힘들긴 하지만 라자루스 IDE 는 이러한 작업을 훨씬 수월하게 해주는 필터 구성 대화창을 제공하며, 그림 6.56에 실려 있다.

그림 6.56: 파일명과 관련된 라자루스의 Filter 구성 대화창


TFileOpenDialog 는 표 6.69와 같이 많은 옵션을 가진다. 중요한 옵션 중 하나로 AllowMultiselect 를 들 수 있는데, 하나 이상의 파일 선택을 허용함을 대화창에 알리는 기능이다. 이를 사용할 경우 선택된 파일은 사용자가 대화창을 닫자마자 Files property (TStrings 타입) 를 통해 이용할 수 있다: 리스트 내 항목별로 하나의 파일. 이후 파일 열기는 루프에서 처리해야 한다:

  Var I : Integer;
begin
  With OpenDialog1 do
   If Execute then
     For I := 0 to files.Count-1 do
       OpenFile(Files[i]);
end;


OpenFile 메소드는 물론 프로그래머가 구현해야 한다.

Option 설명
ofAllowMultiselect 하나 이상의 파일을 선택할 수 있다 (대화창 열기만).
ofAutoPreview 위젯 셋이나 OS가 선택된 파일의 미리보기를 허용 시 미리보기를 표시한다.
ofCreatePrompt 기존 파일을 제외한 파일 선택 시, 파일을 생성해야 하는지 사용자에게 질문한다.
ofDontAddToRecent 선택된 파일을 '최근 파일' 리스트로 추가하지 않는다.
ofEnableIncludeNotify 라자루스에서 구현되지 않는다.
ofEnableSizing 파일 선택 다이얼(dial)의 크기 조정을 허용한다.
ogfExtensionDifferent 사용자가 다른 확장자로 된 파일을 선택하도록 해준다.
ofFileMustExist 선택된 파일이 디스크에 존재해야 한다.
ofForce 숨겨진 파일을 항상 표시한다.
ofHideReadOnly 읽기 전용 파일을 표시하지 않는다.
ofNoChangeDir 사용자가 InitialDir에 설정된 디렉터리를 변경하지 못하도록 한다.
ofNoDereferenceLinks Symbolic link를 변경하지 않는다.
ofNoLongNames 창에서만 해당: 파일명을 8.3 포맷으로만 표시한다.
ofNoNetworkButton windows만 해당: 네트워크 버튼을 비활성화한다.
ofNoReadOnlyReturn 사용자가 읽기 전용 파일을 선택하지 못하도록 한다.
ofNoTestFileCreate 디렉터리에 쓰기 권한을 테스트하기 위한 테스트 파일을 생성하지 않는다.
ofNoValidate 라자루스에서 구현되지 않는다.
ofOldStyleDialog 라자루스에서 구현되지 않는다.
ofOverwritePrompt 사용자가 기존 파일을 선택 시 덮어쓰기 경고 대화창이 표시된다.
ofPathMustExist 선택된 파일의 디렉터리가 존재해야 한다.
사용자가 파일을 선택하는 대신 파일 선택 창에 이름을 타이핑할 때만 사용한다.
ofReadOnly 창에서만 해당: 대화창에 '읽기 전용' 체크상자를 활성화한다.
ofShareAware 창에서만 해당: 사용자가 다른 애플리케이션에 이미 열린 파일을 선택 시 오류가 표시된다.
ofShowHelp 대화창에 '도움말' 버튼을 표시한다.
ofViewDetail '상세'보기에 파일을 표시한다.
표 6.69: TFileOpenDialog 옵션


이름 설명
TColorButton 색상 선택을 허용하는 TButton 자손.
TSpinEdit 정수 값의 선택, 증가/감소를 위한 화살표가 있는 편집 컨트롤.
TFloatSpinEdit 부동 소수점(float) 값의 선택, 증가/감소를 위한 화살표가 있는 편집 컨트롤.
TArrow 삼각형 형태로 된 화살표를 그린다.
TCalendar 일자 선택을 위한 달력 컨트롤.
TEditButton 버튼이 부착된 편집 컨트롤.
TFileNameEdit 파일명 선택을 위한 대화창이 뜨는 버튼이 부착된 편집 컨트롤.
TDirectoryEdit 디렉터리 선택을 위한 대화창이 뜨는 버튼이 부착된 편집 컨트롤.
TDateEdit 팝업 달력에서 일자를 선택하기 위한 버튼이 부착된 편집 컨트롤.
TCalcEdit 작은 계산기를 표시하는 버튼이 부착된 편집 컨트롤.
TFileListBox 디렉터리 내 파일의 리스트로부터 파일을 선택하기 위한 리스트상자.
TFilterCombobox 필터를 선택하기 위한 콤보상자.
TXMLPropStorage Published 프로퍼티 값을 XML 파일로 보관하기 위한 컴포넌트.
TINIPropStorage Published 프로퍼티 값을 .INI 파일로 보관하기 위한 컴포넌트.
TBarChart 막대 그래프를 표시하기 위한 컴포넌트 (히스토그램).
TButtonPanel OS 지침서에 따라 대화창에 표준 버튼을 표시하기 위한 패널.
TShellTreeView 디렉터리 구조를 표시하는 트리뷰.
TShellListView 디렉터리의 내용을 표시하는 리스트뷰.
TIDEDialogLayoutStorage IDE 대화창을 위한 레이아웃 보관 상자.
표 6.70: 컴포넌트 팔레트의 'Misc' 탭에서 발견되는 컴포넌트


Misc 탭

그림 6.57: 컴포넌트 팔레트의 Misc 탭


Misc 탭은 그 이름에서 알 수 있듯이 다양한 컴포넌트를 포함한다. 그 중 대부분은 특별 기능을 가지는데, 아래에서 간략히 소개하고자 한다.


특수화된 편집 컨트롤

TEdit 와 TMemo 컨트롤은 기본 편집 컨트롤이다. 하지만 그 외 다른 편집 컨트롤들도 있으며, 모두 TCustomEditButton 컨트롤에서 파생된다. 이 컨트롤은 일반 편집 컨트롤이지만 클릭이 가능한 속도버튼 컨트롤이 붙어있다. 라자루스와 함께 제공되는 컨트롤에서는 버튼을 이용해 대화창을 팝업시킨다. 대화창의 결과는 (일부 폼에서) 편집 텍스트로 저장된다. TEditButton 컨트롤은 TCustomEditButton 자손으로, 새로 도입된 프로퍼티와 이벤트만 publish한다. 이러한 프로퍼티를 표 6.71에 소개하겠다.

프로퍼티 설명
ButtonWidth 속도버튼의 너비. 높이는 항상 편집 컨트롤의 높이와 같다.
ButtonOnlyWhenFocused True 로 설정 시, 속도 버튼은 편집 컨트롤에 포커스를 둔 경우에만 표시된다.
DirectInput True 로 설정 시, 사용자는 편집 컨트롤에 값을 입력할 수 있다.
False 로 설정 시, 편집 컨트롤에 내용을 입력하는 유일한 방법은 속도버튼을 이용하는 것으로, 입력할 값에 대한 제어력을 더 많이 제공한다.
Flat True 로 설정 시, 속도 버튼은 평평한 모양(flat look)을 한다.
Glyph 버튼에 표시된 이미지를 포함한다.
NumGlyphs 글리프 내 이미지 수.
OnButtonClick 사용자가 속도버튼을 클릭할 때 트리거되는 이벤트.
표 6.71: TEditButton 프로퍼티


OnButtonClick 이벤트는 보통 사용자 입력을 요청하는 대화창을 팝업시켜 그 사용자 입력내용을 바탕으로 한 값으로 편집 컨트롤의 텍스트를 채울 때 사용된다:

procedure TMainForm.ETestButtonClick(Sender: TObject);
  Var S: String;
begin
  S := ETest.Text;
  If InputQuery(SPromptCaption,SPrompt,S) then
    ETest.Text = S;
end;


InputQuery 호출은 LCL에서 표준 호출로, 아래와 같이 선언된다:

Function InputQuery(Const ACaption, APrompt: String; Var AValue: String): Boolean;


이는 ACaption 캡션과 함께 표시되어 사용자에게 문자열을 입력하라는 APrompt 메시지를 보낸다. 문자열이 AValue 내에 리턴된다. 함수가 호출될 때 AValue 가 비어있지 않은 경우 기본 값으로 설정된다. 사용자가 OK 버튼으로 대화창을 끝낼 경우 함수는 True 를 리턴하고, 아닐 경우 False 를 리턴한다.


TCustomEditButton 에서 파생되는 컨트롤들을 표 6.72에 소개하겠다.

컨트롤 설명
TFileNameEdit 팝업된 대화창은 파일명 대화창들 중 하나이다. 대화창이 닫히면 선택된 파일명은 편집 컨트롤의 텍스트로 설정된다. 컨트롤은 표시되는 대화창의 유형을 제어하는 추가 프로퍼티를 비롯해 파일 대화창의 공통 프로퍼티를 가진다. 추가 이벤트 OnAcceptFileName 또한 가지는데 이를 이용해 선택된 파일명을 확인하고 어쩌면 변경까지 가능할 것이다.
TDirectoryEdit 팝업된 대화창은 디렉터리 선택 대화창이다. 대화창이 닫히면 선택된 디렉터리는 편집 컨트롤의 텍스트로 설정된다. 컨트롤은 디렉터리 대화창의 모양을 제어하는 추가 프로퍼티를 가진다.
TDateEdit 속도버튼을 클릭하면 작은 달력이 팝업되어 사용자가 일자를 선택할 수 있다. 선택된 일자는 편집 컨트롤의 텍스트로 설정된다.
TCalcEdit 속도버튼을 클릭하면 작은 계산기가 팝업되고, 사용자는 계산을 실행할 수 있다.

계산된 값은 편집 컨트롤의 텍스트로 설정된다.

표 6.72: TCustomEditButton에서 파생된 LCL 컨트롤


클래스 계층구조 차트에 나타나지 않는 두 개의 편집 컨트롤이 있다: TSpinEdit 와 TFloatSpinEdit. 이 컨트롤들은 정수 또는 부동 소수점 값의 편집에 유용하다. 이러한 컨트롤에는 위, 아래 방향키가 부착되어 있고 키를 이용해 편집 컨트롤에 표시된 값을 증가하거나 감소시킬 수 있다. 위의 리스트엔 표시되어 있지 않은데, TCustomEdit 로부터 파생되지 않기 때문이다. 대신 TWinControl 에서 직접 파생된다. 그럼에도 불구하고 이 컨트롤들은 TCustomEdit 컨트롤과 거의 동일한 프로퍼티들을 가지며, 모양을 제어하는 추가 프로퍼티들도 포함한다. 그 프로퍼티를 표 6.73에 소개하겠다.

프로퍼티 설명
Decimals 컨트롤에 표시되는 소수 자리의 수-해당 프로퍼티는 TFloatSpinEdit 컨트롤에만 존재한다.
Increment 위, 아래 방향키 중 하나를 클릭할 때 컨트롤에 표시된 값의 증가/감소량.
MaxValue 컨트롤에 표시할 수 있는 최대 값.
MinValue 컨트롤에 표시할 수 있는 최소 값.
표 6.73: TSpinEdit과 TFloatSpinEdit에 대해 선택된 프로퍼티


ColorButton

TColorButton 은 색상을 입힌 직사각형을 표시하는 간단한 버튼이다. 버튼을 클릭하면 색상 선택 대화창이 뜨면서 사용자가 색상을 선택하도록 해준다. 선택된 색상은 버튼의 ButtonColor 프로퍼티를 통해 이용할 수 있다. 기본 값으로는 기본 프로퍼티가 있는 TColorDialog 를 이용해 색상을 선택한다. 좀 더 정교한 컨트롤이 필요하다면 ColorDialog 프로퍼티를 이용해 사용자가 색상을 선택하도록 해주는 (적절하게 구성된) TColorDialog 컨트롤을 명시할 수 있다: 이후 사용자 정의(customized) 대화창을 이용해 사용자에게 사용 색상을 선택할 수 있도록 해줄 것이다.


Arrow 컨트롤

TArrow 는 스크롤바 또는 TUpDown 컨트롤에 사용되는 화살표와 같은 화살표를 그릴 때 사용된다. 화살표는 클릭 가능하며, OnClick 이벤트를 트리거한다. 화살표의 방향은 ArrowType 프로퍼티를 이용해 설정 가능하며, 그 모양은 ShadowType 프로퍼티를 이용해 변경할 수 있는데, 이는 화살표를 3-D 모양으로 만들 때 사용된다.


달력 컨트롤

TCalendar 컨트롤은 폼에 드롭할 수 있는 간단한 달력 컨트롤이다-TCalendarEdit 팝업에서와 동일한 달력이다. 선택된 데이터는 Date 프로퍼티를 통해 설정 및 검색할 수 있다. DisplaySettings 프로퍼티를 이용해 여러 개의 달력 옵션을 설정할 수 있다 (월요일부터 시작할 것인지, 주별 번호(week number)를 표시해야 하는지 등).


File Listbox 컨트롤

TListBox 의 또 다른 자손으로 TFileLIstBox 를 들 수 있는데, 이는 디렉터리로부터 파일 리스트를 표시하여 사용자가 하나 또는 이상의 파일을 사용하도록 해준다. 세 가지 프로퍼티들은 파일의 어떤 리스트를 표시할 것인지 결정하는데, 표 6.74에 싣겠다. 선택된 파일은 최근 선택된 파일 이름을 포함하는 Filename 프로퍼티를 통해 이용 가능하다. UpdateFileList 메소드는 파일 리스트를 업데이트 하는 데 사용할 수 있다. 아래 나타난 프로퍼티 중 하나가 변경되면 자동으로 호출된다.

프로퍼티 설명
Directory 표시해야 하는 파일의 디렉터리. 최근 라자루스 버전은 해당 프로퍼티를 publish하지 않으므로 런타임 시에 설정되어야 한다.
FileType 파일이 리스트상자에 표시되기 위해 필요로 하는 속성. 값은 SysUtils 유닛에서 찾을 수 있는 FindFirst와 FinNext 호출에 사용되는 값과 일치한다.
Mask SysUtils 유닛의 FindFirst 호출에서 사용되는 파일 마스크 사양. 여기에 경로를 명시하지 않도록 한다.
표 6.74: 흔히 사용되는 TFileListBox의 프로퍼티


FilterCombobox

TFilterCombobox 는 간단한 TComboBox 자손으로, 사용자로 하여금 필터리스트에서 필터를 선택할 수 있도록 해준다. Filters 프로퍼티는 TOpenDialog 혹은 TSaveDialog 컴포넌트에서와 마찬가지로 파일명 마스크의 리스트를 포함하는 문자열로 설정할 수 있다. 사용자에게 선택 가능한 필터의 설명이 표시되고, 선택된 필터에 해당하는 파일 마스크는 Mask 프로퍼티로 검색할 수 있다.


BarChart

TBarChart 를 이용해 어느 종류의 숫자형 데이터든 그로부터 간단한 막대 그래프를 (히스토그램) 생성할 수 있다. Bars 프로퍼티는 표시될 막대의 집합체이다. 집합체 내 각 항목은 그래프에서 막대를 그리는 데 사용될 Caption, Value, Color 를 명시할 수 있다. Depth 프로퍼티는 막대의 시각적 깊이를 조정하고, LabelPosition 은 막대의 캡션을 표시할 장소를 결정한다.


버튼 패널

TButtonPanel 은 4개 버튼의 표준화 버전을 포함한다: 이는 OK, Cancel, Close, Help 버튼을 표시할 수 있으며, 그것이 실행되는 플랫폼에 대한 GUI 설계 규칙을 따른다. 버튼은 기능에 일치하는 올바른 아이콘과 함께 올바른 순서로 표시된다. 이를 대화창 폼에 이용해 GUI 설계 규칙을 따라 일관된 모양을 생성할 수 있다.


Data Controls 탭

Data Controls 탭은 데이터베이스에 데이터를 표시 및 편집하기 위한 시각적 컨트롤들을 포함한다: 데이터셋 컴포넌트와 통신하므로, TDataset 자손을 이용할 수 있다면 어떤 데이터베이스든 함께 사용할 수 있다. 이러한 컨트롤들은 컴포넌트 팔레트의 다른 탭에서 이용 가능한 컨트롤들의 자손들로, 데이터 소스로부터 내용을 취할 수 있다는 점을 제외하곤 어떠한 새 기능도 도입하지 않는다. 데이터베이스 접근은 12장에서 상세히 논하겠다.

그림 6.58: 컴포넌트 팔레트의 Data Controls 탭에서 이용 가능한 컨트롤


Data Access 탭

Data Access 탭은 데이터베이스 내 데이터로 접근하도록 해주는 컴포넌트를 포함한다. 그들은 데이터베이스와 컨트롤 간 연결을 구축하여 실제로 데이터의 표시 및 편집을 허용한다. 이러한 컨트롤들은 Data Controls 탭에서 이용 가능하다. Data Access 탭은 단층 파일(flat-file) 데이터베이스로 접근을 허용하는 컴포넌트들을 포함하는데, 표 6.75에서 소개하겠다. 다른 데이터 소스들도 설치할 수는 있지만 이들은 다른 탭에 위치한다.

그림 6.59: 컴포넌트 팔레트의 Data Access 탭에서 이용 가능한 컴포넌트


이름 설명 패키지
TDatasource 시각적 컨트롤을 데이터셋(dataset)으로 연결한다. FCL
TSDFDataset CSV (콤마로 구분된 값) 파일에 대한 데이터셋. SDFLaz
TFixedFormatDataset 너비가 고정된 텍스트 파일에 대한 데이터셋. SDFLaz
TMemDataset 파일은 없지만 메모리에 데이터를 보관하는 데이터셋. MemdsLaz
TDBF dBase와 Foxpro 파일을 처리하는 데이터셋. DBFLaz
TParadox Paradox 파일을 읽는 데이터셋. Lazparadox
표 6.75: Data Access 탭에서 찾을 수 있는 컴포넌트


System 탭

그림 6.60: 컴포넌트 팔레트의 'System' 탭에서 이용 가능한 컴포넌트


컴포넌트 팔레트의 System 탭은 여러 가지 면에서 도움이 되는, 주로 비시각적인 컴포넌트를 제공하며, 운영체제의 일부 부분에 추상화된 프로그래밍 인터페이스를 제공한다. 컴포넌트는 표 6.76에 열거된다.

컴포넌트 설명
TTimer 주기적으로 이벤트를 트리거하는 컴포넌트.
TIdleTimer 애플리케이션이 유휴상태(idle)가 될 때 이벤트를 트리거하는 컴포넌트.
TLazComponentQueue 스트림(stream)으로부터 또는 스트림으로 컴포넌트를 읽는 (혹은 쓰는) 컴포넌트.
THTMLHelpDatabase 온라인 도움말을 HTML 파일로 관리하는 컴포넌트.
THTMLBrowserHelpViewer HTML 브라우저를 이용해 도움말을 표시하는 컴포넌트.
TAsyncProcess 다른 프로그램들을 실행하기 위한 컴포넌트, non-blocking.
TProcessUTF8 Process 와 같지만 UTF-8 지원.
TProcess 다른 프로그램들을 실행하기 위한 컴포넌트, non-blocking.
TSimpleIPCClient 메시지를 TSimpleIPCServer 로 전송하기 위한 컴포넌트.
TSimpleIPCServer 클라이언트 애플리케이션으로부터 메시지를 수신하기 위한 컴포넌트.
TXMLConfig TIniFile 과 유사, 구성 데이터를 저장하기 위한 컴포넌트.
TEventLog 시스템 로그에 쓰기 위한 컴포넌트.
표 6.76: System 탭에서 이용 가능한 컴포넌트


Synedit 탭

그림 6.61: 컴포넌트 팔레트의 'Synedit' 탭에서 이용 가능한 컴포넌트


SynEdit 탭은 SynEdit 패키지로부터 컴포넌트를 포함하는데, 에디터에 구문 하이라이트를 추가 시 사용할 수 있는 두 개의 시각적 컨트롤, TSynEdit 와 TSynMemo 를 포함한다. 두 컨트롤은 우리에게 좀 더 친숙한 TMemo 컴포넌트와 비슷하게 실행되지만 에디터의 모양을 제어하는 옵션을 추가로 제공한다. 그 외 SynEdit 컴포넌트들은 비시각적 컴포넌트들로, TSynEdit 또는 TSynMemo 컨트롤로 구문 하이라이트 규칙을 추가하거나, HTML로 내보내기, 자동완성, 매크로 기록하기와 같은 추가 기능도 제공한다. 이러한 컴포넌트들을 표 6.77에 소개하겠다.

이름 설명
TSynEdit 실제 에디터.
TSynAutocomplete TSynEdit 에 대해 자동완성 지원.
TSynExporterHTML 하이라이트된 소스를 HTML로 내보내기 위한 컴포넌트.
TSynMacroRecorder 에디터에 대한 매크로 기록 기능.
TSynMemo TSynEdit 와 유사하지만 TMemo 인터페이스를 제공.
TSynPasSyn 파스칼 구문 규칙.
TSynFreePascal SynPascal 구문 규칙, 프리 파스칼 향상(enhancements) 지원.
TSynCppSyn C++ 구문 규칙.
TSynJavaSyn Java 구문 규칙.
TSynPerlSyn Perl 구문 규칙.
TSynHTMLsyn HTML 구문 규칙.
TSynXMLSyn XML 구문 규칙.
TSynLFMSyn LFM (라자루스 폼) 구문 규칙.
TSynUnixShellScriptSyn Unix 셸 스크립트 구문 규칙.
TSynCssSyn CSS 데이터 구문 규칙.
TSynPHPSyn PHP 구문 규칙.
TSynTexSyn TeX 구문 규칙.
TSynSQL Syn SQL 구문 규칙.
TSynPython SynPython 구문 규칙.
TSynVBSyn Visual Basic 구문 규칙.
TSynAny SynUser 정의의 구문 규칙, IDE에서 구성 가능.
TSynMulti SynUser 정의의 구문 규칙, 파일로부터 로딩 가능.
표 6.77: 컴포넌트 팔레트의 SynEdit 탭에서 이용 가능한 컴포넌트


Notes