방패 모양 윈도우 만들기 > MFC Tip

본문 바로가기
사이트 내 전체검색

MFC Tip

방패 모양 윈도우 만들기

페이지 정보

profile_image
작성자 이즈
댓글 0건 조회 1,073회 작성일 06-12-27 00:10

본문

윈도우의 모양을 개성있게 만들기 위해 노턴 크래시 가드의 모양처럼 방패 모양의 윈도우를 만들려고 합니다. SetWindowRgn() 함수를 사용하라고 하던데 이 함수는 CreateEllipsRgn() 등의 함수를 이용해 영역을 만들어야 하더군요. 하지만 이런 영역을 만드는 함수가 만들 수 있는 영역의 모양은 타원, 사각형, 둥그런 사각형, 다각형, 다중다각형 등의 모양 밖에 안됩니다. 이런 정도의 함수로 자유로운 모양의 윈도우를 제작할 수는 없나요?

 가끔 이상한 모양의 윈도우를 보게 될 것입니다. 대표적으로 자주 보게 되는 것이 MP3 플레이어로 각광받고 있는 WinAmp를 예를 들 수 있죠. 이런 윈도우들을 보면 어떻게 구현했는지 참 궁굼합니다. 이런 종류의 윈도우들은 대부분 윈도우에 비트맵(Bitmap)을 덮어 씌워 구현합니다. 일단 이런 종류의 윈도우를 구현하려면 좌표 영역을 계산해야 되기 때문에 상당히 잔손이 많이 가게 됩니다. 구현원리는 이렇습니다.먼저 몇가지 NC(Non-Client 영역)에 대한 메시지들을 처리해야 합니다.

윈도우의 캡션바를 변경하려면 우선 윈도우가 활성화되는 경우 모두 세 가지가 있는데 이럴 때 캡션 부분을 WindowDC로 그려주면 됩니다(WindowDC에 대한 설명은 MSDN을 참조). PreCreate 메시지 핸들러에서 윈도우 스타일을 WS_VISIBLE, WS_CAPTION, WS_THICKFRAME 이 세가지 스타일만 있게 정의하고, 다음과 같이 메인 프레임 메시지 핸들러에 정의하면 첫째 파라미터 nStart는 세 가지의 파라미터가 넘어옵니다.

afx_msg void OnActivate(UINT nState, CWnd* pWndOther, BOOL bMinimized);

 WA_ACTIVE : 클릭 이외 다른 윈도우가 인액티브 돼 자신이 z-order의 맨 앞으로 왔을 때 발생
 WA_CLICKACTIVE : 클릭에 의해 액티브될 때 발생
 WA_INACTIVE : 인액티브 상태

 이 파라미터 값을 체크하고 모든 경우에 대해 알맞은 그림을 그려주면 됩니다. 그림을 그릴 때 약간의 테크닉이 필요합니다. 비트맵을 제어해 본 독자는 알겠지만 많은 양의 비트맵을 그릴 경우 화면의 깜박임 현상을 볼 수 있는데, 이런 깜박임 현상을 없애려면 memDC를 사용하면 됩니다. memDC를 사용하는 것은 우선 메모리 상에 가상의 비트맵을 만들고 거기에 모든 그림을 그린 다음 화면에 한 번에 뿌리면 화면 깜박임이 없어지게 됩니다.

CRect rect;
GetWindowRect(&rect);
CBitmap bmpCaption;    // 캡션 그림을 그리는 비트맵
bmpCaption.LoadBitmap(IDB_CAPTION);
CWindowDC capDC(this);    // 창에 그릴 DC를 선택
CDC capMemDC;
CDC bufDC;
capMemDC.CreateCompatibleDC(&capDC);
CBitmap bufBitmap;    // 메모리 상의 가상 비트맵
// 윈도우 크기만큼의 메모리 비트맵을 만든다.
bufBitmap.CreateCompatibleBitmap(&capDC, rect.Width(), 48);

CBitmap* pOldBitmap1 = (CBitmap*)bufDC.SelectObject(&bufBitmap);
CBitmap* pOldBitmap2 = (CBitmap*)capMemDC.SelectObject(&bmpCaption);

bufDC.BitBlt(0, 0, 120, 48, &capMemDC, 0, 0, SRCCOPY);

for(int i = 120; i<rect.Width()-120; ) {
    bufDC.BitBlt(i, 0, 10, 48, &capMemDC, 100, 0, SRCCOPY);
    i += 10;    // 크기가  10 픽셀인 비트맵을 캡션에 그린다.
}

capDC.BitBlt(0, 0, rect.Width(), 48, &bufDC, 0, 0, SRCCOPY);

 

 이런 식으로 비트맵 파일을 핸들링하고 WM_NCPAINT 메시지에서 적절히 처리해주면 됩니다.

afx_msg OnNcCalcsize(BOOL bCalcValidRects, NCCALCSIZE_PARAMS FAR* lpncsp);

위의 함수는 WM_NCCALCSIZE 라는 메시지 핸들러인데, 이 함수의 두 번째 함수 인자는 CRect이 세 개로 구성된 struct이고 이 중에 첫 번째가 클라이언트 영역을 표시하는 부분입니다. 이 인자의 값을 조정해주면 원하는 클라이언트 영역으로 조정할 수 있게 됩니다.

afx_msg UINT OnNcHitTest(CPoint point);
afx_msg UINT OnHitTest(. . . . .);

 이런 식으로 윈도우의 모양을 자유롭게 만들 수 있습니다. 윈도우에 비트맵을 씌워 윈도우 모양을 바꾸면 프레임웍에서 더 이상 체크를 못합니다. 예를 들어 일정한 영역에 마우스가 들어왔는지, 클릭이 됐는지 등등이지요. 그렇다면 이것도 다  구현해야 합니다. 이럴 때 위의 메시지 핸들러를 사용하면 됩니다. 우리가 비트맵을 씌워 만든 윈도우에 어느 영역에 마우스, 키보드 등의 이벤트가 발생했는지를 체크하면 됩니다. 앞서 서두에서 말한 지루한 작업이 바로 이것입니다. 이런 식으로 캡션 부분(위쪽), 상태바 부분(아래쪽), 클라이언트 부분(뷰), 테두리 부분 등 어느 부분이나 모양을 자유로이 변경할 수 있습니다.

댓글목록

등록된 댓글이 없습니다.

Total 172건 7 페이지

검색

회원로그인

회원가입

사이트 정보

컴퓨터 정보,윈도우즈,리눅스,포토샵,3ds
맥스,프로그래밍 강좌팁

접속자집계

오늘
310
어제
569
최대
5,287
전체
636,585
Copyright © www.qdata.co.kr All rights reserved.