现在的位置: 首页 > 自动控制 > 工业·编程 > 正文

如何重绘CListCtrl的表头

2012-09-09 22:00 工业·编程 ⁄ 共 4692字 ⁄ 字号 评论 1 条

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();
}

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

目前有 1 条留言    访客:1 条, 博主:0 条

  1. elite_jwp 2014年03月21日 5:57 下午  @回复  Δ1楼 回复

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

    ListCtrl默认插入列时,使用的HDM_ITEMINSERTW消息,而你程序可能使用HDM_INSERTITEM做的消息映射,如果以非UNICODE方式编译,则只会捕捉到HDM_INSERTITEMA消息,不会捕捉HDM_INSERTITEMW消息。
    所以要2个消息均做映射。
    ON_MESSAGE(HDM_INSERTITEMA,OnInsertItem)
    ON_MESSAGE(HDM_INSERTITEMW,OnInsertItem)

给我留言

留言无头像?