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