另外一种实现平面工具栏的方.htm
来自「VC的一些技巧性文档」· HTM 代码 · 共 1,007 行 · 第 1/3 页
HTM
1,007 行
</pre> </dd> <dd><pre>#if _mfc_ver >= 0x420</pre> </dd> <dd><pre> lresult ccustomdrawinfo :: notifyparent() { lresult lres = cdrf_dodefault;</pre> </dd> <dd><pre> if( m_preceiver ) lres = m_preceiver->sendmessage(wm_notify, wparam(m_cdrw.hdr.idfrom), lparam(&m_cdrw)); return lres; }</pre> </dd> <dd><pre> ccustomdrawinfo :: ccustomdrawinfo( cdc & dc, ctoolbarex * pbar ) : m_prepaint(0) , m_itemprepaint(0) { verify((m_ptoolbar = pbar) != 0); verify((m_cdrw.hdc = dc.getsafehdc()) != 0);</pre> </dd> <dd><pre> hwnd hwnd = pbar->getsafehwnd(); verify(::iswindow(hwnd));</pre> </dd> <dd><pre> // initialise the nmhdr member of the customdraw structure m_cdrw.hdr.hwndfrom = hwnd; m_cdrw.hdr.idfrom = uint(::getwindowlong(hwnd, gwl_id)); m_cdrw.hdr.code = nm_customdraw;</pre> </dd> <dd><pre> // do not use ccontrolbar::getdockingframe() to receive // the parent. cwnd::getparent() is inacceptable too. // both these functions don't work, if the toolbar is // floating in the air! m_preceiver = pbar->getparentframe(); if( m_preceiver ) verify(::iswindow(m_preceiver->getsafehwnd())); }</pre> </dd> <dd><pre> void ccustomdrawinfo :: notifyprepaint() { // fill the customdraw structure with values for cdds_prepaint m_cdrw.dwdrawstage = cdds_prepaint; // the rest of the structure stays undefined in this stage // of drawing. m_prepaint = notifyparent(); }</pre> </dd> <dd><pre> bool ccustomdrawinfo :: notifyitemprepaint( int nitem ) { bool bret = true; // we assume to do the default if( m_prepaint & cdrf_notifyitemdraw ) { m_cdrw.dwdrawstage = cdds_itemprepaint; m_ptoolbar->getitemrect(nitem, &m_cdrw.rc); m_cdrw.dwitemspec = dword(m_ptoolbar->getitemid(nitem)); uint ustyle = m_ptoolbar->getbuttonstyle(nitem); bool benable = m_ptoolbar->gettoolbarctrl() .isbuttonenabled(m_cdrw.dwitemspec); m_cdrw.uitemstate = (benable ? 0 : cdis_disabled) | (((ustyle & tbbs_pressed) || (ustyle & tbbs_checked)) ? cdis_checked : 0); m_cdrw.litemlparam = 0; m_itemprepaint = notifyparent(); if( m_itemprepaint & cdrf_skipdefault ) bret = false; } return bret; }</pre> </dd> <dd><pre> void ccustomdrawinfo :: notifyitempostpaint( int nitem ) { if( m_itemprepaint & cdrf_notifypostpaint ) { m_cdrw.dwdrawstage = cdds_itempostpaint; // the rest of the data has not been changed since itemprepaint // make sure it is so: assert(m_ptoolbar->getitemid(nitem) == m_cdrw.dwitemspec); notifyparent(); } }</pre> </dd> <dd><pre> void ccustomdrawinfo :: notifypostpaint() { if( m_prepaint & cdrf_notifypostpaint ) { m_cdrw.dwdrawstage = cdds_postpaint; notifyparent(); } } </pre> </dd> <dd><pre>#else // _mfc_ver < 4.2</pre> </dd> <dd><pre> ccustomdrawinfo :: ccustomdrawinfo( cdc & dc, cwnd * pparent ) { }</pre> </dd> <dd><pre> void ccustomdrawinfo :: notifyprepaint() { }</pre> </dd> <dd><pre> void ccustomdrawinfo :: notifypostpaint() { } </pre> </dd> <dd><pre> bool ccustomdrawinfo :: notifyitemprepaint( int ) { return true; // we always make the drawing by ourself }</pre> </dd> <dd><pre> void ccustomdrawinfo :: notifyitempostpaint( int ) { }</pre> </dd> <dd><pre>#endif // _mfc_ver</pre> </dd> <dd><pre>/////////////////////////////////////////////////////////////////////////////// ctoolbarex</pre> </dd> <dd><pre>ctoolbarex::ctoolbarex() : m_bflatlook(true) , m_clrbtnface(::getsyscolor(color_btnface)) , m_clrbtnhilight(::getsyscolor(color_btnhilight)) , m_clrbtnshadow(::getsyscolor(color_btnshadow)) , m_nlastbtn(-1) , m_utimerevent(0){ calculateoffset();</pre> </dd> <dd><pre> // create the default font, used for buttons with text cfont font; bool boldsys = false; if( ! font.createstockobject( default_gui_font ) ) { // older versions of windows* (nt 3.51 for instance) // fail with default_gui_font verify( font.createstockobject( system_font ) ); boldsys = true; } logfont logfont ; font.getlogfont( &logfont ) ; if( boldsys ) { logfont.lfweight = 400; strcpy(logfont.lffacename,"ms sans serif"); } logfont.lfheight = 6 ; logfont.lfwidth = 0 ; // let windows compute this. verify( m_guifont.createfontindirect( &logfont ) ) ;}</pre> </dd> <dd><pre>ctoolbarex::~ctoolbarex(){}</pre> </dd> <dd><pre>implement_dynamic(ctoolbarex, ctoolbar)</pre> </dd> <dd><pre>begin_message_map(ctoolbarex, ctoolbar) //{{afx_msg_map(ctoolbarex) on_wm_paint() on_wm_syscolorchange() on_wm_nccalcsize() on_wm_mousemove() on_wm_ncpaint() on_wm_timer() on_wm_create() //}}afx_msg_map on_message(tb_setbuttonsize, onsetbuttonsize) on_message(tb_setbitmapsize, onsetbitmapsize)end_message_map()</pre> </dd> <dd><pre>/////////////////////////////////////////////////////////////////////////////// ctoolbarex message handlers</pre> </dd> <dd><pre>lresult ctoolbarex :: onsetbuttonsize(wparam wparam, lparam lparam) { lresult lresult = ctoolbar::onsetbuttonsize(wparam, lparam); if( lresult ) calculateoffset(); return lresult;}</pre> </dd> <dd><pre>lresult ctoolbarex :: onsetbitmapsize(wparam wparam, lparam lparam) { lresult lresult = ctoolbar::onsetbitmapsize(wparam, lparam); if( lresult ) calculateoffset(); return lresult;}</pre> </dd> <dd><pre>void ctoolbarex::onpaint() { himagelist himg = getimagelist();</pre> </dd> <dd><pre>#ifdef _debug if( himg == 0 ) { trace0("ctoolbarex::onpaint(): could not get image list\n"); }#endif</pre> </dd> <dd><pre> if( m_bflatlook && himg ) { crect rcupdate; if( ! getupdaterect(rcupdate) ) return;</pre> </dd> <dd><pre> if( m_pstringmap && !m_pstringmap->isempty() ) calculateoffset(); // strings may have been added</pre> </dd> <dd><pre> // attach image-list for even more mfc feeling :) cimagelist imglist; imglist.attach(himg);</pre> </dd> <dd><pre> point cursor; ::getcursorpos(&cursor); screentoclient(&cursor);</pre> </dd> <dd><pre> cpaintdc dc(this); // device context for painting cfont * poldfont = dc.selectobject(&m_guifont);</pre> </dd> <dd><pre> // now it's time for the first custom-draw-notification... ccustomdrawinfo cdrw(dc, this); cdrw.notifyprepaint();</pre> </dd> <dd><pre> register const int nbtn = gettoolbarctrl().getbuttoncount();</pre> </dd> <dd><pre> for( register int i = 0; i < nbtn; ++i ) { crect rc; getitemrect(i, rc);</pre> </dd> <dd><pre> int nbitmap; uint uid, ustylestate; getbuttoninfo(i, uid, ustylestate, nbitmap); word wstyle = loword(ustylestate); word wstate = hiword(ustylestate);</pre> </dd> <dd><pre> if( wstate & tbstate_hidden ) continue;</pre> </dd> <dd><pre> if( wstyle == tbstyle_sep ) { if( !(wstate & tbstate_wrap) || ! isfloating() ) drawseparator(dc, rc); } else { if( ! crect().intersectrect(rcupdate, rc) ) continue; // this button needs no repaint</pre> </dd> <dd><pre> // maybe the button has text dc.settextcolor(rgb(0,0,0)); dc.setbkcolor(m_clrbtnface);</pre> </dd> <dd><pre> // there is a bug in ctoolbar: if there are texts assigned // to buttons, then the button-widths may change transparently // (without notified by ctoolbar), so we recalculate the // horizontal offset here: m_sizeoffset.cx = (rc.width() - m_sizeimage.cx) / 2;</pre> </dd> <dd><pre> if( ! cdrw.notifyitemprepaint(i) ) continue; // parent has already drawn the button</pre> </dd> <dd><pre> bool bbtndown = (wstate & tbstate_checked) || (wstate & tbstate_pressed); bool bbtnenabled = gettoolbarctrl().isbuttonenabled(int(uid));</pre> </dd> <dd><pre> dc.fillsolidrect(rc,m_clrbtnface);</pre> </dd> <dd><pre> // it seems, that cdc::draw3drect() changes the backgrounddi2001.jpgd color colorref clrbk = dc.getbkcolor();</pre> </dd> <dd><pre> if( bbtndown ) // draw a pressed button dc.draw3drect(rc, m_clrbtnshadow, m_clrbtnhilight); else if( rc.ptinrect(cursor) && ! bbtndown && bbtnenabled ) // draw a normal button dc.draw3drect(rc, m_clrbtnhilight, m_clrbtnshadow); else if( ! bbtndown && bbtnenabled ) // draw an invisible rect around the button. // this prevents us from erasing the backgrounddi2001.jpgd // if the button was formed before // (that would cause the button to flicker ...) dc.draw3drect(rc, m_clrbtnface, m_clrbtnface); </pre> </dd> <dd><pre> dc.setbkcolor(clrbk);</pre> </dd> <dd><pre> // the point where to start with the image cpoint pt(rc.left + m_sizeoffset.cx + bbtndown, rc.top + m_sizeoffset.cy + bbtndown); </pre> </dd> <dd><pre> imglist.draw(&dc, nbitmap, pt, ild_transparent); cstring strtext = getbuttontext(i); if( strtext.getlength() ) { crect recttext( rc.left+3+bbtndown, rc.top+m_sizeoffset.cy+m_sizeimage.cy+1+bbtndown, rc.right-3+bbtndown, rc.bottom-3+bbtndown ); dc.drawtext(strtext, recttext, dt_center|dt_vcenter|dt_noclip); } </pre> </dd> <dd><pre> if( ! bbtnenabled ) // gray out that button drawdisabledbutton(dc, rc);</pre> </dd> <dd><pre> cdrw.notifyitempostpaint(i); } }</pre> </dd> <dd><pre> dc.selectobject(poldfont);</pre> </dd> <dd><pre> if( ! m_bdeleteimglist ) imglist.detach();</pre> </dd> <dd><pre> // last but not least: inform the parent for end of painting cdrw.notifypostpaint(); } else // classic mode (or couldn't receive imagelist) ctoolbar::onpaint();}</pre> </dd> <dd><pre>void ctoolbarex :: drawdisabledbutton( cdc & dc, const crect & rc ) const { // create a monochrome memory dc cdc ddc; ddc.createcompatibledc(0); cbitmap bmp; bmp.createcompatiblebitmap(&ddc, rc.width(), rc.height()); cbitmap * poldbmp = ddc.selectobject(&bmp); </pre> </dd> <dd><pre> // build a mask ddc.patblt(0, 0, rc.width(), rc.height(), whiteness); dc.setbkcolor(m_clrbtnface); ddc.bitblt(0, 0, rc.width(), rc.height(), &dc, rc.left, rc.top, srccopy); dc.setbkcolor(m_clrbtnhilight); ddc.bitblt(0, 0, rc.width(), rc.height(), &dc, rc.left, rc.top, srcpaint);</pre> </dd> <dd><pre> // copy the image from the toolbar into the memory dc // and draw it (grayed) back into the toolbar. dc.fillsolidrect(rc.left, rc.top, rc.width(), rc.height(), m_clrbtnface); dc.setbkcolor(rgb(0, 0, 0)); dc.settextcolor(rgb(255, 255, 255)); cbrush brshadow, brhilight; brhilight.createsolidbrush(m_clrbtnhilight); brshadow.createsolidbrush(m_clrbtnshadow); cbrush * poldbrush = dc.selectobject(&brhilight);
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?