標準的 TEdit 控件預設不支援使用者透過滑鼠拖曳邊框來調整大小,也不支援在表單上自由拖曳移動位置。本文將示範如何透過 Windows API 修改視窗樣式,為 TEdit 增加「調整大小邊框」與「標題列拖曳移動」兩項實用功能,讓單行編輯框擁有類似視窗的互動體驗。
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
// 1. 取得 Edit1 目前的視窗樣式
DWORD dwStyle = ::GetWindowLong(Edit1->Handle, GWL_STYLE);
// 2. 加入 WS_SIZEBOX,使其擁有可調整大小的邊框
::SetWindowLong(Edit1->Handle, GWL_STYLE, dwStyle | WS_SIZEBOX);
// 3. 強制重繪視窗,修正客戶區尺寸,確保邊框可被正確拖曳
::MoveWindow(Edit1->Handle,
Edit1->Left, Edit1->Top,
Edit1->Width, Edit1->Height + 1,
true);
}
//---------------------------------------------------------------------------
// 當滑鼠在 Edit1 上按下時,若游標為箭頭則啟動拖曳
void __fastcall TForm1::Edit1MouseDown(TObject *Sender,
TMouseButton Button, TShiftState Shift, int X, int Y)
{
if (Edit1->Cursor == crArrow)
{
::ReleaseCapture(); // 釋放滑鼠捕獲
// 送出「非客戶區左鍵按下」訊息,參數 HTCAPTION 表示點擊標題列
::SendMessage(Edit1->Handle, WM_NCLBUTTONDOWN, HTCAPTION, 0);
}
}
//---------------------------------------------------------------------------
// 滑鼠移動時保持箭頭游標,提示使用者可拖曳
void __fastcall TForm1::Edit1MouseMove(TObject *Sender,
TShiftState Shift, int X, int Y)
{
Edit1->Cursor = crArrow;
}
//---------------------------------------------------------------------------
加入 WS_SIZEBOX 後,視窗邊框會變粗以容納調整控制點,但控件的客戶區大小不會自動更新。呼叫 MoveWindow 並將高度加 1 像素,強制視窗重新計算非客戶區與客戶區的佈局,使邊框能正確回應滑鼠拖曳。
WM_NCLBUTTONDOWN 配合 HTCAPTION 是 Windows 內建的視窗移動觸發機制。我們在 OnMouseDown 事件中手動發送此訊息,欺騙系統以為使用者正在拖曳標題列,從而無需撰寫複雜的座標計算與 SetWindowPos 迴圈即可實現平滑拖曳。
TMemo、TRichEdit 等其他視窗化控件。OnResize 或 OnCanResize 事件中加入邏輯判斷。| 現象 | 可能原因 | 解決方案 |
|---|---|---|
| 邊框出現但無法拖曳調整 | 未呼叫 MoveWindow 更新佈局 | 確保建構子中呼叫 MoveWindow 並將高度 +1 |
| 拖曳移動時畫面閃爍 | 未釋放滑鼠捕獲 | 在 SendMessage 前務必呼叫 ReleaseCapture() |
| 游標不變為箭頭 | OnMouseMove 未設定 Cursor | 在 OnMouseMove 中指派 Edit1->Cursor = crArrow |
掌握這項技巧,能讓你的 C++Builder 應用程式擁有更靈活、更專業的使用者介面互動體驗。