WinAPI: SetTimer、KillTimer - 创建与移除高性能定时器

本文详细介绍了Windows系统中定时器的使用方法,包括SetTimer和KillTimer函数的参数解析及应用实例,展示了如何通过回调函数处理定时任务。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

//创建定时器函数的声明:
SetTimer(
  hWnd: HWND;               {与定时器相关联的窗口句柄}
  nIDEvent: UINT;           {指定一个非 0 的定时器标识符}
  uElapse: UINT;            {指定间隔时间, 单位是毫秒}
  lpTimerFunc: TFNTimerProc {每到时间后, 要调用的函数的指针}
): UINT;                    {返回定时器标识符; 失败返回 0}

//移除定时器函数的声明:
KillTimer(
  hWnd: HWND;    {与定时器相关联的窗口句柄}
  uIDEvent: UINT {定时器标识符}
): BOOL;

//处理 WM_TIMER 消息的回调函数的格式:
TimerProc(
  hWnd: HWND;    {与定时器相关联的窗口句柄}
  uMsg: UINT;    {WM_TIMER 消息}
  idEvent: UINT; {定时器的标识符}
  Time: DWORD    {以世界时间公约格式(UTC)指定的系统时间}
);               {这是个过程, 无返回值}

应该先理解一下再举例:

SetTimer 的参数1: hWnd, 一般指定 Self.Handle 就可以了;

SetTimer 的参数2: nIDEvent 是某个定时器的标识符, 说明可以创建若干个定时器, 随便给个正整数即可;

SetTimer 的参数3: uElapse, 这相当于 VCL 中 Timer 类的 Interval 属性;

看来参数 1-3 还是非常简单, 不好理解的就是参数4: lpTimerFunc, 这是一个过程的地址.

任意一个过程的地址吗? 当然不是; 这个过程的参数结构是 Windows 系统规定的, 我们必须按规定去定义这个过程; 即使你用不到其中的参数也必须如此.
//举例:
var
  i: Integer;

//先定义回调函数
procedure MyTimerProc(hWnd: HWND; uMsg: UINT; idEvent: UINT; Time: DWORD);
begin
  Form1.Text := IntToStr(i);
  Inc(i);
end;

//创建定时器
procedure TForm1.Button1Click(Sender: TObject);
begin
  SetTimer(Handle, 1, 10, @MyTimerProc); {每 1/100 秒调用一次 MyTimerProc}
end;

//删除定时器
procedure TForm1.Button2Click(Sender: TObject);
begin
  KillTimer(Handle, 1); {创建时指定的定时器标识是 1, 这里必须要一致}
end;

//如果回调过程是窗体类的一个方法, 需要这样: var i: Integer; //先定义回调函数 procedure TForm1.MyTimerProc(hWnd: HWND; uMsg: UINT; idEvent: UINT; Time: DWORD); begin Text := IntToStr(i); Inc(i); end; //创建定时器 procedure TForm1.Button1Click(Sender: TObject); begin SetTimer(Handle, 1, 10, @TForm1.MyTimerProc); {每 1/100 秒调用一次 MyTimerProc} end; //删除定时器 procedure TForm1.Button2Click(Sender: TObject); begin KillTimer(Handle, 1); {创建时指定的定时器标识是 1, 这里必须要一致} end;
#include <windows.h> #define TIMER_ID 1 // 颜色序列常量定义 COLORREF colors[] = { RGB(255, 0, 0), // 红 RGB(255, 165, 0), // 橙 RGB(255, 255, 0), // 黄 RGB(0, 255, 0), // 绿 RGB(0, 255, 255), // 青 RGB(0, 0, 255), // 蓝 RGB(148, 0, 211) // 紫 }; int colorIndex = -1; // 当前使用的颜色索引初始化为无效值(-1) LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow) { static char szAppName[] = "HelloWin"; HWND hwnd; MSG msg; WNDCLASS wndclass; // 设置WNDCLASS结构体... wndclass.style = CS_HREDRAW | CS_VREDRAW; wndclass.lpfnWndProc = (WNDPROC)WndProc; wndclass.cbClsExtra = 0; wndclass.cbWndExtra = 0; wndclass.hInstance = hInstance; wndclass.hIcon = LoadIcon(NULL, IDI_APPLICATION); wndclass.hCursor = LoadCursor(NULL, IDC_ARROW); wndclass.hbrBackground = GetStockBrush(WHITE_BRUSH); // 初始白色背景刷子 wndclass.lpszMenuName = NULL; wndclass.lpszClassName = szAppName; if (!RegisterClass(&wndclass)) { MessageBox(NULL, TEXT("This program requires Windows NT!"), szAppName, MB_ICONERROR); return 0; } hwnd = CreateWindow(szAppName, TEXT("The Windows Program"), WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, hInstance, NULL); ShowWindow(hwnd, iCmdShow); UpdateWindow(hwnd); SetTimer(hwnd, TIMER_ID, 500, NULL); // 启动周期性事件(每隔半秒钟) while (GetMessage(&msg, NULL, 0, 0)) { TranslateMessage(&msg); DispatchMessage(&msg); } KillTimer(hwnd, TIMER_ID); // 停止定时器 return msg.wParam; } LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) { HDC hdc; PAINTSTRUCT ps; RECT rect; switch(message){ case WM_CREATE: break; case WM_PAINT: { hdc = BeginPaint(hwnd,&ps); // 获取客户区矩形区域信息. GetClientRect(hwnd,&rect); ++colorIndex %= sizeof(colors)/sizeof(COLORREF); // 自增当前颜色索引 FillRect(hdc,&rect,(HBRUSH)CreateSolidBrush(colors[colorIndex])); DeleteObject((HGDIOBJ)(HPEN)SelectObject(hdc,GetStockPen(DC_PEN))); EndPaint(hwnd,&ps); }break; case WM_DESTROY: PostQuitMessage(0); break; default : return DefWindowProc(hwnd,message,wParam,lParam); } return 0; }
最新发布
03-12
``` #include <windows.h> #include <bits/stdc++.h> #define UNICODE #define _UNICODE // 双缓冲绘图 HDC hdcBuffer; HBITMAP hbmBuffer; HBITMAP hOldBmp; RECT rect; // 颜色转换函数 COLORREF HSLtoRGB(float h, float s, float l) { float c = (1 - fabs(2 * l - 1)) * s; float x = c * (1 - fabs(fmod(h / 60.0f, 2) - 1)); float m = l - c / 2.0f; float r, g, b; if (h < 60) { r = c; g = x; b = 0; } else if (h < 120){ r = x; g = c; b = 0; } else if (h < 180){ r = 0; g = c; b = x; } else if (h < 240){ r = 0; g = x; b = c; } else if (h < 300){ r = x; g = 0; b = c; } else { r = c; g = 0; b = x; } return RGB((r + m) * 255, (g + m) * 255, (b + m) * 255); } // 窗口过程 LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { switch(msg) { case WM_PAINT: { PAINTSTRUCT ps; HDC hdc = BeginPaint(hwnd, &ps); static float t = 0.0f; t += 0.01f; hdcBuffer = CreateCompatibleDC(hdc); GetClientRect(hwnd, &rect); hbmBuffer = CreateCompatibleBitmap(hdc, rect.right, rect.bottom); hOldBmp = (HBITMAP)SelectObject(hdcBuffer, hbmBuffer); FillRect(hdcBuffer, &rect, (HBRUSH)GetStockObject(BLACK_BRUSH)); const float a = 50.0f; for(float ii = 0; ii < 6.283f; ii += 0.001f) { float r = a * (1 - sin(ii)); float scale = 1.0f + 0.1f * sin(t * 5.0f); float phase = t * 50.0f; int x = (int)(scale * r * cos(ii) + rect.right/2); int y = (int)(-scale * r * sin(ii) + rect.bottom/2); SetPixel(hdcBuffer, x, y, HSLtoRGB(fmod(ii*30 + phase, 360), 1.0f, 0.5f)); } BitBlt(hdc, 0, 0, rect.right, rect.bottom, hdcBuffer, 0, 0, SRCCOPY); SelectObject(hdcBuffer, hOldBmp); DeleteDC(hdcBuffer); DeleteObject(hbmBuffer); EndPaint(hwnd, &ps); InvalidateRect(hwnd, NULL, FALSE); break; } case WM_DESTROY: PostQuitMessage(0); break; default: return DefWindowProc(hwnd, msg, wParam, lParam); } return 0; } // 主函数 int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrevInst, LPSTR lpCmdLine, int nCmdShow) { WNDCLASSEXW wc = {0}; wc.cbSize = sizeof(WNDCLASSEXW); wc.style = CS_HREDRAW | CS_VREDRAW; wc.lpfnWndProc = WndProc; wc.hInstance = hInst; wc.hCursor = LoadCursor(NULL, IDC_ARROW); wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1); wc.lpszClassName = L"HeartWindow"; if(!RegisterClassExW(&wc)) return 0; HWND hwnd = CreateWindowExW( 0, L"HeartWindow", L"Animated Heart", WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, 800, 600, NULL, NULL, hInst, NULL ); if(!hwnd) return 0; ShowWindow(hwnd, nCmdShow); UpdateWindow(hwnd); MSG msg; while(GetMessage(&msg, NULL, 0, 0)) { TranslateMessage(&msg); DispatchMessage(&msg); } return (int)msg.wParam; }```源文件未编译 请写出此题修改后的完整代码
03-10
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值