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

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

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

Восстановить пароль
Повторная активизация e-mail

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

Ответ
 
Опции темы Поиск в этой теме
Старый 18.11.2009, 00:20   #1
Casper-SC
Форумчанин
 
Регистрация: 04.07.2007
Сообщений: 549
Вопрос Варианты реализации программы с использованием таймеров

1) Есть такой вопрос: Подскажите как лучше реализовать программу будильник. Он сидит в трее при нажатии правой кнопки
мышки вылазиет окошко с настройками, списком будильников и т.д. Так как в моей программе будет возможность создать
очень много будильников, просто напоминаний и напоминаний дней рождений (ну ещё немного дополнительных функций). То я
хочу как-то его оптимизировать, чтобы он не положил слабую систему. Даже если и не положит, хочу максимум оптимизации.
Есть варианты:
1) Настраиваю 1-ый будильник на срабатывание такого-то числа, через 15 дней. 2-ой через 5 часов. Ну и ещё штук 10 тоже
по разному. Далее эти будильники висят в опиративке и каждую секунду сверяют время, глупо? Думаю даже очень. Идея такая
1-ый проверяет время и дату, если срабатывать ему не сегодня, то интервал проверки 10 часов например. 2-ой проверяет и
узнаёт, что ему ещё 5 часов или скажем больше 4-ёх, то интервал 2 часа, потом ещё раз сверяет осталось ему 2 часа
интервал, час, потом каждые 10 минут, потом каждую секунду. А ещё можно чтобы был один отдельный таймер, который
получал бы каждую минуту или секунду время и каждый раз когда час становиться 0, то ещё и дату, но тогда у таймера
каждую секунду добавляется проверка сколько сейчас часов, что лучше проверка или просто получение даты? Потом все
будильники уже получают время и дату из переменных, куда записал их этот отдельный таймер.
2)У меня постоянно какая-то навязчивая мысль, что надо как можно меньше компонентов и таймеров и проверок в программу,
но не в ущерб функциональности, что таймеры сильно тормозят систему? Или проверка чего либо каждую секунду для
компьютера это вообще ничто? У кого какие идеи есть как лучше сделать?
Я как-то выкладывал будильник и меня попросили его уменьшить, ну я уменьшил, точнее теперь у него 2 размера. И
показывает текущее время так я и там постарался оптимизировать его вот код:
Код:
procedure TForm1.TimerSystemTimeTimer(Sender: TObject);
var H, M : word;
begin

  if TimerSystemTime.Tag = 0 then
  begin
  if SecondOf(Now) = 0 then
    begin
      ForTime := 0;
      TimerSystemTime.Tag := 1;
      TimerSystemTime.Interval := 60000;
      LabelHourNow.Caption := IntToStr(HourOf(Now));
      LabelMinNow.Caption  := IntToStr(MinuteOf(Now));
     { Memo1.Lines.Add('ТаймерСистэмТайм.Тэг присвоено 1');
      Memo1.Lines.Add('ТаймерСистэмТайм.Интервал присвоено 60000');
      Memo1.Lines.Add('ForTime присвоено 0');
      Memo1.Lines.Add(IntToStr(HourOf(Now))+':'+IntToStr(MinuteOf(Now))+':'+IntToStr(SecondOf(Now)));
      Memo1.Lines.Add('');   }
    end;
  end;
  if TimerSystemTime.Tag = 1 then //выполняется раз в минуту
  begin
    inc(ForTime);
   { Memo1.Lines.Add('ForTime достигло значения '+IntToStr(ForTime));
    Memo1.Lines.Add(IntToStr(HourOf(Now))+':'+IntToStr(MinuteOf(Now))+':'+IntToStr(SecondOf(Now))+'...');
    Memo1.Lines.Add('...');  }
    H := HourOf(Now);
    M := MinuteOf(Now);
    if H < 10 then LabelHourNow.Caption :='0'+IntToStr(H)
              else LabelHourNow.Caption :=IntToStr(H);
    if M < 10 then LabelMinNow.Caption :='0'+IntToStr(M)
              else LabelMinNow.Caption :=IntToStr(M);
    if ForTime = 30 then
    begin
      TimerSystemTime.Interval := 1000;
      TimerSystemTime.Tag := 0;
    {  Memo1.Lines.Add('ТаймерСистэмТайм.Тэг присвоено 0');
      Memo1.Lines.Add('ТаймерСистэмТайм.Интервал присвоено 1000');
      Memo1.Lines.Add('ForTime достигло значения 30');
      Memo1.Lines.Add(IntToStr(HourOf(Now))+':'+IntToStr(MinuteOf(Now))+':'+IntToStr(SecondOf(Now))+'...');
      Memo1.Lines.Add('...'); }
    end;
  end;
end;
У меня чё паранойя? ))))

Последний раз редактировалось Casper-SC; 18.11.2009 в 00:22. Причина: веская =)
Casper-SC вне форума Ответить с цитированием
Старый 18.11.2009, 01:26   #2
mihali4
*
Старожил
 
Регистрация: 22.11.2006
Сообщений: 9,201
По умолчанию

Извините, но это бред...
Хватит одного таймера на 1000 будильников.
Ставим один таймер с интервалом 1 секунда, который просто берет текущее системное время.
А дальше запускает процедуру проверки.
Что она делает? Она определяет, у какого из будильников (а это просто массив переменных) записанное в нем время-дата стало меньше системного.
И если такой найден - звоните, запускайте МР3, пусть у вас всплывает окошко с какой-то напоминалкой и т.д.
Идея ясна? Тогда - вперед, "под танки"
Только не надо, чтобы окошки "вылазили", ладно? Пусть они всплывают или просто появляются, но никак не "вылазят". Нет такого слова в русском языке. Это просто элементарная неграмотность...

Последний раз редактировалось mihali4; 18.11.2009 в 01:29.
mihali4 вне форума Ответить с цитированием
Старый 18.11.2009, 03:30   #3
Casper-SC
Форумчанин
 
Регистрация: 04.07.2007
Сообщений: 549
Вопрос

mihali4 у меня к Вам вопрос, я как понимаю вы в программировании нехило соображаете. Есть форма, на ней ListView и рядом кнопки "Новый", "Изменить" и т.д. При нажатии на кнопку "Новый" выполняется этот код (приведена основная часть):
Код:
procedure TForm1.BtnNewClockClick(Sender: TObject);
var Alarm : TClock;
begin
  FormNewClock := TFormNewClock.Create(self);
  FormNewClock.RadBut_1Raz.Checked := True; //если RadioButton - "Один раз"
  FormNewClock.ReserveVolume := FormNewClock.GetVolume; //зарезервировать текущую громкость звука
 try
  if FormNewClock.ShowModal = mrOK then //если в FormNewClock нажали "ОК" то выполняется код
  begin
    Alarm := TClock.Create;
    FormNewClock.SetData(Alarm); //получить настройки будильника из формы FormNewClock

if (Alarm.FMode = ONE_ALARM) then //если режим будильника выбран "Один раз" то...
begin
    with ListViewAlarm.Items.Add do
    begin
      Caption := Alarm.FTextMessage; //В ListView записать текст выводимого сообщения
      SubItems.Add(DateToStr(FormNewClock.DatePicker.Date)); //дата
      SubItems.Add(TimeToStr(FormNewClock.TimePicker.Time)); //время
      SubItems.Add(Alarm.FPeriodAlarm);//добавляется периодичность срабатывания
      Data := Pointer(Alarm); //связываем строку ListView с объектом
      Checked := True;
    end;
end;
Вот описание самого объекта, ещё не полностью сформировано (в ходе написания программы постоянно, что-то добавляется):

Код:
type
  TClock = class(TObject)
    MP : TMediaPlayer;
    FDateAlarm : TDateTime; //Дата срабатывания
    FTextMessage : string; //выводимое сообщение
    FMusicWay : string;
    FProgramWay : array [1..10] of string[255];
    FPeriodAlarm : string[15];
    FDayOfWeek : byte;      //Номер дня недели из ComboBox записывается
    FMonth : byte;               //Номер меяца из ComboBox записывается
    FMinuteEveryH : byte;   //Минуты каждого часа из Edit + UpDown
    FMode : TModeAlarmClock; //режим работы
    FChangeSound : boolean; //изменяется ли громкость вообще
    FMusicEnabled : boolean;//играть ли музыку вообще
    FVolume : LongWord;     //громкость
    FChangeVol : byte;      //время за которое будет прибавляться звук
    FTrackBar1Pos : byte;   //позиция TrackBar'a 1
    FTrackBar2Pos : byte;   //позиция TrackBar'a 2
    FHour, FMin, FSec, FMilSec : word;

    procedure SaveAlarmsToIni(Ini : TIniFile; Section : string);
    procedure LoadAlarmsToIni(Ini : TIniFile; Section : string);
    procedure SetText;
    function GetText : string;
   end;
Код нажатия на кнопке "Изменить":
Код:
procedure TForm1.BtnChancgeClockClick(Sender: TObject);
var
    Alarm : TClock;
    SavedIndex : integer;
begin
    FormNewClock := TFormNewClock.Create(self);
    FormNewClock.ReserveVolume := FormNewClock.GetVolume;
    try
    with ListViewAlarm do Alarm := TClock(ListViewAlarm.Items.Item[ItemIndex].Data);
      FormNewClock.GetData(Alarm);
      if FormNewClock.ShowModal = mrOK then //Происходит когда уже будильник настроили
      begin                                 //и нажали "ОК" на форме FormNewClock.
        FormNewClock.SetData(Alarm); //получить настройки будильника из формы FormNewClock
        with ListViewAlarm do
        begin
          SavedIndex := ItemIndex;

if (Alarm.FMode = ONE_ALARM) then
begin
    ListViewAlarm.Items.Item[ItemIndex].SubItems.Clear; //Очищаем строку
    with ListViewAlarm.Items.Item[ItemIndex] do

    begin
      Caption := Alarm.FTextMessage;
      SubItems.Add(DateToStr(FormNewClock.DatePicker.Date));
      SubItems.Add(TimeToStr(FormNewClock.TimePicker.Time));
      SubItems.Add(Alarm.FPeriodAlarm);//добавляется периодичность срабатывания
      Checked := True;
    end;
end;
Я всё это к тому выложил, судя по этим текстам в оперативной памяти висят все созданные пользователем будильники : TClock. А как тогда проверять их таймером одним? Или вообще кому не сложно, объясните как сделать проверку одним таймером на примере кода, желательно функционирующем с моим объектом.
Или как сделать такой массив, ведь заране неизвестно сколько будет создано будильников?
Casper-SC вне форума Ответить с цитированием
Старый 18.11.2009, 08:20   #4
Stilet
Белик Виталий :)
Старожил
 
Аватар для Stilet
 
Регистрация: 23.07.2007
Сообщений: 57,097
По умолчанию

Хм... Ты помоему малость не в ту степь попер.
У тя есть твой TClock где настроен будильник - некое время когда нужно чет сделать.
Прекрасно - прикручиваем к форме Alarms:TObjectList
Это будет массивом, хранящим все будильники.
Добавляем будильник:
Код:
Alarm := TClock.Create;
Alarms.Add(alarm);
Набиваем так массив будиль ников, а после в одном таймере проходимся по массиву:
Код:
procedure Timer1Timer(Sender:TObject);
var i:integer;
begin
 TTimer(sender).Enabled:=false;
 for i:=0 to Alarms.Count-1 do begin
  if TClock(Alarms[i]).FDateAlarm=now then begin
   Значит TClock(Alarms[i]) сейчас должен звонить.
  end;
 end; 
 TTimer(sender).Enabled:=True;
end;
Таймер ставь 1000 - пусть посекундно шарашит, ниче страшного.
И все.
То что я жирным выделил делать не обязательно. но я не знаю какие у тя действия будут по срабатыванию одного из будильников, потому на всякий случай таймер при проверке луче останавливать.
I'm learning to live...
Stilet вне форума Ответить с цитированием
Старый 18.11.2009, 13:34   #5
mihali4
*
Старожил
 
Регистрация: 22.11.2006
Сообщений: 9,201
По умолчанию

Цитата:
Сообщение от Stilet Посмотреть сообщение
я не знаю какие у тя действия будут по срабатыванию одного из будильников, потому на всякий случай таймер при проверке луче останавливать.
Дружище, современный комп (да и старинный тоже ) за секунду столько наворотит... Так что останавливать таймер... сомнительно...
Тут мы один нюанс упустили - по срабатыванию любого будильника ему нужно какую-то отметочку делать, что он уже сработал, иначе они как начнут хором каждую секунду вновь запускаться
mihali4 вне форума Ответить с цитированием
Старый 18.11.2009, 18:59   #6
Casper-SC
Форумчанин
 
Регистрация: 04.07.2007
Сообщений: 549
По умолчанию

Посмотрел английскую справку и понял почему у меня объект лист не хочет работать, подключил модуль Contnrs, всё заработало.

Я сделал так: Объявил Alarms : TObjectList; в разделе var в том, что перед implementation.
В событии формы OnCreate написал: Alarms := TObjectList.Create;

Далее я добавляю объект в массив Alarms.Add(Alarm); смотрите в коде: Правильно?

Код:
procedure TForm1.BtnNewClockClick(Sender: TObject);
var Alarm : TClock;
begin
  FormNewClock := TFormNewClock.Create(self);
  FormNewClock.RadBut_1Raz.Checked := True; //выбрать RadioButton - "Один раз"
  FormNewClock.ReserveVolume := FormNewClock.GetVolume; //зарезервировать текущую громкость звука
 try
  if FormNewClock.ShowModal = mrOK then //если в FormNewClock нажали "ОК" то выполняется код
  begin
    Alarm := TClock.Create;
    FormNewClock.SetData(Alarm); //получить настройки будильника из формы FormNewClock
    Alarms.Add(Alarm); //тут я добавляю в массив

if (Alarm.FMode = ONE_ALARM) then //если режим будильника выбран "Один раз" то...
begin
    with ListViewAlarm.Items.Add do
    begin
      Caption := Alarm.FTextMessage; //В ListView записать текст выводимого сообщения
      SubItems.Add(DateToStr(FormNewClock.DatePicker.Date)); //дата
      SubItems.Add(TimeToStr(FormNewClock.TimePicker.Time)); //время
      SubItems.Add(Alarm.FPeriodAlarm);//добавляется периодичность срабатывания
      Data := Pointer(Alarm); //связываем строку ListView с объектом
      Checked := True;
    end;
end;
Таким образом я удаляю и строку и объект из ListView, а из массива он тоже удаляется?
Код:
 procedure TForm1.BtnDeleteClockClick(Sender: TObject); //Нажатие на кнопке "Удалить"
begin
  with ListViewAlarm do
  begin
    TClock(Items.Item[ItemIndex].Data).Free;
    Items.Item[ItemIndex].Delete;
  end;
end;
К коду кнопки "Изменить" ничего не добавлял, так как там доступ к будильнику получаю не из массива, а через указатель. То есть сам будильник связан со строкой (ListView). Всё ли я правильно делаю? А то я просто не вкурсе, что там в памяти со всем этим делом происходит, компилирую ошибок пока не замечал.

Последний раз редактировалось Casper-SC; 18.11.2009 в 19:10.
Casper-SC вне форума Ответить с цитированием
Старый 22.11.2009, 10:44   #7
Casper-SC
Форумчанин
 
Регистрация: 04.07.2007
Сообщений: 549
По умолчанию

Всё оттестировал, многое дописал в программе, но оказалась одна беда, я из ListView удаляю строку освобождаю как я понял указатель, а не объект удаляю, даже из массива пытаюсь удалить его, только вообще понять не могу удаляется там чё нибудь или нет. Строки из ListView удалены, а будильники продолжают срабатывать.
Подскажите кто нибудь как правильно удалять объекты привязанные к определённой строке ListView и этот же объект к определённому индексу ObjectList.

Кнопка "копировать" будильник. Посмотрите тут всё верно?
Код:
procedure TForm1.BtnCopyClockClick(Sender: TObject);
var NewAlarm, Alarm : TClock;
    SavedIndex : integer;
begin
  FormNewClock := TFormNewClock.Create(self);
  FormNewClock.ReserveVolume := FormNewClock.GetVolume;
  with ListViewAlarm do Alarm := TClock(Items.Item[ListViewAlarm.ItemIndex].Data); 
  FormNewClock.GetData(Alarm); //получить значения у копируемого
будильника на форму FormNewClock
 
try
  if FormNewClock.ShowModal = mrOK then //Происходит когда уже будильник настроили
  with ListViewAlarm do
  begin
    SavedIndex := ItemIndex;
    NewAlarm := TCLock.Create;
    FormNewClock.SetData(NewAlarm); //получить настройки будильника
из формы FormNewClock
    //with ListViewAlarm do TClock(Items.Item[ListViewAlarm.ItemIndex].Data).Free;
    Alarms.Add(NewAlarm);
  if (NewAlarm.FMode = ONE_ALARM) then
begin
    with ListViewAlarm.Items.Add do
    begin
      Caption := NewAlarm.FTextMessage;
      SubItems.Add(DateToStr(FormNewClock.DatePicker.Date));
      SubItems.Add(TimeToStr(FormNewClock.TimePicker.Time));
      SubItems.Add(NewAlarm.FPeriodAlarm);//добавляется периодичность срабатывания
      Data := Pointer(NewAlarm);
      Checked := True;
      NewAlarm.ClockEnable;
    end;
end;
Кнопка "Удалить" будильники
Код:
procedure TForm1.BtnDeleteClockClick(Sender: TObject); //Нажатие на кнопке "Удалить"
begin
  with ListViewAlarm do
  begin
    TClock(Items.Item[ItemIndex].Data).Free;
    Items.Item[ItemIndex].Delete;
    //выделяет нижнюю строчку
    if Items.Item[Items.Count] <> Items.Item[0] then Items.Item[Items.Count-1].Selected := True;
  end;
end;
Помогите ничего понять не могу! Вообще проблемы с индексами, они путаются в ListView строках и в ObjectList так ладно путаются. Мож кто знает где можно про это почитать, да подробно. А то аж уже раздражают эти самоучители, всё чисто поверхностно, а нужно наоборот полное погружение от и до.

-----------------------------------------------------
Ну в очередной раз методом проб и ошибок, и чтением кривого перевода справки, X-Translator'ом, я наконец-то разобрался: Вот оно:
Это выполняется при копировании будильника:
Код:
 with ListViewAlarm do
  begin
   ...
    FormNewClock.SetData(NewAlarm);
    Alarms.Insert(ListViewAlarm.ItemIndex+1, NewAlarm);
    Label2.Caption := 'Индекс в массиве:'+ IntToStr(Alarms.IndexOf(Alarm));
...
------------------------------------------------------
Нда, щас сделал прогой ProcessExplorer такое дело: открыл окно наблюдения за процессом (так назовём), и смотрю сколько оперативки кушает моя программа, создаю будильник, заполняю текстовые поля очень длинным текстом и потом копирую штук 30 таких же будильников с заполнеными полями, получается килобайт 400 лишних начинает прога кушать, удаляю все будильники, проверка в массиве на срабатывание не даёт результата (что меня радует, этого я и добивался), но оперативка не освобождается!??? Я опять в тупике.

Последний раз редактировалось Casper-SC; 22.11.2009 в 12:54.
Casper-SC вне форума Ответить с цитированием
Старый 27.11.2009, 13:07   #8
Casper-SC
Форумчанин
 
Регистрация: 04.07.2007
Сообщений: 549
По умолчанию

Появился такой вопрос:
Всё, что в коде имеет в начале букву F, это поля объекта TClock

Есть TObjectList , TClock и TListView, когда создаю будильник нажатием на кнопку “Новый”, то создаётся будильник(как создаётся можно посмотреть выше):
Для полного понимания моего вопроса

Так выглядит проверка привязанных к каждой строке списка ListView будильников:

Код:
procedure TForm1.TimerAlarmsTimer(Sender: TObject);
var I : integer;
begin
  DateTimeNow := Now;
  DecodeDate(DateTimeNow, YearNow, MonthNow, DayNow);
  DecodeTime(DateTimeNow, HourNow, MinNow, SecNow, MilSecNow);
  for I := 0 to (ListViewAlarm.Items.Count - 1)  do
  begin
   if TClock(ListViewAlarm.Items.Item[I].Data).CheckTime then //НИЖЕ СМОТРИТЕ  ЧТО ПРОИСХОДИТ В CheckTime
   begin
     if MP.Mode = mpPlaying then 
     begin
       MP.Stop;
       MP.Close;
     end;
     FormMessage := TFormMessage.Create(Self);
     FormMessage.CreateMessage(TClock(ListViewAlarm.Items.Item[I].Data), ListViewAlarm.Items.Item[I]); 
     FormMessage.Show;
   end;
  end;
end;
Вот что происходит при TClock(ListViewAlarm.Items.Item[I].Data).CheckTime:

Код:
function TClock.CheckTime : boolean;  //возвращает True, если время совпало
var
    DayOfWeekNow : integer;
begin
  result := False;
  if FMode = ONE_ALARM then
  begin
    if not FHandled and (FYear = YearNow) and (FMonth = MonthNow) and (FDay = DayNow) and (FHour = HourNow) and (FMin = MinNow) and (FSec <= SecNow) then
    begin
        FToRemoval := True; //подлежит удалению после закрытия сообщения
        FHandled := True;
        result := True;
        //ShowMessage('Да время и дата совпадают "Один раз"');
        exit; //нет смысла дальше вести проверку, так как каждый будильник проверяется в отдельности
    end;
  end;
…
Далее при срабатывании будильника создаётся сообщение
FormMessage := TFormMessage.Create(Self);
FormMessage.CreateMessage(TClock(Li stViewAlarm.Items.Item[I].Data), ListViewAlarm.Items.Item[I]);
Эти строки взяты из примера выше

После того как пользователь нажимает в окошке сообщения на кнопку «Закрыть»
Происходит следующее:
Код:
procedure TFormMessage.SpeedButton1Click(Sender: TObject);
var
  I: Integer;
begin
  Form1.TimerAlarms.Enabled := False; //Отключаем таймер проверки будильников на срабатывание
  if Form1.MP.Mode = mpPlaying then //если музыка ещё играет отключаем
  begin
   Form1.MP.Stop;
   Form1.MP.Close;
  end;

  if ReserveVol <> 0 then
  begin
    waveOutSetVolume(WAVE_MAPPER, ReserveVol);
  end;
  for I := 0 to Form1.ListViewAlarm.Items.Count - 1 do  
  begin
    if TClock(Form1.ListViewAlarm.Items.Item[I].Data).FToRemoval then //проверяем подлежит ли будильник удалению
    begin
      with Form1.ListViewAlarm do
      begin
        Alarms.Delete(Alarms.IndexOf(TClock(Items.Item[I].Data)));
        Alarms.Pack;
        Alarms.Capacity := Alarms.Count;
        Items.Item[I].Delete;
      end;
    end;
  end;
  Form1.TimerAlarms.Enabled := True;
  FormMessage.Close;
end;
Тут проверяется подлежит ли будильник удалению, так как при срабатывании будильника в режиме «Один раз», то полю FToRemoval объекта TClock, присваивается True. И если такой будильник находиться в списке он удаляется, получается изменяется ObjectList.Count и ListView.Items.Count, становятся на 1 меньше, для этого и выключался таймер проверки времени срабатывания будильников, так как там тоже цикл :
for I := 0 to (ListViewAlarm.Items.Count - 1) do, если Count уменьшился будет ошибка в цикле, но её вроде нету, так как выключаю таймер (выше в коде всё это есть). Проблема в другом, если в списке ListView один будильник и он в режиме «Один раз», то такой код срабатывает, но если добавить например ещё один с режимом, тоже например «Каждый день», то вылетает ошибка. Помогите пожалуйста, я уже устал над ним колдовать, ничё не могу понять. И вообще зачем тут ObjectList? Я его использую вообще только… по сути вообще не использую, это видно в коде.

вот что написано при ошибке: Project AlarmClock.exe raised exception class EAccessViolation with message 'Access violation at address 004B778E in module 'AlarmClock.exe' Read of address 0000000C.'
и компилятор выделяет строку if TClock(Form1.ListViewAlarm.Items.It em[I].Data).FToRemoval then
Casper-SC вне форума Ответить с цитированием
Старый 27.11.2009, 13:33   #9
Stilet
Белик Виталий :)
Старожил
 
Аватар для Stilet
 
Регистрация: 23.07.2007
Сообщений: 57,097
По умолчанию

Что-то я запутался
у тебя если некой будильник одноразово стоит то по срабатыванию пусть он себя освобождает из списка в котором он находится.
I'm learning to live...
Stilet вне форума Ответить с цитированием
Старый 27.11.2009, 16:00   #10
Casper-SC
Форумчанин
 
Регистрация: 04.07.2007
Сообщений: 549
Восклицание

Цитата:
Сообщение от Stilet Посмотреть сообщение
Что-то я запутался
у тебя если некой будильник одноразово стоит то по срабатыванию пусть он себя освобождает из списка в котором он находится.
А как это сделать? Попробую объяснить пошагово:
запускается программа, создаю будильник, появляется он в списке ListView, работает таймер с интервалом 1000 мс. вот что происходит:
Код:
...
for I := 0 to (ListViewAlarm.Items.Count - 1)  do
  begin
   if TClock(ListViewAlarm.Items.Item[i].Data).CheckTime then 
...
Что происходит при CheckTime написано в прошлом моём сообщении
Если в списке 7 будильников, то цикл будет повторяться 7 раз, но если при срабатывании я сразу его освобожу внутри цикла, то ListViewAlarm.Items.Count уменьшиться на 1, а цикл попытается всё равно пройти 7 раз и выдаст ошибку. Поэтому я и намутил такое, чтобы при закрытии сообщения останавливался таймер проверки будильников и как я думаю (но не уверен) прерывал цикл. Потом запускается цикл который ищет помеченные будильники, то есть у кого из них поле FToRemoval равно True и удаляет их, после сразу включает таймер дальше проверять будильники.
Я пробовал сделать так:
К проверке, что написана выше в этом сообщении я добавлял
Код:
and TClock(ListViewAlarm.Items.Item[i].Data).FMode = ONE_ALARM
- получается: Если будильник сработал и он в режиме "Один раз", то прервать цикл (break) и удалить этот будильник, но если например у меня 10 одноразовых будильников, а цикл проверки запускается раз в секунду, то теряются 10 секунд, так как все остальные будильники не проверяются так как цикл прерывается, при некоторых обстоятельствах может из-за этого не сработать какой нибудь другой будильник.
Что посоветуете? И вообще нужен ли тут TObjectList? Мне посоветовали его использовать, только помоему от него лишних заморочек больше. И ещё я не написал код нажатия на кнопку "Новый" в прошлом моём сообщении из-за того, что сообщение превышало 5000 символов, а там по сравнению с тем кодом куда я сослался есть небольшое изменение, вот:

Код:
procedure TForm1.BtnNewClockClick(Sender: TObject);
var Alarm : TClock;
    IndexAlarms : integer;
begin
  FormNewClock := TFormNewClock.Create(self);
  FormNewClock.RadBut_1Raz.Checked := True;
  FormNewClock.ReserveVolume := FormNewClock.GetVolume; //зарезервировать текущую громкость звука
 try
  if FormNewClock.ShowModal = mrOK then //если в FormNewClock нажали "ОК" то выполняется код
  begin
    Alarm := TClock.CreateClock;
    FormNewClock.SetData(Alarm); //получить настройки будильника из формы FormNewClock
    IndexAlarms :=  Alarms.Add(Alarm);
    Label2.Caption := 'Индекс в массиве:'+ IntToStr(Alarms.IndexOf(Alarm));
if (Alarm.FMode = ONE_ALARM) then
begin
    with ListViewAlarm.Items.Add do
    begin
      Caption := Alarm.FTextMessage;
      SubItems.Add(DateToStr(FormNewClock.DatePicker.Date));
      SubItems.Add(TimeToStr(FormNewClock.TimePicker.Time));
      SubItems.Add(Alarm.FPeriodAlarm);//добавляется периодичность срабатывания
      Data := Pointer(Alarms[IndexAlarms]); //ВОТ ТУТ ИЗМЕНЕНИЕ
      Checked := True;
      Alarm.ClockEnable;
    end;
end;
...
Неужели никто не знает ответа? Я как не напишу вопрос, кто нибудь напишет ответ или тоже вопрос и всё тема умирает. Поскажите... плиззз... Если профессионалы не понимают моей писанины, тогда не удивительно, что у меня самого не получается разобраться со всем этим. Я просто не потомственный маг, чтобы понимать, что же происходит в данный момент в памяти, на конкретном шаге. Знаю отладка и т.д. Но при некоторых ситуациях это не помогает. АААААА (бабах себе в голову с двухстволки)

Последний раз редактировалось Casper-SC; 28.11.2009 в 06:30.
Casper-SC вне форума Ответить с цитированием
Ответ


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



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Написание программы с использованием функции Ветас Помощь студентам 5 08.11.2009 14:31
Прошу вашей помощи в реализации программы по динамическим структурам technotamplier Помощь студентам 0 25.10.2009 22:20
Программы с использованием операторов ветвления и циклов Vitas1234 Помощь студентам 1 11.06.2008 17:41
Программы с использованием операторов ветвления и циклов Vitas1234 Паскаль, Turbo Pascal, PascalABC.NET 9 11.06.2008 16:18