서브 클래싱이란 이미 생성되어 있는 특정 윈도우의 윈도우 프로시저 함수를 임이의 다른 함수로 대체하여 처리하는 기법으로 특정 메시지의 처리나 윈도우의 기능을 확장할 목적으로 사용한다.

서브클래싱의 분류
1) 특정 컨트롤 윈도우의 서브 클래싱
2) 특정 윈도우 컨트롤 전체의 서브 클래싱

전역 클래싱의 경우 윈도우 클래스 구조체 WNDCLASS 의 내용을 직접 변경하는 방식을 말하며,
일반적으로 서브 클래싱이란 특정 윈도우의 윈도우 프로시저 함수를 임의의 다른 함수로 바꾸는 행위를 컨트롤 윈도우에 적용하는 것을 말한다.

서브 클래싱을 Win32 프로그래밍 방식에서 구현할 때는 고려할 게 많은데, 우선 윈도우 프로시저를 다른 함수로 변경하려면 ::SetWindowLong() 함수를 사용하고, 별도의 전역 함수를 만들고, 기존 윈도우 프로시저를 대체한 새 윈도우 프로시저 함수는 반드시 ::CallWindowProc() 함수로 호출해야 한다. 이런 일련의 과정은 API 후킹 기법과 매우 유사하다고 할 수 있다.

MFC 프로그래밍에서는 특정 컨트롤 윈도우를 확장할 때 서브 클래싱 구조를 기반으로 하며, 서브 클래싱은 단순히 파생 클래스를 등록하는 간단한 처리 하나만으로 완성된다. 그러므로 스태틱(Static) 텍스트를 서브 클래싱으로 확장할 때 단순히 CStatic 클래스를 상속받는 새로운 파생 클래스를 만드는 것으로 끝난다.

그러나 이와 같은 방법으로 기능을 확장하기 어려울 때는 명시적으로 해당 컨트롤 윈도우를 서브 클래싱해야 하는데, 대표적인 예로 리스트 컨트롤에 내장된 헤더 컨트롤이나 에디트 컨트롤처럼 이미 만들어진 컨트롤 윈도우에 대해 확장을 해야 하는 경우이다.

다음은 리스트 컨트롤의 헤더 컨트롤(CHeaderCtrl)을 명시적으로 서브 클래싱하여 확장할 때 사용한 주요 코드다. 



메인 다이얼로그 헤더에 추가.

public:
 CListCtrl m_List;
 CSubClassTestWnd m_wndTest; //리스트 컨트롤의 헤더 컨트롤을 서브 클래싱후 별도의 코드를 동작하게 한다.


void CSubClassTestWnd::OnPaint()
{
 //CPaintDC dc(this); // device context for painting 없애야 한다.
.

//상위 클래스의 OnPaint() 를 명시적으로 호출함으로써 서브 클래싱 될 대상 컨트롤 윈도우의 그리기가 완성됨
 CWnd::OnPaint();    //여기부터는 그리기가 완료된 헤더 컨트롤에 덧칠하듯 사각형을 그리는 코드다.
 CClientDC dc(this);

 CRect Rect(3,3,16,16);
 if(m_bFlag) dc.FillSolidRect(&Rect, RGB(192,0,0)); //검색
 else  dc.FillSolidRect(&Rect, RGB(255,255,255)); //흰색
}

void CSubClassTestWnd::OnLButtonDown(UINT nFlags, CPoint point)
{
 
 CWnd::OnLButtonDown(nFlags, point);

 CRect Rect(3,3,16,16);
 if(PtInRect(&Rect, point))
 {
  m_bFlag=!m_bFlag;
  RedrawWindow();
 }

}

void CSubClassTestWnd::OnDestroy()
{

 UnsubclassWindow(); //서브클래싱된 컨트롤 윈도우의 윈도우 프로시저 함수를 원래의 함수로 되돌려준다.
 CWnd::OnDestroy();


}




BOOL CSubClassDemo2Dlg::OnInitDialog()

//생략~~
 CHeaderCtrl* pHeaderCtrl = m_List.GetHeaderCtrl();
 m_wndTest.SubclassWindow(pHeaderCtrl->m_hWnd);
}




만일 이미 생성된 컨트롤 윈도우가 아니라 생성할 컨트롤 윈도우의 기능을 확장하고자 한다면 파생 클래스를 등록하는 간편한 방법으로 서브 클래싱을 구현하자.




'Windows > MFC' 카테고리의 다른 글

데이터베이스 ( Database ) - DBMS,ODBC  (0) 2011.11.20
오너 드로우 버튼 ( Owner-Draw )  (0) 2011.11.20
특별한 메시지 - 사용자 정의 메시지  (0) 2011.11.20
MFC 객체 간의 접근 방법  (0) 2011.11.19
CArchive 클래스  (0) 2011.11.19

+ Recent posts