: : ok i have posted this message because i am tired of searching the web for resources that will teach me how to program a screen saver in windows. I know that a screen saver is just a .exe renamed .scr but how do i get it to diplay the properties dialog when required, the preview screen when required? When i rename a .exe and select the program in the screensaver drop down list it starts it up rather than just providing a preview. Does anybody know how to make a .exe behave just like a screensaver???
: :
: Actually I thought there were some differences. I myself would like to do some screen-saver coding in GL, but have yet to find all the documentation needed to do so.
:
: -
Sephiroth
:
:
I'd been wondering about screensaver coding a while back also, Here is a (verry basic) WinAPI only skeleton of a screensaver I'd been playing with then:
//Ball ScreenSaver.cpp
#include <windows.h>
#include <scrnsave.h>
LRESULT WINAPI ScreenSaverChildProc(HWND hWnd,UINT message, WPARAM wParam, LPARAM lParam);
LRESULT WINAPI ScreenSaverProc(HWND hWnd,UINT message, WPARAM wParam, LPARAM lParam)
{
static HWND hChild = NULL;
HINSTANCE hInst = hMainInstance;
int nMaxX = 0;
int nMaxY = 0;
int nWndSize = 0;
switch(message) {
case WM_CREATE:
WNDCLASS wc;
wc.style = CS_VREDRAW | CS_HREDRAW | CS_OWNDC ;
wc.lpfnWndProc = (WNDPROC) ScreenSaverChildProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hInst;
wc.hIcon = NULL;
wc.hCursor = NULL;
wc.hbrBackground = NULL;
wc.lpszMenuName = NULL;
wc.lpszClassName = "NTDEVCLASS";
RegisterClass(&wc);
if(nMaxX == 0) { //Get the desktop size
RECT rect;
GetClientRect(hWnd,&rect);
HDC hdc;
hdc = GetDC(hWnd);
nMaxX = rect.right;
nMaxY = rect.bottom;
nWndSize = (int) ((float)nMaxY* .35f);
::ReleaseDC(hWnd,hdc);
}
hChild = CreateWindow(wc.lpszClassName, "Child1", WS_CHILD | WS_VISIBLE,
0, 0, nWndSize, nWndSize, hWnd, NULL, hInst, NULL);
break;
case WM_DESTROY:
KillTimer(hWnd, 1);
DestroyWindow(hChild);
PostQuitMessage(0);
break;
case WM_TIMER:
break;
default: return DefScreenSaverProc(hWnd, message, wParam, lParam);
}
return 0;
}
BOOL WINAPI ScreenSaverConfigureDialog(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) {
return false;
}
BOOL WINAPI RegisterDialogClasses(HANDLE hInst) {
return true;
}
///////////////////////////////////////////////////////////////////////
//SSchild.cpp
#include <windows.h>
#include <scrnsave.h>
#include "resource.h"
HBITMAP hbmBall, hbmMask, hbmBuffer;
HDC hdcBuffer;
BITMAP bm;
int ballX, ballY;
int deltaX, deltaY;
int deltaValue = 14;
int ANIM_WIDTH, ANIM_HEIGHT;
void EraseBall(HDC hdc){
RECT rc;
rc.left = ballX;
rc.top = ballY;
rc.right = ballX + bm.bmWidth;
rc.bottom = ballY + bm.bmHeight;
FillRect(hdc, &rc, (HBRUSH)GetStockObject(BLACK_BRUSH));
}
void DrawBall(HDC hdc){
HDC hdcMemory;
hdcMemory = CreateCompatibleDC(hdc);
SelectObject(hdcMemory, hbmMask);
BitBlt(hdc, ballX, ballY, bm.bmWidth, bm.bmHeight, hdcMemory, 0, 0, SRCAND);
SelectObject(hdcMemory, hbmBall);
BitBlt(hdc, ballX, ballY, bm.bmWidth, bm.bmHeight, hdcMemory, 0, 0, SRCPAINT);
DeleteDC(hdcMemory);
}
void UpdateBall(void){
ballX += deltaX;
ballY += deltaY;
if(ballX < 0){
ballX = 0;
deltaX = deltaValue;
}
else if(ballX + bm.bmWidth > ANIM_WIDTH){
ballX = ANIM_WIDTH - bm.bmWidth;
deltaX = -deltaValue;
}
if(ballY < 0){
ballY = 0;
deltaY = deltaValue;
}
else if(ballY + bm.bmHeight > ANIM_HEIGHT){
ballY = ANIM_HEIGHT - bm.bmHeight;
deltaY = -deltaValue;
}
}
LRESULT WINAPI ScreenSaverChildProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{ int retVal;
switch(message) {
case WM_CREATE:
RECT rcWindow, rcClient, rc;
hbmBall = LoadBitmap(hMainInstance, (LPCTSTR)MAKEINTRESOURCE(BALL));
hbmMask = LoadBitmap(hMainInstance, (LPCTSTR)MAKEINTRESOURCE(MASK));
if(!hbmBall || !hbmMask) {
MessageBox(hWnd, "Load of resources failed.", "Error", MB_OK | MB_ICONEXCLAMATION);
return -1;
}
ANIM_WIDTH = GetSystemMetrics(SM_CXSCREEN);
ANIM_HEIGHT = GetSystemMetrics(SM_CYSCREEN);
hdcBuffer = CreateCompatibleDC(0);
SelectObject(hdcBuffer, hbmBall);
hbmBuffer = CreateCompatibleBitmap(hdcBuffer, ANIM_WIDTH, ANIM_HEIGHT);
SelectObject(hdcBuffer, hbmBuffer);
if(!hbmBuffer){
MessageBox(hWnd, "Buffer creation failed.", "Error", MB_OK | MB_ICONEXCLAMATION);
return -1;
}
rc.left = rc.top = 0;
rc.right = ANIM_WIDTH;
rc.bottom = ANIM_HEIGHT;
FillRect(hdcBuffer, &rc, (HBRUSH)GetStockObject(BLACK_BRUSH));
GetObject(hbmBall, sizeof(bm), &bm);
SetTimer(hWnd, 1, 10, NULL);
ballX = ballY = 0;
deltaX = deltaY = deltaValue;
GetWindowRect(hWnd, &rcWindow);
GetClientRect(hWnd, &rcClient);
if(rcClient.right != ANIM_WIDTH || rcClient.bottom != ANIM_HEIGHT) {
MoveWindow(hWnd, rcWindow.left, rcWindow.top,
((rcWindow.right - rcWindow.left) - rcClient.right) + ANIM_WIDTH,
((rcWindow.bottom - rcWindow.top) - rcClient.bottom) + ANIM_HEIGHT, TRUE);
}
break;
case WM_TIMER:
if(hbmBall && hbmMask) {
HDC hdcWindow;
hdcWindow = GetDC(hWnd);
EraseBall(hdcBuffer);
UpdateBall();
DrawBall(hdcBuffer);
BitBlt(hdcWindow, 0, 0, ANIM_WIDTH, ANIM_HEIGHT, hdcBuffer, 0, 0, SRCCOPY);
ReleaseDC(hWnd, hdcWindow);
}
break;
case WM_PAINT:
if(hbmBall && hbmMask) {
PAINTSTRUCT ps;
HDC hdcWindow;
hdcWindow = BeginPaint(hWnd, &ps);
BitBlt(hdcWindow, 0, 0, ANIM_WIDTH, ANIM_HEIGHT, hdcBuffer, 0, 0, SRCCOPY);
EndPaint(hWnd, &ps);
}
break;
case WM_DESTROY:
KillTimer(hWnd, 1);
PostQuitMessage(0);
break;
case WM_KEYDOWN:
case WM_ACTIVATE:
case WM_MOUSEMOVE:
case WM_SETCURSOR:
case WM_SYSKEYDOWN:
case WM_SYSCOMMAND:
case WM_NCACTIVATE:
case WM_ACTIVATEAPP:
case WM_LBUTTONDOWN:
case WM_MBUTTONDOWN:
case WM_RBUTTONDOWN:
retVal = DefScreenSaverProc(hWnd, message, wParam, lParam);
DefScreenSaverProc(hMainWindow, message, wParam, lParam);
return retVal;
default: return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}
Hope that helps
Stoic Joker