Adding intelligent horizontal scroll bars for Clistbox

xiaoxiao2021-03-06  65

In the MFC, uses a list box (Clistbox) to display multiple strings is a very convenient way. But the default list box level rolling bar is not intelligent - the intelligence here is that when there should be, it should not appear, and it should be automatically adjusted. This article illustrates the problems and solutions for examples.

First, the problem demonstration

First create a project CustomClistbox with the Visual Studio application wizard. This is a dialog-based application, all optional parameters provided by the wizard use their default.

In the resource editor, the main box font is set to the Song body 12, insert a CListBox control, set its ID to IDC_llisttest, size is 125 x 84. Please confirm that the vertical scroll bar of the list box, the horizontal scroll bar is valid, and cancel its sort style.

Start Class Wizard, select the MEMBER VARIABLES tab, add the corresponding member variable M_llistTest to the list box, select Control in Category.

Next, select ClassView in the Workspace pane, extend the CCUSTOMCListBoxDLG class and double-click OnItDialog (), find the comment line "Todo: Add Extra Initialization Here" in the editing pane, add the following below: Add the following:

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 ("Northland scenery, thousands of miles of ice, thousands of miles away."));

m_llisttest.addstring (_t ("eleght"));

m_llisttest.addstring (_t ("nine"));

m_llisttest.addstring (_t ("ten"));

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

If you add a line behind the m_llisttext.addstring (_t "ten"):

m_llisttest.addstring (_t ("eleven"));

Re-compiling and run the project, you can find a vertical scroll bar. The appearance of the vertical scroll makes the list box level valid display width becomes smaller, and the content of the seventh line is cut without complete display. However, at this time, the horizontal scroll bar did not appear automatically, and the seventh line was unable to see by the cutting portion.

If we delete the last joined statement, lengthen the seventh line of Chinese characters to the excess list to display the width, or find that the horizontal scroll bar will not appear automatically. The cut part is still unable to see.

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

Second, solve problems

In order to improve the reusability of the code, you can create a CLISTBOX derived class, and implement the "intelligent" horizontal scroll bar in the derived class. The main problems that need to be considered include tracking the maximum string width (which should adapt to font changes in different situations), if necessary, calculate the vertical scroll width, automatically display and adjust the horizontal scroll bar.

Select menu INSERT / New Class, the name of the newly created class is CDJListBox, the base class is CListbox, and other options use the default. Click OK, Visual Studio automatically generate two files of Djlistbox.cpp and DjlistBox.h. Next, change the list box of the main dialog to the CDJListBox type, that is, in the ClassView extended CCUSTOMLISTBOXDLG class and double-click M_llistTest member, in the edit pane, modify

Clistbox m_llisttest;

for:

Cdjlistbox m_llisttest;

Then, inserted before the class declaration code

#include "djlistbox.h"

At this point, if you recompile and run, you can't see any substantive changes because we didn't modify CDJListBox. All calls to CDJListbox are passed directly to the base class CListbox.

The maximum width of the tracking string can be implemented by overwriting the CListbox :: addString (). Open DJListBox.h, the destructor of the next class is added to the following statement:

Int AddString (LPCTSTR LPSZITEM);

And add this function framework in implementing file DJListBox.cpp:

INT CDJListBox :: AddString (LPCTSTR LPSZITEM)

{

// Add a string width tracking, horizontal scroll bar display, etc.

}

String width tracking can be implemented with a shaped member variable m_nmaxwidth. Add the following lines in DjlistBox.h's Protected Declaration:

INT m_nmaxwidth;

In the DJListBox.cpp file, find the constructive function of CDJListBox, initialize this maximum width:

m_nmaxwidth = 0;

You can now change the newly added addString (). You should call the base class addString (), and record it with NRET:

INT nret = clistbox :: addstring (lpszitem);

Next, getScrollInfo () is called to obtain the relevant information of the vertical scroll bar. This information is passed through a scrollInfo structure, the following is the code initialized and called getScrollInfo ():

ScrollInfo 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, you can find the correct value to get NMAX and NPAGE, the list box should contain at least one string. ScrollInfo members NPAGE saves the list of items that can be displayed, Nmax is the total number of items in the list box. When Nmax is greater than or equal to NPAGE, a vertical scroll bar appears. We need to know the width of the vertical scroll bar to correctly display the valid display width of the list of list boxes. Here, an integer NScrollWidth of an initial value is 0 is represented, and it assigns it when the vertical scroll bar is displayed:

INT nscrollwidth = 0;

IF (getCount ()> 1 && ((int) scrollInfo.nmax

> = (int) scrollInfo.npage))

{

nscrollWidth = GetSystemMetrics (SM_CXVSCROLL);

}

Next, a size variable SSIZE is declared, and the CClientDC: size size size of the dialog;

CclientDC MYDC (this);

The fonts used in the dialog may be the default font, which is also possible to choose from. Right-click on the dialog box in the dialog editor and select Properties to view the current value. Although myDC is obtained from the list box, the list box font information is not included in my MYDC. That is, the font used when the dialog is created does not "select" CclientDC. To get a real string size from getTexTextentPoint32 (), you should call GetFont () to get the font information of the list box, then select this font to the MYDC, the code is:

Cfont * plistboxfont = getFont ();

IF (PListBoxFont! = NULL)

{

CFont * PoldFont =

Mydc.selectObject (PListBoxFont);

You can now call the GetTexTextendPoint32 () function to get the width of the string. The width of the string returns by the CX member of the SSIZE structure, comparing the value and the existing maximum width:

GettextExtentPoint32 (mydc.m_hdc,

LPSZITEM, STRLEN (LPSZITEM), & SSIZE

m_nmaxwidth = max (m_nmaxwidth, (int) ssize.cx);

One of the rest of the important work is to set the size of the horizontal scroll bar. This can be done by calling the sethorizontalExtent (). If the shaded parameters passed to it are smaller than the column form box itself, the horizontal scroll bar is hidden.

There is a place where it is easy to ignore here. If Clistbox is carefully observed, you can find that there is a small blank blank on the left side of the text, and its size is 3. This part of the width should be added to the text width. If you want to empty the column on the right side of the text, you can add 3 on the text width.

SETHORIZONTALEXTENT (m_nmaxwidth 3);

Before the end, we need to select the original font for MyDC. The original font is saved in PoldFont:

Mydc.selectObject (PoldFont);

Return nret;

To compile and execute new code, you can see that the horizontal scroll bar is finally available automatically.

Third, other issues

In practical applications, all functions that change the contents of the list box may affect the display requirements of the horizontal scroll bar, so they must also be customized. However, its basic process - calculates the text width and displays the scroll bar according to the specified size, and the above discussion process is similar.

The CListbox class can change the list of lists in addition to addString (), and deleteString (), insertstring (), resetContent (). Where INSERTSTRING () is used to insert a string in the specified location, which is the same in the subject matter discussed in this article.

DeleteString () Deletes a string, in the derived class, its reference code is as follows:

INT CDJListBox :: deleteString (uint nindex)

{

RECT LRECT;

GetWindowRect (& LRECT);

INT nret = clistbox :: deleteString (nindex);

Int nboxwidth = limited ..right - limited.Lect.Left;

m_nmaxwidth = nboxwidth;

Size SSIZE;

CclientDC MYDC (this);

INT I;

Char szentry [257];

For (i = 0; i nboxwidth) // Displays horizontal scroll bar {

Showscrollbar (SB_HORZ, TRUE);

SthorizontalExtent (m_nmaxwidth);

}

Else

{

Showscrollbar (SB_HORZ, FALSE);

}

Return nret;

}

RESETCONTENT () is used to clear all the contents of the list box. In the derived class, its reference code is as follows:

Void cdjlistbox :: resetcontent ()

{

Clistbox :: resetContent ();

m_nmaxwidth = 0;

SthorizontalExtent (0);

}

转载请注明原文地址:https://www.9cbs.com/read-87115.html

New Post(0)