Click here to Skip to main content
15,879,535 members
Please Sign up or sign in to vote.
3.71/5 (5 votes)
See more:
Hello,

I do want to draw round edged button with gradient in back ground

Can anyone help me out?
Posted
Comments
ManjIndian 9-Oct-12 9:43am    
this one is also a single line question.... but seniors will answer for this... not for mine.. what a funny...................

Page 1 of 3


For head start, here is a sample of it in C#
Round Button in C#[^]

Update:
I saw the tag. I gave you that as a start to you. You will have to Paint it yourself. Handle the Paint event for the button.

or are you asking the full codebase for what you need?
 
Share this answer
 
v2
But i have to define some thing here: the bold.

m_cButon.Create("", WS_CHILD | WS_VISIBLE, CRect(150, 20, 250, 43), this, UNIT ID);


what to provide for UINT ID?
 
Share this answer
 
Eugen, the project which i had sent you earlier, I am working on the same project.

I am creating button in one cpp and using it in another cpp. Like this.

int CMyButton::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
    if (CButton::OnCreate(lpCreateStruct) == -1)
        return -1;

    // TODO:  Add your specialized creation code here
    m_cButon.Create("", WS_CHILD|WS_VISIBLE|BS_PUSHBUTTON, CRect(20, 34, 90, 79), this, 1);

    return 0;
}


And using here.
void CDisplayBar::DoDataExchange(CDataExchange* pDX)
{
    // TODO: Add your specialized code here and/or call the base class

    CDialogBar::DoDataExchange(pDX);

    DDX_Control(pDX, 1, m_Btn1);
 }


For more clarification, try to look on my sent project which is named as ColoredButton.
 
Share this answer
 
v2
No, first i do want to work with one button perfectly.

But after making "Owner draw" FALSE, still control is not coming hre:

C#
int CMyButton::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
    if (CButton::OnCreate(lpCreateStruct) == -1)
        return -1;

    // TODO:  Add your specialized creation code here
    //m_cButon.Create("", WS_CHILD|WS_VISIBLE|BS_PUSHBUTTON, CRect(20, 34, 90, 79), this, 1);
    this->SetWindowRgn(m_cRgn, TRUE);

    return 0;
}


and here:

void CMyButton::OnDrawItem(int nIDCtl, LPDRAWITEMSTRUCT lpDrawItemStruct)
{
	// TODO: Add your message handler code here and/or call default
	CButton::OnDrawItem(nIDCtl, lpDrawItemStruct);
	CRect cRect;
	m_cButon.GetClientRect(cRect);
	m_cRgn.CreateRoundRectRgn(0, 0, cRect.Width(), cRect.Height(), 25, 25);
	m_cButon.SetWindowRgn(m_cRgn, TRUE);
}


And i am not getting Round Edged Button.
 
Share this answer
 
v2
Yes. it is there.

C#
public:
    CDisplayBar();
    virtual ~CDisplayBar();
    void InitDialog();

    // Dialog Data
  //{{AFX_DATA(CDisplayBar)
    enum { IDD = IDD_DIALOGBAR };
    CMyButton m_Btn1;
  //}}AFX_DATA



VB
BEGIN_MESSAGE_MAP(CMyButton, CButton)
    ON_WM_CREATE()
    ON_WM_DRAWITEM()
END_MESSAGE_MAP()
 
Share this answer
 
When i am making "Owner Draw" TRUE for IDC_BUTTON!, I am gettng "Debug Assertion Failed.

How to get rid of this. I have already posted where i am getting this error, please do have a look of my previous reply.

C#
void CButton::DrawItem(LPDRAWITEMSTRUCT)
{
    ASSERT(FALSE);
}

Here i am getting "Debug Assertion Failed".
 
Share this answer
 
Thanks Eugen.

Now one new issue came into picture. When i am changing Dialogbar background, then i am able to see rectangular edges of button which of grey in color.

Though we have made round edged button but rectangular edge is still there whcih you can see when you change background color of form

here is the piece of code fof changing background color:
BOOL CButtonDialogBar::OnEraseBkgnd(CDC* pDC)
{
	// TODO: Add your message handler code here and/or call default
  CRect rect;
  GetClientRect(&rect);
  int r1=19,g1=40,b1=85; //Any start color
  int r2=60,g2=88,b2=156; //Any stop color
  for(int i=0;i<rect.Height();i++)
  { 
    int r,g,b;
    r = r1 + (i * (r2-r1) / rect.Height());
    g = g1 + (i * (g2-g1) / rect.Height());
    b = b1 + (i * (b2-b1) / rect.Height());
    pDC->FillSolidRect(0,i,rect.Width(),1,RGB(r,g,b));
  }
  return true; 
}


And add this code for CMyButton:
void CRoundColoredButton::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct)
{
  CDC dc;
  RECT rect;
  dc.Attach(lpDrawItemStruct ->hDC); 
  CDC* pDC = CDC::FromHandle(lpDrawItemStruct->hDC);
  pDC->RoundRect(0,
                 0,
                 lpDrawItemStruct->rcItem.right,
                 lpDrawItemStruct->rcItem.bottom,
                 50,
		 50);
  
  CRgn cRgn1;
  cRgn1.CreateRoundRectRgn(0,
                          0,
                          lpDrawItemStruct->rcItem.right,
                          lpDrawItemStruct->rcItem.bottom,
                          50,
                          50);
  pDC->SelectClipRgn(&cRgn1);
  pDC->FillSolidRect(&lpDrawItemStruct->rcItem, RGB(255, 255, 255));

  CRgn cRgn2;
  cRgn2.CreateRoundRectRgn(3,
                          3,
                          lpDrawItemStruct->rcItem.right-3,
                          lpDrawItemStruct->rcItem.bottom-3,
                          50,
                          50);
  pDC->SelectClipRgn(&cRgn2);
 
  int r2=19,g2=40,b2=85; //Any start color
  int r1=60,g1=88,b1=156; //Any stop color
  
  rect = lpDrawItemStruct->rcItem;     //Store the Button rect to our local rect.
  for(int i=0;i<rect.bottom;i++)
  { 
    int r,g,b;
    r = r1 + (i * (r2-r1) / rect.bottom);
    g = g1 + (i * (g2-g1) / rect.bottom);
    b = b1 + (i * (b2-b1) / rect.bottom);
   dc.FillSolidRect(0,i,rect.right,1,RGB(r,g,b));
  }

  CString strText;
  GetWindowText(strText);
  int iOldMode = pDC->SetBkMode(TRANSPARENT);
  COLORREF crOldColor = pDC->SetTextColor(RGB(255,255,255));

  if (lpDrawItemStruct->itemState & ODS_SELECTED) {
    lpDrawItemStruct->rcItem.top += 2;
    lpDrawItemStruct->rcItem.left += 2;
  }

  pDC->DrawText(strText, &lpDrawItemStruct->rcItem,  DT_SINGLELINE|DT_VCENTER|DT_CENTER);
  pDC->SetTextColor(crOldColor);
  pDC->SetBkMode(iOldMode);
  pDC->SelectClipRgn(NULL);
}


Apply above code, you will come to know what i am talking about,

How to make rounded edge button completely by cutting rectangular edge of button?
 
Share this answer
 
v2
Sorry :)

The usage of m_cFont must be placed in to the CRoundColoredButton::DrawItem(..)


(we do not need OnDrawItem :) )
 
Share this answer
 
Yes :)

void CMyButton::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct)
{
  CDC* pDC0 = CDC::FromHandle(lpDrawItemStruct->hDC);
  int iCX = lpDrawItemStruct->rcItem.right;
  int iCY = lpDrawItemStruct->rcItem.bottom;

  CRgn cRgn1;
  cRgn1.CreateRoundRectRgn(0,
                           0,
                           lpDrawItemStruct->rcItem.right,
                           lpDrawItemStruct->rcItem.bottom,
                           50,
                           50);
  pDC0->SelectClipRgn(&cRgn1);
  
  CDC cMemDC;
  cMemDC.CreateCompatibleDC(pDC0);
  CDC* pDC = &cMemDC;
  
  CBitmap cBmp;
  cBmp.CreateCompatibleBitmap(pDC0, iCX, iCY);
  CGdiObject* pcOldBitmap = cMemDC.SelectObject(&cBmp);
  
  pDC->RoundRect(0,
                 0,
                 lpDrawItemStruct->rcItem.right,
                 lpDrawItemStruct->rcItem.bottom,
                 50,
                 50);
  pDC->FillSolidRect(&lpDrawItemStruct->rcItem, RGB(255, 255, 255));
  CRgn cRgn2;
  cRgn2.CreateRoundRectRgn(3,
                           3,
                           lpDrawItemStruct->rcItem.right-3,
                           lpDrawItemStruct->rcItem.bottom-3,
                           50,
                           50);
  pDC->SelectClipRgn(&cRgn2);
  int r2=19,g2=40,b2=85; //Any start color
  int r1=60,g1=88,b1=156; //Any stop color
  RECT rect = lpDrawItemStruct->rcItem;     //Store the Button rect to our local rect.
  for(int i=0;i<rect.bottom;i++)  {
    int r,g,b;
    r = r1 + (i * (r2-r1) / rect.bottom);
    g = g1 + (i * (g2-g1) / rect.bottom);
    b = b1 + (i * (b2-b1) / rect.bottom);
    pDC->FillSolidRect(0,i,rect.right,1,RGB(r,g,b));
  }
  CString strText;
  GetWindowText(strText);
  int iOldMode = pDC->SetBkMode(TRANSPARENT);
  COLORREF crOldColor = pDC->SetTextColor(RGB(255,255,255));
  if (lpDrawItemStruct->itemState & ODS_SELECTED) {
    lpDrawItemStruct->rcItem.top += 2;
    lpDrawItemStruct->rcItem.left += 2;
  }
  lpDrawItemStruct->rcItem.top = (lpDrawItemStruct->rcItem.bottom -
                                  lpDrawItemStruct->rcItem.top) /2;
  strText = _T("this is a long\ntest text...");
  pDC->DrawText(strText, &lpDrawItemStruct->rcItem, DT_CENTER|DT_WORDBREAK );
  pDC0->BitBlt(0, 0, iCX, iCY, pDC, 0, 0, SRCCOPY);
  
  pDC->SetTextColor(crOldColor);
  pDC->SetBkMode(iOldMode);
  pDC->SelectObject(pcOldBitmap);
  pDC->DeleteDC();
  pDC0->SelectClipRgn(NULL);
}
 
Share this answer
 
OK :)

Please check your buttons implementation:
void CMyButton::PreSubclassWindow()
{
  CRect cRect;
  GetWindowRect(cRect);
  m_cRgn.CreateRoundRectRgn(0, 0, cRect.Width(), cRect.Height(), 50, 50);
  SetWindowRgn(m_cRgn, TRUE);
}

void CMyButton::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct)
{
  CRgn cRgn;
  cRgn.CreateRoundRectRgn(0,
                          0,
                          lpDrawItemStruct->rcItem.right,
                          lpDrawItemStruct->rcItem.bottom,
                          50,
                          50);
  CDC* pDC = CDC::FromHandle(lpDrawItemStruct->hDC);
  pDC->SelectClipRgn(&cRgn);
  _FillGradient(pDC, lpDrawItemStruct->rcItem,
                lpDrawItemStruct->itemState & ODS_SELECTED ?
                RGB(0, 200, 0) : RGB(0, 100, 0),
                lpDrawItemStruct->itemState & ODS_SELECTED ?
                RGB(0, 100, 0) : RGB(0, 200, 0),
                TRUE, 0, 0);
  // Get the button's text.
  CString strText;
  GetWindowText(strText);
  int iOldMode = pDC->SetBkMode(TRANSPARENT);
  COLORREF crOldColor = pDC->SetTextColor(RGB(255,255,255));
  if (lpDrawItemStruct->itemState & ODS_SELECTED) {
    lpDrawItemStruct->rcItem.top += 2;
    lpDrawItemStruct->rcItem.left += 2;
  }
  pDC->DrawText(strText, &lpDrawItemStruct->rcItem, DT_SINGLELINE|DT_VCENTER|DT_CENTER);
  
  pDC->SetTextColor(crOldColor);
  pDC->SetBkMode(iOldMode);
  pDC->SelectClipRgn(NULL);
}
 
Share this answer
 
v2
I did like this:
int CMyButton::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
    if (CButton::OnCreate(lpCreateStruct) == -1)
        return -1;

    // TODO:  Add your specialized creation code here
    this->SetWindowRgn(m_cRgn, TRUE);

    return 0;
}


but i got Debug Assertion Failed at:
void CButton::DrawItem(LPDRAWITEMSTRUCT)
{
    ASSERT(FALSE);
}



I am aplogies if i am doing something funny. But i am new to MFC Application.
 
Share this answer
 
It is very good :)

It is just a "sign" to implement you own function CMyButton::OnDrawItem() :)

Seconly, you should be sure,
that the only CMyButton-exchanged buttons
have "True" at their "Owner Draw" property in the resource view :)

Please remember to create the buttons region member
befor you set it:

...
  CRect cRect;
  GetWindowRect(cRect);
  m_cRgn.CreateRoundRectRgn(0, 0, cRect.Width(), cRect.Height(), 50, 50);
...
 
Share this answer
 
v2
Yes, Owner Draw is TRUE.

How to get rid of this Assertion Failed? If i am going in correct direction then why this Assertion Failed is coming and why my Button is not coming in Dialog Bar Form?

Any idea?
 
Share this answer
 
I kept breakpoint in:

C#
int CMyButton::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
    if (CButton::OnCreate(lpCreateStruct) == -1)
        return -1;

    // TODO:  Add your specialized creation code here
    //m_cButon.Create("", WS_CHILD|WS_VISIBLE|BS_PUSHBUTTON, CRect(20, 34, 90, 79), this, 1);
    this->SetWindowRgn(m_cRgn, TRUE);

    return 0;
}


but program is not stopping here. it is showing "Debug Assertion Error" before coming to here.
 
Share this answer
 
Please check
that the buttos IDs are the same
in the resource view and in the exchange function :)

It schould be something like IDC_BUTTONXXX (and not 1 or 2) :)
 
Share this answer
 
Yes, ID of Button is same in all places. No change at all.

but still Problem is ON.
 
Share this answer
 
Please post your bars exchange function :)
 
Share this answer
 
v2
Here is my Bar Function:

C#
void CDisplayBar::DoDataExchange(CDataExchange* pDX)
{
    // TODO: Add your specialized code here and/or call the base class

    CDialogBar::DoDataExchange(pDX);

    DDX_Control(pDX, IDC_BUTTON1, m_Btn1);
}
 
Share this answer
 
Eugen, leave your post.. I will look at it tomorrow morning and get back to your if any problem arise. or else i will give a vote your reply.
 
Share this answer
 
You should have "True" only for the test button
that is icluded in the exchange function :)

Secondly,
please delete the CMyButton::OnCreate(..) (my mistake)
and implement the following function for CMyButton:

virtual void PreSubclassWindow();


void CMyButton::PreSubclassWindow()
{
  CRect cRect;
  GetWindowRect(cRect);
  m_cRgn.CreateRoundRectRgn(0, 0, cRect.Width(), cRect.Height(), 50, 50);
  SetWindowRgn(m_cRgn, TRUE);
}
 
Share this answer
 
Comments
Nitin R G 14-Sep-15 8:20am    
Hello,
I tried with these solutions, i am getting the round edges but not the smooth edges. any 1 have solution for this???

Page 1 of 3
1 2 3

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900