您的位置:首页 > 其它

重写TEdit文本编辑框

2015-10-12 12:17 567 查看
重写TEdit文本编辑框,实现功能如下:

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;
}//---------------------------------------------------------------------------



内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: