-2

どのボタンがそれを呼び出すかに応じて TMenuItem タグが変化する単一の PopupMenu アイテムがあります。各ボタンには、独自の TEdit (ResultTFile1、ResultTFile2、および ResultTFile3) があります。これらの TEdit はフォーム デザイナで作成されます。

var
 TempResultFile : TEdit;
begin
 // Find the right TEdit
 case (Sender as TMenuItem).Tag of
  1: TempResultFile := ResultTFile1;
  2: TempResultFile := ResultTFile2;
  3: TempResultFile := ResultTFile3;
 end;

 // Call save function
 if (SaveDialog1.Execute) then TempResultFile.Text := SaveDialog1.FileName;
end;

しかし、うまくいきません。ダイアログは開きますが、実行後、FileName 変数は実際の TEdit.Text (ResultTFile1、ResultTFile2、および ResultTFile3) に渡されません。エラーはありません。何もありません。デバッガーは反応していないようですが、私が間違っている可能性があります。私がこれをよく理解していれば、値が実際の TEdit ではなく、TempResultFile に与えられているためです。TempResultFileがコンポーネントを指すようにコーディングするにはどうすればよいですか?

4

4 に答える 4

1

他の人が述べているように、あなたが示したコードでうまくいかないことは非常に多くあります。

1) にTMenuItem.Tag間違った値が含まれている可能性があります。

2)有効なポインターTempResultFileが割り当てられていない可能性があります。TEdit他の人が言ったことにもかかわらず、変数を初期化しないままにしておくと、アクセス違反が発生する可能性はありますが、発生することは保証されません。がTEdit正しく作成されていない場合、または解放されている場合、割り当てられているポインターが nil になる可能性もあります。使用しようとすると、AV が発生します。

3) SaveDialog1.Execute()False を返している可能性があります。これは、ダイアログをキャンセルした場合に発生しますが、ダイアログに内部エラーがある場合にも発生する可能性があります。状況によっては、 を使用CommDlgExtendedError()してその状態を確認できます。

4)SaveDialog1.FileNameが空ですSaveDialog1.Execute()。true が返された場合は発生しませんが、かなり最新の Delphi バージョンを使用し、Windows Vista 以降でアプリを実行し、ファイルシステム以外のファイルを選択した場合に発生する可能性があります。

デバッグ中に、これらすべての条件を確認していることを確認してください。

var         
  Item: TMenuItem;
  TempResultFile : TEdit;         
  S: String;
begin         
  Item := Sender as TMenuItem;

  case Item.Tag of         
    1: TempResultFile := ResultTFile1;         
    2: TempResultFile := ResultTFile2;         
    3: TempResultFile := ResultTFile3;         
  else
    raise Exception.CreateFmt('%s.Tag (%d) is not an expected value!', [Item.Name, Item.Tag]);
  end;         

  if TempResultFile = nil then
    raise Exception.Create('TempResultFile is nil!');

  if not SaveDialog1.Execute then
    raise Exception.CreateFmt('SaveDialog1.Execute returned false! Possible CommDlg error? (%d)', [CommDlgExtendedError()]);

  S := SaveDialog1.FileName;
  if S = '' then
    raise Exception.Create('SaveDialog1.FileName is empty!');

  TempResultFile.Text := S;
end;   

を使用する代わりにTMenuItem.TagTPopupMenu.PopupComponentプロパティはどのボタンが PopupMenu を表示したかを示します。そのボタンに対応するコンポーネントTButton.Tagを指すようにプロパティを設定すると、コンポーネントを探すためにプロパティを使用する必要がなくなります。TEditTMenuItem.TagTEdit

procedure TForm1.FormCreate(Sender: TObject);
begin
  ResultTButton1.Tag := NativeInt(ResultTFile1);
  ResultTButton2.Tag := NativeInt(ResultTFile2);
  ResultTButton3.Tag := NativeInt(ResultTFile3);
end;

procedure TForm1.MenuItemClick(Sender: TObject);
var 
  ResultTButton : TButton; 
  TempResultFile : TEdit; 
begin 
  ResultTButton := PopupMenu.PopupComponent as TButton; 
  TempResultFile := TEdit(ResultTButton.Tag); 
  if TempResultFile <> nil then begin
    if SaveDialog1.Execute then
      TempResultFile.Text := SaveDialog1.FileName; 
  end;
end; 
于 2012-08-02T19:00:05.373 に答える
1

コードをデバッグして問題を解決するには、コードを完全に変更します。コメントは、それぞれがどのように機能して問題を解決するのに役立つかを説明しています。

var
  TempResultFile : TEdit;
begin
  if SaveDialog1.Execute then    // Only try assignment if file chosen
  begin
    // Find the right TEdit
    // The default branch will be used if the wrong menu item is 
    // connected to the event, or you forgot to set the tag value
    case (Sender as TMenuItem).Tag of
      1: TempResultFile := ResultTFile1;
      2: TempResultFile := ResultTFile2;
      3: TempResultFile := ResultTFile3;
    else                     // If none of the above match
      raise Exception.CreateFmt('Invalid tag %d in %s', 
         [TMenuItem(Sender).Tag, TMenuItem(Sender).Name]));
    end;
    // At this point, we know TempResultFile has been assigned a value
    TempFileResult.Text := SaveDialog1.FileName;
  end
  else // User clicked cancel on SaveDialog1.
    ShowMessage('SaveDialog1.Execute returned False`);
end;

これはあなたを助けるいくつかのことを行います:

  • が表示されない場合はSaveDialog、メニュー項目に OnClick ハンドラーを割り当てていないことがわかります。

  • ユーザーが を選択CancelするSaveDialogと false が返され、その事実を示すダイアログが表示されます (問題を解消するため)。

  • ユーザーがファイルを選択すると、 に対して有効なTag割り当てが行われたかどうかがチェックされTMenuItem、忘れた場合は例外が発生します (無効なタグ値とクリックされたコンポーネントの名前が返されます)。

さらに、元の質問にあるものよりも安全なコードであり、タグがcaseステートメント内の値の 1 つではなく、 SaveDialog1.Executetrue を返す場合にアクセス違反が発生する可能性があります。TempResultFile(そのプロパティにアクセスするときに、何も割り当てられていない可能性がありTextます。)

何が間違っているのかを理解したら、最終的なものを削除できます

end
else 
  ShowMessage('SaveDialog1.Execute returned False`);
于 2012-08-02T21:00:47.450 に答える
-2

あなたはそれをこのように書くことができます:

begin
  if (SaveDialog1.Execute) then 
  begin
    case (Sender as TMenuItem).Tag of    
       1: ResultTFile1.text := SaveDialog1.FileName;    
       2: ResultTFile2.text := SaveDialog1.FileName;    
       3: ResultTFile3.text := SaveDialog1.FileName;   
    end;  
  end; 
end;
于 2012-08-02T15:56:44.433 に答える
-2

Well...there's really only one reason why your code doesn't work: TempResultFile is not being assigned, meaning the "case" statement is failing to find a match. Either:

  • Sender is not an instance of TMenuItem
  • Sender is not the instance of TMenuItem you're expecting
  • Sender is your TMenuItem but you're not properly assigning the tag

Each case is super-easy to verify. Get to work!

Oh, as an aside, proper defensive style would re-write that code as:

var
 TempResultFile : TEdit;
begin
 {$IFDEF DEBUG}
 // preconditions
 Assert(sender is TMenuItem) ;
 {$ENDIF}
 // Find the right TEdit
 case (Sender as TMenuItem).Tag of
     1: TempResultFile := ResultTFile1;
     2: TempResultFile := ResultTFile2;
     3: TempResultFile := ResultTFile3;
     else Assert(false,'Failed to locate the proper TEdit') ;
 end;

 // Call save function
 if (SaveDialog1.Execute) then 
     TempResultFile.Text := SaveDialog1.FileName;

end;

于 2012-08-02T22:01:35.513 に答える