Code Analysis of the Self-painted scroll bar

Source: Internet
Author: User

The standard scroll bar cannot be made by subclass. If you want to get a nice scroll bar, you need to draw it by yourself.

 

To add a scroll bar for clistctrl, the general idea is as follows:

 

(1) make the standard clistctrl scroll bar unavailable

(2) manually locate the H and V scroll bars (not the child control of clistctrl)

(3) processing required,

Click the left and right arrows to scroll a row.

Click the blank area of the slider to scroll down one page.

Drag the slider

 

The following figure shows a simple example. The slider and the left and right arrows are 26 pixels in width and 12 pixels in height.

 

 

 

 

The analysis code is as follows: skinhorizontalscrollbar. cpp

// Skinhorizontalscrollbar. CPP: implementation file <br/> // </P> <p> # include "stdafx. H "<br/> # include" test_scroll.h "<br/> # include" skinhorizontalscrollbar. H "</P> <p> # ifdef _ debug <br/> # define new debug_new <br/> # UNDEF this_file <br/> static char this_file [] = __ file __; <br/> # endif </P> <p> /////////////////////////// //////////////////////////////////////// ///////// <br/> // cskinhorizontalscrollbar </P> <P> cskinhorizontalscrollbar: cskinhorizontalscrollbar () <br/>{< br/> nthumbleft = 25; <br/> dbthumbremainder = 0.00f; </P> <p> bmousedown = false; <br/> bmousedownarrowleft = false; <br/> bmousedownarrowright = false; <br/> bdragging = false; <br/> plist = NULL; <br/>}</P> <p> cskinhorizontalscrollbar ::~ Callback () <br/>{< br/>}</P> <p> begin_message_map (cskinhorizontalscrollbar, cstatic) <br/> // {afx_msg_map (cskinhorizontalscrollbar) <br/> on_wm_paint () <br/> on_wm_lbuttondown () <br/> on_wm_lbuttonup () <br/> on_wm_mousemove () <br/> on_wm_timer () <br/> //} afx_msg_map <br/> end_message_map () </P> <p> ///////////////////////////////// //////////////////////////////////////// //// <br/> // cskinhori Zontalscrollbar message handlers </P> <p> void cskinhorizontalscrollbar: onpaint () <br/>{< br/> cpaintdc DC (this ); // device context for painting </P> <p> draw (); <br/>}</P> <p> void cskinhorizontalscrollbar: onlbuttondown (uint nflags, cpoint point) <br/>{< br/> setcapture (); <br/> crect clientrect; <br/> getclientrect (& clientrect ); </P> <p> int nwidth = clientrect. width ()-26; </P> <p> // area of the left arrow <br/> crect rectleft Arrow (,); <br/> // right arrow area <br/> crect rectrightarrow (nwidth, 0, nwidth + ); <br/> // Slider Area <br/> crect rectthumb (nthumbleft, 0, nthumbleft + 26, 20 ); </P> <p> // specifies whether to use the slider. <br/> If (rectthumb. ptinrect (point) <br/>{< br/> bmousedown = true; <br/>}</P> <p> // whether to click the right arrow. <br/> If (rectrightarrow. ptinrect (point) <br/>{< br/> bmousedownarrowright = true; <br/> settimer (2,250, null ); <br/>}< br/> // whether to click the left arrow. <br/> If (rectlef Tarrow. ptinrect (point) <br/>{< br/> bmousedownarrowleft = true; <br/> settimer (2,250, null ); <br/>}</P> <p> cstatic: onlbuttondown (nflags, point); <br/>}</P> <p> void cskinhorizontalscrollbar :: onlbuttonup (uint nflags, cpoint point) <br/>{< br/> updatethumbposition (); <br/> killtimer (1); <br/> releasecapture (); </P> <p> bool binchannel = true; </P> <p> crect clientrect; <br/> getclientrect (& clientrect); </P> <p> int Nwidth = clientrect. width ()-26; </P> <p> crect rectleftarrow (,); <br/> crect rectthumb (nthumbleft, 0, nthumbleft + ); </P> <p> If (rectleftarrow. ptinrect (point) <br/>{< br/> scrollleft (); <br/> binchannel = false; <br/>}</P> <p> crect rectrightarrow (nwidth, 0, nwidth + 26,20); </P> <p> If (rectrightarrow. ptinrect (point) <br/>{< br/> scrollright (); <br/> binchannel = false; <br/>}</P> <p> If (rectthumb. ptinrect (Point) <br/>{< br/> binchannel = false; <br/>}</P> <p> If (binchannel = true &&! Bmousedown) <br/>{< br/> If (point. x> nthumbleft) <br/>{< br/> pageright (); <br/>}< br/> else <br/>{< br/> pageleft (); <br/>}</P> <p> // restore all variables <br/> bmousedown = false; <br/> bdragging = false; <br/> bmousedownarrowleft = false; <br/> bmousedownarrowright = false; </P> <p> cstatic: onlbuttonup (nflags, point ); <br/>}</P> <p> void cskinhorizontalscrollbar: onmousemove (uint nflags, cpoint point) <br/>{< br/> C Rect clientrect; <br/> getclientrect (& clientrect); </P> smaller <p> If (bmousedown) <br/> bdragging = true; </P> <p> If (bdragging) <br/> {<br/> // the slider width is 26. It is assumed that the cursor is the midpoint of the slider, calculate the slider position <br/> nthumbleft = point. x-13; </P> <p> double Nmax = plist-> getscrolllimit (sb_horz); <br/> int NPOs = plist-> getscrollpos (sb_horz ); </P> <p> // calculate the scroll range: clientrect. width ()-left arrow width-right arrow width-slider width <br/> double nwidth = clientrect. width ()-75; <br/> do Uble nvar = Nmax; <br/> dbthumbinterval = nwidth/nvar; </P> <p> // nThumbLeft-25: the distance from the start point of the slider <br/> // (nThumbLeft-25) /dbthumbinterval the number of times to scroll <br/> int nscrolltimes = (INT) (nThumbLeft-25)/dbthumbinterval)-NPOs; </P> <p> csize size; <br/> size. cx = nscrolltimes; <br/> size. cy = 0; </P> <p> // force the list to scroll <br/> plist-> scroll (size); </P> <p> limitthumbposition (); </P> <p> draw (); <br/>}</P> <p> cstatic: onmousemove (nflags, Poin T); <br/>}</P> <p> void cskinhorizontalscrollbar: ontimer (uint nidevent) <br/>{< br/> If (nidevent = 1) <br/>{< br/> If (bmousedownarrowright) <br/>{< br/> scrollright (); <br/>}</P> <p> If (bmousedownarrowleft) <br/>{< br/> scrollleft (); <br/>}< br/> else if (nidevent = 2) <br/>{< br/> If (bmousedownarrowright) <br/>{< br/> killtimer (2); <br/> settimer (1, 50, null ); <br/>}</P> <p> If (bmousedownarrowleft) <br />{< Br/> killtimer (2); <br/> settimer (1, 50, null ); <br/>}</P> <p> cstatic: ontimer (nidevent); <br/>}</P> <p> void cskinhorizontalscrollbar:: scrollleft () <br/>{< br/> plist-> sendmessage (wm_hscroll, makelong (sb_lineleft, 0), null); <br/> updatethumbposition (); <br/>}</P> <p> void cskinhorizontalscrollbar: scrollright () <br/>{< br/> plist-> sendmessage (wm_hscroll, makelong (sb_lineright, 0), null); <br/> UPD Atethumbposition (); <br/>}</P> <p> void cskinhorizontalscrollbar: updatethumbposition () <br/>{< br/> crect clientrect; <br/> getclientrect (& clientrect); </P> <p> double NPOs = plist-> getscrollpos (sb_horz ); <br/> double Nmax = plist-> getscrolllimit (sb_horz); <br/> double nwidth = clientrect. width ()-75; <br/> double nvar = Nmax; </P> <p> dbthumbinterval = nwidth/nvar; </P> <p> double nnewdbvalue = dbthumbinterval * (NPOs); <br/> int nnewvalue = (INT) nnewdbvalue; <br/> // double nextra = nnewdbvalue-nnewvalue; <br/> // dbthumbremainder = nextra; </P> <p> nthumbleft = 25 + nnewvalue; </P> <p> trace ("NPOs: % 0.3f, Nmax: % 0.3f, nwidth: % 0.3f, dbthumbinterval: % 0.3f/R/N ", <br/> NPOs, Nmax, nwidth, dbthumbinterval); </P> <p> limitthumbposition (); </P> <p> draw (); <br/>}</P> <p> void cskinhorizontalscrollbar: pageright () <br/>{< br/> Trace ("cskinhorizontalscrollbar: pageright/R/N"); <br/> plist-> sendmessage (wm_hscroll, makelong (sb_pagedown, 0), null ); <br/> updatethumbposition (); <br/>}</P> <p> void cskinhorizontalscrollbar: pageleft () <br/>{< br/> trace ("cskinhorizontalscrollbar: pageleft/R/N"); <br/> plist-> sendmessage (wm_hscroll, makelong (sb_pageup, 0), null); <br/> updatethumbposition (); <br/>}</P> <p> void cskinhorizontalscrollbar:: Draw () <br/>{< br/> cclientdc (this); <br/> crect clientrect; <br/> getclientrect (& clientrect ); <br/> cmemdc memdc (& DC, & clientrect); </P> <p> // fill in the background <br/> memdc. fillsolidrect (& clientrect, RGB (118,); </P> <p> // draw the left arrow <br/> CDC bitmapdc; <br/> bitmapdc. createcompatibledc (& DC); <br/> cbitmap bitmap; <br/> bitmap. loadbitmap (idb_horizontal_scrollbar_leftarrow); <br/> cbitmap * poldbitmap = bitmapdc. selectobje CT (& Bitmap); <br/> memdc. bitblt (clientrect. left, clientrect. top, 26,12, & bitmapdc, 0, 0, srccopy); </P> <p> bitmapdc. selectObject (poldbitmap); <br/> bitmap. deleteobject (); <br/> poldbitmap = NULL; </P> <p> // draw intermediate background <br/> bitmap. loadbitmap (idb_horizontal_scrollbar_span); <br/> poldbitmap = bitmapdc. selectObject (& Bitmap); <br/> int nwidth = clientrect. width ()-26; <br/> memdc. stretchblt (clientrect. left + 26, clientrect. Top, nwidth, 12, & bitmapdc, 0, 0, 1, 12, srccopy); <br/> bitmapdc. selectObject (poldbitmap); <br/> bitmap. deleteobject (); <br/> poldbitmap = NULL; </P> <p> // draw the right arrow <br/> bitmap. loadbitmap (idb_horizontal_scrollbar_rightarrow); <br/> poldbitmap = bitmapdc. selectObject (& Bitmap); <br/> memdc. bitblt (nwidth, clientrect. top, 26,12, & bitmapdc, 0, 0, srccopy); <br/> bitmapdc. selectObject (poldbitmap); <br/> bitmap. deleteobject (); <Br/> poldbitmap = NULL; </P> <p> // if there is nothing to scroll then don't <br/> // show the thumb control otherwise show it <br/> trace ("plist -> getscrolllimit: % d/R/N ", plist-> getscrolllimit (sb_horz); </P> <p> If (plist-> getscrolllimit (sb_horz )! = 0) <br/>{< br/> bitmap. loadbitmap (idb_horizontal_scrollbar_thumb); </P> <p> poldbitmap = bitmapdc. selectObject (& Bitmap); </P> <p> memdc. bitblt (clientrect. left + nthumbleft, clientrect. top, 26,12, <br/> & bitmapdc, 0, 0, srccopy); </P> <p> bitmapdc. selectObject (poldbitmap); <br/> bitmap. deleteobject (); <br/> poldbitmap = NULL; <br/>}</P> <p> void cskinhorizontalscrollbar: limitthumbposition () <br/>{< br/> crect clientrect; <br/> getclientrect (& clientrect ); </P> <p> // the range of the slider is the area between the left and right arrows, with a width of 26 pixels. <br/> If (nthumbleft + 26> (clientrect. width ()-26) <br/>{< br/> nthumbleft = clientrect. width ()-51; <br/>}</P> <p> If (nthumbleft <(clientrect. left + 25) <br/>{< br/> nthumbleft = clientrect. left + 25; <br/>}< br/>

 

 

 

Skinhorizontalscrollbar. h

# If! Defined (partition _) <br/> # define afx_skinhorizontalscrollbar_h1_77b6a7df_1670_44d6_aa66_281_af219db1_included _ </P> <p> # include "memdc. H "</P> <p> class cskinhorizontalscrollbar: Public cstatic <br/>{< br/> Public: <br/> cskinhorizontalscrollbar (); <br/> void scrollleft (); <br/> void scrollright (); </P> <p> bool bmousedownarrowright, bmoused Ownarrowleft; <br/> bool bdragging; <br/> bool bmousedown; </P> <p> int nthumbleft; <br/> double dbthumbremainder; <br/> double dbthumbinterval; </P> <p> // attributes <br/> Public: </P> <p> // Operations <br/> public: </P> <p> Public: <br/> clistctrl * plist; <br/> void limitthumbposition (); <br/> void draw (); <br/> void pageleft (); <br/> void pageright (); <br/> void updatethumbposition (); <br/> virtual ~ Cskinhorizontalscrollbar (); </P> <p> protected: <br/> afx_msg void onpaint (); <br/> afx_msg void onlbuttondown (uint nflags, cpoint point ); <br/> afx_msg void onlbuttonup (uint nflags, cpoint point); <br/> afx_msg void onmousemove (uint nflags, cpoint point ); <br/> afx_msg void ontimer (uint nidevent); </P> <p> declare_message_map () <br/>}; </P> <p> # endif

 

 

Cmylistctrl: init dynamically creates a scroll bar control and locates the position of the scroll bar.

 

Call m_list.init at cdialog: oninitdialog.

 

 

 

 

 

 

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.