我想让按钮形状随位图的形状改变,按钮风格是自己绘制(BS_OWNERDRAW)
使用的方法是在初始化按钮时,用SetWindowRgn来改变其形状。
但是我无法改变窗口的形状??? BITMAP bminfo;
m_bmpDef.GetObject(sizeof(bminfo), &bminfo); CDC * pDC = this->GetDC();
CDC memDC;
memDC.CreateCompatibleDC(pDC);
memDC.SelectObject(&m_bmpDef);
this->ReleaseDC(pDC); // Create the rgn
CRgn rgnTemp;
COLORREF  color, temp;
color = GetPixel(memDC.GetSafeHdc(), 0, 0);
m_rgnBgd.CreateRectRgn(0, 0, bminfo.bmWidth, bminfo.bmHeight);

int i, j;
for (i = 0; i < bminfo.bmWidth; i ++)
{
for (j = 0; j < bminfo.bmHeight; j ++)
{
temp = memDC.GetPixel(i, j);
if (color == temp)
{
rgnTemp.CreateRectRgn(i, j, i+1, j+1);
m_rgnBgd.CombineRgn(&m_rgnBgd, &rgnTemp, RGN_DIFF);
rgnTemp.DeleteObject();
}
}
}

this->SetWindowRgn(m_rgnBgd, TRUE);
//******************************************************************
以下是完整代码
#if !defined(AFX_HBITBUTTON_H__382B43A8_422E_453F_964E_37F057CF3CFE__INCLUDED_)
#define AFX_HBITBUTTON_H__382B43A8_422E_453F_964E_37F057CF3CFE__INCLUDED_#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
// HBitButton.h : header file
///////////////////////////////////////////////////////////////////////////////
// CHBitButton windowclass CHBitButton : public CButton
{
// Construction
public:
CHBitButton();// Attributes
public:// Operations
public:
BOOL LoadBitmap(UINT nIDDef, UINT nIDMouseHover, UINT nIDMouseDown, UINT nIDDis);// Overrides
// ClassWizard generated virtual function overrides
//{{AFX_VIRTUAL(CHBitButton)
public:
virtual void DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct);
//}}AFX_VIRTUAL// Implementation
public:
BOOL LoadBitmap(char * strBmpDef, char * strBmpMouseHover, char * strBmpMouseDown, char * strBmpDisable);
virtual ~CHBitButton();protected:
CBitmap m_bmpDef;
CBitmap m_bmpMouseHover;
CBitmap m_bmpMouseDown;
CBitmap m_bmpDis;
CRgn m_rgnBgd; BOOL m_bHover; int m_nState; // 0: Default, 1:MouseHover, 2:MouseDown, 3:Disable HRGN m_ButtonRgn;
// Generated message map functions
protected:
//{{AFX_MSG(CHBitButton)
afx_msg void OnDrawItem(int nIDCtl, LPDRAWITEMSTRUCT lpDrawItemStruct);
afx_msg void OnMouseMove(UINT nFlags, CPoint point);
afx_msg void OnLButtonDown(UINT nFlags, CPoint point);
afx_msg void OnLButtonUp(UINT nFlags, CPoint point);
afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);
//}}AFX_MSG
afx_msg void OnMouseLeave(WPARAM wParam, LPARAM lParam);
afx_msg void OnMouseHover(WPARAM wParam, LPARAM lParam);
DECLARE_MESSAGE_MAP()
};///////////////////////////////////////////////////////////////////////////////{{AFX_INSERT_LOCATION}}
// Microsoft Visual C++ will insert additional declarations immediately before the previous line.#endif // !defined(AFX_HBITBUTTON_H__382B43A8_422E_453F_964E_37F057CF3CFE__INCLUDED_)

解决方案 »

  1.   


    //************************************************************************
    // HBitButton.cpp : implementation file
    //#include "stdafx.h"
    #include "BitmapButton.h"
    #include "HBitButton.h"#ifdef _DEBUG
    #define new DEBUG_NEW
    #undef THIS_FILE
    static char THIS_FILE[] = __FILE__;
    #endif/////////////////////////////////////////////////////////////////////////////
    // CHBitButtonCHBitButton::CHBitButton()
    {
    m_nState = 0;
    m_bHover = FALSE;
    }CHBitButton::~CHBitButton()
    {
    }
    BEGIN_MESSAGE_MAP(CHBitButton, CButton)
    //{{AFX_MSG_MAP(CHBitButton)
    ON_WM_DRAWITEM()
    ON_WM_MOUSEMOVE()
    ON_WM_LBUTTONDOWN()
    ON_WM_LBUTTONUP()
    ON_WM_CREATE()
    //}}AFX_MSG_MAP
    ON_MESSAGE(WM_MOUSEHOVER, OnMouseHover)
    ON_MESSAGE(WM_MOUSELEAVE, OnMouseLeave)
    END_MESSAGE_MAP()/////////////////////////////////////////////////////////////////////////////
    // CHBitButton message handlers
    BOOL CHBitButton::LoadBitmap(char *strBmpDef, char *strBmpMouseHover, char *strBmpMouseDown, char *strBmpDisable)
    {
    HBITMAP hbitmap;
    if (strBmpDef != NULL)
    {
    hbitmap  = 
    (HBITMAP)::LoadImage(NULL, strBmpDef,IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE);
    m_bmpDef.Attach(hbitmap);
    }
    if (strBmpMouseHover != NULL)
    {
    hbitmap  = 
    (HBITMAP)::LoadImage(NULL, strBmpMouseHover,IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE);
    m_bmpMouseHover.Attach(hbitmap);
    }
    if (strBmpMouseDown != NULL)
    {
    hbitmap  = 
    (HBITMAP)::LoadImage(NULL, strBmpMouseDown,IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE);
    m_bmpMouseDown.Attach(hbitmap);
    }
    if (strBmpDisable != NULL)
    {
    hbitmap  = 
    (HBITMAP)::LoadImage(NULL, strBmpDisable,IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE);
    m_bmpDis.Attach(hbitmap);
    }
    return TRUE;
    }BOOL CHBitButton::LoadBitmap(UINT nIDDef, UINT nIDMouseHover, UINT nIDMouseFocus, UINT nIDDis)
    {
    if (nIDDef)
    {
    m_bmpDef.LoadBitmap(nIDDef);
    }
    if (nIDMouseHover)
    {
    m_bmpMouseHover.LoadBitmap(nIDMouseHover);
    }
    if (nIDMouseFocus)
    {
    m_bmpMouseDown.LoadBitmap(nIDMouseFocus);
    }
    if (nIDDis)
    {
    m_bmpDis.LoadBitmap(nIDDis);
    }
    return TRUE;
    }
    void CHBitButton::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct) 
    {
    // TODO: Add your code to draw the specified item
    CBitmap * pBitmap = NULL; switch(m_nState)
    {
    case 0:
    pBitmap = &m_bmpDef;
    break;
    case 1:
    pBitmap = &m_bmpMouseHover;
    break;
    case 2:
    pBitmap = &m_bmpMouseDown;
    break;
    case 3:
    pBitmap = &m_bmpDis;
    break;
    } CDC * pDC;
    pDC = this->GetDC(); CDC memDC;
    memDC.CreateCompatibleDC(pDC);
    CBitmap* pOldBitmap = memDC.SelectObject(pBitmap);
    BITMAP bminfo;
    pBitmap->GetObject(sizeof(bminfo), &bminfo); pDC->BitBlt(0, 0, bminfo.bmWidth, bminfo.bmHeight, &memDC, 0, 0, SRCCOPY);
    memDC.SelectObject(pOldBitmap);
    this->ReleaseDC(pDC);
    }void CHBitButton::OnDrawItem(int nIDCtl, LPDRAWITEMSTRUCT lpDrawItemStruct) 
    {
    // TODO: Add your message handler code here and/or call default
    CButton::OnDrawItem(nIDCtl, lpDrawItemStruct);
    }void CHBitButton::OnMouseMove(UINT nFlags, CPoint point) 
    {
    // TODO: Add your message handler code here and/or call default
    if (!m_bHover)
    {
    TRACKMOUSEEVENT evntTrack;
    evntTrack.cbSize = sizeof(TRACKMOUSEEVENT);
    evntTrack.dwFlags = TME_HOVER | TME_LEAVE;
    evntTrack.dwHoverTime = 1;
    evntTrack.hwndTrack = this->m_hWnd;
    _TrackMouseEvent(&evntTrack);
    //this->Invalidate();
    }
    CButton::OnMouseMove(nFlags, point);
    }void CHBitButton::OnMouseLeave(WPARAM wParam, LPARAM lParam)
    {
    m_bHover = FALSE;
    m_nState = 0;
    this->Invalidate();
    }void CHBitButton::OnMouseHover(WPARAM wParam, LPARAM lParam)
    {
    m_bHover = TRUE;
    m_nState = 1;
    this->Invalidate();
    }void CHBitButton::OnLButtonDown(UINT nFlags, CPoint point) 
    {
    // TODO: Add your message handler code here and/or call default
    m_nState = 2;
    this->Invalidate();
    //CButton::OnLButtonDown(nFlags, point);
    }void CHBitButton::OnLButtonUp(UINT nFlags, CPoint point) 
    {
    // TODO: Add your message handler code here and/or call default
    m_nState = 1;
    this->Invalidate();
    CButton::OnLButtonUp(nFlags, point);
    }int CHBitButton::OnCreate(LPCREATESTRUCT lpCreateStruct) 
    {
    if (CButton::OnCreate(lpCreateStruct) == -1)
    return -1;

    // TODO: Add your specialized creation code here
    ModifyStyle(0, BS_OWNERDRAW); BITMAP bminfo;
    m_bmpDef.GetObject(sizeof(bminfo), &bminfo); CDC * pDC = this->GetDC();
    CDC memDC;
    memDC.CreateCompatibleDC(pDC);
    memDC.SelectObject(&m_bmpDef);
    this->ReleaseDC(pDC); // Create the rgn
    CRgn rgnTemp;
    COLORREF  color, temp;
    color = GetPixel(memDC.GetSafeHdc(), 0, 0);
    m_rgnBgd.CreateRectRgn(0, 0, bminfo.bmWidth, bminfo.bmHeight);

    int i, j;
    for (i = 0; i < bminfo.bmWidth; i ++)
    {
    for (j = 0; j < bminfo.bmHeight; j ++)
    {
    temp = memDC.GetPixel(i, j);
    if (color == temp)
    {
    rgnTemp.CreateRectRgn(i, j, i+1, j+1);
    m_rgnBgd.CombineRgn(&m_rgnBgd, &rgnTemp, RGN_DIFF);
    rgnTemp.DeleteObject();
    }
    }
    }

    this->SetWindowRgn(m_rgnBgd, TRUE); return 0;
    }
      

  2.   

    看看m_rgnBgd.CombineRgn(&m_rgnBgd, &rgnTemp, RGN_DIFF);的返回值
      

  3.   

    to:happyparrot(快乐鹦鹉) 
    要画位图就要有一个内存DC呀!!
    //=============================================问题解决了!!
    绘制位图时,不仅要改变按钮本身的有效区域m_rgnBgd,
    而且要改变相应的DC的裁减区域(需另增成员变量m_rgnDC)
    在DrawItem中,BitBlt之前增加
    pDC->SelectClipRgn(&m_rgnDC);  //改变pDC的裁减区域
    另外在OnCreate函数的for循环之后,增加
    m_rgnDC.CombineRgn(&m_rgnDC, &m_rgnBgd, RGN_AND);//保存DC的裁减区域谢谢各位捧场!!