Delphi - TEdit标签无法显示(仅适用于Windows 7 / Vista)

3
我们在另一个窗口中插入了几个TEdit表单,但是它们的标签直到我改变窗口大小才会显示出来。这只会在Windows Vista / Windows 7上发生。Windows XP则正确显示所有标签。
我已经尝试了重绘/刷新(仅针对TEdit / 整个表单等),但没有结果。
使用Delphi 7。
谢谢你的回答。
错误版本: enter image description here 正确版本: enter image description here 代码很快就会添加 :)

5
TEdit表单是一个用于接收用户输入的窗体控件,它没有标签。以下是一个示例代码,可以用来复制并实现:procedure TForm1.Button1Click(Sender: TObject); var Edit1: TEdit; begin Edit1 := TEdit.Create(Self); with Edit1 do begin Parent := Self; Left := 50; Top := 50; Width := 100; Height := 20; end; end;这段代码会在点击一个按钮时,在窗体上创建一个TEdit对象,并将其放置在(50,50)的位置,宽度为100,高度为20。 - David Heffernan
1
我和大卫一样感到困惑...你的意思是TLabeledEdit吗? 我能补充的唯一一点是,TLabels不是窗口化控件,因此会出现在窗口化控件后面。 如果TLabels与TEdits没有共同的父控件,则可能看不到它们。 如果这是你屏幕截图中它们都坐在的一个TPanel上,请确保TLabels在该面板上而不是窗体上。 - Jerry Gagnon
你真的把一个表单插入到另一个表单中了吗?还是你在谈论tFrame对象?tFrames非常特殊(或者如果你更喜欢这个术语的话,可以说是有bug的;)),尤其是在旧版本的Delphi中。在那个版本中,丑陋的“创建后调整窗口大小”的技巧可能是解决类似问题的最佳方法 :(. - knowledge stacker
将DFM视为文本,并粘贴仅包含缺失标签部分的DFM内容。它是一个包含编辑框的滚动框吗?同时,请按类别列出从缺失的编辑框到顶部的完整父级链(例如,一个窗体包含一个窗体,其中包含一个GroupBox,其中包含一个Panel,其中包含标签等)。 - Warren P
这里有一个开源应用程序,附带源代码,展示了相同的行为:https://sourceforge.net/projects/poptray/files/PopTray/3.2/ 特别是,例如uFrameDefaults上的标签在Vista上不会绘制,但是,如果将窗口拖到任务栏下方并垂直向上拖回,有时它会正确地重新绘制,但不是一致的。该表单上的按钮在Vista上也存在随机消失和出现的问题。此屏幕在XP上显示良好。 - Jessica Brown
显示剩余2条评论
6个回答


2
我成功地解决了我的项目中的相同问题。它似乎是绘图顺序的问题。最终的解决方法是在没有正确显示的框架上调用frame.Refresh;。但是,在找到适当的刷新位置之前,我尝试了几个位置,这有点棘手。对我有效的地方是,在我选择要在选项面板上显示和物理显示嵌套框架的方法中,在围绕未绘制正确的标签的最内部框架上调用frame.Refresh;。调用内部框架而不是整个窗口的框架似乎是关键。
从您展示的屏幕截图来看,您的设置可能类似于具有复杂帧的设置,其中可能会在帧上显示帧,并且在帧最初显示后可能会动态更改。这似乎是首先出现问题的设置,最初显示的帧似乎永远不会出现问题。
然而,需要注意的是,如果窗口移动到屏幕外或重新调整大小,另一个窗口被拖到其前面或鼠标悬停在消失的按钮上,这些操作可能会导致问题再次自发出现。可能还有其他位置,例如在窗口调整大小的特殊处理程序中等,或者在定时器上,在其中定期调用框架刷新,类似于ALT键错误的一些解决方案。问题类型和修复方法之间似乎存在一些重叠,但原因并不完全相同(此错误似乎无论Alt键如何都会发生)。

1
在使用Windows主题时,TButton存在一些错误。您可以在StdCtrls.pas中搜索'ThemesEnabled',删除/注释掉所有相关的分支,例如:
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。

0
{ Labels no Windows Vista, 7, 8 to Fix the problem, Delphi 7 32 bits }

在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;

只需运行这个。


0

我遇到了同样的问题,但只有在应用程序主题化时才会出现问题。如果取消主题化(即项目->选项->应用程序->外观->默认样式=Windows),它就可以正常工作,不需要刷新或重绘。

似乎与TFrame类有关,因此我想可能是重绘处理程序中的某些内容出了问题(与Invalidate有关)。VCL中的ChangeNotify过程或Windows消息泵中的某些内容可能没有沿着父控件链向上传递,并响应级联重绘,从而回流到“无效”的所有内容。

我尝试过的另一个方法是将主机控件的Visible属性设置为False,然后在下一行将其设置为True:

procedure TFrame1.UpdatePanel;
  Panel1.Visible := False;
  Panel1.Visible := True;
end;

然后在需要适当绘制的位置调用此方法。

Panel1的所有其他子控件都完美地绘制出来了。如果您的更新发生在修改TEdit或TMemo等子控件的内容时,可能需要缓存文本光标的位置。与寻找问题原因的几个小时相比,这应该是微不足道的。也许查看有问题的控件宿主(如TPanel)上的Visible属性的Setter方法的VCL源代码可以为解决在此情况下Repaint和Refresh似乎无法正常工作的整体问题提供一些见解。


0

实际上,它比迄今为止提出的任何解决方案都要简单得多。 唯一需要的是响应WM_UPDATEUISTATE消息。 在表单中添加以下过程:

...
  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.

将该单元的名称添加到希望出现此行为的任何窗体的接口会话的uses子句中,然后您就完成了。只需确保在uses子句中将单元的名称放在“Forms”之后即可。无需创建包或安装任何内容。这就是我所谓的视觉子类化,因为没有更好的术语。

我尝试了这个,但它不起作用。按Alt键仍然会使标签消失。 - Ross

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接