ドクペリアンベアー モッカディートのスクリーンセーバー

ぐへへ:
http://d.hatena.ne.jp/ore_de_work/20130318#1363763563

調整.
横軸5匹にした。
スピー度調整
アニメフレーム追加すんのは今週末

調整.
バグってた修正

/* モッカディート スクリーンセーバー */
#include <windows.h>
#include <scrnsave.h>
#include <tchar.h>
#include "resource.h"
#include <stdio.h>

/* スクリーンセーバー用ライブラリの指定 */
#ifdef UNICODE
#    pragma comment(lib,"scrnsavw.lib")
#else
#    pragma comment(lib,"scrnsave.lib")
#endif
#pragma comment(lib,"comctl32.lib")

// Y位置調整用
#define Y ((rc.bottom - rc.top - scrh*2) / 10)

// 速度
#define XX ((rc.right - rc.left) / 45)

// 一列のくまさんの数 
#define MOKKADEET 5

// アニメーション
#define ANIME 4

HBITMAP hBitmap[ANIME*2];

LONG i, x1, x2;

int debug = 0;
TCHAR str [1024];

/* ------------------------------------------------------------------ */
BOOL WINAPI RegisterDialogClasses(HANDLE hInst)
{
	return TRUE;
}

/* ------------------------------------------------------------------ */
/* 設定ダイアログだけどモッカディート表示します */
BOOL WINAPI
ScreenSaverConfigureDialog(HWND hWnd,UINT uMsg,WPARAM wParam,LPARAM lParam)
{
	switch(uMsg) {
	case WM_INITDIALOG:
		debug = 1;
		uMsg = WM_CREATE;
		// 塗りつぶしタイマー
		SetTimer(hWnd,2, 800, NULL);
		ScreenSaverProc( hWnd,  uMsg,  wParam,  lParam);
	case WM_CREATE:
		break;
	case WM_DESTROY:
	case WM_TIMER:
		ScreenSaverProc( hWnd,  uMsg,  wParam,  lParam);
		break;

	case WM_COMMAND:
	case WM_CLOSE:
		EndDialog(hWnd, 0);
		break;

	default:
		break;
	}
	return FALSE;
}

/* ------------------------------------------------------------------ */
/* スクリーンセーバー処理 */
LONG WINAPI
ScreenSaverProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
	HDC    hdc;
	LONG cx1, cx2;
	BITMAP bmp_info;
	HDC hdc_mem;
	RECT rc;
	LONG bmpw, bmph;
	LONG scrw, scrh;

	switch(uMsg) {
	case WM_CREATE:
		{
			int i, j;
			// bitmap 読込 (上) 方向 ← ← ← ← ←
			for( i = 0; i < ANIME; i++ )
				hBitmap[i] = LoadBitmap(hMainInstance, (LPCTSTR)IDB_BITMAP1 + i);

			// 逆像を作る  
			j = ANIME;
			for( ; i < ANIME * 2; i++ )
				hBitmap[i] = hBitmap[--j];

		}

		// 100ms くらいでいい
		SetTimer(hWnd,1, 100, NULL);
		break;

	case WM_DESTROY:
		KillTimer(hWnd,1);
		/* タイマー割り込み終了 */
		for( i = 0; i < ANIME; i++ )
			DeleteObject(hBitmap[i]);
		break;

	case WM_TIMER:
		hdc = GetDC(hWnd);
		GetClientRect(hWnd, &rc);

		if(wParam == 2)
		{
			/* それなりの色で塗りつぶす */
			HBRUSH hBrush, hOldBrush;
			hBrush = CreateSolidBrush(RGB(0, 0, 0)); 
			//hBrush = CreateSolidBrush(RGB(0, 24, 24)); 
			hOldBrush = (HBRUSH)SelectObject(hdc, hBrush);
			Rectangle(hdc, rc.left, rc.top, rc.right, rc.bottom);
			SelectObject(hdc, hOldBrush);
		}

		if(wParam == 1)
		{
			i++;
			i %= ((ANIME) * 2);
			hdc_mem = CreateCompatibleDC(hdc);
			SelectObject(hdc_mem, hBitmap[i]);
			GetObject(hBitmap[i], sizeof(BITMAP), &bmp_info);
			bmpw =bmp_info.bmWidth;
			bmph =bmp_info.bmHeight;

			// スクリーンサイズからモッカディートのサイズを算出
			scrw = (rc.right - rc.left) / MOKKADEET;
			scrh = scrw *   bmph / bmpw;

			// 速度
			x1 += XX;
			x2 += XX;

			// 位置補正
			cx1 = scrw - x1;
			cx2 = x2;
			cx1 %= scrw;
			//   x1 %= scrw;
			x2 %= scrw;

			SetStretchBltMode(hdc,COLORONCOLOR);

			// (上) 方向 ← ← ← ← ←
			for(; cx1 < rc.right ; cx1 += scrw)
				StretchBlt(hdc, cx1, Y, scrw, scrh,
				hdc_mem, 0, 0, bmpw, bmph, SRCCOPY);
			// (下) 方向 → → → → →
			for(; cx2 < rc.right + scrw ; cx2 += scrw)
				StretchBlt(hdc, cx2, rc.bottom - scrh - Y, -scrw, scrh,
				hdc_mem, 0, 0, bmpw, bmph, SRCCOPY);

			if( cx1 < 0) x1 = 0;

			if(debug){
				_stprintf( str, _T("scr %d/%d tgt %d/%d bmp[%d:%lx] %d/%d x1 %d/%d x2 %d/%d ."),  
					rc.right - rc.left, rc.bottom - rc.top,  
					scrw, scrh,
					i, (LONG)hBitmap[i], bmpw, bmph,
					x1, cx1, x2, cx2

					);
				TextOut(hdc, 0, 0, str , (int) _tcslen(str));
			}

			DeleteDC(hdc_mem); 

		}

		ReleaseDC(hWnd, hdc);
		break;

	default:
		return DefScreenSaverProc(hWnd,uMsg,wParam,lParam);
	}

	return 0;
}