달력

122025  이전 다음

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31

MFC코드의 기본 구조

MFC 2014. 3. 17. 02:36



응용프로그램도 포함되어있음. -> App + 문서 (Doc)

CWinApp 클래스
 
m_hInstance ▶현재 응용 프로그램의 인스턴스 핸들입니다. WinMain()함수의 첫번째 파라미터인 hInstance와 같은것임.
m_lpCmdLine ▶WinMain() 함수의 lpCmdLine 파라미터와 같은것입니다. 프로그램을 실행하였을때 명령줄 정보가 들어있음.
m_nCmdShow  ▶WinMain()함수의 마지막 파라미터인 nCmdShow와 같은것.
m_pActiveWnd ▶응용프로그램의 최상위 프레임 윈도우에 대한 포인터. SDI구조에서 이값은 CMainFrame 클래스 객체의 포인터.
m_pszAppName ▶응용프로그램의 제목에 해당하는 문자열 포인터. 문자열의 좀더 정확한 정보는 문자열 테이블에 있는 AFX_IDS_APP_TITLE에 해당하는값
m_pszExeName ▶빌드한 실행 파일에서 확장자(.exe)를 제외한 파일명.

가상함수로 정의된 함수중 중요한것!
(InitInstance(), ExitInstance(),Run())

InitInstance()▶메서드는 응용프로그램이 초기화 되는 시점에서 호출되며 Run()메소드와 달리 대부분 재정의 되어있으며, 직접 코드를 수정할수 있다.
 ↓
Run()▶메시지 루프가 시작되는 시점에 CWinApp클래스의 Run()메소드가 호출되는 시점. Run()메서드가 반환하면 응용프로그램은 종료됨.
 ↓
ExitInstance()▶InitInstance()메소드와 반대로 응용프로그램을 종료하는 시점에 호출. 메인메시지 루프를 종료하는 시점(Run()함수가 반환한 시점) 에 호출. 기본적으로 재정의되어있지않지만
                필요한경우 재정의해서 사용가능.


CframeWnd클래스 계층구도

CObject 
    └→CCmdTarget
              └→CWnd
                   └→CFrameWnd

 
CFreameWnd& Control bar windows
  1-2캡쳐


CDocument클래스 계층구도

Cobject
   └→ CCmdTarget
              └→ CDocument

메모장 처럼 한프로그램당 한개의 화면이므로, SDI(싱글도큐먼트)


OnNewDocument() ▶처음시작 할때 불림.(파일을 새로열때.)
AfxMessageBox() ▶Afx - MFC에서 제공하는 전역변수(팝업용 텍스트)
OnOpenDocument()▶문서열기 를 할시에 콜됨.
SetModifiedFlag(True)▶ 무조건 수정된걸로 인식되어 종료시에 저장을 물음.

MessageMap
-------------------------------------------------
BEGIN_MESSAGE MAP(CHelloSdiViewmCEditView) 
  ~~
  ~~
  ~~
END_MESSAGE_MAP()
=================================================

속성으로 WM_CREATE()를 추가하면, 코드도 추가 됨과 동시에 MESSAGE_MAP에도 추가한 코드의 구조체가 추가된다.
WM_CREATE()추가시
-----------------------------------------
BEGIN_MESSAGE MAP(CHelloSdiViewmCEditView)
  ~~
  ~~
  ~~
  ON_WM_CREATE()
END_MESSAGE_MAP()
------------------------------------------


MESSAGE_MAP 은 API의 case문을 대체 함.

'MFC' 카테고리의 다른 글

비트맵과 이미지 처리  (0) 2014.03.17
키보드 입력  (0) 2014.03.17
WinMain함수  (0) 2014.03.17
Posted by 레이드리안
|

WinMain함수

MFC 2014. 3. 17. 02:35


* WinMain 함수
- C언어의 메인과 마찬가지임.. 
  시작되는 함수는 여기에서 처리함


핵심함수: _tWinMain
          MyRegister(hInstance);
          InitInstance


        ★main message loop(가장중요)//메시지 루프
          while(GetMessage(&msg,NULL,0,0))
         {
  if(!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
  {
   TranslateMessage(&msg);
                        DispatchMessage(&msg);
  }
         }

Get Message <-  Msg Queue 에서 가지고옴
메시지를 가져오면 루프를 돌고 메시지를 가지고 오지못하면(quit) 종료되는구조.

윈도우에서 Message란?
-모든것이 다 Message다.(보여지는것,생성되는것,이동되는것,입력 등등...) 
-Message Driven 방식

H.I.D(Human Input Device)- Keyboard, Mouse등(H/W Event 발생)▶OS에서 감지


-키보드에서 키가 눌리면 하드웨어 이벤트가 발생하고, 이이벤트는 OS에서 감지하며 모니터(출력)에 Message로 보내줌.


-DispatchMessage 함수가 호출이 된다면 윈도우 프로시저 함수를 호출(Window Proc)<_Winproc->윈도우창의 인풋에 대해 메시지를 처리함.

메시지 내용은 (HWND hWnd,UNIT message, WPARAM wParam, LPARAM lParam)에 메시지정보를 담고있음.

작업관리자에서 "응답없음"이뜨는것은 메인메시지 에서 루프가 멈추면 "응답없음"발생


Handle 이란 -어떤 포인터에 관한 값.
-------------------------------tWinMain--------------------------

_tWinMain(HINSTANCE hInstance,) ▶응용프로그램 자체를 식별하는 값(실행파일의 메모리상의 위치)

lpCmdLine ▶ 프로그램시작할때 ~~~.exe /?라던지 실행할때쓰는것
nCmdShow ▶ 윈도우를 화면에 보여줄것인지 말것인지를 지정하는 값.

MSG msg ▶메시지 구조체.
====================================
typedef struct tagMSG{
 HWND hwnd; //윈도우핸들.(특정윈도우를 식별할때 핸들로 식별함)▶값
 UINT message;//핸들의 UINT형의 message로 전달됨
 WPARAM wParam;- 메시지 파라미터(매개변수,인수,인자)
 LPARAM lParam;- 메시지 파라미터(매개변수,인수,인자)
 DWORD time;- 메시지가 전달된 시간(시스템시간)
 POINT pt;-포인터 구조체 (x,y) 모니터상의 표시좌표 ↓y →x 
#ifdef _MAC
 DWORD lPrivate;
#endif
}MSG, *PMSG,NEAR *NPMSG,FAR *LPMSG;

===================================

HACCEL hAccelTable ▶단축키 테이블
<리소스뷰 ▶ HellowWorld▶HelloWorld.rc▶Acceletator▶IDC_HELLOWORLD(단축키테이블)

LoadString(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING)
▶IDS_APP_TITLE - 선언부에 가면 그냥 값이들어가있고, 이값을 로딩을해서 전역변수로 선언되어있는 szTitle(TCHAR타입 MAX_LOADSTRING(100개-define) 선언)
▶ 리소스 뷰에서 String Table 안에 보면 IDS_APP_TITLE를 값으로 따지면 103번 그것을 로딩하면 HelloWorld값이 버퍼에저장
   :다국어 지원때문에 리소스이름으로 넣어둠.


MyRegisterClass(hInstance)▶윈도우의 RegisterClassEx를 호출하는것이 목적.Class▶등급  c++의 클래스 뜻이아님.
윈도우 스탈일, 레지스터, 아이콘,마우스포인터,배경색,메뉴,윈도우이름-리소스뷰(IDC_HELLOWORLD(icon/Menu)
wcex.lpfnWndProcWinProc등록되었다는것은▶ Msg-OS-메세지큐-처리(WinProc)<호출하지는않음>-수동적으로 OS에의해 호출되어짐

UINT▶unsigned int 
CALLBACK▶Call Convention(함수호출 시 스텍에 저장할때 어떻게 넣을꺼냐는것)<_stdcall>

WM_COMMAND: ▶ 어떤키를 눌렀을때 발생한 메세지를 처리


InitInstance(hInstance, nCmdShow)▶ CreateWindow함수를 직접 호출
===========================================================
hWnd = CreateWindow(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW,
       CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL,NULL, hInstance,NULL)
===========================================================
CreateWindow▶윈도우 핸들을 리턴
WS_OVERLAPPEDWINDOW▶ WS: 윈도우 스타일 OVERLAPPEDWINDOW:중첩해서 쓰는 윈도우(가장기본적인윈도우)

WM_PAINT▶윈도우를 다시 그릴때 사용
WM_DESTORY▶ 종료를 눌렀을때 불림.

'MFC' 카테고리의 다른 글

비트맵과 이미지 처리  (0) 2014.03.17
키보드 입력  (0) 2014.03.17
MFC코드의 기본 구조  (0) 2014.03.17
Posted by 레이드리안
|

윈도우즈 프로그래밍

API 2014. 3. 17. 02:34


변수 명명법

표준 함수들은 모두 이방식대로 인수 이름을 작성하므로 접두어들을 외우고 있으면 함수의 인수가 어떤의미인가를 쉽게파악할수있다.

윈도우즈 프로그래밍에서쓰는 이런 변수 명명법을 헝가리식 명명법이라고 한다.(이렇게 쓰면 편하다는 것이지 꼭 지켜야하는 의무는 아니다)

BOOL InvalidateRect(HWND hWnd, CONST RECT *lpRect, BOOL bErase);

다음함수의 원형을 보면 hWnd는 핸들이고, lpRect는 포인터이며, bErase는 진위형이라는것을 쉽게 알수 있다.

위 표는 윈도우즈에서 사용자 정의 데이터형이다. 이 데이터형은 windows.h라는 헤더파일에 typedef로 선언되어있으며,

마치 표준 데이터형처럼 사용함으로 알아두면 유용하다.

◎핸들에 대한 이해

- 핸들이란 구체적인 어떤 대상에 붙여진 번호이며 문법적으로 32비트의 정수값이다.

윈도우에서는 여러가지 종류의 핸들이 사용되고있으며, 만들어진 윈도우에 윈도우 핸들(hWnd)을 붙여 번호로 관리한다.

DC에 대해서도 핸들을 사용하고 논리적펜, 브러시 에도 핸들을 붙여 관리한다.

※핸들의 특징

①핸들은 일단 정수값이며, 대부분의 경우 32비트 값이다. 핸들을 사용하는 목적은 오로지 구분을 위한 것이므로, 핸들끼리 중복

되지 않아야하며, 이런 목적으로는 정수형이 가장 적합하다. 정수형은 비교나 대입 연산이 가장 빠른 타입이므로,핸들로 쓰여

지기적합하다.

②핸들은 운영체제가 발급하며, 사용자는 쓰기만 한다. 윈도우를 만들거나 파일을 열면 운영체제는 만들어진 윈도우나 열려진

파일에 핸들을 붙이고, 그값을 리턴한다. 사용자는 이 핸들을 잘 보관해 두었다가 해당 윈도우나 파일을 다시 참조 할 때 사용

한다. 사용자가 직접핸들을 만드는 경우는 없다.

③같은 종류의 핸들끼리는 절대 중복된 값을 가지지않는다.(대상을 구분하는 원래의 목적을 달성할수 없기 때문), 하지만 다른

종류의 핸들끼리는 중복된 값을 가질수도 있다.

④핸들은 정수형이므로 값을 가지겠지만 그 실제값이 무엇인지는 몰라도 상관없다. 핸들은 단순 표식일 뿐이다. 핸들형 변수를

만들어 핸들을 대입받아 쓰고 난후에는 버리면 된다.

-윈도우즈에서 핸들은 예외없이 접두어 H로 시작되며 핸들값을 저장하기 위해 별도의 데이터형까지 정의해 두고 있다.

HWND,HPEN,HBRUSH,HDC등이 핸들을 담기 위한 데이터형들이며 모두 부호없는 정수형이다.

●비트 OR연산자

- 사용자가 원하는 작업을 하기 위해 함수를 호출한다. 이때 함수에게 작업의 내용을 전달하는 인수가 같이 건네지는데, 인수에는

작업의 목적과 방법을 지정하는 정보가 포함된다.

전달가능한 옵션이 여러개 있을 경우 필요한 옵션수 만큼 인수를 전달받는것이아니라, 하나의 인수에 복수개의 옵션을 묶어

전달하는데 이때 사용되는 연산자가 비트OR연산자(|)이다.

CreateWindow 함수는 만들고자 하는 윈도우의 스타일을 인수로 전달 받는데 WS_CHILD,WS_CAPTION,WS_BORDER등 옵션

이 수십개나 되지만 단 하나의 인수로 이옵션을 모두 전달 받는다.

비트 OR연산자를 사용하면 관심없는 인수는 생략해버릴수도 있고, OR연산은 교환 법칙이 성립하므로 값의 순서에 무관하게

여러가지 옵션을 묶어서 전달하므로 호출 속도도 빠르다.

여러개의 옵션을 비트 OR연산자로 묶어 하나의 정수값만 전달하더라도 함수는 인수의 개별비트를 테스트 한후 어떤 옵션

이 선택되었는지를 알수 있다. 각 옵션의 실제 값이 어떻게 정의 되어있는 가는 알 필요가 없으며, 매크로 상수만 알면되는데

매크로 상수가 곧 옵션의 이름이다.

●유니코드

TCHAR는 C의 기본 타입 중 하나인 char와 같지만 유니코드로 컴파일할때는 wchar_t타입이된다. wchar_t는 실제로 unsigned short로 정의 되어있으며 부호 없는 16비트 정수 형이다.TCHAR타입의 실제 정의문은 조건부 컴파일로 작성되어있다.

#ifdef UNICODE

typedef wchar_t TCHAR;

#else

typedef char TCHAR;

#endif

char를 바로쓴 소스를 유니코드로 바꿀때는 일일이 소스를 뜯어 고쳐야하지만, TCHAR라는 중간 타입을 사용한 소스는 프로젝트 설정에 따라 소스도 같이 바뀌는 효과가 있으므로 소스는 그대로두고 컴파일할수 있다.

문자열을 다루는 함수들도 가급적으로 유니코드를 인식하는 함수를 사용한다.

유니코드 인식함수들은 표준 함수와 이름이 비슷하되 앞에 l가가 하나 더 붙는다는 것만 다르며, 운영체제가 제공하는 API함수이므로 별도의 용량을 차지하지않는다는 장점이있다.

strlen은 char타입의 문자열 길이만 조사하지만 lstrlen은 TCHAR 타입이 문자열에 대해서도 동작하므로 이식이 훨씬 더유리하다.

문자열 상수도 타입이있으므로 겹따옴표안에 바로 문자열상수를 쓰지말고, TEXT 매크로로 둘러 싸는 것이 좋다.

TCHAR *str="string"; //x

TCHAR *str=TEXT("string"); //TEXT매크로 안에 문자열 상수를 쓴다.

TEXT매크로는 유니코드 설정에 따라 문자열 상수의 타입을 변경한다. 유니코드로 컴파일할때는 각 문자가 16비트의 유니코드

문자가되며 그렇지 않을 때는 8비트의 안시(ANSI)문자가 된다.

유니코드로 컴파일 하면 세계의 모든 문자를 단일 코드체계로 표현할수 있어 국제화에 유리하다는 장점이있다.

●64비트 API

64비트에서 달라지는 가장 큰 차이점은 주소 공간이 확대됨으로 해서 포인터의 크기가 64비트로 확장되었다는 점이다.

포인타 타입외 int나 long형은 여전히 32비트를 유지하는데 이런 정수 타입까지 64비트로 확장하면 낭비가 너무 심하기 때문이다.64비트개발 환경은 이식의 편의를 위해 여러가지 중간타입을 제공하는데 고정타입보다는 가급적이면 중간 타입을 사용하는것이 유리하다.

실행되는 환경에 상관없이 일정한 길이를 가져야한다면 이타입을 사용한다. INT32는 항상 32비트의 부호있는 정수형이며,

INT64는 항상 부호있는 64비트 정수 이다.

INT_PTR,LONG_PTR,ULONG_PTR,DWORD_PTR,

뒤에 _PTR이 붙은 타입은 운영체제의 비트수에 따라 크기가 가변적이며 포인터와 같은 길이를 가진다. 포인터와 호환되어야 하는 정수가 필요할때는 이타입을 사용해야한다.

Posted by 레이드리안
|