Compartilhar via


Manipulando poupadores de tela

A API do Microsoft Win32 dá suporte a aplicativos especiais chamados de poupadores de tela. Os poupadores de tela começam quando o mouse e o teclado estão ociosos por um período de tempo especificado. Eles são usados por estes dois motivos:

  • Para proteger uma tela contra a queima de fósforo causada por imagens estáticas.
  • Para ocultar informações confidenciais deixadas em uma tela.

Este tópico é dividido nas seções a seguir.

Sobre os Poupadores de Tela

O aplicativo Área de Trabalho no Windows Painel de Controle permite que os usuários selecionem em uma lista de protetores de tela, especifique quanto tempo deve decorrer antes do início da proteção de tela, configurar os poupadores de tela e visualizar os poupadores de tela. Os poupadores de tela são carregados automaticamente quando o Windows é iniciado ou quando um usuário ativa a proteção de tela por meio do Painel de Controle.

Depois que um protetor de tela é escolhido, o Windows monitora pressionamentos de teclas e movimentos do mouse e, em seguida, inicia a proteção de tela após um período de inatividade. No entanto, o Windows não iniciará a proteção de tela se alguma das seguintes condições existir:

  • O aplicativo ativo não é um aplicativo baseado no Windows.
  • Uma janela cbt (treinamento baseado em computador) está presente.
  • O aplicativo ativo recebe a mensagem WM_SYSCOMMAND com o parâmetro wParam definido como o valor SC_SCREENSAVE, mas não passa a mensagem para a função DefWindowProc .

Contexto de segurança do protetor de tela

O contexto de segurança do protetor de tela depende se um usuário está conectado interativamente. Se um usuário estiver conectado interativamente quando o protetor de tela for invocado, o protetor de tela será executado no contexto de segurança do usuário interativo. Se nenhum usuário estiver conectado, o contexto de segurança do protetor de tela dependerá da versão do Windows que está sendo usada.

  • Windows XP e Windows 2000 – a proteção de tela é executada no contexto do LocalSystem com contas restritas.
  • Windows 2003 – a proteção de tela é executada no contexto de LocalService com todos os privilégios removidos e o grupo de administradores desabilitado.
  • Não se aplica ao Windows NT4.

O contexto de segurança determina o nível de operações privilegiadas que podem ser feitas a partir de um protetor de tela.

Windows Vista e posterior: Se a proteção por senha estiver habilitada pela política, a proteção de tela será iniciada independentemente do que um aplicativo faz com a notificação de SC_SCREENSAVE.

Os poupadores de tela contêm funções exportadas específicas, definições de recursos e declarações de variável. A biblioteca de proteção de tela contém a função main e outros códigos de inicialização necessários para um protetor de tela. Quando um protetor de tela é iniciado, o código de inicialização na biblioteca de proteção de tela cria uma janela de tela inteira. A classe de janela para essa janela é declarada da seguinte maneira:

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;

Para criar um protetor de tela, a maioria dos desenvolvedores cria um módulo de código-fonte que contém três funções necessárias e as vincula à biblioteca de proteção de tela. Um módulo de proteção de tela é responsável apenas por configurar a si mesmo e por fornecer efeitos visuais.

Uma das três funções necessárias em um módulo de proteção de tela é ScreenSaverProc. Essa função processa mensagens específicas e passa todas as mensagens não processadas de volta para a biblioteca de proteção de tela. A seguir estão algumas das mensagens típicas processadas pelo ScreenSaverProc.

Mensagem Significado
WM_CREATE Recupere os dados de inicialização do arquivo Regedit.ini. Defina um temporizador de janela para a janela de proteção de tela. Execute qualquer outra inicialização necessária.
WM_ERASEBKGND Apago a janela de proteção de tela e prepare-se para operações de desenho subsequentes.
WM_TIMER Executar operações de desenho.
WM_DESTROY Destrua os temporizadores criados quando o aplicativo processou a mensagem WM_CREATE . Execute qualquer limpeza adicional necessária.

 

ScreenSaverProc passa mensagens não processadas para a biblioteca de proteção de tela chamando a função DefScreenSaverProc . A tabela a seguir descreve como essa função processa várias mensagens.

Mensagem Ação
WM_SETCURSOR Defina o cursor como o cursor nulo, removendo-o da tela.
WM_PAINT Pinte a tela de fundo.
WM_LBUTTONDOWN Encerre a proteção de tela.
WM_MBUTTONDOWN Encerre a proteção de tela.
WM_RBUTTONDOWN Encerre a proteção de tela.
WM_KEYDOWN Encerre a proteção de tela.
WM_MOUSEMOVE Encerre a proteção de tela.
WM_ACTIVATE Encerre a proteção de tela se o parâmetro wParam estiver definido como FALSE.

 

A segunda função necessária em um módulo de proteção de tela é ScreenSaverConfigureDialog. Essa função exibe uma caixa de diálogo que permite que o usuário configure o protetor de tela (um aplicativo deve fornecer um modelo de caixa de diálogo correspondente). O Windows exibe a caixa de diálogo de configuração quando o usuário seleciona o botão Configurar na caixa de diálogo Proteção de Tela do Painel de Controle.

A terceira função necessária em um módulo de proteção de tela é RegisterDialogClasses. Essa função deve ser chamada por todos os aplicativos de proteção de tela. No entanto, aplicativos que não exigem janelas especiais ou controles personalizados na caixa de diálogo de configuração podem simplesmente retornar TRUE. Os aplicativos que exigem janelas especiais ou controles personalizados devem usar essa função para registrar as classes de janela correspondentes.

Além de criar um módulo que dá suporte às três funções descritas, um protetor de tela deve fornecer um ícone. Esse ícone só fica visível quando o protetor de tela é executado como um aplicativo autônomo. (Para ser executado pelo Painel de Controle, um protetor de tela deve ter a extensão de nome de arquivo .scr; para ser executado como um aplicativo autônomo, ele deve ter a extensão de nome de arquivo .exe.) O ícone deve ser identificado no arquivo de recurso do protetor de tela pela constante ID_APP, que é definida no arquivo de cabeçalho Scrnsave.h.

Um requisito final é uma cadeia de caracteres de descrição do protetor de tela. O arquivo de recurso para um protetor de tela deve conter uma cadeia de caracteres que o Painel de Controle exibe como o nome do protetor de tela. A cadeia de caracteres de descrição deve ser a primeira cadeia de caracteres na tabela de cadeia de caracteres do arquivo de recurso (identificada com o valor ordinal 1). No entanto, a cadeia de caracteres de descrição será ignorada pelo Painel de Controle se o protetor de tela tiver um nome de arquivo longo. Nesse caso, o nome do arquivo será usado como a cadeia de caracteres de descrição.

Usando as funções de proteção de tela

Esta seção usa o código de exemplo obtido de um aplicativo de proteção de tela para ilustrar as seguintes tarefas:

Criando um protetor de tela

Em intervalos que variam de 1 a 10 segundos, o aplicativo neste exemplo repinta a tela com uma das quatro cores: branco, cinza claro, cinza escuro e preto. O aplicativo pinta a tela sempre que recebe uma mensagem WM_TIMER . O usuário pode ajustar o intervalo no qual essa mensagem é enviada selecionando a caixa de diálogo de configuração do aplicativo e ajustando uma única barra de rolagem horizontal.

Biblioteca de proteção de tela

As funções de proteção de tela estática estão contidas na biblioteca de proteção de tela. Há duas versões da biblioteca disponíveis, Scrnsave.lib e Scrnsavw.lib. Você deve vincular seu projeto a um destes. Scrnsave.lib é usado para poupadores de tela que usam caracteres ANSI, e Scrnsavw.lib é usado para poupadores de tela que usam caracteres Unicode. Um protetor de tela vinculado ao Scrnsavw.lib só será executado em plataformas Windows compatíveis com Unicode, enquanto um protetor de tela vinculado ao Scrnsave.lib será executado em qualquer plataforma Windows.

Suporte à caixa de diálogo de configuração

A maioria dos poupadores de tela fornece uma caixa de diálogo de configuração para permitir que o usuário especifique dados de personalização, como cores exclusivas, velocidades de desenho, espessura da linha, fontes e assim por diante. Para dar suporte à caixa de diálogo de configuração, o aplicativo deve fornecer um modelo de caixa de diálogo e também deve dar suporte à função ScreenSaverConfigureDialog . Veja a seguir o modelo de caixa de diálogo para o aplicativo de exemplo.

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

Você deve definir a constante usada para identificar o modelo da caixa de diálogo usando o valor decimal 2003, como no exemplo a seguir:

#define  DLG_SCRNSAVECONFIGURE 2003

O exemplo a seguir mostra a função ScreenSaverConfigureDialog encontrada no aplicativo de exemplo.

#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; 
}

Além de fornecer o modelo da caixa de diálogo e dar suporte à função ScreenSaverConfigureDialog , um aplicativo também deve dar suporte à função RegisterDialogClasses . Essa função registra todas as classes de janela não padrão exigidas pelo protetor de tela. Como o aplicativo de exemplo usou apenas classes de janela padrão em seu procedimento de caixa de diálogo, essa função simplesmente retorna TRUE, como no exemplo a seguir:

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

Suporte ao procedimento de janela de proteção de tela

Cada protetor de tela deve dar suporte a um procedimento de janela chamado ScreenSaverProc. Como a maioria dos procedimentos de janela, o ScreenSaverProc processa um conjunto de mensagens específicas e passa todas as mensagens não processadas para um procedimento padrão. No entanto, em vez de passá-las para a função DefWindowProc , ScreenSaverProc passa mensagens não processadas para a função DefScreenSaverProc . Outra diferença entre ScreenSaverProc e um procedimento de janela normal é que o identificador passado para ScreenSaverProc identifica toda a área de trabalho em vez de uma janela do cliente. O exemplo a seguir mostra o procedimento de janela ScreenSaverProc para a proteção de tela de exemplo.

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); 
}

Criando um arquivo de definição de módulo

As funções ScreenSaverProc e ScreenSaverConfigureDialog devem ser exportadas no arquivo de definição de módulo do aplicativo; No entanto, RegisterDialogClasses não deve ser exportado. O exemplo a seguir mostra o arquivo de definição de módulo para o aplicativo de exemplo.

NAME    SSTEST.SCR 

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

Instalando novos poupadores de tela

Ao compilar a lista de poupadores de tela disponíveis, o Painel de Controle pesquisa no diretório de Inicialização do Windows arquivos com a extensão .scr. Como os poupadores de tela são arquivos executáveis padrão do Windows com extensões .exe, você deve renomeá-los para que eles tenham extensões .scr e copiá-los para o diretório correto.

Adicionando ajuda à caixa de diálogo Configuração do Protetor de Tela

A caixa de diálogo de configuração de um protetor de tela normalmente inclui um botão Ajuda . Os aplicativos de proteção de tela podem marcar para o identificador do botão Ajuda e chamar a função WinHelp da mesma forma que a Ajuda é fornecida em outros aplicativos baseados no Windows.