/* // スクリーンセーバー・サンプル 4 */ #include #include #include #include #include "resource.h" /* スクリーンセーバー用ライブラリの指定 */ #pragma comment(lib,"scrnsave.lib") /*--------------------------------------------------------------------------*/ /* グラフィック関係 */ #define GR_RGB(r,g,b) (((unsigned char)(r)<<16)|((unsigned char)(g)<<8)|(unsigned char)(b)) typedef struct gr_inf_t { int w, h; // 描画画面サイズ int x0,y0; // 描画画面の表示画面での開始位置. int fs_w, fs_h; // 表示画面サイズ int mode; // 0=センター表示 1=画面サイズに合わせる(拡大) } gr_inf_t; extern gr_inf_t *gr_inf; // 画面情報 #define gr_width() (gr_inf->w) #define gr_height() (gr_inf->h) int gr_init(HWND hwnd, int w, int h, int md); void gr_term(void); void gr_update(void); void gr_cls(void); void gr_pset(int x, int y, int c); void gr_line(int x0, int y0, int x1, int y1, int c); void gr_boxLine(int x0, int y0, int w, int h, int c); void gr_boxFill(int x0, int y0, int w, int h, int c); /*---------------------------------------------------------------------------*/ /* デバッグ・ログ・ルーチン */ #if 1 //def NDEBUG #define DBGF(n) #else #include #include #define DBGF(n) (dbgf n) static void dbgf(char *fmt, ...) { FILE *fp; va_list app; fp = fopen("dbg.txt", "at"); if (fp) { va_start(app, fmt); vfprintf(fp, fmt, app); va_end(app); fclose(fp); } } #endif /*--------------------------------------------------------------------------*/ /* スクリーンセーバー処理 */ static void ss_main_init(HWND hwnd); static void ss_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) { // スクリーンセーバー処理実体 unsigned t; //DBGF(("msg %04x\n", uMsg)); switch(uMsg) { case WM_CREATE: // 初期化 // gr_init は wを-1にすると全画面, さらにhが -1 指定で全画面とりこみ if (gr_init(hWnd, -1/*SCRN_W*/, -1/*SCRN_H*/, 0) == 0) { return 1; } ss_main_init(hWnd); t = SetTimer(hWnd,1, 17, NULL); /* タイマー割り込み設定. 1000/60=17ms */ if(t == 0){ MessageBox(hWnd,"タイマの空きが無いので起動できません", "ScrnSvr4",MB_ICONEXCLAMATION | MB_OK); return FALSE; } break; case WM_DESTROY: // 終了 KillTimer(hWnd,1); /* タイマー割り込み終了 */ gr_term(); break; case WM_TIMER: // 約 1/60秒ごとの処理 ss_main_loop(); break; case WM_ERASEBKGND: #if 0 { // 画面を消す必要がある場合 RECT rc; GetClientRect(hWnd, &rc); FillRect((HDC)wParam, &rc, (HBRUSH)GetStockObject(BLACK_BRUSH)); } #endif break; default: return DefScreenSaverProc(hWnd,uMsg,wParam,lParam); } return 0; } /*--------------------------------------------------------------------------*/ typedef struct ss_main_t { unsigned tmr; HWND hwnd; HINSTANCE hinst; } ss_main_t; static ss_main_t ss_main; static void ss_main_init(HWND hwnd) { ss_main.hwnd = hwnd; ss_main.hinst = (HINSTANCE)GetWindowLong(ss_main.hwnd, GWL_HINSTANCE); } static void ss_main_loop(void) { // 毎フレームの処理. // 乱数で、適当に点や線、箱をかく int i,x,y,r,g,b,n,d, tmr; tmr = ++ss_main.tmr; if (tmr > 3 * 60 * 60) { gr_cls(); // 3分以上たったら、すべてクリア } else if (tmr < 5*60) { // 最初は、明るい点を打って、画面を白っぽくする d = 0xc0; n = 0x100; } else { // 5秒たったら、暗い点を打つように設定 d = 0; n = 0x100 - (tmr-5*60)*3; if (n < 0) n = 0; } for (i = 0; i < 16*1024; i++) { // 適当な座標に適当な色で点をうつ x = rand() % gr_width(); y = rand() % gr_height(); r = rand() & 0xff; g = rand() & 0xff; b = rand() & 0xff; // 適当に明るくする r |= d; g |= d; b |= d; // 徐々に暗くするための計算 r = r * n >> 8; g = g * n >> 8; b = b * n >> 8; // 点を打つ gr_pset(x, y, ((r<<16)|(g<<8)|b)); } // 画面更新 gr_update(); } /*--------------------------------------------------------------------------*/ /* スクリーンセーバー用 自力画面描画ルーチン */ /* by tenk */ /*--------------------------------------------------------------------------*/ #ifndef __cplusplus #define inline __inline #endif #define GR_BPP 32 // 16 or 32 bit色のみ. //#define GR_BPP 16 // 16 or 32 bit色のみ. /*--------------------------------------------------------------------------*/ #if GR_BPP == 32 // // 描画バッファを32bit色にするとき typedef unsigned gr_pix_t; #define GR_RGB2PIX(c) (c) #else // 描画バッファを16bit色にするとき typedef unsigned short gr_pix_t; #define GR_RGB2PIX(c) (((((c)>>16)&0xF8)<<7)|((((c)>>8)&0xF8)<<2)|(((c)>>3)&0x1f)) #endif typedef struct gr_t { // グラフィック関係の変数。 BYTE *pix; // 描画バッファの表示基準の先頭アドレス int lPitch; // 描画バッファの次の行までのバイト数 BYTE *pix_mem; // 描画バッファのmallocしたときのアドレス HWND hwnd; // カレントウィンドウ BITMAPINFO bmpInfo; // 仮想フレームバッファ表示に使う HBITMAP hBitmap; } gr_t; static gr_t gr_inst; static gr_t *gr = &gr_inst; static gr_inf_t gr_inf_inst; extern gr_inf_t *gr_inf = &gr_inf_inst; /*--------------------------------------------------------------------------*/ int gr_init(HWND hwnd, int w, int h, int md) { // グラフィック処理の初期化 RECT r; int gt=0; gr->hwnd = hwnd; gr_inf->mode = md; gr_inf->w = w; gr_inf->h = h; // 表示範囲を取得(フル画面サイズのはず...) GetClientRect(hwnd,&r); gr_inf->fs_w = r.right - r.left; gr_inf->fs_h = r.bottom - r.top; if (gr_inf->fs_w == 0 || gr_inf->fs_h == 0) return 0; if (gr_inf->w < 0 || gr_inf->h < 0) { if (gr_inf->h < 0) gt = 1; gr_inf->w = gr_inf->fs_w; gr_inf->h = gr_inf->fs_h; } gr_inf->x0 = (gr_inf->fs_w - gr_inf->w) >> 1; gr_inf->y0 = (gr_inf->fs_h - gr_inf->h) >> 1; // 描画バッファの設定. 16 or 32ビットカラー。 gr->lPitch = -gr_inf->w * sizeof(gr_pix_t); // 描画バッファを表示するときに使う memset(&gr->bmpInfo, 0, sizeof(gr->bmpInfo)); gr->bmpInfo.bmiHeader.biSize = 0x28/*sizeof(gr->bmpInfo)*/; gr->bmpInfo.bmiHeader.biWidth = gr_inf->w; gr->bmpInfo.bmiHeader.biHeight = gr_inf->h; gr->bmpInfo.bmiHeader.biPlanes = 1; gr->bmpInfo.bmiHeader.biBitCount = 8*sizeof(gr_pix_t); // 16 or 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; // { //BITMAPINFOHEADER bi; BITMAPINFOHEADER *lpbi; HDC hdc; HANDLE hdib; hdib = GlobalAlloc(GHND, sizeof(BITMAPINFOHEADER) ); lpbi = (BITMAPINFOHEADER*)GlobalLock(hdib); *lpbi = gr->bmpInfo.bmiHeader; hdc = GetDC(hwnd); gr->hBitmap = CreateDIBSection(hdc, (LPBITMAPINFO)lpbi, DIB_RGB_COLORS, &gr->pix_mem, NULL, 0); ReleaseDC(hwnd, hdc); GlobalUnlock(hdib); GlobalFree(hdib); } gr->pix = gr->pix_mem + (gr_inf->h - 1) * gr_inf->w * sizeof(gr_pix_t); if (gt) { // デスクトップ画面を読みこむ HDC dstHdc; HDC srcHdc; srcHdc = GetDC(hwnd); dstHdc = CreateCompatibleDC(srcHdc); SelectObject(dstHdc, gr->hBitmap); BitBlt(dstHdc, 0,0, gr_inf->w, gr_inf->h, srcHdc, 0,0, SRCCOPY); DeleteDC(dstHdc); DeleteDC(srcHdc); } return 1; } void gr_term(void) { // グラフィック処理の終了 if (gr->hBitmap) DeleteObject(gr->hBitmap); memset(gr, 0, sizeof(*gr)); memset(gr_inf, 0, sizeof(*gr_inf)); } void gr_update(void) { // 画面の更新 HDC hdc = GetDC(gr->hwnd); if (gr_inf->mode == 0) { // 拡大せずセンターに表示 //DBGF(("gr_update センター\n")); SetDIBitsToDevice(hdc, gr_inf->x0, gr_inf->y0, gr_inf->w, gr_inf->h, 0, 0, 0, gr_inf->h, gr->pix_mem, &gr->bmpInfo, DIB_RGB_COLORS); } else { // フル画面に拡大表示 //DBGF(("gr_update フル画面\n")); StretchDIBits(hdc, 0, 0, gr_inf->fs_w, gr_inf->fs_h, 0, 0, gr_inf->w, gr_inf->h, gr->pix_mem, &gr->bmpInfo, DIB_RGB_COLORS, SRCCOPY); } ReleaseDC(gr->hwnd,hdc); } void gr_cls(void) { // 描画バッファクリア unsigned *p = (long *)gr->pix_mem; int l = gr_inf->w * gr_inf->h * sizeof(gr_pix_t)/sizeof(unsigned); do { *p++ = 0; } while (--l); } /*-------------------------------------------*/ static inline void pset(int x, int y, int c) { if ((unsigned)x < (unsigned)gr_inf->w && (unsigned)y < (unsigned)gr_inf->h) { // ※(unsigned)することで負の座標も範囲外にしている unsigned char *p = gr->pix + y * gr->lPitch + x * sizeof(gr_pix_t); //(x,y)座標のアドレスを設定 *(gr_pix_t*)p = c; } } static inline void drawRectInChk(int *ax, int *ay, int *aw, int *ah, int *au, int *av) { int da_x1 = 0, da_y1 = 0, da_x2 = gr_inf->w-1, da_y2 = gr_inf->h-1; int x,y, x2,y2; x = (*ax > da_x1) ? *ax : da_x1; y = (*ay > da_y1) ? *ay : da_y1; x2 = (*ax+*aw < da_x2) ? *ax+*aw : da_x2; y2 = (*ay+*ah < da_y2) ? *ay+*ah : da_y2; *au = x - *ax; *av = y - *ay; *ax = x; *ay = y; *aw = x2 - x; *ah = y2 - y; } void gr_pset(int x, int y, int c) { // (x,y) にピクセル cを表示. //DBGF(("gr_pset(%3d,%3d,%06x)\n",x,y,c)); pset(x,y, GR_RGB2PIX(c)); } void gr_line(int x0, int y0, int x1, int y1, int c) { int w = 1 + x1 - x0, h = 1 + y1 - y0; int x,y,t,d; //DBGF(("gr_line(%3d,%3d,%3d,%3d, %06x)\n",x0,y0,x1,y1,c)); c = GR_RGB2PIX(c); if (abs(w) >= abs(h)) { if (w < 0) { w = -w; t = x0, x0 = x1, x1 = t; t = y0, y0 = y1, y1 = t; h = y1 - y0; } y = y0<<16; d = (w) ? ((h << 16) / w) : 0; for (x = x0; x <= x1; x++) { pset(x, y>>16, c); y += d; } } else { if (h < 0) { h = -h; t = x0, x0 = x1, x1 = t; t = y0, y0 = y1, y1 = t; w = x1 - x0; } x = x0 << 16; d = (h) ? ((w << 16) / h) : 0; for (y = y0; y <= y1; y++) { pset(x>>16, y, c); x += d; } } } void gr_boxLine(int x0, int y0, int w, int h, int c) { int x,y; //DBGF(("gr_boxLine(%3d,%3d,%3d,%3d, %06x)\n",x,y,w,h,c)); c = GR_RGB2PIX(c); for (x = x0; x < x0 + w; x++) { pset(x, y0 , c); pset(x, y0+h-1, c); } for (y = y0+1; y < y0 + h-1; y++) { pset(x0, y, c); pset(x0+w-1, y, c); } } void gr_boxFill(int x0, int y0, int w, int h, int c) { int u = 0, v = 0; int x,y, d; //DBGF(("gr_boxFill(%3d,%3d,%3d,%3d, %06x)\n",x,y,w,h,c)); c = GR_RGB2PIX(c); drawRectInChk(&x0, &y0, &w, &h, &u, &v); // 表示範囲に矩形をレサイズ if (w > 0 && h > 0) { gr_pix_t *p = (gr_pix_t*)(gr->pix + y0 * gr->lPitch + x0 * sizeof(gr_pix_t)); d = gr->lPitch - w*sizeof(gr_pix_t); y = h; do { x = w; do { *p++ = c; } while (--x); p = (gr_pix_t*)((char*)p + d); } while (--y); } }