【问题标题】:Why is the caret suddenly centered in an edit field?为什么插入符号突然在编辑字段中居中?
【发布时间】:2010-09-21 09:37:34
【问题描述】:

我在 Delphi 2006 登录表单上有一个“用户名”TEdit。当应用程序启动时,用户被要求输入用户名。 TEdit 获得焦点,并且插入符号由于某种原因被放置在其水平中心。一旦键入任何内容,插入符号就会再次左对齐,一切看起来都很正常。

也很奇怪,它并不总是这样。这种行为是几年前突然开始的(相信当时我们还在用Delphi 6)。知道是什么原因造成的吗?

其他信息(已被要求):

  • 问题很普遍:D2006 和 D6(我相信),5 或 6 个 Delphi 实例在尽可能多的计算机上,所有应用程序都使用该登录表单。效果仅限于表单,但不会出现在其他 TEdit 上。
  • TEdit 没有填充空格(一开始这样做会很奇怪)。

  • 更多信息(11 月 13 日):
  • 插入符号未准确居中,它几乎居中。
  • 目前它似乎只出现在 DLL 中。常规的可执行文件中使用了相同的登录对话框,并且在那里没有显示问题(尽管我相信它有时会出现)。
  • 编辑字段是密码编辑,OnChange 处理程序仅设置该表单的整数字段,该编辑字段上没有其他事件处理程序。
  • 我添加了另一个普通的 TEdit,它也是 ActiveControl,以便在表单显示时具有焦点(与密码编辑一样)。我还删除了默认文本“Edit1”。现在问题以同样的方式出现在该 TEdit 中。
  • 如果输入了一个字符或者如果我通过控件切换,“居中”插入符号会恢复正常 - 当我返回 TEdit 时,它看起来很正常。密码编辑也是如此。
  • 【问题讨论】:

    • 你能提供给我们相关的pas和dfm文件吗?
    • 添加了更多问题,(我们正在取得进展)。

    标签: delphi


    【解决方案1】:

    另一种解决方法:

    在显示第二个表单之前,防止第一个表单上的网格执行 Paint 动作。代码 sn-p 如下。

    Gird.BeginUpdate;
    
    try
    
      //Show the second form here
    
    finally
    
      Grid.EndUpdate;
    
    end;
    

    【讨论】:

      【解决方案2】:

      我在 Delphi 2007 中也遇到了同样的问题,
      将 TEdit 放置在通过双击 Grid 调用的模态表单中。

      我做了一些测试,从 TSpeedButton 启动相同的表单。 我注意到 TEdit 的问题仅在网格聚焦时出现。

      经过更多测试后,问题似乎是 VCL 中的错误
      在 TCustomGrid.paint 中有一个 SetCaretPos 调用,即使网格不在活动窗体上。

            ../..
            Focused := IsActiveControl;
            if Focused and (CurRow = Row) and (CurCol = Col)  then
            begin
              SetCaretPos(Where.Left, Where.Top);          
              Include(DrawState, gdFocused);
            end;
            ../.. 
      

      上面的代码来自 Grids.pas 中的 TCustomGrid.paint 在此代码中,如果网格是父窗体的“activeControl”,则 Focused 设置为 true,代码不考虑窗体是否处于活动状态。

      然后,如果需要重新绘制网格,则使用网格坐标调用 setCaretPos,导致问题中提到的错误。

      这个错误很难注意到,因为在大多数情况下,插入符号只是从活动表单中消失,而不是在 TEdit 中间附近闪烁。

      重现错误的步骤:

      1. 启动新的 VCL 表单应用程序。
      2. 将 TStringGrid 添加到其中。
      3. 向应用添加第二个表单,其中只有一个 TEdit。
      4. 以主窗体 (unit1) 返回并从网格 DblClick 事件中调用 form2.showmodal。

      就是这样:您可以启动应用程序并双击网格单元格。 如果您将模态窗体拖离主窗体,则需要重新绘制网格,然后导致插入符号从模态窗体中消失(或者如果您非常幸运,它会出现在 TEdit 的中间)

      所以,我认为需要在 Grids.pas 中进行修复。

      在上面 grid.pas 的摘录中,我建议通过调用一个名为 IsFocusedControl 的新函数来替换函数 IsActiveControl 的调用:

      // new function introduced to fix a bug
      // this function is a duplicate of the function IsActiveControl
      // with a minor modification (see comment)
      function TCustomGrid.IsFocusedControl: Boolean;
      var
        H: Hwnd;
        ParentForm: TCustomForm;
      begin
        Result := False;
        ParentForm := GetParentForm(Self);
        if Assigned(ParentForm) then
        begin
          if (ParentForm.ActiveControl = Self) then
            //Result := True;            // removed by DamienD
            Result := ParentForm.Active; // added by DamienD
        end
        else
        begin
          H := GetFocus;
          while IsWindow(H) and (Result = False) do
          begin
            if H = WindowHandle then
              Result := True
            else
              H := GetParent(H);
          end;
        end;
      end;
      

      这个修复(在 Delphi2007 中制作)对我来说效果很好,但不是保证。
      (另外,do not modify directly units of the VCL)。

      【讨论】:

      • 刚刚测试过:这个问题在 D2009 中得到解决(我拥有但仍然不使用 D2009(我的应用程序中的 unicode 问题..))
      • DamienD,感谢您提出这个老问题。不幸的是,我肯定还涉及其他一些事情,因为我在这里不使用网格。不过,它可能是由类似的问题引起的。无法使用 D2009 进行测试,因为我没有它;-)
      【解决方案3】:

      我在 Richedits 中也注意到了这种行为。

      在我们的应用程序中,双击一个网格会显示另一个包含 RichEdit 的屏幕。插入符号似乎总是出现在 Richedit 中双击网格发生的相同位置,即如果 dblclick 位于网格的第 3 行,插入符号将出现在编辑中向下约 3 行。只要按下一个键,插入符号就会重置到左上角的正确位置。

      它不限于某种形式或 pc,因为它发生在所有开发人员机器和客户端机器上。 该应用程序最初是在 Delphi 5 中开发的,但直到我们迁移到 D2006 才出现(或没有注意到)问题。

      这不是一个特别大的问题,只是……烦人。

      【讨论】:

        【解决方案4】:

        你确定这是一个简单的 TEdit 吗?它可能用几个空格而不是空字符串来初始化。然后,onChange 处理程序可能会在您开始键入后立即删除空格。 TEdit 扩展可能将文本对齐设置为居中而不是左侧,并且仅在 onChange 上设置文本对齐。

        [编辑] 请显示 TEdit 的事件处理程序。

        【讨论】:

          【解决方案5】:

          还有几个问题:

          1. 这个问题是在一台电脑上还是在多台电脑上?
          2. 它发生在一个应用程序上还是在所有应用程序上?
          3. 是仅在您的 Delphi 应用程序上发生还是在所有应用程序上发生?

          如果它只在一台电脑上,我认为这是一个奇怪的注册表设置。如果它在更多的电脑上,但你只有一台德尔福开发电脑,它仍然可能是一个注册表设置。但还有其他可能性。

          你可以尝试一些测试:

          1. 在开发电脑上创建一个简单的应用程序并在另一台电脑上运行它。这是否显示效果。
          2. 使用Delphi创建但在另一台不显示效果的PC上构建的应用程序,并在dev PC上运行它,这是否显示效果?

          我真的认为这是一个注册表设置。根据您给我的信息,它从 Delphi 6 开始就发生了,并且仍在发生。 它也可以是一个区域设置,但它必须在更多程序中发生。

          编辑: 感谢您提供额外的信息。 所以看起来问题可以被隔离到一个单一的形式。但它发生在所有电脑上。

          您可以做的是删除编辑,然后重新添加一个新的。这样可以节省搜索奇怪的属性值。

          • TEdit 上是否存在可以解释效果的事件?
          • 设置了哪些属性值? (但我更喜欢看一下 dfm 和代码,因为这样我就可以重现效果。)

          【讨论】:

            猜你喜欢
            • 2014-06-28
            • 1970-01-01
            • 1970-01-01
            • 2012-01-03
            • 1970-01-01
            • 1970-01-01
            • 2010-12-29
            • 2019-11-26
            相关资源
            最近更新 更多