旌旗博客

2007-01-26

OwnerDraw HeaderCtrl

Filed under: I.T. — 标签: — rocky @ 12:32

code.screen, div.codescreen{
font-family: monospace;
font-size: 1em;
display: block;
padding: 10px;
border: 1px solid #bbb;
background-color: #eee;
color: #000;
overflow: auto;
border-radius: 2.5px;
-moz-border-radius: 2.5px;
margin: 0.5em 2em;
}

Although many people don’t like MFC, sometimes we have to use it. This article presents a sample to describe how to implement height adjustment and owner drawing for HeaderControl of ListControl. 

 

 

 

  Header file:

 

class CSkinManager;
class COwnerDrawHeaderCtrl : public CHeaderCtrl
{
public:
    COwnerDrawHeaderCtrl();

protected:
    virtual void DrawItem(LPDRAWITEMSTRUCT);

protected:
    //{{AFX_MSG(COwnerDrawHeaderCtrl)
    afx_msg LRESULT OnLayout(WPARAM wParam, LPARAM lParam);
    afx_msg void OnPaint();
    afx_msg BOOL OnEraseBkgnd(CDC* pDC);
    //}}AFX_MSG
    DECLARE_MESSAGE_MAP()

private:
    CSkinManager &m_skinManager;
};
 
Source file:
COwnerDrawHeaderCtrl::COwnerDrawHeaderCtrl()
    :m_skinManager(CPootaoClientService::Instance().GetSkinManager())
{
};

BEGIN_MESSAGE_MAP(COwnerDrawHeaderCtrl, CHeaderCtrl)
    //{{AFX_MSG_MAP(COwnerDrawHeaderCtrl)
    ON_MESSAGE(HDM_LAYOUT, OnLayout)
    ON_WM_PAINT()
    ON_WM_ERASEBKGND()
    //}}AFX_MSG_MAP
END_MESSAGE_MAP()

LRESULT COwnerDrawHeaderCtrl::OnLayout( WPARAM wParam, LPARAM lParam )
{
    HDLAYOUT* pLayout = ( HDLAYOUT* ) lParam; // cast the lParam

    pLayout->pwpos->hwnd = GetSafeHwnd (); // populate WINDOWPOS struct
    pLayout->pwpos->hwndInsertAfter = HWND_TOP;
    pLayout->pwpos->flags = SWP_NOACTIVATE | SWP_NOZORDER | SWP_FRAMECHANGED;

    int nHdrBottom = m_skinManager.m_sizeHeaderBackground.cy;

    pLayout->pwpos->x = pLayout->prc->left;
    pLayout->pwpos->y = 0;
    pLayout->pwpos->cx = pLayout->prc->right - pLayout->prc->left;
    pLayout->pwpos->cy = nHdrBottom;

    pLayout->prc->top = nHdrBottom;

    return TRUE;
}

void COwnerDrawHeaderCtrl::DrawItem(LPDRAWITEMSTRUCT)
{
}

BOOL COwnerDrawHeaderCtrl::OnEraseBkgnd(CDC* pDC)
{

    return FALSE;
}

void COwnerDrawHeaderCtrl::OnPaint()
{
    CPaintDC dc(this);

    HDC dcMem = dc.m_hDC;

    CRect rectWindow;
    GetClientRect(&rectWindow);

    HFONT hOldFont = (HFONT)SelectObject(dcMem, GetStockObject(DEFAULT_GUI_FONT));

    ::SetBkColor(dcMem, GetSysColor(COLOR_WINDOW));
    SetBkMode(dcMem, TRANSPARENT);

    //draw the contents to a memory device context
    HDC dcMemBk = ::CreateCompatibleDC(dc.m_hDC);
    HBITMAP hOldBitmapBk = (HBITMAP)SelectObject(dcMemBk, m_skinManager.m_hBmpHeaderBackground);

    int rightMost = 0;
    for (int i=0; i<GetItemCount(); i++)
    {
        HDITEM hdi;
        TCHAR  lpBuffer[256];

        hdi.mask = HDI_TEXT | HDI_FORMAT | HDI_IMAGE | HDI_ORDER;
        hdi.pszText = lpBuffer;
        hdi.cchTextMax = 256;

        GetItem(i, &hdi);

        CRect rcItem;
        GetItemRect(i, &rcItem);

        SelectObject(dcMemBk, m_skinManager.m_hBmpHeaderSep);
        BitBlt(dcMem
            , rcItem.left, rcItem.top
            , m_skinManager.m_sizeHeaderSep.cx, m_skinManager.m_sizeHeaderSep.cy
            , dcMemBk, 0, 0, SRCCOPY);

        SelectObject(dcMemBk, m_skinManager.m_hBmpHeaderBackground);
        StretchBlt(dcMem
            , rcItem.left + 1, rcItem.top
            , rcItem.Width()-1, rcItem.Height()
            , dcMemBk
            , 0, 0, m_skinManager.m_sizeHeaderBackground.cx, m_skinManager.m_sizeHeaderBackground.cy
            , SRCCOPY);

        SelectObject(dcMemBk, m_skinManager.m_hBmpHeaderSep);
        BitBlt(dcMem
            , rcItem.right, rcItem.top
            , m_skinManager.m_sizeHeaderSep.cx, m_skinManager.m_sizeHeaderSep.cy
            , dcMemBk, 0, 0, SRCCOPY);

        rightMost = max(rightMost, rcItem.right);

        DRAWITEMSTRUCT DrawItemStruct;
        GetItemRect(i, &rcItem);

        DrawItemStruct.CtlType        = 100;
        DrawItemStruct.hDC        = dc.GetSafeHdc();
        DrawItemStruct.itemAction    = ODA_DRAWENTIRE;
        DrawItemStruct.hwndItem     = GetSafeHwnd();
        DrawItemStruct.rcItem    = rcItem;
        DrawItemStruct.itemID    = i;
        DrawItem(&DrawItemStruct);

        // Draw the items text using the text color.
        COLORREF crOldColor = ::SetTextColor(dcMem,
            RGB(0x4f,0x4f,0x4f));
        SetBkMode(dcMem, TRANSPARENT);

        UINT uFormat = DT_SINGLELINE|DT_VCENTER|DT_NOPREFIX|DT_END_ELLIPSIS;
        if( hdi.fmt & HDF_CENTER)
            uFormat |= DT_CENTER;
        else if( hdi.fmt & HDF_RIGHT)
            uFormat |= DT_RIGHT;
        else
            uFormat |= DT_LEFT;

        CRect rectText(rcItem);
        CPoint ptImage(0, 0);

        CImageList *imageList = NULL;
        if (hdi.fmt & HDF_IMAGE && (imageList = GetImageList()) != NULL)
        {
            IMAGEINFO imageInfo;
            if (imageList->GetImageInfo(hdi.iImage, &imageInfo))
            {
                if (!(hdi.fmt & HDF_BITMAP_ON_RIGHT))
                {
                    ptImage = rcItem.TopLeft();
                    ptImage.x += 4;
                    ptImage.y = rcItem.top + (rcItem.Height()-(imageInfo.rcImage.bottom-imageInfo.rcImage.top))/2;

                    imageList->Draw(&dc, hdi.iImage, ptImage, ILD_TRANSPARENT);

                    rectText.left += imageInfo.rcImage.right-imageInfo.rcImage.left+4;
                }
                else
                {
                    rectText.right -= imageInfo.rcImage.right-imageInfo.rcImage.left+4;
                }
            }

            ::SetTextColor(dcMem, RGB(0x00,0x00,0x00));
        }

        rectText.DeflateRect(4, 2, 4, 2);
        int nTextSize = ::DrawText(dcMem, lpBuffer, lstrlen(lpBuffer), &rectText, uFormat);
        ::SetTextColor(dcMem, crOldColor);

        if (hdi.fmt & HDF_IMAGE && imageList != NULL)
        {
            IMAGEINFO imageInfo;
            if (hdi.fmt & HDF_BITMAP_ON_RIGHT
                && imageList->GetImageInfo(hdi.iImage, &imageInfo))
            {
                CSize sizeText;
                GetTextExtentPoint(dcMem, lpBuffer, lstrlen(lpBuffer), &sizeText);
                ptImage = CPoint(min(rectText.right + sizeText.cx + 16, rcItem.left + rcItem.Width()-(imageInfo.rcImage.right-imageInfo.rcImage.left)-4)
                    , (rcItem.Height()-(imageInfo.rcImage.bottom-imageInfo.rcImage.top))/2);

                imageList->Draw(&dc, hdi.iImage, ptImage, ILD_TRANSPARENT);
            }
        }
    }

    SelectObject(dcMemBk, m_skinManager.m_hBmpHeaderBackground);
    StretchBlt(dcMem
        , rightMost+1, 0
        , rectWindow.Width()-rightMost-1, rectWindow.Height()
        , dcMemBk
        , 0, 0, m_skinManager.m_sizeHeaderBackground.cx, m_skinManager.m_sizeHeaderBackground.cy
        , SRCCOPY);

    SelectObject(dcMemBk, hOldBitmapBk);
    DeleteDC(dcMemBk);
}

Powered by WordPress