Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Начинающим";
Текущий архив: 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
2-1292199055
v2
2010-12-13 03:10
2011.03.06
ООП


15-1290500287
ixen
2010-11-23 11:18
2011.03.06
Странная проверка пароля в Firebird


2-1291905273
Vidog
2010-12-09 17:34
2011.03.06
Embedded-файлы


15-1290424828
stas
2010-11-22 14:20
2011.03.06
Хорошая книга по XCode


15-1290866571
VLK32
2010-11-27 17:02
2011.03.06
Очередной велосипед





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский