精品理论电影在线_日韩视频一区二区_一本色道精品久久一区二区三区_香蕉综合视频

C語言輔導(dǎo):可編輯子項(xiàng)的CListCtrl類

發(fā)布時(shí)間:2011-08-29 共1頁

  一、說明
  家都知道在MFC中通過給CListCtrl設(shè)置LVS_EDITLABELS屬性,并且在程序中響應(yīng)控件的LVN_ENDLABELEDIT消息可以修改列表控件每一行的第一項(xiàng),也就是主項(xiàng)(Item)。代碼如下:
  void CEditListCtrlSampleDlg::OnEndlabeleditList1(NMHDR* pNMHDR, LRESULT* pResult)
  {
  LV_DISPINFO* pDispInfo = (LV_DISPINFO*)pNMHDR;
  // TODO: Add your control notification handler code here
  *pResult = TRUE;  //TRUE值表示可以修改主項(xiàng),F(xiàn)ALSE值表示不修改主項(xiàng)
  }但是讓人郁悶的是,微軟留了一手,CListCtrl不支持直接修改子項(xiàng)(SubItem)。無奈之下只好自力更生,對CListCtrl進(jìn)行擴(kuò)展。>_<!!!!
  二、原理
  通過在浩如煙海的互聯(lián)網(wǎng)上查找資料(當(dāng)然包括了名鼎鼎的VCKBASE),發(fā)現(xiàn)現(xiàn)有的實(shí)現(xiàn)都是對子項(xiàng)鼠標(biāo)單擊一次就可以編輯。但本人對CListCtrl的單擊一次高亮文本,再單擊一次才開始編輯的操作模式感覺比較喜歡,所以就有了這篇文章的誕生。
  要想實(shí)現(xiàn)高亮文本也就是對文本進(jìn)行著色處理,這可以通過對NM_CUSTOMDRAW消息進(jìn)行處理實(shí)現(xiàn),提示類向?qū)е袥]有這個(gè)消息映射只能進(jìn)行手工添加。
  要想編輯文本則可以通過EditLabel(int nItem)成員函數(shù)以及對LVN_BEGINLABELEDIT和LVN_ENDLABELEDIT的消息處理實(shí)現(xiàn)。
  三、實(shí)現(xiàn)
  本文最終實(shí)現(xiàn)的CEditListCtrl擴(kuò)展類在盡量符合CListCtrl操作步驟的情況下實(shí)現(xiàn)對主項(xiàng)及子項(xiàng)的可編輯。
  成員變量說明:
  int m_iItem; //主項(xiàng)標(biāo)識符
  int m_iSubItem; //子項(xiàng)標(biāo)識符
  BOOL m_bFocus; //是否繪制項(xiàng)文本焦點(diǎn)框
  BOOL m_bHighLight; //是否高亮項(xiàng)文本
  CItemEdit m_edtItemEdit; //用于子類化EditLabel函數(shù)返回的CEdit*指針
  列表控件中所有項(xiàng)文本的繪制以及特效(焦點(diǎn)框、高亮)都在NM_CUSTOMDRAW消息處理中實(shí)現(xiàn):
  void CEditListCtrl::OnCustomDraw(NMHDR* pNMHDR, LRESULT* pResult)
  {
  NMLVCUSTOMDRAW* pNMLVCustomDraw = (NMLVCUSTOMDRAW*)pNMHDR;
  // Take the default processing unless we set this to something else below.
  *pResult = CDRF_DODEFAULT;
  // First thing - check the draw stage. If it's the control's prepaint
  // stage, then tell Windows we want messages for every item.
  if (pNMLVCustomDraw->nmcd.dwDrawStage == CDDS_PREPAINT)
  {
  *pResult = CDRF_NOTIFYITEMDRAW;
  }
  else if (pNMLVCustomDraw->nmcd.dwDrawStage == CDDS_ITEMPREPAINT)
  {
  // This is the notification message for an item. We'll request
  // notifications before each subitem's prepaint stage.
  *pResult = CDRF_NOTIFYSUBITEMDRAW;
  }
  else if (pNMLVCustomDraw->nmcd.dwDrawStage == (CDDS_ITEMPREPAINT | CDDS_SUBITEM))
  {
  //當(dāng)前要繪制的主項(xiàng)標(biāo)識符和子項(xiàng)標(biāo)識符
  int iItem = (int)pNMLVCustomDraw->nmcd.dwItemSpec;
  int iSubItem = pNMLVCustomDraw->iSubItem;
  CDC* pDC = CDC::FromHandle(pNMLVCustomDraw->nmcd.hdc);
  CString strItemText = GetItemText(iItem, iSubItem);
  CRect rcItem, rcText;
  GetSubItemRect(iItem, iSubItem, LVIR_LABEL, rcItem);
  rcText = rcItem;
  CSize size = pDC->GetTextExtent(strItemText);
  if(strItemText == _T(""))
  {
  size.cx = 41;
  }
  //設(shè)置文本高亮矩形
  rcText.left += 4;
  rcText.right = rcText.left + size.cx + 6;
  if(rcText.right > rcItem.right)
  {
  rcText.right = rcItem.right;
  }
  COLORREF crOldTextColor = pDC->GetTextColor();
  //繪制項(xiàng)焦點(diǎn)/高亮效果
  if(m_bFocus)
  {
  if((m_iItem == iItem) && (m_iSubItem == iSubItem))
  {if(m_bHighLight)
  {pDC->SetTextColor(::GetSysColor(COLOR_HIGHLIGHTTEXT));
  pDC->FillSolidRect(&rcText, ::GetSysColor(COLOR_HIGHLIGHT));
  }
  pDC->DrawFocusRect(&rcText);
  }}
  //繪制項(xiàng)文本
  rcItem.left += 6;
  pDC->DrawText(strItemText, &rcItem, DT_LEFT | DT_VCENTER | DT_SINGLELINE | DT_END_ELLIPSIS | DT_NOCLIP);
  pDC->SetTextColor(crOldTextColor);
  *pResult = CDRF_SKIPDEFAULT;// We've painted everything.
  }}單擊一次文本高亮,再單擊一次文本開始編輯在WM_LBUTTONDOWN消息處理中實(shí)現(xiàn):void CEditListCtrl::OnLButtonDown(UINT nFlags, CPoint point)
  {
  m_bFocus = TRUE;
  LVHITTESTINFO lvhit;
  lvhit.pt = point;
  int item = SubItemHitTest(&lvhit);
  //if (over a item/subitem)
  if (item != -1 && (lvhit.flags & LVHT_ONITEM))
  {
  CListCtrl::OnLButtonDown(nFlags, point);
  if(m_bHighLight && m_iItem == lvhit.iItem && m_iSubItem == lvhit.iSubItem)
  {
  //第二次單擊
  EditLabel(m_iItem);
  return;
  }
  else
  {
  //第一次單擊
  m_iItem = lvhit.iItem;
  m_iSubItem = lvhit.iSubItem;
  m_bHighLight = TRUE;
  }
  }
  else
  {
  if(m_edtItemEdit.m_hWnd == NULL)
  {
  //未出現(xiàn)文本編輯框時(shí)
  m_bHighLight = FALSE;
  }
  CListCtrl::OnLButtonDown(nFlags, point);
  }
  Invalidate(); //強(qiáng)制重繪控件
  }關(guān)鍵的一步,對項(xiàng)文本進(jìn)行編輯。在以上代碼中當(dāng)執(zhí)行到EditLabel時(shí)將會(huì)產(chǎn)生一個(gè)編輯框,這時(shí)需要將它進(jìn)行子類化處理,以控制它出現(xiàn)的位置。void CEditListCtrl::OnBeginlabeledit(NMHDR* pNMHDR, LRESULT* pResult)
  {
  LV_DISPINFO* pDispInfo = (LV_DISPINFO*)pNMHDR;
  if (m_iSubItem >= 0)
  {
  ASSERT(m_iItem == pDispInfo->item.iItem);
  CRect rcSubItem;
  GetSubItemRect( pDispInfo->item.iItem, m_iSubItem, LVIR_BOUNDS, rcSubItem);
  //get edit control and subclass
  HWND hWnd= (HWND)SendMessage(LVM_GETEDITCONTROL);
  ASSERT(hWnd != NULL);
  VERIFY(m_edtItemEdit.SubclassWindow(hWnd));
  //move edit control text 4 pixel to the right of org label,
  //as Windows does it...編輯框定位
  m_edtItemEdit.m_iXPos = rcSubItem.left + 4;
  m_edtItemEdit.SetWindowText(GetItemText(pDispInfo->item.iItem, m_iSubItem));
  }
  *pResult = 0;
  }
  void CEditListCtrl::OnEndlabeledit(NMHDR* pNMHDR, LRESULT* pResult)
  {
  LV_DISPINFO* pDispInfo = (LV_DISPINFO*)pNMHDR;
  LV_ITEM*plvItem = &pDispInfo->item;
  if (m_iSubItem >= 0)
  {
  if (plvItem->pszText != NULL )
  {
  SetItemText(plvItem->iItem,m_iSubItem, plvItem->pszText);
  }
  VERIFY(m_edtItemEdit.UnsubclassWindow()!=NULL);*pResult = 0;
  }
  //編輯文本時(shí)對控件父窗口操作(如單擊其它控件)引發(fā)"OnEndlabeledit"時(shí)刷新控件
  CRect rect;
  GetWindowRect(&rect);
  CPoint point;
  ::GetCursorPos(&point);
  if(!rect.PtInRect(point))
  {
  m_iItem = -1;
  m_iSubItem = -1;
  m_bFocus = FALSE;
  m_bHighLight = FALSE;
  }
  }通過以上三個(gè)步驟體實(shí)現(xiàn)了本文要達(dá)到的目的,但是還不能放松。接下來還要進(jìn)行一些顯示細(xì)節(jié)方面的處理。這包括對WM_PAINT、WM_SETFOCUS和WM_KILLFOCUS消息的處理,限于篇幅,就不進(jìn)行細(xì)講了,有興趣的朋友可以查看本文提供的源代碼。

百分百考試網(wǎng) 考試寶典

立即免費(fèi)試用