Форум: "Начинающим";
Текущий архив: 2011.03.06;
Скачать: [xml.tar.bz2];
ВнизПроцедура класса в SetTimer Найти похожие ветки
← →
Тима (2010-12-10 23:16) [0]Возможно ли использовать процедуру\метод собственного класса в апишном таймере, подсунув её последним параметром в SetTimer?
← →
Leonid Troyanovsky © (2010-12-10 23:33) [1]
> Тима (10.12.10 23:16)
> Возможно ли использовать процедуру\метод собственного класса
> в апишном таймере, подсунув её последним параметром в SetTimer?
Процедуру можно.
А метод зачем, если можно ссылку на объект.
--
Regards, LVT.
← →
Тима (2010-12-11 00:37) [2]Простите, если торможу, каким образом? Решение "в лоб"
SetTimer(0, IDTimer, FInterval, @TimerFunc);
не прокатывает. Переменную требует..
← →
Германн © (2010-12-11 02:08) [3]
> не прокатывает. Переменную требует..
>
А можно обойтись без "домосканного" перевода ошибки?
Если "что-то не прокатывает", то нужно приводить в вопросе это что-то с указанием строки, на которой выдаётся ошибка. И с "дословным" цитированием самого сообщения об ошибке.
← →
Тима (2010-12-11 03:05) [4]А я думал, догадаетесь. Оказывается, это сложно :) Переменную требует - сие означает примерно "Variable required". Если немного подумать, а не сетовать сразу же на вопрошающего. Вот полный текст ошибок компилятора:
> [Error] MTModule.pas(133): Variable required
> [Fatal Error] Project1.dpr(11): Could not compile used unit
> "MTModule.pas"
← →
Тима (2010-12-11 03:10) [5]ЗЫ. Код, на который ругается, приведён выше. TimerFunc есть процедура моего класса, приводить полностью который смысла не имеет. Процедура объявлена так:
...
public
constructor Create;
destructor Destroy; override;
procedure TimerFunc;
...
TimerFunc - процедура, которая должна выполняться по таймеру, но из которой я должен иметь доступ к собственному классу, из-за чего стандартную stdcall-процедуру использовать не могу.
← →
Германн © (2010-12-11 03:21) [6]
> TimerFunc - процедура
В данном коде "TimerFunc" - это не процедура, а метод класса/формы.
> TimerFunc - процедура, которая должна выполняться по таймеру,
> но из которой я должен иметь доступ к собственному классу
В древнем Китае тебе уже давно бы отрубили голову. :)
← →
Тима (2010-12-11 03:25) [7]Ну ладно, голова пока цела. А что делать? Что, совсем никак нельзя получить доступ к классу из этой процедуры? Выхода иного, как создавать глобальную переменную с указателем на экземпляр класса, я не вижу. Есть ли решение красивее?
← →
Тима (2010-12-11 03:27) [8]
> А метод зачем, если можно ссылку на объект.
Поясните плиз, видимо, сказывается ночная работа над кодом :) Какую ссылку, куда... тфу...
← →
Германн © (2010-12-11 03:33) [9]
> Тима (11.12.10 03:25) [7]
> Тима (11.12.10 03:27) [8]
Сначала на [3] ответь.
Только строго.
← →
Тима (2010-12-11 03:46) [10]Я не знаю, как ещё строже. Не буду же приводить весь листинг. Хорошо. Давайте так.
Я создаю класс, у класса есть некий метод, который должен выполняться с заданной периодичностью по таймеру. Таймер создаю при помощи SetTimer в конструкторе класса. Вопрос. Могу ли я указать в качестве callback-функции этот самый метод моего класса? Метод является той же самой callback-функцией, только размещённой внутри моего класса. Т.е. так:TMyClass = class
protected
private
public
constructor Create;
destructor Destroy; override;
procedure TimerFunc(Wnd: hWnd; Msg, ID, Time: Cardinal); <-- вот эта callback-функция
end;
Я пытаюсь сделать так:SetTimer(0, IDTimer, FInterval, @TimerFunc);
Но получаю [Error] MTModule.pas(133): Variable required
← →
Германн © (2010-12-11 04:03) [11]
> Но получаю [Error] MTModule.pas(133): Variable required
>
Допрос партизана продолжается.
А на какой строке кода выдаётся эта ошибка?
> Я не знаю, как ещё строже. Не буду же приводить весь листинг.
Не надо весь листинг. Его никто читать "забесплатно" не будет.
Хотя бы три строки. До ошибки, с ошибкой, после ошибки. Далее посмотрим.
← →
Тима (2010-12-11 04:05) [12]
> А на какой строке кода выдаётся эта ошибка?constructor TMyClass.Create;
begin
inherited;
FInterval := 10000;
SetTimer(0, IDTimer, FInterval, @TimerFunc); <-- на этой
end;
← →
Anatoly Podgoretsky © (2010-12-11 10:21) [13]
> Тима (11.12.10 03:10) [5]
Это не процедура.
← →
Anatoly Podgoretsky © (2010-12-11 10:21) [14]
> Тима (11.12.10 03:46) [10]
Это не процедура.
← →
Anatoly Podgoretsky © (2010-12-11 10:23) [15]> Тима (11.12.2010 04:05:12) [12]
У тебя тут шесть строк, а просили ОДНУ!
Какая у тебя оценка по русскому языку?
← →
Плохиш © (2010-12-11 12:38) [16]
> Тима (11.12.10 03:05) [4]
>
> А я думал, догадаетесь.
А так сдесь игра в догадалки, дальше читать не стал.
← →
Anatoly Podgoretsky © (2010-12-11 15:23) [17]
> А я думал, догадаетесь.
Мы программисты, нам не положено.
← →
Юрий Зотов © (2010-12-11 15:41) [18]
> Тима (11.12.10 03:46) [10]
Наследуйте свой класс от TTimer, либо агрегируйте в него объект TTimer - и не будет никаких проблем. Глобальная переменная - тоже вариант, только лучше спрятать ее в секции implementation.
← →
_Юрий (2010-12-11 16:58) [19]
> Метод является той же самой callback-функцией
В общем то, не является
Метод - это пара "указатель на экземпляр, указатель на код".
В принципе, можно извратиться и передать туда метод (приведением типов), но во первых, метод не должен быть виртуальным или динамическим, во вторых, внутри метода нельзя будет обращаться к self, иначе получите AV.
Так что лучше сделать по человечески
← →
Leonid Troyanovsky © (2010-12-12 16:11) [20]
> _Юрий (11.12.10 16:58) [19]
> В принципе, можно извратиться и передать туда метод
Для подобных вещей принято использовать MakeObjectInstance.
Т.к. оно заточено под оконную процедуру, то проще ее и менять.
И еще, ИШ приводил ссылку на Чена (ЕМНИП), в которой обсуждались
возможные последствия посылок сообщений потоку,
см. 1 параметр SetTimer.
--
Regards, LVT.
← →
Тима (2010-12-14 12:21) [21]Спасибо Юриям - единственным, кто потрудился понял задачу и прочитал дальше. Леониду спасибо за 20 пост (понять можете, когда хотите!).
В итоге. Сделал наследованием, правда, пришлось многое в классе переписать. Также встречал в сети вариант с "переходником", передающим процедуру объекта в SetTimer, кому интересно, может прочитать здесь
> http://www.sql.ru/forum/actualthread.aspx?tid=217966
Но делать так не стал, ибо уже сделал наследованием. Но приём интересен, может, кому пригодится.
← →
Ega23 © (2010-12-14 17:05) [22]
> В итоге. Сделал наследованием,
Зачем?TMyObject := class (TObejct)
private
FTimer: TTimer;
procedure OnTimer(Sender: TObject);
function GetInterval: Integer;
procedure SetInterval(const Value: Integer);
public
constructor Create;
destructor Destroy; override;
procedure Start;
procedure Stop;
property Interval: Integer read GetInterval write SetInterval;
end;
procedure TMyObject.OnTimer(Sender: TObject);
begin
FTimer.Enabled := False;
try
ShowMessage("Bla-bla-bla");
finally
FTimer.Enabled := True;
end;
end;
constructor TMyObject.Create;
begin
inherited;
FTimer := TTimer.Create(nil);
FTimer.Enabled := False;
end;
procedure TMyObject.Start;
begin
FTimer.Enabled := True;
end;
procedure TMyObject.Stop;
begin
FTimer.Enabled := False;
end;
procedure TMyObject.SetInterval(const Value: Integer);
begin
FTimer.Interval := Value;
end;
function TMyObject.GetInterval: Integer;
begin
Result := FTimer.Interval;
end;
destructor TMyObject.Destroy;
begin
FTimer.Free;
inherited;
end;
← →
Leonid Troyanovsky © (2010-12-14 18:01) [23]
> Тима (14.12.10 12:21) [21]
> и прочитал дальше. Леониду спасибо за 20 пост (понять можете,
> когда хотите!).
А чего понимать, если можно и ссылку объект?
procedure TimerProc(wnd: HWND; msg: UINT; idEvent: UINT; dwTime: DWORD);
stdcall;
begin
TButton(idEvent).Caption := IntToStr(dwTime); // можно звать любой метод
end;
procedure TForm1.Button1Click(Sender: TObject);
begin
SetTimer(Handle, UINT(Button1), 1000, @TimerProc);
end;
procedure TForm1.Button2Click(Sender: TObject);
begin
KillTimer(Handle, UINT(Button1));
end;
--
Regards, LVT.
Страницы: 1 вся ветка
Форум: "Начинающим";
Текущий архив: 2011.03.06;
Скачать: [xml.tar.bz2];
Память: 0.5 MB
Время: 0.003 c