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

VC++ 擴充 CRichEditCtrl 實作右鍵選單與字體設定:撤銷/剪貼/複製/貼上/全選/字型

     編輯:VC 教學

前言

MFC `CRichEditCtrl` 功能強大支援富文本,但預設不響應滑鼠右鍵,也缺乏內建的字體選擇對話框整合。本文示範繼承 `CRichEditCtrl` 實作 `CMyRichEdit`,加入右鍵彈出選單(撤銷、剪貼、複製、貼上、清除、全選、字型)、選單項目啟用/禁用狀態動態更新、字體對話框雙向同步(選取文字套用/預設字體設定),完整可直接放入專案使用。

一、類別宣告


class CMyRichEdit : public CRichEditCtrl
{
    DECLARE_DYNAMIC(CMyRichEdit)
public:
    CMyRichEdit();
    virtual ~CMyRichEdit();

protected:
    // 選單命令 ID
    enum { ID_UNDO = 101, ID_CUT, ID_COPY, ID_PASTE, ID_CLEAR, ID_SELECTALL, ID_SETFONT };

    afx_msg void OnRButtonDown(UINT nFlags, CPoint point);
    afx_msg void OnUndo();      afx_msg void OnCut();
    afx_msg void OnCopy();      afx_msg void OnPaste();
    afx_msg void OnClear();     afx_msg void OnSelectAll();
    afx_msg void OnSetFont();

    DECLARE_MESSAGE_MAP()
};

二、右鍵選單建構與狀態更新


void CMyRichEdit::OnRButtonDown(UINT nFlags, CPoint point)
{
    SetFocus(); // 確保焦點在編輯框

    CMenu menu;
    menu.CreatePopupMenu();

    // 加入項目
    menu.AppendMenu(MF_STRING, ID_UNDO, _T("&Undo"));
    menu.AppendMenu(MF_SEPARATOR);
    menu.AppendMenu(MF_STRING, ID_CUT, _T("Cu&t"));
    menu.AppendMenu(MF_STRING, ID_COPY, _T("&Copy"));
    menu.AppendMenu(MF_STRING, ID_PASTE, _T("&Paste"));
    menu.AppendMenu(MF_STRING, ID_CLEAR, _T("C&lear"));
    menu.AppendMenu(MF_SEPARATOR);
    menu.AppendMenu(MF_STRING, ID_SELECTALL, _T("Select &All"));
    menu.AppendMenu(MF_SEPARATOR);
    menu.AppendMenu(MF_STRING, ID_SETFONT, _T("&Font..."));

    // 動態啟用/禁用
    BOOL bCanUndo = CanUndo();
    menu.EnableMenuItem(ID_UNDO, bCanUndo ? MF_ENABLED : MF_GRAYED);

    BOOL bHasSel = (GetSelectionType() != SEL_EMPTY);
    menu.EnableMenuItem(ID_CUT, bHasSel ? MF_ENABLED : MF_GRAYED);
    menu.EnableMenuItem(ID_COPY, bHasSel ? MF_ENABLED : MF_GRAYED);
    menu.EnableMenuItem(ID_CLEAR, bHasSel ? MF_ENABLED : MF_GRAYED);

    BOOL bCanPaste = CanPaste();
    menu.EnableMenuItem(ID_PASTE, bCanPaste ? MF_ENABLED : MF_GRAYED);

    // 顯示選單:螢幕座標
    ClientToScreen(&point);
    menu.TrackPopupMenu(TPM_RIGHTBUTTON | TPM_LEFTALIGN, point.x, point.y, this);
    menu.DestroyMenu();

    CRichEditCtrl::OnRButtonDown(nFlags, point);
}

三、命令處理函數


BEGIN_MESSAGE_MAP(CMyRichEdit, CRichEditCtrl)
    ON_WM_RBUTTONDOWN()
    ON_COMMAND(ID_UNDO, OnUndo)
    ON_COMMAND(ID_CUT, OnCut)
    ON_COMMAND(ID_COPY, OnCopy)
    ON_COMMAND(ID_PASTE, OnPaste)
    ON_COMMAND(ID_CLEAR, OnClear)
    ON_COMMAND(ID_SELECTALL, OnSelectAll)
    ON_COMMAND(ID_SETFONT, OnSetFont)
END_MESSAGE_MAP()

void CMyRichEdit::OnUndo()  { Undo(); }
void CMyRichEdit::OnCut()   { Cut(); }
void CMyRichEdit::OnCopy()  { Copy(); }
void CMyRichEdit::OnPaste() { Paste(); }
void CMyRichEdit::OnClear() { Clear(); }
void CMyRichEdit::OnSelectAll() { SetSel(0, -1); }

四、字體選擇對話框整合


void CMyRichEdit::OnSetFont()
{
    CHARFORMAT2 cf = {0}; cf.cbSize = sizeof(CHARFORMAT2);
    LOGFONT lf = {0};

    // 取得目前選取或預設字體格式
    BOOL bHasSel = (GetSelectionType() != SEL_EMPTY);
    if (bHasSel) GetSelectionCharFormat(cf);
    else         GetDefaultCharFormat(cf);

    // CHARFORMAT2 → LOGFONT
    lf.lfCharSet = cf.bCharSet;
    lf.lfHeight = cf.yHeight / 20; // twips → 華氏點
    lf.lfPitchAndFamily = cf.bPitchAndFamily;
    lf.lfWeight = (cf.dwEffects & CFE_BOLD) ? FW_BOLD : FW_NORMAL;
    lf.lfItalic = (cf.dwEffects & CFE_ITALIC) ? TRUE : FALSE;
    lf.lfUnderline = (cf.dwEffects & CFE_UNDERLINE) ? TRUE : FALSE;
    lf.lfStrikeOut = (cf.dwEffects & CFE_STRIKEOUT) ? TRUE : FALSE;
    _tcscpy_s(lf.lfFaceName, LF_FACESIZE, cf.szFaceName);

    CFontDialog dlg(&lf, CF_EFFECTS | CF_SCREENFONTS, NULL, this);
    dlg.m_cf.rgbColors = cf.crTextColor; // 傳入目前文字顏色

    if (dlg.DoModal() == IDOK)
    {
        dlg.GetCharFormat(cf); // 取回使用者選擇的格式

        if (bHasSel)
            SetSelectionCharFormat(cf); // 套用到選取文字
        else
            SetWordCharFormat(cf);      // 設定預設字體(後續輸入生效)
    }
}

五、專案整合注意事項

  1. 初始化 RichEdit 庫:在 `CWinApp::InitInstance()` 最前面呼叫 `AfxInitRichEdit2()`(RichEdit 4.1)或 `AfxInitRichEdit()`(舊版)。
  2. 對話方塊資源:放入 `RichEdit20A`/`RichEdit20W` 控制項(工具箱無圖示,需用 `Insert ActiveX Control` 或手動修改 `.rc` 類別名)。
  3. 子類化關聯:`DDX_Control(pDX, IDC_RICHEDIT, m_richEdit)` 或動態 `SubclassDlgItem`。
  4. Unicode 專案:確保使用 `RichEdit20W` 並包含 `` 定義 `CHARFORMAT2W`。

六、執行效果

RichEdit 右鍵選單與字體對話框示範

右鍵彈出選單,項目依編輯狀態啟用/禁用,選擇 Font 彈出標準字型對話框,確定後選取文字或後續輸入即時生效。

七、擴充建議

  • 段落格式:加入 `PARAFORMAT2` 對話框(對齊、縮排、行距)。
  • 插入物件:圖片、OLE 物件、超連結(`CFE_LINK` 效果 + `EN_LINK` 通知)。
  • 拼寫檢查:整合 ISpell 或 Windows 8+ `ISpellCheckProvider`。
  • 工具列同步:`EN_SELCHANGE` 通知更新工具列按鈕狀態(粗體/斜體/底線按鈕按下狀態)。

八、結語

僅繼承 `CRichEditCtrl`、覆寫 `OnRButtonDown` 建構選單、映射 7 個命令、整合 `CFontDialog` 雙向同步 `CHARFORMAT2`/`LOGFONT`,即可賦予 RichEdit 專業文字處理器級的右鍵編輯與字體設定能力。`CMyRichEdit` 封裝完整、零依賴,適合直接納入專案共用控制項庫,為任何富文本編輯需求提供堅實基礎。

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