1

ユーザーが情報を入力するためのいくつかのラベル付きの編集とラジオ ボタン (ラジオ グループにグループ化) と、エントリを保存するための [保存] ボタンを備えたフォームがあります。[保存] ボタンもフォームを閉じます。無効なエントリ (数字ではなく英字など) がある場合、または一部のエントリが空白のままになっている場合は、エラーを修正するようユーザーに警告し、空白の編集ボックスやチェックされていないラジオがなくなるまでフォームを閉じないようにしたいグループ。ユーザーに間違いを警告する messageDlg を発生させることにより、編集ボックスとラジオ グループごとに個別にエラー チェックを行います。ただし、ユーザーが間違いを修正せずにフォームを保存しようとすると、フォームを開いたままにして (閉じることができないようにして)、ユーザーに間違いを警告したいと考えています。すべてのエントリが有効で、チェックされていないラジオ グループがなくなった後にのみ、フォームを閉じることができるはずです。

以前のメッセージへのいくつかの返信に基づいて、次のコードを作成しました。1 つ目は 1 つの編集ボックス (いくつかあります) のデータ入力検証の例で、2 つ目は [保存] ボタンの OnClick イベントのコードです。

procedure TfrmAnalysisOptions.lbleConstraintsMaxChange(Sender: TObject);
var
  I: integer;
  Val, ValidEntry: string;
  Chr: char;
  RangeMin, RangeMax: Double;
  const Allowed = ['0'..'9', '.'];
begin

  Val := lbleConstraintsMax.Text;

      //initialize values    
  ValidEntry := '';
  ConstraintsMaxChange := '';

  //value can contain only numerals, and "."
    for I := 1 to Length(Val) do
     begin
       Chr := Val[I];
       if not (Chr in Allowed) then
       begin
     MessageDlgPos('The value entered for the max value of the ' +
               'constraint must contain only a numeral, a decimal ' +
               'point or a negative sign.',
            mtError, [mbOK], 0, 300, 300);
     Exit;

       end
       else ValidEntry := 'OK'; //validity check for this part

     end;

     //max value cannot be zero or less than the min value
    if not TryStrToFloat(Val, RangeMax) then Exit
    else if RangeMax = 0 then
    begin
       MessageDlg('Max value cannot be zero.', mtError, [mbOK], 0);
       Exit;
    end
    else if not TryStrToFloat(lbleConstraintsMin.Text, RangeMin) then Exit
    else if RangeMax < RangeMin then
      begin
    MessageDlgPos('Max value cannot be less than Min value.',
           mtError, [mbOK], 0, 300, 300);
    Exit;
      end

    else if (RangeMax < 0) then
      begin
    MessageDlgPos('A constraint cannot be negative.',
              mtError, [mbOK], 0, 300, 300);
    Exit;
      end

    //final validity check
    else if ValidEntry = 'OK' then ConstraintsMaxChange := 'OK'
    else MessageDlgPos('There was an unexpected problem with the ' +
               'value entered in the max constraints box.',
            mtError, [mbOK], 0, 300, 300);

end;

これは、[保存] ボタンの OnClick イベントのコードです。ご覧のとおり、いくつかのエントリの有効性をチェックしており、すべてが有効な場合 (つまり、対応する変数の値として「OK」がある場合) にのみ、フォームを閉じることができます。無効なエントリがある場合、messageDlg が正しく発生しています。ただし、エラーが修正されて [保存] ボタンが押された後も、messageDlg が発生し続けています。

procedure TfrmAnalysisOptions.btnSaveOptionsClick(Sender: TObject);
//save input and output options
begin
    //check if all the option questions have been answered
    if not ((ConstraintsMinChange = 'OK') and //validation of correct entry as it is being entered
    (ConstraintsMinExit = 'OK') and //validation of entry as user is moving to another entry after an incorrect entry
    //several other such 'OK's 
      then
      begin
    MessageDlgPos('There is an invalid entry on the form.  Please ' +
              'correct it.', mtError, [mbOK], 0, 300, 300);
    Exit;
      end


    else if //more messageDlgs if some other conditions are not met 

    else
      begin
      //save input and output options
      end;
     //finally if all the conditions are met, close the form 
    Close;
end;
4

3 に答える 3

3

フォームを自動的に閉じないようにボタンのModalResultプロパティを設定し、必要に応じてエントリを検証し、OK と検証された場合にのみ必要に応じてフォームのプロパティを設定します。例:mrNoneOnClickModalResult

procedure TfrmAnalysisOptions.btnSaveOptionsClick(Sender: TObject);
begin
  // check the entries as needed ...

  if (there is a validation error) then
  begin
    // do not close this form if there is an invalid entry
    MessageDlgPos('There is an invalid entry.  Please check and correct the entry.', mtError, [mbOK], 0, 300, 300)
    Exit;
  end;

  // save all the entries into different variables ...

  // now close the Form
  ModalResult := mrOk;
end;

更新:更新に基づいて、代わりにこれを試してください:

type
  TfrmAnalysisOptions = class(TForm)
  private
    //...
    ConstraintsMinOK: Boolean;
    ConstraintsMaxOK: Boolean;
    //...
  end;

procedure TfrmAnalysisOptions.lbleConstraintsMaxChange(Sender: TObject);
var
  I: integer;
  Val: string;
  Chr: char;
  RangeMin, RangeMax: Double;
begin
  //initialize values    
  ConstraintsMaxOK := False;

  Val := Trim(lbleConstraintsMax.Text);

  if not TryStrToFloat(Val, RangeMax) then
  begin
    MessageDlgPos('The value entered for the max value of the ' +
                  'constraint is not a valid numeric value.',
                  mtError, [mbOK], 0, 300, 300);
    Exit;
  end;

  //max value cannot be zero or less than the min value

  if RangeMax < 0 then
  begin
    MessageDlgPos('The value entered for the max value of the ' +
                  'constraint cannot be negative.',
                  mtError, [mbOK], 0, 300, 300);
    Exit;
  end;

  if RangeMax = 0 then
  begin
    MessageDlg('The value entered for the max value of the ' +
               'constraint cannot be zero.',
               mtError, [mbOK], 0);
    Exit;
  end;

  if not TryStrToFloat(lbleConstraintsMin.Text, RangeMin) then Exit;
  if RangeMax < RangeMin then
  begin
    MessageDlgPos('The value entered for the max value of the ' +
                  'constraint cannot be less than Min value.',
                  mtError, [mbOK], 0, 300, 300);
    Exit;
  end;

  //final validity check
  ConstraintsMaxChange := True;
end;

procedure TfrmAnalysisOptions.btnSaveOptionsClick(Sender: TObject);
begin
  if (not ConstraintsMinOK) or
     (not ConstraintsMaxOK)
    //or several other such 'OK's missing
  then
  begin
    MessageDlgPos('There is an invalid entry on the form.  Please ' +
                  'correct it.', mtError, [mbOK], 0, 300, 300);
    Exit;
  end;

  if //more messageDlgs if some other conditions are not met 
    //...
    Exit;
  end;

  //save input and output options...

  //finally if all the conditions are met, close the form 
  Close;
end;

または、ユーザーがまだデータを入力している間は動的検証を行わないでください。注意しないと、あらゆる種類の奇妙な副作用が発生する可能性があります。代わりに [保存] ボタンが押されるまで待ってから、すべてを検証します。

function ValidateNumeric(const S, Desc: String; var Value: Double): Boolean;
var
  I: Integer;
begin
  Result := TryStrToFloat(Trim(S), Value);
  if not Result then
  begin
    MessageDlgPos('The value entered for the ' + Desc +
                  ' is not a valid numeric value.',
                  mtError, [mbOK], 0, 300, 300);
    Exit;
  end;
end;

procedure TfrmAnalysisOptions.btnSaveOptionsClick(Sender: TObject);
var
  RangeMin, RangeMax: Double;
begin
  if not ValidateNumeric(lbleConstraintsMin.Text, 'min value of the constraint', RangeMin) then
  begin
    lbleConstraintsMin.SetFocus;
    Exit;
  end;

  if not ValidateNumeric(lbleConstraintsMax.Text, 'max value of the constraint', RangeMax) then
  begin
    lbleConstraintsMax.SetFocus;
    Exit;
  end;

  if RangeMax < 0 then
  begin
    MessageDlgPos('The value entered for the max value of the ' +
                  'constraint cannot be negative.',
                  mtError, [mbOK], 0, 300, 300);
    Exit;
  end;

  if RangeMax = 0 then
  begin
    MessageDlg('The value entered for the max value of the ' +
               'constraint cannot be zero.', mtError, [mbOK], 0);
    Exit;
  end;

  if RangeMax < RangeMin then
  begin
    MessageDlgPos('The value entered for the max value of the ' +
                  'constraint cannot be less than Min value.',
                  mtError, [mbOK], 0, 300, 300);
    Exit;
  end;

  //more validations...
  //more messageDlgs if some other conditions are not met ...

  //save input and output options...

  //finally if all the conditions are met, close the form 
  Close;
end;
于 2013-10-09T01:12:27.787 に答える
2

以下は、モーダルな結果と有効性をどのように扱うかの典型的なスキームです:

procedure TSomeModalForm.FormCloseQuery(Sender: TObject; var CanClose: Boolean);
begin
  if ModalResult = mrOK then
    begin
      CanClose := CheckValidity;
      if CanClose then
        CanClose := SaveData;
    end
  else if dtsPacket.Modified then
    CanClose := dtsPacket.Cancel
  else if dtsNote.Modified then
    CanClose := dtsNote.Cancel
  else
    CanClose := TRUE;
end;

CheckValidity関数は次のようになります。

function TSomeModalForm.DoCheckValidity: boolean;
var
  InvCnt: Integer;
begin
  Result := inherited;
  InvCnt := 0;
  //
  HighlightInvalidValue(not edClient.IsEmpty, edClient, InvCnt);
  HighlightInvalidValue(not edBranch.IsEmpty, edBranch, InvCnt);
  HighlightInvalidValue(not edDstClient.IsEmpty, edDstClient, InvCnt);
  HighlightInvalidValue(not edDstBranch.IsEmpty, edDstBranch, InvCnt);
  //
  Result := Result and (InvCnt = 0);
  if not Result then
    ShowInErrBox(1);
end;

このコードは、当社独自の非 VCL コントロールに基づいており、フォーム アセンダントでの検証サポートを前提としていますが、原則は明らかです。

于 2013-10-09T06:26:58.467 に答える
1

あなたの代わりに、私は問題に別の方法でアプローチします。[保存] ボタンがクリックされたときにチェックを実行し、データ入力の問題を一度に報告したいので、すべてのエラー メッセージを一度に返す検証プロセスを実行します。これにより、ユーザーは次に保存を試みる前に、すべての問題を確認して修正することができます。

次のようになります。

TMemoフォームにコンポーネントを追加し、非表示にして として整列させalTopます。このメモは、もしあれば、すべてのエラーメッセージを保持し、それらを表示します。すべての編集コントロールをパネルに配置し、alClient.

[保存] ボタンのOnClickイベント ハンドラーは次のようになります。

procedure TfrmAnalysisOptions.btnSaveOptionsClick(Sender: TObject);
begin
  ErrorsMemo.Lines.Clear; // clear previous messages
  GetErrorMessages(ErrorsMemo.Lines); // run our error check and retrieve messages
  ErrorsMemo.Visible := ErrorsMemo.Lines.Count>0; // if there are messages, show them
  if not ErrorsMemo.Visible then  // if no errors are showing, close
    Close;
end;

メソッドはすべてのチェックを保持し、次のGetErrorMessageようになります

procedure TfrmAnalysisOptions.GetErrorMessages(aMessageList: TStrings);
var
  I: Integer;
  Chr: Char;
begin
  // Here you put all the checks and add the error message to aMessageList,
  // for instance:

  // value can contain only numerals, and "."
  for I := 1 to Length(Val) do
  begin
    Chr := Val[I];
    if not (Chr in Allowed) then
      aMessageList.Add('The value entered for the max value of the ' +
                       'constraint must contain only a numeral, a decimal ' +
                       'point or a negative sign.');

 // Other validations follow here...

終わり;

ここでの主なアイデアは、確認プロセスをメッセージ表示から分離し、フォームを閉じるプロセスをより簡単にすることです。

于 2013-10-10T11:40:57.240 に答える