- 윈도우 프로그램은 하나 이상의 윈도우(윈도우 단위로 구성)를 가지고 메세지 구동 방식으로 실행됩니다.

 

■ WinMain 함수 매개변수

- 윈도우 프로그램의 main 함수

 

 int APIENTRY WinMain(HANDLE hInstance, HANDLE hPrevInstance, LPSTR lpCmdLine,

                               int nCmdShow)

 

hInstance : 현재 실행을 시작하는 프로그램의 인스턴스 핸들

hPrevInstance : 이전에 실행된 동일 프로그램의 인스턴스 핸들

lpCmdShow : main 함수의 argv와 같은 기능  

nCmdShow : 프로그램의 윈도우가 어떤 모습으로 실행될 것인지 결정

                   옵션은 최소화 상태, 감춰진 상태, 보통 상태 등이 있음

 

※ 용어

인스턴스 : 프로그램이 실행되어 메모리에 로딩된 상태에 있을 때.

핸들 : 메모리에 로딩된 인스턴스 식별하기 위해 사용. 즉 윈도우 식별자

이외에도 윈도우 프로그래밍에서 '핸들'은 특정 메모리 블록을 식별하기 위한 포인터.

 

 

■ WinMain 함수의 구성

1. 프로그램을 초기화 한다.

2. 인스턴스를 초기화 한다.

3. 메세지 루프를 돈다.

 #include <windows.h>

 int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,

                                  LPSTR lpCmdLine, int nCmdShow)

 {

     // 프로그램 초기화

     if( !hPrevInstance )     // 인스턴스가 처음 생성되는 경우에만 실행

          if( !InitApplication(hInstance) )

               return FALSE ;

 

     // 인스턴스 초기화

     if( !hInitInstance(hInstance, nCmdShow ) )

          return FALSE ;

 

     // 메세지 루프

     return Run()

 } 

 

프로그램 초기화 : 프로그램의 인스턴스가 메모리에 처음 로딩될 때 수행해야 하는 초기화 작업

인스턴스 초기화 : 각각의 인스턴스가 메모리에 로딩될 때마다 수행해야 하는 초기화 작업

즉, 프로그램이 이미 실행되어 메모리에 인스턴스가 존재하면 두 번째 인스턴스가 생성될 때 프로그램 초기화 작업은 하지 않아도 된다. 인스턴스 초기화 작업만 하면 된다.

 

 

□ 프로그램 초기화 : 윈도우 클래스 등록

- Edit 컨트롤, Combo Box 컨트롤, List Box 컨트롤 등의 윈도우는 운영체제에 이미 클래스가 등록되어 있다. => 파생클래스로 상속을 받아 조작

- 그러나 우리가 만드는 윈도우는 새로운 기능을 가진 윈도우므로 이 윈도우 클래스를 운영체제에 새로 등록해 주어야 한다.

1. WNDCLASS 구조체에 값을 채움

2. RegisterClass 함수를 호출하여 윈도우 클래스 등록

 BOOL InitApplication( HINSTANCE hInstance )

 {

     WNDCALSS wc ;

     wc.style = CS_HREDRAW | CS_VERDRAW ;

     wc.lpfnWndProc = WndProc ;     // 함수 포인터

     wc.hInstance = hInstance ;

     wc.hIcon = LoadIcon( NULL, IDI_APPLICATION )

     wc.hCursor = LoadCursor( NULL, IDC_ARROW ) ;

     wc.hbrBackgroud = (HBRUSH)GetStockObject( WHITE_BRUSH ) ;

     wc.lpszMenuName = NULL ;

     wc.lpszClassName = "ExampleCalss" ;

     wc.cbClsExtra = 0 ;

     wc.cbWndExtra = 0 ;

 

     reutnr RegisterClass( &wc ) ;

 }

 

。WNDCLASS 구조체

 typedef struct _WNDCLASS {

     UNIT          style ;            // 윈도우 스타일

     WNDPROC lpfnWndProc ; // 윈도우 프로시저(메세지를 처리할 함수)

     int             cbClsExtra ;   // (사용하지 않음) 미래 확장을 위해 사용된 값

     int             cbWndExtra ;  // (사용하지 않음) 미래 확장을 위해 예약된 값

     HANDLE     hInstance ;    // 인스턴스 핸들

     HICON       hIcon ;           // 윈도우가 최소화 되었을 때 표시될 아이콘의 핸들

     HCURSOR  hCursor ;       // 윈도우 위로 마우스 커서가 올라갔을 때 보여질 커서의 핸들

     HBRUSH     hbrBackground ;  // 배경을 지우는데 사용할 브러시의 핸들

     LPCTSTR   lpszMenuName ;  // 이 윈도우가 소유할 메뉴

     LPCTSTR   lpszClassName ;  // 윈도우 클래스의 이름

 } WNDCLASS ;

 

 

□ 인스턴스 초기화 : 윈도우 생성

1. 핸들 정의

2. 윈도우를 생성 값을 핸들에 넘김

 BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)

 {

     HWND hWnd ;

     if( !(hWnd = CreateWindow("ExampleClass", "C로 만든 프로그램",     

                                           WS_OVERLAPPEDWINDOW,

                                           CW_USEDEFAULT, CW_USEDEFAULT,

                                           CW_USEDEFAULT, CW_USEDEFAULT,

                                           NULL, NULL, hInstance, NULL ) ) )

          return FALSE ;

 

     ShowWindow( hWnd, nCmdShow ) ;  // 메인 프레임 윈도우를 화면에 보이게 한다.

     UpdateWindow( hWnd ) ;                  // 메인 프레임 윈도우를 다시 그려준다.

     return TRUE ;

 }

 

。CreateWindow 함수의 매개변수

 매개변수  의미 
 lpClassNamae  프로그램 초기화 부분에서 등록한 윈도우 클래스의 이름
 lpWindowName  윈도우 타이틀 바에 출력될 문자열
 dwStyle  윈도우 스타일
 x, y, nWidth, nHeight  윈도우의 위치와 가로 세로 길이
 hWndParent  부모 윈도우의 핸들
 hMenu  메뉴의 핸들
 hInstance  인스턴스의 핸들
 lpParam  CREATESTRUCT 구조체로 지정되는 윈도우 생성에 필요한 추가 정보

 

 

□ 메세지 루프

- 프로그램에 어떤 이벤트가 발생하면 윈도우 운영체제가 이를 감지하여 프로그램의 메세지 큐에 적당한 메세지를 넣어준다.

1. 프로그램의 메세지 큐에서 메세지를 가져온다.

2. 이 메세지의 정보를 알려준다.

3. 메세지를 윈도우 프로시저에 전달한다.

 int Run()

 {

     MSG msg ;

     while( GetMessage( &msg, NULL, NULL, NULL ) )

     {

          TranslateMessage( &msg ) ;

          DispatchMessag( &msg ) ;

      }

      return (int)msg.wParam ;

 }

 

GetMessage 함수는 프로그램의 메세지 큐에서 메세지를 가져오는 기능을 수행합니다.

이 함수는 프로그램을 종료하라는 WM_QUIT 메세지를 가져오면 TRUE를 반환하고, 그렇지 않으면 FALSE를 반환한다. FALSE를 만나면 while문을 빠져나온다.

키보드가 눌리면 WM_KEYDOWN 메시지가, 키보드가 떼지면 WM_KEYUP 메세지가 발생한다. Translatemessage 함수는 이 메세지 조합을 이용하여 KEY_CHAR, KEY_DEADCHAR, KEY_SYSCHAR 등의 메세지를 발생하여 실제로 어떤 문자가 눌렸는지 정보를 알려준다.

DispatchMessage 함수는 이 메세지를 윈도우 프로시저에 전달한다.

 

 

□ 윈도우 프로시저 : 메세지 처리

- 윈도우 메세지를 처리하는 함수로 이 함수를 어떻게 만드냐에 따라 윈도우 기능이 결정된다.

 

 LRESIT WINAPI WndProc(HANDLE hWnd, UNIT message, WPARAM wParam,

                                     LPARAM lParam)

 {

     switch( message )

     {

          case WM_KEYDOWN :          // 키보드가 눌렸을 때의 처리

               break ;

          case WM_LBUTTONDOWN :  // 마우스 왼쪽 버튼이 클릭되었을 때

               break ;

          case WM_MOUSEMOVE :     // 마우스가 움직였을 때

               break ;

     }

     return DefWindowProc( hWnd, message, wParam, lParam ) ;

 }

 

DefWindowProc 함수는 윈도우 운영체제가 미리 정해둔 윈도우의 기본 기능을 수행하도록 한다. 

 
Posted by 모과이IT
,

 #include "stdafx.h"

 /********************************************************************

                                              클래스 선언

 *********************************************************************/

 class CTestApp : public CWinApp

 {

     public :

          virtual BOOL InitInstance() ;

 } ;

 class CTestFrame : public CFrameWnd

     public :

          CMainFrame() {

                    Create(NULL, "MFC로 만든 프로그램") ;

          }

          // 메세지 처리기

          afx_msg void ONPaint() ;

          afx_msg void ONLButtonDown( UNIT nFlags, CPoint point ) ;

          DECLARE_MESSAGE_MAP()

 } ;

 /********************************************************************

                          전역변수로 클래스의 인스턴스 선언

 *********************************************************************/

 CTestApp : theApp ;

 /********************************************************************

                                            멤버 함수 구현

 *********************************************************************/

 BEGIN_MESSAGE_MAP( CMainFrame, CFrameWnd )

     ON_WM_PAINT()

     ON_WM_LBUTTONDOWN()

 END_MESSAGE_MAP()

 

 // 인스턴스 초기화

 BOOL CTestApp::InitInstance()

 {

     // 메인 프레임 윈도우 생성

     m_pMainWnd = new CMainFrame ;

     m_pMainWnd->ShowWindow( m_nCmdShow ) ;

     m_pMainWnd->UpdateWindow() ;

     return TRUE ;

 }

 

 void CMainFrame::OnPaint()

 {

     CPaintDC dc( this ) ;

     CRect rect ;

     GetClientRect( &rect ) ;

     dc.DrawText( "마우스 버튼을 클릭해 보세요." -1, &rect,

                          DT_SINGLELlNE | DT_CENTER | DT_VCENTER ) ;

 }

 

 void CMainFrame::OnLButtonDown( UNIT nFlags, CPoint point )

 {

     AfxMessageBox( "마우스 버튼이 클릭 되었습니다." ) ;

 }

 

헤더파일 stdafx.h를 열어 "#include <afxwin.h>"를 추가해준다. 

 
Posted by 모과이IT
,

■ SDK와 MFC

- SDK에서 제공하는 모든 기능이 다 MFC에 캡슐화 되어 있는 것은 아니라는 점에서 주의하라.

- 굳이 클래스 형태로 캡슐화 할 필요가 없는 기능들도 많이 있는데 MFC에서는 이런 함수들을 굳이 클래스로 만들지 않고, 그냥 SDK 형태로 사용하도록 두었다.

- 예를들어 GlobalAlloc 처럼 메모리를 할당하는 일은 특정 클래스에서만 하는 것이 아니라 언제, 어디서든 사용할 수 있는 기능이기 때문에 그냥 SDK 함수 형태로 사용한다.

 

 

■ WinMain 은 어디에?

- MFC는 어떠한 프로그램을 작성하더라도 WinMain 함수를 건드리지 않고 작성할 수 있도록 모든 것을 완벽하게 처리해 놓았다.

- MFC 내부에 들어 있는 WinMain 함수를 간략히 보면 다음과 같다.

 int APIENTRY WinMain( HANDLE hInstance, HANDLE hPrevInstance, LPSTR lpCmdLine,

                                   int nCmdShow )

 {

     CWinApp *pApp = AfxGetApp() ;

     pApp->InitApplication() ;

     pApp->InitInstance() ;

     pApp->Run() ;

     pApp->ExitInstance() ;

 }

 

InitApplication 함수는 프로그램 초기화 기능을 수행하고, InitInstance 함수는 보통 재정의되는 함수로 도큐먼트 뷰를 등록하고, 메인 프레임 윈도우를 생성하는 일을 수행한다. Run 함수는 WM_QUIT 메세지를 만날 때까지 무한 루프를 돌면서 메세지를 윈도우 프로시저에 전달하는 기능을 한다. 

 

Posted by 모과이IT
,