Top.Mail.Ru
Мастера DELPHI, Delphi programming community Титульная страница Поиск, карта сайта Написать письмо 
| Новости | Поиск | FAQ | Статьи | Книги | Новости VCL |
| Форумы ЧАТ | Орешник | KOL и MCK |
Форумы -» Основная («Начинающим»)/ Базы / WinAPI / Компоненты / Сети / Media / Игры / Corba и COM / KOL / FreePascal / .Net / Прочее / RSDN.ORG

« предыдущая ветвь | форум | следующая ветвь »

Процедура класса в SetTimer


Страницы:   1 2

Тима ©   (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'


Страницы:   1 2

Наверх

Титульная страница Поиск, карта сайта Написать письмо