锐英源软件
第一信赖

精通

英语

开源

擅长

开发

培训

胸怀四海 

第一信赖

当前位置:锐英源 / 开源技术 / C++开源心得 / VC++开发简单文本编辑器
服务方向
人工智能数据处理
人工智能培训
kaldi数据准备
小语种语音识别
语音识别标注
语音识别系统
语音识别转文字
kaldi开发技术服务
软件开发
运动控制卡上位机
机械加工软件
软件开发培训
Java 安卓移动开发
VC++
C#软件
汇编和破解
驱动开发
联系方式
固话:0371-63888850
手机:138-0381-0136
Q Q:396806883
微信:ryysoft

锐英源精品开源,禁止转载和任何形式的非法内容使用,违者必究


VC++开发简单文本编辑器


介绍

文本编辑器是可以处理文本文件的常用应用程序。文本编辑器的主要功能包括“打开/保存文件”,“编辑/查看内容”等。在本教程中,我们将介绍如何构建基于WTL的简单文本编辑器。

如何使用代码?

我们假设读者有一个支持ATL / WTL的Visual C ++。如果是这样,源代码可以直接用作VC ++项目。如果没有,读者应该做一些额外的工作来准备开发环境。

  1. 获取并在您的系统上安装Visual C ++程序。Visual C ++的版本应该高于6.0,因为Visual C ++ 6.0版之后提供了内置的完整的STL支持。如果您必须使用VC6.0,则需要在系统中安装STL库STLPort并将VC6.0设置为使用STL库。
  2. 获取并安装与您的Visual C ++程序兼容的Windows驱动程序包(WDK)。WDK包括WTL所必需的独立ATL / MFC工具。确保WDK头文件、库文件和可执行文件的路径包含在Visual C ++的环境设置中。
  3. 获取并安装一个开源WTL工具。最新的WTL版本为8.1。在WTL安装包中,有几个相应版本的VC ++的安装脚本。

创建一个WTL项目

通过WTL项目向导创建C ++项目,我们可以为文档视图选择基类。CEdit类 和CRichEditCtrl类 都可能是一个简单的文本编辑器的基础。CRichEditCtrl 是Windows ActiveX控件richedt20.dll 的WTL包装 ,而CEdit是一个基于Windows API的WTL作品。作为一个简单的文本编辑程序,CEdit 类还行。我们需要做的是加强CEdit的功能并实现一个简单的文本编辑器。

打开并保存文本

通过WTL项目向导创建的初始项目提供了一个基本的程序框架。作为一个完整的可执行程序,它提供了基本的GUI,包括窗口、menu、工具栏、工作区和状态栏,以及用户友好的入口点来定制其程序行为。
我们可以在工作区输入文本,但输入结果无法保存,程序也无法打开存在的文本文件。原因是默认文件打开/保存行为为空。我们首先将文件打开并保存功能加到到程序中,如下所示。

读取文件并在CEdit视图中显示内容


HANDLE hFile = ::CreateFile(sPath, GENERIC_READ, 0, 0,
OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN, 0);
if(INVALID_HANDLE_VALUE == hFile) return false;

DWORD dwSizeLow = GetFileSize(hFile, 0);
char* pbBuff = (char*)malloc(dwSizeLow+1);
DWORD pcb = 0;

DWORD dwRet = ::ReadFile(hFile, pbBuff, dwSizeLow, (LPDWORD)&pcb, NULL);
pbBuff[dwSizeLow] = '\0';

::CloseHandle(hFile);

ATLASSERT(::IsWindow(m_hWnd));

::SendMessage(m_hWnd, WM_SETTEXT, 0, (LPARAM)pbBuff);
delete pbBuff;

将CEdit视图中的内容保存到文件中


HANDLE hFile = ::CreateFile(sPath, GENERIC_WRITE,
0, 0, CREATE_ALWAYS, FILE_FLAG_WRITE_THROUGH, 0);
if(INVALID_HANDLE_VALUE == hFile) return false;

ATLASSERT(::IsWindow(m_hWnd));

DWORD dwSizeLow = ::GetWindowTextLength(m_hWnd);
char* pbBuff = (char*)malloc(dwSizeLow+1);
::SendMessage(m_hWnd, WM_GETTEXT, (WPARAM)dwSizeLow, (LPARAM)pbBuff);
pbBuff[dwSizeLow] = '\0';

DWORD pcb = 0;
DWORD dwRet = ::WriteFile(hFile, pbBuff, dwSizeLow, (LPDWORD)&pcb, NULL);

::CloseHandle(hFile);

基本文本编辑功能

CEdit 类支持基本的文本编辑操作,我们可以输入文本,复制/粘贴/剪切在工作区中的文本。然而, CEdit 编辑操作是通过操纵它的内部数据完成。因为我们的文本编辑程序需要做一些自定义操作,所以我们基于我们自己的数据结构来实现基本的编辑操作。

定义数据结构

我们使用STL列表string 来存储内容。


#include <vector>
#include <string>

vector<string> m_contents;

不同数据结构之间的映射

每个string 包含一个文本行,默认情况下,我们使用两个字符'\ r'\ n'来完成一行并开始一个新行。我们知道,与我们的方法不同,CEdit 类将内容视为长字符序列。如果我们在工作区域中选择文本,CEdit 函数GetSel()将返回当前选择的位置。我们必须将通过GetSel() 函数获得的位置映射到我们m_contents变量内的位置。例如,内容...


[
Hello world!

foo
]

...被默认处理为序列“Hello world!\ r \ n \ r \ n foo”,我们将它视为字符串“Hello world!\ r \ n”“\ r \ n” “富”。序列中的位置17为“f”,而其对应位置为[2,0],即char 第三个位置的第一位string。映射函数如下所示:


GetRowColFromPosition(int& nRow, int &nCol, int nPosition)
{
int len = 0;
int size = m_rawText.size();
nCol = nPosition;
for(nRow=0;nRow<size;nRow++) {
len = m_rawText[nRow].size();
if(nCol > len)
nCol -= len;
else {
if(nCol == len && size - nRow > 1) {
nCol = 0; nRow++;
}
break;
}
}
}

位置映射后,仍然需要处理文本编辑的消息。这些消息包括WM_CHAR,WM_KEYDOWN,...

处理WM_CHAR消息

当编辑器 通过WM_CHAR 消息捕获用户输入char时,CEdit 该类将更改保存到其内部数据结构中,并将其反映在工作区上。但是,我们可以通过重叠来自定义程序行为,或者使用函数“ OnChar”来处理WM_CHAR 消息。


BEGIN_MSG_MAP(CEditExView)
MESSAGE_HANDLER(WM_KEYDOWN, OnKeyDown)
MESSAGE_HANDLER(WM_CHAR, OnChar)
END_MSG_MAP()

OnChar主要过程 首先在工作区定位当前选定的内容,然后通过输入char替换所选内容。重要的是编辑器应该识别控件的字符并正确处理它们。例如,当输入为“ return” VK_RETURN,程序应将string 对象分成两个string 对象,但不能简单地替换所选内容。


int CEditExView::InsertAt(int nSelectionStart, TCHAR chNewChar)
{
int nInsertionPoint=nSelectionStart;
int nRow = 0;
int nCol = 0;
GetRowColFromPosition(nRow, nCol, nInsertionPoint);

          if(chNewChar==VK_RETURN)
{
string line1 = m_rawText[nRow].substr(0, nCol);
line1.append(1, '\r').append(1, '\n');
string line2 = m_rawText[nRow].substr(nCol, m_rawText[nRow].size());
m_rawText[nRow] = line2;
m_rawText.insert(m_rawText.begin() + nRow, line1);
nInsertionPoint++;
}
else if (chNewChar == VK_TAB)
{
for(int i=0;i<m_TabCount;i++) {
nInsertionPoint = nCol++;
m_rawText[nRow].insert(nInsertionPoint, 1, _T(' '));
}
}
else
m_rawText[nRow].insert(nCol, &chNewChar);

          return nInsertionPoint;
}

处理WM_KEYDOWN消息

WM_KEYDOWN 这里的消息用于处理“ insert”  VK_INSERT。每按一次VK_INSERT 键,编辑模式应在INSERT 模式和REPLACE 模式之间切换。


LRESULT CEditExView::OnKeyDown(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
{
UINT nChar = (TCHAR)wParam;

          BOOL bIsShiftKeyDown=::GetAsyncKeyState(VK_SHIFT)<0;
BOOL bIsCtrlKeyDown=::GetAsyncKeyState(VK_CONTROL)<0;

          if(nChar == VK_INSERT) {
if (!bIsShiftKeyDown && !bIsCtrlKeyDown)
{
// The standard CEdit control does not support over-typing.
// This flag is used to manage over-typing internally.
SetInsertMode(!GetInsertMode());
}
}
return 0;
}

友情链接
版权所有 Copyright(c)2004-2021 锐英源软件
公司注册号:410105000449586 豫ICP备08007559号 最佳分辨率 1024*768
地址:郑州大学北校区院(文化路97号院)内