|   
 | 
| 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:
  nlbuttondown (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轴的角度,角度的单位是十分之一度而不是度,例如,ifescapement为450表示字体旋转45度。为确保所有的字体沿坐标系统的同一方向旋转,一定要设置ifescapement成员的clip_lh_angles位,否则,有些字体可能反向旋转。下例使用了14点arial字体每间隔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);
 | 
 |