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属性。这两个属性结合在一起,就像屏幕FormCountForms属性是一对一样。您的代码将表单属性与屏幕属性混合在一起。

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

此外,您绝对应该从查询管理器的数量中减去 1,否则这意味着您没有正确跟踪您拥有的查询管理器的数量。您在大多数代码中看到的“-1”在那里是因为 Delphi“for”循环的上限是inclusive。循环变量将从下限开始,循环将继续运行,直到变量超过上限。当列表中没有项目时,它可以帮助您推断基本情况下会发生什么。在那种情况下,循环根本不应该运行,对吧?因为那里什么都找不到。设置为从 " 0 to 0" 运行的循环将执行一次,因此上限必须为负数以防止循环运行。(这在文档中都有描述。)

至于为什么您的函数即使您认为它不应该返回空引用,我只能假设这是由于您的代码中的其他问题。也许您没有像您想象的那样循环遍历尽可能多的表单,或者您可能超出了查询管理器列表的末尾并获得了一些未定义的值。你的Result分配的位置是正确的,尽管你把它放在哪里并不重要,因为它被分配的唯一其他地方就在函数退出之前。


我看到你在 About.com 上询问过 MDI 儿童。在那里, Zarco Gajic通过给你这样的代码回答了你的问题:

for cnt := 0 to -1 + MDIChildCount do

虽然它是有效的代码,但它不是惯用的。我以前从未见过其他人写过这样的代码,所以明智的做法是不要养成这种习惯。当我们想要比某物少一时,我们不会在值中添加文字负一。相反,我们减去正数:

for cnt := 0 to MDIChildCount - 1 do

或者,我有时使用Pred标准函数:

for cnt := 0 to Pred(MDIChildCount) do
于 2009-11-16T22:38:08.663 回答
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 的,因此使用某物的计数会给你一个太多。

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 回答
1

它返回nil是因为您实际上并没有在循环中访问应用程序中的每个表单,这与是否在循环中使用 -1 无关(在正确编写的版本中,您必须这样做)。

您不会访问每个表单,因为您正在循环浏览表单的应用程序列表,其中包含 MDIChildren非 MDI 表单。但是您用来决定要查看多少个表单的值是 MDIChildCount。该数字仅包括 MDIChildren。因此,如果您的应用程序有 7 个表单,其中 4 个是 MDI 子级,那么您只查看 7 个表单中的前 4 个(嗯,5 个因为循环问题)。如果您想要的表格是 6 号或 7 号(很可能),您将永远无法达到它。

另外,我看不到在表单的循环内,您实际上的是表单的任何属性。

于 2009-11-16T23:53:21.953 回答