Здесь ссылка объясняет, что вам нужно знать.
По сути, вам нужно либо поставить «нулевой хук», что вы уже знали, либо вам нужновставьте крючок "VCL colors", что составляет половину того, что вам не хватает.Другая половина - ваша проблема с нулевым указателем.
Чтобы производные TEdit (как и ваши) выглядели как стандартные цвета VCL, код, необходимый для работы с вашим элементом управления, выглядит следующим образом:
uses
Winapi.Messages,
Vcl.Controls,
Vcl.StdCtrls,
Vcl.Forms,
Vcl.Themes,
Vcl.Styles;
type
TEditStyleHookColor = class(TEditStyleHook)
private
procedure UpdateColors;
protected
procedure WndProc(var Message: TMessage); override;
constructor Create(AControl: TWinControl); override;
end;
implementation
type
TWinControlH= class(TWinControl);
constructor TEditStyleHookColor.Create(AControl: TWinControl);
begin
inherited;
//call the UpdateColors method to use the custom colors
UpdateColors;
end;
//Here you set the colors of the style hook
procedure TEditStyleHookColor.UpdateColors;
var
LStyle: TCustomStyleServices;
begin
if Control.Enabled then
begin
Brush.Color := TWinControlH(Control).Color; //use the Control color
FontColor := TWinControlH(Control).Font.Color;//use the Control font color
end
else
begin
//if the control is disabled use the colors of the style
LStyle := StyleServices;
Brush.Color := LStyle.GetStyleColor(scEditDisabled);
FontColor := LStyle.GetStyleFontColor(sfEditBoxTextDisabled);
end;
end;
//Handle the messages of the control
procedure TEditStyleHookColor.WndProc(var Message: TMessage);
begin
case Message.Msg of
CN_CTLCOLORMSGBOX..CN_CTLCOLORSTATIC:
begin
//Get the colors
UpdateColors;
SetTextColor(Message.WParam, ColorToRGB(FontColor));
SetBkColor(Message.WParam, ColorToRGB(Brush.Color));
Message.Result := LRESULT(Brush.Handle);
Handled := True;
end;
CM_ENABLEDCHANGED:
begin
//Get the colors
UpdateColors;
Handled := False;
end
else
inherited WndProc(Message);
end;
end;
Procedure ApplyVCLColorsStyleHook(ControlClass :TClass);
begin
if Assigned(TStyleManager.Engine) then
TStyleManager.Engine.RegisterStyleHook(ControlClass, TEditStyleHookColor);
end;
initialization
ApplyVCLColorsStyleHook(TwwDBComboDlg);
Ваша проблема с NIL заключается в том, что если у вас не включены темы VCL, то Engine равен nil, и вы должны проверить и просто вернуться из этого кода, не вызывая ту функцию, которую вы вызываете.Вот где вы можете включить темы, если вы их пропустили:
Интересная дополнительная информация: Получить VCL Styles использует библиотеку .Вот пример использования его для изменения цвета вещей:
TCustomStyleExt(TStyleManager.ActiveStyle).SetStyleColor(scEdit, clWindow);
TCustomStyleExt(TStyleManager.ActiveStyle).SetStyleFontColor(sfEditBoxTextNormal
,clWindowText);
Вы можете создавать стили, применять эти стили к конкретным элементам управления и даже расширять механизм создания тем, возможно, можно будет использовать стили VCLИспользует инструмент, чтобы получить желаемый результат, но он не будет тривиальным.