다음을 통해 공유


창 프로시저 정보

각 창은 특정 창 클래스의 멤버입니다. 창 클래스는 개별 창에서 메시지 처리에 사용하는 기본 창 프로시저를 결정합니다. 동일한 클래스에 속하는 모든 창은 동일한 기본 창 프로시저를 사용합니다. 예를 들어 시스템은 콤보 상자 클래스(COMBOBOX)에 대한 창 프로시저를 정의하며, 모든 콤보 상자는 해당 창 프로시저를 사용합니다.

일반적으로 애플리케이션은 하나 이상의 새 창 클래스 및 관련 창 프로시저를 등록합니다. 클래스를 등록하고 나면 애플리케이션은 해당 클래스의 여러 창을 만들 수 있으며, 모두 동일한 창 프로시저를 사용합니다. 즉, 여러 소스가 동시에 동일한 코드를 호출할 수 있으므로 창 프로시저에서 공유 리소스를 수정할 때는 주의해야 합니다. 자세한 내용은 Window 클래스를 참조하세요.

대화 상자의 창 프로시저(대화 상자 프로시저라고 함) 구조는 일반 창 프로시저와 유사합니다. 해당 섹션의 창 프로시저를 참조하는 모든 부분은 대화 상자 프로시저에도 적용됩니다. 자세한 내용은 대화 상자를 참조하세요.

이 섹션에서는 다음 항목을 설명합니다.

창 프로시저의 구조

창 프로시저는 네 개의 매개 변수가 있고 서명된 값을 반환하는 함수입니다. 매개 변수는 창 핸들, UINT 메시지 식별자, WPARAM 및 LPARAM 데이터 형식으로 선언된 두 개의 메시지 매개 변수로 구성됩니다. 자세한 내용은 WindowProc을 참조하세요.

메시지 매개 변수는 종종 낮은 자리와 높은 자리의 단어에 정보를 포함합니다. 애플리케이션이 메시지 매개 변수에서 정보를 추출하는 데 사용할 수 있는 몇 가지 매크로가 있습니다. 예를 들어 LOWORD 매크로는 메시지 매개 변수에서 낮은 자리의 단어(비트 0~15)를 추출합니다. 다른 매크로는 HIWORD, LOBYTEHIBYTE 매크로를 포함합니다.

반환 값의 해석은 특정 메시지에 따라 다릅니다. 각 메시지에 대한 설명을 참조하여 적절한 반환 값을 확인합니다.

창 프로시저를 재귀적으로 호출할 수 있으므로 사용하는 지역 변수의 수를 최소화하는 것이 중요합니다. 개별 메시지를 처리할 때 애플리케이션은 지역 변수의 과도한 사용을 방지하기 위해 창 프로시저 외부에서 함수를 호출해야 하며, 이로 인해 딥 재귀 중에 스택이 오버플로될 수 있습니다.

기본 창 프로시저

기본 창 프로시저 함수인 DefWindowProc는 모든 창에서 공유하는 특정 기본 동작을 정의합니다. 기본 창 프로시저는 창에 최소한의 기능을 제공합니다. 애플리케이션 정의 창 프로시저는 기본 처리를 위해 처리하지 않는 메시지를 DefWindowProc 함수에 전달해야 합니다.

창 프로시저 서브클래싱

애플리케이션이 창을 생성할 때 시스템은 창에 대한 메시지를 처리하는 창 프로시저의 주소를 포함하여 창과 관련된 정보를 저장하기 위해 메모리 블록을 할당합니다. 시스템에서 창에 메시지를 전달해야 하는 경우 창 관련 정보를 검색하여 창 프로시저의 주소를 검색하고 해당 프로시저에 메시지를 전달합니다.

서브클래싱 은 애플리케이션이 특정 창에 전송되거나 게시된 메시지를 가로채고 처리할 수 있도록 하는 기술입니다. 애플리케이션은 창을 서브클래싱하여 창의 동작을 보강, 수정 또는 모니터링할 수 있습니다. 애플리케이션은 편집 컨트롤 또는 목록 상자와 같은 시스템 전역 클래스에 속하는 창을 서브클래스 할 수 있습니다. 예를 들어 애플리케이션은 컨트롤이 특정 문자를 허용하지 않도록 편집 컨트롤을 서브클래싱 할 수 있습니다. 그러나 다른 애플리케이션에 속하는 창 또는 클래스를 서브클래스 할 수는 없습니다. 모든 서브클래싱은 동일한 프로세스 내에서 수행해야 합니다.

애플리케이션은 창의 원래 창 프로시저 주소를 서브클래스 프로시저라는 새 창 프로시저의 주소로 바꿔 창을 서브클래싱합니다. 그런 다음 서브클래스 프로시저는 창에 전송 또는 게시한 모든 메시지를 받습니다.

서브클래스 프로시저는 메시지를 받을 때 세 가지 작업을 수행할 수 있습니다. 메시지를 원래 창 프로시저에 전달하거나, 메시지를 수정하고 원래 창 프로시저에 전달하거나, 메시지를 처리하고 원래 창 프로시저에 전달하지 않을 수 있습니다. 서브클래스 프로시저가 메시지를 처리하는 경우 메시지를 원래 창 프로시저에 전달하기 전, 후 또는 전후 모두 처리할 수 있습니다.

시스템은 인스턴스 전역이라는 두 가지 유형의 서브클래싱을 제공합니다. 인스턴스 서브클래싱에서 애플리케이션은 창의 단일 인스턴스의 창 프로시저 주소를 대체합니다. 애플리케이션은 인스턴스 서브클래싱을 사용하여 기존 창을 서브클래싱해야 합니다. 전역 서브클래싱에서 애플리케이션은 창 클래스의 WNDCLASSEX 구조에서 창 프로시저의 주소를 대체합니다. 클래스를 사용하여 만든 모든 후속 창에는 서브클래스 프로시저의 주소가 있지만 클래스의 기존 창은 영향을 받지 않습니다.

인스턴스 서브클래싱

애플리케이션은 SetWindowLongPtr 함수를 사용하여 창의 인스턴스를 서브클래싱합니다. 애플리케이션은 GWL_WNDPROC 플래그, 창 핸들을 서브클래스로, 서브클래스 프로시저의 주소를 SetWindowLongPtr에전달합니다. 서브클래스 프로시저는 애플리케이션의 실행 파일 또는 DLL에 상주할 수 있습니다.

GWL_WNDPROC 플래그를전달하면 SetWindowLongPtr는 창의 원래 창 프로시저 주소를 반환합니다. 애플리케이션은 원래 창 프로시저에 가로채는 메시지를 전달하기 위해 CallWindowProc 함수에 대한 후속 호출에서 이 주소를 사용하여 이 주소를 저장해야 합니다. 또한 애플리케이션에는 창에서 서브클래스를 제거하려면 기존의 창 프로시저 주소가 있어야 합니다. 서브클래스를 제거하기 위해 애플리케이션은 SetWindowLongPtr를 다시 호출하여 원래 창 프로시저의 주소를 GWL_WNDPROC 플래그와 핸들을 창에 전달합니다.

시스템은 시스템 전역 클래스를 소유하며 컨트롤의 측면은 시스템의 한 버전에서 다음 버전으로 변경될 수 있습니다. 애플리케이션이 시스템 전역 클래스에 속하는 창을 서브클래스해야 하는 경우 개발자는 새 버전의 시스템이 릴리스 될 때 애플리케이션을 업데이트해야 할 수 있습니다.

인스턴스 서브클래싱은 창을 만든 후에 발생하므로 창에 추가 바이트를 추가할 수 없습니다. 창을 서브클래싱하는 애플리케이션은 창의 속성 목록을 사용하여 서브클래스 된 창의 인스턴스에 필요한 모든 데이터를 저장해야 합니다. 자세한 내용은 창 속성을 참조하세요.

애플리케이션이 서브클래싱 된 창을 서브클래싱하는 경우, 수행된 역순으로 서브클래스를 제거해야 합니다. 제거 순서를 바꾸지 않으면 복구할 수 없는 시스템 오류가 발생할 수 있습니다.

전역 서브클래싱

창 클래스를 전역적으로 서브클래스하려면 애플리케이션에 클래스의 창에 대한 핸들이 있어야 합니다. 또한 애플리케이션은 서브클래스를 제거하는 핸들이 필요합니다. 핸들을 가져오기 위해 애플리케이션은 일반적으로 서브클래스 할 클래스의 숨겨진 창을 만듭니다. 핸들을 가져온 후 애플리케이션은 SetClassLongPtr 함수를 호출하여 핸들, GCL_WNDPROC 플래그 및 서브클래스 프로시저의 주소를 지정합니다. SetClassLongPtr는 클래스에 대한 원래 창 프로시저의 주소를 반환합니다.

원래 창 프로시저 주소는 인스턴스 서브클래싱에서 사용되는 것과 동일한 방식으로 전역 서브클래싱에 사용됩니다. 서브클래스 프로시저는 CallWindowProc를 호출하여 기존의 창 프로시저에 메시지를 전달합니다. 애플리케이션은 SetClassLongPtr를 다시 호출하고 원래 창 프로시저의 주소, GCL_WNDPROC 플래그 및 서브클래싱되는 클래스의 창에 대한 핸들을 지정하여 창 클래스에서 서브클래스를 제거합니다. 전역적으로 컨트롤 클래스를 서브클래싱하는 애플리케이션은 애플리케이션이 종료되면 서브클래스를 제거해야 하며, 그렇지 않을 경우 복구할 수 없는 시스템 오류가 발생할 수 있습니다.

전역 서브클래싱에는 인스턴스 서브클래싱과 동일한 제한 사항과 몇 가지 추가 제한이 있습니다. 애플리케이션은 원래 창 프로시저에서 사용하는 방법을 정확히 알지 못하는 경우, 클래스 또는 창 인스턴스에 대해 추가 바이트를 사용하면 안 됩니다. 애플리케이션이 데이터를 창과 연결해야 하는 경우 창 속성을 사용해야 합니다.

창 프로시저 슈퍼클래싱

슈퍼클래싱은 애플리케이션이 기존 클래스의 기본 기능과 애플리케이션에서 제공하는 향상된 기능을 사용하여 새 창 클래스를 만들 수 있도록 하는 기술입니다. 슈퍼클래스는 기본 클래스라는 기존 창 클래스를 기반으로 합니다. 종종 기본 클래스는 편집 컨트롤과 같은 시스템 전역 창 클래스인 경우가 많으나, 어떤 창 클래스라도 될 수 있습니다.

슈퍼클래스에는 슈퍼클래스 프로시저라고 하는 자체 창 프로시저가 있습니다. 슈퍼클래스 프로시저는 메시지를 받을 때 세 가지 작업을 수행할 수 있습니다. 메시지를 원래 창 프로시저에 전달하거나, 메시지를 수정하고 원래 창 프로시저에 전달하거나, 메시지를 처리하고 원래 창 프로시저에 전달하지 않을 수 있습니다. 슈퍼클래스 프로시저가 메시지를 처리하는 경우 메시지를 원래 창 프로시저에 전달하기 전, 후 또는 전후 모두 처리할 수 있습니다.

서브클래스 프로시저와 달리 슈퍼클래스 프로시저는 창 생성 메시지(WM_NCCREATE, WM_CREATE 등)를 처리할 수 있지만 기본 클래스 창 프로시저가 초기화 프로시저를 수행할 수 있도록 원래 기본 클래스 창 프로시저에도 전달해야 합니다.

창 클래스를 슈퍼클래싱하기 위해 애플리케이션은 먼저 GetClassInfoEx 함수를 호출하여 기본 클래스에 대한 정보를 검색합니다. GetClassInfoEx는WNDCLASSEX 구조를 기본 클래스의 WNDCLASSEX 구조 값으로 채웁니다. 다음으로, 애플리케이션은 자체 인스턴스 핸들을 WNDCLASSEX 구조의 hInstance 멤버에 복사하고 슈퍼클래스의 이름을 lpszClassName 멤버에 복사합니다. 기본 클래스에 메뉴가 있는 경우 애플리케이션은 동일한 메뉴 식별자를 사용하여 새 메뉴를 제공하고 메뉴 이름을 lpszMenuName 멤버에 복사해야 합니다. 슈퍼클래스 프로시저가 WM_COMMAND 메시지를 처리하고 기본 클래스의 창 프로시저에 전달하지 않으면 메뉴에 해당 식별자가 필요하지 않습니다. GetClassInfoEx는 WNDCLASSEX구조의lpszMenuName, lpszClassName 또는 hInstance 멤버를 반환하지 않습니다.

또한 애플리케이션은 WNDCLASSEX 구조의 lpfnWndProc 멤버를 설정해야 합니다. GetClassInfoEx 함수는 이 멤버를 클래스의 원래 창 프로시저 주소로 채웁니다. 애플리케이션은 이 주소를 저장하여 원래 창 프로시저에 메시지를 전달한 다음, 슈퍼클래스 프로시저의 주소를 lpfnWndProc 멤버에 복사해야 합니다. 필요한 경우, 애플리케이션은 WNDCLASSEX 구조의 다른 멤버를 수정할 수 있습니다. WNDCLASSEX 구조를 채운 후 애플리케이션은 구조의 주소를 RegisterClassEx 함수에 전달하여 슈퍼클래스를 등록합니다. 그런 다음, 슈퍼클래스를 사용하여 창을 만들 수 있습니다.

슈퍼클래싱은 새 창 클래스를 등록하므로 애플리케이션은 추가 클래스 바이트와 추가 창 바이트 둘 다에 추가할 수 있습니다. 슈퍼클래스는 인스턴스 서브클래스 또는 전역 서브클래스가 사용해서는 안되는 것과 같은 이유로 기본 클래스 또는 창에 원래 추가 바이트를 사용하면 안 됩니다. 또한 애플리케이션이 클래스 또는 창 인스턴스에 사용하기 위해 추가 바이트를 추가하는 경우 원래 기본 클래스에서 사용하는 추가 바이트 수를 기준으로 추가 바이트를 참조해야 합니다. 기본 클래스에서 사용하는 바이트 수는 기본 클래스의 한 버전에서 다음 버전으로 다를 수 있으므로 슈퍼클래스의 추가 바이트에 대한 시작 오프셋도 기본 클래스의 한 버전에서 다음 버전으로 다를 수 있습니다.