About listctrol owner-draw and custom-draw

Source: Internet
Author: User

1. Owner-draw and custom drawing (custom-draw)

1. Add the sorting function to the control
The report-style list control needs to support sorting in many cases, and it is best to support sorting by different columns. The clistctrl class method sortitems supports the sorting function. However, during the sorting process, the actual comparison process of the two data is completed through the callback comparison function pointed to by the first parameter of sortitems. By comparing the values corresponding to each item set by the setitemdata function, this function returns a value representing the comparison result. sortitems can sort the values based on the returned values. It can be seen that this method is simple,
But there is a serious defect, that is, it cannot be sorted by different columns of data.
To support sorting by different columns, you need to do the following:
1. The list control responds to the lnv_columnclick message, obtains the column number to be sorted, and notifies headerctrl to draw a forward or inverted triangle mark on the column head;
2. Write a comparison function. The function is similar to the callback function mentioned above, but this function will be called by our own sorting function. To support sorting of multiple types of column values, this function should be able to compare different types of values;
3. Write a list control row exchange function. After the sort function calls the comparison function, it calls this function based on the returned value to complete the sorting. This function can be implemented by calling deleteitem and insertitem functions, or by exchanging data in two rows through getitem and setitem functions;
4. Write a sorting function. This function is similar to the above functions completed by the sortitems function. By specifying the column number, sorting method (positive or inverted), and the row number of the start and end of the sorting, according to a certain sorting Policy (insert sorting, fast sorting, etc ), you can call the comparison function and the row exchange function to complete sorting. If there are not many data items in the list, it is quite satisfactory to use recursive calls to achieve fast sorting.

2. Add progress bars
Adding a progress bar to the list control is also a common requirement. Unfortunately, clistctrl does not seem to provide a direct solution to this problem. There are two ways of thinking: one is to create a progress bar control, embed it into the corresponding position of the list control, and process the progress bar display through the Response Message. For the self-painted control, directly drawing your own progress bar may be a simpler and more effective method, and the effect of this idea may surprise people.
Here we introduce a method to use the Paster progress bar, which has a very good effect. First, you need to define two cbitmap-type variables to load the progress bar background and foreground bitmap resources, and then calculate the size of the subitem where the progress bar is located, the size of the progress bar background area, and the size of the foreground area. Finally, to draw the position of the progress bar in the control's self-painting function drawitem, call the stretchblt function of DC to display the progress bar background and foreground bitmap in a stretch mode.

3. Support for multi-line text
If the text displayed for a subitem is too long, multiple lines of text are very important. In fact, multi-line text display reflects the idea program of the Self-painted control to a large extent: When you need to draw, you can calculate the size of the drawn area and the size of the area required for the displayed content, make appropriate policies and display them in a correct and reasonable manner.
Multi-line text display is supported. First, the size of the display area is calculated. Then, the getlogfont function is used to query the font attributes currently set to get the font height and width; then, you can calculate the number of lines of text to be displayed and the number of words to be displayed in each line. Of course, because of the differences between Chinese and English, the font width cannot be calculated simply. You can use the gettextextent function of DC to obtain the actual size of the area required by the text, and then adjust it accordingly. In addition, when the display area is full, you can use "..." to indicate the remaining characters.

4. scroll bars
The scroll bar of the list control is very useful. Here I don't want to talk about the content of the scroll bar, such as self-painting, which is a complicated topic. In fact, the cwnd class of MFC can be set to ws_vscroll and ws_hscroll, which respectively represent support for vertical scroll bars and horizontal scroll bars. clistctrl is inherited from cwnd, which is naturally no exception. What makes us even more pleased is that the clistctrl base class has implemented the scroll bar
Function and control, but the scroll bar here is not a scrollbar control, but a clistctrl self-drawn.
Although we do not need to implement the scroll bar function by ourselves, we still need to have some concepts about the attributes and features of the scroll bar in clistctrl, because sometimes we need to use it. For example, we use the drawitem function to plot the display of each item. We need to refresh the remaining area in the background refresh function onerasebkgnd. Then, we need to calculate the position of the remaining area based on the number of items and Row Height, now we have to consider
The position of the scroll bar. You can use the getscrollinfo function to obtain the scroll bar information. The structure of scrollinfo information must be described. Definition:
Typedef struct tagscrollinfo
{
Uint cbsize;
Uint fmask;
Int Nmin;
Int Nmax;
Uint npage;
Int NPOs;
Int ntrackpos;
} Scrollinfo, far * lpscrollinfo;
Typedef scrollinfo const far * lpcscrollinfo;
Nmin and Nmax indicate the scroll range set by the current scroll bar, while NPOs indicate the position of the current scroll block in the scroll bar. This position is relative to Nmin and Nmax. For example, the value range is (). If the scroll block is located in the middle of the scroll bar, the value is 15. Npage indicates the number of scroll positions on each page of the scroll bar. Generally speaking, when you click a position other than the scroll block in the scroll bar, the scroll bar will flip up or down, the number of rolling positions is the value of npage. It can be seen from the above that the number of workers corresponding to a rolling position can be calculated based on the rolling window size and the set rolling range. In clistctrl, we can see from the actual debugging that the number of rows in which the vertical scroll bar scrolls to a position is actually the Row Height of the list control, that is, the Nmin in info is 0, nmax indicates the number of rows that can be included in the hidden area height.

5. Prevent flashing during refresh
Almost all controls and views must be refreshed. Almost all solutions are regarded as "dual Buffering" technology. In fact, sometimes double buffering may not solve the problem, and sometimes it may not be as complicated as double buffering. The most important thing is to figure out why flash occurs. Apart from the performance of the video card, the biggest cause of Flash is that the screen difference is too large before and after refresh. With this in mind, many phenomena can clearly analyze the cause. For example, you have completed Double Buffering in the refresh function, but unfortunately you find that the flash still exists. I think it is very likely that you have not stopped MFC from refreshing the window background by default. All you need to do is overwrite the onerasebkgnd function of the base class, draw the background by yourself, and return true, to tell windows not to help you draw the background.
There are actually many ways to prevent flickering. We can handle the background in onerasebkgnd to eliminate the flickering caused by large background differences; we can use double buffering technology in the onpaint or ondraw functions to reduce the flickering caused by frequent refresh due to drawing Complex Images. When we call a function that causes invalid areas or windows, set parameters to prevent background re-painting. We can refine the re-painting area to minimize the number of re-painting areas when force-refreshing...

Vi. Troubles caused by adjusting the column width
When you inadvertently adjust the column width of headerctrl, you may suddenly find many problems with the self-painted list control:
1. Your first column is a thumbnail. You do not want to adjust the column width;
2. When you adjust the width of a column to 0, you cannot see it, and it seems very difficult to get it out. Or when you reduce the width of a column to a certain extent, we found that the two columns were drawn in coincidence;
3. You reduced the width of a column and found that the last column moved to the left, but the rightmost area of headerctrl showed different background colors. (This may be different for different versions. Unicode has this problem. The multibytes version does not exist. I have not figured out the cause)
For the first problem, you need to support a column and do not support adjusting the column width. For the second problem, you need to set a minimum column width. For the third problem, an effective solution is to dynamically adjust the width of the rightmost column so that it always conforms to the window width of the list control.
1. Fixed column width is supported.
It is very easy to override the virtual function onchildnotify in headerctrl. When the message type is hdn_begintrackw and hdn_begintracka, and the column number is the column to be fixed, directly assign the plresult parameter to true, and return true.
In this way, messages between the adjustment columns are blocked, so the list control will not receive the corresponding message. Of course, if you want to do something nice, you can also block the cursor change action at this time.
2. Set the minimum width of a column
It is also very easy to override the list control's virtual function onnotify. When the message type is hdn_itemchangingw or hdn_itemchanginga, the column number is the column whose minimum width needs to be set. When the column width is smaller than the set column width, assign true to the parameter presult and return true. Here we need to explain a problem. After imagelist is set in your list control, the minimum width and height of all subitems are the size of the image in imagelist, therefore, when you call the getsubitemrect function in the drawitem function to query the subitem size, the returned results are different from the results displayed on the interface. Note this 1.1. This is also the cause of the overlap of the above two columns.
3. dynamically set the width of the rightmost column to a proper size.
At the same position as the preceding function, adjust the width of the rightmost column when processing messages whose width is adjusted. It should be noted that the call to the setcolumnwidth function will trigger this message again, so you need to determine whether the current adjustment column is the rightmost column, otherwise it will continue to loop, causing the program to crash.
In addition, when you call the setcolumnwidth function, set the parameter to lvscw_autosize_useheader. Instead of updating the width immediately, you must set a specific value. It may be lvscw_autosize_useheader. This parameter does not force the list control to refresh immediately and takes effect only when the list control is refreshed next time.

The clistctrl control is one of the most functional controls in the MFC control. It can be summarized and learned a lot, other functions that can be researched and enriched include tooltip, self-painting scroll bar, edit subitem, drag and drop, group function, virtual list, etc.

These two methods should be the most common method in Control Self-painting. (Of course, you only need to process the wm_ctlcolor message to change the color of the Control .) However, many developers may not be very clear about the differences between the two. If you have made the Control Self-painting, you may be familiar with the owner-draw. Generally, you only need to set the control's self-painting style attribute and implement the owner-draw message (wm_drawitem) to respond to the virtual function (drawitem. Controls that can be used in this method include buttons, ComboBox, listctrl, menu, statusbar, headerctrl, tabctrl, and many other controls with a self-painted style, when the control needs to be re-painted, MFC calls the rendering function and transmits information such as the DC and control position and size. What we need to do is to use this information to draw the desired control appearance. However, this method cannot be used for editctrl, or for a non-Report-style listctrl.
The custom-draw method is the nm_customdraw message in response. Unlike the wm_drawitem message, it is included in the wm_notify message and sent. Message ing must be added to the class implementation. Compared with the owner-draw method, the biggest advantage of this method is that it strictly controls the draw phase and can implement different draw policies in different response phases, for example, you can either draw by default or reload the function for special painting, or you can only change the value of some variables so that the MFC can re-paint as required. We know that in the drawing function of owner-draw mode, code control of GDI or GDI + is required for all the Drawing details, while in the custom-draw mode, we may only need to change the variable values (such as the control color. Controls supported by custom-draw include listview, toolbar, tooltip, and Treeview. listctrl supports all styles. For more information about custom-draw, refer to this article http://msdn.microsoft.com/zh-cn/library/ms364048 (vs.80). aspx.

Ii. Load thumbnails
This is actually very simple. You can create a cimagelist type object, customize the image size and pixel type, and then call the setimagelist function of clistctrl to set it. Note that the small type must be set in the normal and small types.

3. Custom Headers
Write a subclass that inherits cheaderctrl to implement the drawitem function. Set and draw the background, Font, and text color of the header. If you want to change the height of the header, you can map the hdm_layout message Response Function and set the control layout. Then, declare a custom headerctrl type variable in your listctrl class, and call the subclasswindow function of headerctrl in the presubclasswindow function to subclass it, then, you can set the format of each item to hdf_ownerdraw during initialization.

4. Adjust the clistctrl background, Font, text color, and line height.
The implementation method is basically the same as that of the preceding header. Of course, you must set the list self-painting style and select the self-painting method. In addition, if a thumbnail is loaded, the row height is adjusted accordingly. Another simple method is to set the font size, which is similar to the thumbnail. If you want to define the Row Height accurately, it is more troublesome. First, set the self-painting style of the list, then reload the measureitem function, set the value of the item height variable in the struct, and then add on_wm_measureitem_reflect () in message ing (), you can make the list respond to change the row height when appropriate. Note the following two points:
1. The message response functions of measureitem and wm_measureitem are different;
2. The wm_measureitem message that triggers the measureitem function call is sent only under certain conditions. A simple method is to send a wm_windowposchanged message to trigger the message.
3. Set the lvs_ownerdrawfixed style in the create or presubclasswindow function. Otherwise, measureitem will not be called.

Http://www.cnblogs.com/BeyondTechnology/archive/2011/03/25/1995921.html

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.