먼저 Microsoft Visual Studio.NET 통합 개발 환경에서 Windows Forms 응용 프로그램을 만드는 것부터 출발합시다. 메뉴에서 [파일]=>[새로만들기]=>[프로젝트]를 선택하세요. 그리고 새 프로젝트 창에서 Windows Forms 응용 프로그램을 선택하여 프로젝트 명을 입력하여 프로젝트를 생성합니다.
*개발 도구 버전에 따라 다를 수 있지만 학습하는데 큰 지장은 없습니다.*
프로젝트를 생성하면 [그림 1.3]과 같은 초기 화면이 나타납니다. 그리고 이 상태에서 실행(Ctrl + F5)하면 하나의 창이 뜨는 간단한 응용 프로그램이 동작합니다. 개발자가 코드를 작성한 부분이 없어 특별한 동작은 하지 않지만 가장 가벼운 형태의 윈도우즈 응용 프로그램이 만들어 진 것입니다.
이제 마법사에 의해 만들어진 것들이 무엇인지 살펴봅시다.
[메뉴]=>[보기]=>[솔루션 탐색기]를 선택하여 솔루션 탐색기 창을 보면 트리 형태로 솔루션 노드 자식으로 프로젝트 노드를 확인할 수 있습니다. 그리고 프로젝트 노드에는 Properties와 참조, Form1.cs, Program.cs 노드가 나타납니다.
Properties 노드에서는 프로젝트의 어셈블리 정보 및 리소스, 설정에 관한 정보를 빠르게 확인 및 편집할 수 있습니다.
AssemblyInfo.cs 파일에는 프로젝트의 어셈블리 정보들이 들어있습니다. 이 부분은 개발자가 직접 작성하는 것보다 프로젝트 속성 창에서 설정하면 마법사에 의해 자동으로 편집해 주는 것을 그대로 사용하는 것이 일반적입니다. 이 책에서도 앞으로 이 부분에 관한 내용은 다루지 않을 것입니다.
Resources 부분은 프로그램에서 사용할 이미지나 문자열 등의 자원에 관한 부분입니다. Settings 부분은 응용 프로그램의 속성 설정과 기타 정보를 동적으로 저장하고 검색할 수 있는 기능입니다. 프로젝트 속성 창의 설정 탭에서 편집할 수 있으며 자세한 내용은 MSDN의 응용 프로그램 설정을 참고하시기 바랍니다. 이 책에서는 이 부분은 별도로 다루지 않습니다.
다음은 AssemblyInfo.cs 소스 파일의 코드 내용입니다.
using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; // 어셈블리의 일반 정보는 다음 특성 집합을 통해 제어됩니다. // 어셈블리와 관련된 정보를 수정하려면 // 이 특성 값을 변경하십시오.
[assembly: AssemblyTitle(“FirstApp”)]
[assembly: AssemblyDescription(“”)]
[assembly: AssemblyConfiguration(“”)]
[assembly: AssemblyCompany(“”)]
[assembly: AssemblyProduct(“FirstApp”)]
[assembly: AssemblyCopyright(“Copyright © 2015”)]
[assembly: AssemblyTrademark(“”)]
[assembly: AssemblyCulture(“”)]
// ComVisible을 false로 설정하면 이 어셈블리의 형식이 COM 구성 요소에 // 표시되지 않습니다. COM에서 이 어셈블리의 형식에 액세스하려면 // 해당 형식에 대해 ComVisible 특성을 true로 설정하십시오.
[assembly: ComVisible(false)]
// 이 프로젝트가 COM에 노출되는 경우 다음 GUID는 typelib의 ID를 나타냅니다.
[assembly: Guid(“09f8dd0a-b5af-4e26-9e7b-ebea619044b1”)]
// 어셈블리의 버전 정보는 다음 네 가지 값으로 구성됩니다. // // 주 버전 // 부 버전 // 빌드 번호 // 수정 버전 // // 모든 값을 지정하거나 아래와 같이 ‘*’를 사용하여 빌드 번호 및 수정 버전이 자동으로 // 지정되도록 할 수 있습니다. // [assembly: AssemblyVersion(“1.0.*”)]
[assembly: AssemblyVersion(“1.0.0.0”)]
[assembly: AssemblyFileVersion(“1.0.0.0”)]
참조 노드에서는 응용 프로그램에서 참조해 사용하는 어셈블리(확장자 dll)를 표시합니다.
기본적으로 참조 추가한 것 중에서 System과 System.Windows.Forms는 필수적으로 참조하여야 Windows Forms 응용 프로그램을 작성할 수 있습니다.
System에서는 string, int, object 등의 기본 형식을 포함하여 가장 기본적인 것들을 정의하고 있는 어셈블리입니다.
System.Windows.Forms 에서는 Form 클래스를 비롯하여 다양한 UI 컨트롤 클래스 등을 정의하고 있는 어셈블리입니다.
개발자는 프로젝트에 필요하면 컨텍스트 메뉴(마우스를 우측 클릭하였을 때 나타나는 메뉴)를 통해 개발자가 정의한 어셈블리를 참조 추가할 수 있습니다.
참조 추가 창에서는 시스템에 등록 상태의 .NET 어셈블리와 COM, 프로젝트, 찾아보기, 최근에 사용한 파일 탭을 선택하여 원하는 어셈블리를 참조 추가할 수 있습니다.
Form1.cs 노드를 펼쳐보면 Form1.cs 파일과 Form1.Designer.cs 파일로 구성합니다. Form1.cs 파일은 개발자가 구현하기 위한 소스 파일입니다. 자식 컨트롤을 배치하거나 속성 지정 및 이벤트 핸들러를 등록하면 마법사에 의해 코드를 추가하는 부분은 Form1.Designer.cs 파일입니다.
▷Form1.cs
using System.Windows.Forms; namespace FirstApp { public partial class Form1 : Form { public Form1() { InitializeComponent(); } } }
Form 클래스를 비롯한 UI 컨트롤 클래스들은 System.Windows.Forms 네임 스페이스에 만들어져 있습니다. 이들을 사용하기 위해 필요한 using 구문입니다.
using System.Windows.Forms;
C#의 모든 코드는 특정 네임 스페이스 공간 속에 존재해야 합니다. 기본적인 네임 스페이스는 프로젝트 이름으로 만들어집니다.
namespace FirstApp {
자동으로 만들어진 Form1 클래스는 기반 클래스 Form에서 파생한 클래스입니다. Form 클래스에는 다양한 속성과 메서드 및 이벤트 핸들러를 제공합니다.
public partial class Form1 : Form {
생성자 메서드의 InitializeComponet 메서드는 Form1의 화면 배치 및 속성 지정, 이벤트 핸들러 등의 작업을 수행하는 곳입니다. 실제 메서드는 Form1.Designer.cs 파일에 있으며 개발자가 직접 수정할 일은 것이 없습니다.
주의할 점은 Form1 개체를 생성하면서 해야 할 일을 InitializeComponent 메서드 호출보다 앞쪽에 배치하지 말라는 것입니다. InitailizeComponent 메서드에서 폼 속성 및 자식 컨트롤 배치 등의 작업을 수행하기 때문입니다.
public Form1() { InitializeComponent(); } } }
▷Form1.Designer.cs
mespace FirstApp { partial class Form1 { /// <summary> /// 필수 디자이너 변수입니다. /// </summary> private System.ComponentModel.IContainer components = null; /// <summary> /// 사용 중인 모든 리소스를 정리합니다. /// </summary> /// <param name="disposing">관리 리소스를 삭제해야 하면 true, 그렇지 않으면 false.</param> protected override void Dispose(bool disposing) { if (disposing && (components != null)) { components.Dispose(); } base.Dispose(disposing); } #region Windows Form 디자이너에서 생성한 코드 /// <summary> /// 디자이너 지원에 필요한 메서드입니다. /// 이 메서드의 내용을 코드 편집기로 수정하지 마십시오. /// </summary> private void InitializeComponent() { this.components = new System.ComponentModel.Container(); this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; this.Text = "Form1"; } #endregion } }
개발자는 특별한 일이 없다면 Form1.Designer.cs 파일의 내용을 수정할 필요는 없습니다. [디자인] 창에서 개발자가 컨트롤을 배치하거나 속성 지정 및 이벤트 핸들러를 등록하였을 때 마법사에 의해 자동으로 만들어주는 코드입니다.
componets는 구성 요소들을 보관하는 컬렉션으로 Form1을 구성하는 디자이너 필수 요소입니다.
namespace FirstApp { partial class Form1 { private System.ComponentModel.IContainer components = null;
Form1 개체가 소멸하면서 해제해야 할 것이 있을 때 수행하는 코드입니다.
protected override void Dispose(bool disposing) {
만약 입력 인자로 전달받은 dispoing 변수가 true이면서 componets가 null이 아니면 components를 구성하는 요소들을 해제합니다.
if (disposing && (components != null)) { components.Dispose(); }
그리고 기반 형식인 Form의 Dispose 메소드를 호출하여 자원을 해제합니다.
base.Dispose(disposing); }
Form1 개체를 생성하면서 속성을 지정하거나 자식 컨트롤을 생성하고 이벤트 핸들러 등을 등록하는 코드들로 구성하는 메서드입니다.
private void InitializeComponent() { this.components = new System.ComponentModel.Container(); this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; this.Text = "Form1"; } } }
Program.cs 파일에는 진입점 클래스와 진입점 Main 정적 메서드가 있습니다.
▷Program.cs
using System; using System.Windows.Forms; namespace FirstApp { static class Program { /// <summary> /// 해당 응용 프로그램의 주 진입점입니다. /// </summary> [STAThread] static void Main() { Application.EnableVisualStyles(); Application.SetCompatibleTextRenderingDefault(false); Application.Run(new Form1()); } } }
Program.cs 파일도 개발자에 의해 특별히 작성할 일은 없습니다. 앞으로 이 책에서는 Program.cs 파일에 관해 특별히 설명하는 일은 없습니다.
using System; using System.Windows.Forms; namespace FirstApp { static class Program {
단일 스레드에서 안전함을 명시하는 Attribute 입니다. 폼과 컨트롤은 생성한 스레드가 아닌 다른 스레드에 의해 속성 등을 변경하면 크로스 스레드 문제를 야기합니다. 이는 비동기적인 프로그래밍 요소에 의해 폼이나 컨트롤의 속성 등을 변경하였을 때 자원 경쟁 문제에 따른 교착상태(DeadLock) 등에 빠지는 것을 방지하기 위한 것입니다.
[STAThread] static void Main() {
응용 프로그램에서 비주얼 스타일을 사용할 수 있게 합니다. 비주얼 스타일에는 색이나 글꼴처럼 운영 체제 테마를 구성하는 다양한 시각적 요소들로 구성합니다.
Application.EnableVisualStyles();
자식 컨트롤들의 랜더링할 때 응용 프로그램의 기본값으로 설정합니다. 입력 인자에 따라 랜더링에 사용하는 클래스가 달라집니다. 입력 인자가 true일 때는 텍스트 랜더링에 Graphics 클래스를 사용하고 false이면 TextRender 클래스를 사용합니다.
Application.SetCompatibleTextRenderingDefault(false);
Form1 개체를 생성하여 화면에 띄워주고 Form1 창이 닫힐 때 반환합니다. 실제 진입점 Main 메서드에서 제일 중요한 부분입니다.
Application.Run(new Form1()); } } }