首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> C++ >> 關於C++

編輯控制項 (Edit Control) 訊息與應用完全指南

     編輯:關於C++

前言

編輯控制項是 Windows 應用程式中最常見的文字輸入元件。掌握其通知訊息 (控制項→父視窗) 與控制訊息 (父視窗→控制項) 兩大類訊息,即可實作輸入驗證、自動完成、語法高亮、撤銷/重做、密碼遮罩、唯讀切換等進階功能。

一、通知訊息 (WM_COMMAND / WM_NOTIFY 透傳)

父視窗透過 WM_COMMAND 接收,HIWORD(wParam) 為通知碼,LOWORD(wParam) 為控制項 ID,lParam 為控制項 HWND。

通知碼觸發時機典型應用
EN_CHANGE文字內容實際改變後即時字數統計、儲存按鈕啟用、自動存檔觸發
EN_UPDATE文字即將更新 (重繪前)語法高亮預處理、輸入法組合字串攔截
EN_SETFOCUS / EN_KILLFOCUS獲得/失去輸入焦點顯示/隱藏工具提示、驗證整體輸入、啟用輸入法模式
EN_MAXTEXT嘗試超過文字長度限制 (EM_LIMITTEXT/MaxLength)彈出警告、自動截斷提示、記錄截斷事件
EN_HSCROLL / EN_VSCROLL使用者點擊水平/垂直捲軸同步外部捲軸、記錄捲動位置、延遲載入大檔案區塊
EN_ERRSPACE記憶體不足無法完成編輯操作釋放緩衝、提示關閉其他程式、降低編輯功能

二、控制訊息 (SendMessage 發送)

1. 撤銷/重做系統

訊息用途回傳值
EM_CANUNDO查詢是否可撤銷TRUE/FALSE
EM_UNDO執行撤銷TRUE 成功
EM_EMPTYUNDOBUFFER清除撤銷緩衝 (不可復原)無

2. 文字長度與限制

訊息用途參數
EM_LIMITTEXT / EM_SETLIMITTEXT設定最大文字長度 (字元數)wParam = max chars (0 = 64KB 預設)
EM_GETLIMITTEXT取得目前限制回傳上限值

3. 選取範圍操作

訊息用途參數說明
EM_GETSEL取得選取範圍wParam=起始指標, lParam=結束指標 (以字元索引)
EM_SETSEL設定選取範圍wParam=start, lParam=end; -1 代表游標位置/結尾
EM_REPLACESEL以指定文字取代選取範圍lParam=LPCTSTR 新文字; 可用於插入/追加/清空

4. 行與座標轉換 (多行編輯專用)

訊息用途關鍵參數/回傳
EM_GETLINECOUNT取得總行數回傳 int
EM_GETLINE複製指定行內容至緩衝區wParam=行索引(0-based), lParam=緩衝區指標 (首字為長度)
EM_LINEINDEX取得指定行第一個字元索引wParam=行索引, 回傳字元索引
EM_LINELENGTH取得指定行長度wParam=字元索引, 回傳該行長度
EM_LINEFROMCHAR字元索引對應行號wParam=字元索引, 回傳行號
EM_POSFROMCHAR / EM_CHARFROMPOS字元索引 ↔ 用戶區座標 (POINT)lParam=字元索引 / 回傳 MAKELONG(x,y)
EM_GETFIRSTVISIBLELINE取得目前可見區域首行索引回傳行號
EM_LINESCROLL垂直/水平捲動行數/字元數wParam=水平字元, lParam=垂直行數

5. 格式化與製表位

訊息用途
EM_FMTLINES取得文字時是否包含軟換行字元 (wParam=TRUE/FALSE)
EM_SETTABSTOPS設定製表位間距 (以對話單位),wParam=數量, lParam=陣列指標
EM_SETMARGINS / EM_GETMARGINS設定/取得左右邊距 (EC_LEFTMARGIN/EC_RIGHTMARGIN/EC_USEFONTINFO)
EM_SETRECT / EM_SETRECTNP / EM_GETRECT設定/取得格式化矩形 (NP=不重繪)

6. 密碼與唯讀模式

訊息用途
EM_SETPASSWORDCHAR設定密碼遮罩字元 (wParam=字元, 0=關閉)
EM_GETPASSWORDCHAR取得目前遮罩字元
EM_READONLY設定/取消唯讀狀態 (wParam=TRUE/FALSE)
EM_SETMODIFY / EM_GETMODIFY設定/查詢修改旗標 (內容是否異動)

三、進階應用範例

即時字數統計與長度限制提示

// 父視窗 WM_COMMAND 處理
case EN_CHANGE:
    int len = SendMessage(hEdit, WM_GETTEXTLENGTH, 0, 0);
    SetDlgItemInt(hDlg, IDC_STAT_COUNT, len, FALSE);
    if (len >= MAX_LEN) {
        // 可選:自動截斷或禁用輸入
        SendMessage(hEdit, EM_SETSEL, MAX_LEN, -1);
        SendMessage(hEdit, EM_REPLACESEL, 0, (LPARAM)L"");
    }
    break;

程式化插入時間戳記

void InsertTimestamp(HWND hEdit) {
    WCHAR buf[64];
    SYSTEMTIME st; GetLocalTime(&st);
    swprintf(buf, L"[%04d-%02d-%02d %02d:%02d:%02d] ", 
             st.wYear, st.wMonth, st.wDay, st.wHour, st.wMinute, st.wSecond);
    SendMessage(hEdit, EM_REPLACESEL, TRUE, (LPARAM)buf);
}

同步捲軸位置 (雙編輯視窗比對)

case EN_VSCROLL:
    int firstLine = SendMessage(hEdit1, EM_GETFIRSTVISIBLELINE, 0, 0);
    SendMessage(hEdit2, EM_LINESCROLL, 0, firstLine - 
                SendMessage(hEdit2, EM_GETFIRSTVISIBLELINE, 0, 0));
    break;

四、Unicode 與 DPI 注意事項

  • 所有文字訊息 (WM_SETTEXT, EM_REPLACESEL, EM_GETLINE) 在 Unicode 專案中接受 wchar_t*,ANSI 專案接受 char*;建議統一使用 Unicode 建置。
  • High-DPI 環境下,EM_POSFROMCHAR 回傳的座標為邏輯像素 (非物理像素),搭配 GetDpiForWindow 換算。
  • EM_SETTABSTOPS 的單位為對話單位 (1/4 字元寬 × 1/8 字元高),需以 MapDialogRect 轉換為像素。

結語

編輯控制項訊息集涵蓋從基本輸入到專業文字編輯器所需的所有底層操作。善用 EM_GETSEL/SETSEL/REPLACESEL 三劍客即可實作 90% 的文字操作邏輯;多行編輯則需熟練行/字元/座標轉換 API。現代開發若需語法高亮、代碼摺疊、巨集記錄等進階功能,建議改用 Scintilla (SciLexer.dll) 或 RichEdit 4.1+ (msftedit.dll) 控制項,它們繼承並大幅擴充了標準編輯控制項的訊息介面。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved