자료 저장소

[특수한 윈도우]

# 윈도우 리전

일반적으로 윈도우 모양은 거의 모두 직사각형이다. 그러나 윈도우즈 95이후에는 직사각형이 아닌 모양의
윈도우도 아주 쉽게 만들 수 있다. 불규칙한 모양의 윈도우를 만들 때는 리전(Region)을 사용한다.

int SetWindowReg(HWND hWnd,HRGN hRgn,BOOL bRedraw);
리전 생성 함수로 리전을 만든 후 이 함수로 hRgn을 윈도우 리전으로 설정한다. 윈도우 리전은 그리기와 마우스
입력이 허가되는 윈도우 영역이며 윈도우 리전 바깥으로는 어떠한 그리기도 허가되지 않는다. 따라서 리전을
동그랗게 만들면 동그란 모양의 윈도우가 되고 별 모양으로 만들면 별 모양의 윈도우가 된다. 리전 생성 함수는
여러가지 종류가 있고 리전끼리 다양한 방법으로 조합이 가능하므로 얼마든지 복잡한 모양의 윈도우도 만들 수
있다.

bRedraw인수는 윈도우 리전을 설정한 후 윈도우를 다시 그릴 것인가 아닌가를 지정하며 TRUE이면 다시 그린다.
윈도우 리전에서 사용하는 좌표는 작업영역의 좌표가 아니라 윈도우 좌표이므로 리전 내부에 그리기를 할 때는
좌표 계산에 신경을 써야 한다. 아니면 아예 타이틀 바를 가지지 않은 팝업 윈도우로 만들면 윈도우 좌표와
작업영역 좌표가 일치 하므로 이런 좌표 문제는 신경쓰지 않아도 된다.


[윈도우 리전을 사용하여 타원 윈도우 만들기]

int APIENTRY WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance 
,LPSTR lpszCmdParam,int nCmdShow)
{
...
hWnd=CreateWindow(lpszClass,lpszClass,WS_POPUP | WS_SYSMENU,
100,100,200,200,NULL,(HMENU)NULL,hInstance,NULL); // 팝업 윈도우 생성
...
}

LRESULT CALLBACK WndProc(HWND hWnd,UINT iMessage,WPARAM wParam,LPARAM lParam)
{
HDC hdc;
PAINTSTRUCT ps;
UINT nHit;
HRGN hWndRgn;

switch (iMessage) {
case WM_CREATE:
hWndRgn=CreateEllipticRgn(0,0,200,200); // 타원 리전 생성
SetWindowRgn(hWnd,hWndRgn,FALSE); // 윈도우 리전으로 지정
return0;
case WM_PAINT:
hdc=BeginPaint(hWnd, &ps);
Ellipse(hdc,0,0,199,199); // 타원 그리기
Rectangle(hdc,40,50,160,150); // 사각형 그리기
TextOut(hdc,45,90,TEXT("스페이스-종료"),13);
EndPaint(hWnd, &ps);
return0;
case WM_NCHITTEST:
nHit=DefWindowProc(hWnd,iMessage,wParam,lParam);
if (nHit==HTCLIENT)
nHit=HTCAPTION; // 작업영역을 눌렀을때 캡션을 누른것 처럼 변경
return nHit;
case WM_KEYDOWN:
if (wParam==VK_SPACE)
DestroyWindow(hWnd);
returnTRUE;
case WM_DESTROY:
PostQuitMessage(0);
return0;
}
return(DefWindowProc(hWnd,iMessage,wParam,lParam));
}
: 리전에 대해서는 고급 그래픽에서 상세하게 설명함.


# 반투명한 윈도우
 
리전이 복잡해지면 시스템의 처리속도가 떨어져 화면이 깜빡이거나 윈도우 출력이 늦어지는 단점이 있다.
윈도우 2000에서는 레이어드 윈도우라는 새로운 기술이 추가되어 더욱 화려한 윈도우들을 만들 수 있게 되었다.

레이어드윈도우(Layered Window)는 리전보다 훨씬 복잡한 모양을 쉽게 만들 수 있을 뿐만 아니라 애니메이션도
용이하며 반투명 효과, 투명효과, 수시로 모양이 변하는 애니메이션까지 가능하다.

레이어드 윈도우를 만들려면 WS_EX_LAYERED 확장 스타일을 준다. CreateWindowEx 함수로 윈도우를 만들 때
줄 수도 있고 아니면 이미 만들어진 윈도우에 SetWindowLong 함수로 이 스타일을 추가 할 수도 있다.
일단 레이어드 윈도우가 되면 이 윈도우는 다음 함수를 호출하기 전에는 화면에 보이지 않는다.

BOOL SetLayeredWindowAttributes(HWND hwnd,COLORREF crKey,BYTE bAlpha,DWORD dwFlags);
이 함수는 레이어드 윈도우의 투명 빛 반투명 속성을 설정한다. hWnd는 설정 대상 윈도우의 핸들이며 crKey는
투명으로 처리할 색상을 지정한다. 투명으로 지정된 색상 부분은 윈도우에서 보이지 않는 투명 영역으로
처리 된다. bAlpha는 윈도우 전체의 반투명정도를 지정하는데 0이면 완전투명, 255이면 불투명, 128이면
반투명하게 그려진다. 이때 배경에 있는 다른 윈도우는 시스템이 알아서 그린다. dwFlags는 두 효과중 어떤
효과를 적용할 것인가를 지정하는데 LWA_COLORKEY 플래그는 투명 색상 지정을, LWA_ALPHA는 반투명
정도를 지정하며 두 플래그를 동시에 줄 수도 있다.

[투명 윈도우 및 투명도를 조절하는 예제]

int APIENTRY WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance 
,LPSTR lpszCmdParam,int nCmdShow)
{
DialogBox(hInstance, MAKEINTRESOURCE(IDD_DIALOG1), HWND_DESKTOP, MainDlgProc);

return0;
}

void SetAttr(int iOpa)
{
SetLayeredWindowAttributes(hDlgMain,RGB(0,0,255),iOpa,
LWA_ALPHA | LWA_COLORKEY);
}

BOOL CALLBACK MainDlgProc(HWND hDlg,UINT iMessage,WPARAM wParam,LPARAM lParam)
{
HDC hdc;
PAINTSTRUCT ps;
HBRUSH hBrush, hOldBrush;
staticint iOpa=200;

switch (iMessage) {
case WM_INITDIALOG:
hDlgMain = hDlg;
SetWindowLong(hDlg,GWL_EXSTYLE,
GetWindowLong(hDlg,GWL_EXSTYLE) | WS_EX_LAYERED);
SetAttr(iOpa);
returnTRUE;
case WM_COMMAND:
switch (LOWORD(wParam)) {
case IDOK:
case IDCANCEL:
EndDialog(hDlgMain,0);
returnTRUE;
case IDC_BTNPLUS:
iOpa+=25;
if (iOpa > 255)
iOpa=255;
SetAttr(iOpa);
returnTRUE;
case IDC_BTNMINUS:
iOpa-=25;
if (iOpa < 50)
iOpa=50;
SetAttr(iOpa);
returnFALSE;
}
case WM_PAINT:
hdc=BeginPaint(hDlg, &ps);
hBrush=CreateSolidBrush(RGB(0,0,255));
hOldBrush=(HBRUSH)SelectObject(hdc,hBrush);
SelectObject(hdc,GetStockObject(NULL_PEN));
Rectangle(hdc,10,10,300,80);
SelectObject(hdc,hOldBrush);
DeleteObject(hBrush);
EndPaint(hDlg, &ps);
return0;
}
returnFALSE;
}


레이어드 윈도우와 함께 사용되는 또 다른 함수는 UpdateLayeredWindow라는 함수 인데 이 함수를 사용하면
윈도우의 모양도 자유 자재로 바꿀 수 있고 훨씬 더 많은 효과를 줄 수 있다. 상당히 매력적이긴하나 95/98에선
실행이 되지않는다.


# 윈도우 애니메이션

BOOL AnimateWindow(HWND hWnd,DWORD dwTime,DWORD dwFlags);

이 함수는 98이상 윈도우즈에서만 사용가능하다.
hWnd는 대상 윈도우의 핸들이며 dwTime은 애니메이션 진행 시간을 지정하고 dwFlags는 애니메이션의 종류와
방식을 지정한다.  종류는 슬라이딩 방식, 블렌딩 방식, 중앙에서 열리는 방식 등이 있고 방향을 지정하는 여러값
들이 있다.

MSDN : http://msdn.microsoft.com/en-us/library/ms632669(VS.85).aspx 


[간단한 애니메이션 윈도우]

LRESULT CALLBACK WndProc(HWND hWnd,UINT iMessage,WPARAM wParam,LPARAM lParam) 
{
HDC hdc;
PAINTSTRUCT ps;
TCHAR *Mes=TEXT("마우스 왼쪽 버튼을 누르시면 애니메이션을 볼 수 있습니다");
int i;

switch (iMessage) {
case WM_LBUTTONDOWN:
i=(LOWORD(lParam)-10)/50;
ShowWindow(hWnd,SW_HIDE);
switch (i) {
case0:
AnimateWindow(hWnd,500,AW_SLIDE | AW_HOR_POSITIVE);
break;
case1:
AnimateWindow(hWnd,500,AW_SLIDE | AW_HOR_NEGATIVE);
break;
case2:
AnimateWindow(hWnd,500,AW_SLIDE | AW_VER_POSITIVE);
break;
case3:
AnimateWindow(hWnd,500,AW_SLIDE | AW_VER_NEGATIVE);
break;
case4:
AnimateWindow(hWnd,500,AW_SLIDE | AW_HOR_POSITIVE | AW_VER_POSITIVE);
break;
case5:
AnimateWindow(hWnd,500,AW_SLIDE | AW_HOR_POSITIVE | AW_VER_NEGATIVE);
break;
case6:
AnimateWindow(hWnd,500,AW_BLEND);
break;
case7:
default:
AnimateWindow(hWnd,500,AW_CENTER);
break;
}
InvalidateRect(hWnd,NULL,TRUE);
SetForegroundWindow(hWnd);
returnTRUE;
case WM_PAINT:
hdc=BeginPaint(hWnd, &ps);
TextOut(hdc,10,10,Mes,lstrlen(Mes));
for (i=10;i<=360;i+=50)
Rectangle(hdc,i,50,i+50,100);
EndPaint(hWnd, &ps);
return0;
case WM_DESTROY:
PostQuitMessage(0);
return0;
}
return(DefWindowProc(hWnd,iMessage,wParam,lParam));
}
댓글 로드 중…

최근에 게시된 글