首页 > 代码库 > CEdit

CEdit

 CEdit类提供了Windows编辑控件中的功能。编辑控件是一个子窗口矩形,用户可以向其中输入文本。

  可以通过对话模板或直接从代码中创建一个编辑控件。在两种情形下,首先调用CEdit构造程序构造CEdit对象,再调用Create成员函数创建Windows编辑控件并将其与CEdit对象连接。

  构造在CEdit派生类中可以单步实现。为派生类编写构造程序并从构造程序中调用Create

  CEditCWnd继承了重要的功能,要在CEdit对象中设置或获取文本,使用CWnd成员函数SetWindowTextGetWindowText,可以设置和得到编辑控件的全部内容,即使它是一个多行控件。如果编辑控件是多行的,使用CEdit成员函数GetLineGetSelGetSelReplaceSel来获取和写入控件的部分文本。

  如果要处理编辑控件发往其父类(通常是一个CDialog派生类)的通知消息,则向父类中为每一消息添加一个消息映射入口和消息处理成员函数。

  各消息映射入口可采用如下形式:

  ON_Notification(id,memberFxn)

  其中id指定了发送通知的编辑控件的子窗口IDmemberFxn为你写好的处理通知的父成员函数的名字。

  父函数形式如下:

  afx_msg void memberFxn();

  下面是一组可能的消息映射入口,以及在何种情况下向父类发送的描述:

·

ON_EN_CHANGE

用户采取的行动可能会改变编辑控件的文本。与EN_UPDATE通知消息不同,该通知是在Windows更新显示之后发送的。

·

ON_EN_ERRSPACE

编辑控件不能为特定请求分配足够的空间。

·

ON_EN_HSCROLL

用户单击了编辑控件中的水平滚动条,父窗口在屏幕更新之前被通知。

·

ON_EN_KILLFOCUS

编辑控件失去输入焦点。

·

ON_EN_MAXTEXT

当前输入超过了为编辑控件指定的数目,并作截尾处理。当编辑控件不具有ON_EN_HSCROLL风格且要输入的字符会超过编辑控件的宽度时,发送消息。当编辑控件不具有ON_EN_VSCROLL风格且要输入的字符会超过编辑控件的高度时,也会发送消息。

·

ON_EN_SETFOCUS

编辑控件获得焦点。

·

ON_EN_UPDATE

编辑控件将要显示变动的文本。在控件对文本格式化之后但在显示文本之前发送消息,以便在必要时改变窗口尺寸。

·

ON_EN_VSCROLL

用户单击了编辑控件中的垂直滚动条,父窗口在屏幕更新之前被通知。

如果在对话框内创建CEdit对象,CEdit对象在用户关闭对话框时自动被删除。

  如果使用对话框编辑器从对话资源中创建CEdit对象,CEdit对象在用户关闭对话框时自动被删除。

  如果在窗口内创建CEdit对象,也需要删除它。如果在栈上创建CEdit对象,它被自动删除。如果使用new函数在堆上创建CEdit对象,在用户中止编辑控件时,必须对其调用delete来删除它。如果在CEdit对象中分配存储空间,覆盖CEdit析构程序来处理分配情况。

  #include <afxwin.h>

  CEdit类的成员

  构造函数

CEdit

构造一个CEdit控件对象

Create

创建一个Windows编辑控件,并将其与CEdit对象连接

  属性

CanUndo

决定一个编辑控件操作是否能够被撤销

GetLineCount

获得多行编辑控件中的行数

GetModify

决定编辑控件的内容是否被修改

SetModify

为编辑控件设置或清除修改标记

GetRect

为编辑控件获取格式化的矩形

GetHandle

获得为当前多行编辑控件分配的内存的句柄

SetHandle

设置为多行编辑控件使用的本地内存的句柄

SetMargins

CEdit设置左边和右边的空白边界

GetMargins

获得为CEdit设置左边和右边的空白边界

SetLimitText

设置CEdit能够容纳的文本的最大量

GetLimitText

获得CEdit能够容纳的文本的最大量

PosFromChar

获得指定字符索引的左上角的坐标

CharFromPos

获得最靠近指定位置的字符的行和字符索引

GetLine

从编辑控件中获得一行文本

GetPasswordChar

获得当用户输入文本时在编辑控件中显示的口令

GetFirstVisibleLeLine

决定在编辑控件中最顶部的可视的行

  操作

EmptyUndoBuffer

重新设置(清除)编辑控件的撤销标记

FmtLines

设置在多行编辑控件中的软回车打开或关闭

LimitText

用户在输入文本时的文本长度限制

LineFromChar

获得包含指定字符索引的行的数目

LineIndex

获得在多行编辑控件中的某行的字符索引

LineLength

获得编辑控件中的行的长度

LineScroll

在多行编辑控件中滚动文本

ReplaceSel

用指定文本覆盖编辑控件中当前被选中的文本

SetPasswordChar

设置或清除当用户输入文本时在编辑控件中显示的口令

SetRect

设置多行编辑控件的带格式的矩形,并更新该控件

SetRectNP

设置多行编辑控件的带格式的矩形,而不必重新绘制

SetSel

在编辑控件中选定文本SetTabStops设置多行编辑控件的制表键停顿位

SetReadOnly

为编辑控件设置只读状态

  剪贴板操作

Undo

撤销上一次的编辑控件操作

Clear

删除(清除)编辑控件中当前选中的文本

Copy

将编辑控件中的当前选中文本以CF_TEXT格式拷贝到剪贴板中

Cut

删除编辑控件中当前选中的文本,并将删除的文本以CF_TEXT格式拷贝到剪贴板中

Paste

在当前光标位置插入剪贴板内的文本。只有在剪贴板数据为CF_TEXT格式时才进行插入

CEdit::SetLimitText

void SetLimitText( UINT nMax );

参数说明

nMax

The new text limit, in bytes.

新的文本限制,以字节计算。

备注

Call this member function to set the text limit for this CEdit object. The text limit is the maximum amount of text, in bytes, that the edit control can accept.

调用此成员函数设置编辑控件中的文本的长度限制。此限制是编辑控件可以接收的以字节形式表示的文本大小。

Changing the text limit restricts only the text the user can enter. It has no effect on any text already in the edit control, nor does it affect the length of the text copied to the edit control by the SetWindowText member function in CWnd. If an application uses the SetWindowText function to place more text into an edit control than is specified in the call toLimitText, the user can delete any of the text within the edit control. However, the text limit will prevent the user from replacing the existing text with new text, unless deleting the current selection causes the text to fall below the text limit.

改变文本限定仅使用户能输入的文本受到限制,而对已在编辑控件中的文本没有影响,也不影响用CWnd中的SetWindowText成员函数能拷贝到编辑控件中的文本的长度。如果用SetWindowText函数输入的文本超过调用LimitText函数所指定的值,则用户可以在编辑控件中删除任何文本,但文本限制会禁止用户将已存在的文本替换为新文本,直到删除当前所选文本而使文本大小降至限制以内。

 

 

详情:

VC++6.0编程的时候,文本编辑控件Edit Box是一个经常用到的控件。如果你是用它输入一些简单的文字、数字等信息,直接拿来用就可以了,但如果你用它制作大文本的编辑软件,就会觉得不好控制,许多功能无法实现,即便用CEditView,也只会生成一个类似于记事本的东西,再想加入些自己编写的功能也很困难。下面我以CEdit为基类定义了一个CEditBox类,加入了许多文本编辑时经常要用到的接口函数,用它来控制Edit Box控件就很容易制作出具有较强文本编辑功能的编辑软件了。

在这个扩展类中主要增加了以下功能:

①增加控件的容量,使它能容纳大文本;
②可设置编辑控件文字颜色、背景色和字体;
③对控件内的文本和选择文本的访问;
④直接装入文件到控件和保存控件内容到文件;
⑤自定义的右键菜单;
⑥多重ReDo/UnDo功能。

这些功能基本上都是独立的,实际使用时可根据需要选用所需功能。

准备工作:用ClassWizard在工程中加入一个新类,基类选为CEdit,类名设置为CEditBox

一、设置控件的容量:

EditBox控件默认情况下只能装入64K的文本,如果超出,多出部分会被自动截掉。利用CEdit类的SetLimitText()函数可重新设置控件容量。

函数原型为:

void SetLimitText(UINT nMax);

参数为nMax为控件可接收的文本最大字节数。

设置方法:用ClassWizardCEditBox类中添加消息函数PreSubclassWindow(),把设置文本容量的语句放在里面即可。

void CEditBox::PreSubclassWindow()
{
    SetLimitText( -1 );    //设置编辑控件可接收的最大字节数
    CEdit::PreSubclassWindow();
}

因为nMax为无符号整型,-1是把它设置为可以取到的最大值。你也可以根据需要设置控件的容量。

注意:在不同操作系统下,控件可设置的最大容量也不同。如果是Windows98,这个值就是64K,无法再增大了,而在Windows2000WindowsXP下这个值要大得多,才可以起到增加控件容量的目的。

二、设置编辑控件的前景色、背景色和字体:

CEditBox的头文件中加入以下变量定义:

COLORREF    m_ForeColor;       //文本颜色
COLORREF    m_BackColor;       //背景色
CBrush      m_BkBrush;         //背景刷
CFont*      p_Font;            //字体指针
int         m_FontSize;        //字体大小(1/10点)
CString     m_FontName;        //字体名

CEditBox的构造函数中设置它们的初值:

CEditBox::CEditBox()
{
    m_ForeColor = RGB(0,0,0);          //文字颜色(黑)
    m_BackColor = RGB(255,255,255);    //文字背景色(白)
    m_BkBrush.CreateSolidBrush(m_BackColor);   //背景刷
    p_Font = NULL;        //字体指针
}

CEditBox的析构函数中回收创建的字体资源:

CEditBox::~CEditBox()
{
    if( p_Font )
        delete p_Font;    //回收字体资源
}

这里只设置了前景色和背景色的默认值,如果想设置默认字体,可在上面的PreSubclassWindow()函数中进行设置:

void CEditBox::PreSubclassWindow()
{
    SetLimitText( -1 );    //设置编辑控件可接收的最大字节数
    
    m_FontSize = 100;
    m_FontName = _T("宋体");
    p_Font = new CFont;    //生成字体对象
    p_Font->CreatePointFont( m_FontSize, m_FontName );  //创建字体
    SetFont( p_Font );     //设置控件默认字体

    CEdit::PreSubclassWindow();
}

这里使用了比较简单的CreatePointFont()函数创建字体,它只需给出字体尺寸和字体名。如果想创建更复杂的字体,可以改用CreateFont()函数。本例中设置控件的初始字体为尺寸为1000.1点)的"宋体"字。

如果你想用EditBox本身的默认字体作为初始字体,就不要在PreSubclassWindow()函数中加入这些语句。

ClassWizard添加消息反射函数CtlColor()来修改控件的文本颜色和背景色。

注意:在ClassWizard下可看到有两个很相似的消息,一个是"=WM_CTLCOLOR"消息,另一个是"WM_CTLCOLOR"消息,这里必须用"=WM_CTLCOLOR"消息添加函数。如果误用了"WM_CTLCOLOR"消息将得不到想要的效果。

HBRUSH CEditBox::CtlColor(CDC* pDC, UINT nCtlColor)
{
    pDC->SetTextColor( m_ForeColor );    //设置控件文字颜色
    pDC->SetBkColor( m_BackColor );      //设置文字的背景色
    return (HBRUSH)m_BkBrush.GetSafeHandle();  //控件背景刷
}

PreSubclassWindow()CtlColor()函数都是消息函数,为了设置控件颜色和字体,还需定义接口函数在使用时调用:

//设置文本颜色
void CEditBox::SetForeColor(COLORREF color)
{
    m_ForeColor = color;
    Invalidate();
}

//获取文本颜色
COLORREF CEditBox::GetForeColor()
{
    return m_ForeColor;
}

//设置背景颜色
void CEditBox::SetBkColor(COLORREF color)
{
    m_BackColor = color;
    m_BkBrush.Detach();
    m_BkBrush.CreateSolidBrush( m_BackColor );
    Invalidate();
}

//获取背景色
COLORREF CEditBox::GetBkColor()
{
    return m_BackColor;
}

//设置字体
void CEditBox::SetTextFont(int FontSize,LPCTSTR FontName)
{
    if ( p_Font )    delete p_Font;
       p_Font = new CFont;
    p_Font->CreatePointFont( FontSize, FontName );
    SetFont( p_Font );
    m_FontSize = FontSize;
    m_FontName = FontName;
}

//获取字体大小
int CEditBox::GetFontSize()
{
    return m_FontSize;
}

//获取字体名
CString CEditBox::GetFontName()
{
    return m_FontName;
}

至此,用CEditBox类可以定义出可设置颜色和字体的Edit Box控件了。使用时,先在对话框中加入一个Edit Box控件,用ClassWizard为定义一个控制变量m_Edit,类型设定为CEditBox。然后用m_Edit.SetForeColor(color)m_Edit.SetBkColor()m_Edit.SetTextFont(FontHight,FontName)为控件设置颜色和字体,这样就可以作出一个美观的文本框了。

说明:Edit Box控件只能放入纯文本,不支持对文本格式的设置,也就不能对局部的文字颜色和字体进行设置,所以,以上设置都是针对整个控件的。

三、访问编辑控件的内容:

Edit Box控件已经提供了几种访问控件内容的方法:

①定义一个与控件关联的变量,类型可设置为CString或其它类型,用UpdateData()函数来更新控件或变量。

②用GetWindowText()获取控件内文本,用SetWindowText()设置控件文本。

③用SetSel()设置控件内的选择区,用GetSel()获取控件中选择文本的位置,用ReplaceSel()替换选择的文本。

但只用这几种方法还是不太方便,所以在CEditBox类中又增加了几个访问接口函数。

1、读取控件文本ReadText()

int CEditBox::ReadText(CString& str)
{
    GetWindowText( str );        //获取控件文本
    return str.GetLength();      //文本长度
}

参数str是字符串的引用,用于接收读取的控件内容,返回值是控件中文本字节数。

2、用字符串设置控件内容SetText()

void CEditBox::SetText(LPCTSTR str)
{
    SetSel( 0, -1, true );    //全选
    ReplaceSel( str );        //替换
    SetSel(0);                //设置插入点为起始位置
}

参数str是准备设置控件的内容,要求是字符串。

3、读取当前选择的文本ReadSelText()

int CEditBox::ReadSelText(CString& str)
{
    int selStart, selEnd;
    GetSel( selStart, selEnd );      //获取当前选择的位置
    int selLen = selEnd-selStart;    //求选择区长度
    if( selLen )
    {
        CString text;
        GetWindowText( text );      //获取控件文本
        str = text.Mid( selStart, selLen );  //获取选择的文本
    }
    else
        str = _T("");
    return selLen;
}

参数str是字符串的引用,用于接收读出的文本,返回值是读出的文本字节数。

如果当前控件中有内容被选择,则读出选择文本,并返回长度;如果没有选择的文本,读出的是空串,返回为0

4、设置选择区SetSelText()

void CEditBox::SetSelText(int nStartChar,int nSelLen)
{
    SetSel(nStartChar,nStartChar+nSelLen);
}

参数nStartChar为选择区起点(从0算起),nSelLen为选择区长度。

功能是把控件的指定区域设置为选择的状态。

5、当前是否有选择isSelect()

BOOL CEditBox::isSelect()
{
    int selStart, selEnd;
    GetSel( selStart, selEnd );     //获取当前选择的位置
    return selEnd-selStart;
}

如果当前控件中有选择的文本,返回非0值,否则返回0

以上是为了使控件访问更方便而增加的接口函数。再配合CEdit本身提供的访问函数,很多操作都可轻易实现了。

CEdit控件提供访问函数主要有:

int GetWindowText(LPCTSTR lpszStringBuf,intnMaxCount);
获取控件文本,与ReadText()功能相同。

void SetWindowText(LPCTSTR lpszString);
设置控件文本。

void GetSel(int& nStartChar,int& nEndChar);
获取选择区的位置

void SetSel(int nStartChar,intnEndChar,BOOL bNoScroll=FALSE);
设置选择区,参数为起点和终点,用SetSel(0,-1)可设置为全选

void ReplaceSel(LPCTSTR lpszNewText,BOOLbCanUndo=FALSE);
用字符串替换选择的文本

四、与文件的接口:

这部分接口函数供"打开文件""保存文件"等操作调用。把它们定义在CEditBox类中,增强了控件的封装性,也可以简化应用中"打开""保存"的操作。

1、文件内容装入Edit控件

void CEditBox::LoadFile(LPCTSTR PathName)
{
    CFile file;        //构造一个CFile类的对象
    if( file.Open( PathName, CFile::modeRead )==0 )  //以读方式打开文件
        return;
    int len = file.GetLength();        //求文件长度
    CString text = _T("");
    file.Read( text.GetBufferSetLength(len), len );  //读文件
    text.ReleaseBuffer();
    file.Close();                   //关闭文件
    SetText( text );                //装入编辑控件
    m_PathName = PathName;
    SetModify( false );        //清除修改标志
}

参数PathName为文件路径名,调用该函数可以把指定文件装入编辑控件。如果文件不存在,直接返回。

2、保存编辑控件内容到文件

void CEditBox::SaveFile(LPCTSTR PathName)
{
    CFile file;
    if( file.Open( PathName, CFile::modeCreate | CFile::modeWrite )==0 )
        return;
    CString text;
    int textLen = ReadText( text );
    file.Write( (LPCTSTR)text, textLen ); //把字符串内容写入文件
    file.Close();            //关闭文件
    m_PathName = PathName;
    SetModify( false );      //清除修改标志
}

参数PathName为文件路径名,调用该函数可以把控件内容写入指定文件。如果建立文件失败,直接返回。

3、新建文件

void CEditBox::NewFile()
{
    SetSel( 0, -1, true );  //全选
    Clear();                //清除
    m_PathName = _T("");
    SetModify( false );     //清除修改标志
}

"新建"文件菜单消息调用,功能是清空控件。

4、是否有文件打开

BOOL CEditBox::isOpenFile()
{
    return !(m_PathName.IsEmpty());
}

如果控件中已经有打开的文件,返回非0,否则返回0

5、获取打开的文件名

CString CEditBox::GetPathName()
{
    return m_PathName;
}

如果控件中已经有打开的文件,返回文件路径名,否则返回空串。

5个函数中的m_PathName是在CEditBox中定义的字符串变量,并初始化为空串。

五、自定义右键菜单:

文本编辑框已经提供了一个默认右键菜单,如果你想重新定义一个来代替它,可以按下面的方法制作。

VC++Project菜单下选择AddTo Project下的Components and Controls,在弹出的对话框中打开Visual C++Components,找到Pop-up Menu,单击Insert按钮,选择加入的类为CEditBox,确定。关闭对话框。

这时,你在CEditBox类中会看到已经加入了下面的代码:

void CEditBox::OnContextMenu(CWnd*, CPoint point)
{
    // CG: This block was added by the Pop-up Menu component
    {
        if (point.x == -1 && point.y == -1){
            //keystroke invocation
            CRect rect;
            GetClientRect(rect);
            ClientToScreen(rect);
            point = rect.TopLeft();
            point.Offset(5, 5);
        }
        CMenu menu;
        VERIFY(menu.LoadMenu(CG_IDR_POPUP_EDIT_BOX));
        CMenu* pPopup = menu.GetSubMenu(0);
        ASSERT(pPopup != NULL);
        CWnd* pWndPopupOwner = this;
        while (pWndPopupOwner->GetStyle() & WS_CHILD)
            pWndPopupOwner = pWndPopupOwner->GetParent();
        pPopup->TrackPopupMenu(TPM_LEFTALIGN | TPM_RIGHTBUTTON, point.x, point.y,
            pWndPopupOwner);
    }
}

再到资源的Menu下,你可以找到一个ID号为CG_IDR_POPUP_EDIT_BOX的新菜单,编辑它就可得到你想要的右键菜单了。这和其它菜单的做法没有区别,我就不再详细介绍了。

  

1.List ControlCheck Box
SetExtendedStyle方法可以设置,看代码:
CListCtrl m_ListCtrl;

DWORD dwStyle = m_ListCtrl.GetStyle();
dwStyle |= LVS_EX_CHECKBOXES;
m_ListCtrl.SetExtendedStyle(dwStyle);

2.List BoxCheck Box
首先,声明Control变量的时候用CCheckListBox代替CListBox
然后,将List BoxHas Strings属性改为True;把Ower Draw属性改为Fixed

3.Spin ControlEdit Control的绑定
首先,要让Spin ControlTap Order紧跟着Edit Control(就是说,Spin ControlTap OrderEdit ControlTap Order1)。
然后,设置Spin ControlAuto BuddySet Buddy Integer属性为True

4.可以设置背景和文字颜色的Static控件
CStatic类继承一个自己的Static类,相应WM_CTLCOLOR消息。下面是代码:
.h
文件:

class ClxStatic : public CStatic
{
    DECLARE_DYNAMIC(ClxStatic)
public:
    ClxStatic();
    virtual ~ClxStatic();

    afx_msg HBRUSH CtlColor(CDC* /*pDC*/, UINT /*nCtlColor*/);

    void SetBackColor(COLORREF clrBack);
    void SetTextColor(COLORREF clrText);

protected:
    DECLARE_MESSAGE_MAP()

    CBrush m_brushBack;
    COLORREF m_clrBack;
    COLORREF m_clrText; 
};

.cpp文件:

IMPLEMENT_DYNAMIC(ClxStatic, CStatic)
ClxStatic::ClxStatic()
{
    m_clrBack = ::GetSysColor(COLOR_BTNFACE);
    m_clrText = ::GetSysColor(COLOR_BTNTEXT);
}

ClxStatic::~ClxStatic()
{
}

void ClxStatic::SetBackColor(COLORREF clrBack)
{
    m_clrBack = clrBack;
}

void ClxStatic::SetTextColor(COLORREF clrText)
{
    m_clrText = clrText;
}

BEGIN_MESSAGE_MAP(ClxStatic, CStatic)
    ON_WM_CTLCOLOR_REFLECT()
END_MESSAGE_MAP()

HBRUSH ClxStatic::CtlColor(CDC* pDC, UINT /*nCtlColor*/)
{
    // TODO:  Change any attributes of the DC here
    m_brushBack.Detach();
    m_brushBack.CreateSolidBrush(m_clrBack);

    pDC->SetBkColor(m_clrBack);
    pDC->SetTextColor(m_clrText);

    // TODO:  Return a non-NULL brush if the parent‘s handler should not be called
    //return NULL;
    return (HBRUSH)m_brushBack.GetSafeHandle();
}

5.Static控件中显示BMP
首先,给Static控件添加一个Control变量(ID要改了以后才能添加变量,也就是说ID不能为IDC_STATIC),本例为m_staticTest
然后,用ModifyStyle函数修改Static控件的Style,让它可以显示图片:

m_staticTest.ModifyStyle(0, SS_BITMAP | SS_CENTERIMAGE);

最后,就是Load文件显示出来:

CRect rect;
m_staticTest.GetWindowRect(&rect);

//  
下面的方法是按照Static控件的大小显示bmp,如果要安装图片实际大小显示,用这个方法Load图片:
//  HBITMAP hBmp = (HBITMAP)::LoadImage(0, _T("D:\test.bmp"), IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE);
HBITMAP hBmp = (HBITMAP)::LoadImage(0, _T("D:\test.bmp"), IMAGE_BITMAP, rect.Width(), rect.Height(), LR_LOADFROMFILE);

m_staticTest.SetBitmap(hBmp);
DeleteObject(hBmp);

CEdit