如何在不修改Vcl单元的前提下扩展Delphi的TApplication类
为Delphi全局TApplication扩展自定义功能的解决方案
因为VCL已经预实例化了全局Application对象,无法通过继承自定义子类的方式扩展,结合你已有的TAppData类,这里提供两种实用方案:
方案1:Class Helper + 全局TAppData实例(推荐)
Class Helper可以给TApplication添加自定义方法/属性,再配合全局的TAppData实例处理初始化逻辑,完美适配你的需求:
步骤1:声明全局TAppData变量
在一个公共单元(比如你的自定义工具单元)里声明全局变量:
var AppData: TAppData;
步骤2:程序启动时初始化
在DPR文件的入口处,Application.Initialize之前完成TAppData的初始化,确保VCL启动时数据已准备好:
begin AppData := TAppData.Create(ExtractFileName(ParamStr(0))); try Application.Initialize; Application.MainFormOnTaskbar := True; Application.CreateForm(TMainForm, MainForm); // 如果有依赖VCL的初始化逻辑(比如CreateLogForm),放在这里执行 // AppData.CreateLogForm; Application.Run; finally AppData.Free; end; end.
步骤3:编写TApplication的Class Helper
通过Helper把TAppData的功能映射到TApplication上,让你可以像调用原生方法一样使用:
type TApplicationHelper = class helper for TApplication private function GetAppData: TAppData; public // 直接暴露AppData实例 property AppData: TAppData read GetAppData; // 也可以把TAppData的方法直接封装进来 function AppDir: string; function RunningFirstTime: Boolean; // 按需添加其他方法... end; implementation function TApplicationHelper.GetAppData: TAppData; begin Result := AppData; // 指向全局实例 end; function TApplicationHelper.AppDir: string; begin Result := AppData.AppDir; end; function TApplicationHelper.RunningFirstTime: Boolean; begin Result := AppData.RunningFirstTime; end;
之后在代码里就可以直接写Application.AppDir、Application.AppData.LastUsedFolder,和使用TApplication原生属性完全一致。
方案2:Hook TApplication构造函数(进阶)
如果希望初始化逻辑和TApplication的构造完全绑定,可以用Hook技术替换TApplication的Create方法,在原构造执行后自动初始化TAppData,并通过RTTI把实例附加到TApplication对象上。
这个方法需要熟悉Delphi的RTTI和内存操作,风险较高,适合有经验的开发者,这里不展开细讲。
你的TAppData类代码(格式化后)
类声明
TYPE TAppData= class(TObject) private FAppName: string; FLastFolder: string; { 用于AppLastUsedFolder } //todo: 重命名为FLastFolder FRunningFirstTime: Boolean; // 补充原构造中用到但未声明的变量 function getLastUsedFolder: string; public Initializing: Boolean; { 在cvIniFile.pas中使用,程序初始化完成后设为false } constructor Create(aAppName: string); {-------------------------------------------------------------------------------------------------- 应用路径/名称 --------------------------------------------------------------------------------------------------} function AppDir : string; function SysDir : string; function AppDataFolder(ForceDir: Boolean= FALSE): string; function AppDataFolderAllUsers: string; function AppShortName: string; property AppName: string read FAppName; property LastUsedFolder: string read getLastUsedFolder write FLastFolder; {-------------------------------------------------------------------------------------------------- 应用控制 --------------------------------------------------------------------------------------------------} function RunningFirstTime: Boolean; procedure Restart; procedure SelfDelete; procedure Restore; function RunSelfAtWinStartUp(Active: Boolean): Boolean; function RunFileAtWinStartUp(FilePath: string; Active: Boolean): Boolean; { 设置应用随Windows启动 } {------------------------------------------------------------------------------------------------- 应用版本信息 --------------------------------------------------------------------------------------------------} function GetVersionInfoV : string; { 主版本,不含构建号。示例: v1.0.0 } function GetVersionInfo(ShowBuildNo: Boolean= False): string; function GetVersionInfoMajor: Word; function GetVersionInfoMinor: Word; function GetVersionInfo_: string; function getVersionFixedInfo(CONST FileName: string; VAR FixedInfo: TVSFixedFileInfo): Boolean; {-------------------------------------------------------------------------------------------------- Beta测试工具 --------------------------------------------------------------------------------------------------} function RunningHome: Boolean; function BetaTesterMode: Boolean; function IsHardCodedExp(Year, Month, Day: word): Boolean; end;
构造函数
constructor TAppData.Create(aAppName: string); begin inherited Create; Initializing:= True; { 在cvIniFile.pas中使用,程序初始化完成后设为false } FAppName:= aAppName; FRunningFirstTime:= NOT FileExists(IniFile); ForceDirectories(AppDataFolder); //ToDo: !!!!!!!!!!!!!!!!!!!!!!!! CreateLogForm; 但这样会引入日志模块的依赖! end;
内容的提问来源于stack exchange,提问作者Error - CPU Not Foud
相关产品推荐
相关产品推荐

