ScrBasico é um exemplo de screen saver feito utilizando diretamente a API do Windows. Não é um screen saver muito sofisticado: simplesmente mostra um texto no meio da tela, com a cor variando continuamente entre branco e preto.
O programa principal é simples:
- int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrecInst,
- LPSTR lpCmdLine, int nShowCmd)
- {
- hInst = hInstance;
- AnalisaCmd (lpCmdLine);
- switch (modo)
- {
- case smConfig:
- DialogBox (hInst, MAKEINTRESOURCE (IDD_CONFIG), hMainWnd,
- ConfigDlgProc);
- break;
- case smPassword:
- ChangePassword ();
- break;
- case smPreview:
- case smSaver:
- DoScreenSaver ();
- break;
- }
- return 0;
- }
- static void AnalisaCmd (char *szCmd)
- {
- // valores default
- hMainWnd = NULL;
- modo = smConfig;
- // por seguranca
- if (szCmd == NULL)
- return;
- // pula delimitadores inicias
- while ((*szCmd == ' ') || (*szCmd == 0x09))
- szCmd++;
- // testa comando vazio
- if (*szCmd == 0)
- return;
- // testa e trata flags
- if ((*szCmd == '-') || (*szCmd == '/'))
- {
- szCmd++;
- switch (*szCmd)
- {
- // config
- case 'c':
- case 'C':
- modo = smConfig;
- hMainWnd = PegaHandle (szCmd+1);
- return;
- // screen saver
- case 's':
- case 'S':
- modo = smSaver;
- return;
- // preview
- case 'p':
- case 'P':
- case 'l':
- case 'L':
- modo = smPreview;
- hMainWnd = PegaHandle (szCmd+1);
- return;
- // alteração de senha
- case 'a':
- case 'A':
- modo = smPassword;
- hMainWnd = PegaHandle (szCmd+1);
- return;
- }
- }
- // algo inesperado
- modo = smNone;
- }
A rotina de alteração de senha (usada somente pelos arqueólogos brincando com Windows 9x) apela para uma rotina não documentada do Windows, linkada dinamicamente da MPR.DLL:
- static void ChangePassword()
- {
- HINSTANCE hmpr;
- hmpr = LoadLibrary("MPR.DLL");
- if (hmpr != NULL)
- {
- PWDCHANGEPASSWORD PwdChangePassword = (PWDCHANGEPASSWORD)
- GetProcAddress (hmpr,"PwdChangePasswordA");
- if (PwdChangePassword != NULL)
- PwdChangePassword("SCRSAVE", hMainWnd, 0, 0);
- FreeLibrary(hmpr);
- }
- }
- static void DoScreenSaver ()
- {
- WNDCLASS wc;
- int cx, cy;
- UINT oldval;
- MSG msg;
- // Registra a nossa classe de janela
- wc.style = CS_HREDRAW | CS_VREDRAW;
- wc.lpfnWndProc = ScreenSaverProc;
- wc.cbClsExtra = 0;
- wc.cbWndExtra = 0;
- wc.hInstance = hInst;
- wc.hIcon = NULL;
- wc.hCursor = NULL;
- wc.hbrBackground = (HBRUSH) GetStockObject(BLACK_BRUSH);
- wc.lpszMenuName = NULL;
- wc.lpszClassName = szWndClass;
- RegisterClass (&wc);
- // Cria a janela
- if (modo == smPreview)
- {
- RECT rc;
- GetWindowRect (hMainWnd, &rc);
- cx = rc.right - rc.left;
- cy = rc.bottom - rc.top;
- hSSWnd = CreateWindowEx (0, szWndClass, "Preview", WS_CHILD | WS_VISIBLE,
- 0, 0, cx, cy, hMainWnd, NULL, hInst, NULL);
- }
- else
- {
- cx = GetSystemMetrics (SM_CXSCREEN);
- cy = GetSystemMetrics (SM_CYSCREEN);
- hSSWnd = CreateWindowEx (WS_EX_TOPMOST, szWndClass, "ScreenSaver",
- WS_POPUP | WS_VISIBLE,
- 0, 0, cx, cy, NULL, NULL, hInst, NULL);
- }
- if (hSSWnd == NULL)
- return;
- // avisa screen saver rodando (desativa Ctrl Alt Del)
- if (modo == smSaver)
- SystemParametersInfo(SPI_SCREENSAVERRUNNING,1,&oldval,0);
- // Loop de tratamento de mensagens
- while (GetMessage(&msg,NULL,0,0))
- {
- TranslateMessage(&msg);
- DispatchMessage(&msg);
- }
- // avisa fim do screen saver (reativa Ctrl Alt Del)
- if (modo == smSaver)
- SystemParametersInfo(SPI_SCREENSAVERRUNNING,0,&oldval,0);
- }
- LRESULT WINAPI ScreenSaverProc (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
- {
- static POINT InitCursorPos; // posicao inicial do mouse
- static UINT uTimer; // identificador do timer
- static int iCor; // cor da mensagem
- static int iDelta; // variacao da cor
- static BOOL bFecha = FALSE; // TRUE se geramos WM_CLOSE
- static DWORD dwInicio; // inicio da execucao do screen saver
- switch (uMsg)
- {
- case WM_CREATE: // janela foi criada
- LeCfg (szMsg, sizeof (szMsg));
- GetCursorPos (&InitCursorPos); // salva posicao do mouse
- uTimer = SetTimer(hWnd, 1, 150, NULL); // liga o timer
- dwInicio = GetTickCount (); // guarda horario inicial
- iCor = 0;
- iDelta = 4;
- break;
- case WM_TIMER: // mensagem periodica
- Desenha (hWnd, szMsg, iCor);
- iCor += iDelta;
- if (iCor < icor =" 0;"> 255)
- iCor = 255;
- if ((iCor == 0) || (iCor == 255))
- iDelta = -iDelta;
- break;
- case WM_ACTIVATE: case WM_ACTIVATEAPP: case WM_NCACTIVATE:
- if ((modo == smSaver) && !bDialogo && (LOWORD(wParam) == WA_INACTIVE))
- {
- // Desativar screen saver
- bFecha = TRUE;
- PostMessage (hWnd, WM_CLOSE, 0, 0);
- }
- break;
- case WM_SETCURSOR:
- if ((modo == smSaver) && !bDialogo)
- SetCursor (NULL); // apaga o cursor do mouse
- else
- SetCursor (LoadCursor (NULL,IDC_ARROW));
- break;
- case WM_LBUTTONDOWN: case WM_MBUTTONDOWN: case WM_RBUTTONDOWN: case WM_KEYDOWN:
- if ((modo == smSaver) && !bDialogo)
- {
- // apertou botao ou tecla, fechar screen saver
- bFecha = TRUE;
- PostMessage (hWnd, WM_CLOSE, 0, 0);
- }
- break;
- case WM_MOUSEMOVE:
- if ((modo == smSaver) && !bDialogo)
- {
- POINT pt;
- int dx, dy;
- // Verifica se moveu o suficente para desativar
- GetCursorPos(&pt);
- dx = pt.x - InitCursorPos.x;
- if (dx < dx =" -dx;" dy =" pt.y" dy =" -dy;"> MouseThreshold) || (dy > MouseThreshold))
- {
- bFecha = TRUE;
- PostMessage (hWnd, WM_CLOSE, 0, 0);
- }
- }
- break;
- case WM_SYSCOMMAND:
- if (modo == smSaver)
- {
- // Ignora ativacao de screen saver e close
- if ((wParam == SC_SCREENSAVE) || (wParam == SC_CLOSE))
- return FALSE;
- }
- break;
- case WM_CLOSE:
- if ((modo == smSaver) && !bDialogo && bFecha)
- {
- BOOL bOk = TRUE;
- // Estamos tentando fechar
- if (GetTickCount() > 5000) // Pode interromper sem senha se for rapido
- {
- bOk = VerifyPassword (hWnd);
- GetCursorPos (&InitCursorPos); // salva posicao do mouse
- }
- if (bOk)
- DestroyWindow (hWnd); // encerra screen saver
- }
- bFecha = FALSE;
- if (modo == smSaver)
- return FALSE; // ignora WM_CLOSE
- break;
- case WM_DESTROY:
- if (uTimer)
- KillTimer(hWnd, uTimer);
- PostQuitMessage(0);
- break;
- }
- return DefWindowProc (hWnd, uMsg, wParam, lParam);
- }
Um último ponto de interesse é a rotina VerifyPassword:
- static BOOL VerifyPassword (HWND hwnd)
- {
- OSVERSIONINFO osv;
- HINSTANCE hpwdcpl;
- VERIFYSCREENSAVEPWD VerifyScreenSavePwd;
- BOOL bResult;
- // No NT e derivados, o screen saver deve terminar, o sistema solicita a senha
- // e re-executa o screen saver se senha incorreta
- osv.dwOSVersionInfoSize = sizeof(osv);
- GetVersionEx (&osv);
- if (osv.dwPlatformId == VER_PLATFORM_WIN32_NT)
- return TRUE;
- // No 95/98/Me, usa funcao nao documentada
- hpwdcpl = LoadLibrary ("PASSWORD.CPL");
- if (hpwdcpl == NULL)
- return TRUE;
- VerifyScreenSavePwd = (VERIFYSCREENSAVEPWD)
- GetProcAddress (hpwdcpl,"VerifyScreenSavePwd");
- if (VerifyScreenSavePwd == NULL)
- {
- FreeLibrary(hpwdcpl);
- return TRUE;
- }
- bDialogo = TRUE;
- SendMessage (hwnd, WM_SETCURSOR, 0, 0); // mostra cursor
- bResult = VerifyScreenSavePwd (hwnd);
- bDialogo = FALSE;
- SendMessage (hwnd, WM_SETCURSOR, 0, 0); // esconde cursor
- FreeLibrary (hpwdcpl);
- return bResult;
- }
O mesmo screen saver, feito com a Screen Saver Library está em LibScrSaver. Neste caso a biblioteca cuida de quase tudo, o que interessa é somente a rotina ScreenSaverProc:
- LRESULT WINAPI ScreenSaverProc (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
- {
- static UINT uTimer;
- static int iCor;
- static int iDelta;
- // Trata mensagens
- switch (uMsg)
- {
- // Iniciacao: le config e cria timer
- case WM_CREATE:
- LeCfg (szMsg, sizeof (szMsg));
- uTimer = SetTimer(hWnd, 1, 150, NULL);
- iCor = 0;
- iDelta = 4;
- break;
- // Chamada periodica, faz a animacao
- case WM_TIMER:
- Desenha (hWnd, szMsg, iCor);
- iCor += iDelta;
- if (iCor < icor =" 0;"> 255)
- iCor = 255;
- if ((iCor == 0) || (iCor == 255))
- iDelta = -iDelta;
- break;
- // Termino: destroi o timer
- case WM_DESTROY:
- if (uTimer)
- KillTimer(hWnd, uTimer);
- break;
- }
- // Executa tratamento default
- return DefScreenSaverProc(hWnd, uMsg, wParam, lParam);
- }
Nenhum comentário:
Postar um comentário