如果要修改字符,则不能仅仅简单地用修改过的nchar调用cedit: : onchar,然后cedit: : onchar调用cwnd: : default获取原来的wparam 和lparam 的值,这样是不行的。要修改一个字符,需要首先修改nchar,然后用修改过的nchar调用cwnd: : defwindowproc。下例说明了如何将字符转变为大写:
//make all characters uppercase
void cmyedit : : onchar (uint nchar , uint nrepcnt , uint nflags )
{
//make sure character is uppercase .
if (: : ischaralpha ( .( tchar) nchar)
nchar=: : charupper(nchar )
//bypass default onchar processing and directly call
//default window proc.
defwindproc (wm_char, nchar , makelparam (nrepcnt, nflags ))
}
(48) 如何改变控件的颜色
有两种方法。其一,可以在父类中指定控件的颜色,或者利用mfc4.0新的消息反射在控件类中指定颜色。 当控件需要重新着色时,工作框调用父窗口(通常是对话框)的cwnd: : oncrtlcolor,可以在父窗口类中重置该函数并指定控件的新的绘画属性。例如,下述代码将对话中的所有编辑控件文本颜色改为红色:
hbrush caboutdig : : onctlcolor (cdc * pdcm , cwnd * pwnd , uint nctlcolor)
{
hbrush hbr = cdialog : : onctlcolor (pdc, pwnd , nctlcolor )
//draw red text for all edit controls .
if (nctlcolor= = ctlcolor_edit )
pdc —> settextcolor (rgb (255, 0 , 0 , ) )
return hbr
}
然而,由于每个父窗口必须处理通知消息并指定每个控件的绘画属性,所以,这种方法不是完全的面向对象的方法。控件处理该消息并指定绘画属性更合情合理。消息反射允许用户这样做。通知消息首先发送给父窗口,如果父窗口没有处理则发送给控件。创建一个定制彩色列表框控件必须遵循下述步骤。
首先,使用classwizard 创建一个clistbox 的派生类并为该类添加下述数据成员。
class cmylistbox publilc clistbox
{
…
private
colorref m_clrfor // foreground color
colorref m_clrback //background color
cbrush m_brush //background brush
…
}
其次,在类的构造函数中,初始化数据中。
cmylistbox : : cmylistbox ()
{
//initialize data members .
m_clrfore =rgb (255 , 255 , 0) //yellow text
m_clrback=rgb (0 , 0 , 255) // blue background
m_brush . createsolidbrush (m _clrback )
}
最后,使用classwizard处理反射的wm_ctlcolor(=wm_ctlcolor)消息并指定新的绘画属性。
hbrush cmylistbox : : ctlcolor (cdc* pdc, uint nctlcolor )
{
pdc—>settextcolor (m_clrfore)
pdc—>setbkcolor (m_clrback)
return (hbrush) m_brush.getsafehandle ()
}
现在,控件可以自己决定如何绘画,与父窗口无关。
(49) 当向列表框中添加多个项时如何防止闪烁
调用cwnd::setredraw 清除重画标志可以禁止clistbox(或者窗口)重画。当向列表框添加几个项时,用户可以清除重画标志,然后添加项,最后恢复重画标志。为确保重画列表框的新项,调用setredraw (true) 之后调用cwnd::invalidate。
//disable redrawing.
plistbox->setredraw (false)
//fill in the list box gere
//enable drwing and make sure list box is redrawn.
plistbox->setredraw (true)
plistbox->invalidate ()
(50) 如何向编辑控件中添加文本
由于没有cedit:: appendtext函数,用户只好自己做此项工作。调用cedit:: setsel移动到编辑控件末尾,然后调用cedit:: replacesel添加文本。下例是appendtext 的一种实现方法:
void cmyedit:: appendtext (lpcstr ptext)
{
int nlen=getwindowtextlength ()
setfocus ()
setsel (nlen, nlen)
replacesel (ptext)
}
(51) 如何访问预定义的gdi对象
可以通过调用cdc:: slectstockobject使用windows的几个预定义的对象,诸如刷子、笔以及字体。下例使用了windows预定义的笔和刷子gdi对象在视窗中画一个椭圆。
//draw ellipse using stock black pen and gray brush.
void csampleview:: ondraw (cdc* pdc)
{
//determine size of view.
crect rcview
getclientrect (rcview)
//use stock black pen and stock gray brush to draw ellipse.
pdc->selectstockobject (black_pen)
pdc->selectstockobject (gray_brush)
//draw the ellipse.
pdc->ellipse (review)
}
也可以调用新的sdk函数getsyscolorbrush获取一个系统颜色刷子,下例用背景色在视窗中画一个椭圆:
void csampleview:: ondraw (cdc* pdc)
{
//determine size of view.
crect rcview
getclientrect (rcview)
//use background color for tooltips brush.
cbrush * porgbrush=pdc->selectobject ( cbrush ::fromhandle( ::getsyscolorbrush (color_infobk)))
//draw the ellipse.
pdc->ellipse (rcview)
//restore original brush.
pdc->selectobject (porgbrush)
}
(52) 如何获取gdi对象的属性信息
可以调用gdiobject:: getobject。这个函数将指定图表设备的消息写入到缓冲区。下例创建了几个有用的辅助函数。
//determine if font is bold.
bool isfontbold (const cfont&font)
{
logfont stfont
font.getobject (sizeof (logfont), &stfont)
return (stfont.lfbold)? true: false
}
//return the size of a bitmap.
csize getbitmapsize (const cbitmap&bitmap)
{
bitmap stbitmap
bitmap.getobject (sizeof (bitmap), &stbitmap)
return csize (stbitmap.bmwidth, stbitmap.bmheight)
}
//create a pen with the same color as a brush.
bool createpenfrombrush (cpen&pen, cost cbrush&brush)
{
logbrush stbrush
brush.getobject (sizeof (logbrush), &stbrush)
return pen. createpen (ps_solid, 0, stbrush.ibcolor)
}
(53) 如何实现一个橡皮区矩形
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
}