![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Процедура класса в SetTimer
Тима © (2010-12-10 23:16:00)Возможно ли использовать процедуру\метод собственного класса в апишном таймере, подсунув её последним параметром в SetTimer?
Leonid Troyanovsky (2010-12-14 18:01:00) [1]
> Тима (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.
Ega23 (2010-12-14 17:05:00) [2]
> В итоге. Сделал наследованием,
Зачем?
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;
Тима (2010-12-14 12:21:00) [3]Спасибо Юриям - единственным, кто потрудился понял задачу и прочитал дальше. Леониду спасибо за 20 пост (понять можете, когда хотите!).
В итоге. Сделал наследованием, правда, пришлось многое в классе переписать. Также встречал в сети вариант с "переходником", передающим процедуру объекта в SetTimer, кому интересно, может прочитать здесь
> http://www.sql.ru/forum/actualthread.aspx?tid=217966
Но делать так не стал, ибо уже сделал наследованием. Но приём интересен, может, кому пригодится.
Leonid Troyanovsky (2010-12-12 16:11:00) [4]
> _Юрий (11.12.10 16:58) [19]
> В принципе, можно извратиться и передать туда метод
Для подобных вещей принято использовать MakeObjectInstance.
Т.к. оно заточено под оконную процедуру, то проще ее и менять.
И еще, ИШ приводил ссылку на Чена (ЕМНИП), в которой обсуждались
возможные последствия посылок сообщений потоку,
см. 1 параметр SetTimer.
--
Regards, LVT.
_Юрий (2010-12-11 16:58:00) [5]
> Метод является той же самой callback-функцией
В общем то, не является
Метод - это пара "указатель на экземпляр, указатель на код".
В принципе, можно извратиться и передать туда метод (приведением типов), но во первых, метод не должен быть виртуальным или динамическим, во вторых, внутри метода нельзя будет обращаться к self, иначе получите AV.
Так что лучше сделать по человечески
Юрий Зотов (2010-12-11 15:41:00) [6]
> Тима (11.12.10 03:46) [10]
Наследуйте свой класс от TTimer, либо агрегируйте в него объект TTimer - и не будет никаких проблем. Глобальная переменная - тоже вариант, только лучше спрятать ее в секции implementation.
Anatoly Podgoretsky (2010-12-11 15:23:00) [7]
> А я думал, догадаетесь.
Мы программисты, нам не положено.
Плохиш (2010-12-11 12:38:00) [8]
> Тима (11.12.10 03:05) [4]
>
> А я думал, догадаетесь.
А так сдесь игра в догадалки, дальше читать не стал.
Anatoly Podgoretsky (2010-12-11 10:23:00) [9]> Тима (11.12.2010 04:05:12) [12]
У тебя тут шесть строк, а просили ОДНУ!
Какая у тебя оценка по русскому языку?
Anatoly Podgoretsky (2010-12-11 10:21:00) [10]
> Тима (11.12.10 03:46) [10]
Это не процедура.
Anatoly Podgoretsky (2010-12-11 10:21:00) [11]
> Тима (11.12.10 03:10) [5]
Это не процедура.
Тима (2010-12-11 04:05:00) [12]
> А на какой строке кода выдаётся эта ошибка?
constructor TMyClass.Create;
begin
inherited;
FInterval := 10000;
SetTimer(0, IDTimer, FInterval, @TimerFunc); <-- на этой
end;
Германн (2010-12-11 04:03:00) [13]
> Но получаю [Error] MTModule.pas(133): Variable required
>
Допрос партизана продолжается.
А на какой строке кода выдаётся эта ошибка?
> Я не знаю, как ещё строже. Не буду же приводить весь листинг.
Не надо весь листинг. Его никто читать "забесплатно" не будет.
Хотя бы три строки. До ошибки, с ошибкой, после ошибки. Далее посмотрим.
Тима (2010-12-11 03:46:00) [14]Я не знаю, как ещё строже. Не буду же приводить весь листинг. Хорошо. Давайте так.
Я создаю класс, у класса есть некий метод, который должен выполняться с заданной периодичностью по таймеру. Таймер создаю при помощи 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 03:33:00) [15]
> Тима (11.12.10 03:25) [7]
> Тима (11.12.10 03:27) [8]
Сначала на [3] ответь.
Только строго.
Тима (2010-12-11 03:27:00) [16]
> А метод зачем, если можно ссылку на объект.
Поясните плиз, видимо, сказывается ночная работа над кодом :) Какую ссылку, куда... тфу...
Тима (2010-12-11 03:25:00) [17]Ну ладно, голова пока цела. А что делать? Что, совсем никак нельзя получить доступ к классу из этой процедуры? Выхода иного, как создавать глобальную переменную с указателем на экземпляр класса, я не вижу. Есть ли решение красивее?
Германн (2010-12-11 03:21:00) [18]
> TimerFunc - процедура
В данном коде "TimerFunc" - это не процедура, а метод класса/формы.
> TimerFunc - процедура, которая должна выполняться по таймеру,
> но из которой я должен иметь доступ к собственному классу
В древнем Китае тебе уже давно бы отрубили голову. :)
Тима (2010-12-11 03:10:00) [19]ЗЫ. Код, на который ругается, приведён выше. TimerFunc есть процедура моего класса, приводить полностью который смысла не имеет. Процедура объявлена так:
...
public
constructor Create;
destructor Destroy; override;
procedure TimerFunc;
...
TimerFunc - процедура, которая должна выполняться по таймеру, но из которой я должен иметь доступ к собственному классу, из-за чего стандартную stdcall-процедуру использовать не могу.
Тима (2010-12-11 03:05:00) [20]А я думал, догадаетесь. Оказывается, это сложно :) Переменную требует - сие означает примерно "Variable required". Если немного подумать, а не сетовать сразу же на вопрошающего. Вот полный текст ошибок компилятора:
> [Error] MTModule.pas(133): Variable required
> [Fatal Error] Project1.dpr(11): Could not compile used unit
> 'MTModule.pas'