. 컨트롤화 방법

두 가지 컨트롤화 방법에 대해 알아 봤는데 직감적으로 느낄 수 있겠지만 윈도우 컨트롤로 만드는 것보다는 오브젝트로 만드는 것이 여러 모로 유리하다. 그렇다고 해서 윈도우 컨트롤로 만드는 것이 모든 면에서 다 나쁜 것은 아니고 약간의 장점도 있다. 윈도우즈의 표준 컨트롤과 같은 방식이라는 점에서 OOP를 모르는 사람도 기존 방법대로 쓸 수 있다는 점이 첫 번째 장점이고 C++ 컴파일러 없이 C 컴파일러로도 개발할 수 있어 개발툴의 사양이 좀 낮아도 상관없다는 것도 좀 억지스럽기는 하지만 장점이기는 하다. ApiEdit9까지 디폴트 인수를 제외하고 C++의 기능은 전혀 사용하지 않았다.

그리고 중간 과정을 거치지 않고 윈도우 프로시저가 메시지를 곧바로 받기 때문에 함수 호출속도가 좀 더 빠르다. 하지만 이런 몇 가지 장점에도 불구하고 윈도우 컨트롤은 분명히 시대에 뒤떨어진 방법이다. Win32 환경에서 C 언어만 지원하는 컴파일러도 없고 함수 호출속도가 빨라 봐야 측정 불가능한 정도이기 때문이다. 그래서 ApiEdit를 윈도우 컨트롤로 만드는 실습은 하지 않고 간단하게 제작 절차만 정리하도록 한다.

 

 ApiEditTest라는 이름으로 새 프로젝트를 만든다. ApiEdit.h InitApiEdit 함수 원형만 작성하고 ApiEdit.cpp에는 ApiEdit9.cpp의 모든 코드를 복사해 온다. IME 기능 구현을 위해 imm32.lib를 링크한다.

 ApiEdit.cpp WinMain을 없앤다. 대신 InitApiEdit 함수에 윈도우 클래스 등록 코드를 작성한다. 윈도우 클래스 이름은 ApiEdit로 하고 cbWndExtra 4로 지정한다. 윈도우 프로시저의 이름은 ApiEditProc으로 변경한다.

 SApiEdit 구조체를 선언하고 모든 전역변수를 이 구조체의 멤버로 선언한다. OnCreate에서 구조체를 할당하고 여분 메모리에 그 포인터를 대입해 둔다. OnDestroy에서는 물론 해제해야 한다.

 모든 함수에서 전역변수를 액세스하기 전에 여분 메모리에 저장된 구조체의 포인터를 구한다. 아예 매크로로 만들어 두는 것도 괜찮은 방법이다.

 

SApiEdit *pAe=(SApiEdit *)GetWindowLong(hWnd,0);

 

그리고 모든 전역변수 앞에 pAe->를 붙여주어 구조체의 멤버를 액세스하도록 한다. 지역변수는 그럴 필요가 없다.

 모든 함수가 여분 메모리를 액세스할 수 있도록 hWnd 인수를 추가하고 함수 호출문에서 hWnd를 전달한다. 모든 함수들이 윈도우 핸들을 받으므로 hWndMain 전역변수는 불필요하며 hWndMain hWnd로 변경한다.

 SetFocus 함수 추가 및 PostQuitMessage 함수 삭제 등의 몇 가지 필요한 수정을 한다.

 ApiEditTest.cpp를 작성하여 메인 윈도우를 만든다. 필요한 만큼 윈도우 핸들을 선언하고 CreateWindow 함수로 ApiEdit 컨트롤을 생성하여 사용한다.

 

이상의 절차대로 ApiEdit.h ApiEdit.cpp를 작성하면 ApiEdit는 윈도우 컨트롤이 된다. 문법적으로 분명히 가능한 방법이고 실제로 이 방법대로 컨트롤을 만들기도 하지만 기존 소스를 이 방식대로 바꾸기 위해서는 굉장히 많은 잔손질이 필요하다. pAe->를 전역변수 앞에 일일이 붙여주는 것도 귀찮고 모든 함수가 hWnd를 받아야 하는 것도 쉽지 않다. 숙련된 조교가 직접 작업해 본 결과 38분이나 걸렸다.