Перейти к содержанию
Fire Monkey от А до Я
  • 0

TMsgDlg а ля .Sync


UFO 007

Вопрос

Желаю всем здравия, други мои.
Скультивировал тут намедни приблуду на базе ЕСП8266 и прикол в том, что на написание VCL-проги поддержки (с параллельной дошлифовкой прошивки) ушло пару-тройку дней (хоть в той же ХЕ2), а вот с Андрюхиной поддержкой - вторую неделю бьюсь (как рыба об лёд). Во-первых: возможность компилить под Андрюху появилась (по-моему) только в ХЕ5, но она с поставленной задачей если и справилась, то весьма и весьма дерьмовенько и, не испытывая судьбу с ХЕ6 и ХЕ7, скачал сразу аж ХЕ8 и о-ля-ля, но есть одна бЯда: на точки останова - ноль эмоций (т.е. отладка на RedMi4Pro - невозможна и как следствие - вместо Exception-мессагов типа нет ВаВай-пермишенсов или "память не может быть реад": выпадение через чёрный экран на рабочий стол - может lSuper чё-то нужное вырезал?) и как следствие - следующий шаг: 10.4.1 Сидней(от того же lSuper'a)... Но тут другая бЯда: функции ВаВайСкан и ВаВайКоннект не работают никак: отлаживай-не отлаживай, трассируй - не трассируй(тут Exception-мессаги изобилуют)... Но это - предыстория (с параллельным подвопросом: нет ли между ХЕ8 и Сиднеем (ведь как обычно - пока он не дойдёт до ипостаси где-то 10.4.5 - так и будет не одно, так другое дерьмецо подсовывать) какой-нить ХЕ9 или может где-то есть инструкции по настройке той же ХЕ8?), а суть вопроса темы - это: во-вторых... Так вот Во-вторых: (что под ХЕ8, что под Сиднеем) если процедура хочет что-то сообщить пользователю при чём не однократно, а раз эдак 5-6, то пользователь видит только 1-е из сообщений (при чём если кто-то из последующих более ресурсоёмок по тексту, то видно только его затенённые края) и приходится 5-6 раз жать "ОК" (и тут принцип стека LIFO - никто не отменял: сообщение, появившееся последним, пропадает (так и оставшись непрочитанным) первым) и ЧЁ там процедура натворила? - Х его З: ведь там "внизу" могли быть не только сообщения, но и диалоги, а касание мимо окна диалога расценивается как No, Cancel, Abort и т.д. но прочитать что за вопрос был - уже не судьба... При курении справки на этот предмет (в разделе где-то/что-то/как-то так TDialogService) на поверхность выплыло, что метод .Sync (синхронно т.е. когда ShowMessage ждёт нажатия "ОК") работает только для Win/Lin/Mac/Огрызка, а для Андрюхи - только .АSync (поэтому и все 6 "форточек" появляются "синхронно", а процедура давно першагнула "end;"). Пришлось, слегка поЯndexив, изобретать собственный лИсАпед который я и хочу вынести на всеобщий(ее) суд(обозрение):

var
  Form2: TForm2;
  DlgMR: TModalResult;
  Step: byte = 0;
  tsWS, tsESP: TStringList;
  GlobIterator: integer = 0;

implementation

{$R *.fmx}

uses
  UMyMsgDlg;

procedure TForm2.MyShwMsg(Msg: string);
var
  mY: TMyMsgDlg;
Begin
  mY := TMyMsgDlg.Create(Msg, mbОК, self, nil, nil);
  mY.ShowMe;
End;

procedure TForm2.MyMsgDlg(Msg: string; AButtons: TMyMsgDlgBtn);
var
  mY: TMyMsgDlg;
Begin
  mY := TMyMsgDlg.Create(Msg, AButtons, self,
    procedure // btOkClick
    begin
      case AButtons of
        mbДаНет: DlgMR:= mrYes;
        mbОКейОтмена: DlgMR:= mrOk;
        mbПовторПрервать: DlgMR:= mrRetry;
      end;
      Inc(Step);
    end,
    procedure // btCancelClick
    begin
      case AButtons of
        mbДаНет: DlgMR:= mrNo;
        mbОКейОтмена: DlgMR:= mrCancel;
        mbПовторПрервать: DlgMR:= mrAbort;
      end;
      Inc(Step);
    end);
  mY.ShowMe;
End;

procedure TForm2.btTimerDlgClick(Sender: TObject);
begin
  DlgTimer.Enabled:= True;
  If Not WifiManager.isWifiEnabled then
  MyMsgDlg('При инициализации ВаФайМанагера оказалось, что РадиоМодуль обесточен.'+
           ' ТипО "Включить ВайВай?"', mbДаНет)
{  Else
  Begin // WiFi включен
    inc(Step); // вместо MyMsgDlg : без тимера
    FirstStep(mrNone);
  End;
}end;

Procedure TForm2.FirstStep(MesRes: TModalResult);
begin
    if MesRes = mrYes then
    Begin
      if WifiManager.setWifiEnabled(true) then
      MyMsgDlg('WiFi включен. Провести сканирование в пределах видимости '+
               'на предмет обнаружения наших железяк?', mbПовторПрервать);
    End Else // MesRes = mrNo
    Begin
    If WiFiScan('ESP-007', tsESP) = 0 Then // Step = 1
      MyMsgDlg('В эфире не обнаружено ни '+ #10 + #13 +
                'одной железяки. Продолжаем?', mbОКейОтмена); // Step =>> 2;       mbДаНет
    Else // если железяки морзируют тоннами
    if FileExists(TPath.Combine(TPath.GetSharedDocumentsPath, 'AP_Name.txt')) then ~ tstmp.ЛоадФромФиле
      if WiFiConnect(tstmp.Strings[0]) then
      Begin
        MyShwMsg('Сетевое Имя агрегата найдено в файле, соединение - установлено');
        DlgTimer.Enabled:= false;
      End; 
	Else //File_Not_Exists 'AP_Name.txt'
      MyMsgDlg('Файл AP_Name.txt не обнаружен - вычисляем сетевое Имя агрегата по алгоритму?', mbДаНет);
    End;

end;

Procedure TForm2.SecondStep(MesRes: TModalResult);
begin
  case MesRes of
    mrYes: Begin // вычисляем сетевое Имя агрегата по алгоритму
      if tsESP.Count < 2 then
      Begin
        MyMsgDlg('Необходимо подтвердить что найденная в эфире железяка - твоя', mbОКейОтмена);
      End
      else // tsESP.Count = 2 or > 2
      Begin
        WiFiConnect(tsESP.Strings[GlobIterator]);{GlobIterator = 0}   
		BuzTimer.Enabled := True;
        MyMsgDlg('Слышите звуковые сигналы с интервалом пол-секунды?111', mbДаНет);
      End;
    End;
    mrNo: Begin
      MyShwMsg('???');   DlgTimer.Enabled:= false;
    End;
    mrOk: Begin  // В эфире не обнаружено ни одной железяки. Продолжаем?
      if WiFiScan('ESP-007', tsESP) = 0 then // т.е. все=Выкл и ESP-007.1, и ESP-007.2, и ... ESP-007.999999
      Begin
        MyShwMsg('Включите агрегат в сеть 220в, нажмите на нём кнопку "WiFi" и повторите процедуру');
        DlgTimer.Enabled:= false;
      End
	else {"tsESP.Count <> 0"} Begin tsESP.Free; Dec(Step); FirstStep(mrNo); // MesRes = mrNo : WiFi включен
    End;
    mrCancel: Begin
      MyShwMsg('Перезапустите агрегат: 220в= Выкл/Вкл, нажмите на нём кнопку "WiFi" и повторите процедуру');
      DlgTimer.Enabled:= false;
    End;
    mrRetry:Begin // Провести сканирование в пределах видимости
      Dec(Step);// "синхронизация" тимера
      FirstStep(mrNo);
    End;
    mrAbort: Begin
      MyShwMsg('Ну-у-у... Так мы никогда не узнаем что в окрУге творится');
      DlgTimer.Enabled:= false;
    End;
  end;
end;

Procedure TForm2.ThirdStep(MesRes: TModalResult);
begin
  case MesRes of
    mrOk: Begin  {Необходимо подтвердить} WiFiConnect(tsESP.Strings[0]);  Sleep(50); BuzTimer.Enabled := True;
      MyMsgDlg('Слышите звуковые сигналы' + #10 + #13 +
               'с интервалом пол-секунды?222', mbДаНет);
    End;
    mrCancel: Begin
      MyShwMsg('А зря отказался : вдруг железяка, что в эфире - твоя?');
      DlgTimer.Enabled:= false;
    End;
    mrYes: SaveFile;//Слышите звуковые сигналы
    mrNo: Begin // He Слышите звуковые сигналы
      if GlobIterator < tsESP.Count - 1 then
      Begin Inc(GlobIterator);  Dec(Step);  if WiFiConnect(tsESP.Strings[GlobIterator]) then BuzTimer.Enabled := True;
        MyMsgDlg('Слышите звуковые сигналы с интервалом пол-секунды?333', mbДаНет);
      End
      Else
      Begin // список кончился
        MyShwMsg('Проверьте: агрегат запитан от 220в? Кнопка "WiFi" нажата? И повторите процедуру - '+
        'похоже, что звуковые сигналы звучали на соседской кухне...');
        DlgTimer.Enabled:= false;
        Step:= 255;
      End;
    End;
    mrRetry: Begin
      // Из SecondStep не вызывалось
    End;
    mrAbort: Begin
      // Из SecondStep не вызывалось
    End;
  end;

end;

Procedure TForm2.FourtStep(MesRes: TModalResult);
begin
  if MesRes = mrYes then // Слышите звуковые сигналы
  SaveFile;
end;

Procedure TForm2.SaveFile;
Var
  s: string;
Begin 
  BuzTimer.Enabled := False;
  s:= tsESP.Strings[GlobIterator];
  tsESP.Clear;
  tsESP.Add(s);
  tsESP.SaveToFile(TPath.Combine(TPath.GetSharedDocumentsPath, 'AP_Name.txt'));
  MyShwMsg('Спасибо. Агрегат детектирован, сетевое Имя сохранено.');
  DlgTimer.Enabled:= false;
End;

procedure TForm2.DlgTimerTimer(Sender: TObject);
begin
  if DlgMR <> mrNone then
  Begin
    Case Step of
      0: ;// ждём ответа юзверя    = mrYes
      1: FirstStep(DlgMR);
      2: SecondStep(DlgMR);
      3: ThirdStep(DlgMR);
      4: FourtStep(DlgMR);
    End;
    DlgMR:= mrNone;
  End;
end;

end.

Прошу учесть что это - лишь урезанный до нельзя (но чтобы можно было понять принцип синхронизации) скелет реально работающей проги. И да - за саму идею огромное спасибо krapotkin'у и ZuBy (исходники прикрепляю). И при чём можно было бы ещё чётче синхронизировать (но у меня почему-то не получилось: на 3-ем шаге - висюк):

Procedure TForm2.DlgTimerTimer(Sender: TObject);
Begin
  if DlgMR <> mrNone then
  Begin
    case Step of
	....
    End;
    DlgMR:= mrNone;
    if Step <> 2 then // 3-ка норм. не запускается
    DlgTimer.Enabled:= false;
  End;
End;

но тогда при каждом вызове MyMsgDlg надо запускать DlgTimer тогда будет работать так: например FirstStep вывесила окно диалога и завершила свою работу,  а таймер ежесекундно опрашивает результат диалога и как только результат стал вменяемым (а не mrNone) таймер запускает следующую (в соответствии с переменной Step) процедуру с полученным результатом и останавливается до следующего вызова MyMsgDlg.

З.Ы. И на закуску - второй подподвопрос: существует ли эмулятор Андрюхи который может  реально общаться с внешним миром через ВаВай-свисток например D-Link DWA125?

Заранее благодарен. 

 

0_для форума.zip

Изменено пользователем UFO_007
Ссылка на комментарий

Рекомендуемые сообщения

  • 0

Я пробовал полезную нагрузку сунуть в поток а гуй через sync и с ожиданием Event
как то так (псевдокод) :

TThread.CreateAnonThread(
begin
Event:=TEvent.Create;
try
  DoStep1;
  Event.Reset;
  TThread.Sync(
	begin
      ShowMessageAsync('Ахтунг!'
      begin
        Event.SetEvent;
      end)
    end);
  Event.WaitFor;
  DoStep2;....
fin
  Event.Free;
end;

end)


 

Ссылка на комментарий
  • 0
В 22.01.2021 в 07:01, Slym сказал:

сунуть в поток

А если диалогов - десяток, то и потоков столько же запускать? - стремновато как-то... А вообще - одел я этот скелет в симпатичный "пиджак" и ничего: очень даже работает, но только на RedMi4Pro(Андрюха 6.0), а на Honor8А(Андрюха 9.0) - отказывается... Вот и воюю теперь с SDK, но это - ужас отдельной темы.

Изменено пользователем UFO_007
Ссылка на комментарий
  • 0

1 рабочий поток.
но диалоги через Synchronize посылаются в главный поток
при этом рабочий засыпает на Event.WaitFor;
диалог закрывается и дергает Event.SetEvent;
 

у меня это тоже не как скелет, все кишки с евентами и синхронизами спрятаны, 1-3 скроки показать диалог... остальное бизнес логика
 

Ссылка на комментарий
  • 0
В 26.02.2021 в 05:30, Slym сказал:

все кишки с евентами и синхронизами спрятаны

"... Не будет ли любезен многоуважаемый джин ..." перевести это на Паскаль, ну или учебно-тренировочный *.pas (без бизнес-логики) приаттачить. 

 

Спаибо.

Ссылка на комментарий
  • 0
procedure SyncProc(Proc:TProc<TLightweightEvent>);
var
  Event:TLightweightEvent;
begin
  Event:=TLightweightEvent.Create;
  try
    Proc(Event);
    Event.WaitFor();
  finally
    Event.Free;
  end;
end;

function MessageDialogSync(const AMessage: string; const ADialogType: TMsgDlgType; const AButtons: TMsgDlgButtons;
      const ADefaultButton: TMsgDlgBtn; const AHelpCtx: THelpContext): TModalResult;
var LocalResult: TModalResult;
begin
  SyncProc(
    procedure(Event:TLightweightEvent)
    begin
      TThread.Synchronize(nil,
      procedure
      begin
        TDialogServiceAsync.MessageDialog(AMessage, ADialogType, AButtons, ADefaultButton, AHelpCtx,
          procedure(const AResult: TModalResult)
          begin
            LocalResult:=AResult;
            Event.SetEvent;
          end);
      end);
    end);
  result:=LocalResult;
end;

procedure TForm3.Button1Click(Sender: TObject);
begin
  TThread.CreateAnonymousThread(
    procedure
    begin
      while not TThread.CheckTerminated do
      begin
        TThread.Sleep(1000);
        if MessageDialogSync('Продолжать?', TMsgDlgType.mtInformation,[TMsgDlgBtn.mbYes, TMsgDlgBtn.mbNo],TMsgDlgBtn.mbYes,0)<>idYes then
          TThread.CurrentThread.Terminate;
      end;
    end).Start;
end;

поток тормозится до исполнения диалога... диалог показывается в главном потоке

Изменено пользователем Slym
Ссылка на комментарий
  • 0

Спасибо, конечно, огромное, но... из-за постоянного апдейта SDK (новому железу - новые библиотИки) вылазит конфликт, благодаря которому, свой "скелет" пришлось реализовывать на Яве. Хотя - может стОит присмотреться к Вашему "исходнику" (мож даже на яву "перевести")... А вообще в потоки я не въехал изначально: у ZX-Spectrum (если не изменяет память) были ещё и каналы - отсюда и путаница: придётся восполнять пробелы... Да и в Дэлфе упёрся в интерфейсы Явовских классов... Вот теперь и на распутье...

Ссылка на комментарий

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить на вопрос...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

  • Последние посетители   0 пользователей онлайн

    • Ни одного зарегистрированного пользователя не просматривает данную страницу
×
×
  • Создать...