Here's how to use the scroll bar, just how to draw the scrollbar control.
Scroll bar basic Knowledge reference http://hi.baidu.com/3582077/blog/item/d30e5b38f8709aecb211c7c0.html
(PS for the moment to draw the horizontal scroll bar, regardless of vertical scroll bar, with this foundation, the following will give a complete example, directly look at the code on the line, do not need to say it clearly)
Self-painting is done in the scroll bar WM_PAINT message handler. The first step is to know that the various component size information of the scrollbar, such as the left button width, the slider position size, the right channel size, etc., the information can be obtained using the API function GetScrollBarInfo to complete. Let's take a look at a diagram (from the Internet) and get a clear picture of the components, and get a ballpark understanding of them.
So I'm going to CScrollBar. The derived class Cnewscrollbar defines 6 variables CRect, corresponding to the above information.
CRect m_clirect;//scroll bar size
CRect m_rcleftbutton;//left arrow button size
CRect m_rcrightbutton;//right arrow button size
CRect m_rcthumb;//slider position, size
CRect m_rcleftchannel;//left channel size
CRect m_rcrightchannel;//left channel size
OK next, how to assign them the correct value, GetScrollBarInfo get just some simple data, such as button width, slider position, width. Those passages still have to be counted by ourselves.
getscrollbarinfo function Definition:
BOOL GetScrollBarInfo (HWND hwnd,/./scroll bar window handle, or window handle with scroll bar properties (This is a false scrollbar, one with the window)
LONG idobject,//If it is a scrollbar window handle, fill objid_client, if is "false scroll bar", fill objid_hscroll horizontally, vertical objid_vscroll
Pscrollbarinfo PSBI);//This structure contains all the information of the scroll bar.
(If the SCROLLBARINFO structure is undefined when compiling the code, the Stdafx.h header file is prefixed with the # define WINVER 0x500)
Scrollbarinfo Structure Definition:
typedef struct TAGSCROLLBARINFO {
DWORD cbsize;//initializes the struct, which must be assigned sizeof (SCROLLBARINFO), which is the structure size
RECT rcscrollbar;//scroll bar size, position, this is relative to the screen and is not restricted by the parent window. That is, the size that is obtained by calling the GetWindowRect function.
int dxylinebutton;//button width (horizontal), or button height (vertical)
int xythumbtop;//the left position (horizontal) of the slider, the top position (vertical) of the slider, which is relative to the scroll bar.
int xythumbbottom;//the right position (horizontal) of the slider, the bottom position of the slider (vertical). Relative to scroll bar
int reserved;//reserved ...
The DWORD rgstate[cchildren_scrollbar+1];//indicates the status of each component, such as a button being pressed, and a detailed look at MSDN, which is not used in this example.
} scrollbarinfo, *pscrollbarinfo, *lpscrollbarinfo;
For the trouble, I wm_paint the message processing function to calculate the information. As follows:
//Get scroll bar information, button size, slider size, etc.
scrollbarinfo SBI;
sbi.cbsize=sizeof (Scrollbarinfo);
:: GetScrollBarInfo (THIS->M_HWND,OBJID_CLIENT,&SBI);
//scroll bar size
m_clirect=sbi.rcscrollbar;
//Calculate LEFT arrow button size
m_rcleftbutton=crect (0,0,sbi.dxylinebutton,m_clirect.height ());
//Calculate right arrow button size
m_rcrightbutton=crect (M_clirect.width ()-sbi.dxylinebutton,0,
M_clirect.width (), M_clirect.height ());
//Calculate slider position
m_rcthumb=crect (Sbi.xythumbtop,0,sbi.xythumbbottom,m_clirect.height ());
//Calculate left channel size
m_rcleftchannel=crect (Sbi.dxylinebutton,0,m_rcthumb.left,m_clirect.height ());
//Calculate right channel size
m_rcrightchannel=crect (m_rcthumb.right,0,
m_clirect.width ()- Sbi.dxylinebutton,m_clirect.height ());
In fact, even if you do nothing in WM_PAINT message processing, and do not call the parent class WM_PAINT message Handler, the parent class also has the opportunity to draw the scroll bar, and we want to completely self-draw, do not need the parent class to handle. It always goes wrong. For example, double-clicking the ScrollBar, drawing the scrollbar, does not pass the WM_PAINT message handler function.
So we're going to forbid the parent to handle the WM_LBUTTONDBLCLK message, and the method is simple, add the WM_LBUTTONDBLCLK message handler to Cnewscrollbar, and in that function do not call the parent class double-click the message handler function. This is, of course, just an example. There is still a problem with the parent class drawing the scroll bar ...
For example, when the SetScrollPos function is called to set the scrollbar position, it escapes the self-painted range again. The parent class also participates in drawing the scroll bar ...
This is because calling SetScrollPos to set the scrollbar position will send a SBM_SETSCROLLINFO message to the scroll bar, in fact, by sending a message to set the scrolling information. Then in the parent class this message handler, the scroll bar must also be drawn. So what we're going to do is intercept the sbm_setscrollinfo and don't let the parent handle it ...
But here is a problem, if you do not let the parent class processing, then the data is not docking. After all, storing the scroll bar information, such as location, is handled by the parent class.
I have seen an example of completely using my own data instead, that is, the scroll bar size, location, also by the new class to store, set.
This problem will be solved later, now let's put aside to see the message sent.
The scroll bar sends a message to the parent window's code example, such as dragging the scroll bar, and the left and right buttons are clicked, as follows:
GetParent ()->sendmessage (Wm_hscroll,makelong (sb_lineleft,0), (LPARAM) this->m_hwnd);//Left (top) button clicked
GetParent ()->sendmessage (Wm_hscroll,makelong (sb_lineright,0), (LPARAM) this->m_hwnd);//Right (bottom) button clicked
GetParent ()->sendmessage (Wm_hscroll,makelong (sb_pageleft,0), (LPARAM) this->m_hwnd);//left-side channel clicked down
GetParent ()->sendmessage (Wm_hscroll,makelong (sb_pageright,0), (LPARAM) this->m_hwnd);//right channel clicked down
GetParent ()->sendmessage (Wm_hscroll,makelong (Sb_thumbtrack,npos), (LPARAM) this->m_hwnd);//Drag the slider
Use only the above 5 messages, the other message does not need to also can, here also specifically said Sb_thumbtrace this message, this message comes with parameters, to indicate the position of the slider. That is, the npos,npos is used to set the slider position for the caller. And this POS need ourselves to find out (when dragging the slider), here I give a simple calculation method, look at the map, the map is for us to better understand the calculation method, assuming that the maximum slider position is set to 255, the page size is 50.
Above I set the maximum position of the slider is 255, but the actual slider position at 205, the head. The reason is that the page size is set to 50. So the scrollable range of the slider position is 0~205 (minus page size 50). As you can see from the above figure, the slider position range is 0~205, and the scrolling pixel range is 0~235. Then we can figure out how many points to scroll 1 pixels (scale)
That's 205/235. The specific application code is:
The derived scroll bar class defines a double variable, storing the scale, a CRect variable, and storing the scroll size.
Double m_ratio;//ratio
CRect m_clirect;//scroll bar size
In the WM_PAINT message processing function, calculate the scale (the code that calculates the scrolling information above)
Get scroll bar information, page size, slider position
SCROLLINFO si;
Si.cbsize=sizeof (SCROLLINFO);
Getscrollinfo (&SI);
Calculate channel scrollable pixel range
int Chlwidth=m_clirect.width ()-sbi.dxylinebutton*2-m_rcthumb.width ();
Calculate the maximum position at which the slider can be moved
int maxpos=si.nmax-si.npage;
Calculate the ratio, 1 pixels in number of points
m_ratio= (double) maxpos/chlwidth;
Figure out the proportions, then to calculate the mouse drag slider movement, scroll bar the correct position, here also to define some variables in the derived class, as follows:
BOOL m_istrace;//Indicates whether the mouse is currently inside the slider and the left mouse button is under the state
int m_nsize;//mouse click on the slider, the distance from the left of the slider
Above the m_nsize, in the WM_LBUTTONDOWN message processing function, the above figure, for example, the left mouse button on the x-axis 248 pixels down, then the value of M_nsize
is 248-235, see the code in the WM_LBUTTONDOWN message handler function:
void Cnewscrollbar::onlbuttondown (UINT nflags, CPoint Point)
{
if (M_rcthumb.ptinrect (point))
{
M_istrace=true;
M_nsize=point.x-m_rcthumb.left;
SetCapture ();
}
Cscrollbar::onlbuttondown (nflags, point); Do not let parent class handle
}
So in the Wm_movemouse message handler function, the code is this:
void Cnewscrollbar::onmousemove (UINT nflags, CPoint Point)
{
Todo:add your message handler code here and/or call default
if (m_istrace)
{
17 is the left button width, with a constant instead of the dynamic button width, the definition of a variable in the class can be, here do not do so.
int npos= (POINT.X-M_NSIZE-17) *m_ratio;
GetParent ()->sendmessage (Wm_hscroll,makelong (Sb_thumbtrack,npos), (LPARAM) this->m_hwnd);
}
Cscrollbar::onmousemove (nflags, point);
}
OK, finally completed the most difficult sb_thumbtrack message sent, the rest of the message is sent correctly, referring to the code in the project, it is not mentioned here.
Previously said to intercept the Sbm_setscrollinfo message, prevent the parent class to participate in the drawing scroll bar, here is simple to deal with, this certainly has a lot of drawbacks,
But this is learning, from simple to difficult. Now there is no need to make any perfect, beautiful rolling, with this foundation, and so on later when needed to do. It's an introduction.
To add a virtual function WindowProc to Cnewscrollbar, the code for the function is as follows:
LRESULT Cnewscrollbar::windowproc (UINT message, WPARAM WPARAM, LPARAM LPARAM)
{
Todo:add your specialized code here and/or call the base class
if (message==sbm_setscrollinfo)
{
LRESULT res= cscrollbar::windowproc (message, WParam, lParam);//Let parent class handle
Cnewscrollbar does not have its own scroll bar information structure, so it has to rely on the parent class. Calling the function above causes the parent class to draw a scrollbar. This is what we don't want to see.
So immediately after the refresh, here added an unnecessary drawing, if you want to avoid, you must have their own information structure is scrollinfo to set their own
I will give a project in the back, this is a complete project, this project I downloaded on the CodeProject website, which avoids calling the parent class WindowProc method
This->invalidate ();//Refresh Now
return res;
}
return Cscrollbar::windowproc (Message, WParam, LParam);
}
Program Run Effect:
Click Button1 to set the scroll bar information first.
I just made a simple drawing, interested friends can use bitmaps to draw a bit.
In addition, if you click the button quickly, you will find a certain interval, speed can not keep up with the standard scroll bar, this is because the scroll bar window class support mouse double-click (cs_dblclks), I do not know the standard scroll bar is how to do, both support double-click, speed and fast enough. And I can only remove the double-click property of the Window class. I can't use the double-tap anyway, and that doesn't make any difference.
The method is to add the virtual function PreCreateWindow to Cnewscrollbar, and change its window class when creating the scroll bar. As follows:
BOOL Cnewscrollbar::P Recreatewindow (createstruct& CS)
{
Todo:add your specialized code here and/or call the base class
Wndclass wndcls;
Window class name ScrollBar, that is, Wndcls.lpszclassname, has been registered, the creation of the time directly with
The following function gets the window class information, which is identified by Wndcls.lpszclassname.
GetClassInfo (NULL, "ScrollBar", &wndcls);
wndcls.style^=cs_dblclks;//Remove Double-click Properties
Wndcls.lpszclassname= "Newscrollbar";//New window class name
Cs.lpszclass=wndcls.lpszclassname;
AfxRegisterClass (&WNDCLS);//Register window class
Return CScrollBar::P Recreatewindow (CS);
}
But the scroll bar above does not work, still produce double-click message, because the above scroll bar is the resource in the dialog box, created, and did not pass the PreCreateWindow function, but the system directly created, Then I estimate to call a function similar to SubclassWindow to associate it again.
So this method only works with scroll bars created by the CREATE function in the control. The CREATE function creates a scroll bar code example as follows:
Cnewscrollbar M_sr;
CRect Rect=crect (0,0,200,17);
M_sr. Create (ws_child| WS_VISIBLE,RECT,THIS,1002);
A try, click the response speed there is no interval.
Project Download Address: http://ishare.iask.sina.com.cn/f/22477752.html
Remember to first click the "Button1" button to set scrolling information.
In addition, I downloaded from the CodeProject project address: http://www.codeproject.com/KB/dialog/skinscrollbar.aspx This project is relatively perfect, can refer to. I just refer to it ...
If the implementation of the ScrollBar hotspot function, you can use the timer, to achieve, every time, judge. (Cancel the timer when the mouse leaves the scroll bar, save resources)
http://hi.baidu.com/3582077/item/bb76bb564dc8589609be1721
Google
http://www.google.com.hk/#newwindow =1&safe=strict&q=%e6%94%b9%e5%8f%98%e6%bb%9a%e5%8a%a8%e6%9d%a1%e5% ae%bd%e5%ba%a6+vc&oq=%e6%94%b9%e5%8f%98%e6%bb%9a%e5%8a%a8%e6%9d%a1%e5%ae%bd%e5%ba%a6+vc&gs_l=serp.12 ... 0.0.2.188.0.0.0.0.0.0.0.0..0.0...0.0...1c.. 9.serp.80bocrxn_94&bav=on.2,or.&bvm=bv.45373924,d.dgi&fp=676c413d4dea429e&biw=1600&bih=805
Replace a Window ' s Internal Scrollbar with a customdraw Scrollbar Control
Http://www.codeproject.com/Articles/14724/Replace-a-Window-s-Internal-Scrollbar-with-a-custo