基于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;
}