Forms Delphi-未显示TEdit标签(仅限Windows 7/Vista)

Forms Delphi-未显示TEdit标签(仅限Windows 7/Vista),forms,delphi,windows-7,repaint,Forms,Delphi,Windows 7,Repaint,我们在另一个窗体上插入了一些TEdit窗体,但在我更改窗口大小之前,它们的标签不会显示。这仅在Windows Vista/Windows 7上发生。Windows XP已正确标记了所有内容 我已经测试过重新喷漆/刷新(只是TEdit/所有表单等),没有结果 德尔菲7 谢谢你的回答 坏版本 正确版本 代码很快就会被添加:)可能是bug吗?在我的项目中,我基本上能够解决同样的问题。这似乎是一个绘画顺序问题。最终的解决方案是调用frame.Refresh。但是,要想找到合适的地方来进行刷新有点棘手

我们在另一个窗体上插入了一些TEdit窗体,但在我更改窗口大小之前,它们的标签不会显示。这仅在Windows Vista/Windows 7上发生。Windows XP已正确标记了所有内容

我已经测试过重新喷漆/刷新(只是TEdit/所有表单等),没有结果

德尔菲7

谢谢你的回答

坏版本

正确版本


代码很快就会被添加:)

可能是bug吗?

在我的项目中,我基本上能够解决同样的问题。这似乎是一个绘画顺序问题。最终的解决方案是调用
frame.Refresh。但是,要想找到合适的地方来进行刷新有点棘手,我尝试了几个地方,然后才找到了一个有效的地方。它对我起作用的地方是,在我选择在选项面板上显示哪一个嵌套帧并实际显示嵌套帧的方法中,调用
frame.Refresh位于围绕未正确绘制的标签的最内层框架上。在内部框架而不是整个窗口的框架上调用refresh似乎是关键

从您正在显示的屏幕截图来看,您可能有一个类似的复杂帧设置,其中可能有帧显示在帧的顶部,在最初显示帧后,这些帧可能会动态变化。这似乎是一开始会产生问题的设置,最初显示的帧似乎从未出现过问题

然而,需要注意的是,如果窗口移出屏幕或被重新调整大小,另一个窗口被拖到它前面,或者鼠标移到正在消失的按钮上,这些操作可能会导致问题自动重新出现。可能还有其他位置,例如在用于调整窗口大小的特殊处理程序中,或者在计时器上,您可以定期调用帧刷新,类似于针对ALT-Key错误提到的一些解决方案。问题的类型和解决方法似乎有一些重叠,但原因并不完全相同(无论Alt键如何,此错误似乎都会发生)

在FormShow上:

var
  i : Integer;
begin
   For i := 0 to (Form1.ComponentCount - 1) do
     begin
        If (Form1.Components[i].ClassType = TLabel) then
            TLabel(Form1.Components[i]).Refresh;
     end;
end;

只需运行此程序。

我得到了相同的结果,只是在应用程序主题化时它似乎是一个问题。如果没有主题化(即项目->选项->应用程序->外观->默认样式=窗口),则工作正常,无需刷新或重新绘制

似乎与TFrame类特别相关,因此我想知道关于重画处理程序的某些内容是否异常(与Invalidate相关)。ChangeNotify进程中的某些内容或VCL中的Windows消息泵可能无法在父控制链上运行,并以级联重新绘制的方式返回“无效”的所有内容

我成功尝试的另一个窍门是在一行中将host control Visible属性设置为False,然后在下一行将其设置为true,即:

procedure TFrame1.UpdatePanel;
  Panel1.Visible := False;
  Panel1.Visible := True;
end;
然后在需要正确图形的地方调用此方法


Panel1的所有其他子控件都画得非常完美。如果在修改某个子控件(如TEdit或TMemo)的内容时进行更新,则可能必须缓存文本光标的位置。与数小时寻找问题原因相比,这应该是微不足道的。可能通过查看冲突控制主机(如TPanel)上Visible属性的Setter方法的VCL源,可以深入了解为什么重绘和刷新在这种情况下似乎无法正常工作的总体问题。

实际上,它比目前介绍的任何解决方案都要简单得多。 唯一需要做的就是响应WM_UpdateUstate消息。 在表单中添加一个类似下面的过程:

...
  protected
  procedure WmUpdateUIState(var Msg: TMessage); message WM_UPDATEUISTATE;
...

procedure TForm1.WmUpdateUIState(var Msg: TMessage);
begin
  inherited;
  Invalidate;
end; { WmUpdateUIState }
完成了

在Windows 10 64位上测试

通过创建这样的单元,可以加快速度:

unit FixAltKeyForm;

interface

uses
  Windows, Messages, Classes, Forms;


type
  TForm = class(Forms.TForm)
  protected
    procedure WmUpdateUIState(var Msg: TMessage); message WM_UPDATEUISTATE;
  end; { TForm }

implementation

{ TForm }

procedure TForm.WmUpdateUIState(var Msg: TMessage);
begin
  inherited;
  Invalidate;
end; { WmUpdateUIState }

end.
procedure TButton.CNCtlColorBtn(var Message: TWMCtlColorBtn);
begin
    with ThemeServices do
    {
        if ThemesEnabled then
        begin
            DrawParentBackground(Handle, Message.ChildDC, nil, False);
            // Return an empty brush to prevent Windows from overpainting we just have created. 
        Message.Result := GetStockObject(NULL_BRUSH);
        end
        else
    }
    inherited;
end;

将该单元的名称添加到任何形式的接口会话的uses子句中,在该子句中需要此行为,并且您已经完成了。在uses子句中,只需确保在“Forms”后面加上设备名称。不需要创建包,也不需要安装任何东西。这就是我所说的可视化子类化,因为没有更好的术语。

使用windows主题运行时,TButton中存在错误。 您可以在StdCtrls.pas中搜索“ThemesEnabled”,删除/注释其所有相关分支,如下所示:

unit FixAltKeyForm;

interface

uses
  Windows, Messages, Classes, Forms;


type
  TForm = class(Forms.TForm)
  protected
    procedure WmUpdateUIState(var Msg: TMessage); message WM_UPDATEUISTATE;
  end; { TForm }

implementation

{ TForm }

procedure TForm.WmUpdateUIState(var Msg: TMessage);
begin
  inherited;
  Invalidate;
end; { WmUpdateUIState }

end.
procedure TButton.CNCtlColorBtn(var Message: TWMCtlColorBtn);
begin
    with ThemeServices do
    {
        if ThemesEnabled then
        begin
            DrawParentBackground(Handle, Message.ChildDC, nil, False);
            // Return an empty brush to prevent Windows from overpainting we just have created. 
        Message.Result := GetStockObject(NULL_BRUSH);
        end
        else
    }
    inherited;
end;

然后编译它,并用您的补丁版本替换lib/StdCtrls.dcu。

什么是TEdit表单?TEdit没有标签。你能给我们一些代码,最好是足够的源代码来复制。我和大卫一样感到困惑。。。你是说特拉贝雷迪特吗?我唯一可以补充的一点是,TLabel不是窗口控件,因此将出现在窗口控件后面。如果TLabel与TEDIT不共享同一父级,则您可能看不到它们。如果那是一个TPanel,他们都坐在你的屏幕截图上,那么确保Tlabel在该面板上,而不是表单上。你真的将一个表单插入另一个表单吗?或者您讨论的是tFrame对象吗?tFames非常特别(如果您更喜欢这个术语,可以使用bugy;),尤其是在旧的Delphi版本中。在该版本中,丑陋的“创建后调整窗口大小”技巧可能是解决类似您的问题的最佳方法:(.以文本形式查看DFM,并将DFM的内容粘贴到包含缺失标签的部分。是否为包含编辑的滚动框?还请按类列出缺失编辑的完整父链,直至顶部(一个表单包含一个表单、一个groupbox、一个panel、一个labels等等)这是一个开源应用程序,其源代码展示了相同的行为:特别是,例如,UFrameDefault上的标签不会在Vista上绘制,但是,如果拖动任务栏下的窗口并垂直向上拖动,有时它会重新绘制