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.