• 0
x11

InputQuery работает только на Windows

Вопрос

Пока всё было внутри модуля формы и внутри локальной процедуры, то запись добавлялась в таблицу.

Решил сделать обёртку и перенёс код в общий модуль, чтобы использовать в других местах.

На винде, всё норм, а на смартфоне ошибок нет, но запись не добавляется.

 

 

 

type
 TInputQueryResult = record
   Res: TModalResult;
   OutV: string;
 end;
...
...
...


function myInputQuery(const Caption, Text, AVal: String): TInputQueryResult;
Var
  val: array of string;
  r: TInputQueryResult;
begin
  SetLength(val, 1);
  val[0] := AVal;

  TDialogService.InputQuery(Caption, [Text], Val,
      procedure(const AResult: TModalResult; const AValues: array of string)
        begin
          case AResult of
            mrOk:
              begin
                R.Res := mrOk;
                R.OutV:= AValues[0];
              end;

            mrCancel:
              begin
                R.Res := mrCancel;
                R.OutV:= '';
              end;
          end;
        end
  );

  result := r;
end;

 

Использование

 

procedure TfmReference.actInsertExecute(Sender: TObject);
Var
  sTableName, cap: string;
  res: TInputQueryResult;
begin
  cap := comboRefType.Items[comboRefType.ItemIndex];

  res := myInputQuery(cap, 'Добавить: ', '');
  if res.Res = mrOk then
  begin
    if not res.OutV.IsEmpty then
    begin
      sTableName := GetTableName;
      sqlInsert.sql.Text := Format('Insert into %s (name) values(' + QuotedStr(res.OutV) + ')', [sTableName]);
      sqlInsert.Execute;
      if sqlInsert.Transaction.Active then sqlInsert.Transaction.Commit;
      actRefreshExecute(nil);
    end;
  end;
end;

 

Изменено пользователем x11

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

13 ответов на этот вопрос

  • 0

Решил проблему так:

 

добавил пару строк

  while r.Res = mrNone do // wait for modal result
    Application.ProcessMessages;

 

и получилось:

function myInputQuery(const Caption, Text, AVal: String): TInputQueryResult;
Var
  val: array of string;
  r: TInputQueryResult;
begin
  SetLength(val, 1);
  val[0] := AVal;

  TDialogService.InputQuery(Caption, [Text], Val,
      procedure(const AResult: TModalResult; const AValues: array of string)
        begin
          case AResult of
            mrOk:
              begin
                R.Res := mrOk;
                R.OutV:= AValues[0];
              end;

            mrCancel:
              begin
                R.Res := mrCancel;
                R.OutV:= '';
              end;
          end;
        end
  );

  while r.Res = mrNone do // wait for modal result
    Application.ProcessMessages;

  result := r;
end;

 

 

Я надеюсь, это нормально или это плохо?

Изменено пользователем x11

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
  • 0
6 часов назад, x11 сказал:

На винде, всё норм, а на смартфоне ошибок нет, но запись не добавляется.

вам знакомо non-blocking dialogs? курим мануальчик

Anatoliy понравилось это

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
  • 0

Да, я уже понял, что в этом дело.

Тут уже в другом вопрос: то, что я добавил

while r.Res = mrNone do Application.ProcessMessages;

это нормально или нельзя так?

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
  • 0

нельзя так

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
  • 0

т.е. придётся лепить тот старый овнокод в каждой процедуре :(

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
  • 0

Неужели никак нельзя придумать "обёртку" TDialogService.InputQuery?

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
  • 0

то, что вы не хотите принять принцип работы операционной системы, которая справедливо лишает "программеров" возможности одним окном убить всё вокруг, никак не повод помогать делать то, что не нужно делать

на мобильных ОС нет модальных диалогов таких как на десктопе.

что конкретно у вас не получается? после выполнения диалога программа придет туда, где у вас Case AResult of

там и размещайте код, который должен выполниться при возврате из диалога

можете заменить 

TDialogService.InputQuery(Caption, [Text], Val,
      procedure(const AResult: TModalResult; const AValues: array of string)
        begin
          ...
        end
  );

на 

procedure TForm1.InputDialogHandler(const AResult: TModalResult; const AValues: array of string);
begin
  case AResult of
  ...
end;

...
TDialogService.InputQuery(Caption, [Text], Val, InputDialogHandler);

в чем проблема-то?

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
  • 0

Да я всё понимаю и не против отсутствия модульных окон.

4 минуты назад, krapotkin сказал:

procedure TForm1.InputDialogHandler(const AResult: TModalResult; const AValues: array of string); begin case AResult of ... end;

 

Получается, что в каждой форме нужно лепить <TForm>.InputDialogHandler"? Просто это противоречит принципу ООП: один раз написал, много раз используй.

Изменено пользователем x11

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
  • 0

Мало того, в каждой форме и на каждый чих нужно создавать свой

TForm1.InputDialogHandler

?

 

Например, процедуры добавление, удаление и редактирование.

Нужно создавать три разных InputDialogHandler.

 

Это и так три разных процедуры, а получается, что нужно создать ещё по одной.

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
  • 0

ничего не понятно

раньше вы писали
if inputQuery then  SomeProcedure
сейчас надо писать
inputQuery(SomeProcedure) 
procedure SomeProcedure;
if Result=mrOK then
собственно вся разница
Одну строку добавили. Где if AResult

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
  • 0

В общем теперь так:

procedure TfmReference.InputDialogHandlerInsert(const AResult: TModalResult; const AValues: array of string);
begin
//запрос на добавление

  case AResult of
    mrOk:
      if not AValues[0].IsEmpty then
      begin
        sqlInsert.sql.Text := Format('Insert into %s (name) values(' + QuotedStr(AValues[0]) + ')', [GetTableName]);
        sqlInsert.Execute;
        if sqlInsert.Transaction.Active then sqlInsert.Transaction.Commit;
        actRefreshExecute(nil);
      end;//
  end;// case
end;

procedure TfmReference.InputDialogHandlerEdit(const AResult: TModalResult; const AValues: array of string);
Var
 id: integer;
begin
//запрос на редактирование

  case AResult of
    mrOk:
      if not AValues[0].IsEmpty then
        begin
          id := StrToIntDef(ListView1.Items[ListView1.Selected.Index].Objects.FindObjectT<TListItemText>('id').Text, -1);
          sqlInsert.sql.Text := Format('update %s set name = ' + QuotedStr(AValues[0]) + 'where id = ' + IntToStr(ID), [GetTableName]);
          sqlInsert.Execute;
          actRefreshExecute(nil);
        end;
  end;// case
end;


procedure TfmReference.MyInputCloseDialogProc(const AResult: TModalResult);
Var
 id: integer;
begin
// запрос на удаление
  if AResult = mrYes then
  begin
    id := StrToIntDef(ListView1.Items[ListView1.Selected.Index].Objects.FindObjectT<TListItemText>('id').Text, -1);
    sqlInsert.sql.Text := Format('delete from %s where id = ' + IntToStr(ID), [GetTableName]);
    try
      sqlInsert.Execute;
      actRefreshExecute(nil);
    except
      on e:exception do
      begin
        ShowMessage('Ошибка удаления. ' + e.Message + sLineBreak + sqlInsert.sql.Text);
      end;// on e:exception do

    end;// try
  end
end;

 

 

 

пример использования:

procedure TfmReference.actInsertExecute(Sender: TObject);
Var
  val: array of string;
  cap: string;
begin
// добавляем запись

  SetLength(val, 1);
  val[0] := '';
  cap    := comboRefType.Items[comboRefType.ItemIndex];

  TDialogService.InputQuery(cap, ['Добавить: '], Val, InputDialogHandlerInsert);
end;

procedure TfmReference.actEditExecute(Sender: TObject);
Var
  val: array of string;
  cap: string;
begin
// редактируем запись

  if not Assigned(ListView1.Selected) then
  begin
    ShowMessage('Выберите строку');
    exit;
  end;

  SetLength(val, 1);
  val[0] := ListView1.Items[ListView1.Selected.Index].Objects.FindObjectT<TListItemText>('name').Text;
  cap    := comboRefType.Items[comboRefType.ItemIndex];

  TDialogService.InputQuery(cap, ['Изменить: '], Val, InputDialogHandlerEdit);
end;
    

procedure TfmReference.actDeleteExecute(Sender: TObject);
Var
  id: integer;
begin
// удаляем запись
    
  if not Assigned(ListView1.Selected) then
  begin
    ShowMessage('Выберите строку');
    exit;
  end;

//  resDel := False;
  TDialogService.MessageDialog('Удалить выбранную строку?', TMsgDlgType.mtConfirmation, mbYesNo, TMsgDlgBtn.mbYes, 0,
    MyInputCloseDialogProc);
end;

 

 

 

Т.е., как видите, получается 6 процедур вместо трёх.

Изменено пользователем x11

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
  • 0

вы не очень внимательно читаете

best practice - это писать

ActInsert...
 if Inputquery() then ProcInsert()
ActEdit...
 if Inputquery() then ProcEdit()
ActDelete...
 if Inputquery() then ProcDelete()

и мы получаем ровно то же количество процедур

если же писать "простыней" в старом варианте

ActInsert...
If InputQuery() then
begin
  ...
end;


то это в точности соответствует

InputQuery(..., procedure (...)begin 
  if AResult=mrOk then
  begin
  end;
end)

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
  • 0

но всё равно, в каждой форме, где планируется использовать InputDialog, нужно создавать свой InputDialogHandler.

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Создайте аккаунт или войдите для комментирования

Вы должны быть пользователем, чтобы оставить комментарий

Создать аккаунт

Зарегистрируйтесь для получения аккаунта. Это просто!


Зарегистрировать аккаунт

Войти

Уже зарегистрированы? Войдите здесь.


Войти сейчас

  • Сейчас на странице   0 пользователей

    Нет пользователей, просматривающих эту страницу