/* // スクリーンセーバー・サンプル */ #include #include #include "resource.h" /* スクリーンセーバー用ライブラリの指定 */ #pragma comment(lib,"scrnsave.lib") /*--------------------------------------------------------------------------*/ /*-----------------------------------*/ typedef struct Gr { int w, h; // 画面サイズ int x0,y0; // 表示開始位置. (0,0)のはずだが念のため BYTE *pix; // 描画バッファの表示基準の先頭アドレス BYTE *pix_mem; // 描画バッファのmallocしたときのアドレス int lPitch; // 描画バッファの次の行までのバイト数 HWND hwnd; // カレントウィンドウ BITMAPINFO bmpInfo; // 仮想フレームバッファ表示に使う } Gr; static Gr gr_body; Gr *gr = &gr_body; int gr_init(HWND hwnd); void gr_term(void); void gr_update(void); void gr_pset(int x, int y, int c); void gr_cls(void); /*--------------------------------------------------------------------------*/ /* スクリーンセーバー処理 */ static void main_loop(void); BOOL WINAPI RegisterDialogClasses(HANDLE hInst) { return TRUE; } BOOL WINAPI ScreenSaverConfigureDialog(HWND hWnd,UINT uMsg,WPARAM wParam,LPARAM lParam) { /* 素で起動したときの処理 */ /* EndDialog()の第二引数の値がアプリケーションの終了値になる! */ switch(uMsg) { case WM_INITDIALOG: return TRUE; case WM_CLOSE: EndDialog(hWnd, 0); break; case WM_COMMAND: switch(LOWORD(wParam)) { case IDOK: EndDialog(hWnd,0/*IDOK*/); break; } break; default: break; } return FALSE; } LONG WINAPI ScreenSaverProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { // スクリーンセーバー処理実体 switch(uMsg) { case WM_CREATE: // 初期化 if (gr_init(hWnd) == 0) { return 1; } SetTimer(hWnd,1, 17, NULL); /* タイマー割り込み設定. 1000/60=17ms */ break; case WM_DESTROY: // 終了 KillTimer(hWnd,1); /* タイマー割り込み終了 */ gr_term(); break; case WM_TIMER: // 約 1/60秒ごとの処理 main_loop(); break; default: return DefScreenSaverProc(hWnd,uMsg,wParam,lParam); } return 0; } /*--------------------------------------------------------------------------*/ static void main_loop(void) { // 毎フレームの処理. // とりあえず、乱数で、適当に点を打っていく int i, x,y, r,g,b; gr_cls(); for (i = 0; i < 8*1024; i++) { x = rand() % gr->w; y = rand() % gr->h; r = rand() & 0xff; g = rand() & 0xff; b = rand() & 0xff; gr_pset(x, y, ((r<<16)|(g<<8)|b)); } gr_update(); } /*--------------------------------------------------------------------------*/ int gr_init(HWND hwnd) { // グラフィック処理の初期化 RECT r; gr->hwnd = hwnd; // 表示範囲を取得(フル画面サイズのはず...) GetClientRect(hwnd,&r); gr->x0 = r.left; gr->y0 = r.top; gr->w = r.right - gr->x0; gr->h = r.bottom - gr->y0; if (gr->w == 0 || gr->h == 0) return 0; // 描画バッファの設定. 32ビットカラー。 gr->pix_mem = (BYTE*)calloc(1, gr->w * gr->h * 4); if (gr->pix_mem == NULL) return 0; gr->pix = gr->pix_mem + (gr->h - 1) * gr->w * 4; gr->lPitch = -gr->w * 4; // 描画バッファを表示するときに使う memset(&gr->bmpInfo, 0, sizeof(gr->bmpInfo)); gr->bmpInfo.bmiHeader.biSize = 0x28/*sizeof(gr->bmpInfo)*/; gr->bmpInfo.bmiHeader.biWidth = gr->w; gr->bmpInfo.bmiHeader.biHeight = gr->h; gr->bmpInfo.bmiHeader.biPlanes = 1; gr->bmpInfo.bmiHeader.biBitCount = 32; gr->bmpInfo.bmiHeader.biCompression = BI_RGB; gr->bmpInfo.bmiHeader.biSizeImage = 0; gr->bmpInfo.bmiHeader.biXPelsPerMeter = 0; gr->bmpInfo.bmiHeader.biYPelsPerMeter = 0; gr->bmpInfo.bmiHeader.biClrUsed = 0; gr->bmpInfo.bmiHeader.biClrImportant = 0; return 1; } void gr_term(void) { // グラフィック処理の終了 if (gr->pix_mem) free(gr->pix_mem); memset(gr, 0, sizeof(*gr)); } void gr_update(void) { // 画面の更新 HDC hdc = GetDC(gr->hwnd); SetDIBitsToDevice(hdc, gr->x0, gr->y0, gr->w, gr->h, 0, 0, 0, gr->h, gr->pix_mem, &gr->bmpInfo, DIB_RGB_COLORS); ReleaseDC(gr->hwnd,hdc); } void gr_cls(void) { // 描画バッファクリア DWORD *p = (DWORD *)gr->pix_mem; int l = gr->w * gr->h; do { *p++ = 0; } while (--l); } void gr_pset(int x, int y, int c) { // (x,y) にピクセル cを表示. BYTE *p; if ((unsigned)x >= (unsigned)gr->w || (unsigned)y >= (unsigned)gr->h) // ※(unsigned)することで負の座標も範囲外にしている return; p = gr->pix + y * gr->lPitch + x * 4; //1ピクセル4バイトで、(x,y)座標のアドレスを設定 *(DWORD*)p = c; }