1. 程式人生 > >VC++Edit控制元件

VC++Edit控制元件

用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(),把設定文字容量的語句放在裡面即可。

void CEditBox::PreSubclassWindow()
{
SetLimitText( -1 );
//設定編輯控制元件可接收的最大位元組數
CEdit::PreSubclassWindow();
}

因為nMax為無符號整型,-1是把它設定為可以取到的最大值。你也可以根據需要設定控制元件的容量。

注意:在不同作業系統下,控制元件可設定的最大容量也不同。如果是Windows98,這個值就是64K,無法再增大了,而在Windows2000和WindowsXP下這個值要大得多,才可以起到增加控制元件容量的目的。

二、設定編輯控制元件的前景色、背景色和字型:

在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()函式。本例中設定控制元件的初始字型為尺寸為100(0.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,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控制元件

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選單下選擇Add To 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的新選單,編輯它就可得到你想要的右鍵選單了。這和其它選單的做法沒有區別,我就不再詳細介紹了。