CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Results 1 to 4 of 4
  1. #1
    Guest

    ListView's ContextMenu

    Hi,

    I use VC5.0 on NT4.

    I need to know how to detect when a user has right-clicked on an item in a listview, and not just anywhere in the client area. I only want to display the
    context menu when there has been right clicked on an item in the view.
    I think I'll have to handle the OnRButtonClick message, but do not know what
    to do then.

    Any help you can give me will be much appreciated.

    Thanks in advance.


  2. #2
    Join Date
    Apr 1999
    Posts
    383

    Re: ListView's ContextMenu

    If you handle the NM_CLICK notification, you will receive an NMLISTVIEW structure as the lParam argument. This has all the information you need:

    typedef struct tagNMLISTVIEW
    {
    NMHDR hdr;
    int iItem;
    int iSubItem;
    UINT uNewState;
    UINT uOldState;
    UINT uChanged;
    POINT ptAction;
    LPARAM lParam;
    } NMLISTVIEW, FAR *LPNMLISTVIEW;

    Have a look at "List View Control Notification Messages" in the online docs.

    Also check out the List Control area on this site, there are probably suitable examples there.

    Dave


  3. #3
    Join Date
    Feb 2001
    Posts
    4

    Re: ListView's ContextMenu

    1. Map CListView's OnContextMenu
    2. Get the Window Rect of List Control,
    3. Compare it with mouse coordinates to determine whether it is over list control
    4. if not , return, else continue with right click popup menu



  4. #4
    Join Date
    Oct 1999
    Location
    Broomfield, CO
    Posts
    3,382

    Re: ListView's ContextMenu

    Here's some sample code for a right-click handler that does what you want.
    If the user right-clicks over a list control item or subitem, the context menu shows "Add," "Edit" and "Delete." If the user right-clicks off of any row (i.e., on a row of white space), then the context menu contains just "Add."

    Ignore the SetCurrentAdvisor() call, it has nothing to do with your problem.
     

    void CAdvisorsPage::OnRclickListReps(NMHDR* pNMHDR, LRESULT* pResult)
    {
    SetCurrentAdvisor();

    NM_LISTVIEW* pNMListView = (NM_LISTVIEW*)pNMHDR;
    CPoint pt(pNMListView->ptAction);
    CMenu menu;
    menu.LoadMenu(IDM_LISTCTRL); // our context menu
    CMenu* pContextMenu = menu.GetSubMenu(0);

    // Only the Fee Schedules page uses Clone
    menu.RemoveMenu(ID_LISTCTRL_CLONE, MF_BYCOMMAND);

    // Make sure something is there before we show the menu.
    // If nothing is there, shorten the menu to just "Add..."
    int nCol = 0;
    CHeaderCtrl* pHdr = m_listctrlReps.GetHeaderCtrl();
    ASSERT(pHdr);
    int nIndex = m_StdRt.HitTestEx( pt,&nCol, m_listctrlReps, pHdr->GetItemCount());
    if(m_CurrentAdvisor.m_FirmID < 0 || nIndex == -1)
    {
    menu.RemoveMenu(ID_LISTCTRL_EDIT, MF_BYCOMMAND); // remove "Edit..."
    menu.RemoveMenu(ID_LISTCTRL_DELETE, MF_BYCOMMAND); // remove "Delete..."
    }

    POINT p;
    p.x = pt.x;
    p.y = pt.y;
    ::ClientToScreen(pNMHDR->hwndFrom, &p);
    int nID = pContextMenu->TrackPopupMenu( TPM_LEFTALIGN | TPM_LEFTBUTTON | TPM_RETURNCMD,
    p.x, p.y, this);

    // if() used instead of case to avoid overhead of instantiating
    // possibly unused resources outside the switch statement
    if(nID == ID_LISTCTRL_ADD)
    AdvisorInsert();
    else if(nID == ID_LISTCTRL_EDIT)
    AdvisorEdit();
    else if(nID == ID_LISTCTRL_DELETE)
    AdvisorDelete();

    // The menu is a temporary MFC object, no need to delete it.

    *pResult = 0;
    }

    ///////////////////////////////////////
    // HitTestEx() code:
     
    /*
    Name: HitTestEx()
    Description: Determines row and column of a mouse click in the list control
    */

    int CStdRoutines::HitTestEx( CPoint point, int *nCol, CListCtrl& list, int nColumnCount)
    {
    int colnum = 0;
    int row = list.HitTest( point, NULL );

    if( nCol ) *nCol = 0;

    // Make sure that the ListView is in LVS_REPORT mode
    if( (GetWindowLong(list.m_hWnd, GWL_STYLE) & LVS_TYPEMASK) != LVS_REPORT )
    return row;

    // Get the top and bottom row visible
    row = list.GetTopIndex();
    int bottom = row + list.GetCountPerPage();

    if( bottom > list.GetItemCount() )
    bottom = list.GetItemCount();

    // Loop through the visible rows
    for( ;row <= bottom;row++)
    {
    // Get bounding rect of item and check whether point falls in it.
    CRect rect;
    list.GetItemRect( row, &rect, LVIR_BOUNDS );
    if( rect.PtInRect(point) )
    {
    // Now find the column
    for( colnum = 0; colnum < nColumnCount; colnum++ )
    {
    int colwidth = list.GetColumnWidth(colnum);
    if( point.x >= rect.left && point.x <= (rect.left + colwidth ) )
    {
    if( nCol ) *nCol = colnum;
    return row;
    }
    rect.left += colwidth;
    }
    }
    }
    return -1;
    }

    ///////////////////////////////////////
     
    // The resource info for the context menu:
    IDM_LISTCTRL MENU DISCARDABLE
    BEGIN
    POPUP ""
    BEGIN
    MENUITEM "&Add...", ID_LISTCTRL_ADD
    MENUITEM "&Edit...", ID_LISTCTRL_EDIT
    MENUITEM "&Delete...", ID_LISTCTRL_DELETE
    MENUITEM "&Clone...", ID_LISTCTRL_CLONE
    END
    END





Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  





Click Here to Expand Forum to Full Width

Featured