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
基本的にクラス情報へのポインターであり、コードを変更すると変更されるハッシュによって決定されます。
問題は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;