Technology is not advanced and backward, only suitable and inappropriate.
This article’s custom control is: the scrollbar.
We can see many custom scrollbar controls on the Internet. Most of them are done by using UserControl, that is, at least one panel or other control is used as the slider, the UserControl itself or another control is used as the background bar, and some complicated ones are added with buttons at the top and bottom. There are many advantages of this, the most important is to support more complex visual and action effects, such as using a series of pictures to achieve very dazzling animation effects.
However, the scroll bar implemented this time does not need too many complex effects. It can be flattened, so there is no need to use UserControl. Therefore, we can directly refer to the ltrackbar in the previous article to implement a scroll bar with a similar style. This is one of the reasons why this article follows the previous one.
Just as it is difficult to calculate the coordinates of the rounded corners when implementing the ltrackbar in the previous article, and then focus on the illustration, in this article, I will explain in detail the counter intuitive and not intuitive imagination of the scroll bar in combination with the schematic diagram.
I believe you will get something after watching it.
2、 Preliminary analysis
（1） Why do I need custom scrollbars?
The scrollbar control is often ignored, but it is used very frequently. As many controls have their own scroll bar, it is often overlooked that the existence of the scroll bar.
However, there is a big drawback of the scrollbars provided by these controls, that is, it is almost impossible to redraw the scrollbars individually, or even adjust the width of the scrollbars provided by the controls. The “seemingly simple” operation, the real workload is almost “suspicious”.
Moreover, the scrollbar controls of the system, vscrollbar and hscrollbar, are still the most basic ones, and their redrawability is very small.
The system control has its own scroll bar. In general WinForm program, it looks very good, but once you use a large proportion of custom controls in WinForm program, the system’s scroll bar will be a bit “dazzling”. Therefore, you need your own scroll bar control.
（2） Achieving goals
Referring to the ltrackbar control in the previous article, I want to implement the appearance style of the scroll bar as follows:
(1) Support mouse drag.
(2) Support to click the non “slider” area to change the slider position.
(3) Support to change the color of the slider when the mouse enters.
(4) Support to modify the color of each part.
(1) Support to change the direction of the scroll bar: vertical or horizontal.
(2) Support color change.
(3) Support round corner and right angle display.
（3） Technical analysis
Similar to ltrackbar, the scroll bar control lscrollbar is also divided into a background bar and a slider. The core technology used is still GDI +.
（4） Scroll bar explanation
Here, I will explain the scroll bar in detail, including the effect of the scroll bar, the calculation of the proportion, etc.
In this section, I will use the “right angle” and “vertical” style scroll bar to explain.
1. How the scroll bar works.
As shown in the figure below, we split the scroll bar and display content into two parts.
Among them, the translucent black part is the “screen”, which is what we can actually see. The actual length of the “document” is much longer than the display part of the screen, so you need to use the “scroll bar” to “scroll” up and down to see other parts of the document.
So, in the intuitive imagination, “rolling” should be like the following animation demonstration:
However, this is not the case. Because the screen does not move now, the document can only be scrolled, so the real scrolling should be like this:
in other words,When we drag the slider of the scroll bar down, the document is actually “up”.
In the specific use of program implementation, that is to change the “Y” coordinate value of “document”.
2. Ratio calculation.
After knowing the internal principle of the scroll bar, it is necessary to calculate some ratios, such as the length of the scroll bar “slider”, the ratio of the drag distance of the slider to the change of the “document” position, etc.
First of all, as not shown in the figure below, I added some signs to facilitate the description.
Length of document = a.
Length of screen = length of visible document section = B.
Then, the invisible document length = A-B = C.
Length of scroll bar = D.
Length of slider = E.
Drag range of slider = D-E = F.
In the implementation, we have the following quantities: a (document length), B (screen length), D (scroll bar length), while e (slider length) is unknown and calculated.
In the process of daily use, we will also find that if the more content to display, the shorter the length of the slider.
The proportion relationship is as follows:
E = D * B / A.
Now we have the length of the slider, which is avery importantThe basic quantity of.
After e (length of slider) is obtained, f (movable range of slider) can also be obtained
Because the “screen” already shows a part of the “document”, the “document” part that you really need to view through the scroll bar is C (invisible document length): C (invisible document length)
From this, we can get an important ratio relation
N * f (slider drag range) = m * C (invisible document length)
(Note: adding N and M is because the relationship between F and C is not 1:1)
We use x instead of this ratio
Why calculate this ratio,Because when we use the scroll bar, we don’t think about whether the mouse is dragging down or up, and how far it has been dragged. Instead, you only need to know the position of the “slider” of the scroll bar, or more accurately, the distance between the top of the “slider” and the top of the scroll barAs shown in the figure below, all we need to know is the value of F (Note: this f is not the f above).
Through the value of F, we calculate the value of B, and then make the “document” move up the distance of B, which is how to use the scroll bar.
So, how to get B from F is very important. This requires a ratio. Through this ratio, f is converted to B, and the ratio is x above.
Through X, we can get the following information:
a. When you drag the scroll bar, the document should be “moved up” by a distance b:
b. After the position of the document is changed, the position of the scroll bar is changed
3、 Start to implement
（1） Preliminary preparation.
Since the implementation of the scroll bar control (lscrollbar) in this article is implemented with reference to the ltrackbar in the previous article, so it is only used for outline, and the specific operation is shown in the previous article.
New class: LScrollBar.cs
Add inheritance: control (need to add reference: System.Windows.Forms .dll）
Modify the accessibility to public
（2） Add control properties
Because this control is very similar to the ltrackbar in the previous article, some properties can also be used directly. This is also a kind of “reuse”.
1. Scroll bar background color
2. Slider color
3. The color of the slider after the mouse enters the scroll bar
This is a kind of prompt color. For example, the scroll bar of some software and web pages is a color at ordinary times, and it is a color when the mouse is above the scroll bar. This property is to achieve this effect.
4. Is the scroll bar rounded or square
5. Scroll bar direction
Unlike the ltrackbar, there are only two directions for the lscrollbar: horizontal and vertical. Therefore, we need to create a new direction enumeration. To avoid conflicts with the ltrackbar direction enumeration, we name the enumeration orientation scrollbar
When you change the direction of the scroll bar, the following code will automatically swap the width and height of the scroll bar.
6. Scroll bar size
The size here refers to the width (in vertical direction) or height (in horizontal direction) of the scroll bar (lscrollbar).
To support this property, you also need to set the control so that it can only modify the height (in the vertical direction) or the width (in the horizontal direction), and you need to override setboundscore.
After rewriting setboundscore, we can only adjust the width or height of the control in the designer interface.
7, “document” length
The term “document” here is derived from MFC and is still used in this department. It refers to the total length to be displayed.
It is convenient to use “length” here. Otherwise, it is too cumbersome to say “height” in vertical state and “width” in horizontal state.
When the document length is set, we call two methods: pinit() and pchangesliderlocation().
The function of pinit() is to initialize each proportion and calculate the length of slider. The purpose of pchangesliderlocation() is to change the position of the slider. The code is as follows:
8, “page” length
Indicates the length of the window that can be displayed.
9. Slider position
Here, the position of the slider refers to the distance between the top of the slider and the top of the scroll bar.
Here, I set it as public read-only because this property is more used to view. If you modify it directly, you need to calculate the proportion. In order to calculate the proportion, you need to provide some additional values to support its calculation, which is very troublesome, so users are not allowed to modify it directly. If you want to change the position of the slider, use the “display position” property below to set it.
10, display position (positive)
The display position here is the distance between the top of the document and the display window.
Take the vertical state as an example, which is its y coordinate, because by default, the coordinate direction of the system is positive to the right and positive to the down. And its origin is the upper left corner of the display window, so the Y coordinate value of “document” is a negative number. In order to facilitate calculation and processing, we will process it in the way of positive number.
When the user sets this property, we will automatically make corresponding calculation and change the position of the slider (that is, the value of the “slider position” attribute above). In this way, the user only needs to know the position of the “document”. When the user sets the position of the document, the position of the slider will automatically change.
11. Sliding distance
This property is public read-only for use in some cases.
12. Slide length
This property is public read-only for use in some cases.
13. Minimum length of slide
In normal state, the scroll bar supports the mouse to press and drag on the slider, so the length of the slider cannot be too short. Of course, if you use the scroll bar only for display and do not need to operate, you can set the minimum length of the slider to 0.
14, rolling interval distance
This attribute is the distance the slider moves each time when using the mouse wheel to scroll up and down, and when pressing the up, down, left and right keys.
This distance is the distance under the “document” angle, not the actual moving distance of the slider. The reason for this setting is that it is convenient for users to set it according to their needs. For example, if they want to implement a listbox, each time they press the key, it is the height of one line. At this time, you can set this property to the height value of that line.
（3） Add event
For the lscrollbar, only one event is needed, that is, the event when the slider scrolls.
Of course, it is estimated that many people will think of many events in the first implementation, such as clicking the slider event, clicking the blank part of the slider event, dragging event, and so on. But we need to remember how the scroll bar works: just know the position of the slider. The result of the previous events is that the position of the slider has changed, so it can be grouped into one event.
（4） Rewriting method
Onpaint is the fundamental to achieve the effect, but the content of this implementation is much simpler than that of ltrackbar. Generally speaking, it is to draw a background bar and then a slider.
Because we want to change the color of the slider when the mouse is above the scroll bar, we need to set the color of the slider to the value of the property: “slider color after the mouse enters the scroll bar”, and redraw the control.
As above, after the mouse leaves the scroll bar, we set the color of the slider to the value of the property: slider color.
Here, we need to determine the location of the next mouse click: the point on the slider, the point above the slider, the point below the slider.
According to daily use experience, when clicking on a non slider, it has corresponding effect. Generally, the blank space above the slider represents “previous page”, that is, subtracting the value of the attribute “page length”. Similarly, clicking the blank space below the slider represents “next page”, that is, adding the value of the property “page length”.
Here, when the mouse point on the slider, hold down the mouse and drag.
In onmousedown above, we calculated two additional values: fabove and fbelow, which are used to calculate the position of the slider at this time.
The details are shown in the following figure:
We need to rewrite this method if we want to roll the mouse wheel button (middle button) with the slider to scroll up and down.
One attribute of the event is needed: Delta. The description of its MSDN is as follows:
When the roller rolls down, the delta value is negative; when the roller rolls up, the delta value is positive.
According to the MSDN explanation above, we only need to know whether the scroll wheel rolls up or down. Depending on whether the scroll wheel is scrolling up or down, the value of the display position is added or subtracted from the value of the attribute: rolling interval distance.
In this method, the main purpose of this method is to implement the corresponding operation when pressing the mouse arrow key.
When the scroll bar is vertical, press the up arrow key to scroll the slider upward; press the arrow key to scroll down.
When the scroll bar is horizontal, press the left arrow key to scroll the slider to the left; press the right arrow key to scroll the slider to the right.
When the key is pressed, the value of the display position is added or subtracted from the value of the property “scroll interval distance”.
（5） Add double buffer
In order to avoid the scroll bar flashing when dragging the slider and changing the size of the scroll bar, the double buffer support is added in its constructor.
（6） Add default event
In order to achieve double-click control, it will automatically implement the only one event: L_ Scrolled, so add default event support at the top of the class.
（7） Other instructions
1. Hide an attribute in the properties window
In addition to category and description, I have added category and description to the previous attributes, which are classification and description, respectively. There is also a browsable (false), as shown in the following figure. Its function is not to be displayed in the “attribute” window of the design interface.
Browsable (false) can be added to some non settable properties or properties that users do not want to set directly through the properties window.
Of course, you can still see this property prompt in the code interface.
2. Method and property display prompt when writing code
As shown in the figure below, the corresponding Chinese prompt will pop up when the mouse is put up, and the Chinese prompt will be displayed in the intelligent prompt when writing code.
To achieve this effect, you must first enter “/ / /” on the property or method. At this time, vs will automatically complete, and then you can add the desired prompt. The attributes like above are all written like this.
However, if you only write this way, you can display Chinese prompts in the same solution. If you refer to the generated DLL separately, there will be no prompt. At this time, you need to generate the corresponding XML help document. In this way, when referencing the DLL, vs will automatically load the corresponding XML file, and there will be corresponding prompts.
XML generation method: select the property of the control class library and check “XML file file” in the “generate” tab. Vs will automatically fill in the generation path. If you want to generate it to other places, you can modify it yourself.
However, when referring to DLL separately, it is necessary to ensure that the DLL and XML files are in the same directory.
4、 Effect demonstration
In this section, we will not only demonstrate the various effects and features of the scroll bar lscrollbar, but also demonstrate how to use lscrollbar.
We’ll add 50 buttons to a panel and then move them up and down by manipulating the scroll bar.
First of all, we create a new WinForm program and add the following controls to it. The control names are as follows:
Next, we double-click the load list button and write the following code into its method. The code function is to add 50 buttons to panel 1.
Finally, we double-click the scroll bar lscrollbar1 to write the following code into its method. The code function is to display the position of the current slider and the distance between all the current buttons and the initial position; the second is to change the position of all buttons to achieve the rolling effect.
After that, compile and run the program, and the running effect is as follows:
5、 Adjustment and optimization
The implementation of lscrollbar to this point is enough for me now, and for most of the places where you need to use custom scrollbars. However, it is not without shortcomings or optimization.
One of the most important points is that it can not directly replace the scroll bar of system control, such as replacing the scroll bar of listbox and textbox.
The reason why it can’t be replaced is that for listbox, textbox and other controls with their own scrollbars, the scrolling of scrollbars is controlled and processed through windows messages, while lscrollbar does not intercept and process these scrollbar messages.
If you want to use lscrollbar to replace the scrollbars of listbox and textbox, you can refer to the following ideas:
First, the processing of scrollbar messages should be added in lscrollbar, including interception and sending.
Then, you can directly adjust the width of lscrollbar to the same width as the scroll bar of listbox and textbox, and then overlay it;
Or hide the scroll bar of listbox and textbox, and put lscrollbar beside it.
Through the above method, we can achieve the effect of “customizing the scrollbar of listbox and TextBox control”.
Note: in view of the space, personal needs and usage scenarios, I did not achieve the above effect of replacing listbox and textbox scrollbars, but only verified from the logical level that the expected effect could be achieved.
In the future, if necessary, I will consider writing an article to achieve this effect.
Through the whole article, we will find that the technical level is not too difficult, but the difficulty lies in breaking through the shackles of conventional thinking.
As you can see, WinForm is not unable to achieve dazzling and more modern effects, but it needs some imagination and more efforts. Similarly, although webui such as WPF and electron are more modern in themselves, it takes a lot of effort to achieve a certain dazzling effect and a more user-friendly interface. It’s not to say that using a new language or framework can easily or automatically achieve the desired effect.
Technology is not advanced and backward, only appropriate and inappropriate, because each has its own advantages and disadvantages, each good and not good at.
Therefore, they should have more confidence in their knowledge, release their imagination and improve themselves in practice.
7、 Source code and Project Download