SetWindowRgn 只能调一次
void CMyButton::PreSubclassWindow() 
{
// TODO: Add your specialized code here and/or call the base class
    CRect rect;// = btnrect;
    GetWindowRect(rect);
rect.OffsetRect(-rect.left,-rect.top);
 
    CRgn rgn;
    rgn.CreateRoundRectRgn(rect.left,rect.top,rect.right,rect.bottom,Radius,Radius);
    SetWindowRgn((HRGN)rgn.m_hObject,TRUE);
    rgn.DeleteObject();

// CButton::PreSubclassWindow();
}

解决方案 »

  1.   

    void CUIButton::PreSubclassWindow()
    { CRect rect;
    GetWindowRect(rect);
    rect.OffsetRect(-rect.left,-rect.top);
    CRgn rgn;
    rgn.CreateRoundRectRgn(rect.left,rect.top,rect.right,rect.bottom,ioffset,ioffset);
    SetWindowRgn((HRGN)rgn.m_hObject,TRUE);
    rgn.DeleteObject();

    UINT uStyle = GetButtonStyle();
    ModifyStyle(0,uStyle | BS_OWNERDRAW);
    CButton::PreSubclassWindow();
    }
    这样改之后,刚开始界面就有圆角白色的,之前是点击之后才有的。
      

  2.   

    按钮需要圆角处理.CreateRoundRectRgn 创建圆角裁剪区域, 再有些区域来裁剪窗口. 就可以把你的按钮裁剪成圆角的了. 白色背景自然就没有了
      

  3.   

    你的问题是添加的时间可能不对.
    需要在创建完成后马上改变. 你可以放到WM_SIZE消息或者WM_CREATE消息中再试试RECT rcWnd;
    ::GetWindowRect(*this, &rcWnd);
    OffsetRect(&rcWnd,-rcWnd.left, -rcWnd.top);
    rcWnd.right++; rcWnd.bottom++;
    HRGN hRgn1 = ::CreateRoundRectRgn(0, 0, rcWnd.right, rcWnd.bottom/3*2, roundTop, roundTop);
    HRGN hRgn2 = ::CreateRoundRectRgn(0, rcWnd.bottom/3, rcWnd.right, rcWnd.bottom, roundBottom, roundBottom);
    HRGN hRgn = hRgn1;
    ::CombineRgn(hRgn,hRgn1,hRgn2,RGN_OR); ::SetWindowRgn(*this, hRgn, TRUE);
    ::DeleteObject(hRgn1);
    ::DeleteObject(hRgn2);
            ::DeleteObject(hRgn);
      

  4.   

       UINT uStyle = GetButtonStyle();
        ModifyStyle(0,uStyle | BS_OWNERDRAW);可以在属性中设置。Draw 时 不必 考虑 园角, rgn 外的 自动 会 Clip 掉。测试过的代码 没问题的
      

  5.   


    按你的方法测试了,依旧不行,总感觉SetwindowRgn没有起作用,能不能将这个类发给你,帮我看下。
      

  6.   

    还有一个办法就是
    把 SetWindowRgn 那句 改成:dc.SelectClipRgn
      

  7.   

    从你的代码中看,你重载了DrawItem虚函数,因此根本不需要调用SetWindowRgn来设置窗口有效范围,因为有BS_OWNERDRAW标志后系统已经完全不会再绘制BUTTON了,必须你自己绘制,此时想要圆角,所以的绘制都用CreateRoundRectRgn来绘制就行了,我没细看你的代码,我猜测你会不会先给BUTTON用白色全部填充了一遍,如果你填充了,也要用圆角矩形区域来填充,不要全部填充。
      

  8.   

    rgn.DeleteObject()???  MSDN:
    After a successful call to SetWindowRgn, the system owns the region specified by the region handle hRgn. The system does not make a copy of the region. Thus, you should not make any further function calls with this region handle. In particular, do not delete this region handle. The system deletes the region handle when it no longer needed.你应该用rgn.Detach();
      

  9.   

    总之试了各种办法都不行。我的环境是win7 64位  vs2010 vs2013
      

  10.   

    不作死就不会死。
    rgn.CreateRoundRectRgn(),SetWindowRgn()后千万别rgn.DeleteObject()!!! 而是应该用rgn.Detatch()和内部的HRGN脱离关系。
      

  11.   


    #pragma once// CUIButton  .henum BTN_COLOR{BTN_ENABLE,BTN_DISABLE,BTN_ON,BTN_OFF,BTN_CUSTOM};
    class CUIButton : public CButton
    {
    DECLARE_DYNAMIC(CUIButton)
    public:
    CUIButton();
    virtual ~CUIButton();protected:
    DECLARE_MESSAGE_MAP()
    public:
    virtual void DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct);
    virtual void PreSubclassWindow();
    BTN_COLOR m_btncolor;
    public:
    COLORREF m_BkColor_Enable;
    COLORREF m_BkColor_Disable;
    COLORREF m_BkColor_On;
    COLORREF m_BkColor_Off;
    COLORREF m_TextColor_On;
    COLORREF m_TextColor_Off;
    COLORREF m_TextColor_Enalbe;
    COLORREF m_TextColor_Disable; COLORREF m_TextColor_Custom;
    COLORREF m_BkColor_Color;
    static const int ioffset = 5; int m_Iconid;
    CString m_szText;
    void Set_Back_Color(COLORREF bkColor);
    void Set_Text_Color(COLORREF textcolor);
    void Set_Icon_ID(int iconid);
    void Set_Window_Text(CString & sztext);
    void Set_BTN_COLOR(BTN_COLOR nstate);
    BTN_COLOR Get_BTN_COLOR();
    };// UIButton.cpp : 实现文件
    //#include "stdafx.h"
    #include "UIButton.h"
    // CUIButtonIMPLEMENT_DYNAMIC(CUIButton, CButton)CUIButton::CUIButton()
    {
    //m_BkColor_Enable = RGB(120, 171, 233);

    m_BkColor_Enable = RGB(117, 174, 17);
    m_BkColor_Disable = RGB(160, 193, 242);
    m_TextColor_Enalbe = RGB(229, 252, 195);
    m_TextColor_Disable = RGB(0,0,255);
    m_BkColor_On = RGB(174, 223, 167);
    m_BkColor_Off = RGB(197, 221, 0);
    m_TextColor_On = RGB(100,21,240);
    m_TextColor_Off = RGB(0, 110, 100);
    m_TextColor_Custom = RGB(193, 221, 239);
    m_BkColor_Color = RGB(92, 136, 201);
    m_Iconid = 0; m_btncolor = BTN_CUSTOM;}CUIButton::~CUIButton()
    {
    }
    BEGIN_MESSAGE_MAP(CUIButton, CButton)
    END_MESSAGE_MAP()// CUIButton 消息处理程序void CUIButton::PreSubclassWindow()
    { /*CRect rect;
    GetWindowRect(rect);
    rect.OffsetRect(-rect.left,-rect.top);
    CRgn rgn;
    rgn.CreateRoundRectRgn(rect.left,rect.top,rect.right,rect.bottom,ioffset,ioffset);
    SetWindowRgn((HRGN)rgn.m_hObject,TRUE);
    rgn.DeleteObject();*/

    UINT uStyle = GetButtonStyle();
    ModifyStyle(0,uStyle | BS_OWNERDRAW);
    CButton::PreSubclassWindow();
    }void CUIButton::Set_Back_Color(COLORREF bkColor)
    {
    //m_BkColor = bkColor;
    Invalidate();
    }
    void CUIButton::Set_Text_Color(COLORREF textcolor)
    {
    //m_TextColor = textcolor;
    Invalidate();
    }
    void CUIButton::Set_Icon_ID(int iconid)
    {
    m_Iconid = iconid;
    Invalidate();
    }
    void CUIButton::Set_Window_Text(CString & sztext)
    {
    m_szText = sztext;
    Invalidate();
    }
    void CUIButton::Set_BTN_COLOR(BTN_COLOR nstate)
    {
    m_btncolor = nstate;
    Invalidate();
    }BTN_COLOR CUIButton::Get_BTN_COLOR()
    {
    return m_btncolor;
    }void CUIButton::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct)
    {
    CRect rect = lpDrawItemStruct->rcItem;
    UINT state = lpDrawItemStruct ->itemState;
    CDC * pDC = CDC::FromHandle(lpDrawItemStruct->hDC);
    CRgn rgn;
    rgn.CreateRoundRectRgn(rect.left,rect.top,rect.right,rect.bottom,ioffset,ioffset);
    SetWindowRgn((HRGN)rgn.m_hObject,TRUE);
    CBrush brushBackGround,*pOldBrush;
    CPen pen,* pOldPen; if(m_btncolor == BTN_ENABLE)
    {
    brushBackGround.CreateSolidBrush(m_BkColor_Enable);
    pen.CreatePen(PS_SOLID,1,m_BkColor_Enable);
    pDC->SetTextColor(m_TextColor_Enalbe);
    }
    else if(m_btncolor == BTN_DISABLE)
    {
    brushBackGround.CreateSolidBrush(m_BkColor_Disable);
    pen.CreatePen(PS_SOLID,1,m_BkColor_Disable);
    pDC->SetTextColor(m_TextColor_Disable);
    }
    else if (m_btncolor == BTN_ON)
    {
    brushBackGround.CreateSolidBrush(m_BkColor_On);
    pen.CreatePen(PS_SOLID, 1, m_BkColor_On);
    pDC->SetTextColor(m_TextColor_On);
    }
    else if (m_btncolor == BTN_OFF)
    {
    brushBackGround.CreateSolidBrush(m_BkColor_Off);
    pen.CreatePen(PS_SOLID, 1, m_BkColor_Off);
    pDC->SetTextColor(m_TextColor_Off);
    }
    else
    {
    brushBackGround.CreateSolidBrush(m_BkColor_Color);
    pen.CreatePen(PS_SOLID, 1, m_BkColor_Color);
    pDC->SetTextColor(m_TextColor_Custom);
    } pOldPen = pDC ->SelectObject(&pen);
    pOldBrush = pDC -> SelectObject(&brushBackGround);
    pDC ->RoundRect(&rect,CPoint(ioffset,ioffset));

    CFont font, *pOldfont;
    font.CreatePointFont(120, _T("微软雅黑"), pDC);
    pOldfont = pDC->SelectObject(&font); if (m_Iconid != 0)
    {
    HICON hicon = (HICON)LoadImage(AfxGetApp()->m_hInstance, MAKEINTRESOURCE(m_Iconid), IMAGE_ICON, 48, 48, LR_DEFAULTCOLOR);
    ICONINFO iconinfo;
    GetIconInfo(hicon, &iconinfo);
    HBITMAP hBitmap = iconinfo.hbmMask;
    BITMAP bmp;
    GetObject(hBitmap, sizeof(bmp), &bmp);
    int xpos, ypos;
    xpos = rect.right - bmp.bmHeight - ioffset;
    ypos = (rect.Height() - bmp.bmHeight) / 2; DrawIconEx(pDC->m_hDC, xpos, ypos, hicon, bmp.bmWidth, bmp.bmHeight, 0, NULL, DI_NORMAL);
    CString szText;
    GetWindowText(szText);
    if (szText.IsEmpty())
    szText = m_szText;
    CSize szExtent = pDC->GetTextExtent(szText);
    CPoint pt((rect.right - bmp.bmWidth - szExtent.cx - ioffset) / 2, (rect.Height() - szExtent.cy ) / 2);

    //pDC->SetTextColor(m_TextColor_Enalbe);
    pDC->SetBkMode(TRANSPARENT);
    pDC->TextOut(pt.x, pt.y, szText);
    }
    else
    {
    CString szText;
    GetWindowText(szText);
    if (szText.IsEmpty())
    szText = m_szText;
    CSize szExtent = pDC->GetTextExtent(szText);
    CPoint pt((rect.right - szExtent.cx) / 2, (rect.Height() - szExtent.cy)/ 2);
    pDC->SetBkMode(TRANSPARENT);
    pDC->TextOut(pt.x, pt.y, szText);
    }
    if (state & ODS_FOCUS) // 具有焦点时,画一圈小虚线
    {
    rect.DeflateRect(3, 3);
    pDC->DrawFocusRect(&rect);
    }
    if (state & ODS_SELECTED)
    {
    rect.DeflateRect(-2, -2);
    pDC->InvertRect(&rect);
    }
    pDC->SelectObject(pOldfont);
    pDC->SelectObject(pOldBrush);
    pDC->SelectObject(pOldPen);
    brushBackGround.DeleteObject();
    pen.DeleteObject();
    font.DeleteObject();
    //rgn.DeleteObject();
    }
    以上是我类的全部代码,很多if只是画不同状态。另附一个链接,感觉都差不多,为什么不行?http://bbs.csdn.net/topics/340257193
      

  12.   


    千万不要被误导,SetWindowRgn调用之后其里面的参数HRGN是可以DeleteObject的。
      

  13.   


    千万不要被误导,SetWindowRgn调用之后其里面的参数HRGN是可以DeleteObject的。删不删除这都不是关键,资源泄漏什么没关系,关键是这个问题没解决,效果不好看。看很多帖子都成功了。
      

  14.   

    我刚测试了一下,重载OnEraseBkgnd返回TRUE即可解决。我试的是XP,在XP下第一次显示时是没有白色的,当把窗口移到屏幕外面,再移回来就出来了白色。
    BOOL CUIButton::OnEraseBkgnd(CDC* pDC)
    {
    // TODO: 在此添加消息处理程序代码和/或调用默认值
    return TRUE;
    return CButton::OnEraseBkgnd(pDC);
    }
      

  15.   

    我的是第一次出来没问题,点击一下就有白色边框了。重载OnEraseBkgnd就解决了。结贴,分给你。
      

  16.   

    这样也可以:void CMyButton::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct) 
    {
    // TODO: Add your code to draw the specified item
    CRect btnrect = lpDrawItemStruct->rcItem;
        UINT state = lpDrawItemStruct ->itemState;
        CDC * pDC = CDC::FromHandle(lpDrawItemStruct->hDC);
     
        CRect rect = btnrect;
     
        CRgn rgn;
        rgn.CreateRoundRectRgn(rect.left,rect.top,rect.right,rect.bottom,Radius,Radius);
        pDC->SelectClipRgn(&rgn,TRUE);
     
        pDC ->FillSolidRect(&rect,RGB(255,0,0));
      

  17.   

    我不是说:"重载OnEraseBkgnd就解决了"的问题
      

  18.   

    因为OnEraseBkgnd先于OnPaint(即DrawItem) 如果在OnEraseBkgnd中
    pDC ->FillSolidRect(&rect,RGB(255,255,255));
    那就会不是RoundRect
    因为:
    pDC->SelectClipRgn(&rgn,TRUE);
    没起作用:
    但可以把
    pDC->SelectClipRgn(&rgn,TRUE);
    放OnEraseBkgnd 中.
    再pDC ->FillSolidRect(&rect,RGB(255,255,255));
    其实是round rect !
      

  19.   

    楼主您好,我将上述您的代码复制,移植到一个基于对话框的程序中,程序不知为何没有反应,能否发一下可调式的源程序代码,仅供学习用,邮箱为[email protected],不胜感激