重写TEdit文本编辑框
2015-10-12 12:17
567 查看
重写TEdit文本编辑框,实现功能如下:
1、输入文本/获取文本,设置字体
2、插入/删除中英文
3、键盘方向键移动光标位置
4、鼠标点击定位字符位置
5、自绘画光标位置
难点:
1、通过定时器,自绘光标
2、从中文输入法中读取文字
3、鼠标定位字符位置
未实现的功能:
1、鼠标多选字符
2、复制、粘贴等右键菜单功能
虽然,上面的功能没有,但就已有的功能来说,基本能适用了。
TWinEditControl.hpp代码内容如下:
头文件中:
1、输入文本/获取文本,设置字体
2、插入/删除中英文
3、键盘方向键移动光标位置
4、鼠标点击定位字符位置
5、自绘画光标位置
难点:
1、通过定时器,自绘光标
2、从中文输入法中读取文字
3、鼠标定位字符位置
未实现的功能:
1、鼠标多选字符
2、复制、粘贴等右键菜单功能
虽然,上面的功能没有,但就已有的功能来说,基本能适用了。
TWinEditControl.hpp代码内容如下:
#ifndef __TWINEDITCONTROL__ #define __TWINEDITCONTROL__ #include "gdi.h" #include "TTimeControl.hpp" class TWinEditControl :public TCustomControl { private: TCanvas * FCanvas; int m_left,m_top,m_width,m_height; Graphics::TBitmap * m_background_bmp; //背景图 TNotifyEvent FOnChange; //定义外部事件 WideString m_edit_text; //输入编辑中的文本 bool m_getFocus; //获得焦点 bool m_mouse_move; //鼠标滑过编辑框 unsigned int m_border_color; //边框颜色 unsigned int m_mouse_move_border_color; //鼠标在上面时的颜色 unsigned int m_getfocus_border_color; //焦点颜色 TTimeControl * TTimerCursorShow; //定时器显示光标 void __fastcall OnTimer(TObject * Sender);//定时器函数 int m_cursorPos; //光标位置 void DrawCursor(); //画光标 AnsiString m_text; //控件的属性text AnsiString GetText(); //读文本内容 void SetText(AnsiString value); //写文本内容 void SetTipText(AnsiString value); //设置提示内容 bool m_tiptext; //初始提示内容 int m_text_width; //文字内容的总宽度 int m_single_width; //单个文字的宽度 int m_count; //容纳文字总数 int m_char_pos; //光标所在字符的位置 int TestStrWidth(WideString str); //测试字符串宽度 void ChCursor(WideString str); //中文光标处理 WideString SubEditString(); //当文字长度超出范围时,取部分显示 void MouseToCursor(int X); //通过鼠标点击,获取字符串位置和光标位置 void AddStrToEdit(WideString str); //增加新字符串 void DeleteStr(); //删除字符串 void KeyCursor(WORD Key); //方向键改变时,光标位置 protected: void Draw(); //集中绘图函数 void DrawEditText();//显示内部文字 BEGIN_MESSAGE_MAP VCL_MESSAGE_HANDLER(CM_MOUSELEAVE, TMessage, MouseLeave) VCL_MESSAGE_HANDLER(CM_MOUSEENTER, TMessage, MouseEnter) VCL_MESSAGE_HANDLER(/*WM_IME_CHAR*/WM_IME_COMPOSITION,TMessage ,InputText) VCL_MESSAGE_HANDLER(WM_CHAR ,TMessage ,InputChar) VCL_MESSAGE_HANDLER(WM_KILLFOCUS,TMessage ,KillFocus) VCL_MESSAGE_HANDLER(CM_WANTSPECIALKEY,TMessage,DirectKey) END_MESSAGE_MAP(TCustomControl) void __fastcall MouseLeave(TMessage & msg);//鼠标离开控件 void __fastcall MouseEnter(TMessage & msg);//鼠标进入控件 void __fastcall InputText(TMessage & msg); //截获文字输入消息 void __fastcall InputChar(TMessage & msg); //输入单个字符 void __fastcall KillFocus(TMessage & msg); //失去焦点 void __fastcall DirectKey(TMessage & msg); //方向键 public: void SetSize(TRect &r); //-------------------------------------------------- __fastcall TWinEditControl(TComponent* Owner); __fastcall ~TWinEditControl(); //--------------------------------------------------父类成员函数 void __fastcall Paint(void); void __fastcall CreateParams(TCreateParams &Params); DYNAMIC void __fastcall MouseUp(TMouseButton Button, Classes::TShiftState Shift, int X, int Y); DYNAMIC void __fastcall MouseDown(TMouseButton Button, Classes::TShiftState Shift, int X, int Y); DYNAMIC void __fastcall MouseMove(Classes::TShiftState Shift, int X, int Y); //DYNAMIC void __fastcall KeyUp(Word &Key, Classes::TShiftState Shift); //DYNAMIC void __fastcall KeyPress(char &Key); virtual void __fastcall SetFocus(void); //属性 __property Graphics::TCanvas* Canvas = {read=FCanvas}; __property Width; __property Height; __property Font; __property AnsiString Text={read = GetText,write=SetText}; __property AnsiString TipText={read=m_text,write=SetTipText};//提示内容 __property TNotifyEvent OnChange={read=FOnChange,write=FOnChange}; }; __fastcall TWinEditControl::TWinEditControl(TComponent* Owner) : TCustomControl(Owner) { TCustomControl * Win = (TCustomControl *)(Owner); this->Parent = Win; m_background_bmp = new Graphics::TBitmap; FCanvas = TCustomControl::Canvas; //-------------------------------------------------- m_border_color = 0xffC7C7C7; //正常边框颜色 m_mouse_move_border_color = 0xff1583DD ;//鼠标在上面时的边框颜色 m_getfocus_border_color = 0xff9EC2DF; //鼠标焦点在编辑框中时的颜色 //-------------------------------------------------- //光标定时器 TTimerCursorShow = new TTimeControl(this->Handle,20,1000); TTimerCursorShow->OnTime = OnTimer; m_cursorPos = 0; //-------------------------------------------------- GdiInit(); } void __fastcall TWinEditControl::CreateParams(TCreateParams &Params) { TWinControl::CreateParams(Params); } void TWinEditControl::SetSize(TRect &r) { this->Left = r.left; this->Top = r.top; this->Width = r.Width(); this->Height = r.Height(); m_left = r.left; m_top = r.top; m_width= r.Width(); m_height=r.Height(); m_background_bmp->Width = m_width; m_background_bmp->Height= m_height; //-------------------------------------------- GdiCreateHandle1(m_background_bmp->Canvas->Handle); GdiFillRectSolidBrush(0xffffffff,0,0,m_width,m_height); GdiReleaseGraphics(); Draw(); Paint(); } void TWinEditControl::Draw() { GdiCreateHandle1(m_background_bmp->Canvas->Handle); //--------------------------------------------------- GdiFillRectSolidBrush(0xffffffff,0,0,m_width,m_height);//清空原有内容 //画外边框 if(m_mouse_move == false) { GdiPen(m_border_color,1); GdiDrawRectangle(0,0,m_width-1,m_height-1); } else //鼠标在上面时,点亮边框 { GdiPen(m_mouse_move_border_color,1); GdiDrawRectangle(0,0,m_width-1,m_height-1); } //处理编辑状态时,再绘加粗边框 if(m_getFocus) { GdiPen(m_mouse_move_border_color,1); GdiDrawRectangle(0,0,m_width-1,m_height-1); GdiPen(m_getfocus_border_color,1); GdiDrawRectangle(1,1,m_width-3,m_height-3); } //显示文字 DrawEditText(); //--------------------------------------------------- GdiReleaseGraphics(); DrawCursor();//画光标 } void __fastcall TWinEditControl::Paint(void) { TRect a(0,0,m_width,m_height); TRect b(0,0,m_width,m_height); FCanvas->CopyRect(a,m_background_bmp->Canvas,b); } //鼠标进入控件区 void __fastcall TWinEditControl::MouseEnter(TMessage & msg) { this->Cursor = crIBeam; m_mouse_move = true; Draw(); Paint(); } //鼠标离开控件区 void __fastcall TWinEditControl::MouseLeave(TMessage & msg) { if(!m_getFocus) //未处于编辑状态 { m_mouse_move = false; Draw(); Paint(); } this->Cursor = crDefault; } void __fastcall TWinEditControl::MouseUp(TMouseButton Button, Classes::TShiftState Shift, int X, int Y) { } void __fastcall TWinEditControl::MouseDown(TMouseButton Button, Classes::TShiftState Shift, int X, int Y) { this->SetFocus();//设置光标 if(m_tiptext) //清空提示文字 { m_edit_text = ""; m_text = ""; m_cursorPos = 0; m_tiptext = false;//恢复颜色 } else //文本框中有输入的内容时 { MouseToCursor(X); } Draw(); Paint(); } void __fastcall TWinEditControl::MouseMove(Classes::TShiftState Shift, int X, int Y) { } __fastcall TWinEditControl::~TWinEditControl() { delete TTimerCursorShow; delete m_background_bmp; } //从输入法获取输入的中文 void __fastcall TWinEditControl::InputText(TMessage & msg) { HIMC hIMC; HWND hWnd = this->Handle; DWORD dwSize; WCHAR lpWideStr[100]; hIMC = ImmGetContext(hWnd);//获取输入法窗口句柄 if(!hIMC)return; if(msg.LParam & GCS_RESULTSTR)//判断空格键取字上屏 { dwSize = ImmGetCompositionStringW(hIMC, GCS_RESULTSTR, NULL, 0);//读取字数 dwSize =dwSize + sizeof(WCHAR); memset(lpWideStr, 0, 100);//清空字符区 //再次调用,获得unicode字符串 ImmGetCompositionStringW(hIMC, GCS_RESULTSTR, lpWideStr, dwSize); WideString strText(lpWideStr); if(m_edit_text.Length() < 180)//总长度小于180个字符 { AddStrToEdit(strText);//添加新内容 } ImmReleaseContext(hWnd, hIMC);//释放输入法句柄 Draw(); Paint(); //文本框内容改变事件 if(FOnChange) { FOnChange(this); } } } //显示文字 void TWinEditControl::DrawEditText() { m_background_bmp->Canvas->Font->Assign(Font); m_background_bmp->Canvas->Brush->Color = clWhite; m_background_bmp->Canvas->FillRect(TRect(3,3,m_width-4,m_height-4)); m_background_bmp->Canvas->Brush->Style = bsClear;//文字区域透明 if(m_tiptext)//是否为提示内容 m_background_bmp->Canvas->Font->Color = 0x808080; else m_background_bmp->Canvas->Font->Color = Font->Color; if(m_edit_text.IsEmpty() == false) { m_background_bmp->Canvas->TextOut(3,4,SubEditString().c_bstr()); } } //输入单个字符,字母或数字 void __fastcall TWinEditControl::InputChar(TMessage & msg) { int l_inputchar = msg.WParam; if(l_inputchar == 8)//删除字符 { DeleteStr(); } else { if(isascii(l_inputchar)) { if(m_edit_text.Length() < 180)//总长度小于180个字符 { AddStrToEdit(WideString((wchar_t)msg.WParam));//添加新内容 } } } m_text = m_edit_text;//存到属性中 Draw(); Paint(); if(FOnChange) { FOnChange(this); } } //重载父类的焦点处理函数 void __fastcall TWinEditControl::SetFocus(void) { TWinControl::SetFocus();//焦点移到当前控件 m_getFocus = true; Draw(); Paint(); } //失去焦点响应函数 void __fastcall TWinEditControl::KillFocus(TMessage & msg) { m_mouse_move = false; m_getFocus = false; Draw(); Paint(); } //文字宽度大于控件宽度时,显示部分字符串 WideString TWinEditControl::SubEditString() { if(!m_edit_text.IsEmpty()) { m_text_width = TestStrWidth(m_edit_text); //测试全部文字宽度 m_single_width = TestStrWidth(m_edit_text.SubString(1,1));//单个文字宽度 m_count = m_width / m_single_width; //控件能显示文字总个数 if(m_edit_text.Length() >= m_count) { AnsiString l_sub_string = m_edit_text.SubString(m_edit_text.Length()-m_count+1,m_count); m_cursorPos = TestStrWidth(l_sub_string); return l_sub_string; } } //m_cursorPos = m_background_bmp->Canvas->TextWidth(m_edit_text);//光标位置 return m_edit_text; } void __fastcall TWinEditControl::OnTimer(TObject * Sender) { if(this->Focused()) { Draw(); Paint(); } } //读文本内容 AnsiString TWinEditControl::GetText() { return m_text; } //写文本内容 void TWinEditControl::SetText(AnsiString value) { m_text = value; m_edit_text = value; Draw(); Paint(); } //画光标 void TWinEditControl::DrawCursor() { if(this->Focused()) { m_background_bmp->Canvas->Pen->Mode = pmNotXor; if(m_background_bmp->Canvas->Pen->Color == clBlack) m_background_bmp->Canvas->Pen->Color = clWhite; else m_background_bmp->Canvas->Pen->Color = clBlack; m_background_bmp->Canvas->Pen->Style = psSolid; m_background_bmp->Canvas->MoveTo(m_cursorPos+3,4); m_background_bmp->Canvas->Pen->Width = 1; m_background_bmp->Canvas->LineTo(m_cursorPos+3,18); } } //设置提示内容 void TWinEditControl::SetTipText(AnsiString value) { m_text = value; m_edit_text = value; m_tiptext = true; Draw(); Paint(); } int TWinEditControl::TestStrWidth(WideString str) { int l_width = m_background_bmp->Canvas->TextWidth(str); return l_width; } //中文光标 void TWinEditControl::ChCursor(WideString str) { if(m_edit_text.Length() == 0) { m_cursorPos = 0; m_char_pos = 0; m_text_width= 0; } if(m_cursorPos == m_text_width)//添加在尾部 { m_edit_text = m_edit_text + str; m_text = m_edit_text; m_char_pos = m_edit_text.Length(); } else //插入字符串在中间 { m_edit_text.Insert(str,m_char_pos+1); m_char_pos++; } m_cursorPos = m_cursorPos + TestStrWidth(str); } //拦截方向键 void __fastcall TWinEditControl::DirectKey(TMessage & msg) { if(msg.WParam ==37 || msg.WParam ==38 || msg.WParam ==39 || msg.WParam ==40) { OutputDebugStringA(AnsiString(msg.WParam).c_str()); KeyCursor(msg.WParam); //光标处理 msg.Result = 1; } } //通过鼠标点击获取字符在字符串中位置和光标位置 //参数为鼠标点击的横坐标 void TWinEditControl::MouseToCursor(int X) { int l_totalwidth = TestStrWidth(m_edit_text);//总宽度 if(X >= l_totalwidth) { m_cursorPos = l_totalwidth; m_char_pos = m_edit_text.Length();//字符串末尾 } if(X <= 3 )//3为左边矩 { m_cursorPos = 0; m_char_pos = 0; } //鼠标在字符串范围内 if(X > 3 && X < l_totalwidth) { int i=0; int l_charwidth = 0;//单个字符宽度累加和 while( i < m_edit_text.Length()) { l_charwidth += TestStrWidth(m_edit_text.SubString(i,1)); if(l_charwidth > X) { m_char_pos = i;//光标所在字符位置(第1个字符,为1) m_cursorPos=TestStrWidth(m_edit_text.SubString(1,m_char_pos)); break; } i++; } } } //向编辑框中增加字符 void TWinEditControl::AddStrToEdit(WideString str) { int l_strwidth = TestStrWidth(str); m_edit_text.Insert(str,m_char_pos+1); m_char_pos = m_char_pos + str.Length(); m_cursorPos += TestStrWidth(str); m_text = m_edit_text;//存到属性中,外部调用 } //删除字符串 void TWinEditControl::DeleteStr() { if(m_cursorPos <= 0) { m_char_pos = 0; m_cursorPos= 0; return; } WideString l_char = m_edit_text.SubString(m_char_pos,1); int l_char_width = TestStrWidth(l_char); m_edit_text.Delete(m_char_pos,1); //删除在符 m_cursorPos = m_cursorPos - l_char_width;//光标位置减少 --m_char_pos; //字符位置减少 if(m_edit_text.IsEmpty()) { m_cursorPos = 0;//光标位置 m_char_pos = 0; } m_text = m_edit_text;//存到属性中,外部调用 } //方向键移动时光标位置 int flag = 0;//按一次方向键会出现两次消息 void TWinEditControl::KeyCursor(WORD Key) { flag++; if(Key == 37 && flag == 2)//按下左向键 { if(m_cursorPos <= 0) { m_cursorPos = 0; m_char_pos = 0; } else { WideString l_char = m_edit_text.SubString(m_char_pos,1); int l_char_width = TestStrWidth(l_char); m_cursorPos = m_cursorPos - l_char_width;//光标位置减少 m_char_pos--; //字符位置减少 } Draw(); Paint(); flag = 0 ; } if(Key == 39 && flag == 2) { int l_edit_width = TestStrWidth(m_edit_text);//字符串总宽度 if(m_cursorPos >= l_edit_width) //大于总宽度 { m_cursorPos = l_edit_width; m_char_pos = m_edit_text.Length(); } else { WideString l_char = m_edit_text.SubString(m_char_pos+1,1); int l_char_width = TestStrWidth(l_char); m_cursorPos = m_cursorPos + l_char_width;//光标位置减少 m_char_pos++; //字符位置减少 } Draw(); Paint(); flag = 0; } } #endif调用方法如下:
头文件中:
#include "TWinEditControl.hpp" TWinEditControl * TEditControl;.CPP文件如下:
__fastcall TForm1::TForm1(TComponent* Owner) : TForm(Owner) { TEditControl = new TWinEditControl(this); TEditControl->SetSize(TRect(130,150,280,173)); TEditControl->TipText = "请输入用户名"; TEditControl->OnChange = OnChange; } //--------------------------------------------------------------------------- void __fastcall TForm1::Button1Click(TObject *Sender) { this->Caption = TEditControl->Text; } //--------------------------------------------------------------------------- void __fastcall TForm1::OnChange(TObject * Sender) { this->Caption = TEditControl->Text; } void __fastcall TForm1::Button2Click(TObject *Sender) { TEditControl->Font->Color = clGreen; }//---------------------------------------------------------------------------
相关文章推荐
- 使用火狐的restclient发送http接口post及get请求
- linux的lsof命令
- Linux 系统挂载数据盘
- Docker 学习笔记(三)--Docker镜像与仓库
- 数据库基础
- 导出excel 利用xml文件
- 指针的指针
- 两个字符串是变位词
- poj_1236 强连通分支
- BFS && DFS
- iOS 处理服务器返回的浮点数数据
- Poj.1775 Sum of Factorials【略坑】 2015/10/12
- iOS9适配必看指南
- iOS-Git使用详解
- 正则后台验证、抓包
- excel中如何筛选重复数据
- win10 amd intel 双显卡 难以干掉黑屏 禁止ulps不利
- Android计算器
- [leetcode]Pascal's Triangle II
- android 内部存储相关知识点: getfilestreampath getDir 子文件夹