삽질의 현장/- MFC

#008_MFC_MDW (Multi Document Window) _ 멀티 윈도우

shovelman 2015. 10. 20. 15:51


안녕하세요 삽잡이입니다.


이번 시간에는 MFC에서 Multi Document Window에 대해서 알아보려고합니다.


우선 동적 Splitter Window에 대해서 알아보고자합니다.

Splitter Window는 우리말로 분할창을 말합니다.

이 분할창은 Main Frame이 뜨면 여러개의 View를 띄울 것입니다.

즉, 하나의 Frame 윈도우에서 여러개의 View로 나누어 주는 것입니다.


이 동적 분할 윈도우는

프로그램 실행 중 윈도우를 하나로 합치거나 나눌 수 있습니다...


처음 프로그램이 실행 될 때 OnCreate 메시지 핸들러 함수가 호출됩니다.

이 때 클라이언트 영역에 새로운 View가 붙는 것이기 때문에,

즉, View를 생성해서 다른 View를 붙이려면 'OnCreateClient' 함수가 필요합니다.


그리고 CSplitterWnd라는 클래스가 필요합니다.

이 클래스는 한 Frame (Main Frame)에 둘 이상의 View를 보여줄 수 있도록 만들어줍니다.

즉, 한 화면에 여러개의 View를 분할해서 보여줄 수 있다 이겁니다...



해당 클래스에 있는 Create 메서드를 통해서 View를 분할 할 수 있습니다.

이 메서드는 '동적 분할 창을 만들기 위해 호출하는 메서드'입니다.

인자로는 부모 프레임의 창, 분할 창의 최대 행열 개수, 최소크기

그리고 context라는 인자 등이 들어갑니다.


이 context는 '문맥', '앞뒤 정황'이라는 의미를 가지고 있습니다.

MFC에서는 Frame과 Window 끼리 각각 전달하는

즉, 서로간에 공유가 되지 않으면 Frame에 맞도록 View가 받아들여지거나

Frame을 부모로 선택할 수 없기 때문에 이를 공유해주는 기본적 정보가 들어있습니다. 

이를 Context라고 부르는 것이지요...


아무튼... 이 Splitter Window는 

합쳐지면 View가 하나가 되고 떨어지면 VIew가 n개가 될 수 있습니다.

Frame은 하나지요...

그리고 이 놈들을 아우르는 대빵 APP 객체가 하나이구요...



그런데 이 때 만약, 여러개의 View에서 가져가는 데이터가 

Document 객체 하나로부터라면 주의해야할 점이 있습니다.

화면을 갱신하려고 Invalidate() 함수를 호출시켜봤자 

자신의 Invalidate() 함수가 호출될 뿐입니다.

즉, 자신의 윈도우를 다시 그릴 뿐 주변 윈도우를 갱신해주지 않는다 이겁니다.

이는 각 윈도우들이 하나의 Document의 데이터만을 통해서 

View로 뿌리기 때문에 문제가 발생하는 것입니다.


따라서, 만약 윈도우 하나만 변경이 되어도 

해당 윈도우와 연결되어있는 모든 Document의 View 객체들을 갱신해야합니다.

이럴 때에는 UpdateAllView() 함수를 사용합니다.

해당 함수는 Document를 사용하는 모든 View에서 만약 변경이 됬을 때 호출해줘야합니다.


그런데 이 UpdateAllView() 함수는 내부적으로 OnUpdate() 함수를 호출하는 것입니다.

보다 정확하게 설명을 드리자면,

기본적으로 UpdateAllView() 메소드를 호출하게 되면, 

호출한 윈도우와 연결되어있는 모든 View에 OnUpdate() 함수가 호출되는 것입니다.



즉, OnUpdate() 메서드를 재정의 하지 않는다면

부모 OnUpdate() 메서드에서는 자기 자신을 Invalidate() 하는 것 뿐입니다.

따라서, UpdateAllView() 메서드 호출 시 

호출한 윈도우와 연결되있는 View들이 모두 갱신이 되는 것이었습니다.


그런데 반드시 UpdateAllView() 메서드를 호출하여 갱신을 할 필요는 없습니다.

경우에 따라서 OnUpdate() 메서드를 재정의해서

본인이 의도하는 대로 코드를 구현할 수 있습니다.

즉, 다른 동작을 하도록 구현할 수 있다 이겁니다.


정적 Splitter Window의 경우 윈도우가 분할된 상태로 프로그램이 시작됩니다.

이 정적 분할 윈도우는 Document는 같지만, View가 다른 형태입니다.

즉, View는 같은 Class가 아닐 수 있다 이겁니다.

그렇다는 말은 동일한 인스턴스가 아닌 서로 다른 인스턴스라는 것이지요...

예를 들어 한쪽은 사각형만 그려지는 class, 또 다른 한쪽은 동그라미만 그려지는 class 이렇게요!


처음 언급했지만 다시 정리를 해보자면,

동적 분할 윈도우는 원래 띄울 때에는 하나인데 사용자가 갈라서 View를 만들었습니다.

하지만 정적 분할 윈도우는 아닙니다...



이 Splitter WIndow의 장점은 

APP 객체에 있는 InitInstance() 함수에 Document Template에 명시한 View를 쓴다는 것입니다.


그런데 정적 분할 윈도우의 경우에는 각각의 View를 명시해줘야합니다.

Document는 그대로 사용한다고 해도 View를 우리가 결정할 수 있다 이겁니다.


 

이렇게 View를 우리가 결정할 수 있다는 것입니다.


RUNTIME_CLASS는 메크로입니다. 이 메크로는 객체를 생성해줍니다.

그런데 우리 객체 생성할 때 'new' 연산자 사용하지 않습니까?

RUNTIME_CLASS가 객체를 생성할 수 있는 정보 객체가 되는 것입니다.

이 메크로가 CRuntiem Class라는 객체를 하나 만들어주고,

이 객체를 통해 언제든지 필요시 객체를 만들 수 있게 됩니다.


원하는 시점에 필요한 객체들을 만들어 낼 수 있도록 코드로 구현한 것이라고 생각하면 됩니다.

실제로는 해당 코드에서 객체를 만드는 것이 아니라,

View가 실제로 필요한 시점에 객체를 만들어내는 것이지요...


이번 시간은 여기까지 하도록 하겠습니다.

이상 삽잡이였습니다!