时间: 2021-07-31 作者:daque
有一种按键,看上去是一幅完备的图片,当鼠标移到按键地区时,图片的一局部凸现,产生一个按键,当鼠标移走时又回复从来状况。 迩来,看了少许对于浮动按键的代码,其道理大概上跟cbitmapbutton差不离,用数幅位图代办按键的各个状况,相应鼠目标百般动静来树立按键的状况,实行按键的浮动表露,然而如许的按键却不许和范围的后台混和成一幅图片。 为了实行“通明”按键,不妨大略地做个考查:先在对话框中介入一个button,经过属性框选“owner draw”作风,再介入一个picture,并介入图片,将button移到picture上。运转截止创造,按键没有表露出来,但在按键地区按下鼠标时,该按键仍旧能发出wm_command动静,如许一个纯通明的按键创造了。明显,这个按键是毫无运用意旨的,由于用户不领会按键的场所,必需让用户简单察觉到按键的场所,不妨把这个按键变革一下: (开始从cbutton派生出一个新类cdrawbutton) ·把按键的题目表露出来 这个实行起来比拟大略,咱们不妨重载cbutton类的分子因变量drawitem(), void cdrawbutton::drawitem(lpdrawitemstruct lpdrawitemstruct){cdc dc;crect rect=lpdrawitemstruct- >rcitem;//获得按键地区cstring scaption;dc.attach(lpdrawitemstruct- >hdc); //获得摆设情况cdcverify(lpdrawitemstruct- >ctltype==odt_button);getwindowtext(scaption);//获得按键的题目dc.setbkmode(transparent);//透鲜明示cfont* m_poldfont=dc.selectobject(m_pfont);dc.drawtext(scaption,&rect,dt_center|dt_vcenter|dt_singleline);dc.selectobject(m_poldfont);} 个中的m_pfont是分子变量,它生存了对话框的字体南针,为了按键的题目作风与对话框的字体作风普遍,在初始化时挪用对话框的分子因变量getfont()即可获得指向对话框字体的cfont类南针。 ·使按键浮动表露 要经过自绘来表白按键的百般状况,可填写drawitemstruct来报告drawitem()因变量须要做什么,咱们先领会一下drawitemstruct: typedef struct tagdrawitemstruct{ uint ctltype; // 控件典型 uint ctlid;// 控件的id号 unit itemid;//菜单项的索引 uint itemaction;// 画图操纵 uint itemstate; // 状况 hwnd hwnditem; // 控件的窗口句柄 hdc hdc; // 关系的摆设情况 rect rcitem;//控件的范畴 dword itemdata;//指定与菜单项相接洽的运用步调设置的32位值}drawitemstruct; 运用这个构造先做一个按键状况树立因变量: void cdrawbutton::setbuttonmode(uint action, uint mode){ // todo: add your message handler code here and/or call default drawitemstruct dis; dis.ctltype = odt_button; dis.ctlid = getdlgctrlid(); dis.itemaction = action; dis.itemstate = mode; dis.hwnditem = getsafehwnd(); dis.hdc = getdc()- >getsafehdc(); getclientrect(&(dis.rcitem)); sendmessage(wm_drawitem,(wparam)getsafehwnd(),(lparam)&dis); releasedc(cdc::fromhandle(dis.hdc));} 如许,咱们不妨相应鼠目标百般动静来树立按键的百般状况: void cdrawbutton::onmousemove(uint nflags, cpoint point) { // todo: add your message handler code here and/or call default crect rect; getclientrect(&rect); if(rect.ptinrect(point)){ if (mbtnstats==btn_normal){ setbuttonmode(oda_select, ods_focus); setcapture(); } } else{//autoload(getdlgctrlid(),getparent());setbuttonmode(oda_drawentire,ods_default); releasecapture(); } cbutton::onmousemove(nflags, point);} 这边,mbtnstats是个uint典型的分子变量,它不妨有三种自设置状况: btn_normal 平常状况btn_up 鼠标移入按键地区或开释鼠标btn_down 按下鼠标(不妨再加一种disable状况) 当在按键地区开释鼠标时,必需发送wm_command动静:void cdrawbutton::onlbuttonup(uint nflags, cpoint point) { // todo: add your message handler code here and/or call default crect rect; getclientrect(&rect); if(rect.ptinrect(point)){ if (mbtnstats==btn_down) getparent()- >sendmessage(wm_command, makelparam(getdlgctrlid(),bn_clicked), (lparam)getsafehwnd()); setcapture(); } else{ setbuttonmode(oda_drawentire,ods_default); releasecapture(); } cbutton::onlbuttonup(nflags, point);} 接着即是绘制按键的百般状况:因为按键必需“通明”,以是在按下和开释时只在按键地区的边际加上一个3d边框就行了。而在平常状况下,则必需去掉边框回复后台。但怎样回复后台图象呢?我是如许做的:在按键初始化时,先把被按键掩盖了的地区生存在一个cbitmap类中,此后须要重绘按键时就把这个cbitmap画在按键上就行了。 void cdrawbutton::drawitem(lpdrawitemstruct lpdrawitemstruct) { // todo: add your code to draw the specified item cdc dc; crect rect=lpdrawitemstruct- >rcitem; cstring scaption; dc.attach(lpdrawitemstruct->hdc); //获得绘制的摆设情况cdc verify(lpdrawitemstruct- >ctltype==odt_button); if (lpdrawitemstruct- >itemaction & oda_drawentire){ //重绘控件(平常状况) mbtnstats=btn_normal; if (m_pbitmap!=0){ cdc memdc; memdc.createcompatibledc(&dc); memdc.selectobject(m_pbitmap); dc.bitblt(0, 0, rect.width(), rect.height(), &memdc, 0, 0, srccopy); memdc.deletedc(); } //表露按键题目 getwindowtext(scaption); dc.setbkmode(transparent); if (m_pfont!=0){ cfont* m_poldfont=dc.selectobject(m_pfont); dc.drawtext(scaption,&rect, dt_center|dt_vcenter|dt_singleline); dc.selectobject(m_poldfont); } }if ((lpdrawitemstruct- >itemstate & ods_selected) && (lpdrawitemstruct- >itemaction & oda_select)){//按下鼠标mbtnstats=btn_down;dc.draw3drect(&rect,rgb(128,128,128),rgb(192,192,192));rect.top=rect.top+1;rect.bottom=rect.bottom-1;rect.left=rect.left+1;rect.right=rect.right-1;dc.draw3drect(&rect,rgb(0,0,0),rgb(255,255,255)); }if(!(lpdrawitemstruct- >itemstate & ods_selected) && (lpdrawitemstruct- >itemaction & oda_select)){//开释鼠标或鼠标加入按键地区mbtnstats=btn_up;dc.draw3drect(&rect,rgb(255,255,255),rgb(0,0,0));rect.top=rect.top+1;rect.bottom=rect.bottom-1;rect.left=rect.left+1;rect.right=rect.right-1;dc.draw3drect(&rect,rgb(192,192,192),rgb(128,128,128)); } dc.detach();} 接着就必需少许初始化处事,个中最要害即是把被按键掩盖了的地区生存进cbitmap类中,咱们领会cdc::stretchblt()因变量不妨把位图的指定地区从一个摆设正片到另一个摆设中,如许不妨很简单地把窗口或对话框的某个地区生存,前提是赢得其dc: void cdrawbutton::loadback(cwnd *pparent){ assert(getstyle() & bs_ownerdraw); if (m_pbitmap!=0) return; crect rect; getwindowrect(&rect); pparent- >screentoclient(&rect);//赢得按键地区 cpaintdc dc(pparent); if (m_pbitmap==0) m_pbitmap=new cbitmap;//初始化位图 m_pbitmap- >createcompatiblebitmap (&dc,rect.width(),rect.height()); cdc memdc; memdc.createcompatibledc(&dc); memdc.selectobject(m_pbitmap);memdc.stretchblt(0, 0, rect.width(),rect.height(), &dc, rect.left, rect.top, rect.width(),rect.height(), srccopy);//生存 memdc.deletedc();m_pfont=pparent- >getfont();//赢得窗口或对话框的字体 modifystyle(0,ws_visible);//表露按键 setbitmapmode(oda_drawentire,0);//绘制按键} 而使这个类和对话框上的按键爆发接洽还必需挪用一下subclassdlgitem(): bool cdrawbutton::autoload(uint nid, cwnd *pparent){ // first attach the cdrawbutton to the dialog control if (m_pbitmap!=0) return false; if (!subclassdlgitem(nid, pparent)) return false; loadback(pparent); return true;} 这个类还必需具备三个分子变量: cfont* m_pfont; cbitmap* m_pbitmap; uint mbtnstats;在结构因变量中初始化那些变量 m_pbitmap=0; m_pfont=0; //付与0是不妨的 mbtnstats=btn_normal;在折构因变量中废除位图 if(m_pbitmap!=0) delete m_pbitmap; 如许,一个通明的浮动式按键类就做好了,简直实行本领以次: 1.接收对话框的button,开始在对话框上画一个button,再加一个picture图片,button的作风必需介入owner draw及去掉visible,把button移到picture上符合的场所,在对话框类介入cdrawbutton类分子m_mybutton,因为按键初始化时必需生存对话框的图象,而对话框在运转initdialog()或第一次运转onpaint()时对话框的控件还没有真实表露出来,咱们只幸亏onmousemove()中举行初始化: m_mybutton.autoload(idc_button1,this);autoload()只运转一次。 2.动静创造cdrawbutton,在对话框类或cxxxview类介入cdrawbutton类分子m_mybutton,不妨在对话框的initdialog()或cxxxview类的initialupdate()中介入:m_mybutton.create()因变量,必需包括bs_ownerdraw而不许有ws_visible作风,而后在onmousemove()或ondraw()中举行初始化:m_mybutton.loadback(this);提防应加在ondraw()的结果。 同样地,loadback()只运转一次。 (即使按键比后台的图片迟创造而具备看来(visible)属性,则会把图片抹掉,以是必需去掉visible属性或不许介入ws_visible作风) ·当鼠标移到按键地区时,变换鼠标 这个很简单实行,不在这边多说了。