Interface Controls-scroll bar scrollbar (a good combination of scroll bar messages and mouse messages)

Source: Internet
Author: User
Tags rowcount

Interface is the portal of human-computer interaction, which is critical to products. In the interface development only unexpectedly has not done, has the good idea, certainly must try to make out. For the extension of the scrollbar, there are now many examples of classes.

VS2015 Code editing is very powerful, there is a feature that can roll the dynamic into the minmap, you can Options Text Editor C/C++ Scroll Bars Behavior Option category to open.

Sublime also has this feature, but there is no good for VS . After becoming minmap, the entire code document becomes a complete thumbnail, which can be easily judged and positioned to the approximate function location when you are familiar with the code. At the same time, the special status, such as: Error information, update information, etc. to identify. You can quickly navigate to the relevant document location by just looking at the scroll bar to know what the current document is.

A lot of advantages: When a file content is longer, it is very convenient to mark relevant important content on it. It can be used to see the relevant information on the scroll bar. No need to open up a window to tell the user what he wants to get information about.

There is a reference to VS , it is easier to do this. Do not know whether Microsoft has registered copyright-_-!!。 So it's a good idea to think about extending Scroll Bar , but the Windows system doesn't give this opportunity, and the general window class comes with a system scroll bar. The system comes with a complete inability to make this effect, and can only do a self-overwriting system default scroll bar.

First, the scroll bar structure scrollinfo
typedef struct tagSCROLLINFO {  UINT cbSize;    // 结构尺寸  UINT fMask; // 需要处理或返回的相关选项参数 int nMin; // 滚动条的最小值 int nMax; // 最大滚动范围 UINT nPage; // 一页有效行数 int nPos; // 当前滚动条 int nTrackPos; // 拖拽滚筒条时的位置} SCROLLINFO, *LPCSCROLLINFO;

Normal we use the scroll bar has the following elements, draw a picture easier to understand the point.

You can see that if we have the default minimum value of =0, we actually need only three scroll bar parameters, the maximum scrollable range NMax, the number of rows that can be displayed on a page npage and the display position of the current line NPos these three parameters.

1. Calculation of rolling quantity

such as scroll bar can scroll to the last line position normally. There are 100 rows of records, scrolling the bottom screen to show the last line. For easy calculation of rows with no records, the height is fixed.

  • Npage = Clientheight/rowheight
  • NMax = rowCount-1 + nPage-1

The normal calculation is the total number of rows-1, which is the value of Nmax, should be allowed to scroll to the last bar of the record, so you need to add a page of scrolling. The formula for the above Nmax is produced.

// 只要超过1行就能滚动,因此需要多加一页的行数。si.nMax   = rowCount - 1 + yClient / rowHeight - 1;si.nPage  = yClient / rowHeight;
2, Slide size calculation

The dimensions of the slider are defined by the height of the scroll bar divided by the scroll range and then by the number of pages per page available.

Slider size = ScrollBar Height/Active range * Quantity per page

There is another problem with the above calculation formula, if the record volume is very large, the cup, the slider will be very small, the user is difficult to catch the slider with the mouse. A sharp eye and a quick hand can accomplish this difficult task. So the minimum value for sliding easy positioning.

 s = max((float)((r.bottom - r.top) / (si.nMax - si.nMin) * si.nPage), 20.0f);
3, Slide position calculation

It is necessary to deduct the size of the slider to see the effective sliding position of the slider on the graph.

Actual sliding position = (ScrollBar height-slider size)/(valid range-Number per page + 1) * Current line position

If there is division, there will be some precision problems, so check out the location to see if the location beyond the customer area.

0;if (si.nPos > 0)     v = (int)((r.bottom - r.top - s) / (float)(si.nMax - si.nMin + 1 - si.nPage) * si.nPos);// 由于精度问题,可能滑块位置会超界。超界就取最大值if (v && v + (int)s > r.bottom) v = r.bottom - (int)s;
Second, scroll bar information

Do scroll bar must record the above mentioned information. Use this structure record directly for easy periods static SCROLLINFO si; . Used directly when setting up and getting.

Custom scroll bars cannot use setscrollinfo or getscrollinfo , both of which are provided to the system. An additional 2 messages are required, and the system has provided two messages that can be used directly. sbm_setscrollinfo and sbm_getscrollinfo handle scrolling information.

Parameters:

  • WParam---sbm_setscrollinfo need to be refreshed, Sbm_getscrollinfo is not valid.
  • LParam---*scrollinfo pointer to the struct body.

The previous reference to Fmaskin the SCROLLINFO structure is required for setup and acquisition.

Mask Value:

  • Sif_range---Set the line number range parameter NMin ~ NMax These two parameter values are valid.
  • Sif_page---Number of rows per page npage parameter value is valid
  • Sif_pos---Position value nPos parameter value is valid
  • Sif_all---All parameter values are valid.

Other corresponding values can be found in the MSDN documentation.

Case Sbm_setscrollinfo:if (!lparam)Return0;Set scroll bar Information PSRCSI = (SCROLLINFO *) LParam;if (Psrcsi->fmask & Sif_range) {//Set content line number Si.nmax = psrcsi->nmax; si.nmin = psrcsi->nmin;} if (Psrcsi->fmask & sif_page) //page can show how many lines si.npage = psrcsi->npage; if (Psrcsi->fmask & Sif_pos) //Line display position Si.npos = psrcsi->npos; //WParam = True refreshes the scrolling area if (WParam) InvalidateRect (hwnd, NULL, false); return 0;  Case Sbm_getscrollinfo: //Here simple processing, should and sbm_setscrollinfo like to judge the information obtained. if (lParam) * (SCROLLINFO *) LParam = si; return 0;               
Third, scroll bar drawing

With basic scroll bar structure information, it's easy to draw your own scroll bar. One thing you need to be aware of is that when the scrollbar size is smaller than the size of the slider, stop drawing the slider.

tip: You can use the ExtTextOut function when filling a color block to reduce flicker without using a dual cache, and you do not need to apply for a paint brush.

Staticvoid mlCgfillcolor (hdc hdc, RECT *r,Unsignedint color) {The actual use of exttextout is better than the FillRect fill color effect, can reduce the flicker problem in the drawing. And don't apply for paint brushes. SetBkColor (hdc, color); ExtTextOut (HDC,0,0, Eto_opaque, R,0,0,0);}WM_PAINT CodeDraw background Color GetClientRect (hwnd, &R); MLCgfillcolor (hdc, &r,0XCCCCCC);Calculate the slider size, do not draw over the hourif (R.bottom-r.top >&& Si.nmax && (si.nmax-si.nmin) >= (int) si.npage) {Slider calculationSize = ScrollBar Height/Active range * Quantity per pageMinimum 20, more content, lower the difficulty for mouse positioning to scroll bar drag. s = Max (float) ((r.bottom-r.top)/(si.nmax-si.nmin) * si.npage),20.0f);Actual sliding position= (ScrollBar height-slider size)/(valid range-Number per page + 1) * Current line positionThe actual scrolling position will be less than the actual number of pages.v =0;if (Si.npos >0) v = (int) ((r.bottom-r.top-s)/(float) (Si.nmax-si.nmin + 1-si.npage) * si.npos); //Due to accuracy problems, the slider position may be hyper-bounded. The maximum value if the bounds are (v && v + (int) s > r.bottom) v = r.bottom-(int) s; //Draw slider r.left++; r.right--; r.top = v; r.bottom = r.top + (int) s; //Drag slider color reverse mlcgfillcolor (hdc, &r, dragstate?) 0x999999: 0x666666e); Inflaterect (&r, -1, -1); MLcgfillcolor (hdc, &r, dragstate?) 0x666666e: 0x999999);}                
Iv. Responding to mouse messages

Mouse messages, mainly left click to locate, drag and scroll wheel scrolling.

1. Click the location response

Click the left mouse button scroll bar position, you can directly navigate to the corresponding row. This feature is the first requirement to quickly navigate to a record line based on the identity. The real core is the actual position of the scroll bar where the mouse is located, calculating the corresponding number of rows.

Calculation method:
NPos = (mouse position-half slide size)/per pixel sliding volume

  • Sliding volume per pixel = effective height/Sliding quantity
  • Effective height = Total height-Slide size
  • Sliding quantity = Total-Quantity per page

According to the above formula, a general method is extracted to calculate the relation function of the pixel position corresponding to the number of rows.

Calculate scroll bar positionStaticIntCalcvertthumpos(int postion, SCROLLINFO *si,int s) {float thumsize;The size of the sliderfloat pxsize;Sliding momentum per pixelint scrollcnt;Number of slides availableSlider size = ScrollBar Height/Active range * Quantity per pageMin. thumsize = max (float) ((s)/(si->nmax-si->nmin) * si->npage),20.0f);if (postion <= (int) (Thumsize/2))Return0; if (postion >= S-(thumsize/2))  Return (si->nmax-si->nmin + 1)-si->npage; //calculation method: //per pixel sliding volume = active height/sliding quantity // Effective height = Total height-Slider size //sliding quantity = Total-Quantity per page scrollcnt = (si->nmax-si->nmin + 1)-si->npage; Pxsize = (float) (s-thumsize)/(float) scrollcnt; ////calculation method: //position = (mouse position-half slide size)/per pixel slide volume return (int) ((Postion-thumsize/2.0)/ pxsize)}                 

Mouse left-click event Response WM_LBUTTONDOWN message.

si.nTrackPos = calcVertThumPos(GET_Y_LPARAM(lParam), &si, height);if (si.nPos != si.nTrackPos)     PostMessage(GetParent(hwnd), WM_VSCROLL, SB_THUMBTRACK, (LPARAM)hwnd);

Use the calcvertthumpos function to calculate the scroll position and scroll through the WM_VSCROLL message request.

Note In MSDN, the Wm_vscroll lparam parameter convention is used when custom controls are typically passed to the HWND of a custom control. Used to differentiate between a system default or a custom control.

Click on the location to get it done.

2, drag slider roll response

Drag-and-drop scrolling requires a simultaneous use of 3 messages Wm_lbuttondown,wm_mousemove , and wm_lbuttonup. When the mouse is pressed ready to drag and drop, drag in the scroll record, mouse release end drag.

Normally the mouse is pressed to lock the mouse setcapture, but sometimes just click, and no need to drag. or internal processing more control, the direct lock is not very good. As a result, a dragstate state is added to the drag-and-drop, and the mouse action is locked only when you are ready to drag.

In another case, some abnormal conditions, the locked mouse will be lost. If the breakpoint debugging will be interrupted, this time there will be unwanted situations. Not in the drag state, the mouse has been released, the slider will still follow the mouse to move.

Case WM_LBUTTONDOWN: ... dragstate =1;Prepare to drag the scroll bar invalidaterect (hwnd,NullFALSE);Return0;Case WM_MOUSEMOVE:if (dragstate = =1) {setcapture (HWND);With drag-and-drop preparation, lock the mouse mouse dragstate =2; }Elseif (dragstate = =2) {if (! ( WParam &Mk_lbutton)) {dragstate =0;Prevent intermediate interrupts, resulting in invalid drag and dropif (getcapture () = = hwnd) releasecapture (); else {//drag the scrollbar position in the locked state. Si.ntrackpos = Calcvertthumpos (Get_y_lparam (LPARAM), &si, height); if (si.ntrackpos! = Si.npos) PostMessage (GetParent (HWND), Wm_vscroll, Sb_thumbtrack, ( LPARAM) HWND); }} return 0; Case WM_LBUTTONUP: if (dragstate = 2) releasecapture (); //release mouse lock if (dragstate) {dragstate = 0; Span class= "Hljs-comment" >//Clear Status InvalidateRect (hwnd, null,  FALSE); } return 0;         
Mouse wheel Response

Scrolling event WM_MouseWheel, there is a precision when the mouse scrolls over the page. Slowly scrolling the wheel moves up or down about 3 rows, and when you scroll quickly, it's easy to get to the end of the document. This is the precision that is generally said.

This is handled by default, scrolling the wheel once to move three rows. Once you have the number of scrolling lines, you can accumulate them directly on the current number NPos . Look out, don't go over the border.

// 鼠标滚动支持accumDelta = GET_WHEEL_DELTA_WPARAM(wParam) / WHEEL_DELTA;  // 滚动精度120一个单位si.nTrackPos = si.nPos - accumDelta * 3;   // 每滚一次3行if (si.nTrackPos < 0) si.nTrackPos = 0;else if (si.nTrackPos > (int)((si.nMax - si.nMin + 1) - si.nPage)) si.nTrackPos = (si.nMax - si.nMin + 1) - si.nPage;if (si.nPos != si.nTrackPos) PostMessage(GetParent(hwnd), WM_VSCROLL, SB_THUMBTRACK, (LPARAM)hwnd);
~ok.

The simple scroll bar is done, and then the logo and so on can be played on this basis. It's up to you to control the scroll bar entirely.

The final effect:

Full code:

  • Github/cmacro simple/gdi_win/testscrollcalc/

Mushroom Room moguf.com

Related Messages and APIs:

  • Sbm_setscrollinfo---setting scroll bar information
  • Sbm_getscrollinfo---get scroll bar information
  • Wm_vscroll---scrolling messages
  • Wm_lbuttondown---left mouse click to press the message
  • Wm_lbuttonup---left mouse click to pop up the message
  • Wm_mousemove---mouse move message
  • WM_MouseWheel---mouse wheel messages
  • SetCapture---mouse capture
  • ReleaseCapture--Release the mouse
  • ExtTextOut---Text and is used for background padding.

Http://www.cnblogs.com/gleam/p/5433719.html

Interface Controls-scroll bar scrollbar (a good combination of scroll bar messages and mouse messages)

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.