안녕하세요 삽잡이 입니다.
이번 시간에는 지난 시간에 이어서
WinMain함수와 WndProc함수에 대해서 조금 더 알아보도록 하겠습니다.
우선, 지난 시간에 배운 내용을 간략하게 설명하자면...
WinProc 함수는 프로시저이고 , 메시지를 처리하는 함수를 뜩합니다.
메인 함수인 WinMain함수는 크게 세가지 영역으로 나뉠 수 있습니다.
첫번째로, 윈도우의 클래스를 등록하는 부분이 있습니다.
윈도우 클래스를 등록하기 위해서는 구조체를 사용해야합니다.
즉, 윈도우 클래스라는 구조체를 설정한 다음 해당 윈도우 클래스를 등록하는 것입니다.
윈도우 구조체를 잠시 살펴보도록 하기 전, MSDN의 도움을 청해보도록 하겠습니다.
자... 여러분이 지금 살펴보시는 구조체가 바로 WNDCLASS라고 부르며,
해당 클래스를 등록하여 윈도우 인스턴스를 생성합니다.
본인은 해당 클래스에서 보다 중요한 부분들을 생각해보며 글을 써내려가도록 하겠습니다.
여러분 한번 생각해보는 시간을 가져봅시다...
객체 지향 프로그래밍을 처음 접했을때 인스턴스화를 시키기 위해서 어떻게 했습니까?
클래스명을 사용하지 않았나요?
API도 다르지 않습니다. 윈도우 클래스 구조체 내부 중 클래스 이름을 알아야
반드시 윈도우 인스턴스를 생성하는 것이 가능하게 됩니다.
우리가 말하는 프로그램을 살아있지 않습니다.
이 말인 즉, 윈도우 클래스라는 것은 말그대로 코드 정의일 뿐입니다.
메모리 상에 생성되는 것이 아닙니다. 즉, 컴퓨터에서 활동 가능한 상태가 아니라는 것입니다.
그렇다면 컴퓨터에서 활동 가능한 상태가 되기 위해서는 어떻게 되야할까요?
바로 메모리 상에 상태가 만들어져야합니다.
이 말인 즉, 클래스를 실제 활동 가능한 상태로 만들기 위해서 오브젝트라는 객체를 만들어야합니다.
그 오브젝트들을 클래스의 인스턴스라고 부르는 것이고요...
쉽게 인스턴스라는 용어를 정의한다면, '실체'라고 말씀드릴 수 있을 것 같습니다.
프로그램은 단지 명령어와 데이터의 집합일 뿐입니다.
즉, 프로그램을 분류하라고 한다면 데이터와 집합으로 나뉠 수 있다는 뜻이지요...
모든 것들은 데이터로 존재해야하는데 메모리에 할당되야합니다.
자... 그렇다는 것은 우리는 WNDCLASS 라는 구조체에 값을 저장했다면,
윈도우 클래스를 등록해야 하며, CreateWindow() 함수를 통해 윈도우 인스턴스가 만들어집니다.
왜냐하면 실제 윈도우를 유지하기 위해 메모리를 만들어야하기 때문입니다.
CreateWindow 함수는 위에서 언급한 프로그램의 정의에 부합하기 위해 필요한 함수입니다.
해당 함수를 호출하게 되면 윈도우 정보를 유지하기 위한 데이터가 메모리에 할당되게 되고,
이를 윈도우 인스턴스라고 부르게 되는 것입니다.
말이 좀 길어졌지만, 결국 실체화 하기 위해...
즉, 윈도우 클래스의 인스턴스화를 위해서는 반드시 클래스명이 필요합니다.
다음으로 프로시저 이름을 지정하는 것 또한 매우 중요합니다.
'lpfnWndProc'으로 되어있지요...
클래스의 이름과 프로시저의 이름을 지정해주는 것은 아주 중요합니다.
우리는 프로시저를 지정할때에 함수의 이름을 명시하고 있습니다.
왜냐하면 함수의 이름은 즉, 함수의 주소이기 때문이지요...
자... 다음으로 WinMain 함수의 두번째 부분인 윈도우 인스턴스 생성하는 부분이 있습니다.
위에서 잠시 언급을 했었는데, 인스턴스라는 용어는 정말로 중요한 용어입니다.
아무튼... 윈도우 인스턴스를 생성하기 위해서도 굉장히 중요한 세가지가 있습니다.
우선 MSDN을 통해 CreateWindow 함수를 살펴보도록 하겠습니다.
첫번째로 윈도우 클래스 이름이 중요합니다.
즉, '이 윈도우를 생성하겠다.' 라는 것을 알리기 위해 필요합니다.
다음으로 Style 또한 중요합니다. 윈도우 스타일을 지정하여 설정할 수 있습니다.
기본적으로 WS_OVERLAPPEDWINDOW 키워드를 설정하게 된다면,
오버랩 될 수 있다는 뜻을 가지는데, 윈도우와 윈도우 사이에 겹쳐질 수 있게 되는 것입니다.
반대의 예로 스마트폰은 창이 겹쳐지지 않지요...
WS_OVERLAPPEDWINDOW 내부를 확인해보면
여러가지의 옵션들에 해당되는 기능들이 있습니다.
밑에서 두번째, 세번째 순서에 있는 hInstance와 그 위의 NULL은 핸들을 말합니다.
정확하게 NULL은 부모 윈도우 핸들을 말합니다.
부모 윈도우 핸들이 NULL이라고 하는 것은
최초로 만들어진 메인 윈도우를 의미하는 것입니다. 즉, 메인 윈도우는 모두 NULL이라는 것이지요...
OS가 관리하는 윈도우를 데스크탑 윈도우라고 하는데,
이는 바탕화면을 꽉 채우고 있는 놈을 말합니다.
그리고 그 위에 어플리케이션 윈도우들이 만들어지는 것이지요....
(정확하게 메인 윈도우는 0이 아니지만... 0이라고 합니다.)
윈도우 상에는 부모 자식간의 관계라는 것이 있습니다.
데스크탑 윈도우를 기준으로
A프로그램, B프로그램과 같은 메인 윈도우가 있을 것입니다.
그렇다면, 이 데스크탑 윈도우를 부모로 하여 A와 B라는 메인 윈도우들이 만들어지고
A와 B를 기준으로 자식 윈도우가 ...
또 자식 윈도우가... 이렇게 반복을 하게 되는 것이지요...
왜 이런 구조를 이루고 있을까요?
메인 윈도우를 최소화 시킨다고 가정해봅시다.
부모와 자식간의 관계가 아닌 독립적인 프로세스라면
A라는 메인 프로그램을 최소화 시켜도 그 내부에 켜져있는 윈도우들은
최소화가 되지 않는 문제가 발생하겠지요...
hInstance는 옛 잔재입니다. API를 다 고칠 수 없기에 남아있는 것이지요..
인스턴스는 어떠한 프로그램의 살아있는 실채라고 했습니다.
프로그램이 뜨면 프로세스가 만들어지고 이를 프로그램의 인스턴스라고 합니다.
이 인스턴스는 프로세스라는 뜻을 가지고 있다는 것이라고 말할 수도 있지요...
이 인스턴스에 핸들을 의미하는 h가 붙습니다.
그렇다면 핸들에 대해서 이제 얘기를 해보도록 하겠습니다.
Windows (s가 붙으면 OS를 의미합니다.)에서 핸들은 정말 중요합니다.
핸들과 유사하며 비교될 수 있는 것은 바로 ID입니다.
ID는 쉽게 식별 번호입니다. 대부분 정수로 되어있습니다.
ID만을 가지고는 Uniq하게 구별할 수 있지는 않죠...
핸들은 그렇다면 ID와 견주어봤을때 어떨까요?
우선 핸들도 정수로 된 번호입니다. 정확하게는 주소형식으로 되어있지요...
핸들은 말 그대로 제어할 수 있는 것입니다.
ID를 알고 있으면 식별을 할 수 있겠지만, 핸들을 알고 있으면 제어를 할 수 있게 되지요...
마치 객체 지향에서 객체의 주소를 알고 있다면 모든 할 수 있는 것과 같이 말입니다.
객체 지향에서는 객체의 주소가 중요하듯이,Windows에서는 Handle이 굉장히 중요합니다.
Windows는 만들때부터 핸들 방식의 프로그래밍으로 되어있다고 해도 과언이 아닐 정도로 말이죠...
OS가 있고 OS가 어떤 객체의 메모리를 생성할 것인데,
실제 주소를 넘겨주면 해당 윈도우를 멋대로 망가뜨릴 위험이 있습니다.
따라서 OS에서는 진짜 주소는 자신만 가지고 있고, 이 Window를 컨트롤 할 수 있는 번호를 할당하게 됩니다.
그리고 그 번호를 Application에 넘기게 되는 것이죠.
즉, 어플리케이션에서는 컨트롤 할 수 있는 번호만을 가지게 되는 것입니다.
따라서 이와 같은 이유로 Handle이라는 개념이 만들어졌습니다.
직접 접근하게 되면 위험성이 높아지니깐 말이죠...
Handle은 ID와 다릅니다. 반드시 다른 것을 아셔야 합니다.
그래서 hInstanace는 뭐냐?
WinMain함수의 매개변수중 두개가 hInstance로 이루어져 있는데요,
하나는 자기 자신의 프로세스 핸들을 말하고 그 다음 부모 프로세스의 핸들을 말하는 것입니다.
프로세스상에서도 부모 프로세스가 있습니다.
OS는 크게 Kernel과 Shell로 나뉠 수 있습니다.
커널은 핵심 기능을 담당하고 있고, 쉘을 사용자와 대화를 담당하고 있는 것입니다.
OS의 쉘이 대부분 프로세스의 부모가 됩니다.
프로그램을 클릭함으로 활성화 시켜주면 메모리를 띄워주지 않습니까?
그 메모리를 누가 띄워줄까요? 바로 OS의 Shell이 띄워주는 것입니다.
따라서 대부분 OS 쉘이 부모 프로세스가 되는 것입니다.
결론적으로, 누가 누구를 띄우냐에 따라 부모가 달라지겠죠...
A가 B를 띄웠으면 부모의 Handle은 A의 핸들 값이곘고...
아무튼... 그런데 이건 예전엔 중요헀지만 지금은 별로 중요하지 않습니다.
예전에는 API를 많이 사용했기 때문에 알고있을 필요성이 있었지만, 지금은 닷넷이라는 친구를 사용하지요...
그렇다면 API를 왜 사용할까요...
우리가 C언어를 배우는 것과 같습니다.
개념이 중요하지요... C언어를 배움으로 메모리 구조를 이해하고 기초적인 구조를 파악할 수 있듯이,
API를 배움으로서 어떻게 그래픽으로 사용자와 어떠한 방식으로 대화할지에 대해
파악할 수 있게 되는 것입니다.
따라서 기초를 바탕으로 한 개념을 이해하는 과정으로 글을 써내려가보도록 하겠습니다.
이상 삽잡이였습니다!
'삽질의 현장 > - 윈도우 API' 카테고리의 다른 글
#004_WIndow_API_WinMain, WndProc에 대해서 (3) (0) | 2015.09.08 |
---|---|
#003_WIndow_API_WinMain, WndProc에 대해서 (2) (0) | 2015.09.08 |
#001_WIndow_API_Intro (0) | 2015.09.07 |
#Win API 기본 (0) | 2015.09.06 |
[삽잡이::Window] Window? 창문이냐? 미안하다! (0) | 2015.06.09 |