Click here to Skip to main content
15,885,757 members
Articles / Desktop Programming / MFC
Article

Multistring List Control

Rate me:
Please Sign up or sign in to vote.
3.86/5 (6 votes)
23 Oct 20023 min read 134.4K   1.4K   33   11
A list control, that supports multistring text items, drag & drop and item's editing

Sample Image - lpage.jpg

Actuality

The standard CListCtrl is very good instrument for creating lists. It can be present as icon's set, simple list or report, can have many columns. But it can't have text items with many strings per one, i.e. items with different heights; the maximum lenghth of CListCtrl's items is 512 characters (I haven't intend virtual lists). So I decide to create a class, that have over-passed this problem - the CLPPageCtrl. In first, I planed to inherit it from CListCtrl, but it has one unpleasant characteristic: monoheights of items, at that there is no way to set this height as you want (the height depends on selected font of the control). At any case I didn't find it. In addition I wanted to reserve possibility to add non only-text items. Pictures, tables and so on. And I wanted to realize Drag & Drop and editing for items. Of course, the CHTMLView is good decision for it. In this case there is need to write on DHTML, to write scripts and may be to generate HTML pages dynamically. Finally I have wrote CLPageCtrl as child of CWnd.

Properties of control

CLPPageCtrl has these properies:

  • Multistring text items
  • One views - list (not report, icon view)
  • All items of one type have one style
  • Text(CLPPara) items can have mark on the left - radios, one for all (to select)
  • Drag&drop for items
  • Editing for text items with saving user's new lines ('\v' instead of '\n')
  • Text items have aligning: left-, right-, center- and wide-justify
  • Items have const width - screen width
  • The control can be scrolled

Inner struct

CLPPageCtrl is a child of CWnd and CLPPage. CLPPage carry out most work (it suppose possibility to create CLPPageView). As long as items can be various, CLPPage doesn't know many about items. It just know, that they have a placement rectangle and may have mark. Besides CLPPage is a manager, that store statically parameters for items - text color, offset from border, distance between items, font. And items have rectangle, there they do everything, that they want, and state field to store own conditions. They know about CLPPage well. CLPPage communicates with CLPFields using LPFMSG. This is analogue of MSG struct of Microsoft Platform SDK. I tried to make items like as child window of main - CLPPage. In the end, most functions in CLPPage call CLPPage::OnWmMessage(), that call CLPField::WmMessage() for one's part.

Futures of using

Using of CLPPageCtrl is very simple. You can define a variable of CLPPageCtrl type or inherit new class from it. Then setup styles by function SetStyles and structure LPFSTLE with various flags that are described in lpage.h. After creation of window (standard CWnd::Create(...)), add one ore more items as initializing by AddItem with pointer to CLPField. You need not be afraid of memory leak - AddItem() will copy item and destroy at end correctly. After this you will have a list with items, that can be drag & dropped and edited. One AddItem method has a point on input. It's suit to add an item by mouse's click. This way it allow you to insert an item between other items. To get text from a text item, call GetItem(), the text will be placed in CLPField::text. Don't forget about '\v'. This char appears when user press <Enter> key in edit. Selected ("marked") item is determined by GetMarkedItem(), edited by GetFocusedItem(). All of them returns CLPField pointer. You can translate it to index using GetItemIndex(). Also you can change text's font and color and background color by calling SetFont()(this method is absent in CLPPage interface, because I intercept WM_SETFONT window message), SetTextColor() and SetBkColor().

Sample code

To present my work I created an SDI project with MFC-exe wizard. Here I don't use document/view paradigm. The CChildView class is inherited from CLPPageCtrl. The ChildView.cpp is to be of interest of analysis. Here I cite its fragment:

int CChildView::OnCreate(LPCREATESTRUCT lpCreateStruct) 
{
    if (CLPPageCtrl::OnCreate(lpCreateStruct) == -1) return -1;

    // List's initialization
    CString str;
    for (int i=0; i<15; i++){
        str.Format("Multistring\vitem\v%i", i+1); // item with many strings
        CLPPara para(this, str); 
        AddItem(-1, ¶, 0); // add to end
    }
    return 0;
}

// change color of text
void CChildView::OnViewColors()
{
    CColorDialog dlg(text_color, CC_ANYCOLOR | 
                                 CC_FULLOPEN |
                                 CC_PREVENTFULLOPEN |
                                 CC_ENABLEHOOK, this);
    if (dlg.DoModal()==IDOK){
        SetTextColor(dlg.m_cc.rgbResult);
        InvalidateRect(NULL, 0);
    }
}

// change text's font
void CChildView::OnSetfont() 
{
    CFontDialog dlg(NULL, CF_EFFECTS | CF_SCREENFONTS |
                         CF_FORCEFONTEXIST | CF_INITTOLOGFONTSTRUCT |
                         CF_NOOEMFONTS, NULL, this);    
    GetFont()->GetLogFont(&dlg.m_lf);
    if (dlg.DoModal()==IDOK){
        CFont fnt; fnt.CreateFontIndirect(&dlg.m_lf);
        SetFont(&fnt);
    }
}


// display context menu with insert,(delete) items
void CChildView::OnContextMenu(CWnd* pWnd, CPoint ptScreen) 
{
    CPoint ptClient = ptScreen; ScreenToClient(&ptClient);
    CMenu *pmnu = m_mnuContext.GetSubMenu(0); ASSERT(pmnu); 

    if (GetItem(ptClient)) // if on item
      pmnu->EnableMenuItem(ID_CONTEXTMENU_DELETE, MF_ENABLED|MF_BYCOMMAND);
    else 
      pmnu->EnableMenuItem(ID_CONTEXTMENU_DELETE, MF_GRAYED|MF_BYCOMMAND);
    pmnu->TrackPopupMenu(TPM_RIGHTBUTTON, ptScreen.x, ptScreen.y, this);
}

// delete item
void CChildView::OnContextmenuDelete() 
{
        // GetHotItem() returns an item under mouse cursor
    DeleteItem(GetItemIndex(GetHotItem()));
}

// add item
void CChildView::OnContextmenuAdd() 
{
        // don't forget translate point from screen coordinates
    CPoint pt; GetCursorPos(&pt), ScreenToClient(&pt);
        CLPPara para(this, "");
        // place edit on new item
    SetFocusedItem(AddItem(pt, ¶)); 
}

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here


Written By
Software Developer
Russian Federation Russian Federation
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
GeneralMy vote of 1 Pin
AlexeeFF24-Apr-12 1:50
AlexeeFF24-Apr-12 1:50 
GeneralRe: Error Pin
Ken Keray17-Jun-05 9:49
Ken Keray17-Jun-05 9:49 
GeneralQuicky Update text Programatically Pin
bob carleone28-Oct-03 10:29
bob carleone28-Oct-03 10:29 
GeneralRe: Quicky Update text Programatically Pin
Ken Keray29-Oct-03 6:41
Ken Keray29-Oct-03 6:41 
QuestionHow to (Radio button -> Check Box)? Pin
opcon22-Jun-03 20:39
opcon22-Jun-03 20:39 
AnswerRe: How to (Radio button -&gt; Check Box)? Pin
Ken Keray23-Jun-03 6:27
Ken Keray23-Jun-03 6:27 
General??error Pin
arthur_general17-Mar-03 4:01
arthur_general17-Mar-03 4:01 
GeneralRe: ??error Pin
Ken Keray17-Mar-03 16:32
Ken Keray17-Mar-03 16:32 
GeneralRe: ??error Pin
arthur_general23-Mar-03 3:13
arthur_general23-Mar-03 3:13 
GeneralSuggestions Pin
qmlee12-Feb-03 20:08
qmlee12-Feb-03 20:08 
GeneralRe: Suggestions Pin
Ken Keray13-Feb-03 2:36
Ken Keray13-Feb-03 2:36 

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.