標準 TEdit 僅支援文字編輯,無法像視窗那樣拖曳移動或拖曳邊框調整大小。透過修改視窗風格加入 WS_SIZEBOX 並攔截滑鼠訊息模擬標題列拖曳,即可賦予 Edit 視窗級的互動能力。
__fastcall TForm1::TForm1(TComponent* Owner) : TForm(Owner) {
// 1. 加入 WS_SIZEBOX 風格,啟用邊框調整大小
DWORD dwStyle = ::GetWindowLong(Edit1->Handle, GWL_STYLE);
::SetWindowLong(Edit1->Handle, GWL_STYLE, dwStyle | WS_SIZEBOX);
// 2. 修正視窗實際尺寸,確保邊框可被滑鼠命中
::MoveWindow(Edit1->Handle, Edit1->Left, Edit1->Top,
Edit1->Width, Edit1->Height + 1, TRUE);
}
// 3. 滑鼠按下:若游標為箭頭,模擬標題列拖曳移動整個 Edit
void __fastcall TForm1::Edit1MouseDown(TObject *Sender, TMouseButton Button,
TShiftState Shift, int X, int Y) {
if (Edit1->Cursor == crArrow) {
::ReleaseCapture(); // 釋放原有捕獲
// 發送 WM_NCLBUTTONDOWN + HTCAPTION,系統視為點擊標題列
::SendMessage(Edit1->Handle, WM_NCLBUTTONDOWN, HTCAPTION, 0);
}
}
// 4. 滑鼠移動:保持箭頭游標,暗示可拖曳
void __fastcall TForm1::Edit1MouseMove(TObject *Sender, TShiftState Shift,
int X, int Y) {
Edit1->Cursor = crArrow;
}
| 技術點 | 說明 |
|---|---|
WS_SIZEBOX (0x00040000) | 賦予視窗可調整大小的粗邊框,系統自動處理邊框拖曳調整大小邏輯。 |
WM_NCLBUTTONDOWN + HTCAPTION | 標準視窗拖曳移動觸發機制。發送此訊息欺騙系統以為使用者點擊了標題列,啟動內建移動循環。 |
ReleaseCapture | 確保無其他視窗持有滑鼠捕獲,避免衝突。 |
MoveWindow ... Height+1 | 微調高度確保底部邊框完整顯示並可命中,避免邊框過細無法拖曳。 |
游標設為 crArrow | 視覺提示使用者此控制項可拖曳移動,區別於編輯狀態的 I-beam 游標。 |
MouseDown 中判斷游標狀態決定是移動還是編輯。Edit1MouseMove 或自訂 WM_WINDOWPOSCHANGING 處理中限制 Left/Top 範圍。WM_GETMINMAXINFO 設定 ptMinTrackSize/ptMaxTrackSize。TCustomEdit,在建構函式套用上述風格與事件,發布為 TDraggableSizableEdit。僅需幾行 API 呼叫,即可將普通 TEdit 昇級為具備視窗級拖曳移動與縮放能力的互動控制項,極大豐富介面靈活性。