[cpp] 작업 영역 정확하게 구하는 방법

@codemaru · June 18, 2015 · 3 min read

일반적으로 작업 영역을 구할때는 아래와 같은 코드를 많이 사용합니다. 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;
}
@codemaru
돌아보니 좋은 날도 있었고, 나쁜 날도 있었다. 그런 나의 모든 소소한 일상과 배움을 기록한다. 여기에 기록된 모든 내용은 한 개인의 관점이고 의견이다. 내가 속한 조직과는 1도 상관이 없다.
(C) 2001 YoungJin Shin, 0일째 운영 중