Click here to Skip to main content
12,945,927 members (64,561 online)
Click here to Skip to main content
Add your own
alternative version

Stats

30.7K views
2.5K downloads
25 bookmarked
Posted 22 Jun 2009

Change of Height and Location of CHeaderCrtrl’s and Heights of Lines of CListCtrl’s Descendants with a Help HDM_LAYOUT and WM_MEASUREITEM Messages

, 22 Jun 2009 CPOL
Rate this:
Please Sign up or sign in to vote.
The decision of problem of the header «deformation» and its locality, height of lines of list control and their text formatting.

Formulation of Problem and Methods of its Decision

I do not know if it is possible to explain such a fact that header of CHeaderCtrl / SysHeader32 of standard CListCtrl / SysListView32 list of the Windows appears with some distortion that strikes the eyes at once. It does for the impression from the programs which use these controls. Usually the lines of header fall behind on 1 pixel from the lines of list and header for some reason on 2 pixels shorter, then would follow. To hide this effect, often the lines of list are taken away. It is good evidently in fig. 1-3.

image001.jpg

Fig. 1. Typical CListCtrl’s descendant with data and gridlines.

image003.jpg

Fig. 2. The same CListCtrl’s descendant without the gridlines.

image005.jpg

Fig. 3. Enlarged CListCtrl’s descendant with data and gridlines.

Besides the decision of problem of the header «deformation» it will be interestingly to us arbitrarily to change its height and height of lines of list control, regardless of sizes of current font and image icon present in columns or rows of the list. Thus, we wish to decide these questions in the most elegant method. We also wish to use preset fonts and text formatting in the header and list cells. Except for it, demonstration example, for a typical list, we will fill with data, quite ordinarily via InsertItem / SetItem, and for the modified list will use the virtual mode (LVS_OWNERDATA style), with the help of the SetItemCount function and LVN_GETDISPINFO message.

A job performance is presented in fig. 4. We will notice that although we wished for typical CListCtrl’s descendant to even its first column «Ind. No.» on a right edge, this control ignored our «order» and equalized a column on the left edge (fig. 1-3). And only for the modified control we were able to obtain the necessary alignment (fig. 4). In addition, we showed that it is possible to change data formatting.

image007.jpg

Fig. 4. Modified CHeaderCtrl’s / CListCtrl’s descendants with data and gridlines.

If we change the height of header due to an enlargement font or image icons, indicated «deformation» nevertheless, saved. Obviously, that it is «property» of not MFC’s CListCtrl class but of the SysListView32 Windows’ control.

To liquidate «deformation» of header, it is needed additionally to displace it to the right on a 1 pixel and to increase its height on 2 pixels, desirably without the obvious bringing in of such functions as MoveWindow / SetWindowPos, and also without the necessity to do the own drawing of CHeaderCtrl’s / CListCtrl’s descendants in functions like OnPaint. Except for it, we do not want to use the SetFont function not on purpose (only for an header enlargement, with the subsequent resize of his font). The same touches image icons which we wish to use exceptionally on purpose too, but not for a change only of sizes of header or lines (say, due to the use of thin icons of decision height and not distinctive from a background). There is yet a variant recreate header on a base CHeaderCtrl::Create function, which assumes the obvious pointing of sizes and his location, but this variant also does not arrange as too bulky.

Thus, we have one variant for the change of height and locality of header (with a help HDM_LAYOUT message) and one variant of change of height of lines of list actually (with a help WM_MEASUREITEM message). A method with HDM_LAYOUT is interesting and because very often programmers use it incorrectly, that sometimes results in a surplus code or incorrect work of a program. We will show that it is possible to format a text in the cells of list and his header.

HDM_LAYOUT Message

To get and process the HDM_LAYOUT message of a table header, it is necessary to define the function:

afx_msg LRESULT OnLayout(WPARAM wparam, LPARAM lparam)

in the HeaderCtrlEx.h header file. Then in the proper HeaderCtrlEx.cpp file to specify a macro in the messages map:

ON_MESSAGE(HDM_LAYOUT, OnLayout)

and to define the proper OnLayout function:

/////////////////////////////////////////////////////////
// OnLayout

/////////////////////////////////////////////////////////
LRESULT CHeaderCtrlEx::OnLayout(WPARAM, LPARAM lParam) {
    LPHDLAYOUT pHL = reinterpret_cast<LPHDLAYOUT>(lParam);

    //*** The table list rectangle

    RECT *pRect = pHL->prc;

    //*** The table header rectangle

    WINDOWPOS *pWPos = pHL->pwpos;

    //*** Here's equivalent code for the code which follows after

    /*
    pWPos->hwndInsertAfter = NULL;

    //*** Moves the table header to the right
    pWPos->x = pRect->left + m_nHdrWidthDefect;
    pWPos->y = pRect->top;
    pWPos->cx = pRect->right - pRect->left;

    //*** New table header height
    pWPos->cy = m_nHdrHeight + m_nHdrHeightDefect;

    pWPos->flags = SWP_NOACTIVATE|SWP_NOZORDER;

    //*** Decreases the table list height on the table header height
    pRect->top += m_nHdrHeight;

    return TRUE;
    */
    //*** Sends HDM_LAYOUT message to the base class


    int nRet = CHeaderCtrl::DefWindowProc(HDM_LAYOUT, 0, lParam);

    //*** Moves the table header to the right

    pWPos->x += m_nHdrWidthDefect;

    //*** New table header height

    pWPos->cy = m_nHdrHeight + m_nHdrHeightDefect;

    //*** Decreases the table list height on the table header height

    pRect->top = m_nHdrHeight;

    return nRet;
}  // OnLayout

Actually, here are two variants of change of sizes and locality of header of CHeaderCtrlEx class without evident using functions of kind of SetFont / MoveWindow / SetWindowPos / CHeaderCtrlEx::Create or using pseudo image icons (for achievement of the same aims). Not looking on seeming simplicity of our CHeaderCtrlEx::OnLayout function, many programmers assume errors in processing HDM_LAYOUT message. Possibly, it is caused from not enough clear description of LPHDLAYOUT structure in MSDN.

WM_MEASUREITEM Message

Like the previous one, we determine function:

afx_msg void MeasureItem(LPMEASUREITEMSTRUCT pMIS)

in the ListCtrlEx.h header file. Then in the proper ListCtrlEx.cpp file, we specify a macro in the messages map:

ON_WM_MEASUREITEM_REFLECT()

and determine the proper MeasureItem function:

/////////////////////////////////////////////////////////////////////////////
// MeasureItem

/////////////////////////////////////////////////////////////////////////////
void CListCtrlEx::MeasureItem(LPMEASUREITEMSTRUCT pMIS) {
            //*** The table list height

            pMIS->itemHeight = m_nListHeight;
}  // MeasureItem

Text Formatting

It’s a little more difficult to determine the text formatting at our discretion. Here’s the CHeaderCtrlEx::DrawItem code:

///////////////////////////////////////////////////////////////////////////// 
// DrawItem 

///////////////////////////////////////////////////////////////////////////// 

void CHeaderCtrlEx::DrawItem(LPDRAWITEMSTRUCT pDIS) { 
    HDITEM hDI; 
    TCHAR szBuf[MAXITEMTEXT]; 

    hDI.mask = HDI_TEXT; 
    hDI.pszText = szBuf; 
    hDI.cchTextMax = MAXITEMTEXT; 

    GetItem(pDIS->itemID, &hDI); 

    CDC *pDC; 
    HDC hDC = pDIS->hDC;  // Handle to device context 

    pDC = CDC::FromHandle(hDC); 

    //*** Selects necessary font 

    pDC->SelectObject(m_pFont); 
    //pDC->SelectObject(GetStockObject(DEFAULT_GUI_FONT)); 


    int x = 0;  // x-coordinate of reference point 

    int y = 0;  // y-coordinate of reference point 


    UINT nOptions = 0;  // Text-output options ETO_CLIPPED|ETO_OPAQUE 

    RECT *pIRect = NULL;  // Optional clipping and/or opaquing rectangle 


    pIRect = &pDIS->rcItem; 
    SIZE Size = {0}; 

    //*** Gets the header cell sizes 

    if(!GetTextExtentPoint(hDC, szBuf, wcslen(szBuf), &Size)) { 
        _M("Failed to call GetTextExtentPoint for table header!"); 
        return; 
    } 

    // x-coordinate of reference point 

    x = (pIRect->left + pIRect->right - Size.cx)/2 - 1; 
    x = (x < pIRect->left + 2) ? pIRect->left + 2 : x; 

    // y-coordinate of reference point 

    y = (pIRect->bottom - pIRect->top - Size.cy)/2 - 1; 

    // Specifies that the current background color fills the rectangle pIRect 


    nOptions |= ETO_CLIPPED; 

    //*** Decreases the text border to the right 

    pIRect->right -= 4; 

    //*** Writes the text in the (x, y) - coordinates 

    pDC->ExtTextOut(x, y, nOptions, pIRect, szBuf, wcslen(szBuf), NULL); 

    //*** Restores system font 

    pDC->SelectStockObject(SYSTEM_FONT); 
}  // DrawItem

And here’s the most substantial code for the list text formatting:

///////////////////////////////////////////////////////////////////////////// 
// SetColItemText 

///////////////////////////////////////////////////////////////////////////// 
void CListCtrlEx::SetColItemText(CDC *pDC, CString& stColText,  CRect& TextRect,
    UINT nJustify) 
{
    int x = 0;  // x-coordinate of reference point 

    int y = 0;  // y-coordinate of reference point 

    UINT nOptions = 0;  // Text-output options ETO_CLIPPED|ETO_OPAQUE 


    int nTextLen = stColText.GetLength(); 
    HDC hDC = pDC->m_hDC; 
    SIZE Size = {0}; 

    if(!GetTextExtentPoint(hDC, stColText, nTextLen, &Size)) { 
        _M("Failed to call GetTextExtentPoint for table list!"); 
        return; 
    } 

    // Align the text in the whole table 

    CRect TmpRect(TextRect); 

    // x-coordinate of reference point 

    x = (TextRect.left + TextRect.right - Size.cx)/2 - 1; 
    x = (x < TextRect.left + 2) ? TextRect.left + 2 : x; 

    // y-coordinate of reference point 

    y = (TextRect.bottom - TextRect.top - Size.cy)/2 - 1; 

    //*** Specifies that the current background color fills the rectangle 

    nOptions |= ETO_OPAQUE; 

    //*** Draw the background fast 

    pDC->ExtTextOut(TextRect.left, TextRect.top, nOptions, TextRect, NULL, 0, NULL); 

    TmpRect.left++;  // Cosmetic 

    TmpRect.top += y;      // y-coordinate of reference point 

    TmpRect.InflateRect(-3, 0);   // Text does not touch borders 


    UINT nFormat = 0; 

    switch(nJustify & LVCFMT_JUSTIFYMASK) { 
      case LVCFMT_LEFT: 
        nFormat = DT_LEFT; 
        break; 
      case LVCFMT_RIGHT: 
        nFormat = DT_RIGHT; 
        break; 
      case LVCFMT_CENTER: 
        nFormat = DT_CENTER; 
        break; 
      default: 
        _M("CListCtrlEx: Error of the text formatting!");
        return; 
    } 

    //*** Writes the text in the TmpRect 

    ::DrawText(hDC, stColText, nTextLen, TmpRect, nFormat); 
}  // SetColItemText

The examples of realization of the virtual mode of list are known well, therefore I will not expand on them.

History

  • 22nd June, 2009: Initial post

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

Emery Emerald
Software Developer
Ukraine Ukraine
No Biography provided

You may also be interested in...

Comments and Discussions

 
QuestionThank you. Pin
Member 1094796416-May-16 5:25
memberMember 1094796416-May-16 5:25 
GeneralMy vote of 5 Pin
iibug9-Jan-11 4:28
memberiibug9-Jan-11 4:28 
QuestionPaint Problem for moved header control. Pin
Vaibhav Gade8-Sep-10 19:22
memberVaibhav Gade8-Sep-10 19:22 
AnswerRe: Paint Problem for moved header control. Pin
Emery Emerald9-Sep-10 18:51
memberEmery Emerald9-Sep-10 18:51 
GeneralGood effort... Pin
Grump29-Jun-09 22:19
memberGrump29-Jun-09 22:19 
GeneralRe: Good effort... Pin
Emery Emerald29-Jun-09 23:46
memberEmery Emerald29-Jun-09 23:46 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

Permalink | Advertise | Privacy | Terms of Use | Mobile
Web02 | 2.8.170518.1 | Last Updated 22 Jun 2009
Article Copyright 2009 by Emery Emerald
Everything else Copyright © CodeProject, 1999-2017
Layout: fixed | fluid