TApplication 封裝 Windows 應用程式模型,是 VCL 專案的唯一全域單例(全域變數 Application),負責訊息泵驅動、主視窗管理、異常捕獲、提示系統、幫助系統、國際化設定同步等核心基礎設施。本文系統梳理類架構、關鍵屬性、訊息迴路機制、異常處理流程、IDE 設計時整合與現代化架構建議。
TObject
└── TPersistent
└── TComponent
└── TApplication // 非視覺元件,不在元件調色盤
// 全域單例(專案啟動時自動構造)
extern PACKAGE TApplication* Application;
關鍵點:
- 每進程唯一實例,不可手動構造/銷毀。
- 無公開屬性於 Object Inspector,設定通過 Project → Options → Application 頁面。
- 擁有所有 TForm,析構時自動釋放。
| 類別 | 屬性 | 說明 |
|---|---|---|
| 視窗管理 | MainForm | 主視窗(首個 CreateForm 建立),關閉即終止應用 |
ShowMainForm | 啟動時是否顯示主視窗(OLE 服務常設 false) | |
Handle | 應用程式主視窗 HWND,供 DLL/外部 API 父視窗用 | |
Icon/Title | 任務列圖標與標題 | |
| 提示系統 | ShowHint/Hint | 全域啟用/當前提示文本 |
HintPause/HintHidePause/HintShortPause | 顯示/隱藏/連續切換延遲(毫秒) | |
HintColor | 提示視窗背景色 | |
| 幫助系統 | HelpFile | 幫助檔路徑(.chm/.hlp) |
HelpContext/HelpCommand/HelpJump | 程式化顯示幫助 | |
| 國際化/度量 | UpdateFormatSettings/UpdateMetricSettings | 響應系統區域/字體變更自動刷新 |
| 運行狀態 | Active/Terminated | 前台狀態/收到 WM_QUIT |
// 標準啟動碼 (WinMain)
Application->Initialize();
Application->CreateForm(__classid(TMainForm), &MainForm);
Application->Run(); // 進入訊息泵,直到 Terminated
// Run 內部邏輯(簡化)
void __fastcall TApplication::Run() {
while (!Terminated) {
if (PeekMessage(&msg, 0, 0, 0, PM_REMOVE)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
} else {
Idle(nullptr); // 觸發 OnIdle
}
}
}
ProcessMessages():同步處理佇列中所有訊息並返回,適用於長時間運算中保持 UI 響應。HandleMessage():處理單個訊息(或空閒),適用於自定義迴循。OnIdle:訊息佇列空時觸發,Done 參數控制是否 WaitMessage。// 內部捕獲流程
try {
DispatchMessage(&msg); // 事件處理器可能拋異常
} catch (Exception& e) {
HandleException(this, e); // 核心處理入口
}
// HandleException 邏輯
void __fastcall TApplication::HandleException(TObject* Sender, Exception* E) {
if (dynamic_cast(E)) return; // 靜默中止
if (OnException) OnException(Sender, E); // 用戶鉤子
else ShowException(E); // 預設:彈出錯誤對話框
}
最佳實踐:
① 為 OnException 提供全域日誌記錄 + 用戶友好提示。
② 執行緒異常需自行捕獲(TThread::OnTerminate 或 try/catch 在 Execute 內),主執行緒 OnException 不捕獲 背景執行緒異常。
③ Application->ShowException 可重載自定義對話框。
// 顯示上下文幫助
Application->HelpContext(1001); // 對應 .chm 中 Context ID 1001
// 程式化命令
Application->HelpCommand(HELP_FINDER, 0); // 開啟幫助查找器
// OnHelp 事件可攔截並自定義顯示邏輯
void __fastcall TForm1::ApplicationHelp(TObject* Sender, int& Command, int& Data, bool& CallHelp) {
if (Command == HELP_CONTEXT) {
// 自行用 HtmlHelp API 顯示
CallHelp = false; // 阻止預設 WinHelp
}
}
Project → Options → Application 頁面持久化屬性:
- Title、Icon、HelpFile、ShowMainForm、EnableRuntimeThemes 等。
修改即時寫入 .dproj / .cbproj,編譯期注入資源。
TApplication 視為啟動器,業務邏輯遷移至服務層(TDataModule 或純 C++ 類)。ThreadExceptionHandler 全域函數,SetUnhandledExceptionFilter 捕獲非 VCL 執行緒崩潰。Application->Scaled = true + Manifest dpiAware=PerMonitorV2。CreateMutex + FindWindow 激活既有實例,避免多開。Chromium/CEF、Python 等需自有迴循時,改寫 Run 或啟動獨立執行緒跑子迴循,主執行緒仍跑 Application->Run()。| 現象 | 原因 | 對策 |
|---|---|---|
| 主視窗關閉程式未退出 | 非 MainForm 視窗仍存活 | 確保所有視窗關閉或 Application->Terminate() |
| DLL 視窗不隨主程式最小化 | DLL 內 Application->Handle 未設為主程式 Handle | DLL 載入時 Application->Handle = MainAppHandle |
| 提示不顯示 | ShowHint=false 或控件 ShowHint=false | 檢查雙層開關 |
| OnIdle 狂佔 CPU | Done=false 導致不等待訊息 | 僅極短輪詢設 false,其餘保持 true |
TApplication 是 VCL 應用程式的「心臟」,掌握其訊息泵、異常流、提示/幫助子系統與 IDE 整合點,即能從容駕馭從傳統桌面到現代高 DPI、多執行緒、混合技術棧的複雜應用場景。