. 오너 드로우 파트

상태란의 각 파트는 개별적으로 오너 드로우로 지정할 수 있다. SB_SETTEXT 메시지로 텍스트를 지정할 때 wParam에 SBT_OWNERDRAW 플래그를 주면 이 파트는 오너 드로우가 된다. 이때 lParam은 텍스트 대신 부모 윈도우로 전달될 사용자 정의 데이터를 지정한다. 오너 드로우 파트가 그려져야 할 때는 다른 컨트롤과 마찬가지로 부모 윈도우로 WM_DRAWITEM 메시지가 보내지며 이때 lParam으로 전달되는 DRAWITEMSTRUCT에는 다음과 같은 정보가 전달된다.

 

멤버

설명

itemID

파트의 번호

hwndItem, CtrlID

상태란의 핸들과 ID

hDC

그리기에 사용될 DC 핸들

rcItem

상태란의 좌상단을 기준으로 한 파트의 영역

itemData

SB_SETTEXT 메시지의 lParam으로 전달된 사용자 데이터

 

다른 컨트롤과는 달리 itemAction, itemState 등의 멤버는 아무런 값도 가지지 않으므로 이 값들은 참조하지 말아야 한다. DC 핸들과 그릴 영역을 전달 받으므로 그림은 물론 비트맵을 출력할 수도 있다. WM_DRAWITEM 메시지를 처리하는 방법은 메뉴나 리스트 박스 등 오너 드로우를 지원하는 모든 컨트롤과 동일하다.

SB_SETTEXT 메시지의 또 다른 재미있는 기능은 텍스트에 탭 문자를 넣어 정렬 상태를 지정할 수 있다는 점이다. 아무런 지정없이 텍스트만 전달하면 이 문자열은 파트의 왼쪽을 기준으로 정렬된다. 문자열에 \t를 넣으면 이 문자열은 파트의 중앙에 정렬되며 \t를 두번 넣으면 오른쪽으로 정렬된다. 즉 "텍스트"라고 쓰면 왼쪽으로, "\t텍스트"라고 쓰면 중앙으로 "\t\t텍스트"라고 쓰면 오른쪽으로 정렬된다. 각 탭 문자 사이에도 텍스트를 넣을 수 있는데 이렇게 되면 한 파트 내에서 탭을 기준으로 정렬 상태가 다른 문자열을 출력할 수도 있다.

상태란은 보통 몇개의 파트로 구분되는데 심플 모드라는 별도의 모드를 사용하면 상태란 전체를 하나의 긴 텍스트를 출력하는 용도로 잠시 전환할 수 있다. 여러 종류의 정보를 보여주기 위해 파트를 나누어 놓은 상태에서 잠시 긴 메시지를 보여줄 필요가 있다면 심플 모드로 전환한 후 메시지를 보여 주고 다시 파트 모드로 돌아오면 된다. 각 파트에 기억된 문자열과 심플 모드에 기억된 문자열은 서로 구분되어 저장되므로 모드를 바꾸더라도 파트의 텍스트가 바뀌지는 않는다.

심플 모드의 텍스트를 지정할 때도 SB_SETTEXT 메시지를 사용하는데 파트 번호 대신 SB_SIMPLEID를 지정하면 된다. 이 값은 commctrl.h에 0xff로 정의되어 있으나 비주얼 C++ 6.0의 헤더 파일에는 이 값이 없으므로 상수를 곧바로 적어주어야 한다. 비주얼 C++ 7.0을 사용하고 있다면 SB_SIMPLEID를 곧바로 적어 주면 된다.

심플 모드로 전환할 때는 SB_SIMPLE 메시지를 사용하며 현재 상태가 심플 모드인가 아닌가를 알고 싶을 때는 SB_ISSIMPLE 메시지로 조사할 수 있다. 심플 모드는 오너 드로우를 지원하지 않으며 텍스트만 출력할 수 있다. SB_SETTEXT 메시지는 여러 모로 재미있는 기능을 많이 지원하고 있는데 다음 예제는 지금까지 설명한 이 메시지의 모든 기능을 종합적으로 보여준다.

 

#include <Commctrl.h>

HWND hState;

LRESULT CALLBACK WndProc(HWND hWnd,UINT iMessage,WPARAM wParam,LPARAM lParam)

{

   HDC hdc;

   PAINTSTRUCT ps;

   int SBPart[6],i;

   LPDRAWITEMSTRUCT lpdis;

   RECT rt;

 

   switch(iMessage) {

   case WM_CREATE:

      InitCommonControls();

      hState=CreateStatusWindow(WS_CHILD | WS_VISIBLE, "", hWnd,0);

      for (i=0;i<5;i++) {

          SBPart[i]=100+i*100;

      }

      SBPart[5]=-1;

      SendMessage(hState, SB_SETPARTS, 6, (LPARAM)SBPart);

      SendMessage(hState, SB_SETMINHEIGHT,30,0);

      SendMessage(hState, SB_SETTEXT,0 | SBT_OWNERDRAW,0);

      SendMessage(hState, SB_SETTEXT,1 | SBT_OWNERDRAW,0);

      SendMessage(hState, SB_SETTEXT,2,(LPARAM)"왼쪽");

      SendMessage(hState, SB_SETTEXT,3,(LPARAM)"\t가운데");

      SendMessage(hState, SB_SETTEXT,4,(LPARAM)"\t\t오른쪽");

      SendMessage(hState, SB_SETTEXT,5,(LPARAM)"\t중앙\t    ");

      SendMessage(hState, SB_SETTEXT,0xff/*SB_SIMPLEID*/,

          (LPARAM)"상태란 전체를 차지하는 도움말입니다");

      return 0;

   case WM_DRAWITEM:

      lpdis=(LPDRAWITEMSTRUCT)lParam;

      if (lpdis->hwndItem == hState) {

          if (lpdis->itemID == 0) {

             SelectObject(lpdis->hDC,GetStockObject(LTGRAY_BRUSH));

             Rectangle(lpdis->hDC,lpdis->rcItem.left+10, lpdis->rcItem.top+2,

                lpdis->rcItem.right-10, lpdis->rcItem.bottom-2);

          } else {

             SelectObject(lpdis->hDC,GetStockObject(DKGRAY_BRUSH));

             Ellipse(lpdis->hDC,lpdis->rcItem.left+10, lpdis->rcItem.top+2,

                lpdis->rcItem.right-10, lpdis->rcItem.bottom-2);

          }

      }

      return 0;

   case WM_LBUTTONDOWN:

      if (SendMessage(hState, SB_ISSIMPLE,0,0)) {

          SendMessage(hState,SB_SIMPLE,(WPARAM)FALSE,0);

      } else {

          SendMessage(hState,SB_SIMPLE,(WPARAM)TRUE,0);

      }

      return 0;

   case WM_SIZE:

      SendMessage(hState, WM_SIZE, wParam, lParam);

      return 0;

   case WM_PAINT:

      hdc=BeginPaint(hWnd, &ps);

      SetRect(&rt,10,10,500,30);

      DrawStatusText(hdc,&rt,"마우스 왼쪽 버튼을 누르면 심플 모드를 토글합니다.",0);

      EndPaint(hWnd, &ps);

      return 0;

   case WM_DESTROY:

      PostQuitMessage(0);

      return 0;

   }

   return(DefWindowProc(hWnd,iMessage,wParam,lParam));

}

 

오너 드로우 기능을 테스트하기 위해 SB_SETMINHEIGHT 메시지를 사용하여 상태란의 높이를 30픽셀로 높게 만들었다. 6개의 파트로 나누었으며 첫번째, 두번째 파트는 오너 드로우로 사각형과 타원을 그려 보았다. 나머지 파트는 탭을 이용한 정렬 기능을 보여 준다. 실행 결과는 다음과 같다.

마우스 왼쪽 버튼을 누르면 심플 모드로 전환하여 심플 모드 텍스트를 보여 주고 마우스 버튼을 다시 누르면 파트가 나누어진 상태로 복원된다. 두 모드의 텍스트는 각각 따로 저장되므로 모드를 바꾼다고 해서 텍스트를 다시 지정할 필요는 없다.

다음 함수는 상태란과 직접적인 상관은 없지만 공통 컨트롤 라이브러리에 의해 제공되는 함수이다.

 

void DrawStatusText(HDC hdc, LPRECT lprc, LPCTSTR pszText, UINT uFlags );

 

DC 핸들과 문자열 출력 영역, 그리고 문자열을 주면 이 문자열을 마치 상태란의 파트처럼 출력해 준다. uFlags에는 SBT_POPOUT, SBT_NOBORDER 등의 플래그를 줄 수 있다. 3차원의 박스를 그리고 문자열을 출력해 주므로 장식적인 문자열 출력에 적합한 함수이다. 특히 빈 문자열을 주면 양각, 음각의 사각 박스만 그릴 수 있다는 점에서 응용 가치가 있다. 상태란의 파트와 마찬가지로 탭 문자를 이용하여 정렬 상태를 지정할 수 있다.