Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2011.03.06;
Скачать: CL | DM;

Вниз

Процедура класса в 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;
Скачать: CL | DM;

Наверх




Память: 0.53 MB
Время: 0.011 c
13-1126779474
_Alexander_
2005-09-15 14:17
2011.03.06
EhLib: DBGridEh ругается на отстутсвие gstNone


15-1290461384
Юрий
2010-11-23 00:29
2011.03.06
С днем рождения ! 23 ноября 2010 вторник


3-1246532222
Дмитрий Белькевич
2009-07-02 14:57
2011.03.06
Out of memory в результате фетча большого числа записей.


2-1292048365
SIV5000
2010-12-11 09:19
2011.03.06
TIcon SetSize


15-1290554696
Дмитрий С
2010-11-24 02:24
2011.03.06
Для какого имени лучше купить сертификат.