首页 > C/C++开发工具专区 > VC技术 > Visual C++编程技巧之七
2006
03-14

Visual C++编程技巧之七

49、如何实现一个橡皮区矩形


CRectTracker是一个很有用的类,可以通过调用CRectTracker:: TrackRubberBand响应WM_LBUTTONDOWN消息来创建一个橡皮区矩形。下例表明使用CRectTracker移动和重置视窗中的蓝色椭圆的大小是很容易的事情。


首先,在文件档中声明一个CRectTracker数据成员:


class CSampleView : Public CView


{



public :


CrectTracker m_tracker;



};


其次,在文档类的构造函数中初始化CRectTracker 对象:


CSampleDoc:: CSampleDOC ()


{


//Initialize tracker position, size and style.


m_tracker.m_rect.SetRect (0, 0, 10, 10);


m_tracker.m_nStyle=CRectTracker:: resizeInside |


CRectTracker:: dottedLine;


}


然后,在OnDraw函数中画椭圆和踪迹矩形:


void CSampleView:: OnDraw (CDC* pDC)


{


CSampleDoc* pDoc=GetDocument ();


ASSERT_VALID (pDoc);


//Select blue brush into device context.


CBrush brush (RGB (0, 0, 255));


CBrush* pOldBrush=pDC->SelectObject (&brush);


//draw ellipse in tracking rectangle.


Crect rcEllipse;


pDoc->m_tracker.GetTrueRect (rcEllipse);


pDC->Ellipse (rcEllipse);


//Draw tracking rectangle.


pDoc->m_tracker.Draw (pDC);


//Select blue brush out of device context.


pDC->Selectobject (pOldBrush);


}


最后,使用ClassWizard处理WM_LBUTTONDOWN消息,并增加下述代码。该段代码根据鼠标击键情况可以拖放、移动或者重置椭圆的大小。


void CSampleView::OnLButtonDown (UINT nFlags, CPoint point)


{


//Get pointer to document.


CSampleDoc* pDoc=GetDocument ();


ASSERT_VALID (pDoc);


//If clicked on ellipse, drag or resize it. Otherwise create a


//rubber-band rectangle nd create a new ellipse.


BOOL bResult=pDoc->m_tracker.HitTest (point)!=


CRectTracker::hitNothing;


//Tracker rectangle changed so update views.


if (bResult)


{


pDoc->m_tracker.Track (this,point,TRue);


pDoc->SetModifiedFlag ();


pDoc->UpdateAllViews (NULL);


}


else


pDoc->m-tracker.TrackRubberBand (this,point,TRUE);


CView:: onLButtonDown (nFlags,point);


}


50、如何更新翻转背景颜色的文本


调用CDC:: SetBkmode并传送OPAQUE用当前的背景颜色填充背景,或者调用CDC::SetBkMode并传送TRANSPAARENT使背景保持不变,这两种方法都可以设置背景模式。下例设置背景模式为TRANSPARENT,可以两次更新串,用花色带黑阴影更新文本。黑色串在红色串之后,但由于设置了背景模式仍然可见。


void CSampleView:: OnDraw (CDC* pDC)


{


//Determint size of view.


CRect rcView;


GetClientRect (rcVieew);


//Create sample string to display.


CString str (_T (“Awesome Shadow Text...“));


//Set the background mode to transparent.


pDC->SetBKMode (TRANSPARENT);


//Draw black shadow text.


rcView.OffsetRect (1, 1);


pDc->SetTextColor (RGB (0, 0, 0));


pDC->DrawText (str, str.GetLength (), rcView,


DT_SINGLELINE | DT_CENTER | DT_VCENTER);


//Draw red text.


rcView.OffsetRect (-1,-1);


pDc->SetTextColor (RGB (255, 0, 0));


pDC->DrawText (str, str.GetLength (), rcView,


DT_SINGLELINE | DT_CENTER | DT_VCENTER);


}


51、如何创建一个具有特定点大小的字体


可以指定字体逻辑单位的大小,但有时指定字体的点的大小可能会更方便一些。可以如下将字体的点转换为字体的高度:


int nHeigth=mulDiv (nPointSize, -dc.GetDeviceCaps (LOGPIXELSY), 72);


下例创建了一个8点的Apial字体:


CClientDC dc (AqfxGetMainWnd ());


m_font. CreateFont (MulDiv (8, -dc.GetDeviceCaps (LOGPIXELSY),


72),0,0,0,FW_NORMAL,0,0,0,ANSI_CHARSET,


OUT_STROKE_PRECIS,CLIP_STROKE_PRECIS,DRAFT_QUALITY,


VARIABLE_PITCH | FF-SWISS,_T (“Arial”));


52、如何计算一个串的大小


函数CDC:: Det text Extent 根据当前选择的字体计算一个串的高度和宽度。如果使用的不是系统字体而是其他字体,则在调用GetTextExtent之前将字体选进设备上下文中是很重要的,否则计算高度和宽度时将依据系统字体,由此得出的结果当然是不正确的。下述样板程序当改变下压按钮的标题时动态调整按钮的大小,按钮的大小由按钮的字体和标题的大小而定。响应消息WM_SETTEXT时调用OnSetText,该消息使用ON_MESSAE宏指令定义的用户自定义消息。


LRESULT CMyButton:: OnSettext (WPARAM wParam, LPARAM lParam)


{


//Pass message to window procedure.


LRESULT bResult=CallWindowProc (*GetSuperWndProcAddr (),


m_hWnd, GetCurrentMessage () ->message,wParam,lParam);


//Get title of push button.


CString strTitle;


GetWindowText (strTitle);


//Select current font into device context.


CDC* pDC=GetDc ();


CFont*pFont=GetFont ();


CFont*pOldFont=pDC->SelectObject (pFont);


//Calculate size of title.


CSize size=pDC->GetTextExent (strTitle,strTitle.GetLength ());


//Adjust the button’s size based on its title.


//Add a 5-pixel border around the button.


SetWindowPos (NULL, 0, 0, size.cx+10, size.cy+10,


SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE);


//Clean up.


pDC->SelectFont (pOldFont);


ReleaseDC (pDC);


return bResult;


}


53、如何显示旋转文本


只要用户使用TrueType或者GDI笔或字体就可以显示旋转文本(有些硬件设备也支持旋转光栅字体)。LOGFONT结构中的ifEscapement成员指定了文本行和x轴的角度,角度的单位是十分之一度而不是度,例如,ifEscapement450表示字体旋转45度。为确保所有的字体沿坐标系统的同一方向旋转,一定要设置ifEscapement成员的CLIP_LH_ANGLES位,否则,有些字体可能反向旋转。下例使用了14Arial字体每间隔15度画一个串。


void CSampleView:: OnDraw (CDC* pDC)


{


//Determine the size of the window.


CRect rcClient;


GetClientRect (rcClient);


//Create sample string.


CString str (_T (“Wheeee...I am rotating!”));


//Draw transparent, red text.


pDC->SetBkMode (TRANSPARENT);


pDC->SetTextColor (RGB (255,0,0));


CFont font; //font object


LOGFONT stFont; //font definition


//Set font attributes that will not change.


memset (&stFont, 0, sizeof (LOGFONT));


stFont.ifheight=MulDiv (14, -pDC->GetDeviceCaps (LOGPIXELSY), 72);


stFont.ifWeight=FW_NORMAL;


stFont.ifClipPrecision=LCIP_LH_ANGLES;


strcpy (stFont.lfFaceName, “Arial”);


//Draw text at 15degree intervals.


for (int nAngle=0; nAngle<3600; nAngle+=150)


{


//Specify new angle.


stFont.lfEscapement=nAngle;


//Create and select font into dc.


font.CreateFontIndirect (&stfont);


CFont* pOldFont=pDC->SelectObject (&font);


//Draw the text.


pDC->SelectObject (pOldFont);


font.DelectObjext ();


}


}


54、如何正确显示包含标签字符的串


调用GDI文本绘画函数时需要展开标签字符,这可以通过调用CDC:: TabbedTextOut或者CDC:: DrawText并指定DT_EXPANDTABS标志来完成。TabbedTextOut函数允许指定标签位的数组,下例指定每20设备单位展开一个标签:


void CSampleView:: OnDraw (CDC* pDC)


{


CTestDoc* pDoc=GetDocument ();


ASSERT_VALID (pDoC);


CString str;


str.Format (_T (“Cathy\tNorman\tOliver”));


int nTabStop=20; //tabs are every 20 pixels


pDC->TabbedtextOut (10, 10, str, 1, &nTabStop, 10);


}


55、串太长时如何在其末尾显示一个省略号


调用CDC:: DrawText并指定DT_END_ELLIPSIS标志,这样就可以用小略号取代串末尾的字符使其适合于指定的边界矩形。如果要显示路径信息,指定DT_END_ELLIPSIS标志并省略号取代串中间的字符。


void CSampleView:: OnDraw (CDC* pDC)


{


CTestDoc* pDoc=GetDocument ();


ASSERT_VALID (pDoc);


//Add ellpsis to end of string if it does not fit


pDC->Drawtext (CString (“This is a long string”),


CRect (10, 10, 80, 30), DT_LEFT | DT_END_ELLIPSIS);


//Add ellpsis to middle of string if it does not fit


pDC->DrawText (AfxgetApp () ->m_pszhelpfilePath,


CRect (10, 40, 200, 60), DT_LEFT | DT_PATH_ELLIPSIS);


}


56、如何快速地格式化一个CString对象


调用CString:: Format,该函数和printf函数具有相同的参数,下例说明了如何使用Format函数:


//Get size of window.


CRect rcWindow;


GetWindowRect (rcWindow);


//Format message string.


CString strMessage;


strMessage.Format (_T (“Window Size (%d, %d)”),


rcWindow.Width (), rcWindow.Height ());


//Display the message.


MessageBox (strmessage);



留下一个回复