专心研究dotnet技术

.net啊.net什么叫.net呢?

  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理
要实现定制按钮的功能,可以从MFC的CButton派生出你自己的一个子类,比如CIndicatorButton,其定义如下:

class CIndicatorButton : public CButton
{
// Construction
public:
    CIndicatorButton();

// Attributes
public:

// Operations
public:
    void SetBkColor(COLORREF crBk); // 设置背景颜色
    COLORREF GetBkColor() { return m_crBk; } // 得到背景色(用CBrush画时的颜色)
    void SetForeColor(COLORREF crFore); // 设置前景颜色(用CPen画时的颜色)
    COLORREF GetForeColor() { return m_crFore; } // 得到前景色
    // 设置超级连接标志
    void SetHypertextFlag(BOOL bIsHypertext = TRUE) { m_bIsHypertext = bIsHypertext; }

// Overrides
    // ClassWizard generated virtual function overrides
    //{{AFX_VIRTUAL(CIndicatorButton)
    public:
    virtual void DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct); // 在这个函数中按你的意愿去画按钮
    protected:
    virtual void PreSubclassWindow(); // 在这个函数中给按钮加入自画风格
    //}}AFX_VIRTUAL

// Implementation
public:
    virtual ~CIndicatorButton();

    // Generated message map functions
protected:
    //{{AFX_MSG(CIndicatorButton)
        // NOTE - the ClassWizard will add and remove member functions here.
    afx_msg void OnMouseMove(UINT nFlags, CPoint point);
    //}}AFX_MSG

    DECLARE_MESSAGE_MAP()

private:
    COLORREF m_crBk;
    COLORREF m_crFore;
    HCURSOR m_hCursor; // 超级连接时的光标
    HCURSOR m_hOldCursor;// 正常时的光标
    BOOL m_bIsHypertext; // 如果是超级连接文本
};


代码如下:

// 构造函数,用来初始化变量
CIndicatorButton::CIndicatorButton()    
{
    m_crBk = RGB(0, 0, 255); // 初始化背景色为蓝色
    m_crFore = RGB(255, 255, 0);// 初始化前景色为黄色
}

// 按钮子类化之前调用的虚拟函数,在这个函数中修改按钮风格
void CIndicatorButton::PreSubclassWindow()
{
    // TODO: Add your specialized code here and/or call the base class
    UINT uStyle = GetButtonStyle(); // 得到按钮的愿风格
    SetButtonStyle(uStyle | BS_OWNERDRAW);// 加入自画风格
    CButton::PreSubclassWindow();
}

// 设置背景色
void CIndicatorButton::SetBkColor(COLORREF crBk)
{
    m_crBk = crBk;
    Invalidate(); // 通知按钮重绘自己
}

// 设置前景色
void CIndicatorButton::SetForeColor(COLORREF crFore)
{
    m_crFore = crFore;
    Invalidate();
}

// 根据鼠标的移动来改变按钮的外观
void CIndicatorButton::OnMouseMove(UINT nFlags, CPoint point)
{
    // TODO: Add your message handler code here and/or call default
    CRect rcItem;
    GetClientRect(rcItem);
    if (rcItem.PtInRect(point))
    {
        // 只在第一次重绘,否则会闪烁
        if (this != GetCapture())
        {
            SetCapture();
            m_crBk = RGB(0, 0, 0);
            Invalidate();
        }

        if (m_bIsHypertext)
        {        
            if (NULL == m_hCursor)        
                m_hCursor = AfxGetApp()->LoadCursor(IDC_CURSOR);
            
            m_hOldCursor = ::SetCursor(m_hCursor);        
        }
    }
    else
    {
        ReleaseCapture();
        m_crBk = RGB(0, 0, 255);

        if (m_bIsHypertext)
        {
            if (NULL != m_hOldCursor)
                ::SetCursor(m_hOldCursor);
        }
        Invalidate();
    }

    CButton::OnMouseMove(nFlags, point);
}

// 这个函数是关键函数,在这里你几乎可以实现你想要的任何按钮
// DRAWITEMSTRUCT 结构请参看MSDN文档
void CIndicatorButton::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct)
{
    // TODO: Add your code to draw the specified item
    // 如果不是按钮不则不进行任何操作
    if (lpDrawItemStruct->CtlType != ODT_BUTTON)
        return ;
        
    CDC *pDC = CDC::FromHandle(lpDrawItemStruct->hDC); //     将句柄的DC转化为MFC类,以方便后续操作
    CString strCaption; // 按钮标题
    GetWindowText(strCaption);// 得到按钮标题,以备后续操作可以在DC上重画按钮标题
    
    // 设置背景模式为透明,否则在画按钮标题时,标题的背景会部分地覆盖掉按钮的背景
    pDC->SetBkMode(TRANSPARENT);
    // 在这里更改按钮的背景色,当然还有其它的办法,反正只要在这个DC上涂上你所要的背景色即可
    pDC->FillRect(&lpDrawItemStruct->rcItem, &CBrush(RGB(0, 0, 255)));
    
    pDC->SetTextColor(m_crFore); // 设置前景色
    // 画按钮标题,水平和垂直都居中。当然你也可以用 TextOut等函数来实现,反正你把DC当作一个画布就是了,你想怎么画就怎么画
    // 如果要使DT_VCENTER(垂直居中)有效,必须同时设置DT_SINGLELINE(单行)风格
    pDC->DrawText(strCaption, lpDrawItemStruct->rcItem, DT_SINGLELINE | DT_CENTER | DT_VCENTER);
    
    // 按钮具有焦点时,画聚焦矩形
    if (ODS_FOCUS == itemState || ODA_FOCUS == itemAction)
    {    
        CRect rcFocus(rcItem);// 聚焦矩形
        rcFocus.DeflateRect(2, 2); // 聚焦矩形要小些
        pDC->DrawFocusRect(&rcFocus);
    }
    
    // 余下的自己去完成吧,比如你可以根据鼠标的移动来改变颜色字体等,但要注意不要随意地重绘,
    // 因为如果随意地重绘会产生严重的闪烁,所以只有在必要的时候进行重绘,比如在鼠标在进入时重绘次,在没有
    // 出来重入之前就不重绘等等
}
posted on 2006-06-30 22:15  xxsdfsdf  阅读(2990)  评论(0编辑  收藏  举报