参考http://www.codeguru.com/cpp/controls/editctrl/article.php/c3917/Multiline-Edit-Box-with-Automatic-Scroll-Bar-Display.htm
TheProblem
IfyouneedamultilineEditControl,youcanimplementoneatdesigntimebyusingtheResourceEditorandsettingthestylesMultiline,Horizontalscroll,AutoHScroll,Verticalscroll,andAutoVScrollfromtheStylesTabinEditProperties.Or,ifyoucreatetheEditControlfromcodeatruntime,youneedtosetthestylesWS_HSCROLL,WS_VSCROLL,ES_MULTILINE,ES_AUTOHSCROLL,andES_AUTOVSCROLL.Fordisplayingmultiplelines,youneedtoenterCtrl+RETURNinteractivelyfromthekeyboardduringprogramexecution,orfromthecodeyouneedtoseparatethelineswiththesequence"\r\n",forexample:
m_oEdit.SetWindowText(_T("FirstLine\r\nSecondLine\r\n...\r\n"));
Theproblemwiththeseapproachesisthatthescrollbarsarevisibleevenwhentheyarenotneeded;forexample,whentheEditBoxisemptyorwhenthetextisveryshort.ThisproblemissolvedbytheCScrollEditclasspresentedinthisarticle.
TheSolution
TheCScrollEditclassisderivedfromtheCEditMFCclass.Asexplainedbefore,thestylesWS_HSCROLL,WS_VSCROLL,ES_MULTILINE,ES_AUTOHSCROLL,andES_AUTOVSCROLLhavetobesetforproperfunctioningoftheEditControl.Whenthescrollbarsarenotneededfordisplay,theycanbehiddenbycallingthefunctionShowScrollBar():
ShowScrollBar(SB_HORZ,FALSE);
ShowScrollBar(SB_VERT,FALSE);
Theproblemishowtodetectwhenthescrollbarsareneededandwhentheyarenotneeded.ThisisdonebythefunctionCheckScrolling(),whichisthecoreoftheCScrollEditclass:
voidCScrollEdit::CheckScrolling(LPCTSTRlpszString)
{
CRectoRect;
GetClientRect(&oRect);
CClientDCoDC(this);
intiHeight=0;
BOOLbHoriz=FALSE;
CFontpEdtFont=GetFont();
if(pEdtFont!=NULL)
{
//DetermineTextWidthandHeight
SIZEoSize;
CFontpOldFont=oDC.SelectObject(pEdtFont);
//DeterminethelineHeight
oSize=oDC.GetTextExtent(CString(_T("")));
iHeight=oSize.cy;
//TextWidth
intiWidth=0,i=0;
CStringoStr;
//Parsethestring;thelinesinamultilineEditare
//separatedby"\r\n"
while(TRUE==::AfxExtractSubString(oStr,lpszString,
i,_T(''\n'')))
{
if(FALSE==bHoriz)
{
intiLen=oStr.GetLength()-1;
if(iLen>=0)
{
//Eliminatelast''\r''
if(_T(''\r'')==oStr.GetAt(iLen))
oStr=oStr.Left(iLen);
oSize=oDC.GetTextExtent(oStr);
if(iWidth iWidth=oSize.cx;
if(iWidth>=oRect.Width())
bHoriz=TRUE;
}
}
i++;
}
oDC.SelectObject(pOldFont);
//TextHeight
iHeight=i;
}
ShowHorizScrollBar(bHoriz);
ShowVertScrollBar(iHeight>=oRect.Height());
}
TheideainthisfunctionistoparsetheEditControl''stextandextractthelines(whichareseparatedinthetextbythesequence"\r\n").ThenforgettingthesizeofeachlinetheGetTextExtent()functionisused.Theheightofthetextisdeterminedbymultiplyingtheheightofalinewiththenumberoflines.IftheheightofthetextisgreaterorequalthantheheightoftheEditControl''sclientrectanglethentheverticalscrollbarhastobedisplayed,otherwiseisnotdisplayed.FordisplayingthehorizontalscrollbaritisenoughtodetectjustonelinewiththewidthgreaterthanorequaltothewidthoftheEditControl''sclientrectangle.
ThefunctionCheckScrolling()iscalledfromtwoplaces:
FromthefunctionSetWindowText(),whichisoverloadingtheCWnd::SetWindowText()function:
voidCScrollEdit::SetWindowText(LPCTSTRlpszString)
{
CheckScrolling(lpszString);
CEdit::SetWindowText(lpszString);
}
FromthehandlerOnCheckText()whichistreatingthespecialusermessageUWM_CHECKTEXT:
LRESULTCScrollEdit::OnCheckText(WPARAMwParam,LPARAM
lParam)
{
CStringoStr;
GetWindowText(oStr);
CheckScrolling(oStr);
return0;
}
ThemessageUWM_CHECKTEXTispostedfromtheOnChar()handler(thehandlerfortheWM_CHARmessage)eachtimetheuseriseditinginsidetheEditControl:
voidCScrollEdit::OnChar(UINTnChar,UINTnRepCnt,
UINTnFlags)
{
//PossibleTextChange
PostMessage(UWM_CHECKTEXT);
CEdit::OnChar(nChar,nRepCnt,nFlags);
}
//////////////////////////////
HowtoUsetheCode
UsingtheCScrollEditclassisveryeasy,anditisdemonstratedbytheaccompanyingdemoproject.Youneedtoincludethesourcefiles//ScrollEdit.handScrollEdit.cpp//inyourproject.InScrollEdit.cpp,changetheline
#include"ScrollEditTst.h"
totheappropriate#includeforyourapplication''sheaderfile.Then,declarethecontrolmembervariableintheappropriateheaderfile:
#include"ScrollEdit.h"
//...
CScrollEditm_oScrollEdit;
anddosubclassingintheappropriateplace;forexample,intheOnInitDialog()handler:
m_oScrollEdit.SubclassDlgItem(IDC_EDIT1,this);
m_oScrollEdit.SetWindowText(_T(""));
Theinitializationwithtext_T("")isnecessaryfortheproperinitializationofthescrollbar''sdisplay(inthiscase,theyarenotdisplayedinitially).
/////////////////////////////// |
|