现在的位置: 首页 > 综合 > 正文

如何重绘CListCtrl的表头

2014年01月29日 ⁄ 综合 ⁄ 共 4881字 ⁄ 字号 评论关闭

1。要重绘listctrl表头,则listctrl表现选择为report风格

2。其表头(CHeaderCtrl)可以通过GetHeaderCtrl获取

3。继承CHeaderCtrl类,重绘表头。

     有两种方式重绘:

     a。重载OnPaint方法,事例代码如下:

void CSkinHeaderCtrl::OnPaint()
{
 TRACE("CSkinHeaderCtrl::OnPaint()/n");
 CPaintDC dc(this); // device context for painting
 
 CRect rect, rectItem, clientRect;
 GetClientRect(&rect);
 GetClientRect(&clientRect);
 CMemDC memDC(&dc, rect);
 CDC bitmapDC;
 bitmapDC.CreateCompatibleDC(&dc);
 
 memDC.FillSolidRect(&rect, RGB(76,85,118));

 CBitmap bitmapSpan;
 bitmapSpan.LoadBitmap(IDB_COLUMNHEADER_SPAN);
 CBitmap* pOldBitmapSpan = bitmapDC.SelectObject(&bitmapSpan);

 memDC.StretchBlt(rect.left+2, 0, rect.Width(), 12, &bitmapDC, 0, 0, 1, 12, SRCCOPY);

 bitmapDC.SelectObject(pOldBitmapSpan);
 bitmapSpan.DeleteObject();
 
 int nItems = GetItemCount();

 CBitmap bitmap;
 CBitmap bitmap2;
 CBitmap bitmap3;
 
 bitmap.LoadBitmap(IDB_COLUMNHEADER_START);
 bitmap2.LoadBitmap(IDB_COLUMNHEADER_SPAN);
 bitmap3.LoadBitmap(IDB_COLUMNHEADER_END);

 for(int i = 0; i <nItems; i++)
 {
  
  TCHAR buf1[256];
  HD_ITEM hditem1;
  
  hditem1.mask = HDI_TEXT | HDI_FORMAT | HDI_ORDER;
  hditem1.pszText = buf1;
  hditem1.cchTextMax = 255;
  GetItem( i, &hditem1 );
  
  GetItemRect(i, &rect);
  
  CBitmap* pOldBitmap = NULL;
  
  //make sure we draw the start piece
  //on the first item so it has a left border

  //For the following items we will just use the
  //right border of the previous items as the left
  //border
  if(hditem1.iOrder==0)
  {
   pOldBitmap = bitmapDC.SelectObject(&bitmap);
   memDC.BitBlt(rect.left,rect.top,2,12,&bitmapDC,0,0,SRCCOPY);
  }
  else
  {
   memDC.BitBlt(rect.left-1,rect.top,2,12,&bitmapDC,0,0,SRCCOPY);
   pOldBitmap = bitmapDC.SelectObject(&bitmap2);
   memDC.BitBlt(rect.left+1,rect.top,1,12,&bitmapDC,0,0,SRCCOPY);
  }

  bitmapDC.SelectObject(pOldBitmap);
  
  //span the bitmap for the width of the column header item
  int nWidth = rect.Width() - 4;
  
  CBitmap* pOldBitmap2 = bitmapDC.SelectObject(&bitmap2);
  
  memDC.StretchBlt(rect.left+2, 0, nWidth, 1, &bitmapDC, 0,0, 1, 12, SRCCOPY);

  bitmapDC.SelectObject(pOldBitmap2);
  
  
  //draw the end piece of the column header
  CBitmap* pOldBitmap3 = bitmapDC.SelectObject(&bitmap3);
  memDC.BitBlt((rect.right-2), 0, 2, 12, &bitmapDC,0,0,SRCCOPY);
  bitmapDC.SelectObject(pOldBitmap3);
  
  //Get all the info for the current
  //item so we can draw the text to it
  //in the desired font and style
  DRAWITEMSTRUCT DrawItemStruct;
  GetItemRect(i, &rectItem);
  
  
  DrawItemStruct.CtlType  = 100;
  DrawItemStruct.hDC   = dc.GetSafeHdc();
  DrawItemStruct.itemAction = ODA_DRAWENTIRE;
  DrawItemStruct.hwndItem  = GetSafeHwnd();
  DrawItemStruct.rcItem = rectItem;
  DrawItemStruct.itemID = i;
  DrawItem(&DrawItemStruct);
  
  UINT uFormat = DT_SINGLELINE | DT_NOPREFIX | DT_TOP |DT_CENTER | DT_END_ELLIPSIS ;
  
  
  CFont font;
  LOGFONT lf;
  memset(&lf, 0, sizeof(LOGFONT));
  lf.lfHeight = 8;
  strcpy(lf.lfFaceName, "Sevenet 7");
  font.CreateFontIndirect(&lf);
  CFont* def_font = memDC.SelectObject(&font);
  
  memDC.SetBkMode(TRANSPARENT);
  rectItem.DeflateRect(2,2,2,2);
  
  TCHAR buf[256];
  HD_ITEM hditem;
  
  hditem.mask = HDI_TEXT | HDI_FORMAT | HDI_ORDER;
  hditem.pszText = buf;
  hditem.cchTextMax = 255;
  GetItem( DrawItemStruct.itemID, &hditem );

  memDC.DrawText(buf, &rectItem, uFormat);
  memDC.SelectObject(def_font);
  font.DeleteObject();
 }  
}

 

b。重载DrawItem方法,事例代码如下:

ASSERT(lpDrawItemStruct-> CtlType   ==   ODT_HEADER);      
 HDITEM       hdi;      
 TCHAR       lpBuffer[256];      
 hdi.mask   =   HDI_TEXT;      
 hdi.pszText   =   lpBuffer;      
 hdi.cchTextMax   =   256;  
 GetItem(lpDrawItemStruct-> itemID,&hdi);    
 
 CDC*       pDC;      
 pDC   =   CDC::FromHandle(lpDrawItemStruct-> hDC);          
 pDC-> SetTextColor(RGB(0,0,0));    
 pDC-> SetBkColor(RGB(222,213,242));
 CBrush       brush;      
 brush.CreateSolidBrush(RGB(222,213,242));  
 CRect       rect   =   lpDrawItemStruct-> rcItem;  
 //THIS   FONT   IS   ONLY   FOR   DRAWING   AS   LONG   AS   WE   DON'T   DO   A   SetFont(...)      
 CBrush       *pOldBrush=pDC-> SelectObject(&brush);      
 pDC-> FillRect(&rect,&brush);      
 pDC-> SelectObject(pOldBrush);      
 pDC-> SelectObject(GetStockObject(DEFAULT_GUI_FONT));      
 //DRAW   THE   TEXT
 lpDrawItemStruct-> rcItem.top   +=   6;
 ::DrawText(lpDrawItemStruct->hDC,lpBuffer,strlen(lpBuffer),   &lpDrawItemStruct->rcItem,DT_VCENTER);      
 pDC-> SelectStockObject(SYSTEM_FONT);

 

注:重载DrawItem时,必须要设置CHeaderCtrl为HDF_OWNERDRAW,我设置的方法如下:

调用了InsertColumn之后,用下面的方法设置表头可以自绘。

CHeaderCtrl *pHeader = NULL;
 pHeader = m_SkinList.GetHeaderCtrl();
 if(pHeader)
 {  
  TRACE("header item count:%d/n", pHeader->GetItemCount());
  int iColumn=pHeader->GetItemCount();
  for (int i=0; i<iColumn; i++)
  {
   HDITEM hdItem;
   BOOL bResult = FALSE;
   bResult=pHeader->GetItem(i, &hdItem);
   hdItem.fmt |= HDF_OWNERDRAW;
   bResult=pHeader->SetItem(i, &hdItem);
  }
  
 }

本来我想在CHeaderCtrl的InsertItem上做文章的,但是无法在其被调用时改变其属性,且用SPY++也抓不到HDM_INSERTITEM消息(奇怪),只能作罢。

 

4。继承CListCtrl类,并重载

void CSkinListCtrl::PreSubclassWindow()
{
 //use our custom CHeaderCtrl as long as there
 //is a headerctrl object to subclass
 if(GetHeaderCtrl())
 {  
  m_SkinHeaderCtrl.SubclassWindow(GetHeaderCtrl()->m_hWnd);
 }

 CListCtrl::PreSubclassWindow();
}

 

这样就可以使用自己的表头了

 

抱歉!评论已关闭.