VCL 為了開發效率封裝了大多數常用功能,但也犧牲了部分底層控制力(如系統選單修改、TrackBar 缺乏 OnStartTrack/OnEndTrack)。幸好 Borland 保留「攔截 Windows 消息」的後門,讓開發者能像純 API 程式設計一樣直接處理消息。
TForm::Dispatch(&Message) 讓消息繼續傳遞(否則 VCL 內部邏輯可能失效)。// Unit1.h
class TMainForm : public TForm {
BEGIN_MESSAGE_MAP
MESSAGE_HANDLER(WM_SYSCOMMAND, TMessage, OnWMSysCommand)
MESSAGE_HANDLER(WM_HSCROLL, TMessage, OnWMHScroll)
END_MESSAGE_MAP(TForm)
private:
void __fastcall OnWMSysCommand(TMessage &Message);
void __fastcall OnWMHScroll(TMessage &Message);
};
// Unit1.cpp
void __fastcall TMainForm::OnWMSysCommand(TMessage &Message)
{
if (Message.WParam == MY_CUSTOM_MENU_ID) {
// 處理自訂選單項目
}
TForm::Dispatch(&Message); // 關鍵:傳遞給 VCL
}
FormCreate 動態修改選單void __fastcall TForm1::FormCreate(TObject *Sender)
{
HMENU hSysMenu = GetSystemMenu(Handle, FALSE);
AppendMenu(hSysMenu, MF_SEPARATOR, 0, NULL);
AppendMenu(hSysMenu, MF_STRING, ID_SYSMENU_ABOUT, L"關於(&A)...");
AppendMenu(hSysMenu, MF_STRING, ID_SYSMENU_SETTING, L"設定(&S)...");
}
WM_SYSCOMMAND 響應點擊void __fastcall TForm1::OnWMSysCommand(TMessage &Message)
{
switch (Message.WParam) {
case ID_SYSMENU_ABOUT: ShowAboutDialog(); break;
case ID_SYSMENU_SETTING: ShowSettingDialog(); break;
}
TForm::Dispatch(&Message);
}
TrackBar 滑塊拖曳過程對應 WM_HSCROLL(垂直為 WM_VSCROLL),wParam 低字節為捲動代碼:
SB_THUMBTRACK (5):滑塊正在拖動(對應 OnTrack)。SB_THUMBPOSITION (4):滑塊釋放(對應 OnEndTrack)。SB_THUMBTRACK 視為 OnStartTrack。private:
void __fastcall TrackBar1StartTrack(TObject *Sender);
void __fastcall TrackBar1EndTrack(TObject *Sender);
WM_HSCROLL 觸發事件void __fastcall TMainForm::OnWMHScroll(TMessage &Message)
{
if (Message.LParam == (LPARAM)TrackBar1->Handle) {
WORD scrollCode = LOWORD(Message.WParam);
static bool tracking = false;
if (scrollCode == SB_THUMBTRACK) {
if (!tracking) {
tracking = true;
TrackBar1StartTrack(TrackBar1); // 首次拖動
}
}
else if (scrollCode == SB_THUMBPOSITION) {
if (tracking) {
tracking = false;
TrackBar1EndTrack(TrackBar1); // 釋放滑塊
}
}
}
TForm::Dispatch(&Message);
}
void __fastcall TMainForm::TrackBar1StartTrack(TObject *Sender)
{
MediaPlayer->Pause(); // 拖動時暫停播放
}
void __fastcall TMainForm::TrackBar1EndTrack(TObject *Sender)
{
MediaPlayer->Time = TrackBar1->Position; // 定位新位置
MediaPlayer->Play();
}
Dispatch 傳遞。FormDestroy 中釋放。PostMessage 延後處理。「當 VCL 無法滿足需求時,Windows API 就是你的舞台。」—— 攔截消息是挖掘系統潛能的關鍵鑰匙。