본문 바로가기
C & C++/C & C++

CWnd 이해하기

by izen8 2011. 3. 29.
반응형
CWnd 이해하기

서론
MFC를 하는 사람들이 한 번은 시도해 보게 된다는 일, MSDN의 CWnd 설명 해석하기. 그만큼 MFC를 함에 있어 CWnd를 이해하는 것은 중요하다. MFC의 수많은 컨트롤들이 CWnd를 상속받기 때문에 CWnd를 제대로 이해하게 되면 컨트롤[각주:1]을 다루기 쉬워지며, 더 나아가 MFC를 이용하는 것이 매우 편해진다.

   MFC를 배우는 사람이 겪는 전형적인 문제는 책에 있는 예제를 따라해서 뭔가 하기는 했는데, 자신이 작성해 놓은 코드가 어떻게 그 일을 하게 되는지 알기 쉽지 않다는 것이다. 그 이유는, MFC는 매우 방대한 라이브러리이기 때문에 MFC의 전체적인 모습을 알지 못하고 그냥 중간에 조금 건드렸기 때문이다. 전체적인 흐름을 알지 못한 채 중간에 있는 것 조금 건드렸기 때문에 그것이 어떻게 동작하는지 알 수 없는 것이다. 바로 그 '전체적인 모습'에 해당하는 것 중 핵심이 CWnd라고 할 수 있겠다. 자, 그럼 CWnd에 대해 살펴 보자.

본론에 들어 가기에 앞서, 윈도우즈(Windows)의 '복수형'은 마이크로소프트 윈도우즈를 지칭하는 말로 운영체제를 의미하며, 윈도우(window)의 '단수형'은 말 그대로 '창', 즉 탐색기나 메모장을 띄울 때의 그 '창'을 의미한다.

본론

CWnd와 Windows의 window의 관계
   실제로 우리가 사용하는 윈도우라는 것은 윈도우즈의 윈도우, 즉 HWND로 지정할 수 있는 윈도우이다. CWnd라는 것은 속성(멤버 변수)으로 하나의 윈도우, 즉 HWND를 갖고 있고, 이 윈도우에 사용하는 많은 함수들을 모아 놓은 하나의 클래스에 불과하다. 즉, HWND라는 것은 진정한 의미에서의 윈도우이고,  CWnd라는 것은 단지 하나의 클래스(말 그대로 멤버 변수와 그에 따른 많은 멤버 함수를 제공하는 클래스)일 뿐이며, 이 클래스의 주된 멤버 변수가 윈도우즈에서 사용하는 실제의 윈도우인 HWND(m_hWnd)이고, CWnd는 이것을 제어하기 위한 많은 함수를 제공한다. 실제로 CWnd 클래스의 정의를 보면

    HWND m_hWnd;            // must be first data member

란 구문이 있다. 즉, 이 클래스의 어떤 특성이든지 이 클래스에 접근하기 위해서는 우선 그에 따른 윈도우(메모리 상에 존재하지 않는 윈도우에 어떤 동작을 수행할 수는 없다)가 존재해야 하는 것이다. 외부에서 프로그래머가 사용하기 위한 데이타 멤버는 HWND m_hWnd밖에 없다.


(편의를 위하여 CWnd 객체를 Cls, window 객체를 Wnd라 하자)

위의 그림에서 보듯이 실제로 우리가 사용하는, 네모나고, 제목 표시줄이 있고 아이콘을 가지며 마우스 움직임을 받는 것은 오른쪽의 윈도우이다. 윈도우라는 하나의 객체를 나타내는 가장 기본이 되는 것, 즉 이 객체의 핸들(주소와 같은 개념)이 CWnd 의 m_hWnd에 연결되게 된다. 그래서 CWnd::GetWindowText();등의 함수를 호출하면, 이 함수는 내부적으로 우선 HWND m_hWnd가 메모리상에 윈도우의 특성을 나타내면서 존재하는 값인지를 확인한다(다른 건 하나도 없이 달랑 HWND  hWnd란 값이 주소형태로 존재하고, 나머지는 윈도우의 특성을 나타내기에 부적당한 값들이 있을 수도 있기 때문에 우선 hWnd에 의한 주소에 가서 그 주소에 있는 구조체가 윈도우의 구조체인지를 확인하는 것이다)[각주:2]. 만약 윈도우를 나타내는 것이 맞는다면 그 때 비로소 윈도우의 문자열을 반환하게 된다. CWnd의 대부분의 멤버 함수가 이런 식의 형태를 띄게 된다. 즉, CWnd 클래스의 멤버 함수는 실제로 자신의 클래스가 갖고 있는 윈도우라는 구조체의 많은 특성들을 참조/변환하기 위한 것이다.

다음 구문을 보며 CWnd 객체를 만들고 파괴시킬 때 어떤 일이 일어나는지 알아 보자.



CWnd *mp_Wnd; //이걸 멤버 변수로 선언했다.

생성자에서

mp_Wnd = NULL; //--->1

뷰에서 마우스 왼쪽 버튼이 클릭되었을 때 다음의 구문을 적어 놓았다.

mp_Wnd = new CWnd(); //--->2
mp_Wnd->Create(NULL,"", WS_OVERLAPPEDWINDOW , CRect(10,10,100,100),this,11); //--->3

mp_Wnd은 CWnd의 포인터이기 때문에 CWnd의 포인터형이 이 클래스가 생성될 때 할당이 된다. 물론 이 값은 쓰레기 값이다. 그런데 생성자가 실행될 때 널로 넣어주고 있으므로 값이 바로 널로 바뀌게 된다. 이 구문은 중요하지 않은 것 같으나 실제로는 초기화를 해주지 않아서 곤란을 겪을 수도 있다. 널로 해주지 않았다고 가정한다면, 디버깅을 할 때 전에 프로그램을 실행시켜서 mp_Wnd에 윈도우를 하나 만들어서 붙였다고 가정할 때, 그 프로그램이 끝났어도, 어떤 경우에는 컴퓨터가 mp_Wnd를 생성시킬 때 이미 전에 만들어 놓고 지우지 않은 곳, 즉 전에 윈도우를 나타내는 포인터를 갖고 있는 바로 그 곳에 다시 이 변수를 잡을 수도 있다. 이 부분에서 어떤 문제가 발생할 수 있는지는 좀 더 있으면 알 수 있다.

2번이 실행되면 mp_Wnd라는 값은 어떤 주소값을 갖게 된다. 그것은 저 위에서 Cls의 위치를 나타내는 값이 되겠다. 하지만, 아직 Wnd를 만든 것이 아니기 때문에 m_hWnd에는 널[각주:3]이 들어가게 된다(Cls와 Wnd가 뭔지는 저 위를 다시 보자!!) 이제 Wnd만 만들면 CWnd는 Wnd에 따른 많은 일을 할 수 있는 하나의 완벽한 CWnd클래스가 될 준비가 끝난 것이다.

3번을 실행하면 실제로 Wnd가 만들어져서 이 Wnd의 핸들(hWnd)이 mp_Wnd의 m_hWnd에 저장된다.

CWnd::Attach(HWND hWnd);라는 함수는 CWnd객체의 m_hWnd값에 hWnd값을 넣어준다는의미로, hWnd가 나타내는 윈도우를 CWnd의 클래스 멤버 함수로 조작하기 위한 준비단계가 되겠다.

CWnd::Detach();함수는 CWnd에 연결된 hWnd를 끊어버리는 것으로 이제 더이상 CWnd객체는 아무 Wnd 도 갖고 있지 않는 것이다. 그러므로 Detach();함수를 호출한 뒤, CWnd의 멤버 함수를 호출하면 에러가 난다. 왜냐 하면, CWnd의 멤버 함수들은 이 클래스가 갖고 있는 멤버 변수인 m_hWnd라는 실제의 윈도우를 조작하기 위한 것들인데, Detach();로 그 m_hWnd값을 없애 버리기 때문에(널로 넣었기 때문에) 더이상 조작할 수 있는 대상이 없기 때문이다.

CWnd::DestroyWindow();라는 함수는, CWnd::m_hWnd가 나타내는 실제의 윈도우를 파괴한다. 즉, CWnd 자체를 파괴하는 것이 아니고, CWnd가 멤버 변수로 갖고 있는 윈도우라는 실체를 파괴하는 것일 뿐이다.

CWnd::GetSafeHwnd();라는 함수는 CWnd의 객체가 갖고 있는 Wnd라는 것, 즉 CWnd의 유일한, 실제의 윈도우의 핸들을 반환해준다. 만약 CWnd라는, 클래스라는 객체만 생성되었고, 아직 실제의 윈도우가 만들어져서 CWnd에 연결된 것(Attach된 것, 즉 CWnd의 m_hWnd에 실제 윈도우의 hWnd가 들어간 것)이 아니라면 널을 반환한다.

윈도우를 생성시킬 때 보통 다음 세 구문을 사용할 수 있다.

if(!mp_Wnd){ ~~~}; // or                  ----->1
if(!mp_Wnd->GetSafeHwnd()); // or         ----->2
if(!::IsWindow(mp_Wnd->GetSafeHwnd()); // ----->3

1번은 CWnd객체가 생성되었는지를 확인한다. 즉 실제의 윈도우인 Wnd라는 것의 생성 여부는 확인하지 않는다. 이 구문이 실행되려면 mp_Wnd가 널일 경우이므로 이 구문은 비교적 안정하다고 할 수 있다. 하지만, 만약 mp_Wnd를 널로 초기화하지 않았다거나 예전에 이것에 관계된 윈도우를 파괴시킬 때

mp_Wnd->DestroyWindow();
delete mp_Wnd;

로 했다면, 프로그래머는 이 구문이 실행될 것을 기대하지만, 실제로는 실행되지 않는다. 왜냐 하면, mp_Wnd->DestroyWindow();구문은 mp_Wnd->m_hWnd가 가리키는 실제의 윈도우 객체를 파괴하는 것이므로 mp_Wnd를 널로 만들지 않고, delete mp_Wnd;구문도 결코 mp_Wnd라는 값을 널로 만들지는 않기 때문이다. 따라서 윈도우를 생성할 때 1번과 같은 구문으로 생성하고 정확한 결과를 기대할려면 윈도우를 파괴할 때

mp_Wnd->DestroyWindow();
delete mp_Wnd;
mp_Wnd = NULL; //--->요 구문을 꼭 써 넣어야 한다.

2번과 같이 생성을 하는 경우는 mp_Wnd->m_hWnd의 값이 널이 아닐 경우에 실행된다. mp_Wnd->m_hWnd에 널이 들어가는 경우는 mp_Wnd->DestroyWindow();나 mp_Wnd->Detach();를 실행한 후이다. 이 구문은 윈도우를 파괴할 때 mp_Wnd->DestroyWindow();로만으로도 생성/파괴를 반복할 수 있다. 하지만 여기서 문제점은  delete mp_Wnd;라는 구문을 해주지 않았기 때문에 mp_Wnd가 가리키는 메모리의 위치가 계속 바뀌면서 새로 생성되어서 결국 메모리 누수를 가져온다는 것이다. 따라서 2번과 같이 윈도우를 생성하고 윈도우의 생성/파괴를 반복하기 위해서는 윈도우를 다음과 같이 파괴해야 한다.

mp_Wnd->DestroyWindow();
delete mp_Wnd;
mp_Wnd = NULL; --->요 구문을 꼭 써 넣어야 한다.

너무 위에 있으니 다시 한 번 적어 본다.

if(!::IsWindow(mp_Wnd->GetSafeHwnd()) ----->3

3번과 같이 생성하는 경우. 가장 안전하고 가장 올바른 경우라 할 수 있다. 우선 CWnd::GetSafeHwnd();는 CWnd와 연결된 hWnd가 있으면 그것을 반환해주고, 없으면 널을 반환해준다. 또한 IsWindow();라는 함수는 hWnd가 가리키는 것이 실제의 윈도우인지, 그러니까 이게 값만 덜렁 갖고 있고, 실제로 그 주소로 가보니까 윈도우의 모양새를 한 녀석이 아닌, 얼토당토 않은 놈은 아닌지, 이 모든 걸 확인해 준다. 따라서 이 함수의 의미는 mp_Wnd가 가리키는 것이 정말 윈도우가 되는가를 가장 정확하게 확인해 주는 구문이라 할 수 있다. 물론 이 때는 mp_Wnd->DestroyWindow();함수로만 지워도 되기는 하나, 좀 더 명확성을 위해서 1,2번처럼 파괴시켜 주는 것이 좋다.

자, 그럼 1번과 같이 생성시키는 루틴을 집어 넣고, 만약 mp_Wnd를 초기화해주지 않는다면 어떤 일이 일어날 수도 있는지 살펴 보자. 만약 지금 프로그램을 디버깅하는 단계라서 수시로 중단했다 다시 실행시키고 있는 중이라면 초기화를 해주지 않는 것은 상당한 문제가 될 수 있다. 만약 mp_Wnd를 생성했다가 이에 연결된 hWnd를 파괴하는 과정 없이 프로그램을 끝냈다고 가정하자. 그러면 물론 mp_Wnd라는 것은 메모리에서 해제가 되었을지라도 그에 연결된 hWnd는 완전히 해제되지 않은 상태이다. 그 상태에서 다시 프로그램을 구동시키면 mp_Wnd에 처음에 자동으로 쓰레기값이 들어가는 데(멤버 변수이기 때문에)그 값이 공교롭게도 전에 있던 위치 그대로가 될 수 있다. 그러면 그 위치의 m_hWnd가 가리키는 것은 여전히 윈도우의 형태를 하고 있을 수 있는 것이다. 따라서 1번과 같이 하는 것은 바람직하다고 할 수 없다.


정리하면 윈도우를 생성하고 파괴하는 가장 안정적이고 올바른 루틴은 다음과 같다.

--생성에서는

if(!::IsWindow(mp_Wnd->GetSafeHwnd())){
    ~~~여기서 생성시킨다.
}

--파괴에서는

if(::IsWindow(mp_Wnd->GetSafeHwnd())){
    mp_Wnd->DestroyWindow(); //mp_Wnd에 붙어 있는 hWnd의 실제 윈도우 파괴
delete mp_Wnd; // mp_Wnd를 메모리 상에서 해제
mp_Wnd = NULL;// 다시 초기화
}

결론 이로써 CWnd가 사실은 API로 작성할 때의 window라는 것을 알았고, 우리가 보는 윈도우 바로 그 창에 여러 가지 동작을 할 수 있는 멤버 함수를 제공하고 있는 객체라는 것을 알게 되었다. 윈도우를 생성할 때 부모 윈도우를 설정하게 되어 있는데, 뷰의 윈도우를 부모로 지정해 주면 버튼 컨트롤을 뷰의 중간에 떵그러니 만들 수도 있는 것이다.

///////////////////////////////////////////////////////////////////////////////////////////////////

CWnd와 Windows의 window의 관계

실제로 우리가 사용하는 윈도우라는 것은 윈도우즈의 윈도우, 즉 HWND로 지정할 수 있는 윈도우이다. CWnd라는 것은 하나의 윈도우, 즉 HWND를 갖고 있고,이 윈도우에 사용하는 많은 함수들을 모아 놓은 하나의 클래스에 불과하다. 즉, HWND라는 것은 진정한 의미에서의 윈도우이고,  CWnd라는 것은 단지 하나의 클래스(말 그대로 멤버 변수와 그에 따른 많은 멤버 함수를 제공하는 클래스)일 뿐이며, 이 클래스의 주된 멤버 변수가 윈도우즈에서 사용하는 실제의 윈도우인 HWND(m_hWnd)이고, 이것을 제어하기 위한 많은 함수를 제공한다. 실제로 CWnd 클래스의 정의를 보면 

    HWND m_hWnd;            // must be first data member

란 구문이 있다. 즉, 이 클래스의 어떤 특성이든지 이 클래스에 접근하기 위해서는 우선 그에 따른 윈도우(운영 체제의 실제 윈도우)가 존재해야 하는 것이다. 외부에서 프로그래머가 사용하기 위한 데이타 멤버는 HWND m_hWnd밖에 없다. 


        CWnd                                                       Window
         |                                                                 |
    HWND m_hWnd;  ----이게 이걸루 연결된다----> HWND hWnd;//핸들 
                                                                        WNDCLASS WndClass; //모양
 그외의 멤버 함수들                                             HMENU hMenu;//메뉴
                                                                          ...등등등...

   <CWnd 객체의 모양새>                    <실제 윈도우 구조체의 모양새>
<편의를 위해 Cls라고 하자>                   <편의를 위해 Wnd라고 하자>

위의 그림에서 보듯이 실제로 우리가 사용하는, 네모나고, 제목 표시줄이 있고 아이콘을 가지며 마우스 움직임을 받는 것은 오른쪽의 윈도우이다. 윈도우라는 하나의 객체를 나타내는 가장 기본이 되는 것, 즉 이 객체의 핸들(주소와 같은 개념)이 CWnd 의 m_hWnd에 연결된다. 그래서 CWnd::GetWindowText();등의 함수를 호출하면, 이 함수는 내부적으로 우선 HWND m_hWnd가 메모리상에 윈도우의 특성을 나타내면서 존재하는 값인지를 확인한다(다른 건 하나도 없이 달랑 HWND  hWnd란 값이 주소형태로 존재하고, 나머지는 윈도우의 특성을 나타내기에 부적당한 값들이 있을 수도 있기 때문에 우선 hWnd에 의한 주소에 가서 그 주소에 있는 구조체가 윈도우의 구조체인지를 확인하는 것이다). 만약 윈도우를 나타내는 것이 맞는다면 그 때 비로소 윈도우의 문자열을 반환하게 된다. CWnd의 대부분의 멤버 함수가 이런 식의 형태를 띄게 된다. 즉, CWnd 클래스의 멤버 함수는 실제로 자신의 클래스가 갖고 있는 윈도우라는 구조체의 많은 특성들을 참조/변환하기 위한 것이다. 

다음 구문을 보며 실제로 어떤 일이 일어나는 지 확인해보자.

CWnd *mpWnd; //이걸 멤버 변수로 선언했다.

생성자에서 

mp_Wnd = NULL; --->1

뷰에서 마우스 왼쪽 버튼이 클릭되었을 때 다음의 구문을 적어 놓았다.

mp_Wnd = new CWnd(); --->2
mp_Wnd->Create(NULL,"", WS_OVERLAPPEDWINDOW , CRect(10,10,100,100),this,11);---
>3


1번이 실행되기 전에는, mp_Wnd라는 값은 CWnd의 포인터이기 때문에 CWnd의 포인터형이 할당되어 있다. 물론 이 값은 쓰레기 값이다. 그런데 생성자가 실행될 때 널로 넣어주고 있으므로 값이 바로 널로 바뀌게 된다. 이 구문은 중요하지 않은 것 같으나 실제로는 초기화해주지 않아서 곤란을 겪을 수도 있다. 널로 해주지 않았다고 가정한다면, 디버깅을 할 때 전에 프로그램을 실행시켜서 mp_Wnd에 윈도우를 하나 만들어서 붙였다고 가정할 때, 그 프로그램이 끝났어도, 어떤 경우에는 컴퓨터가 mp_Wnd를 생성시킬 때 이미 전에 만들어 놓고 지우지 않은 곳, 즉 전에 윈도우를 나타내는 포인터를 갖고 있는 바로 그 곳에 다시 이 변수를 잡을 수도 있다. 이 부분에서 어떤 문제가 발생할 수 있는지는 좀 더 있으면 알 수 있다. 

2번이 실행되면 mp_Wnd라는 값은 어떤 주소값을 갖게 된다. 그것은 저 위에서 Cls의 위치를 나타내는 값이 되겠다. 하지만, 아직 Wnd를 만든 것이 아니기 때문에 m_hWnd에는 널이 들어가게 된다(Cls와 Wnd가 뭔지는 저 위를 다시 보자!!) 이제 Wnd만 만들면 CWnd는 Wnd에 따른 많은 일을 할 수 있는 하나의 완벽한 CWnd클래스가 될 준비가 끝난 것이다. 

3번을 실행하면 실제로 Wnd가 만들어져서 이 Wnd의 핸들(hWnd)이 mp_Wnd의 m_hWnd에 
저장된다. 

CWnd::Attach(HWND hWnd);라는 함수는 CWnd객체의 m_hWnd값에 hWnd값을 넣어준다는의미로, hWnd가 나타내는 윈도우를 CWnd의 클래스 멤버 함수로 조작하기 위한 준비단계
가 되겠다.

CWnd::Detach();함수는 CWnd에 연결된 hWnd를 끊어버리는 것으로 이제 더이상 CWnd객
체는 아무 Wnd 도 갖고 있지 않는 것이다. 그러므로 Detach();함수를 호출한 뒤, CWnd의 멤버 함수를 호출하면 에러가 난다. 왜냐 하면, CWnd의 멤버 함수들은 이 클래스가 갖고 있는 멤버 변수인 m_hWnd라는 실제의 윈도우를 조작하기 위한 것들인데, Detach();로 그 m_hWnd값을 없애 버리기 때문에(널 혹은 INVALID_HANDLE_VALUE로 넣었기 때문에) 더이상 조작할 수 있는 대상이 없기 때문이다. 

CWnd::DestroyWindow();라는 함수는, CWnd::m_hWnd가 나타내는 실제의 윈도우를 파괴한다. 즉, CWnd 자체를 파괴하는 것이 아니고, CWnd가 멤버 변수로 갖고 있는 윈도우라는 실체를 파괴하는 것일 뿐이다. 

CWnd::GetSafeHwnd();라는 함수는 CWnd의 객체가 갖고 있는 Wnd라는 것, 즉 CWnd의 유일한, 실제의 윈도우의 핸들을 반환해준다. 만약 CWnd라는, 클래스라는 객체만 생성되었고, 아직 실제의 윈도우가 만들어져서 CWnd에 연결된 것(Attach된 것, 즉 CWnd의 m_hWnd에 실제 윈도우의 hWnd가 들어간 것)이 아니라면 널을 반환한다. 

윈도우를 생성시킬 때 보통 다음 세 구문을 사용할 수 있다.

if(!mp_Wnd){ ~~~} or                  ----->1
if(!mp_Wnd->GetSafeHwnd()) or         ----->2
if(!::IsWindow(mp_Wnd->GetSafeHwnd()) ----->3

1번은 CWnd객체가 생성되었는지를 확인한다. 즉 실제의 윈도우인 Wnd라는 것의 생성 여부는 확인하지 않는다. 이 구문이 실행되려면 mp_Wnd가 널일 경우이므로 이 구문은 비교적 안정하다고 할 수 있다. 하지만, 만약 mp_Wnd를 널로 초기화하지 않았다거나 예전에 이것에 관계된 윈도우를 파괴시킬 때 

mp_Wnd->DestroyWindow();
delete mp_Wnd;

로 했다면, 프로그래머는 이 구문이 실행될 것을 기대하지만, 실제로는 실행되지 않는다. 왜냐 하면, mp_Wnd->DestroyWindow();구문은 mp_Wnd->m_hWnd가 가리키는 실제의 윈도우 객체를 파괴하는 것이므로 mp_Wnd를 널로 만들지 않고, delete mp_Wnd;구문도 결코 mp_Wnd라는 값을 널로 만들지는 않기 때문이다. 따라서 윈도우를 생성할 때 1번과 같은 구문으로 생성하고 정확한 결과를 기대할려면 윈도우를 파괴할 때 

mp_Wnd->DestroyWindow();
delete mp_Wnd;
mp_Wnd = NULL; --->요 구문을 꼭 써 넣어야 한다.

2번과 같이 생성을 하는 경우는 mp_Wnd->m_hWnd의 값이 널이 아닐 경우에 실행된다. 
mp_Wnd->m_hWnd에 널이 들어가는 경우는 mp_Wnd->DestroyWindow();나 
mp_Wnd->Detach();를 
실행한 후이다. 이 구문은 윈도우를 파괴할 때 mp_Wnd->DestroyWindow();로만으로도 생성/파괴를 반복할 수 있다. 하지만 여기서 문제점은 delete mp_Wnd;라는 구문을 해주지 않았기 때문에 mp_Wnd가 가리키는 메모리의 위치가 계속 바뀌면서 새로 생성되어서 결국 메모리 누수를 가져온다는 것이다. 따라서 2번과 같이 윈도우를 생성하고 윈도우의 생성/파괴를 반복하기 위해서는 윈도우를 다음과 같이 파괴해야 한다. 

mp_Wnd->DestroyWindow();
delete mp_Wnd;
mp_Wnd = NULL; --->요 구문을 꼭 써 넣어야 한다.

너무 위에 있으니 다시 한 번 적어 본다.

if(!::IsWindow(mp_Wnd->GetSafeHwnd()) ----->3

3번과 같이 생성하는 경우. 가장 안전하고 가장 올바른 경우라 할 수 있다. 우선 CWnd::GetSafeHwnd();는 CWnd와 연결된 hWnd가 있으면 그것을 반환해주고, 없으면 널을 반환해준다. 또한 IsWindow();라는 함수는 hWnd가 가리키는 것이 실제의 윈도우인지, 그러니까 이게 값만 덜렁 갖고 있고, 실제로 그 주소로 가보니까 윈도우의 모양새를 한 녀석이 아닌, 얼토당토 않은 놈은 아닌지, 이 모든 걸 확인해 준다. 따라서 이 함수의 의미는 mp_Wnd가 가리키는 것이 정말 윈도우가 되는가를 가장 정확하게 확인해주는 구문이라 할 수 있다. 물론 이 때는 mp_Wnd->DestroyWindow();함수로만 지워도 되기는 하나, 좀 더 명확성을 위해서 1,2번처럼 파괴시켜 주는 것이 좋다. 

자, 그럼 1번과 같이 생성시키는 루틴을 집어 넣고, 만약 mp_Wnd를 초기화해주지 않는다면 어떤 일이 일어날 수도 있는지 살펴 보자. 만약 지금 프로그램을 디버깅하는 단계라서 수시로 중단했다 다시 실행시키고 있는 중이라면 초기화를 해주지 않는 것은 상당한 문제가 될 수 있다. 만약 mp_Wnd를 생성했다가 이에 연결된 hWnd를 파괴하는 과정 없이 프로그램을 끝냈다고 가정하자. 그러면 물론 mp_Wnd라는 것은 메모리에서해제가 되었을지라도 그에 연결된 hWnd는 완전히 해제되지 않은 상태이다. 그 상태에서 다시 프로그램을 구동시키면 mp_Wnd에 처음에 자동으로 쓰레기값이 들어가는 데(멤버 변수이기 때문에)그 값이 공교롭게도 전에 있던 위치 그대로가 될 수 있다. 그러면 그 위치의 m_hWnd가 가리키는 것은 여전히 윈도우의 형태를 하고 있을 수 있는 것이다. 따라서 1번과 같이 하는 것은 바람직하다고 할 수 없다. 

정리하면 윈도우를 생성하고 파괴하는 가장 안정적이고 올바른 루틴은 다음과 같다.

--생성에서는

if(!::IsWindow(mp_Wnd->GetSafeHwnd())){
    ~~~여기서 생성시킨다.
}

--파괴에서는

if(::IsWindow(mp_Wnd->GetSafeHwnd())){
    mp_Wnd->DestroyWindow(); //mp_Wnd에 붙어 있는 hWnd의 실제 윈도우 파괴
    delete mp_Wnd; // mp_Wnd를 메모리 상에서 해제
    mp_Wnd = NULL; // 다시 초기화
}

///////////////////////////////////////////////////////////////////////////////////////////

- CWnd 클래스는 MFC의 모든 윈도우 클래스들에 대해서 기본적인 기능을 제공 하는 클래스이다. 

데이터 멤버
m_hWnd : CWnd와 관련된 HWND를 가리킨다. 


생성/소멸 관련 함수
CWnd : CWnd객체를 생성한다.
DestroyWindow : 윈도우를 소멸한다. 그렇지만 객체를 소멸시키는 것은 아니다. 


초기화 관련 함수
Create : CWnd 객체와 관련된 자식 윈도우를 만들고 초기화한다.
PreCreateWindow : CWnd 객체와 관련된 실제 윈도우를 만들기 전에 호출된다.
CaleWindowRect : 클라이언트 사각형 영역에서 윈도우를 만들기 전에 호출된다.
GetStyle : 현재 윈도우의 스타일을 반환한다.
GetExStyle : 확장된 윈도우의 스타일을 반환한다.
Attach : CWnd 객체에 윈도우 핸들을 추가한다.
Detach : CWnd 객체에서 윈도우 핸들을 분리하고 핸들을 반환한다.
PreSubclassWindow : SubclassWindow가 호출되기 전에 필요한 다른 서브클래싱이 일어나 는 것을 허용한다.
SubclassWindow : CWnd 객체에 윈도우를 추가하고 CWnd의 메시지맵을 통해서 루트 메시 지로 만든다.
UnSubclassWindow : CWnd 객체에서 윈도우를 분리한다.
FromHandle : 윈도우에 핸들이 주어질 때 CWnd 객체에 대한 포인터를 반환한다. CWnd 객체가 핸들을 가지지 않는다면, 임시적인CWnd 객체기 생성되고 추가된다.
FromHandlePermanent : 윈도우에 핸들이 주어질 때 CWnd 객체에 대한 포인터를 반환한다. 
CWnd 객체가 핸들을 가지지 않는다면, NULL이 반환된다.
DeleteTempMap : CWinApp가 자동으로 호출하며 FromHandle에 의해서 생성된 어떠한 임시 CWnd 객체도 지운다.
GetSafeHwnd : 포인터가 NULL이면, m_hWnd, 또는 NULL을 반환된다.
CreateEx : 오버랩된 형태의 팝업 자식 윈도우를 생성하고 이것을 CWnd 객체에 추가한다
CreateControl : MFC 프로그램에서 CWnd 객체에 의해서 표현되는 OLE 컨트롤을 생성한다. 


윈도우 상태 함수
IsWindowEnabled : 윈도우에 마우스와 키보드 입력이 가능한지를 결정한다.
EnableWindow : 윈도우에 마우스와 키보드로 입력을 가능하게 하거나 불가능하도록 한다.
GetActiveWindow : 활성 윈도우를 얻는다.
SetActiveWindow : 윈도우를 활성화한다.
GetCapture : 마우스를 캡쳐한 CWnd를 얻는다.
SetCapture : 모든 일련의 마우스 입력이 CWnd로 보내지도록 한다.
GetFocus : CWnd가 현재 입력 포커스를 가지고 있는지 검사한다.
SetFocus : 입력 포커스를 설정한다.
GetDestktopWindow : 윈도우 시스템의 desktop윈도우를 얻는다.
GetForegroundWindow : 포그라운드 윈도우의 포인터를 반환한다.
SetForegroundWindow : 생성된 윈도우의 스레드를 포그라운드로 설정하고 윈도우를 활성 화 한다.
GetIcon : 핸들에서 아이콘을 얻는다.
SetIcon : 핸들에 특정 아이콘을 설정한다.
GetWindowContextHelpId : 도움말 항목에 대한 식별자를 얻는다.
SetWindowContextHelpId : 도움말 항목에 대한 식별자를 지정한다.
ModifyStyle : 현재 윈도우의 스타일을 수정한다.
ModifyStyleEx : 확장된 윈도우의 스타일을 수정한다.
 
IsWindow(HWND hWnd):  윈도우가 존재하면 TRUE 아니면 FALSE
IsWindowVisible(HWND hWnd): 윈도우가 보이면 TRUE 아니면 FALSE

윈도우의 크기와 위치
GetWindowPlacement : 윈도우가 보여지는 상태와 정상(복귀된), 최소, 최대화된 윈도우의 위치를 얻는다.
SetWindowPlacement : 윈도우가 보여지는 상태와 정상(복귀된), 최소, 최대화된 윈도우의 위치를 설정한다.
IsIconic : CWnd가 최소화되었는지를 알아본다.
IsZoomed : CWnd가 최대화되었는지를 알아본다.
MoveWindow : CWnd의 위치또는 크기를 변경한다.
SetWindowPos : 크기, 위치, 순서, 팝업, 최상위 윈도우에 대한 것을 설정한다.
ArrangeIconicWindows : 모든 축소된(아이콘화 된) 자식 윈도우에 대한 것을 설정한다.
BringWindowToTop : CWnd를 오버랩 된 윈도우의 맨 처음으로 보낸다.
GetWindowRect : CWnd의 화면 좌표를 얻는다.
GetClientRect : CWnd 클라이언트 영역의 크기를 얻는다. 


윈도우 참조 관련 함수
ChildWinddowFromPoint : 어떤 자식 윈도우가 특정 점을 포함하고 있는지를 알아낸다.
FindWindow : 윈도우의 이름과 클래스로 확인이 가능한 윈도우의 핸들을 반환한다.
GetNextWindow : 윈도우 관리자의 리스트에서 다음 또는 이전 윈도우를 반환한다.
GetOwner : CWnd의 소유자에 대한 포인터를 얻는다.
SetOwner : CWnd의 소유자를 변경한다.
GetTopWindow : CWnd에 속한 맨 첫 번째 자식 윈도우를 반환한다.
GetWindow : 이 윈도우와 특정한 관계를 가지고 있는 윈도우를 반환한다.
GetLastActivePopup : CWnd이 가지고 있는 팝업 윈도우가 가장 최근에 활성화 되었는지를 알아낸다.
IsChild : CWnd가 자식 윈도우인지 또는 다른 특정 윈도우의 후손인지를 알아낸다.
GetParent : CWnd의 부모 윈도우가 있다면 그 윈도우를 얻는다.
GetSafeOwner : 지정된 윈도우의 소유자를 얻는다.
SetParent : 부모 윈도우를 변경한다.
WindowFromPoint : 특정 점을 포함하는 윈도우를 알아낸다.
GetDlgItem : 특정 대화상자에서 특정 ID의 컨트롤을 얻는다.
GetDlgCtrlID : CWnd가 자식 윈도우이면, 자신의 ID 값을 반환한다.
SetDlgCtrlID : 윈도우에 윈도우 또는 컨트롤의 ID를 설정한다.
GetDescendantWindow : 모든 자식 윈도우를 검색하고 윈도우의 특징 ID를 반환한다.
GetParentFrame : CWnd 객체의 부모 프레임 윈도우를 얻는다.
SendMessageToDescendants : 윈도우의 모든 자식 윈도우에게 메시지를 보낸다.
GetToLevelParent : 윈도우의 최상위 부모를 얻는다.
GetToLevelOwner : 최상위 윈도우를 얻는다.
GetParentOwner : 자식 윈도우의 부모 윈도우에 대한 포인터를 반환한다.
GetTopLevelFrame : 윈도우의 촤상위 프레임 윈도우를 얻는다.
UpdateDialogControls : 대화상자의 버튼이나 다른 컨트롤들의 상태 갱신을 요구한다.
UpdateData : 대화상자의 데이터를 초기화하고 유효화한다.
CenterWindow : 부모 윈도우의 중앙에 윈도우를 위치시킨다. 


갱신/그리기 함수
BeginPaint : 드로잉 작업을 수행하기 위해서 CWnd를 준비한다.
EndPaint : 드로임 작업을 마친다.
Print : 특정 디바이스 컨텍스트에 현재 윈도우를 그린다.
PrintClient : 특정 디바이스 컨텍스트에 모든 윈도우를 그린다.
LockWindowUpdate : 정해진 윈도우에 드로잉을 불가능하도록 하거나 다시 가능하도록 한다.
GetDC : 클라이언트 영역에 표시된 디바이스 컨텍스트를 얻는다.
GetDCEx : 클라이언트 영역에 표시된 디바이스 컨텍스트를 얻고, 그리는 도중에 클리핑이 가능하도록 한다.
RedrawWindow : 클라이언트 영역에서 특정 사각형이나 특정 영역을 갱신한다.
GetWindowDC : 툴바나, 메뉴, 스크롤 바를 포함한 모든 윈도우 영역에 대한 디바이스 컨 텍스트를 얻는다.
ReleaseDC : 클라이언트와 윈도우 디바이스 컨택스트를 해제함으로써, 다른 애플리케이션 이 사용할 수 있도록 한다.
UpdateWindow : 클라이언트 영역을 갱신한다.
SetRedraw : CWnd가 변화된 것을 다시 그리도록 설정하거나, 다시 그릴 수 없도록 설정 하는 역할을 한다.
GetUpdateRect : CWnd의 갱신 영역을 완전히 둘러싸는 가장 작은 사각형의 좌표를 얻는다.
GetUpdateRgn : CWnd의 갱신 영역을 얻는다.
Invalidate : 모든 클라이언트 영역을 무효화한다.
InvalidateRect : 현재의 갱신 영역에 사각형을 추가함으로써 정해진 사각형 내의 클라이언 트 영역을 무효화한다.
InvalidateRgn : 현재의 갱신 영역에 영역을 추가함으로써 정해진 영역내의 클라이언트 영 역을 무효화한다.
VaildateRect : 현재의 갱신 영역에서 사각형을 제거함으로써 정해진 사각형 내의 클라이 언트 영역을 유효화시킨다.
VaildateRgn : 현재의 갱신 영역에 영역을 제거함으로써 정해진 영역 내의 클라이언트 영 역을 유효화시킨다.
ShowWindow : 윈도우를 보이도록 하거나 숨긴다.
IsWindowVisible : 윈도우가 보이는지를 알아낸다.
ShowOwnedPopups : 윈도우가 가지고 있는 모든 팝업 윈도우를 보이게 하거나 숨긴다.
EnableScrollBar : 스크롤 바의 화살표를 사용가능하도록 하거나 불가능하게 한다. 


좌표 매핑 관련 함수
MapWindowPoints : CWnd의 좌표계로부터 다른 윈도우의 좌표계로 지정된 점들을 매핑시 킨다.
ClientToSreen : 클라이언트 좌표계를 화면 좌표계로 변환한다.
ScreenToClient : 화면 좌표계를 클라이언트 좌표계로 변환한다. 


윈도우 텍스트 함수
SetWindowText : 윈도우의 텍스트나 캡션 제목을 지정된 텍스트로 설정한다.
GetWindowText : 윈도우의 텍스트나 캡션 제목을 반환한다.
GetWindowTextLength : 윈도우의 텍스트나 캡션 제목의 길이를 반환한다.
SetFont : 현재의 폰트를 설정한다.
GetFont : 현재의 폰트를 얻는다. 


스크롤 관련 함수
GetScrollPos : 스크롤 박스의 현재 위치를 얻는다.
GetScrollRange : 지정된 스크롤 바에 대한 최소, 최대의 스크롤 바 위치 값을 얻는다.
ScrollWindow : 클라이언트 영역의 내용을 스크롤한다.
ScrollWindowEx : 클라이언트 영역의 내용을 스크롤한다. (ScrollWindow과 비슷)
GetScrollInfo : 스크롤 바에 대한 SCROLLINFO 구조체 값을 얻는다.
GetScrollLimit : 스크롤 바의 한계 값을 얻는다.
SetScrollInfo : 스크롤 바에 대한 정보를 설정한다.
SetScrollPos : 스크롤 박스의 현재 위치를 설정하고, 설정이 되면, 새로운 위치를 나타내 도록 스크롤 바를 다시 그린다.
SetScrollRange : 지정된 스크롤 바에 대한 최소와 최대 위치 값을 지정한다.
ShowScrollBar : 스크롤 바를 보이거나 숨긴다.
EnableScrollBarCtrl : 스크롤 바의 컨트롤을 가능하게 하거나 불가능하도록 한다.
GetScrollBarCtrl : 스크롤 바 컨트롤을 반환한다.
RepositionBars : 클라이언트 영역에 컨트롤 바를 재위치 시킨다. 


드래그-드롭 함수
DragAcceptFiles : 윈도우가 드래그된 파일을 받아들일 것인지를 결정한다. 


Caret 관련 함수
CreateCaret : 시스템 캐럿으로 새로운 형태를 생성하고 캐럿의 소유권을 얻는다.
CreateSolidCaret : 시스템 캐럿으로 솔리드 캐럿을 생성하고 캐럿의 소유권을 얻는다.
CreateGrayCaret : 시스템 캐럿으로 회색 캐럿을 생성하고 캐럿의 소유권을 얻는다.
GetCaretPos : 특정 위치로 캐럿을 이동시킨다.
SetCaretPos : 화면에서 캐럿을 숨긴다.
HideCaret : 캐럿의 현재 위치에서 캐럿을 보이도록 한다.
ShowCaret : 캐럿의 현재 위치에서 캐럿을 보이도록 한다. 일단 캐럿이 화면에 나타나면 캐럿은 자동적으로 깜박거리게 된다. 


대화상자 아이템 관련 함수
CheckDlgButton : 버튼 컨트롤 다음에 체크 표시를 하거나 버튼 컨트롤에서 체크 표시를 제거한다.
CheckRadioButton : 특정 라디오 버튼을 체크하고, 특정 버튼 그룹 내에 있는 모든 다른 라디오 버튼에서 체크 표시를 제거한다.
GetCheckedRadioButton : 버튼 그룹에서 현재 체크된 라디오 버튼의 ID를 반환한다.
DlgDirList : 파일이나 디렉토리에 대한 리스트로 리스트 박스를 채운다.
DlgDirListComboBox : 파일이나 디렉토리에 대한 리스트 콤보 박스를 채운다.
DlgDirSelect : 리스트 박스에서 현재 선택된 항목을 얻는다.
DlgDirSelectComboBox : 콤보 박스에서 현재 선택된 항목을 얻는다.
GetDlgItemInt : 지정된 대화상자에서 컨트롤이 사용하는 텍스트를 정수 값으로 변환한다.
GetDlgItemText : 컨트롤과 관련된 캡션이나 텍스트를 얻는다.
GetNextDlgGroupItem : 컨트롤 그룹 내의 다음 또는 이전 컨트롤을 찾는다.
GetNextDlgTabItem : 특정 컨트롤의 다음 또는 이전 컨트롤 중에서 WS_TABSTOP속성을 가 지는 컨트롤을 얻는다.
IsDlgButtonChecked : 버튼 컨트롤이 체크되었는지를 결정한다.
IsDialogItemMessage : 지정된 메시지가 모달리스(modeless)대화상자를 위한 것인지를 알아 내고, 만약에 그렇다면 그것을 처리한다.
SendDigItemMessage : 특정 컨트롤에 메시지를 보낸다.
SendDigItemInt : 지정된 대화상자에서 컨트롤이 사용하는 텍스트를 정수 값에 해당하는 문 자열로 설정한다.
SendDigItemText : 지정된 대화상자에서 컨트롤의 캡션이나 텍스트를 설정한다.
SubclassDlgItem : CWnd 컨트롤에 윈도우 컨트롤을 추가하고 CWnd의 메시지 맵을 통해 메시지를 배정하도록 한다.
ExecuteDlgInit : 해당 대화상자의 리소스로 초기화한다.
RunModalLoop : 모달 상태에 있는 윈도우의 메시지를 검색하고, 번역하거나, 처리한다.
ContinueModal : 윈도우 모달 상태를 지속시킨다.
EndModalLoop : 윈도우 모달 상태를 마친다. 


메뉴 함수
GetaMenu : 특정 메뉴에 대한 포인터를 얻는다.
SetMenu : 현재의 메뉴를 지정된 메뉴로 설정한다.
DrawMenuBar : 메뉴 바를 다시 그린다.
GetSystemMenu : 애플리케이션이 컨트롤 메뉴를 복사하거사 수정하도록 참조하는 것을 허용한다.
HiliteMenuItem : 최상위 메뉴 아이템에서 선택된 부분을 하이라이트하거나 해제한다. 


툴팁 함수
EnableToolTips : 툴팁 컨트롤을 사용가능하도록 한다.
CancelToolTips : 툴팁 컨트롤을 사용 불가능하도록 한다.
FilterToolTipMessage : 대화상자에서 컨트롤과 관련된 제목이나 텍스트를 얻는다.
OnToolHitTest : 포인터가 특정 도구의 사각형 경계(보통 툴바 영역)안에 있는지를 알아내 고 그 도구에 대한 정보를 얻는다. 


타이머 관련 함수
SetTimer : 시작될 때 WM_TIMER 메시지를 보내는 시스템 타미머를 설치한다.
KillTimer : 타이머를 해제한다. 


경고 함수
FlashWindow : 윈도우를 한 번 반짝이게 한다.
MessageBox : 애플리케이션이 제공하는 캡션과 메시지를가지고 있는 윈도우를 생성하고 화면에 출력한다. 


윈도우 메시지 관련 함수
GetCurrentMessage : 윈도우가 현재 처리하고 있는 메시지의 포인터를 반환한다. OnMessage 류의 메시지 핸들러 멤버 함수 내부에서만 호출되어야한다.
Default : 디폴트 윈도우 프로시저를 호출하며, 이것은 애플리케이션에게 어떤 윈도우 메 시지도 디폴트 형태로 처리하도록 한다.
PreTranslateMessage : TranslateMessage와 DispatchMessage 윈도우 함수에서 처리되기 전 에 윈도우의 메시지를 필터링하기 위해서 CWinApp가 사용한다.
SendMessage : CWnd 객체에 메시지를 보내고 메시지를 처리할 때 까지 반환되지 않는다.
PostMessage : 애플리케이션 큐에 메시지를 위치시키고, 윈도우가 메시지를 처리할 때까 지 기다리지 않고 바로 반환한다.
SendNotifyMessage : 특정 메시지를 윈도우에 보내고 호출한 스래드가 윈도우를 생성했는 지에 따라서, 가능한 빨리 반환한다.


클립보드 관련 함수
ChangeClipboardChain : 클립보드 뷰어의 체인으로부터 CWnd를 제거한다.
SetClientboardViewer : 클립보드의 내용이 변하면 윈도우의 체인에 CWnd를 추가한다.
SetClipboard : 클립보드를 연다. 다른 애플리케이션이 윈도우의 CloseClipboard 함수를 호 출할 때까지 클립보드를 수정하지 않도록 한다.
GetClipboardOwner : 클립보드의 현재 소유자에 대한 포인터를 얻는다.
GetOpenClipboardWindow :현재 클립보드가 열려진 윈도우에 대한 포인터를 얻는다.
GetClipboardViewer : 클립보드 뷰어의 체인에서 처음 윈도우에 대한 포인터를 얻는다. 


OLE 콘트롤
SetProperty : OLE 컨트롤 프로퍼티를 설정한다.
OnAmbientProperty : 환경 프로퍼티 값을 구현한다.
GetControlUnknown : 알려지지 않은 OLE 컨트롤에 대한 포인터를 얻는다.
GetProperty : OLE 컨트롤 프로퍼티를 얻는다.
InvokeaHelper : OLE 컨트롤의 메소드나 프로퍼티를 호출한다. 


오버라이드 가능한 함수
WindowProc : CWnd에 대한 디폴트 프로시저를 제공한다. 디폴트로 메시지 맵을 통해서 메시지를 처리하게 된다.
DefWindowProc : 디폴트 윈도우 프로시저를 요구하며, 이것은 애플리케이션이 처리하지 않은 모든 윈도우 메시지에 대해서 디폴트 처리를 하도록 한다.
PostNcDestroy : 윈도우가 소멸된 후에 디폴트 OnNcDestroy 함수에 의해서 호출되는 가상 함수이다.
OnChildNotify : 컨트롤 통지 메시지를 처리하기 위한 기회를 컨트롤에게 주기 위해서 부 모 윈도우에 의해 호출된다.
DoDateExchange : 대화상자의 데이터 교환이나 유효화 검사를 위해서 UpdateData에 의해 서 호출된다. 


초기화 메시지 핸들러
OnInitMenu : 메뉴가 활성화될 때 호출된다.
OnInitMenuPopup : 팝업 메뉴가 활성화될 때 호출된다. 


시스템 메시지 핸들러
OnSysChar : 사용자가 컨트롤 문자로 변환하기 위해서 호출된다.
OnSysCommand : 사용자가 컨트롤 메뉴에서 항목을 선택하거나, 사용자가 최대화 또는 최 소화 버튼을 누를 때 호출된다.
OnSysDeadChar : 키 입력을 시스템의 Dead 문자((')등이 추가된 문자)로 변환할 때 호출 된다.
OnSysKeyDown : 사용자가 Alt 키를 누르고 다른 키를 누를 때 호출된다.
OnSysKeyUp : 사용자가 Alt 키를 누른 상태로 다른 키를 놓을 때 호출된다.
OnCompacting : 윈도우 시스템에서 시스템 메모리가 부족한 경우에 호출된다.
OnDevModeChange : 사용자가 디바이스의 모드 설정을 바꿀 때 최상위 윈도우가 호출된다.
OnFontChange : 폰트 리소스의 풀이 변할 때 호출된다.
OnPaletteChanged : 애플리케이션이 논리 팔레트를 적용할 것임을 다른 애플리케이션들에 게 알린다.
OnPaletteChanging : 윈도우가 논리 팔레트를 적용할 것임을 다른 애플리케이션들에게 알 린다.
OnSysColorChange : 시스템의 컬러 설정에 변화가 있을 때 최상위 윈도우가 호출한다.
OnWindowPosChanging : SetWindowPos나 다른 윈도우-관리 함수의 호출의 결과로 크기, 위치, 또는 Z-Order가 변하려 할 때 호출된다.
OnWindowPosChanged : SetWindowPos나 다른 윈도우-관리 함수의 호출의 결과로 크기, 위치, 또는 Z-Order가 변했을 때 호출된다.
OnDropFiles : 사용자가 드롭된 파일을 실행하기 위한 프로그램으로 등록된 윈도우 위에서 왼쪽 마우스 버튼을 놓을 때 호출된다.
OnSpoolerStatus : 프린트 관리자의 작업이 추가되거나 삭제될 때마다 프린트 관리자가 호출한다.
OnTimeChange : 시스템 시간 설정이 변경되면 최상위 윈도우가 호출한다.
OnWinIniChange : 윈도우의 초기화 파일인 WIN.INI가 변경되면 최상위 윈도우가 호출한다. 


일반 메시지 핸들러
OnCommand : 사용자가 명령을 선택할 때 호출된다.
OnActivate : CWnd가 활성화되거나 비활성화될 때 호출된다.
OnActivateApp : 애플리케이션이 활성화되려고 하거나 비활성화되려고 하는 경우에 호출 된다.
OnCancelMode : CWnd가 마우스 캡쳐와 같은, 어떤 내부적인 모드를 취소하는 것을 허용 하기 위해서 호출된다.
OnChildActivate : MDI의 자식 윈도우에서 CWnd의 크기나 위치가 변경되거나 CWnd가 활 성화될 때 호출된다.
OnClose : CWnd이 종료되는 신호로서 호출된다.
OnCreat : 윈도우 생성의 일부분으로서 호출된다.
OnCtlColor : 컨트롤이 그려지려 할 때 CWnd가 컨트롤의 부모 윈도우이면 호출된다.
OnDestroy : CWnd가 소멸될 때 호출된다
OnEnable : CWnd가 사용 가능하거나 불가능할 때 호출된다.
OnEndSession : 세션이 종료될 때 호출된다.
OnEnterIdle : 모달 대화상자나 메뉴가 유휴(idle)상태에 들어갈 때 애플리케이션의 메인 윈 도우 프로시저에서 호출된다.
OnEraseBkgnd : 윈도우의 바탕이 지워져야 할 때 호출된다.
OnGetMinMaxInfo : 윈도우가 최대화된 위치나 크기, 또는 최소 또는 최대 트랙킹 크기를 알아야 할 때마다 호출된다.
OnIconEraseBkgnnd : CWnd가 최소화되거나 아이콘이 그려지기 전에 아이콘의 배경을 채 워야 하는 경우에 호출된다.
OnKillFocus : CWnd가 입력포커스를 잃기 전에 호출된다.
OnMenuChar : 사용자가 현재 메뉴에서 이미 정의된 코드와 대응이 안되는 문자를 눌렀을 때 호출된다.
OnMenuSelect : 사용자가 메뉴 아이템을 선택할 때 호출된다.
OnMove : CWnd의 위치가 변경된 후에 호출된다.
OnMoving : 사용자가 CWnd 객체를 이동하고 있음을 나타낸다.
OnDeviceChange : 디바이스나 컴퓨터의 하드웨어 설정이 변경되었음을 알려준다.
OnStyleChanged : ::SetWindowLong 윈도우 함수를 사용하여 하나나 혹은 그 이상의 윈도우 의 스타일이 변했음을 알려준다.
OnStyleChanging : ::SetWindowLong 윈도우 함수를 사용하여 하나나 혹은 그 이상의 윈도 우의 스타일이 변하려 하는 것을 알려준다.
OnPaint : 윈도우의 일부분을 다시 그리기 위해서 호출된다.
OnParentNotify : 자식 윈도우가 생성되거나 소멸될 때, 또는 커서가 자식 윈도우 위에 있 는 동안 마우스 버튼을 클릭하는 경우에 호출된다.
OnQueryDragIcon : 최소화된 CWnd가 사용자에 의해서 드래그될 때 호출된다.
OnQueryEndSession : 사용자가 윈도우의 세션 종료를 선택하는 경우에 호출된다.
OnQueryNewPalette : CWnd가 입력 포커스를 받게됨을 알려준다.
OnQueryOpen : CWnd가 아이콘이거나 사용자가 아이콘이 열려지지기를 요구할 때 호출된다.
OnSetFocus : CWnd가 입력 포커스를 얻은 후에 호출된다.
OnShowWindow : CWnd가 감추어지거나 혹은 보여질 때 호출된다.
OnSize : CWnd의 크기가 변한 후에 호출된다.
OnSizing : 사용자가 사각형의 크기를 다시 조정하고 있음을 나타낸다.
OnStyleChanged : 윈도우의 하나나 혹은 그 이상의 스타일이 변한 것을 나타낸다.
OnStyleChanging : 윈도우의 하나나 혹은 그 이상의 스타일이 변하려 하는 것을 나타낸다. 


컨트롤 메시지 핸들러
OnCharToItem : LBS_WANTKEYBOARDINPUT 스타일을 가지고 있는 리스트 박스에 의해서 WM_CHAR에 대한 응답으로 호출된다.
OnCompareItem : 정렬이 가능한 owner draw 형태의 콤보 박스나 리스트 박스에서 새로운 아이템의 상대 위치를 지정하기 위해서 호출된다.
OnDeleteItem : owner draw 형태의 리스트 박스나 콤보 박스가 소멸되거나 아이템이 컨트 롤에서 제거될 때 호출된다.
OnDrawItem : owner draw 형태의 버튼 컨트롤, 콤보 박스 컨트롤, 리스트 박스 컨트롤이 다시 그려져야 할 때 호출된다.
OnGetDlgCode : 컨트롤이 화살표 키와 Tab 키에 대한 입력을 수행할 수 있도록 하기 위 해서 호출된다.
OnMeasureItem : 컨트롤이 생성될 때 owner draw 형태의 콤보 박스, 리스트 박스, 또는 메뉴 아이템을 요구한다. CWnd는 윈도우에게 컨트롤의 크기를 알려준다.
SendChildNotifyLastMsg : 부모 윈도우가 자식 윈도우에게 통보 메시지를 제공하여 자식 윈도우가 작업을 수행할 수 있도록 한다.
OnWndMsg : 윈도우의 메시지가 핸들링되고 있는 것을 나타낸다.
ReflectLastMsg : 자식 윈도우의 마지막 메시지를 나타낸다.
OnVKeyToItem : WM_KEYDOWN 메시지에 대하여 CWnd가 소유한 리스트 박스가 호출된다. 


입력 메시지 핸들러
OnChar : 키 입력이 시스템 문자가 아닌 문자로 변환될 때 호출된다.
OnDeadChar : 키 입력이 시스템 문자가 아닌 Dead 문자로 변환될 때 호출된다.
OnHSroll : 사용자가 CWnd의 수평 스크롤 바를 클릭하는 경우에 호출된다.
OnKeyDown : 시스템 키가 아닌 키보드가 눌러 졌을 때 호출된다.
OnKeyUp : 시스템 키가 아닌 키보드가 놓을 때 호출된다.
OnLButtonDblClk : 사용자가 왼쪽 버튼을 더블 클릭 했을 때 호출된다.
OnLButtonDown : 사용자가 왼쪽 버튼을 눌렀을 때 호출된다.
OnLButtonUp : 사용자가 왼쪽 버튼을 놓을 때 호출된다.
OnMButtonDblClk : 사용자가 가운데 버튼을 더블 클릭 했을 때 호출된다.
OnMButtonDown : 사용자가 가운데 버튼을 눌렀을 때 호출된다.
OnMButtonUp : 사용자가 가운데 버튼을 놓을 때 호출된다.
OnMouseActivate : 커서가 비활성화된 윈도우에 있고 사용자가 마우스 버튼을 누를 때 호출된다.
OnMouseMove : 마우스커서가 움직일 때 호출된다.
OnRButtonDblClk : 사용자가 오른쪽 버튼을 더블 클릭 했을 때 호출된다.
OnRButtonDown : 사용자가 오른쪽 버튼을 눌렀을 때 호출된다.
OnRButtonUp : 사용자가 오른쪽 버튼을 놓을 때 호출된다.
OnSetCuror : 마우스 입력이 캡쳐되지 않고 마우스가 윈도우에서 커서를 움직이게 하려면 호출된다.
OnTimer : SetTimer에서 정해진 간격마다 호출된다.
OnVScroll : 사용자가 윈도우의 수직 스크롤 바를 클릭할 때 호출된다.
OnCaptureChanged : 마우스 캡쳐를 놓치는 윈도우 메시지를 보낸다. 


비 클라이언트 영역 메시지 핸들러
OnNcActivate : 비 클라이언트 영역이 활성화된 상태인지 비활성화된 상태인지를 가리키 기 위해서 변환이 필요한 경우 호출된다.
OnNcCalcSize : 비 클라이언트 영역의 크기와 위치가 계산될 때 호출된다.
OnNcCreate : 비 클라이언트 영역이 생성될 때 OnCreate 보다 먼저 호출된다.
OnNcDestroy : 비 클라이언트 영역이 소멸될 때 호출된다.
OnNcHitTest : CWnd가 커서를 포함하고 SetCapture로 마우스 입력을 캡쳐할 때 마우스가 움직일 때 마다 윈도우에 의해서 호출된다.
OnNcLButtonDblClk : 커서가 CWnd의 비 클라이언트 영역 내에 있는 동안 사용자가 왼쪽 마우스 버튼을 더블 클릭 했을 때 호출된다.
OnNcLButtonDown : 커서가 CWnd의 비 클라이언트 영역 내에 있는 동안 사용자가 왼쪽 마우스 버튼을 눌렀을 때 호출된다.
OnNcLButtonUp : 커서가 CWnd의 비 클라이언트 영역 내에 있는 동안 사용자가 왼쪽 마우스 버튼을 놓을 때 호출된다.
OnNcMButtonDblClk : 커서가 CWnd의 비 클라이언트 영역 내에 있는 동안 사용자가 가운데 마우스 버튼을 더블 클릭 했을 때 호출된다.
OnNcMButtonDown : 커서가 CWnd의 비 클라이언트 영역 내에 있는 동안 사용자가 가운데 마우스 버튼을 눌렀을 때 호출된다.
OnNcMButtonUp : 커서가 CWnd의 비 클라이언트 영역 내에 있는 동안 사용자가 가운데 마우스 버튼을 놓을 때 호출된다.
OnNcMouseMove : 커서가 CWnd의 비 클라이언트 영역 내에서 이동할 때 호출된다.
OnNcPaint : 비클라이언트 영역이 다시 그려지기를 요구할 때 호출된다.
OnNcRButtonDblClk : 커서가 CWnd의 비 클라이언트 영역 내에 있는 동안 사용자가 오른쪽 마우스 버튼을 더블 클릭 했을 때 호출된다.
OnNcRButtonDown : 커서가 CWnd의 비 클라이언트 영역 내에 있는 동안 사용자가 오른쪽 마우스 버튼을 눌렀을 때 호출된다.
OnNcRButtonUp : 커서가 CWnd의 비 클라이언트 영역 내에 있는 동안 사용자가 오른쪽 마 우스 버튼을 놓을 때 호출된다. 


MDI 메시지 핸들러
OnMDIActivate : MDI child 윈도우가 활성화되거나 비활성화될 때 호출된다. 


클립보드 메시지 핸들러
OnAskCbFormatName : 클립보드의 소유자가 클립보드의 내용을 나타낼 때 클립보드 뷰어 애플리케이션에 의해서 호출된다.
OnChangeCbChain : 특정 윈도우가 체인에서 제거되었는지를 통지한다.
OnDestroyClipboard : 클립보드가 윈도우 EmptyClipboard 함수의 호출에 의해서 비워지는 경우에 호출된다.
OnDrawClipboard : 문장이 변경되었을 때 호출된다.
OnHScrollClipboard : 클립보드의 소유주가 클립보드의 이미지를 스크롤해야 하고 적절한 섹션을 무효화할 때 호출되며, 스크롤 바의 값들을 갱신한다.
OnPaintClipboard : 클립보드 뷰어의 클라이언트 영역이 다시 그려져야 할 때 호출된다.
OnRenderAllForamts : 소유주 애플리케이션이 파괴되고 있고 모든 포맷들을 다시 만들 필 요가 있을 때 호출된다.
OnSizeClipboard : 클립보드 뷰어 윈도우의 클라이언트 영역의 크기가 변하는 경우에 호출 된다.
OnVSrollClipboard : 소유주가 크립보드 이미지 스크롤해야 하는 경우에 호출되며, 적절한 섹션을 무효화하고, 스크롤바 값들을 갱신한다. 


메뉴 루프 통지
OnEnterMenuLoop : 메뉴의 모달 루프가 수행되는 경우에 호출된다.
OnExitMenuLoop : 메뉴의 모달 루프가 마치는 경우에 호출된다.

반응형

'C & C++ > C & C++' 카테고리의 다른 글

파일 저장하기  (0) 2011.03.29
[ClipBoard] 클립보드 내용가져오기  (0) 2011.03.29
SetSize 대용량 데이터 추가속도 향상  (0) 2011.03.27
CString 문자열 검색  (0) 2011.03.27
CString 소수 구하는 함수  (0) 2011.03.27

댓글