我有一个源自TMemo的控件。在我第一次使用Delphi XE7 VCL样式之前,它工作得很好。在Delphi XE7下,样式不会应用于控件的滚动条。如果使用黑暗的主题/风格,它看起来很可怕,而滚动条是银色的。
尝试创建一个我们可以重现错误的最小项目我发现了一些非常有趣的东西:添加/删除随机代码行(或DFM控件)会使错误出现/消失。
问题:究竟是什么导致了这种奇怪的行为以及如何解决这个问题?
http://s000.tinyupload.com/index.php?file_id=24129853712119260018
答案 0 :(得分:7)
为自定义类解决问题注册StyleHook
:
TMyMemo = class(TMemo)
strict private
class constructor Create;
class destructor Destroy;
end;
class constructor TMyMemo.Create;
begin
TCustomStyleEngine.RegisterStyleHook(TMyMemo, TMemoStyleHook);
end;
class destructor TMyMemo.Destroy;
begin
TCustomStyleEngine.UnRegisterStyleHook(TMyMemo, TMemoStyleHook);
end;
TStyleEngine.HandleMessage
函数中存在错误,特别是部分试图找到合适的StyleHook
类来处理消息
if RegisteredStyleHooks.ContainsKey(Control.ClassType) then
// The easy way: The class is registered
LStyleHook := CreateStyleHook(RegisteredStyleHooks[Control.ClassType])
else
begin
// The hard way: An ancestor is registered
for LItem in RegisteredStyleHooks do
if Control.InheritsFrom(LItem.Key) then
begin
LStyleHook := CreateStyleHook(Litem.Value);
Break;
end;
如果StyleHook
注册了确切的类,则没有问题,并且将返回适当的StyleHook
类。然而,“艰难的方式”部分是有缺陷的。它将尝试查找已注册StyleHook
的类祖先。但它会回归它所遇到的第一个祖先。如果它首先找到TEditStyleHook
(已注册TCustomEdit
类),则会使用该TMemoStyleHook
而不是TEditStyleHook
。由于RegisteredStyleHooks
不知道如何处理滚动条问题。
有缺陷行为的随机性是由TClass
存储的方式决定的。它们存储在密钥为TClass
的字典中。并且顺序由type
TStyleHelper = class(TCustomStyleEngine)
public
class function GetClasses: TArray<TClass>;
end;
class function TStyleHelper.GetClasses: TArray<TClass>;
begin
Result := Self.RegisteredStyleHooks.Keys.ToArray;
end;
procedure TForm1.Button1Click(Sender: TObject);
var
LItem: TClass;
Classes: TArray<TClass>;
begin
Classes := TStyleHelper.GetClasses;
for LItem in Classes do
MyMemo1.Lines.Add(LItem.ClassName);
end;
哈希确定,该哈希基本上是指向类信息的指针,并且可以在您更改代码时更改。
问题报告为RSP-10066,并且附加项目可以重现它。
借助以下代码,您可以轻松查看在添加/删除代码和/或其他控件时注册类的顺序如何变化。
{{1}}