編輯框是用戶輸入交互的核心控件。MFC CEdit 封裝豐富風格(密碼、多行、自動滾動、大小寫轉換)、文本獲取設置、選中範圍控制、替換選中文本、剪貼板操作及完整消息映射。本文系統講解全功能用法與避坑指南。
一、 創建與風格大全
BOOL Create(LPCTSTR lpszText, DWORD dwStyle, const RECT& rect, CWnd* pParentWnd, UINT nID = 0xffff);
核心編輯風格(可組合)
| 風格 | 功能 | 典型場景 |
ES_MULTILINE | 多行輸入 (需配合 ES_WANTRETURN) | 文本編輯器、日誌顯示 |
ES_PASSWORD | 密碼模式,顯示 * (或自定義字符) | 登錄對話框 |
ES_READONLY | 只讀,不可編輯 | 信息顯示、不可修改字段 |
ES_AUTOHSCROLL | 水平自動滾動 (單行時) | 長文本單行輸入 |
ES_AUTOVSCROLL | 垂直自動滾動 (多行時) | 多行文本編輯 |
ES_WANTRETURN | 多行時 Enter 換行而非確認對話框 | 必配合 ES_MULTILINE |
ES_NUMBER | 僅允許數字輸入 (Win95+) | 數值輸入框 |
ES_UPPERCASE | 自動轉大寫 | 代碼、序列號輸入 |
ES_LOWERCASE | 自動轉小寫 | 郵箱、域名輸入 |
ES_CENTER/ES_LEFT/ES_RIGHT | 文本對齊方式 | 標題、數值對齊 |
ES_NOHIDESEL | 失去焦點仍高亮選中文本 | 代碼編輯器風格 |
ES_OEMCONVERT | ANSI-OEM 轉換 (文件名兼容) | 文件名輸入 |
常用組合示例
// 標準單行輸入
WS_CHILD | WS_VISIBLE | WS_BORDER | ES_AUTOHSCROLL
// 密碼框
WS_CHILD | WS_VISIBLE | WS_BORDER | ES_PASSWORD
// 多行文本編輯器
WS_CHILD | WS_VISIBLE | WS_BORDER | WS_VSCROLL | WS_HSCROLL |
ES_MULTILINE | ES_AUTOVSCROLL | ES_AUTOHSCROLL | ES_WANTRETURN | ES_NOHIDESEL
// 數值輸入 (右對齊)
WS_CHILD | WS_VISIBLE | WS_BORDER | ES_NUMBER | ES_RIGHT
二、 文本核心操作
| 操作 | 函數 | 說明 |
| 獲取全部文本 | GetWindowText(CString&) / GetWindowText(LPTSTR, int) | 複製到緩衝區 |
| 設置全部文本 | SetWindowText(LPCTSTR) | 替換全部內容 |
| 獲取文本長度 | GetWindowTextLength() | 不含結束符 |
| 獲取/設置最大字符數 | GetLimitText() / SetLimitText(int) | 默認 32767 (單行) / 64K (多行) |
三、 選中範圍精確控制
| 操作 | 函數 | 參數說明 |
| 獲取選中範圍 | GetSel(int& nStart, int& nEnd) | 字符索引,0-based,nEnd 為結束位置(不含) |
| 設置選中範圍 | SetSel(int nStart, int nEnd, BOOL bNoScroll=FALSE) | SetSel(0,-1) 全選 |
| 替換選中文本 | ReplaceSel(LPCTSTR, BOOL bCanUndo=FALSE) | 插入/替換,可納入撤銷隊列 |
| 獲取選中文本 | GetSelText(CString&) (MFC 封裝) | 直接獲取選中段落 |
選中範圍實戰技巧
// 全選
edit.SetSel(0, -1);
// 定位到指定行行首 (多行)
int lineIdx = edit.LineFromChar(charIndex);
int lineStart = edit.LineIndex(lineIdx);
edit.SetSel(lineStart, lineStart);
// 選中整行
int lineLen = edit.LineLength(lineStart);
edit.SetSel(lineStart, lineStart + lineLen);
// 追加文本並滾動到末尾
edit.SetSel(-1, -1); // 光標移到末尾
edit.ReplaceSel(newText);
edit.ScrollCaret(); // 確保光標可見
四、 剪貼板操作(封裝標準命令)
| 操作 | 函數 | 等效鍵盤 |
| 複製 | Copy() | Ctrl+C |
| 剪切 | Cut() | Ctrl+X |
| 粘貼 | Paste() | Ctrl+V |
| 刪除(不入剪貼板) | Clear() | Del |
| 撤銷 | Undo() | Ctrl+Z |
| 可否撤銷 | CanUndo() | 布爾值 |
| 清空撤銷隊列 | EmptyUndoBuffer() | - |
五、 消息映射宏
ON_EN_XXX(IDC_EDIT, OnXxxEdit)
// 處理函數:afx_msg void OnXxxEdit();
| 宏 | 觸發條件 | 典型用途 |
ON_EN_CHANGE | 文本內容改變 (用戶/程序) | 實時驗證、字符計數、自動保存標記 |
ON_EN_UPDATE | 文本即將更新 (屏幕未重繪) | 攔截輸入、動態過濾字符 |
ON_EN_SETFOCUS | 獲得輸入焦點 | 顯示提示、選中全文、輸入法控制 |
ON_EN_KILLFOCUS | 失去輸入焦點 | 驗證格式、保存數據、隱藏提示 |
ON_EN_ERRSPACE | 內存分配失敗 | 錯誤恢復、釋放資源 |
ON_EN_MAXTEXT | 超過最大字符限制 | 提示用戶、截斷處理 |
ON_EN_HSCROLL | 水平滾動 | 同步其他視圖 |
ON_EN_VSCROLL | 垂直滾動 | 同步行號、標記 |
六、 進階技巧與避坑指南
1. 密碼框自定義掩碼字符
edit.SetPasswordChar('●'); // 設置為圓點
edit.SetPasswordChar(0); // 恢復明文顯示
2. 多行文本換行處理
// 獲取行數
int lines = edit.GetLineCount();
// 獲取指定行文本
CString lineText;
edit.GetLine(lineIndex, lineText.GetBuffer(256), 256);
lineText.ReleaseBuffer();
// 設置 Tab 寬度
edit.SetTabStops(4); // 4 字符寬度
3. 輸入過濾(只允許特定字符)
void CMyDialog::OnEnUpdateEdit() {
CString text;
edit.GetWindowText(text);
// 過濾邏輯:只保留數字和小數點
CString filtered;
for (int i = 0; i < text.GetLength(); ++i) {
TCHAR ch = text[i];
if (_istdigit(ch) || ch == _T('.')) filtered += ch;
}
if (filtered != text) {
int start, end;
edit.GetSel(start, end);
edit.SetWindowText(filtered);
// 盡量恢復光標位置
edit.SetSel(min(start, filtered.GetLength()), min(end, filtered.GetLength()));
}
}
4. 避坑清單
- ES_MULTILINE 必配 ES_WANTRETURN:否則 Enter 關閉對話框而非換行
- SetWindowText 會重置選中狀態:程序修改文本後需手動恢復光標/選中
- 多行編輯框 GetWindowText 包含 \r\n:跨平台處理需統一換行符
- ES_NUMBER 僅阻攔鍵盤輸入:
SetWindowText 程序設置仍可放入非數字
- 大文本性能:超過 10KB 建議用
CRichEditCtrl 或分頁加載
- ON_EN_CHANGE 高頻觸發:實時驗證需防抖(定時器延遲 300ms 執行)
本文整理自 MFC 經典技術文檔,適用於 VC6~VS2022 所有版本。