Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > Delphi программирование > Общие вопросы Delphi
Регистрация

Восстановить пароль

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 29.05.2007, 10:54   #1
Lexicss
Новичок
Джуниор
 
Регистрация: 29.05.2007
Сообщений: 2
По умолчанию Вызов функции по таймеру

Привет, народ! Вот тут упёрся в одну проблемку, может вы поможете разобрать и решить.
Работаю на Delphi 5 и вот наткнулся на такую ситуацию. Есть у меня одна функция и мне её надо вызвать спустя какой-то интервал времени, делаю это с помощью SetTimer. В чём странность? Так вот: в 98-ой винде работает всё нормально. В XP функция таймера срабатывает дважды, а в 2000-ой мало того что срабатывает функция дважды, так после второго завершения программа вылетает с исключением "Access violation", притом не важно что выполняется в функции(процедуре) вызываемой по таймеру.
Приведу приметивнейший пример

Код:
 
unit Main;
interface
uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs;
type
  TForm1 = class(TForm)
    procedure FormCreate(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;
var
  Form1: TForm1;
procedure MyFunc(hWnd: THandle; uMsg: DWord; idEvent: DWord; dwTime: DWord);
implementation
{$R *.DFM}
 
procedure TForm1.FormCreate(Sender: TObject);
begin
  SetTimer(0,0,5000,@MyFunc);
end;
procedure MyFunc(hWnd: THandle; uMsg: DWord; idEvent: DWord; dwTime: DWord);
begin
  if dwTime = 0
  then beep;
end;
end.
Проведя некоторые исследования, я заметил такую особенность, если число параметров в вызываемой функции не превышает 3, то такой ситуации не возникает(из ассемблерного кода видно, что если в функции большех трёх параметров, то 4-ый и последующие уже передаются не через регистры, а через стэк). Ещё одна особенность, если процедуру MyFunc вызывать с соглашение stdcall, то тоже всё нормально.
Очень важно узнать почему так? Может здесь какая-то несовместимость Delphi 5 и Windows 2000(и выше)?
И как тогда выкручиваться при использовании SetTimer в Delphi 5, так как программа должна быть универсальной и работать как под 98-ой, как под 2000-ой и др одинаково?

Как я понял : Моя процедура MyFunc является callback API-шной и следовательно нуждается в директиве stdcall. Если я понял что-то не так - поправьте, пожалуйста.
Но всё же остаётся открытым вопрос, почему в Windows 98 эта функция работатет нормально без stdcall, хоть в ней и больше 3-х параметров? Может ещё какие будут варианты объяснения кроме случайности? Если кто что толкового подскажет, буду признателен.
Lexicss вне форума Ответить с цитированием
Старый 29.05.2007, 14:41   #2
JTG
я получил эту роль
Старожил
 
Аватар для JTG
 
Регистрация: 25.05.2007
Сообщений: 3,694
По умолчанию

А что значит
if dwTime = 0 then beep; ???

Цитата:
dwTime
[in] Specifies the number of milliseconds that have elapsed since the system was started. This is the value returned by the GetTickCount function.
Когда он бипать-то будет тогда?

Вообще Х/З, попробуй передать ей хендл окна и timerID
пыщь
JTG вне форума Ответить с цитированием
Старый 29.05.2007, 16:29   #3
Wolfheart
Любитель
Пользователь
 
Регистрация: 29.05.2007
Сообщений: 16
По умолчанию

Дружище, ты создаешь таймер без родителя!
Пиши следующее:

const
TimerId = 1;

var
Time : Integer = 1000;

begin
SetTimer(Form1.Handle, TimerId, Time, @Func);
end;

И не забудь в своей callback-функции поставить stdcall.
Должно работать.
Хочешь рассмешить Бога, расскажи ему о планах на завтра…
Wolfheart вне форума Ответить с цитированием
Старый 30.05.2007, 13:57   #4
Lexicss
Новичок
Джуниор
 
Регистрация: 29.05.2007
Сообщений: 2
По умолчанию

Цитата:
Сообщение от JTG Посмотреть сообщение
А что значит
if dwTime = 0 then beep; ???


Когда он бипать-то будет тогда?

Вообще Х/З, попробуй передать ей хендл окна и timerID
if dwTime = 0 then beep - это просто случайна строка кода, что бы функция пустой не была. на самом деле здесь должен быть листинг кода того что будет выполняться в функции, но я его не писал, это не нужно. TimerID тож в данном случае нет необходимости.


Насчёт stdcall. Да, всё работает, единственно меня интересует, почему? Потомучто моя MyFunc является API-шной функцией?

И ещё вопрос, почему в 98-ой винде всё работает нормально без stdcall?
Lexicss вне форума Ответить с цитированием
Старый 30.05.2007, 22:47   #5
Wolfheart
Любитель
Пользователь
 
Регистрация: 29.05.2007
Сообщений: 16
По умолчанию

С точки зрения системы - обыкновенная функция, в которую передается набор параметров в определённой последовательности (последовательность указывается явно с помощью stdcall). Вообще, отправляю автора вопроса к чтению MS SDK по Callback-функциям.
Хочешь рассмешить Бога, расскажи ему о планах на завтра…
Wolfheart вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц

Опции темы Поиск в этой теме
Поиск в этой теме:

Расширенный поиск


Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Вызов функции MarSeON PHP 2 01.08.2008 20:22
Visual Basic, рисование по таймеру Arion Помощь студентам 5 21.05.2008 12:42
Вызов процедуры при обьявлении функции ivannikov Общие вопросы Delphi 6 12.03.2008 13:20
Нечто подобное таймеру Артэс Общие вопросы C/C++ 8 11.02.2008 19:19
Автоматический вызов функции класса Flaton Общие вопросы C/C++ 4 19.10.2007 17:56