注册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
存储方式所致。它们存储在 key 所在的字典中TClass
。顺序由TClass
散列决定,散列基本上是指向类信息的指针,并且可以随着您更改代码而更改。
问题报告为RSP-10066,并且附有复制它的项目。
在以下代码的帮助下,很容易看到注册类的顺序在您添加/删除代码和/或其他控件时如何变化。
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;