文本编辑器

文本编辑器——记事本类型的应用,可以打开、编辑、保存文本文档。可以增加单词高亮和其它的一些特性。

效果图:

//CGEditorDlg成员
public:
	CString m_filename;//打开文件名
	CRichEditCtrl m_richedit;//富文本框控件
	CString m_text;//富文本框中的文本
	std::set<std::wstring> blueText;//需要变蓝色的单词
	std::set<std::wstring> redText;//需要变红色的单词

	afx_msg void OnBnClickedOk();
	afx_msg void OnBnClickedCancel();
	afx_msg void OnBnClickedButtonsearch();//浏览按钮消息处理
	afx_msg void OnEnChangeRichedit();//富文本框文本变化时消息处理
	afx_msg void OnBnClickedButtonsave();//保存按钮消息处理
	afx_msg void OnEnMsgfilterRichedit(NMHDR *pNMHDR, LRESULT *pResult);//筛选键盘消息,处理tab键
BOOL CGEditorDlg::OnInitDialog()
{
	CDialogEx::OnInitDialog();

	// 设置此对话框的图标。  当应用程序主窗口不是对话框时,框架将自动
	//  执行此操作
	SetIcon(m_hIcon, TRUE);			// 设置大图标
	SetIcon(m_hIcon, FALSE);		// 设置小图标

	// TODO:  在此添加额外的初始化代码
	m_richedit.SetEventMask(m_richedit.GetEventMask() | ENM_CHANGE | ENM_KEYEVENTS);

	blueText.clear();
	blueText.insert(L"int");
	blueText.insert(L"double");
	blueText.insert(L"float");
	blueText.insert(L"void");
	blueText.insert(L"char");
	redText.clear();
	redText.insert(L"include");
	redText.insert(L"using");
	redText.insert(L"namespace");
	redText.insert(L"return");

	return TRUE;  // 除非将焦点设置到控件,否则返回 TRUE
}
void CGEditorDlg::OnBnClickedButtonsearch()
{
    // TODO:  在此添加控件通知处理程序代码
    CFileDialog dlg(TRUE, TEXT("cpp"), TEXT("text"), OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT,
        TEXT("C源文件(*.c)|*.c|C++源文件(*.cpp)|*.cpp|文本文件(*.txt)|*.txt||"));//open
    if (IDOK == dlg.DoModal())
    {
        //MessageBox(dlg.GetPathName());
        wifstream ifs(dlg.GetPathName().GetBuffer());
        if (!ifs.is_open())
        {
            MessageBox(dlg.GetPathName(), TEXT("文件打开失败"));
        }
        ifs.imbue(std::locale("chs"));
        istreambuf_iterator<wchar_t> beg(ifs), end;
        wstring text(beg, end);
        m_text = text.c_str();
        m_text.Replace(TEXT("\t"), TEXT("    "));
        m_text.Replace(TEXT("\n"), TEXT("\r\n"));
        m_filename = dlg.GetPathName();
        ifs.close();
        UpdateData(FALSE);
        OnEnChangeRichedit();
        SetWindowText(dlg.GetPathName());
    }
}
void CGEditorDlg::OnEnChangeRichedit()
{
    // TODO:  如果该控件是 RICHEDIT 控件,它将不
    // 发送此通知,除非重写 CDialogEx::OnInitDialog()
    // 函数并调用 CRichEditCtrl().SetEventMask(),
    // 同时将 ENM_CHANGE 标志“或”运算到掩码中。

    // TODO:  在此添加控件通知处理程序代码
    UpdateData(TRUE);

    long start, end;
    m_richedit.GetSel(start, end);//保存光标位置

    CHARFORMAT2 fm1, fm2;
    memset(&fm1, 0, sizeof(fm1));
    memset(&fm2, 0, sizeof(fm2));
    //CPoint pos = m_richedit.GetCaretPos();
    m_richedit.GetDefaultCharFormat(fm1);
    m_richedit.GetDefaultCharFormat(fm2);

    m_richedit.SetSel(0, -1);
    m_richedit.SetSelectionCharFormat(fm2);

    fm1.cbSize = sizeof(fm1);
    fm1.dwMask = CFM_COLOR;
    fm1.dwEffects &= ~CFE_AUTOCOLOR;

    setlocale(LC_ALL, "chs");
    m_text.Replace(TEXT("\r\n"), TEXT("\n"));
    wstring word;
    wstring text(m_text.GetBuffer());
    wstring::size_type index1 = 0;
    wstring::size_type index2 = -1;

    while ((index1 = text.find_first_of(L"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", index1)) != wstring::npos)
    {
        index2 = text.find_first_not_of(L"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", index1);
        word = text.substr(index1, index2-index1);//切分出每个单词

        if (blueText.find(word) != blueText.end())
        {
            fm1.crTextColor = RGB(0, 0, 255);
            m_richedit.SetSel(index1,index2);
            m_richedit.SetSelectionCharFormat(fm1);
        }
        else if (redText.find(word) != redText.end())
        {
            fm1.crTextColor = RGB(255, 0, 0);
            m_richedit.SetSel(index1, index2);
            m_richedit.SetSelectionCharFormat(fm1);
        }

        if (index2 == wstring::npos)
            break;
        else
            index1 = index2 + 1;
    }

    //处理一下注释,因为这是后来加上去的,所以在这里处理,整体效率又被拖低了
    index1 = index2 = 0;
    while ((index1 = text.find(wstring(L"\/\/"), index1)) != wstring::npos)
    {
        index2 = text.find_first_of(L"\n", index1);
        fm1.crTextColor = RGB(0, 255, 0);
        m_richedit.SetSel(index1, index2);
        m_richedit.SetSelectionCharFormat(fm1);
        if (index2 == wstring::npos)
            break;
        else
            index1 = index2;
    }

    m_richedit.SetSel(start, end);
    //m_richedit.SetCaretPos(pos);
    //m_richedit.SetSelectionCharFormat(fm2);//???
}
void CGEditorDlg::OnBnClickedButtonsave()
{
    // TODO:  在此添加控件通知处理程序代码
    UpdateData(TRUE);
    if (IDOK == MessageBox(TEXT("确定保存?"), TEXT("保存")))
    {
        ofstream ofs(m_filename.GetBuffer(),ios::trunc);
        if (!ofs.is_open())
        {
            MessageBox(TEXT("文件保存失败!"));
            ofs.close();
            return;
        }
        m_text.Replace(TEXT("\r\n"),TEXT("\n"));
        m_text.Replace(TEXT("    "), TEXT("\t"));
        setlocale(LC_ALL, "chs");
        ofs.write(CStringA(m_text).GetBuffer(), wcstombs(NULL,m_text.GetBuffer(),NULL));
        ofs.close();
    }
}
void CGEditorDlg::OnEnMsgfilterRichedit(NMHDR *pNMHDR, LRESULT *pResult)
{
    MSGFILTER *pMsgFilter = reinterpret_cast<MSGFILTER *>(pNMHDR);
    // TODO:  控件将不发送此通知,除非您重写
    // CDialogEx::OnInitDialog() 函数,以将 EM_SETEVENTMASK 消息发送
    // 到该控件,同时将 ENM_KEYEVENTS 或 ENM_MOUSEEVENTS 标志
    //“或”运算到 lParam 掩码中。

    // TODO:  在此添加控件通知处理程序代码
    if (pMsgFilter->msg == WM_KEYDOWN && pMsgFilter->wParam == VK_TAB)
    {
        UpdateData(TRUE);
        long start, end;
        m_richedit.GetSel(start, end);
        //CPoint pos = m_richedit.GetCaretPos();
        m_text += TEXT("    ");
        UpdateData(FALSE);//原来这里会改变光标的位置!!!
        //m_richedit.SetCaretPos(pos);
        m_richedit.SetSel(start+4, end+4);
        OnEnChangeRichedit();
        *pResult = 1;
    }
    else
        *pResult = 0;
}

工程地址

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

扫码关注云+社区