- 浏览: 1291382 次
-
文章分类
最新评论
-
char1st:
2b 青年 mongodb
我们该如何设计数据库(一) -
什么向往:
二逼青年的做法的确让人有点觉得:靠,这都行!!
我们该如何设计数据库(一) -
cloudmail:
如果只用到name来查询的话,支持2b做法总之,2b做法是最容 ...
我们该如何设计数据库(一)
扩展Edit Box控件的功能
用VC++6.0编程的时候,文本编辑控件Edit Box是一个经常用到的控件。如果你是用它输入一些简单的文字、数字等信息,直接拿来用就可以了,但如果你用它制作大文本的编辑软件,就会觉得不好控制,许多功能无法实现,即便用CEditView,也只会生成一个类似于记事本的东西,再想加入些自己编写的功能也很困难。下面我以CEdit为基类定义了一个CEditBox类,加入了许多文本编辑时经常要用到的接口函数,用它来控制Edit Box控件就很容易制作出具有较强文本编辑功能的编辑软件了。
在这个扩展类中主要增加了以下功能:
①增加控件的容量,使它能容纳大文本;
②可设置编辑控件文字颜色、背景色和字体;
③对控件内的文本和选择文本的访问;
④直接装入文件到控件和保存控件内容到文件;
⑤自定义的右键菜单;
⑥多重ReDo/UnDo功能。
这些功能基本上都是独立的,实际使用时可根据需要选用所需功能。
准备工作:用ClassWizard在工程中加入一个新类,基类选为CEdit,类名设置为CEditBox。
一、设置控件的容量:
EditBox控件默认情况下只能装入64K的文本,如果超出,多出部分会被自动截掉。利用CEdit类的SetLimitText()函数可重新设置控件容量。
函数原型为:
void SetLimitText(UINT nMax);
参数为nMax为控件可接收的文本最大字节数。
设置方法:用ClassWizard在CEditBox类中添加消息函数PreSubclassWindow(),把设置文本容量的语句放在里面即可。
voidCEditBox::PreSubclassWindow() { SetLimitText(-1);//设置编辑控件可接收的最大字节数 CEdit::PreSubclassWindow(); } |
因为nMax为无符号整型,-1是把它设置为可以取到的最大值。你也可以根据需要设置控件的容量。
注意:在不同操作系统下,控件可设置的最大容量也不同。如果是Windows98,这个值就是64K,无法再增大了,而在Windows2000和WindowsXP下这个值要大得多,才可以起到增加控件容量的目的。
二、设置编辑控件的前景色、背景色和字体:
在CEditBox的头文件中加入以下变量定义:
COLORREFm_ForeColor;//文本颜色 COLORREFm_BackColor;//背景色 CBrushm_BkBrush;//背景刷 CFont*p_Font;//字体指针 intm_FontSize;//字体大小(1/10点) CStringm_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) deletep_Font;//回收字体资源 } |
这里只设置了前景色和背景色的默认值,如果想设置默认字体,可在上面的PreSubclassWindow()函数中进行设置:
voidCEditBox::PreSubclassWindow() { SetLimitText(-1);//设置编辑控件可接收的最大字节数 m_FontSize=100; m_FontName=_T("宋体"); p_Font=newCFont;//生成字体对象 p_Font->CreatePointFont(m_FontSize,m_FontName);//创建字体 SetFont(p_Font);//设置控件默认字体 CEdit::PreSubclassWindow(); } |
这里使用了比较简单的CreatePointFont()函数创建字体,它只需给出字体尺寸和字体名。如果想创建更复杂的字体,可以改用CreateFont()函数。本例中设置控件的初始字体为尺寸为100(0.1点)的“宋体”字。
如果你想用EditBox本身的默认字体作为初始字体,就不要在PreSubclassWindow()函数中加入这些语句。
用ClassWizard添加消息反射函数CtlColor()来修改控件的文本颜色和背景色。
注意:在ClassWizard下可看到有两个很相似的消息,一个是“=WM_CTLCOLOR”消息,另一个是“WM_CTLCOLOR”消息,这里必须用“=WM_CTLCOLOR”消息添加函数。如果误用了“WM_CTLCOLOR”消息将得不到想要的效果。
HBRUSHCEditBox::CtlColor(CDC*pDC,UINTnCtlColor) { pDC->SetTextColor(m_ForeColor);//设置控件文字颜色 pDC->SetBkColor(m_BackColor);//设置文字的背景色 return(HBRUSH)m_BkBrush.GetSafeHandle();//控件背景刷 } |
PreSubclassWindow()和CtlColor()函数都是消息函数,为了设置控件颜色和字体,还需定义接口函数在使用时调用:
//设置文本颜色 voidCEditBox::SetForeColor(COLORREFcolor) { m_ForeColor=color; Invalidate(); } //获取文本颜色 COLORREFCEditBox::GetForeColor() { returnm_ForeColor; } //设置背景颜色 voidCEditBox::SetBkColor(COLORREFcolor) { m_BackColor=color; m_BkBrush.Detach(); m_BkBrush.CreateSolidBrush(m_BackColor); Invalidate(); } //获取背景色 COLORREFCEditBox::GetBkColor() { returnm_BackColor; } //设置字体 voidCEditBox::SetTextFont(intFontSize,LPCTSTRFontName) { if(p_Font)deletep_Font; p_Font=newCFont; p_Font->CreatePointFont(FontSize,FontName); SetFont(p_Font); m_FontSize=FontSize; m_FontName=FontName; } //获取字体大小 intCEditBox::GetFontSize() { returnm_FontSize; } //获取字体名 CStringCEditBox::GetFontName() { returnm_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()
intCEditBox::ReadText(CString&str) { GetWindowText(str);//获取控件文本 returnstr.GetLength();//文本长度 } |
参数str是字符串的引用,用于接收读取的控件内容,返回值是控件中文本字节数。
2、用字符串设置控件内容SetText()
voidCEditBox::SetText(LPCTSTRstr) { SetSel(0,-1,true);//全选 ReplaceSel(str);//替换 SetSel(0);//设置插入点为起始位置 } |
参数str是准备设置控件的内容,要求是字符串。
3、读取当前选择的文本ReadSelText()
intCEditBox::ReadSelText(CString&str) { intselStart,selEnd; GetSel(selStart,selEnd);//获取当前选择的位置 intselLen=selEnd-selStart;//求选择区长度 if(selLen) { CStringtext; GetWindowText(text);//获取控件文本 str=text.Mid(selStart,selLen);//获取选择的文本 } else str=_T(""); returnselLen; } |
参数str是字符串的引用,用于接收读出的文本,返回值是读出的文本字节数。
如果当前控件中有内容被选择,则读出选择文本,并返回长度;如果没有选择的文本,读出的是空串,返回为0。
4、设置选择区SetSelText()
voidCEditBox::SetSelText(intnStartChar,intnSelLen) { SetSel(nStartChar,nStartChar+nSelLen); } |
参数nStartChar为选择区起点(从0算起),nSelLen为选择区长度。
功能是把控件的指定区域设置为选择的状态。
5、当前是否有选择isSelect()
BOOLCEditBox::isSelect() { intselStart,selEnd; GetSel(selStart,selEnd);//获取当前选择的位置 returnselEnd-selStart; } |
如果当前控件中有选择的文本,返回非0值,否则返回0。
以上是为了使控件访问更方便而增加的接口函数。再配合CEdit本身提供的访问函数,很多操作都可轻易实现了。
CEdit控件提供访问函数主要有:
int GetWindowText(LPCTSTR lpszStringBuf,int nMaxCount);
获取控件文本,与ReadText()功能相同。
void SetWindowText(LPCTSTR lpszString);
设置控件文本。
void GetSel(int& nStartChar,int& nEndChar);
获取选择区的位置
void SetSel(int nStartChar,int nEndChar,BOOL bNoScroll=FALSE);
设置选择区,参数为起点和终点,用SetSel(0,-1)可设置为全选
void ReplaceSel(LPCTSTR lpszNewText,BOOL bCanUndo=FALSE);
用字符串替换选择的文本
四、与文件的接口:
这部分接口函数供“打开文件”和“保存文件”等操作调用。把它们定义在CEditBox类中,增强了控件的封装性,也可以简化应用中“打开”和“保存”的操作。
1、文件内容装入Edit控件
voidCEditBox::LoadFile(LPCTSTRPathName) { CFilefile;//构造一个CFile类的对象 if(file.Open(PathName,CFile::modeRead)==0)//以读方式打开文件 return; intlen=file.GetLength();//求文件长度 CStringtext=_T(""); file.Read(text.GetBufferSetLength(len),len);//读文件 text.ReleaseBuffer(); file.Close();//关闭文件 SetText(text);//装入编辑控件 m_PathName=PathName; SetModify(false);//清除修改标志 } |
参数PathName为文件路径名,调用该函数可以把指定文件装入编辑控件。如果文件不存在,直接返回。
2、保存编辑控件内容到文件
voidCEditBox::SaveFile(LPCTSTRPathName) { CFilefile; if(file.Open(PathName,CFile::modeCreate|CFile::modeWrite)==0) return; CStringtext; inttextLen=ReadText(text); file.Write((LPCTSTR)text,textLen);//把字符串内容写入文件 file.Close();//关闭文件 m_PathName=PathName; SetModify(false);//清除修改标志 } |
参数PathName为文件路径名,调用该函数可以把控件内容写入指定文件。如果建立文件失败,直接返回。
3、新建文件
voidCEditBox::NewFile() { SetSel(0,-1,true);//全选 Clear();//清除 m_PathName=_T(""); SetModify(false);//清除修改标志 } |
供“新建”文件菜单消息调用,功能是清空控件。
4、是否有文件打开
BOOLCEditBox::isOpenFile() { return!(m_PathName.IsEmpty()); } |
如果控件中已经有打开的文件,返回非0,否则返回0。
5、获取打开的文件名
CStringCEditBox::GetPathName() { returnm_PathName; } |
如果控件中已经有打开的文件,返回文件路径名,否则返回空串。
这5个函数中的m_PathName是在CEditBox中定义的字符串变量,并初始化为空串。
五、自定义右键菜单:
文本编辑框已经提供了一个默认右键菜单,如果你想重新定义一个来代替它,可以按下面的方法制作。
在VC++的Project菜单下选择Add To Project下的Components and Controls,在弹出的对话框中打开Visual C++ Components,找到Pop-up Menu,单击Insert按钮,选择加入的类为CEditBox,确定。关闭对话框。
这时,你在CEditBox类中会看到已经加入了下面的代码:
voidCEditBox::OnContextMenu(CWnd*,CPointpoint) { //CG:ThisblockwasaddedbythePop-upMenucomponent { if(point.x==-1&&point.y==-1){ //keystrokeinvocation CRectrect; GetClientRect(rect); ClientToScreen(rect); point=rect.TopLeft(); point.Offset(5,5); } CMenumenu; 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的新菜单,编辑它就可得到你想要的右键菜单了。这和其它菜单的做法没有区别,我就不再详细介绍了。
http://221.199.150.103/jsj/Html/vc/wen/vcwen10.htm
六、多重UnDo/ReDo功能:
Edit Box控件提供了UnDo功能,但只能撤销一次操作,要想实现多重UnDo/ReDo功能需要自己设计。
UnDo:撤销上一次修改操作,实现时应保存最近几次修改。
ReDo:重做上一次撤销的操作,如果你撤销后后悔了,就ReDo吧。
1、数据结构
利用一个结构数组作为栈保存最近几次修改操作,定义如下:
#defineUNDOMAX30//栈深度(最大Undo次数) //可撤销的操作名 #defineOP_DELSEL1//删除选择(剪切) #defineOP_REPLACE2//替换选择 #defineOP_DELETE3//删除 #defineOP_BACK4//Backspace #defineOP_INPUT5//输入 //Undo/Redo栈结构 typedefstruct { intop;//操作名 intpos;//操作的位置 CStringstr1;//旧内容 CStringstr2;//新内容 }STACKNODE; private: STACKNODEm_Stack[UNDOMAX];//工作栈 intutop;//Undo栈顶指针 intubottom;//Undo栈底指针 intrtop;//Redo栈顶指针 intrbottom;//Redo栈底指针 BOOLb_DelFlag;//删除标志 |
UNDOMAX是预定义的栈深度,这里定义为30,表示可撤销最近的30步操作。
STACKNODE结构用来定义栈节点,对每一次修改操作,需要纪录修改的位置,修改前的内容和修改后的内容。而且不同的修改操作在撤销时会略有不同,所以还需纪录修改操作名。
所有修改可归结为5种:
OP_DELSEL:删除选择的文本,此时str1保存被删除的文本,str2为空;
OP_REPLACE:替换选择的文本,str1为被换掉的文本,str2为新文本;
OP_DELETE:用Del键删除文本,str1保存被删除的文本,str2为空;
OP_BACK:用BackSpace键删除文本,str1保存被删除的文本,str2为空;
OP_INPUT:键盘输入新文本,str1为空,str2为新输入的文本。
其它的操作都可归纳到这5种之内,如剪切就是OP_DELSEL,粘贴就是OP_REPLACE。
m_Stack是长度为UNDOMAX的栈,它既是UnDo栈,也是ReDo栈,栈指针utop、ubottom确定UnDo栈位置,rtop、rbottom确定ReDo栈位置。
2、栈操作
①初始化工作栈
voidCEditBox::InitStack() { for(inti=0;i<UNDOMAX;i++)//栈空间 { m_Stack[i].op=-1; m_Stack[i].str1=_T(""); m_Stack[i].str2=_T(""); } utop=0;//栈指针 ubottom=0; rtop=0; rbottom=0; } |
②入栈
voidCEditBox::Push(STACKNODE*pNode) { utop=(utop+1)%UNDOMAX;//修改栈顶指针 rtop=utop;//清空Redo栈 rbottom=utop; if(utop==ubottom)//如果栈满 ubottom=(ubottom+1)%UNDOMAX;//修改栈底指针 m_Stack[utop]=*pNode;//入栈 } |
每次修改操作时,把纪录修改的节点推入栈中。栈采用环形结构,当栈满时,新入栈的节点覆盖栈底节点,也就淘汰了最早进入栈内节点。
③UnDo出栈
STACKNODE*CEditBox::UnDoPop() { if(utop==ubottom)//栈空 returnNULL; STACKNODE*p=&m_Stack[utop]; rtop=utop;//Redo入栈 utop=utop-1;//退栈 if(utop<0) utop=UNDOMAX-1; returnp;//返回退栈节点 } |
当进行UnDo操作时,从utop指示的栈顶弹出记录最近一次修改的节点,但这个节点并不删除,通过修改rtop使它进入ReDo栈,供ReDo操作时重做被撤销的操作。所以,这个操作既是UnDo出栈,也是ReDo进栈。
④ReDo出栈
STACKNODE*CEditBox::RedoPop() { if(rtop==utop) returnNULL; STACKNODE*p=&m_Stack[rtop]; utop=(utop+1)%UNDOMAX;//Undo入栈 if(rtop==rbottom)//如果Redo栈满 { rtop=utop;//修改栈底指针 rbottom=utop; } else rtop=(rtop+1)%UNDOMAX;//修改栈顶指针 returnp;//返回出栈的节点 } |
当进行ReDo操作时,从rtop指示的栈顶弹出记录去恢复被撤销的操作,同时通过修改utop使它重新进入UnDo栈,供UnDo操作使用。所以,这个操作执行了ReDo出栈,也执行了UnDo进栈。
这个栈的变化方式如图所示:
UnDo栈和ReDo栈共享一个数组空间,ub和ut是UnDo栈的栈底指针和栈顶指针,rb和rt是ReDo栈的栈底指针和栈顶指针。初始时它们均相等,这时为空栈(图a)。当进行修改操作时,修改结构进栈,修改ut到新的栈顶,同时rb和rt同步移动,ReDo栈仍为空(图b)。当进行撤销操作时,把ut指示的修改结构取出恢复内容,修改ut表示结构从UnDo栈退出,同时修改rt,使结构进入ReDo栈(图c)。恢复撤销时,用rt指示的结构进行恢复。如果不恢复,新的修改进入UnDo栈,同时让rt和rb跟踪ut,使ReDo栈清空。
这个空间是个环形空间,栈满时修改栈底指针淘汰陈旧内容。
⑤取栈顶
STACKNODE*CEditBox::GetTop() { if(utop==ubottom) returnNULL; return&m_Stack[utop]; } |
取UnDo栈的栈顶元素,但不修改栈。
3、UnDo/ReDo操作
①保存可撤销的操作
voidCEditBox::SetUndo(intop,intpos,LPCTSTRstr1,LPCTSTRstr2) { STACKNODE*ptop=GetTop(); if(op==OP_DELETE&&ptop&&ptop->op==OP_DELETE&&ptop->pos==pos) { ptop->str1+=str1; return; } STACKNODEnode; node.op=op; node.pos=pos; node.str1=str1; node.str2=str2; Push(&node);//入栈 } |
每做一次修改操作,通过调用SetUndo()函数把修改操作保存到栈中。参数依次为操作名、修改位置、旧内容和新内容。
函数中先根据参数填写好STACKNODE节点,再把它推入栈内即可。
这里对OP_DELETE操作做了一个特殊处理,当我们用Del键在同一位置连续删除多个字符时,应该记录为一个操作,在撤销时一次性恢复。所以当操作为OP_DELETE时,如果发现上一次操作也是OP_DELETE,且位置相同,则把新删除的字符连接到上次删除的字符串中就行了。
②处理Del键和BackSpace键
用按键消息检测是否进行了Del和BackSpace键操作,并进行相应处理。
voidCEditBox::OnKeyDown(UINTnChar,UINTnRepCnt,UINTnFlags) { CStringText,SelStr; intpos,SelLen; GetText(pos,Text,SelStr,SelLen); if(nChar==VK_DELETE&&!Text.IsEmpty())//Del键 { if(SelLen) SetUndo(OP_DELSEL,pos,SelStr,_T(""));//保存删除内容 else { if(Text[pos]<0||Text[pos]==0x0D||Text[pos]==0x0A) SetUndo(OP_DELETE,pos,Text.Mid(pos,2),_T(""));//删除的是汉字或回车 else SetUndo(OP_DELETE,pos,Text.Mid(pos,1),_T(""));//删除的是字符 } b_DelFlag=true; } elseif(nChar==VK_BACK&&pos>=0)//BackSpace键 { if(SelLen) SetUndo(OP_DELSEL,pos,SelStr,_T(""));//保存删除的内容 else { if(pos>0&&Text[pos-1]<127&&Text[pos-1]>=0x20) SetUndo(OP_BACK,pos-1,Text.Mid(pos-1,1),_T("")); elseif(pos>1&&(Text[pos-2]<0||Text[pos-1]==0x0D||Text[pos-1]==0x0A)) SetUndo(OP_BACK,pos-2,Text.Mid(pos-2,2),_T("")); } b_DelFlag=true; } CEdit::OnKeyDown(nChar,nRepCnt,nFlags); } |
OnKeyDown()函数用ClassWizard添加到CEditBox类中。当检测到Del键或BackSpace键时,如果此时有选择的文本,就保存为“删除选择OP_DELSEL”操作,如果没有选择的文本再保存为“OP_DELETE”操作或“OP_BACK”操作。另外,删除字符和删除汉字也有所区别,如果删除位置为半角字符,就取一个字符进入UnDo栈,如果删除位置处为汉字,就取两个字节进入UnDo栈。
③处理键盘输入
用ClassWizard添加OnChar()函数处理键盘输入,与OnKeyDown()函数不同,OnChar()函数只在输入可打印字符时才响应,用它可过滤掉各种控制键,而OnKeyDown()函数对任何按键都要响应,所以Del键只能用它来处理。
voidCEditBox::OnChar(UINTnChar,UINTnRepCnt,UINTnFlags) { CStringSelStr; ReadSelText(SelStr); intpos1,end,pos2; GetSel(pos1,end);//获取输入前的光标位置 CEdit::OnChar(nChar,nRepCnt,nFlags);//处理键盘输入 if(!b_DelFlag) { CStringText,str; GetWindowText(Text); GetSel(pos2,end);//获取输入后的光标位置 str=Text.Mid(pos1,pos2-pos1); SetUndo(OP_INPUT,pos1,SelStr,str);//保存到UnDo栈 } b_DelFlag=false; } |
为了处理汉字的输入,在处理按键函数CEdit::OnChar前纪录光标位置,这个位置是输入文字前的位置,在CEdit::OnChar函数后再求得的光标位置是输入文字后的位置,两者之间的符号就是应该保存的撤销内容。
这里有个缺陷,就是当输入汉字词组后,撤销时只能一个字一个字的撤销,不能一下撤销整个数组,不知该如何改进。
b_DelFlag用于防止Del键和BackSpace键被重复处理。
4、接口函数
CEditBox增加了UnDo/ReDo功能后,原来的那些涉及修改控件内容的操作就需要重新设计,使它们能够被撤销,所以设计了新的接口函数。
①isCanUndo()和isCanRedo()
判断当前是否有可撤销和可重做的操作。用于激活或禁止UnDo/ReDo菜单。
//判断能否撤销 BOOLCEditBox::isCanUndo() { returnutop!=ubottom; } //判断能否重做 BOOLCEditBox::isCanRedo() { returnutop!=rtop; } |
当存在可撤销或可重做的操作(栈非空)时返回TRUE,否则返回FALSE。
②EditUndo()和EditRedo()
EditUndo()函数执行撤销操作,EditRedo()函数执行重做操作。供UnDo/ReDo菜单调用。
//撤销 voidCEditBox::EditUndo() { STACKNODE*p=UnDoPop();//出栈 if(p) { SetSelText(p->pos,p->str2.GetLength());//选择文本 ReplaceSel(p->str1);//恢复内容 } } //重做 voidCEditBox::EditRedo() { STACKNODE*p=RedoPop();//出栈 if(p) { SetSelText(p->pos,p->str1.GetLength());//选择文本 ReplaceSel(p->str2);//恢复内容 } } |
③EditReplace()和RepAll()
EditReplace()函数是用指定文本替换选择的文本。RepAll()是用指定文本重置编辑控件内容。
//替换选择 voidCEditBox::EditReplace(LPCTSTRstr) { CStringText,SelStr; intpos,SelLen; GetText(pos,Text,SelStr,SelLen); SetUndo(OP_REPLACE,pos,SelStr,str);//保存到Undo ReplaceSel(str);//替换选择 } //替换全部 voidCEditBox::RepAll(LPCTSTRstr) { SetSel(0,-1);//全选 EditReplace(str);//替换 SetSel(0);//设置插入点为起始位置 } |
EditReplace()函数用来代替CEdit类的ReplaceSel()函数,两者功能一致,但用EditReplace()函数做的操作可以撤销,而ReplaceSel()函数做的操作不能撤销。
RepAll()函数用来代替SetWindowText()和前面定义的SetText(),用它做的操作可以撤销。
④剪切和粘贴
CEdit类的Cut()和Paste()函数都需要重新设计,而复制操作Copy()由于不修改文本,可照常使用。
//剪切(代替Cut()) voidCEditBox::EditCut() { CStringText,SelStr; intpos,SelLen; GetText(pos,Text,SelStr,SelLen); SetUndo(OP_DELSEL,pos,SelStr,_T(""));//保存到Undo Cut();//剪切 } //粘贴(代替Paste()) voidCEditBox::EditPaste() { OpenClipboard();//打开剪贴板 HANDLEStrHandle; StrHandle=::GetClipboardData(CF_TEXT); char*pMem; pMem=(char*)::GlobalLock(StrHandle); CStringstr; str=pMem; ::GlobalUnlock(StrHandle); CloseClipboard();//关闭剪贴板 if(!str.IsEmpty()) EditReplace(str);//粘贴 } //全部剪切 voidCEditBox::EditCutAll() { SetSel(0,-1);//全选 EditCut();//剪切 } //全部复制 voidCEditBox::EditCopyAll() { SetSel(0,-1);//全选 Copy();//复制 } //全部删除 voidCEditBox::EditClearAll() { SetSel(0,-1);//全选 EditReplace(_T(""));//清空 } |
七、CEditBox类的使用:
CEditBox类与CEdit类的用法基本相同。你可以在对话框里加入一个Edit Box控件,设置属性Multiline(多行文本)、Vertical scroll(垂直滚动条)、Want return(接收回车),并取消Auto HScroll属性(自动换行);用ClassWizard为控件添加变量,类型设置为CEditBox;再加入头文件#include "EditBox.h";之后就可以根据需要编程控制这个编辑控件了。
再解决一个小问题,就是Tab键的输入问题。
在界面上,Tab键起到选择控件的功能,这导致无法在编辑控件中输入Tab符。
解决方法是:
先在资源中定义一个Tab快捷键:打开资源的Accelerator下的IDR_MAINFRAME,在快捷键表中添加一个VK_TAB的快捷键,假设ID设置为ID_KEY_TAB;
回到视类,用ClassWizard为ID_KEY_TAD添加消息函数OnKeyTab(),在其中加入代码:
//处理Tab输入 voidCEditTestView::OnKeyTab() { m_EditBox.EditReplace(_T("\t")); } |
这里的m_EditBox就是编辑控件的控制变量。
这样CEditBox类就做好了,它的完整代码见示例程序中的EditBox.h和EditBox.cpp。
示例程序是利用CEditBox类制作的一个文本编辑器,它具有了记事本的多数功能。它还具有以下特征:可设置编辑区的字体、颜色;利用ini文件保存设置;有字数统计功能,支持查找/替换操作等。它本身就是一个可代替记事本的好用的编辑器。在此基础上,你可以根据需要添加更多的功能。
示例程序界面图:
http://221.199.150.103/jsj/Html/vc/wen/vcwen11.htm
相关推荐
通过这样的方式,我们不仅可以使Edit控件响应keydown事件,还能扩展到其他类型的控件,实现各种自定义的键盘交互。这种编程技巧在创建具有复杂用户交互的Windows应用时非常有用。理解并熟练运用消息映射和消息处理...
然而,在某些情况下,我们可能需要利用Edit控件来模拟静态文本的功能,同时结合ToolTip来提供额外的信息。这个"Using Edit box as static Text Control for displaying ToolTip"的主题就是关于如何巧妙地结合这两者...
VC2010实现扩展list控件,可对list控件进行编辑写入,编辑功能包含edit控件、Combo Box控件、Radio控件、DataTime Piker 控件。代码见网站内其他资源,请搜索:《史上最详细的扩展List控件制作代码》。
10. **扩展功能**:探索ALXGrid可能提供的高级特性,如排序、过滤、分页、拖放操作等,以及如何实现这些功能。 通过上述知识点的学习和实践,开发者可以充分利用ALXGrid的强大功能,构建出高效且用户友好的数据管理...
`VC++之Edit Box控件.htm`涉及基本的文本输入控件——Edit Box,用户可以在此输入和编辑文本,开发者可以通过编程来获取或设置输入的文字。 `VC++之Scroll Bar.htm`是关于滚动条控件的,滚动条允许用户在内容超出...
总的来说,"C#十六进制显示控件"是C#开发环境中的一种实用工具,它扩展了标准UI控件的功能,使得开发者在处理二进制数据时有了更直观、强大的手段。通过深入理解并有效利用这类控件,可以提高开发效率,优化用户体验...
编辑框(Edit Box)是用户输入文本的地方,通常用于收集用户的信息。自定义编辑框类可以实现如下的增强功能: 1. **格式化输入**:比如限制输入的字符类型,如只允许数字、字母或邮箱地址。 2. **实时验证**:在...
在本例中,我们讨论的是如何在编辑框(Edit Box)中实现这种功能,即“Edit DropFile”,使得用户可以将文本文件如txt、bat、cmd以及VC++的源文件等直接拖放到编辑框中,以便查看或编辑内容。以下是对这一技术的详细...
8. **增强型编辑框(Enhanced Edit Box)**:可能包含语法高亮、自动完成等功能,适合于代码编辑或文本处理。 9. **触摸友好控件(Touch-Friendly Controls)**:优化了触摸操作,适用于触屏设备的应用。 这些...
CXListCtrl是一个基于MFC(Microsoft Foundation Classes)库的扩展控件,它是在标准的CListCtrl基础上进行了增强,以提供更丰富的功能。在这个“CXListCtrl-x64_编辑框_列表控件_下拉框_复选框_”项目中,开发者...
本程序“BehindListbox.zip”着重讲解了如何利用ListBox控件和Edit控件模拟COMBO Box的功能,同时展示了如何控制ListBox后面的相关控件,这对于开发自定义控件或者优化UI设计是非常有价值的。 COMBO Box是Windows ...
总结来说,MFC ActiveX控件的开发涉及属性的添加、编辑框(EditControl box)和静态文本(Static Text)的使用,以及在Visual C++ 2008环境下进行的编程工作。通过理解并熟练掌握这些知识点,开发者能够创建具有复杂...
2. **编辑框(Edit Box)**:允许用户在ListCtrl的特定单元格中直接编辑数据,增强了用户与数据的交互性,常用于数据输入或修改。 3. **复选框(Checkbox)**:复选框是ListCtrl中常用的表示数据状态的控件,用户...
5.27 Visual C++ 2010 Check Box控件 5.27 简介与开发 262 5.28 Visual C++ 2010 Radio Button 5.28 控件简介与开发 264 5.28.1 为单选按钮控件分组 264 5.28.2 获得被选中的单选按钮的 5.28.2 文本 264 5.29 Visual...
通过以上步骤,我们不仅可以将Delphi的VCL控件封装为ActiveX控件供VB使用,还可以进一步定制和扩展这些控件的功能。这种方式极大地拓宽了不同编程语言间的互操作性,有助于开发者更好地利用现有资源和技术,提高开发...
自定义控件通常基于现有控件进行扩展,添加新的功能或改变外观。 7. **对话框和消息框**:对话框(Dialog Box)是用于与用户进行特定交互的窗口,如打开文件对话框(OpenFileDialog)或保存文件对话框...
CEdit是MFC中表示文本编辑控件的类,相当于Windows API中的EDIT控件。你可以使用CEdit类来创建单行或多行文本输入框。在C++代码中,你可以设置CEdit的属性,如文字内容、字体样式,以及处理它的消息,例如EN_CHANGE...
- 控件是构成Windows界面的基本元素,MFC支持丰富的标准控件,如按钮(Button)、编辑框(Edit Control)、列表框(List Box)等。 - 文档提到了控件的非客户端区域(nonclientarea)和客户区域(clientarea),...
这个项目不仅涉及基本控件的创建,还涵盖了自定义Message Box图标以及处理动态添加控件数量不确定的情况。 首先,让我们了解动态添加控件的基本概念。在Windows程序设计中,静态控件是在设计时通过界面设计器预先...
最简单的做法是从编辑框(Edit Box)入手,将其改造为单元格类。这里我们将从`CEdit`类派生出`CCell`类,并进行必要的定制。 ##### `CCell`类的实现 1. **响应焦点事件**:为了使单元格具备交互性,我们需要关注...