"Run every" implies that it should run N times in T time...
#define RUNEVERY(n) for (static unsigned long lasttime, unsigned long t = (n); millis() - lasttime > t; lasttime += t)
"Run after" implies that it should run after T milliseconds have elapsed...
#define RUNAFTER(n) for (static unsigned long lasttime; millis() - lasttime > (n); lasttime = millis())
The variable should be named to reduce the chances of a conflict...
#define RUNAFTER(n) for (static unsigned long _lasttime; millis() - _lasttime > (n); _lasttime = millis())
To be more Arduinoish the macro should be named in modified camel...
#define runAfter(n) for (static unsigned long _lasttime; millis() - _lasttime > (n); _lasttime = millis())
To eliminate drift, time should be sampled once...
#define runAfter(n) for (static unsigned long _lasttime, unsigned long _thistime = millis(); _thistime - _lasttime > (n); _lasttime = _thistime)
The error needs to be eliminated...
#define runAfter(n) for (static unsigned long _lasttime, unsigned long _thistime = millis(); _thistime - _lasttime >= (n); _lasttime = _thistime)
16 bit may be a better choice...
#define runAfter(n) for (static uint16_t _lasttime, uint16_t _thistime = millis(); (uint16_t)(_thistime - _lasttime) >= (uint16_t)(n); _lasttime = _thistime)
What did I forget?