为什么插入符号突然位于编辑字段中?

时间:2008-11-07 23:36:58

标签: delphi

我在Delphi 2006登录表单上有一个“用户名”TEdit。当应用程序启动时,系统会要求用户输入用户名。由于某种原因,TEdit得到了焦点并且插入符号位于其水平中心。只要输入任何东西,插入符号就会再次对齐,一切看起来都很正常。

奇怪的是,它并不总是这样。这种行为几年前突然开始(我相信我们当时仍然使用Delphi 6)。知道可能导致这种情况的原因吗?

其他信息(已被要求):

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

  • 更多信息(11月13日):
  • 插入符不完全居中,它几乎居中。
  • 目前它似乎只出现在DLL中。在常规可执行文件中使用相同的登录对话框并且没有显示那里的问题(虽然我相信它在某个时间确实存在)。
  • 编辑字段是密码编辑,OnChange处理程序仅设置该表单的整数字段,该编辑字段上没有其他事件处理程序。
  • 我添加了另一个简单的TEdit,它也是ActiveControl,以便在表单显示时具有焦点(与密码编辑一样)。我还删除了默认文本“Edit1”。现在该问题以同样的方式存在于该TEdit中。
  • 如果输入了一个字符或者我通过控件选项卡,“居中”插入符号将恢复正常 - 当我回到TEdit时,它看起来很正常。这与密码编辑相同。
  • 5 个答案:

    答案 0 :(得分:2)

    我在Delphi 2007中也有同样的问题,
    将TEdit放在一个模态形式中,双击一个Grid。

    我做了一些测试,从TSpeedButton启动相同的Form。 我注意到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。
    5. 这就是全部:您可以启动应用程序并双击网格单元格。 如果您将模态窗体拖离主窗体,则需要重新绘制网格,然后使插入符从模式窗体中消失(或者如果您非常幸运,则显示在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)。

    答案 1 :(得分:1)

    另外几个问题:

    1. 这个问题出在一台电脑或更多电脑上吗?
    2. 是在一个应用程序上还是在所有应用程序上发生?
    3. 仅在您的Delphi应用程序或所有应用程序上发生吗?
    4. 如果它只在一台电脑上,我认为这是一个奇怪的注册表设置。如果它在更多的PC上,但你只有一个delphi开发的PC,它仍然可能是一个注册表设置。但还有其他可能性。

      您可以尝试一些测试:

      1. 在dev pc上创建一个简单的应用程序并在另一个上运行它。这是否显示效果。
      2. 使用由Delphi创建但在另一台不显示效果的电脑上构建的应用程序,并在开发者电脑上运行,这是否显示效果?
      3. 我真的认为这是一个注册表设置。根据你给我的信息,它发生在自Delphi 6以来,并且仍在发生。 它也可以是一个语言环境设置,但它必须在更多的程序中发生。

        修改 感谢您的额外信息。 因此看起来问题可以被隔离到单个表单。但它发生在所有电脑上。

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

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

    答案 2 :(得分:0)

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

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

    答案 3 :(得分:0)

    我也注意到了richedits中的这种行为。

    我们的应用中的一个地方是双击网格,显示另一个包含RichEdit的屏幕。插入符号总是出现在Richedit中与双击网格的位置相同,即如果dblclick位于网格的第3行,则插入符号将在编辑时显示~3行。一旦按下一个键,插入符就会重置到左上角的正确位置。

    它不仅限于某种形式或个人电脑,因为它发生在所有开发者机器上以及客户机器上。 该应用程序最初是在Delphi 5中开发的,但在我们搬到D2006之前,问题没有发生(或者没有被发现)。

    这不是一个特别大的问题,只是......太刺激了。

    答案 4 :(得分:0)

    另一种解决方法:

    在显示第二个表单之前,请阻止第一个表单上的网格执行Paint操作。代码段如下。

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