IT_Programming/MFC · API

[API] 슈퍼 클래싱 (Super Classing)

JJun ™ 2009. 7. 29. 15:52

================================================================================================

 

[ 슈퍼 클래싱 ]

 

- ( 서브 클래싱의 경우 윈도우 프로시저만 교체하는 것인 반면... ) 

   기존 클래스(베이스 클래스)의 정보를 바탕으로 하여 새로운 클래스를 만드는 것이다. 

 

- GetClassInfo(ex) 함수 사용 (RegisterClass 함수의 반대 함수라고 생각하자!)

   :  lpClassName 윈도우 클래스의 정보를 조사하여 lpWndClass가

      가리키는 WNDCLASS 구조체에 채운다. (시스템에 의해 만들어진 윈도우 - 1번째 인자 : NULL)

 

- GetClassInfo 함수 이후 WndClass의 정보를 적절히 수정한 후 다시 RegisterClass 함수로 등록한다.

 

-----------------------------------------------------------------------------------------------

 

주의! 클래스 이름이 베이스 클래스와 같아서는 안된다. 또한 hInstance 멤버에는 이 윈도우 클래스를

등록하는 응용 프로그램의 인스턴스 핸들을 대입해야 한다.(그래야 이 인스턴스가 종료될 때 등록해제 된다.)

또 가장 중요한 lpfnWndProc 멤버를 수정하여 응용 프로그램이 정의한 윈도우 프로시저로 메시지를

보내도록 해야한다. 단, 이 때 기존의 윈도우 프로시저 번지는 복구를 위해 잘 보관해두어야 한다.

 

[ 서브클래싱과 슈퍼 클래싱에 대한 결론 ]

☞ 특정 윈도우 하나만 수정할 때는 인스턴스 서브 클래싱을 사용하고,

    다량의 윈도우를 한꺼번에 바꿀 때는 전역 서브 클래싱 또는 슈퍼 클래싱을 사용하는 것이 편리하다!

 

-----------------------------------------------------------------------------------------------

 

[ 내용참조 및 예제참조 출처 - 윈도우즈 API 정복 1권]

================================================================================================

 

[실행화면]

 

- 키보드를 누를 때마다 소리를 낸다! 

 

================================================================================================

 

[소스코드]

 

#include <windows.h>

 

#define ID_EDIT1 100

 

LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
LRESULT CALLBACK SuperEditProc(HWND, UINT, WPARAM, LPARAM);

 

HINSTANCE g_hInst;
HWND  hEdit1;
WNDPROC  Old_EditProc;

 

int APIENTRY WinMain( HINSTANCE hInstance,

                                  HINSTANCE hPrevInstance,

                                  LPSTR lpCmdLine,

                                  int nShowCmd )
{
      static char MainClassName[] = TEXT("WinMain");
      HWND  hwnd;
      MSG   msg;
      WNDCLASS wndclass;
  
      g_hInst = hInstance;

     

      wndclass.cbClsExtra  = 0;
      wndclass.cbWndExtra  = 0;
      wndclass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
      wndclass.hCursor  = LoadCursor(NULL, IDC_ARROW);
      wndclass.hIcon   = LoadIcon(NULL, IDI_APPLICATION);
      wndclass.hInstance  = hInstance;
      wndclass.lpfnWndProc = WndProc;
      wndclass.lpszClassName = MainClassName;
      wndclass.lpszMenuName = NULL;
      wndclass.style   = CS_VREDRAW | CS_HREDRAW;

     

      RegisterClass(&wndclass);

 

      hwnd = CreateWindow (
                                          MainClassName,
                                          MainClassName,
                                          WS_OVERLAPPEDWINDOW,
                                          CW_USEDEFAULT,
                                          CW_USEDEFAULT,
                                          CW_USEDEFAULT,
                                          CW_USEDEFAULT,
                                          NULL,
                                          (HMENU) 0,
                                          hInstance,
                                          NULL
                                    );
 
      ShowWindow(hwnd, nShowCmd);

 

      while(GetMessage(&msg, NULL, 0, 0))
      {
            TranslateMessage(&msg);
            DispatchMessage(&msg);
      }

 

      return (int)msg.wParam;
}

 

LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wp, LPARAM lp)
{
      HDC   hdc;
      PAINTSTRUCT ps;
      WNDCLASS wndclass; // 수정할 윈도우 클래스를 담을 변수
      TCHAR  *Mes = TEXT("에디트에서 키보드를 누를때 마다 소리를 낸다!");

     

      switch (message)
      {
            case WM_CREATE : MoveWindow(hwnd, 300, 250, 370, 100, TRUE);

                                          // ↓ wndclass에 원래 edit 윈도우 속성을 세팅
                                          GetClassInfo(NULL, TEXT("edit"), &wndclass);   

                                          wndclass.hInstance  = g_hInst;

                                          // 슈퍼클래싱할 윈도우 클래스명
                                          wndclass.lpszClassName = TEXT("SuperEditClass");  

                                          wndclass.hCursor  = LoadCursor(NULL, IDC_WAIT);

                                   

                                          // 기존 윈도우 프로시저의 번지를 저장하고, 슈퍼클래싱!
                                          Old_EditProc   = wndclass.lpfnWndProc;
                                          wndclass.lpfnWndProc = SuperEditProc; // 슈퍼클래스 프로시저 등록
                                          RegisterClass(&wndclass);

 

                                          hEdit1 = CreateWindow (

                                                                                // ↓ 슈퍼클래싱한 윈도우 클래스명
                                                                               TEXT("SuperEditClass"), 

                                                                               NULL,
                                                         WS_CHILD | WS_VISIBLE | WS_BORDER | ES_AUTOHSCROLL,
                                                                               80,
                                                                               10,
                                                                               200,
                                                                               25,
                                                                               hwnd,
                                                                               (HMENU)ID_EDIT1,
                                                                               g_hInst,
                                                                               NULL
                                                                         );
                                         SetFocus(hEdit1);
                                         return 0;

 

            case WM_PAINT :  hdc = BeginPaint(hwnd, &ps);
                                        TextOut(hdc, 10, 50, Mes, lstrlen(Mes));
                                        EndPaint(hwnd, &ps);
                                        return 0;

 

            case WM_DESTROY : PostQuitMessage(0);
                                            return 0;
      }

     

      return (DefWindowProc(hwnd, message, wp, lp));
}

 

/* 슈퍼 클래스 프로시저 */

LRESULT CALLBACK SuperEditProc(HWND hwnd, UINT message, WPARAM wp, LPARAM lp)
{
      switch (message)
      {
            case WM_KEYDOWN : MessageBeep(0); 
                                   //       break;
      }

// CallWindowProc 함수: 관심을 가지는 메시지 이외에는 원래의 에디트 윈도우 방식으로 처리!  
      return CallWindowProc(Old_EditProc, hwnd, message, wp, lp);

================================================================================================