基于Windows API的粒子随机运动C++实现

基于Windows API编写Windows动画演示程序,具有便捷、不依赖于IDE的特点。

以随机运动粒子系统为例,实现了该动画框架,C++代码与效果图像如下:

#include 

//粒子数量
#define N 1024

//粒子类型
typedef struct Particle {
	float x, y;
	float speedx, speedy;
	COLORREF rgb;
	Particle() {
		x = (float)rand() / RAND_MAX;
		y = (float)rand() / RAND_MAX;
		speedx = (float)rand() / RAND_MAX - 0.5;
		speedy = (float)rand() / RAND_MAX - 0.5;
		rgb = RGB(rand() % 256, rand() % 256, rand() % 256);
	}

	void update() {
		speedx += ((float)rand() / RAND_MAX - 0.5) * 0.1;
		speedy += ((float)rand() / RAND_MAX - 0.5) * 0.1;
		x += 0.01 * speedx;
		y += 0.01 * speedy;
		if (x < 0 || x > 1)
			x = (float)rand() / RAND_MAX;
		if (y < 0 || y > 1)
			y = (float)rand() / RAND_MAX;
	}
} Particle;

//粒子群体
Particle particles[N];

//定时器编号
UINT_PTR timerId;

/*  Declare Windows procedure  */
LRESULT CALLBACK WindowProcedure (HWND, UINT, WPARAM, LPARAM);

/*  Make the class name into a global variable  */
char szClassName[ ] = "CodeBlocksWindowsApp";


int WINAPI WinMain (HINSTANCE hThisInstance,
                     HINSTANCE hPrevInstance,
                     LPSTR lpszArgument,
                     int nCmdShow)
{
    HWND hwnd;               /* This is the handle for our window */
    MSG messages;            /* Here messages to the application are saved */
    WNDCLASSEX wincl;        /* Data structure for the windowclass */

    /* The Window structure */
    wincl.hInstance = hThisInstance;
    wincl.lpszClassName = szClassName;
    wincl.lpfnWndProc = WindowProcedure;      /* This function is called by windows */
    wincl.style = CS_DBLCLKS;                 /* Catch double-clicks */
    wincl.cbSize = sizeof (WNDCLASSEX);

    /* Use default icon and mouse-pointer */
    wincl.hIcon = LoadIcon (NULL, IDI_APPLICATION);
    wincl.hIconSm = LoadIcon (NULL, IDI_APPLICATION);
    wincl.hCursor = LoadCursor (NULL, IDC_ARROW);
    wincl.lpszMenuName = NULL;                 /* No menu */
    wincl.cbClsExtra = 0;                      /* No extra bytes after the window class */
    wincl.cbWndExtra = 0;                      /* structure or the window instance */
    /* Use Windows's default colour as the background of the window */
    wincl.hbrBackground = (HBRUSH) COLOR_BACKGROUND;

    /* Register the window class, and if it fails quit the program */
    if (!RegisterClassEx (&wincl))
        return 0;

    /* The class is registered, let's create the program*/
    hwnd = CreateWindowEx (
           0,                   /* Extended possibilites for variation */
           szClassName,         /* Classname */
           "Code::Blocks Template Windows App",       /* Title Text */
           WS_OVERLAPPEDWINDOW, /* default window */
           CW_USEDEFAULT,       /* Windows decides the position */
           CW_USEDEFAULT,       /* where the window ends up on the screen */
           1024,                 /* The programs width */
           768,                 /* and height in pixels */
           HWND_DESKTOP,        /* The window is a child-window to desktop */
           NULL,                /* No menu */
           hThisInstance,       /* Program Instance handler */
           NULL                 /* No Window Creation data */
           );

    /* Make the window visible on the screen */
    ShowWindow (hwnd, nCmdShow);

    /* Run the message loop. It will run until GetMessage() returns 0 */
    while (GetMessage (&messages, NULL, 0, 0))
    {
        /* Translate virtual-key messages into character messages */
        TranslateMessage(&messages);
        /* Send message to WindowProcedure */
        DispatchMessage(&messages);
    }

    /* The program return-value is 0 - The value that PostQuitMessage() gave */
    return messages.wParam;
}


/*  This function is called by the Windows function DispatchMessage()  */

LRESULT CALLBACK WindowProcedure (HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
	int wmId, wmEvent;
	PAINTSTRUCT ps;
	HDC hdc, memdc;
	HBITMAP hbitmap, oldbitmap;
	RECT rc;
	HBRUSH          hBrush;
	HPEN pen, *oldpen;

	int x, y, W, H;

	switch (message)
	{
	case WM_CREATE:
		timerId = SetTimer(hWnd, 1, 20, NULL);
		break;
	case WM_TIMER:
		InvalidateRect(hWnd, NULL, FALSE);
		break;
	case WM_COMMAND:
		wmId    = LOWORD(wParam);
		wmEvent = HIWORD(wParam);
		// 分析菜单选择:
		switch (wmId)
		{
		default:
			return DefWindowProc(hWnd, message, wParam, lParam);
		}
		break;
	case WM_PAINT:
		hdc = BeginPaint(hWnd, &ps);
		GetClientRect(hWnd, &rc);
		W = (rc.right - rc.left + 1);
		H = (rc.bottom - rc.top + 1);

		memdc = CreateCompatibleDC(hdc);
		hbitmap = CreateCompatibleBitmap(hdc, W, H);
		oldbitmap = (HBITMAP)SelectObject(memdc, hbitmap);

        hBrush = CreateSolidBrush(RGB(0, 0, 0));
        FillRect(memdc, &rc, hBrush);
		for(int i = 0; i < N; i++) {
			pen = CreatePen(0, 4, particles[i].rgb);
			oldpen = (HPEN *)SelectObject(memdc, pen);
			x = particles[i].x * W;
			y = particles[i].y * H;
			Ellipse(memdc, x - 3, y - 3, x + 3, y + 3);
			particles[i].update();
			DeleteObject(pen);
			//SelectObject(hdc, oldpen);
		}
		//DrawText(memdc, 5, 5, "this");
		DeleteObject( hBrush );
		BitBlt(hdc, 0, 0, W, H, memdc, 0, 0, SRCCOPY);
		SelectObject(memdc, oldbitmap);
		DeleteObject(hbitmap);
		DeleteObject(memdc);

		EndPaint(hWnd, &ps);
		break;
    case WM_KEYDOWN:
        if (wParam == 27) {
            KillTimer(hWnd, timerId);
            PostQuitMessage(0);
        }
		break;
	case WM_DESTROY:
		KillTimer(hWnd, timerId);
		PostQuitMessage(0);
		break;
	default:
		return DefWindowProc(hWnd, message, wParam, lParam);
	}
	return 0;
}
基于Windows API的粒子随机运动C++实现_第1张图片

你可能感兴趣的:(C++,图像处理,算法,科学计算)