Функция вызова по истечении определенного времени - PullRequest
2 голосов
/ 07 октября 2010

Я делаю GUI API (для игр, а не ОС) и хотел бы реализовать анимированные кнопки. Я хотел бы иметь возможность создавать синхронизированные события, но внутри класса. Пример:

class TextBox
{
   void changeColor(int color);

    void createTimedEvent(func* or something, int ticks);
     void animate()
{

    createTimedEvent(changeColor(red),30);

}

};

Таким образом, в этом примере таймер вызовет функцию changeColor экземпляра класса с аргументом red через 30 мс. Есть ли способ сделать это?

По сути, функция для вызова функции, которая может быть функцией из инстанцируемого класса без аргументов после истечения заданного интервала.

Точность таймера для меня не имеет большого значения.

Спасибо

Ответы [ 2 ]

2 голосов
/ 07 октября 2010

Я полагаю, что вы могли бы сделать эту работу переносимой, используя Boost.Asio - это в первую очередь предназначено для асинхронного ввода-вывода, но я не вижу причин, почему код таймера нельзя использовать в других контекстах. См. этот пример , чтобы узнать, как запустить таймер, который вызывает ваш код после истечения срока действия.

Единственное условие, которое я заметил, это то, что вам нужно вызвать ioservice::run в каком-то потоке с экземпляром ioservice, который вы использовали здесь, иначе обратные вызовы не произойдут.

#include <iostream>
#include <boost/asio.hpp>
#include <boost/date_time/posix_time/posix_time.hpp>

void print(const boost::system::error_code& /*e*/)
{
  std::cout << "Hello, world!\n";
}

int main()
{
  boost::asio::io_service io;

  boost::asio::deadline_timer t(io, boost::posix_time::seconds(5));

  t.async_wait(print);

  // ensure we call io.run() from some thread or callbacks will not happen

  // other app logic

  return(0);
}

Автор этой библиотеки также обсуждает эту тему в блогах MSDN .

0 голосов
/ 07 октября 2010

Я бы хотел, чтобы кто-нибудь показал обратное, но, насколько я знаю, вам придется разбираться с этим поэтапно.Первый шаг - создать связанную функцию, т. Е. Взять указанную вами функцию и создать объект, который, когда вы ее вызываете, в свою очередь вызывает указанную функцию с указанными параметрами.Используя Boost / TR1 / C ++ 0x bind, это будет выглядеть примерно так:

std::tr1::function<void (int)> func(std::tr1::bind(&TextBox::changColor, this, red));

Это делает func объектом, который будет вызывать TextBox::changeColor(red) при его вызове.Однако есть одна небольшая проблема: func это объект, а не функция.Синтаксически использование этого похоже на вызов функции, но это иллюзия, созданная компилятором C ++;Попытка передать адрес этого объекта чему-то, что будет использовать его как адрес функции, потерпит неудачу (вероятно, довольно впечатляюще).К сожалению, по крайней мере в Windows нет способа назначить произвольный параметр, который будет передан функции обратного вызова таймера (хотя вы могли бы , вероятно, сделать это в параметре nIdEvent с некоторым действительно грубым приведением, что-то вроде:

void callback(HWND, UINT, UINT_PTR f, DWORD) { 
    typedef std::tr1::function<void (int)> function;
    function *func = reinterpret_cast<function *>(f);
    (*func)();
}

Чтобы сделать это немного чище, вместо преобразования адреса в целое число без знака, я бы рассмотрел сохранение адреса обратного вызова в массиве и передачу его индекса ввместо массива:

void callback(HWND, UINT, UINT_PTR f, DWORD) { 
    callback_functions[f]();
}

Таким образом, действительно остается непереносимой частью: фактически заставить систему вызывать эту функцию по истечении определенного промежутка времени. Хотя большинство современных систем имеют одну, каждаявсе еще уникален. В Windows (для одного примера) вы могли бы сделать что-то вроде этого:

callback_functions[++N] = func;
SetTimer(hWnd, N, 30, callback);

Для такой простой идеи это слишком уродливый и сложный ответ, но я, честно говоря, не знаючто-нибудь намного менее сложное, что сработает. Если у вас есть почти любой разумный выбор в этом вопросе, я бы использовал что-то еще.на самом деле это набросок потока сознания - ни один код не был скомпилирован, а тем более реально протестирован.Я не вижу веской причины, по которой общая идея не должна работать, но может потребоваться немало усилий, чтобы воплотить ее в реальность (например, я в основном пренебрегал управлением массивом callback_functions).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...