/* // スクリーンセーバー・サンプル */ #include #include #include #include #include #include "resource.h" /* スクリーンセーバー用ライブラリの指定 */ #pragma comment(lib,"scrnsave.lib") #ifndef __cplusplus #define inline __inline #endif /*--------------------------------------------------------------------------*/ #define INIFL_FILE_NAME "ScrnSvr.tmp" //c:\windowsに作られる。ユーザ設定項目を保持するためのファイル #define INIFL_APP_NAME "ScrnSvr_Sample_Program_Data" //INI_FILE にかかれるアプリケーション名 #define SCRN_W 640 // 描画画面の横幅. 普通640. 4の倍数であること! #define SCRN_H 480 // 縦幅. 480. #define SCRN_BPP 32 // 16 or 32 bit色のみ. /*----------------------------------*/ /* グラフィック関係 */ #define GR_RGB(r,g,b) (((unsigned char)(r)<<16)|((unsigned char)(g)<<8)|(unsigned char)(b)) #if SCRN_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 { int w, h; // 描画画面サイズ int x0,y0; // 描画画面の表示開始位置. int fs_w, fs_h; // 表示画面サイズ BYTE *pix; // 描画バッファの表示基準の先頭アドレス BYTE *pix_mem; // 描画バッファのmallocしたときのアドレス int lPitch; // 描画バッファの次の行までのバイト数 int mode; // 0=センター表示 1=画面サイズに合わせる(拡大) HWND hwnd; // カレントウィンドウ BITMAPINFO bmpInfo; // 仮想フレームバッファ表示に使う } Gr; static Gr gr_body; Gr *gr = &gr_body; int gr_init(HWND hwnd, int w, int h, int mode); 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 int inifl_getVal(char *key); static void inifl_setVal(char *key, int val); static void main_loop(void); BOOL WINAPI RegisterDialogClasses(HANDLE hInst) { return TRUE; } BOOL WINAPI ScreenSaverConfigureDialog(HWND hWnd,UINT uMsg,WPARAM wParam,LPARAM lParam) { /* 素で起動したときの処理 */ /* EndDialog()の第二引数の値がアプリケーションの終了値になる! */ int fsFlg; switch(uMsg) { case WM_INITDIALOG: fsFlg = inifl_getVal("FullScreen"); CheckDlgButton(hWnd, IDC_CHECK1, fsFlg); return TRUE; case WM_CLOSE: EndDialog(hWnd, 0); break; case WM_COMMAND: switch(LOWORD(wParam)) { case IDC_OK: fsFlg = IsDlgButtonChecked(hWnd, IDC_CHECK1); inifl_setVal("FullScreen", fsFlg); EndDialog(hWnd,0); break; case IDC_CANCEL: EndDialog(hWnd,0); break; } break; default: break; } return FALSE; } static int inifl_getVal(char *key) { // iniファイルより、keyの値を取得 char buf[256+2]; GetPrivateProfileString(INIFL_APP_NAME, key, "0", buf, 256, INIFL_FILE_NAME); return strtol(buf, NULL, 10); } static void inifl_setVal(char *key, int val) { // iniファイルに値をkeyの値を設定 char buf[256+2]; _snprintf(buf, 256, "%d",val); WritePrivateProfileString(INIFL_APP_NAME, key, buf, INIFL_FILE_NAME); } LONG WINAPI ScreenSaverProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { // スクリーンセーバー処理実体 int fsFlg; //DBGF(("msg %04x\n", uMsg)); switch(uMsg) { case WM_CREATE: // 初期化 fsFlg = inifl_getVal("FullScreen"); if (gr_init(hWnd, SCRN_W, SCRN_H, fsFlg) == 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, c; //gr_cls(); for (i = 0; i < 10; i++) { c = GR_RGB(rand()&0xff, rand()&0xff, rand()&0xff); x = rand() % gr->w; y = rand() % gr->h; switch (rand() % 4) { case 0: gr_pset(x,y, c); break; case 1: gr_line(x,y, rand()%gr->w, rand()%gr->h, c); break; case 2: gr_boxLine(x,y, 1+rand()%100, 1+rand()%100, c); break; case 3: gr_boxFill(x,y, 1+rand()%100, 1+rand()%100, c); break; } } gr_update(); } /*--------------------------------------------------------------------------*/ int gr_init(HWND hwnd, int w, int h, int md) { // グラフィック処理の初期化 RECT r; gr->hwnd = hwnd; gr->mode = md; gr->w = w; gr->h = h; // 表示範囲を取得(フル画面サイズのはず...) GetClientRect(hwnd,&r); gr->fs_w = r.right - r.left; gr->fs_h = r.bottom - r.top; if (gr->fs_w == 0 || gr->fs_h == 0) return 0; gr->x0 = (gr->fs_w - gr->w) >> 1; gr->y0 = (gr->fs_h - gr->h) >> 1; // 描画バッファの設定. 16 or 32ビットカラー。 gr->pix_mem = (BYTE*)calloc(1, gr->w * gr->h * sizeof(gr_pix_t)); if (gr->pix_mem == NULL) return 0; gr->pix = gr->pix_mem + (gr->h - 1) * gr->w * sizeof(gr_pix_t); gr->lPitch = -gr->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->w; gr->bmpInfo.bmiHeader.biHeight = gr->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; 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); if (gr->mode == 0) { // 拡大せずセンターに表示 //DBGF(("gr_update センター\n")); SetDIBitsToDevice(hdc, gr->x0, gr->y0, gr->w, gr->h, 0, 0, 0, gr->h, gr->pix_mem, &gr->bmpInfo, DIB_RGB_COLORS); } else { // フル画面に拡大表示 //DBGF(("gr_update フル画面\n")); StretchDIBits(hdc, 0, 0, gr->fs_w, gr->fs_h, 0, 0, gr->w, gr->h, gr->pix_mem, &gr->bmpInfo, DIB_RGB_COLORS, SRCCOPY); } ReleaseDC(gr->hwnd,hdc); } void gr_cls(void) { // 描画バッファクリア long *p = (long *)gr->pix_mem; int l = gr->w * gr->h * sizeof(gr_pix_t) / sizeof(long); do { *p++ = 0; } while (--l); } /*-------------------------------------------*/ static void inline pset(int x, int y, int c) { if ((unsigned)x < (unsigned)gr->w && (unsigned)y < (unsigned)gr->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->w-1, da_y2 = gr->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); } }