/* mingwscr.c */ #include #include #include #include #include #include "resource.h" #define FPS 60 #define ID_TIMER 101 /* screensaver main processing */ LRESULT WINAPI ScreenSaverProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) { static HBITMAP hBitmap; static HBITMAP hBitmap_mask; static HBITMAP hBitmap_bg; static HBITMAP hBitmap_preview; static HBITMAP offScrnBitmap; static int wdw_w, wdw_h; static int imgw, imgh; static int bgw, bgh; static int pvw, pvh; static float x, y, dx, dy, bgx, bgy; int bx, by; switch (msg) { case WM_CREATE: /* initialize */ // get window size { RECT rc; GetClientRect(hWnd, &rc); wdw_w = rc.right - rc.left; wdw_h = rc.bottom - rc.top; } // create off-screen bitmap { HDC hdc; hdc = GetDC(hWnd); offScrnBitmap = CreateCompatibleBitmap(hdc, wdw_w, wdw_h); ReleaseDC(hWnd, hdc); } // load bitmaps hBitmap = LoadBitmap(((LPCREATESTRUCT)lParam)->hInstance, TEXT("IDI_BALL")); hBitmap_mask = LoadBitmap(((LPCREATESTRUCT)lParam)->hInstance, TEXT("IDI_BALL_MSK")); hBitmap_bg = LoadBitmap(((LPCREATESTRUCT)lParam)->hInstance, TEXT("IDI_BG")); hBitmap_preview = LoadBitmap(((LPCREATESTRUCT)lParam)->hInstance, TEXT("IDI_PREVIEW")); // get images size { BITMAP bp; // get ball image size GetObject(hBitmap, sizeof(BITMAP), &bp); imgw = bp.bmWidth; imgh = bp.bmHeight; // get bg image size GetObject(hBitmap_bg, sizeof(BITMAP), &bp); bgw = bp.bmWidth; bgh = bp.bmHeight; // get preview image size GetObject(hBitmap_preview, sizeof(BITMAP), &bp); pvw = bp.bmWidth; pvh = bp.bmHeight; } // init work x = wdw_w / 2; y = wdw_h / 2; dx = (float)wdw_w / (float)FPS; dy = dx * 0.5; bgx = 0; bgy = 0; // create timer SetTimer(hWnd, ID_TIMER, (int)(1000 / FPS), NULL); break; case WM_TIMER: /* main loop */ // update ball position x += dx; y += dy; if (x <= 0 || x + imgw >= wdw_w) dx *= -1; if (y <= 0 || y + imgh >= wdw_h) dy *= -1; // update bg position bgx -= 2; bgy -= 2; if (bgx <= -bgw) bgx += bgw; if (bgy <= -bgh) bgy += bgh; // draw bitmap if (wdw_w >= 160) { // draw fullscreen HDC hdc, hBmpDC, hMemDC; hdc = GetDC(hWnd); // set off-screen bitmap hMemDC = CreateCompatibleDC(hdc); SelectObject(hMemDC, offScrnBitmap); // draw bg to off-screen hBmpDC = CreateCompatibleDC(hdc); SelectObject(hBmpDC, hBitmap_bg); { int by = bgy; while (by <= wdw_h) { int bx = bgx; while (bx <= wdw_w) { BitBlt(hMemDC, bx, by, bgw, bgh, hBmpDC, 0, 0, SRCCOPY); bx += bgw; } by += bgh; } } DeleteDC(hBmpDC); // draw ball mask to off-screen hBmpDC = CreateCompatibleDC(hdc); SelectObject(hBmpDC, hBitmap_mask); BitBlt(hMemDC, (int)x, (int)y, imgw, imgh, hBmpDC, 0, 0, SRCAND); DeleteDC(hBmpDC); // draw ball source to off-screen hBmpDC = CreateCompatibleDC(hdc); SelectObject(hBmpDC, hBitmap); BitBlt(hMemDC, (int)x, (int)y, imgw, imgh, hBmpDC, 0, 0, SRCPAINT); DeleteDC(hBmpDC); // drawing to off-screen is finished // draw off-screen bitmap to window BitBlt(hdc, 0, 0, wdw_w, wdw_h, hMemDC, 0, 0, SRCCOPY); DeleteDC(hMemDC); // Create*() -> DeleteDC() ReleaseDC(hWnd, hdc); // GetDC() -> ReleaseDC() } else { // draw preview HDC hdc, hBmpDC; hdc = GetDC(hWnd); hBmpDC = CreateCompatibleDC(hdc); SelectObject(hBmpDC, hBitmap_preview); BitBlt(hdc, 0, 0, pvw, pvh, hBmpDC, 0, 0, SRCCOPY); DeleteDC(hBmpDC); // Create*() -> DeleteDC() ReleaseDC(hWnd, hdc); // GetDC() -> ReleaseDC() } break; case WM_DESTROY: KillTimer(hWnd, ID_TIMER); // kill timer // delete bitmap DeleteObject(offScrnBitmap); DeleteObject(hBitmap); DeleteObject(hBitmap_mask); DeleteObject(hBitmap_bg); DeleteObject(hBitmap_preview); PostQuitMessage(0); break; default: break; } return DefScreenSaverProc(hWnd, msg, wParam, lParam); } /* Processing of dialog boxes for configuration */ BOOL WINAPI ScreenSaverConfigureDialog(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam) { switch (msg) { case WM_COMMAND: switch (LOWORD(wParam)) { case IDOK: EndDialog(hDlg, 0); return TRUE; case IDCANCEL: EndDialog(hDlg, 1); return TRUE; } return FALSE; } return FALSE; } /* Register non-standard window classes required by dialog boxes for configuration */ BOOL WINAPI RegisterDialogClasses(HANDLE hInst) { return TRUE; }