Ответ обновлен!Снова.
Ну, я не очень опытный пользователь стилей VCL
, но я постараюсь объяснить, что нужно сделать, чтобы избежать вашей проблемы.Прежде чем читать дальше, я должен сказать вам: нет способа отменить регистрацию любого стиля .
Стиль или нет Стиль
Во-первых, вы должны знать, что стили VCL
используют внутренний словарь FRegisteredStyles
для хранения всех зарегистрированных стилей.Стиль стал зарегистрирован после того, как TStyleManager.LoadFromFile(YourStyleName)
был вызван.К сожалению, стиль никогда не удаляется из словаря.
Не используйте UnregisterStyle
процедуру.Это не отменяет стиль вообще.Просто удаляет указанный стиль из списка доступных стилей.Таким образом, после вызова UnregisterStyle(YourStyle)
вы просто удаляете YourStyle
из внутреннего списка, а не из словаря, упомянутого ранее, и не можете установить этот стиль.
После успешного вызова UnregisterStyle()
вы можете вызвать LoadFromFile()
метод и спросить, почему приложение говорит:
Стиль «Изумруд» уже зарегистрирован.
Это происходит потому, что метод LoadFromFile()
загружает указанный стиль и проверяет его наличие во внутреннем словаре зарегистрированных стилей.Эта проверка всегда возвращает true
, поскольку UnregisterStyle()
процедура не удаляет указанный стиль из словаря.
То же самое относится и к свойству StyleNames
.Это свойство возвращает имя стиля, использует внутренний словарь FRegisteredStyles
для получения имени стиля с указанным индексом.
Если вы хотите узнать мое мнение, такое поведение стиля странно.Метод UnregisterStyle()
также должен удалить указанный стиль из словаря.Может быть, я ошибаюсь, но это настоящая ошибка.С другой стороны, ошибки нет - вы пытаетесь использовать недокументированный метод.Истина где-то рядом.
Styled Result
В заключение я бы порекомендовал вам использовать прямой доступ к стилям, чтобы решить, можете ли вы использовать выбранный стиль или нет.См. Код ниже (при условии, что у вас включен стиль приложения):
procedure TForm1.Button1Click(Sender: TObject);
begin
if Assigned(TStyleManager.Style['Emerald']) and TStyleManager.Style['Emerald'].Available then
// Do your code
else
ShowMessage('Specified style is not available!');
end;
Если у вас есть источники VCL.Themes
, вы можете легко проверить достоверность того, что я написал здесь.
Высокие технологии
Я создал class-helper
для TStyleManager
, который позволяет проверить, зарегистрирован ли файл стиля, и отменить его регистрацию при необходимости.Чтобы заполнить TStyleInfo
запись реальными значениями из файла стилей, нам нужно сохранить указанный стиль в TMemoryStream
и затем передать поток в функцию IsValidStyle
.Также мы могли бы использовать физический путь для стиля (например, C:\Embarcadero\Delphi\Styles\Emerald.vsf
) вместо варианта с потоком, но последний выглядит более элегантно.
К сожалению, согласно комментарию Реми (я не знаю, как сделать ссылку на него), C++ Builder
(который используется OP) не поддерживает class-helper
особенность.Единственное решение - создать простой модуль, содержащий весь код, необходимый для class-helper
.Для работы достаточно добавить такой модуль в предложение uses
и вызвать соответствующие публичные процедуры \ функции.
Это устройство имеет следующую структуру:
unit StyleManager_CH;
interface
uses
VCL.Themes;
function IsStyleRegistered_CH(var AStyle: TCustomStyleServices): Boolean;
procedure UnregisterStyleEx_CH(var AStyle: TCustomStyleServices);
implementation
uses
System.SysUtils, System.Classes, System.Generics.Collections;
type
TStyleManagerHelper = class helper for TStyleManager
public
class function IsStyleRegistered(var AStyle: TCustomStyleServices): Boolean;
class procedure UnregisterStyleEx(var AStyle: TCustomStyleServices);
end;
class function TStyleManagerHelper.IsStyleRegistered(var
AStyle: TCustomStyleServices): Boolean;
begin
Result := Assigned(AStyle) and
TStyleManager.FRegisteredStyles.ContainsKey(AStyle.Name);
end;
class procedure TStyleManagerHelper.UnregisterStyleEx(var
AStyle: TCustomStyleServices);
var
MS: TMemoryStream;
StyleInfo: TStyleInfo;
SourceInfo: VCL.Themes.TStyleManager.TSourceInfo;
begin
if Assigned(AStyle) then
begin
MS := TMemoryStream.Create;
try
AStyle.SaveToStream(MS);
MS.Position := 0;
if AStyle.IsValidStyle(MS, StyleInfo) then
begin
if TStyleManager.FRegisteredStyles.ContainsKey(StyleInfo.Name) then
begin
SourceInfo := TStyleManager.FRegisteredStyles.Items[StyleInfo.Name];
if Assigned(SourceInfo.Data) then
FreeAndNil(SourceInfo.Data);
TStyleManager.FStyles.Remove(AStyle);
TStyleManager.FRegisteredStyles.Remove(StyleInfo.Name);
FreeAndNil(AStyle);
end;
end;
finally
MS.Free;
end;
end;
end;
function IsStyleRegistered_CH(var AStyle: TCustomStyleServices): Boolean;
begin
Result := TStyleManager.IsStyleRegistered(AStyle);
end;
procedure UnregisterStyleEx_CH(var AStyle: TCustomStyleServices);
begin
TStyleManager.UnregisterStyleEx(AStyle);
end;
end.
Приложение _CH
обозначает class-helper
сокращение.Также были исправлены некоторые утечки памяти.
Я не уверен, есть ли другой способ перезагрузить файл стиля "на лету".