0

この関数の何が問題なのかを理解するのに少し苦労しています。-1 を使用する必要があるかどうかはわかりません。コードをどのように配置しようとしても、そうでない場合でも nil を返すようです。新鮮な目で誰か見てもらえませんか?また、結果 := nil が適切な場所にあるかどうかもわかりません。

function TFrmMain.FindQueryFrm(Server, Nickname: String): TFrmMessage;
var
  I,M: Integer;
begin
  ///  No -1 in the I loop - why? Because the first childform will not always be
  ///  of type TFrmMessage, which is what we're looking for.
  ///
  ///  Is this approach wrong?
  for I := 0 to MDIChildCount do
  begin
    if Screen.Forms[I] is TFrmMessage then
    begin
      ///  Same concept with -1 here (M Loop)... I need to check all forms
      ///  stored by QueryManager to see if their .MyServer and .QueryWith's match
      ///
      ///  Is the M Loop wrong?
      for M := 0 to QueryManager.Count do
      begin
        if UpperCase((QueryManager[M] as TFrmMessage).MyServer) = UpperCase(Server) then
        begin
          if UpperCase((QueryManager[M] as TFrmMessage).QueryWith) = UpperCase(NickName) then
          begin // BINGO!
            Result := (QueryManager[M] as TFrmMessage);
            exit;
          end;
        end; // HOST COMPARE
      end; // M Loop
    end; // Is TFrmMessage
  end; // I Loop
  Result := nil; // None Found
end;
4

4 に答える 4

8

フォームの を使用していると思われるように、MDI の子にのみ関心がある場合はMDIChildCount、フォームのMDIChildrenプロパティを使用します。FormCountこれらの 2 つのプロパティは、画面のとFormsプロパティが対になっているように、一緒に使用されます。あなたのコードは、フォームプロパティとスクリーンプロパティを混在させています。

begin
  for I := 0 to MDIChildCount - 1 do
  begin
    if MDIChildren[I] is TFrmMessage then
    begin

さらに、クエリ マネージャーの数から確実に 1 を引く必要があります。そうしないと、そもそもクエリ マネージャーの数を適切に追跡できていないことになります。ほとんどのコードで見られる「-1」は、Delphi の「for」ループの上限がinclusiveであるためです。ループ変数は下限から始まり、変数上限を超えるまでループが実行され続けます。リストに項目がない場合、基本ケースで何が起こるかを推論するのに役立つ場合があります。その場合、ループはまったく実行されるべきではありませんよね? そこには何も見つからないからです。" " から実行するように設定されたループ0 to 0は 1 回実行されるため、上限は負である必要があります。ループが実行されないようにします。(これはすべてドキュメントに記載されています。)

関数が null 参照を返すべきではないと考えている場合でも、なぜ null 参照を返すのかについては、コード内の他の問題が原因であるとしか考えられません。おそらく、思ったほど多くのフォームをループしていないか、クエリ マネージャー リストの末尾を超えて未定義の値を取得している可能性があります。割り当ての配置Resultは正しいですが、割り当てられる他の場所は関数が終了する直前だけであるため、どこに配置しても問題ありません。


About.comでMDIの子供について質問されたのを見ました。そこでは、 Zarco Gajic が次のようなコードを提供して、あなたの質問に答えました。

for cnt := 0 to -1 + MDIChildCount do

これは有効なコードですが、慣用的ではありません。そのようなコードを書いている人を見たことがないので、そのような習慣を身につけない方が賢明です。何かよりも 1 少ないものが必要な場合、値にリテラルの負の 1 を追加しません。むしろ、正の 1 を減算します。

for cnt := 0 to MDIChildCount - 1 do

または、Pred標準関数を使用することもあります。

for cnt := 0 to Pred(MDIChildCount) do
于 2009-11-16T22:38:08.663 に答える
1

ループ内のアプリケーション内のすべてのnilフォームに実際にアクセスしているわけではなく、ループ内でuse -1を使用するかどうかとは関係ありません(適切に記述されたバージョンでは、実行する必要があります)。

MDIChildrenフォーム非MDIフォームを含むフォームのアプリケーションリストをループしているため、すべてのフォームにアクセスしているわけではありません。ただし、これらのフォームの数を決定するために使用している値はMDIChildCountです。その数にはMDIChildrenのみが含まれます。したがって、アプリケーションに7つのフォームがあり、そのうち4つがMDIの子である場合、7つのフォームのうち最初の4つだけが表示されます(ループの問題のために5つ)。必要なフォームが6番または7番(おそらく)の場合、そのフォームに到達することはありません。

また、フォームのループ内で、実際にフォームのプロパティを参照している場所がわかりません。

于 2009-11-16T23:53:21.953 に答える
1

私が間違っていなければ、Screen.Formsも使用する必要がありますScreen.FormsCount
配列に N 個の要素があり、 index から始まる場合、0から列挙し0 .. N-1ます。
Array[N]間違っているでしょう。

以下のコードが機能するかどうかを確認してください。

//for I := 0 to MDIChildCount do
for I := 0 to Screen.FormsCount-1 do
begin
  if Screen.Forms[I] is TFrmMessage then
  begin
     for M := 0 to QueryManager.Count-1
     ...
于 2009-11-16T20:37:34.717 に答える
1

要するに:はい!Delphi の配列は 0 ベースであるため、何かのカウントを使用すると、1 が多すぎます。

MyArray[0] := 'first item';
MyArray[1] := 'second item';
for i:=0 to MyArray.count-1 do
begin
  ...
end;

マイナス 1 なしでカウント (2) を使用している場合、最後にループを通過すると、存在しない myarray[2] が要求されます。

要するに、次のような(よりクリーンな)構文を使用する必要があります。

for M := 0 to Pred(QueryManager.Count) do
于 2009-11-16T23:09:24.927 に答える