|
41、如何一个创建三态下压按钮
可以使用新的bs_pushbutton 风格位和检测框以及按钮来创建一个三态下压按钮。这很容易,只需将检测框和按钮拖拉到对话中并指定属性push—like即可。不用任何附加程序就可以成为三态下压按钮。
42、如何动态创建控件
分配一个控件对象的实例并调用其create成员函数。开发者最容易忽略两件事:忘记指定ws_visble标签和在栈中分配控件对象。下例动态地创建一个下压按钮控件:
//in class declaration (.h file ).
private :
cbutton* m _pbutton ;
//in class implementation (.cpp file ) .
m_pbutton =new cbutton ;
assert_valid (m_pbutton);
m_pbutton —>create (_t ("button title ") , ws_child |ws_visible |bs_pushbutton.
crect ( 0, 0, 100 , 24) , this , idc _mybutton )
43、如何限制编辑框中的准许字符
如果用户在编辑控件中只允许接收数字,可以使用一个标准的编辑控件并指定新的创建标志es_numbers,它是windows 95新增加的标志,该标志限制 编辑控件只按收数字字符。如果用户需要复杂的编辑控件,可以使用microsoft 的屏蔽编辑控件,它是一个很有用的ole定制控件。
如果希望不使用ole 定制控件自己处理字符,可以派生一个cedit 类并处理wm_char消息,然后从编辑控件中过滤出特定的字符。首先,使用classwizard 建立一个 cedit的派生类,其次,在对话类中指定一个成员变量将编辑控件分类在oninitdialog 中调用cwnd: : subclassdlgitem .
//in your dialog class declaration (.h file )
private :
cmyedit m_wndedit ; // instance of your new edit control .
//in you dialog class implementation (.cpp file )
bool csampledialog : : oninitdialog ( )
{
…
//subclass the edit lontrod .
m_wndedit .subclassdlgitem (idc_edit,this );
…
}
使用classwizard处理wm_char消息,计算nchar参量并决定所执行的操作,用户可以确定是否修改、传送字符。下例说明了如何显示字母字符,如果字符是字母字符,则调用cwnd ; onchar,否则不调用onchar.
//only display alphabetic dharacters .
void cmyedit : : onchar (uint nchar , uint nrepcnt , uitn nflags )
{
//determine if nchar is an alphabetic character .
if (: : ischaralpha ( ( tchar) nchar ) )
cedit : : onchar (nchar, nrepcnt , nflags );
}
如果要修改字符,则不能仅仅简单地用修改过的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 )) ;
}
44、如何改变控件的颜色
有两种方法。其一,可以在父类中指定控件的颜色,或者利用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 ()
}
现在,控件可以自己决定如何绘画,与父窗口无关。
45、当向列表框中添加多个项时如何防止闪烁
调用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 ();
46、如何向编辑控件中添加文本
由于没有cedit:: appendtext函数,用户只好自己做此项工作。调用cedit:: setsel移动到编辑控件末尾,然后调用cedit:: replacesel添加文本。下例是appendtext 的一种实现方法:
void cmyedit:: appendtext (lpcstr ptext)
{
int nlen=getwindowtextlength ();
setfocus ();
setsel (nlen, nlen);
replacesel (ptext);
}
47、如何访问预定义的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);
}
48、如何获取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);
} |
|