/********************************************
点が舞うプログラム(2007/06/16)
見てるとちょっと楽しい
********************************************/
#include <stdio.h>
#include <windows.h>
#include <commctrl.h>
#include <tchar.h>
#include <math.h>
#include <stdlib.h>
#include <time.h>
#pragma comment(lib, "comctl32.lib")
//定数
#define BALL 6000 //点の数
#define ACCEL 800 //加速度
#define DOT_R 1 //点の半径pixel
#define WINDOW_WIDTH (800) //ウィンドウの幅
#define WINDOW_HEIGHT (600)//ウィンドウの高さ
#define WINDOW_X ((GetSystemMetrics(SM_CXSCREEN) - WINDOW_WIDTH) /2 ) //ウィンドウの表示位置X座標
#define WINDOW_Y ((GetSystemMetrics(SM_CYSCREEN) - WINDOW_HEIGHT) /2 ) //ウィンドウの表示位置y座標
#define TIMER_ID (100) // 作成するタイマの識別ID
#define TIMER_ELAPSE (20) // WM_TIMERの発生間隔
#define ID_STATUS 100 //ステータスID
//グローバル変数
//プロトタイプ宣言
HWND Create(HINSTANCE hInst);
LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp);
//開始位置
int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrevInst, LPSTR pCmdLine, int showCmd){
HWND hWnd;
MSG msg;
// RECT rect;
//ウィンドウを作成する
hWnd = Create(hInst);
if(hWnd == NULL){
MessageBox( NULL, _T("ウィンドウの作成に失敗しました。"), _T("ERROR"), MB_OK );
return (1);
}
//ウィンドウを表示する
ShowWindow(hWnd,SW_SHOW);
UpdateWindow(hWnd);
/*
//テキストファイルを開く
g_fp = fopen("test.txt","w");
if(g_fp == NULL){
return(1);
}
*/
//マウスカーソルの初期位置をウィンドウの中心にする
SetCursorPos(WINDOW_X + WINDOW_WIDTH / 2,WINDOW_Y + WINDOW_HEIGHT / 2);
/*
//マウスカーソルの移動範囲を制限する
rect.left = WINDOW_X;
rect.top = WINDOW_Y;
rect.right = WINDOW_X + WINDOW_WIDTH;
rect.bottom = WINDOW_Y + WINDOW_HEIGHT;
ClipCursor(&rect);
*/
//メッセージループ
while(1){
BOOL ret = GetMessage(&msg, NULL, 0, 0); //メッセージを取得する
if(ret == 0 || ret == -1){
//アプリケーションを終了させるメッセージが来ていたら、
//或いはGetMessage()が失敗したら(-1が返されたら)、ループを抜ける
break;
}else{
//メッセージを処理する
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
// ClipCursor(NULL); //クリップを解除する
return(0);
}
//ウィンドウを作成する
HWND Create(HINSTANCE hInst){
WNDCLASSEX wc;
HWND hWnd;
//ウィンドウクラスの情報を設定
wc.cbSize = sizeof(wc); //構造体サイズ
wc.style = CS_HREDRAW | CS_VREDRAW ; //スタイル
wc.lpfnWndProc = WndProc; //ウィンドウプロシージャ
wc.cbClsExtra = 0; //拡張情報1
wc.cbWndExtra = 0; //拡張情報2
wc.hInstance = hInst; //インスタンスハンドル
wc.hIcon = (HICON)LoadImage( //アイコン
NULL,MAKEINTRESOURCE(IDI_APPLICATION), IMAGE_ICON,
0, 0, LR_DEFAULTSIZE | LR_SHARED
);
wc.hIconSm = wc.hIcon; //子アイコン
wc.hCursor = (HCURSOR)LoadImage( //マウスカーソル
NULL, MAKEINTRESOURCE(IDC_ARROW), IMAGE_CURSOR,
0, 0, LR_DEFAULTSIZE | LR_SHARED
);
wc.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH); //ウィンドウ背景
wc.lpszMenuName = NULL; //メニュー名
wc.lpszClassName = _T("Default Class Name"); //ウィンドウクラス名
//ウィンドウクラスを登録する
if(RegisterClassEx(&wc) == 0){
return(NULL);
}
/*
//ウィンドウの作成位置を計算する
g_windowPos.left=(GetSystemMetrics(SM_CXSCREEN)-WINDOW_WIDTH)/2;
g_windowPos.top=(GetSystemMetrics(SM_CYSCREEN)-WINDOW_HEIGHT)/2;
g_windowPos.right=g_windowPos.left + WINDOW_WIDTH;
g_windowPos.bottom=g_windowPos.top + WINDOW_HEIGHT;
*/
//ウィンドウを作成する
hWnd = CreateWindow(
wc.lpszClassName, //ウィンドウクラス名
_T("Dots"),//タイトルバーに表示する文字列
WS_OVERLAPPEDWINDOW &~WS_THICKFRAME, //ウィンドウの種類
WINDOW_X, //ウィンドウを表示する位置(X座標)
WINDOW_Y, //ウィンドウを表示する位置(y座標)
WINDOW_WIDTH, //ウィンドウの幅
WINDOW_HEIGHT, //ウィンドウの高さ
NULL, //親ウィンドウのウィンドウハンドル
NULL, //メニューハンドル
hInst, //インスタンスハンドル
NULL //その他の作成データ
);
return(hWnd);
}
//ウィンドウプロシージャ
LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp){
HDC hDC;
PAINTSTRUCT ps; //描画のハンドル
int i; //for文用
double s; //計算用
static HBRUSH hBrushBlack; //ブラシのハンドル
static HBRUSH hBrushWhite;
static HPEN hPenBlack;
static HPEN hPenWhite;
static POINT now[BALL]; //今の点の位置
static POINT old[BALL]; //古い点の位置
static POINT v[BALL]; //点の速度
static HWND hStatusbar; //ステータスバーのハンドル
static int clickFlag = 0; //クリックフラグ
static double time;
clock_t start;
char str[20];
switch(msg)
{
case WM_TIMER: //タイマメッセージ
start = clock();
if( wp != TIMER_ID )
{
break; // 識別IDが一致しないタイマメッセージはDefWindowProc()に任せる
}
//右クリックが押されていたら位置をクライアント内にランダムで
if(clickFlag==2){
for(i=0;i<BALL;i++){
now[i].x = rand() % WINDOW_WIDTH;
now[i].y = rand() % WINDOW_HEIGHT;
}
}else{
//マウスのスクリーン座標げっつ
GetCursorPos( &now[0] );
//スクリーン座標をクライアント座標へ
ScreenToClient(hWnd, &now[0]);
for(i=0;i<BALL;i++){
//左クリックが押されていたら、速度を0に
if(clickFlag==1){
v[i].x=0;
v[i].y=0;
}else{
s = pow(now[0].x - old[i].x ,2) + pow(now[0].y - old[i].y ,2);
if((int)(s + 0.5)==0){
v[i].x = 0;
v[i].y = 0;
}else{
s = time * ACCEL / sqrt(s);
v[i].x += (now[0].x - old[i].x) * s;
v[i].y += (now[0].y - old[i].y) * s;
}
now[i].x = old[i].x + time * v[i].x;
now[i].y = old[i].y + time * v[i].y;
}
}
}
if(clickFlag) clickFlag=0;
//描画準備
hDC = GetDC(hWnd); //GDI関数による描画を開始する
//白色で前のを消す
/*
SelectObject(hDC, hPenWhite);
SelectObject(hDC, hBrushWhite);
for(i=0;i<BALL;i++){
Ellipse(hDC, old[i].x-DOT_R, old[i].y-DOT_R, old[i].x+DOT_R, old[i].y+DOT_R);
}
*/
//新たに描画
/*
SelectObject(hDC, hPenBlack);
SelectObject(hDC, hBrushBlack);
for(i=0;i<BALL;i++){
old[i] = now[i];
Ellipse(hDC, now[i].x-DOT_R, now[i].y-DOT_R, now[i].x+DOT_R, now[i].y+DOT_R);
}
*/
for(i=0;i<BALL;i++){
SetPixelV(hDC,old[i].x, old[i].y, RGB(255,255,255));
old[i] = now[i];
SetPixelV(hDC, now[i].x, now[i].y ,RGB(0,0,0));
}
//描画終了
ReleaseDC(hWnd, hDC);
sprintf(str,"Time : %f",(double)(clock()-start)/CLOCKS_PER_SEC);
SendMessage(hStatusbar,SB_SETTEXT, 0, (LPARAM)str);
return (0);
case WM_LBUTTONDOWN: //マウスの左ボタンが押された時に送られてくる
clickFlag=1;
return(0);
case WM_RBUTTONDOWN: //マウスの右ボタンが押された時に送られてくる
clickFlag=2;
return(0);
case WM_CREATE: //ウィンドウが開かれた時
//コモンコントロール関係の初期化
InitCommonControls();
//ステータスバーを作成
hStatusbar = CreateStatusWindow(
WS_CHILD | WS_VISIBLE | CCS_BOTTOM | SBARS_SIZEGRIP,
"ステータスバー",
hWnd,
ID_STATUS
);
for(i=0;i<BALL;i++){
now[i].x = rand() % WINDOW_WIDTH;
old[i] = now[i];
now[i].y = rand() % WINDOW_HEIGHT;
old[i] = now[i];
}
//ストックペン作成
hPenBlack = (HPEN)GetStockObject(BLACK_PEN);
hPenWhite = (HPEN)GetStockObject( WHITE_PEN ); // 白いストックペンのハンドルを取得する
//ストックブラシ作成、使用
hBrushBlack = (HBRUSH)GetStockObject(BLACK_BRUSH);
hBrushWhite = (HBRUSH)GetStockObject(WHITE_BRUSH);
// タイマを作成する
SetTimer( hWnd, TIMER_ID, TIMER_ELAPSE, NULL );
for(i=0;i<BALL;i++){
v[i].x=0;
v[i].y=0;
}
time = (double)TIMER_ELAPSE / 1000;
return (0);
case WM_CLOSE: //ウィンドウが閉じられようとしたときに送られてくる
KillTimer( hWnd, TIMER_ID );
if(MessageBox(hWnd, _T("本当に終了してもいいですか?"),_T("確認"),MB_YESNO) == IDNO){
SetTimer( hWnd, TIMER_ID, TIMER_ELAPSE, NULL );
return(0); //閉じない為にはDefWindowProc()に処理させてはならない
}
break; //閉じていいのならDefWindowProc()にまかせればいい
case WM_DESTROY: //ウィンドウを破棄する時
PostQuitMessage(0);
return(0);
}
//他のメッセージはデフォルトの処理を行う
return(DefWindowProc(hWnd, msg, wp, lp));
}
最終更新:2007年06月16日 01:14