다음을 통해 공유


화면 보호기 처리

Microsoft Win32 API는 화면 보호기라는 특수 애플리케이션을 지원합니다. 화면 보호기는 마우스와 키보드가 지정된 기간 동안 유휴 상태일 때 시작됩니다. 이러한 두 가지 이유로 사용됩니다.

  • 정적 이미지로 인한 화면 번인을 방지하기 위해.
  • 화면에 남아 있는 중요한 정보를 숨기려면

이 항목은 다음 섹션으로 나뉩니다.

화면 보호기 정보

Windows 제어판의 데스크톱 응용 프로그램을 사용하면 사용자가 화면 보호기 목록에서 선택하고, 화면 보호기가 시작되기 전에 경과해야 하는 시간을 지정하고, 화면 보호기를 구성하고, 화면 보호기를 미리 볼 수 있습니다. Windows가 시작되거나 사용자가 제어판을 통해 화면 보호기를 활성화할 때 화면 보호기가 자동으로 로드됩니다.

화면 보호기를 선택하면 Windows에서 키 입력 및 마우스 움직임을 모니터링한 다음, 비활성 기간 후에 화면 보호기를 시작합니다. 그러나 다음 조건이 있는 경우 Windows에서 화면 보호기를 시작하지 않습니다.

  • 활성 애플리케이션은 Windows 기반 애플리케이션이 아닙니다.
  • CBT(컴퓨터 기반 학습) 창이 있습니다.
  • 활성 애플리케이션은 SC_SCREENSAVE 값으로 설정된 wParam 매개 변수가 있는 WM_SYSCOMMAND 메시지를 수신하지만 DefWindowProc 함수에 메시지를 전달하지는 않습니다.

화면 보호기의 보안 컨텍스트

화면 보호기의 보안 컨텍스트는 사용자가 대화형으로 로그온되었는지 여부에 따라 달라집니다. 화면 보호기가 호출될 때 사용자가 대화형으로 로그온되는 경우 화면 보호기는 대화형 사용자의 보안 컨텍스트에서 실행됩니다. 로그온한 사용자가 없는 경우 화면 보호기의 보안 컨텍스트는 사용 중인 Windows 버전에 따라 달라집니다.

  • Windows XP 및 Windows 2000 - 계정이 제한된 LocalSystem의 컨텍스트에서 화면 보호기가 실행됩니다.
  • Windows 2003 - 모든 권한이 제거되고 관리자 그룹이 비활성화된 LocalService 컨텍스트에서 화면 보호기가 실행됩니다.
  • Windows NT4에는 적용되지 않습니다.

보안 컨텍스트는 화면 보호기에서 수행할 수 있는 권한 있는 작업의 수준을 결정합니다.

Windows Vista 이상: 정책에서 암호 보호를 사용하도록 설정하면 애플리케이션이 SC_SCREENSAVE 알림으로 수행하는 작업과 관계없이 화면 보호기가 시작됩니다.

화면 보호기는 내보낸 특정 함수, 리소스 정의 및 변수 선언을 포함합니다. 화면 보호기 라이브러리에는 화면 보호기에서 필요한 기본 함수 및 기타 시작 코드가 포함되어 있습니다. 화면 보호기가 시작되면 화면 보호기 라이브러리의 시작 코드가 전체 화면 창을 만듭니다. 이 창의 창 클래스는 다음과 같이 선언됩니다.

WNDCLASS cls; 
cls.hCursor        = NULL; 
cls.hIcon          = LoadIcon(hInst, MAKEINTATOM(ID_APP)); 
cls.lpszMenuName   = NULL; 
cls.lpszClassName  = "WindowsScreenSaverClass"; 
cls.hbrBackground  = GetStockObject(BLACK_BRUSH); 
cls.hInstance      = hInst; 
cls.style          = CS_VREDRAW  | CS_HREDRAW | CS_SAVEBITS | CS_DBLCLKS; 
cls.lpfnWndProc    = (WNDPROC) ScreenSaverProc; 
cls.cbWndExtra     = 0; 
cls.cbClsExtra     = 0;

화면 보호기를 만들기 위해 대부분의 개발자는 세 가지 필수 함수가 포함된 소스 코드 모듈을 만들고 화면 보호기 라이브러리와 연결합니다. 화면 보호기 모듈은 자체 구성 및 시각 효과 제공만 담당합니다.

화면 보호기 모듈의 세 가지 필수 함수 중 하나는 ScreenSaverProc. 이 함수는 특정 메시지를 처리하고 처리되지 않은 메시지를 화면 보호기 라이브러리에 다시 전달합니다. 다음은 ScreenSaverProc처리되는 일반적인 메시지 중 일부입니다.

메시지 의미
WM_CREATE Regedit.ini 파일에서 초기화 데이터를 검색합니다. 화면 보호기 창에 대한 창 타이머를 설정합니다. 필요한 다른 초기화를 수행합니다.
WM_ERASEBKGND 화면 보호기 창을 지우고 후속 그리기 작업을 준비합니다.
WM_TIMER 그리기 작업을 수행합니다.
WM_DESTROY 애플리케이션에서 WM_CREATE 메시지를 처리할 때 만든 타이머를 삭제합니다. 필요한 추가 정리를 수행합니다.

 

ScreenSaverProcDefScreenSaverProc 함수를 호출하여 처리되지 않은 메시지를 화면 보호기 라이브러리에 전달합니다. 다음 표에서는 이 함수가 다양한 메시지를 처리하는 방법을 설명합니다.

메시지 행동
WM_SETCURSOR 커서를 null 커서로 설정하고 화면에서 제거합니다.
WM_PAINT 화면 배경을 그립니다.
WM_LBUTTONDOWN 화면 보호기를 종료합니다.
WM_MBUTTONDOWN 화면 보호기를 종료합니다.
WM_RBUTTONDOWN 화면 보호기를 종료합니다.
WM_KEYDOWN 화면 보호기를 종료합니다.
WM_MOUSEMOVE 화면 보호기를 종료합니다.
WM_ACTIVATE wParam 매개 변수가 FALSE로 설정되면 화면 보호기를 종료합니다.

 

화면 보호기 모듈의 두 번째 필수 함수는 ScreenSaverConfigureDialog. 이 함수는 사용자가 화면 보호기를 구성할 수 있도록 하는 대화 상자를 표시합니다(애플리케이션에서 해당 대화 상자 템플릿을 제공해야 합니다). 사용자가 제어판의 화면 보호기 대화 상자에서 설정 단추를 선택하면 Windows에서 구성 대화 상자가 표시됩니다.

화면 보호기 모듈의 세 번째 필수 함수는 registerDialogClasses. 이 함수는 모든 화면 보호기 애플리케이션에서 호출해야 합니다. 그러나 구성 대화 상자에서 특별한 창 또는 사용자 지정 컨트롤이 필요하지 않은 애플리케이션은 단순히 TRUE반환할 수 있습니다. 특수 창 또는 사용자 지정 컨트롤이 필요한 애플리케이션은 이 함수를 사용하여 해당 창 클래스를 등록해야 합니다.

방금 설명한 세 가지 함수를 지원하는 모듈을 만드는 것 외에도 화면 보호기에서 아이콘을 제공해야 합니다. 이 아이콘은 화면 보호기가 독립 실행형 애플리케이션으로 실행되는 경우에만 표시됩니다. (제어판에서 실행하려면 화면 보호기에서 .scr 파일 이름 확장명이 있어야 합니다. 독립 실행형 애플리케이션으로 실행하려면 .exe 파일 이름 확장명이 있어야 합니다.) 화면 보호기 리소스 파일에서 Scrnsave.h 헤더 파일에 정의된 상수 ID_APP 아이콘을 식별해야 합니다.

최종 요구 사항 중 하나는 화면 보호기 설명 문자열입니다. 화면 보호기 리소스 파일에는 제어판이 화면 보호기 이름으로 표시하는 문자열이 포함되어야 합니다. 설명 문자열은 리소스 파일의 문자열 테이블에서 첫 번째 문자열이어야 합니다(서수 값 1로 식별됨). 그러나 화면 보호기에서 긴 파일 이름이 있는 경우 제어판에서 설명 문자열을 무시합니다. 이 경우 파일 이름이 설명 문자열로 사용됩니다.

화면 보호기 함수 사용

이 섹션에서는 화면 보호기 애플리케이션에서 가져온 예제 코드를 사용하여 다음 작업을 보여 줍니다.

화면 보호기 만들기

이 예제의 애플리케이션은 1~10초 간격으로 화면을 흰색, 밝은 회색, 진한 회색 및 검은색의 네 가지 색 중 하나로 다시 칠합니다. 애플리케이션은 WM_TIMER 메시지를 받을 때마다 화면을 그립니다. 사용자는 애플리케이션의 구성 대화 상자를 선택하고 단일 가로 스크롤 막대를 조정하여 이 메시지가 전송되는 간격을 조정할 수 있습니다.

화면 보호기 라이브러리

정적 화면 보호기 함수는 화면 보호기 라이브러리에 포함됩니다. 사용할 수 있는 라이브러리에는 Scrnsave.lib와 Scrnsavw.lib의 두 가지 버전이 있습니다. 프로젝트를 다음 중 하나와 연결해야 합니다. Scrnsave.lib는 ANSI 문자를 사용하는 화면 보호기에서 사용되며 Scrnsavw.lib는 유니코드 문자를 사용하는 화면 보호기에서 사용됩니다. Scrnsavw.lib와 연결된 화면 보호기는 유니코드를 지원하는 Windows 플랫폼에서만 실행되고 Scrnsave.lib와 연결된 화면 보호기는 모든 Windows 플랫폼에서 실행됩니다.

구성 대화 상자 지원

대부분의 화면 보호기는 사용자가 고유한 색, 그리기 속도, 선 두께, 글꼴 등과 같은 사용자 지정 데이터를 지정할 수 있도록 하는 구성 대화 상자를 제공합니다. 구성 대화 상자를 지원하려면 애플리케이션에서 대화 상자 템플릿을 제공해야 하며 ScreenSaverConfigureDialog 함수도 지원해야 합니다. 다음은 샘플 애플리케이션에 대한 대화 상자 템플릿입니다.

DLG_SCRNSAVECONFIGURE DIALOG 6, 18, 160, 63
LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL
STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU
CAPTION "Sample Screen-Saver Setup"
FONT 8, "MS Shell Dlg"
BEGIN
    GROUPBOX      "Redraw Speed", 101, 0, 6, 98, 40
    SCROLLBAR     ID_SPEED, 5, 31, 89, 10
    LTEXT         "Fast", 103, 6, 21, 20, 8
    LTEXT         "Slow", 104, 75, 21, 20, 8
    PUSHBUTTON    "OK", ID_OK, 117, 10, 40, 14
    PUSHBUTTON    "Cancel", ID_CANCEL, 117, 32, 40, 14
END

다음 예제와 같이 10진수 값 2003을 사용하여 대화 상자 템플릿을 식별하는 데 사용되는 상수를 정의해야 합니다.

#define  DLG_SCRNSAVECONFIGURE 2003

다음 예제에서는 샘플 애플리케이션에 있는 ScreenSaverConfigureDialog 함수를 보여 줍니다.

#define MINVEL  1                 // minimum redraw speed value     
#define MAXVEL  10                // maximum redraw speed value    
#define DEFVEL  5                 // default redraw speed value    
 
LONG    lSpeed = DEFVEL;          // redraw speed variable         
  
extern HINSTANCE hMainInstance;   // screen saver instance handle  
 
CHAR   szAppName[80];             // .ini section name             
CHAR   szTemp[20];                // temporary array of characters  
CHAR   szRedrawSpeed[ ] = "Redraw Speed";   // .ini speed entry 
CHAR   szIniFile[MAXFILELEN];     // .ini or registry file name  
 
BOOL WINAPI ScreenSaverConfigureDialog(hDlg, message, wParam, lParam) 
HWND     hDlg; 
UINT     message; 
DWORD    wParam; 
LONG     lParam; 
HRESULT  hr;
{ 
    static HWND hSpeed;   // handle to speed scroll bar 
    static HWND hOK;      // handle to OK push button  
 
    switch(message) 
    { 
        case WM_INITDIALOG: 
 
            // Retrieve the application name from the .rc file.  
            LoadString(hMainInstance, idsAppName, szAppName, 
                       80 * sizeof(TCHAR)); 
 
            // Retrieve the .ini (or registry) file name. 
            LoadString(hMainInstance, idsIniFile, szIniFile, 
                       MAXFILELEN * sizeof(TCHAR)); 
 
            // TODO: Add error checking to verify LoadString success
            //       for both calls.
            
            // Retrieve any redraw speed data from the registry. 
            lSpeed = GetPrivateProfileInt(szAppName, szRedrawSpeed, 
                                          DEFVEL, szIniFile); 
 
            // If the initialization file does not contain an entry 
            // for this screen saver, use the default value. 
            if(lSpeed > MAXVEL || lSpeed < MINVEL) 
                lSpeed = DEFVEL; 
 
            // Initialize the redraw speed scroll bar control.
            hSpeed = GetDlgItem(hDlg, ID_SPEED); 
            SetScrollRange(hSpeed, SB_CTL, MINVEL, MAXVEL, FALSE); 
            SetScrollPos(hSpeed, SB_CTL, lSpeed, TRUE); 
 
            // Retrieve a handle to the OK push button control.  
            hOK = GetDlgItem(hDlg, ID_OK); 
 
            return TRUE; 
 
        case WM_HSCROLL: 

            // Process scroll bar input, adjusting the lSpeed 
            // value as appropriate. 
            switch (LOWORD(wParam)) 
                { 
                    case SB_PAGEUP: 
                        --lSpeed; 
                    break; 
 
                    case SB_LINEUP: 
                        --lSpeed; 
                    break; 
 
                    case SB_PAGEDOWN: 
                        ++lSpeed; 
                    break; 
 
                    case SB_LINEDOWN: 
                        ++lSpeed; 
                    break; 
 
                    case SB_THUMBPOSITION: 
                        lSpeed = HIWORD(wParam); 
                    break; 
 
                    case SB_BOTTOM: 
                        lSpeed = MINVEL; 
                    break; 
 
                    case SB_TOP: 
                        lSpeed = MAXVEL; 
                    break; 
 
                    case SB_THUMBTRACK: 
                    case SB_ENDSCROLL: 
                        return TRUE; 
                    break; 
                } 

                if ((int) lSpeed <= MINVEL) 
                    lSpeed = MINVEL; 
                if ((int) lSpeed >= MAXVEL) 
                    lSpeed = MAXVEL; 
 
                SetScrollPos((HWND) lParam, SB_CTL, lSpeed, TRUE); 
            break; 
 
        case WM_COMMAND: 
            switch(LOWORD(wParam)) 
            { 
                case ID_OK: 
 
                    // Write the current redraw speed variable to
                    // the .ini file. 
                    hr = StringCchPrintf(szTemp, 20, "%ld", lSpeed);
                    if (SUCCEEDED(hr))
                        WritePrivateProfileString(szAppName, szRedrawSpeed, 
                                                  szTemp, szIniFile); 
 
                case ID_CANCEL: 
                    EndDialog(hDlg, LOWORD(wParam) == ID_OK); 

                return TRUE; 
            } 
    } 
    return FALSE; 
}

대화 상자 템플릿을 제공하고 ScreenSaverConfigureDialog 함수를 지원하는 것 외에도 애플리케이션은 RegisterDialogClasses 함수를 지원해야 합니다. 이 함수는 화면 보호기에서 필요한 비표준 창 클래스를 등록합니다. 샘플 애플리케이션은 대화 상자 프로시저에서 표준 창 클래스만 사용했기 때문에 이 함수는 다음 예제와 같이 TRUE반환합니다.

BOOL WINAPI RegisterDialogClasses(hInst) 
HANDLE  hInst; 
{ 
    return TRUE; 
}

화면 보호기 창 프로시저 지원

각 화면 보호기는 ScreenSaverProc창 프로시저를 지원해야 합니다. 대부분의 창 프로시저와 마찬가지로 ScreenSaverProc 특정 메시지 집합을 처리하고 처리되지 않은 메시지를 기본 프로시저에 전달합니다. 그러나 DefWindowProc 함수에 전달하는 대신 ScreenSaverProc 처리되지 않은 메시지를 DefScreenSaverProc 함수에 전달합니다. ScreenSaverProc 일반 창 프로시저의 또 다른 차이점은 ScreenSaverProc에 전달된 핸들이 클라이언트 창이 아닌 전체 데스크톱을 식별할 있다는 것입니다. 다음 예제에서는 샘플 화면 보호기용 ScreenSaverProc 창 프로시저를 보여 줍니다.

LONG WINAPI ScreenSaverProc(hwnd, message, wParam, lParam) 
HWND  hwnd; 
UINT  message; 
DWORD wParam; 
LONG  lParam; 
{ 
    static HDC          hdc;      // device-context handle  
    static RECT         rc;       // RECT structure  
    static UINT         uTimer;   // timer identifier  
 
    switch(message) 
    { 
        case WM_CREATE: 
 
            // Retrieve the application name from the .rc file. 
            LoadString(hMainInstance, idsAppName, szAppName, 80 * sizeof(TCHAR)); 
 
            // Retrieve the .ini (or registry) file name. 
            LoadString(hMainInstance, idsIniFile, szIniFile, MAXFILELEN * sizeof(TCHAR)); 
 
            // TODO: Add error checking to verify LoadString success
            //       for both calls.
            
            // Retrieve any redraw speed data from the registry.  
            lSpeed = GetPrivateProfileInt(szAppName, szRedrawSpeed, 
                                          DEFVEL, szIniFile); 
 
            // Set a timer for the screen saver window using the 
            // redraw rate stored in Regedit.ini. 
            uTimer = SetTimer(hwnd, 1, lSpeed * 1000, NULL); 
            break; 
 
        case WM_ERASEBKGND: 
 
            // The WM_ERASEBKGND message is issued before the 
            // WM_TIMER message, allowing the screen saver to 
            // paint the background as appropriate. 

            hdc = GetDC(hwnd); 
            GetClientRect (hwnd, &rc); 
            FillRect (hdc, &rc, GetStockObject(BLACK_BRUSH)); 
            ReleaseDC(hwnd,hdc); 
            break; 
 
        case WM_TIMER: 
 
            // The WM_TIMER message is issued at (lSpeed * 1000) 
            // intervals, where lSpeed == .001 seconds. This 
            // code repaints the entire desktop with a white, 
            // light gray, dark gray, or black brush each 
            // time a WM_TIMER message is issued. 

            hdc = GetDC(hwnd); 
            GetClientRect(hwnd, &rc); 
            if (i++ <= 4) 
                FillRect(hdc, &rc, GetStockObject(i)); 
            else 
                (i = 0); 
            ReleaseDC(hwnd,hdc); 
            break; 
 
        case WM_DESTROY: 
 
            // When the WM_DESTROY message is issued, the screen saver 
            // must destroy any of the timers that were set at WM_CREATE 
            // time. 

            if (uTimer) 
                KillTimer(hwnd, uTimer); 
            break; 
    } 
 
    // DefScreenSaverProc processes any messages ignored by ScreenSaverProc. 
    return DefScreenSaverProc(hwnd, message, wParam, lParam); 
}

모듈 정의 파일 만들기

ScreenSaverProcScreenSaverConfigureDialog 함수는 애플리케이션의 모듈 정의 파일에서 내보내야 합니다. 그러나 RegisterDialogClasses 내보내면 안 됩니다. 다음 예제에서는 샘플 애플리케이션에 대한 모듈 정의 파일을 보여줍니다.

NAME    SSTEST.SCR 

DESCRIPTION 'SCRNSAVE : Test' 
 
STUB    'WINSTUB.EXE' 
EXETYPE WINDOWS 
 
CODE    MOVEABLE 
DATA    MOVEABLE MULTIPLE 
 
HEAPSIZE  1024 
STACKSIZE 4096 
 
EXPORTS 
        ScreenSaverProc 
        ScreenSaverConfigureDialog

새 화면 보호기 설치

사용 가능한 화면 보호기 목록을 컴파일할 때 제어판은 Windows 시작 디렉터리에서 .scr 확장이 있는 파일을 검색합니다. 화면 보호기는 .exe 확장명이 있는 표준 Windows 실행 파일이므로 확장명이 .scr이 있도록 이름을 바꾸고 올바른 디렉터리에 복사해야 합니다.

화면 보호기 구성 대화 상자에 도움말 추가

화면 보호기 구성 대화 상자에는 일반적으로 도움말 단추가 포함됩니다. 화면 보호기 애플리케이션은 도움말 단추 식별자를 확인하고 다른 Windows 기반 애플리케이션에서 도움말을 제공하는 것과 동일한 방식으로 WinHelp 함수를 호출할 수 있습니다.