Вы действительно правы.WM_TIMER крайне неточен.Если вы попытаетесь сделать что-то подобное с GetTickCount (), WaitForSingleObject (..., timeout) или Sleep (timeout), они также не будут работать, потому что они используют механизм синхронизации, аналогичный WM_TIMER.Механизм, который я могу придумать для достижения вашей цели, заключается в использовании счетчика производительности с высоким разрешением .Обратите внимание, что здесь есть некоторые проблемы, такие как потенциальные проблемы с многопроцессорными системами, потраченные впустую циклы из-за вращения и даже процессоров, которые не используют аппаратные таймеры.Но это отправная точка для вас.
Вот как вы его используете:
Сначала спросите систему, какова частота счетчиков производительности.Затем выполните цикл и несколько раз получите текущее время и посмотрите, сколько времени прошло.Когда пройдет 1/25 секунды, делай свое дело.Пример кода:
#include <windows.h>
#include <string>
#include <sstream>
#include <iostream>
using namespace std;
typedef unsigned __int64 u64;
string format_elapsed(u64 elapsed, u64 freq)
{
stringstream ss;
ss << static_cast<double>(elapsed)/static_cast<double>(freq) << " sec";
return ss.str();
}
int main()
{
LARGE_INTEGER li = {};
QueryPerformanceFrequency(&li);
u64 freq = static_cast<u64>(li.QuadPart); // clock ticks per second
u64 period = 25; // 25 fps
u64 delay = freq/period; // clock ticks between frame paints
u64 start = 0, now = 0;
QueryPerformanceCounter(&li);
start = static_cast<u64>(li.QuadPart);
for( ; ; ) // loop forever
{
QueryPerformanceCounter(&li);
now = static_cast<u64>(li.QuadPart);
if( now - start >= delay )
{
// time to paint
cout << "Paint! Elapsed = " << format_elapsed(now-start,freq) << "\n";
// reset new start time & loop
start = now;
}
}
}