Add a smart horizontal scroll bar to clistbox

Source: Internet
Author: User
In MFC, it is convenient to use a list box (clistbox) to display multiple strings. However, the horizontal scroll bar of the default list box is not smart enough-the meaning of intelligence here is: when it should appear, it should not disappear, and it should be able to automatically adjust its own size. This article illustrates the existing problems and solutions through examples.

I. Problem demonstration

First, use the Visual Studio Application Wizard to create the customclistbox project. This is a dialog box-based application. All optional parameters provided by the wizard use their default values.

In the resource editor, set the main text box font to 12 12, insert a clistbox control, set its ID to idc_llisttest, And the size is 125x84. Make sure that the vertical and horizontal scroll bars of the list box are valid to cancel the sorting style.

Start Class Wizard, select the member variables tab, add the corresponding member variable m_llisttest to the list box, and select control in category.

Next, select classview In the workspace pane, expand the ccustomclistboxdlg class, double-click oninitdialog (), find the comment line "Todo: add extra initialization here" in the editing pane, and add the following content to the line:

M_llisttest.addstring (_ T ("one "));
M_llisttest.addstring (_ T ("two "));
M_llisttest.addstring (_ T ("three "));
M_llisttest.addstring (_ T ("four "));
M_llisttest.addstring (_ T ("five "));
M_llisttest.addstring (_ T ("six "));
M_llisttest.addstring (_ T ("North China scenery, thousands of miles of ice, thousands of miles of snow. "));
M_llisttest.addstring (_ T ("Eight "));
M_llisttest.addstring (_ T ("Nine "));
M_llisttest.addstring (_ T ("Ten "));

Compile and run this project, and you will find that the list box correctly displays all the content.

If you add a line after m_llisttext.addstring (_ t "Ten:

M_llisttest.addstring (_ T ("Eleven "));

Recompile and run the project. A vertical scroll bar is displayed. The vertical scroll bar decreases the horizontal display width of the list box. The content of the seventh row is cut and cannot be completely displayed. However, the horizontal scroll bar does not appear automatically at this time, and the seventh row cannot be seen after it is cut.

If we delete the last added statement and extend the number of Chinese characters in the seventh row to a value that exceeds the display width of the list box, we can also find that the horizontal scroll bar does not appear automatically. The cut part is still invisible.

It can be seen that the horizontal scroll bar of clistbox is not as "smart" as the vertical scroll bar: the vertical scroll bar can always appear automatically when it is needed, and can automatically adjust its own size, while the horizontal scroll bar cannot.

Ii. Solving Problems

To improve code reusability, you can create a clistbox derived class and implement a "smart" horizontal scroll bar in the derived class. The main issues to be considered include: Tracking the maximum string width (should be able to adapt to font changes in different occasions), calculating the width of the vertical scroll bar when necessary, and automatically displaying and adjusting the size of the horizontal scroll bar.

Select Insert/new class from the menu and set the name of the newly created class to cdjlistbox. The base class is clistbox. The default value is used for other options. Click OK. Visual Studio automatically generates the djlistbox. cpp and djlistbox. H files.

Next, change the list box in the Main Dialog box to the cdjlistbox type, that is, expand the ccustomlistboxdlg class in the classview and double-click the m_llisttest member. In the editing pane, modify

Clistbox m_llisttest;

Is:

Cdjlistbox m_llisttest;

Then, before the class declaration code, insert

# Include "djlistbox. H"

At this time, if you re-compile and run it, you will not be able to see any substantial changes, because we have not modified cdjlistbox. All calls to cdjlistbox are passed directly to the base class clistbox.

The maximum width of the trace string can be achieved by overwriting clistbox: addstring. Open djlistbox. h and add the following statement to the class destructor:

Int addstring (lpctstr lpszitem );

Add the function framework to the implementation file djlistbox. cpp:

Int cdjlistbox: addstring (lpctstr lpszitem)
{
// Code such as string width tracking and horizontal scroll bar display is added here
}

String width tracking can be implemented using the integer member variable m_nmaxwidth. In the protected declaration area of djlistbox. H, add the following line:

Int m_nmaxwidth;

In the djlistbox. cpp file, find the cdjlistbox constructor and initialize the maximum width:

M_nmaxwidth = 0;

Now you can change the newly added addstring. First, call the base class addstring () and use nret to record the returned value:

Int nret = clistbox: addstring (lpszitem );

Next, call getscrollinfo () to obtain information about the vertical scroll bar. The information is transmitted through a scrollinfo structure. The following code initializes the structure and calls getscrollinfo:

Scrollinfo;
Memset (& scrollinfo, 0, sizeof (scrollinfo ));
Scrollinfo. cbsize = sizeof (scrollinfo );
Scrollinfo. fmask = sif_all;
Getscrollinfo (sb_vert, & scrollinfo, sif_all );

Observe scrollinfo In the debugger and you will find that the list box should contain at least one string to obtain the correct values of Nmax and npage. Npage, a member of scrollinfo, saves the number of items that can be displayed in the "per page" list box. Nmax is the total number of items in the list box. When Nmax is greater than or equal to npage, a vertical scroll bar is displayed. We need to know the width of the vertical scroll bar to correctly calculate the valid display width of the list box. Here, an integer nscrollwidth with an initial value of 0 is used, and it is assigned a value when the vertical scroll bar is displayed:

Int nscrollwidth = 0;
If (getcount ()> 1 & (INT) scrollinfo. Nmax
> = (INT) scrollinfo. npage ))
{
Nscrollwidth = getsystemmetrics (sm_cxvscroll );
}

Next, declare a size variable ssize and instantiate the cclientdc in the dialog box:

Size ssize;
Cclientdc mydc (this );

The font used in the dialog box may be the default font or a purposeful choice. In the dialog box Editor, right-click the dialog box and select Properties to view the current value. Although mydc is obtained from the list box, the font information of the list box is not included in mydc. That is to say, the font used when the dialog box is created is not "selected" cclientdc. To obtain the true string size from gettextextentpoint32 (), call getfont () to obtain the font information of the list box, and then select the font to mydc. The code is:

Cfont * plistboxfont = getfont ();
If (plistboxfont! = NULL)
{
Cfont * poldfont =
Mydc. SelectObject (plistboxfont );

Now you can call the gettextextendpoint32 () function to obtain the string width. The string width is returned by the Cx Member of the ssize structure. Compare this value with the existing maximum width:

Gettextextentpoint32 (mydc. m_hdc,
Lpszitem, strlen (lpszitem), & ssize );
M_nmaxwidth = max (m_nmaxwidth, (INT) ssize. CX );

One of the other important tasks is to set the size of the horizontal scroll bar. This can be done by calling sethorizontalextent. If the integer parameter passed to it is smaller than the width of the list box, the horizontal scroll bar is hidden.

Here is a place that is easy to ignore. If you carefully observe the clistbox, you can find a small blank column on the left of the text, and its size is 3. This part of width should be added to the text width. If you want to leave a blank column on the right side of the text, you can add 3 to the text width.

Sethorizontalextent (m_nmaxwidth + 3 );

Before the end, we need to select the original font for mydc. The original font is stored in poldfont:

Mydc. SelectObject (poldfont );}

Return nret;

Compile and execute the new code. You can see that the horizontal scroll bar is automatically displayed.

Iii. Other problems

In practical applications, all functions that change the content of the list box may affect the display requirements of the horizontal scroll bar, and therefore must be customized. But its basic process-calculating the text width and displaying the scroll bar according to the specified size is similar to the above discussion process.

The clistbox class can change the content of the list in addition to addstring (), as well as deletestring (), insertstring (), resetcontent (). Insertstring () is used to insert a string at a specified position. It is the same as addstring () in the topic discussed in this article.

Deletestring () deletes a string. The reference code in the derived class is as follows:

Int cdjlistbox: deletestring (uint nindex)
{
Rect lrect;
Getwindowrect (& lrect );

Int nret = clistbox: deletestring (nindex );

Int nboxwidth = lrect. Right-lrect. Left;
M_nmaxwidth = nboxwidth;

Size ssize;
Cclientdc mydc (this );

Int I;
Char szentry [257];

For (I = 0; I nboxwidth) // display the horizontal scroll bar
{
Showscrollbar (sb_horz, true );
Sethorizontalextent (m_nmaxwidth );
}
Else
{
Showscrollbar (sb_horz, false );
}
Return nret;
}

Resetcontent () is used to clear all contents in the list box. The reference code in the derived class is as follows:

Void cdjlistbox: resetcontent ()
{
Clistbox: resetcontent ();

M_nmaxwidth = 0;
Sethorizontalextent (0 );
}

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.