일반적으로 작업 영역을 구할때는 아래와 같은 코드를 많이 사용합니다. SystemParametersInfo의 SPI_GETWORKAREA를 사용하여 작업 표시줄을 제외한 작업영역을 구하는 방법입니다.
RECT rc;
SystemParametersInfo(SPI_GETWORKAREA, 0, &rc, FALSE);
위 방법에는 한가지 단점이 있습니다. 작업표시줄의 자동 숨김 옵션을 활성화하면 전체 화면을 작업 영역으로 구하는 것이죠. 자동 숨김으로 하더라도 작업 표시줄이 완전히 사라지는 것이 아니라 미세하게 두께를 차지하기 때문에 약간의 높이가 있습니다. 때로는 이 미세한 영역도 정교하게 처리해 주고 싶을 때가 있습니다. 그럴 땐 SPI_GETWORKAREA를 사용할 수 없습니다.
GetWorkArea는 자동 숨김 옵션을 활성화한 경우에도 항상 정확하게 작업 표시줄 영역을 구해주는 함수입니다. lprc로 RECT 구조체의 포인터를 넘겨주면 절대적인 작업 영역을 구해서 넘겨줍니다. 별로 중요하다거나 어려운 부분은 없습니다. 단지 한가지 알아두면 유용한 것은, 작업 표시줄이 어떤 위치에 바인딩 되어 있는지를 구하기 위해서는 SHAppBarMessage API를 사용한다는 점 입니다.
GetWorkArea 함수 코드 소스 코드 다운로드
void GetWorkArea(LPRECT lprc)
{
SIZE szScreen;
HWND hShell = FindWindowW(L"Shell_TrayWnd", NULL);
szScreen.cx = GetSystemMetrics(SM_CXSCREEN);
szScreen.cy = GetSystemMetrics(SM_CYSCREEN);
SetRect(lprc, 0, 0, szScreen.cx, szScreen.cy);
if(!hShell)
return;
RECT rcTaskbar;
SIZE szTaskbar;
APPBARDATA AppBarData;
POINT pt = {0,0};
POINT ptMouse;
GetWindowRect(hShell, &rcTaskbar);
szTaskbar.cx = rcTaskbar.right - rcTaskbar.left;
szTaskbar.cy = rcTaskbar.bottom - rcTaskbar.top;
AppBarData.cbSize = sizeof AppBarData;
SHAppBarMessage(ABM_GETTASKBARPOS, &AppBarData);
switch(AppBarData.uEdge)
{
case ABE_TOP:
lprc->top += szTaskbar.cy;
break;
case ABE_BOTTOM:
lprc->bottom -= szTaskbar.cy;
break;
case ABE_LEFT:
lprc->left += szTaskbar.cx;
break;
case ABE_RIGHT:
lprc->right -= szTaskbar.cx;
break;
}
}
아래와 같은 테스트 코드로 두 가지 방법을 비교해 보면 작업 표시줄의 항상 숨김 옵션을 끈 경우에는 결과 값이 동일하지만 해당 옵션을 활성화한 경우에는 GetWorkArea가 구한 영역이 조금 더 작다는 것을 보실 수 있습니다.
int main()
{
RECT rc;
SystemParametersInfo(SPI_GETWORKAREA, 0, &rc, FALSE);
printf("%d %d %d %d\n", rc.left, rc.top, rc.right, rc.bottom);
GetWorkArea(&rc);
printf("%d %d %d %d\n", rc.left, rc.top, rc.right, rc.bottom);
return 0;
}