文本编辑器

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

效果图:

//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 条评论
登录 后参与评论

相关文章

来自专栏编程坑太多

springboot(16)Shiro

1786
来自专栏水击三千

Silverlight学习(三)

最近对WCFRIA+MVVM+Prism有了初步的认识,能够简单的实现一些数据库的交互。这节主要讲的是Silverlight通过domainservice和ad...

2488
来自专栏battcn

一起来学SpringBoot | 第二十一篇:轻松搞定数据验证(三)

前面两章中详细介绍了数据有效性校验的重要性、自定有数据有效性校验注解 本章也是 轻松搞定数据验证的最后一篇, 一起来揭开神秘的分组验证

822
来自专栏向治洪

仿qq聊天及定位等

聊天其实就是要实现消息推送,而推送消息就需要保持连接(长连接)。在之前项目里虽然实现了即时聊天,但是一种很本的方法。 去掉了其中的网络访问。地图试用的百度AP...

1676
来自专栏技术沉淀

PHP基础

1276
来自专栏FreeBuf

kill.exe溢出漏洞分析与EXP讨论

* 本文原创作者:zzz66686,本文属FreeBuf原创奖励计划,未经许可禁止转载 1. 前言 前几日,笔者在exploit-db上发现了一个kill.ex...

1699
来自专栏杨建荣的学习笔记

一个关于执行计划的小问题测试(r8笔记第60天)

最近有朋友在微信公众号后台留言提了一个问题,问题如下: 执行计划中,并列的两条操作比如并列的两条table access full,上层没有关联操作比如hash...

3347
来自专栏跨界架构师

Aop动态生成代理类时支持带参数构造函数

  在某些情况下,我们需要植入AOP代码的类并没有默认构造函数。那么此时动态生成的代理类也需要相同签名的构造函数,并且内部调用原始类的构造函数。自己折腾了1晚上...

362
来自专栏PHP技术

WordPress的可拓展性初探(一)

作者:西瓜玩偶(racnil070512 at hotmail dot com) WordPress是一个时下非常流行的网络信息发布平台,它的特性之一便是极强...

2859
来自专栏GopherCoder

Python: 实际项目中抽象出的小项目设计Python: 一周笔记

1413

扫描关注云+社区