文本编辑器

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

效果图:

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

相关文章

来自专栏java学习

Hibernate学习笔记2

定义hbm.xml映射文件和pojo类时都需要定义主键,Hibernate中定义的主键类型包括:自然主键和代理主键:

874
来自专栏Jackson0714

【T-SQL基础】02.联接查询

3619
来自专栏hbbliyong

由一道面试题来了解进程间的通信

周末面试碰到一个面试题,题目是: 在MMO游戏中,服务器采用Linux操作系统,网络通信与游戏逻辑处理进程一般是分离的。 例如:GameSvr进程处理游戏逻辑,...

6347
来自专栏Golang语言社区

Go语言并发与并行学习笔记

Go语言的并发和并行 不知道你有没有注意到一个现象,还是这段代码,如果我跑在两个goroutines里面的话: var quit chan int = make...

3605
来自专栏更流畅、简洁的软件开发方式

【开源】QuickPager ASP.NET2.0分页控件 v2.0.0.2版本。

下载地址:http://files.cnblogs.com/jyk/Page2.0.0.2_080701.rar 这回只有 dll文件。请把包里的文件拷贝到...

1896
来自专栏依乐祝

Redis基本使用及百亿数据量中的使用技巧分享

熟悉的开场白,大家晚上好啊,今天给大家分享的是Redis在大数据中的使用,可能真正讲的是一些redis的使用技巧,Redis基本的一些东西。

740
来自专栏美团技术团队

【技术博客】Spark性能优化指南——基础篇

前言 在大数据计算领域,Spark已经成为了越来越流行、越来越受欢迎的计算平台之一。Spark的功能涵盖了大数据领域的离线批处理、SQL类处理、流式/实时计算、...

3786
来自专栏跟着阿笨一起玩NET

Quartz.Net使用总结

1、Quartz区分NET3.5和NET4.0版本,故新建项目的时候,引用的DLL一定要匹配net freamwork的正确版本。

791
来自专栏Jed的技术阶梯

Spark性能调优04-数据倾斜调优

数据倾斜的原理很简单:在进行shuffle的时候,必须将各个节点上相同的key拉取到某个节点上的一个task来进行处理,比如按照key进行聚合或join等操作。...

1395
来自专栏王亚昌的专栏

妥善处理解决网络I/O瓶颈

Linux 异步 I/O 是 Linux 内核中提供的一个相当新的增强。它是 2.6 版本内核的一个标准特性,但是我们在 2.4 版本内核的补丁中也可以找到它。...

943

扫码关注云+社区