1. Windows Forms
Application
Windows Forms Application은 Visual Studio .NET에서 쉽게 윈도우 기반 응용 프로그램을 개발할 수있는 환경을 제공합니다.
그리고 C++/CLI(C#, VC.NET…)문법을 이용해 .NET 프레임워크환경의 모든 장점을 가질 수 있는 통합 개발 환경을 제공합니다.
Windows Forms Application은 Win32/MFC의 업데이트 버전이나 추가된 버전이 아닌 전혀 다른 .NET CLR 위에서 실행되는 윈도우 개발환경 입니다.
하지만 MFC완 Windows Forms Application은 서로 임베딩 될수 있는 환경을 제공하고 앞으로 더 많은 관련된 기능이 추가될 것으로 기대 됩니다.
2. Windows Forms Application
시작
Visual Studio 2005에서 파일>>새로만들기>>프로젝트 메뉴에서 Window Forms Application 프로젝트를 추가 할 수 있습니다.
새 프로젝트 추가 메뉴를 선택하면 아래 그림과 값이 새 프로젝트를 설정하는 박스가 나타납니다.
Windows Forms Application은 C#, J#, VB에서는 윈도우프로그램이라는 이름으로 생성이 되고 Visual C++에서는 CLR탭에서 Windows Forms Application을 선택하여 만들 수 있습니다.
프로젝트 타입을 Windows Forms Application 으로 선택하고 프로젝트 이름 , 위치 등을 설정하고 “확인”버튼을 클릭합니다.
프로젝트를 생성하면 기존 MFC 윈도우 프로그램과는 많이 다른 모습을 하고 있습니다.
제일 처음 보이는 화면은 “디자인”템플릿입니다.
디자인 템플릿에서 여러가지 .NET 콤포넌트를 추가/삭제 하여 프로그래밍을 하는 환경을 제공합니다.(델파이와 똑같습니다.)
.NET 컴포넌트를 추가할 때는 Visual Studio 오른쪽에 도구상자에서 컴포넌트를 선택해서 추가합니다.
Windows Forms Application에서 기본적으로 제공하는 컨트롤 클래스들은
System.Windows.Forms 네임스페이스내에 존재 합니다.
.NET 콤포넌트들을 Forms Designer에 올려놓아 이벤트나 속성등을 설정하여 쉽게 응용 프로그램을 개발할 수 있습니다.
.NET 콤포넌트 기본 구성요소
3. Windows Forms
Application 동작
Windows Forms Application 프로그램도 다른 프로그램과 마찬 가지로 main함수가 있습니다.
[프로젝트 이름].coo 파일을 열면 다음과 같은 main함수를 볼 수 있습니다.
using namespace WinFormsTest;
[STAThreadAttribute]
int main(array<System::String ^> ^args)
{
// 컨트롤이만들어지기전에Windows XP 시각효과를활성화합니다.
Application::EnableVisualStyles ();
Application::SetCompatibleTextRenderingDefault(false);
// 주창을만들어실행합니다.
Application::Run(gcnew Form1());
return 0;
} |
STAThreadAttribute Attribute로 현재 메인 함수에 대한 COM Threading 모델을 Single 쓰레드 로 설정합니다
다중 쓰레드 모델로 설정할려면 MTAThreadAttribute로 Attribute를 선언합니다.
Application::EnableVisualStyles()메서드를 호출하여 XP스타일의 UI를 적용합니다.
그리고 Application::SetCompatibleTextRenderingDefault()함수로 텍스트를 그리는데 GDI+를 사용할지 GDI를 사용할지 설정합니다.
True면 GDI+를 사용하고, false면 GDI를 사용하여 텍스트를 그립니다.
Application::SetCompatibleTextRenderingDefault()함수는 Windows Forms 응용프로그램을 다른 응용프로그램에 삽입(host)할 때 호출하면 안돱니다.
설정들이 끝마치고 나서 디자인한 Forms를 실행합니다.
Application::Run 함수를 호출 하면 현재 메인 쓰레드에서 메시지루프를 돌면서 Forms 프로그램을 실행 합니다.
Forms 응용프로그램은 아래 그림과 같은 이벤트 호출 루틴으로 실행이 됩니다.
Forms Application 프로젝트를 생성하면 Form 클래스에 상속받은 클래스와 InitializeComponent()멤버 함수가 생성됩니다.
InitializeComponent() 함수는 Form다이얼로그에 올려진 컨트롤들의 초기화나 폼 다이얼로그의 이벤트 핸들러 추가 등을 Form Designer가 자동으로 코드를 만들어 콘트롤들을 초기화 하고 폼 컴포넌트 컨테이너에 등록하는 등의 루틴이 들어가는 함수입니다.
아래는 폼디자이너에서 컨트롤 을 추가하고 이벤트를 추가했을 때 InitializeComponet함수에서 자동으로 추가되는 코드의 일부입니다.
this->AutoScaleDimensions = System::Drawing::SizeF(7, 12);
this->AutoScaleMode = System::Windows::Forms::AutoScaleMode::Font;
this->ClientSize = System::Drawing::Size(227, 326);
//폼 컨트롤 컨테이너에 컨트롤들을 추가.
this->Controls->Add(this->elapsed_time);
this->Controls->Add(this->mine_cnt);
this->Controls->Add(this->label3);
this->Controls->Add(this->label1);
this->Controls->Add(this->menuStrip1);
this->FormBorderStyle = System::Windows::Forms::FormBorderStyle::FixedDialog;
this->MainMenuStrip = this->menuStrip1;
this->Name = L"MineForm";
this->Text = L"지뢰찾기v1.0";
this->Load += gcnew System::EventHandler(this, &MineForm::MineForm_Load);
this->Paint += gcnew System::Windows::Forms::PaintEventHandler(this, &MineForm::DrawItems);
this->menuStrip1->ResumeLayout(false);
this->menuStrip1->PerformLayout();
this->ResumeLayout(false);
this->PerformLayout(); |
이 함수는 편집하지 않는 것을 원칙으로 합니다.( 편집 해도 되지만 계속 편집하다 보면 사용자가 폼 디자이너를 추가/삭제하면 사용자가 넣은 코드가 지워집니다.)
///<summery> ////</summery> 내에는 변수 선언 같은 편집을 하면 폼디자이너가 Fail되는 원인이 되니, ///<summery> ///</summery> 밖에서 변수 선언 등의 작업을 합니다.
Form 생성자가 호출되면 OnFormLoad 이벤트가 발생합니다.
OnFormLoad이벤트 핸들러는 폼이 로드될 때 한번만 호출 됩니다.
사용자가 생성한 컨트롤을 생성/등록할 때 OnFormLoad 이벤트 핸들러에서 하면 됩니다.
다음은 폼 다이얼로그가 활성화 될 때 발생되는 OnFormActivated()이벤트 핸들러가 호출 됩니다.
OnFormActivated()이벤트 후, 폼 다이얼로그가 처음으로 보여졌을 때 OnShown()이벤트가 발생합니다.
여기서 만약 폼 다이얼로그가 비활성화 되면 OnFormDeactivate이벤트가 발생하고, 다시 활성화 되면 OnFormActivated이벤트가 발생합니다.
사용자에 의해 폼 응용프로그램이 종료되면 OnFormClosing() 이벤트 OnFormClosed()이벤트가 차례대로 발생하고 프로그램이 종료하게 됩니다.
4. Message Filter
Win32 API/MFC에서는 윈도우의 특정 메시지를 가져올려면 해당 윈도우를 서브 클래싱 하거나 DefMessageProc멤버 함수 같은 메시지 프로시져를 재정의 함으로써 특정 메시지에 대한 동작을 작성할 수 있었습니다.
Windows Forms Application에서도 이와 비슷하게 특정 메시지를 전처리하기 위한 방법으로 몇 가지 방법이 있습니다.
WndProc함수를 재정의하는 방법과 메시지 필터 인터메이스 클래스를 사용하는 방법이 있습니다.
메시지 필터 인터페이스는 Application클래스의 멤버 함수인 AddMessageFilter함수로 추가 하고 RemoveMessageFilter함수로 제거 할수 있습니다.
IMessageFilter클래스의 PreFilterMessage 순가상함수를 재정의를 합니다.
PreFilterMessage함수가 true를 리턴하면 해당 메시지가 다른 메시지 필터로 처리가 되게하고 false를 리턴하면 다른 메시지필터 가 처리할 수 있도록 합니다.
PreFilterMessage함수는 링크 될 때 UnmanagedCode 권함을 필요하기 때문에 , 아래 예제 에서 처럼 속성을 줍니다.
아래 예제메세지 필터 인터페이스 클래스를 사용하는 예제 입니다.
ref class TestMessageFilter: public IMessageFilter
{
public:
[SecurityPermission(SecurityAction::LinkDemand, Flags =
SecurityPermissionFlag::UnmanagedCode)]
virtual bool PreFilterMessage( Message % m )
{
if ( m.Msg ==0x100 ) //WM_KEYDOWN
{
Int32 key = m.WParam.ToInt32();
KeysConverter tc; //Converter object that converting Integer keyvalue to string.
tc.ConvertToString(key);
return true;
}
else
return false;
}
TestMessageFilter^ MsgFilter; //클래스 멤버 변수로 선언합니다.
sgFilter = gcnew TestMessageFilter();
Application::AddMessageFilter(MsgFilter); //Message Filter 인터페이스를 추가. |
5. Platform Invocation (PInvoke)
C++/CLI에서는 네이티브 API함수들을 호출할수 있는 방법을 Platform Invoke라는 이름으로 제공하고 있습니다.
이 방법은 네이티브 환경에서 dll 함수를 호출하는 방법보다 쉽고 간단하게 할 수 있습니다.
네이티브 환경에서 dll함수를 호출하는 방법과 같이 명시적 호출 방법과 묵시적 호출 방법이 있습니다.
묵시적 호출은 사용할 API가 있는 dll파일을 프로젝트 설정에서 추가하고
해당 함수를 extern타입으로 선언하고 사용하는 방법입니다.
//MessageBeep 함수를 묵시적으로 사용할 때 , 해당 함수 선언.
extern "C" int __stdcall MessageBeep(int); |
명시적 호출 방법은 해당 네이티브 함수를 선언하고 dll을 명시정으로 Attribute으로 설정하여 사용하는 방법입니다.
using namespace System::Runtime::InteropServices;
[DllImport("User32.dll", EntryPoint = "FindWindow",CallingConvention = CallingConvention::Cdecl, CharSet = CharSet::Auto)]
IntPtr FindWindow( System::String^ lpClassName, System::String^ lpWindowName); |