アットウィキロゴ
/********************************************
点が舞うプログラム(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