Click here to Skip to main content
15,920,508 members
Please Sign up or sign in to vote.
3.88/5 (6 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 2 of 3


Eugen, I have done according to you. but i am still getting "Debug Assertion Failed".

Do I have to include "OnDrawItem()"?
 
Share this answer
 
Please observe the this at the assertion
(right click -> QuickWatch -> type "this") -
what class name is shown there ? :)
 
Share this answer
 
v2
Eugen, Now "Debug Assertion Failed" is solved. I used "DrawItem()" because Owner Draw is TRUE.

But I am not getting Round Edged Button after applying your suggested code.

What to do next?
 
Share this answer
 
Here would be a "replacement" for CDrawManager::DrawGradient(..):
void _FillGradient(CDC* pDC,
                        CRect rect,
                        COLORREF colorStart,
                        COLORREF colorFinish,
                        BOOL bHorz/* = TRUE*/,
                        int nStartFlatPercentage/* = 0*/,
                        int nEndFlatPercentage/* = 0*/)
{
	if (colorStart == colorFinish)
	{
		CBrush br(colorStart);
		pDC->FillRect(rect, &br);
		return;
	}
	if (nStartFlatPercentage > 0)
	{
		ASSERT(nStartFlatPercentage <= 100);
		if (bHorz)
		{
			CRect rectTop = rect;
			rectTop.bottom = rectTop.top + rectTop.Height() * nStartFlatPercentage / 100;
			rect.top = rectTop.bottom;
			CBrush br(colorFinish);
			pDC->FillRect(rectTop, &br);
		}
		else
		{
			CRect rectLeft = rect;
			rectLeft.right = rectLeft.left + rectLeft.Width() * nStartFlatPercentage / 100;
			rect.left = rectLeft.right;
			CBrush br(colorStart);
			pDC->FillRect(rectLeft, &br);
		}
	}
	if (nEndFlatPercentage > 0)
	{
		ASSERT(nEndFlatPercentage <= 100);
		if (bHorz)
		{
			CRect rectBottom = rect;
			rectBottom.top = rectBottom.bottom - rectBottom.Height() * nEndFlatPercentage / 100;
			rect.bottom = rectBottom.top;
			CBrush br(colorStart);
			pDC->FillRect(rectBottom, &br);
		}
		else
		{
			CRect rectRight = rect;
			rectRight.left = rectRight.right - rectRight.Width() * nEndFlatPercentage / 100;
			rect.right = rectRight.left;
			CBrush br(colorFinish);
			pDC->FillRect(rectRight, &br);
		}
	}
	if (nEndFlatPercentage + nStartFlatPercentage > 100)
	{
		ASSERT(FALSE);
		return;
	}
	// this will make 2^6 = 64 fountain steps
	int nShift = 6;
	int nSteps = 1 << nShift;
	for (int i = 0; i < nSteps; i++)
	{
		// do a little alpha blending
		BYTE bR = (BYTE)((GetRValue(colorStart) *(nSteps - i) + GetRValue(colorFinish) * i) >> nShift);
		BYTE bG = (BYTE)((GetGValue(colorStart) *(nSteps - i) + GetGValue(colorFinish) * i) >> nShift);
		BYTE bB = (BYTE)((GetBValue(colorStart) *(nSteps - i) + GetBValue(colorFinish) * i) >> nShift);
		CBrush br(RGB(bR, bG, bB));
		// then paint with the resulting color
		CRect r2 = rect;
		if (bHorz)
		{
			r2.bottom = rect.bottom - ((i * rect.Height()) >> nShift);
			r2.top = rect.bottom - (((i + 1) * rect.Height()) >> nShift);
			if (r2.Height() > 0)
				pDC->FillRect(r2, &br);
		}
		else
		{
			r2.left = rect.left + ((i * rect.Width()) >> nShift);
			r2.right = rect.left + (((i + 1) * rect.Width()) >> nShift);
			if (r2.Width() > 0)
				pDC->FillRect(r2, &br);
		}
	}
}
 
Share this answer
 
v2
Thank you so much Eugen.

One more question on this, how to draw white border line on this Round Edged Button?
 
Share this answer
 
You could draw at three steps :) :
- CDC::RoundRect(..) at the itemRect

- Decrement the itemRect
- The rest (SelectClipRgn(..) and so on)
 
Share this answer
 
If I m doing so. I am lossing my filled gradient.
One thing i do want to let u know that i havn't used "FillGradient" method. I used for loop for fill gradient. and it is working perfectly.

What how to draw white border line? I am loosing all information of Gradient if I am using RoundRect().
 
Share this answer
 
Try it :)

void CMyButton::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct)
{
  CDC* pDC = CDC::FromHandle(lpDrawItemStruct->hDC);
  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(2,
                          2,
                          lpDrawItemStruct->rcItem.right -2,
                          lpDrawItemStruct->rcItem.bottom -2,
                          50,
                          50);
  pDC->SelectClipRgn(&cRgn2);
...
 
Share this answer
 
not working. It is filling over all area with white and giving "DEbug Assertion Failed" for next Rgn.

Any other idea?
 
Share this answer
 
Try it :)
void CMyButton::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct)
{
  CDC* pDC = CDC::FromHandle(lpDrawItemStruct->hDC);
  pDC->RoundRect(0,
                 0,
                 lpDrawItemStruct->rcItem.right,
                 lpDrawItemStruct->rcItem.bottom,
                 50,
                 50);
  CRgn cRgn2;
  cRgn2.CreateRoundRectRgn(2,
                          2,
                          lpDrawItemStruct->rcItem.right -1,
                          lpDrawItemStruct->rcItem.bottom -1,
                          50,
                          50);
  pDC->SelectClipRgn(&cRgn2);
...
 
Share this answer
 
It is working fine. I am getting two border. Now whre to place code for getting white color between two border?
 
Share this answer
 
It is working by me :) :
void CMyButton::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct)
{
  CDC* pDC = CDC::FromHandle(lpDrawItemStruct->hDC);
  pDC->RoundRect(0,
                 0,
                 lpDrawItemStruct->rcItem.right,
                 lpDrawItemStruct->rcItem.bottom,
                 50,
                 50);
  CRgn cRgn1;
  cRgn1.CreateRoundRectRgn(1,
                          1,
                          lpDrawItemStruct->rcItem.right,
                          lpDrawItemStruct->rcItem.bottom,
                          50,
                          50);
  pDC->SelectClipRgn(&cRgn1);
  pDC->FillSolidRect(&lpDrawItemStruct->rcItem, 0x00FFFFFF);
  CRgn cRgn2;
  cRgn2.CreateRoundRectRgn(2,
                          2,
                          lpDrawItemStruct->rcItem.right -1,
                          lpDrawItemStruct->rcItem.bottom -1,
                          50,
                          50);
  pDC->SelectClipRgn(&cRgn2);
...


P.S. For the "fine working"
you could implement the drawing with GDI+ functions :)
 
Share this answer
 
Please implement the same function of CMyButton :) :
C++
BOOL CMyButton::OnEraseBkgnd(CDC* pDC)
{
  return true;
}
 
Share this answer
 
v2
Thanks again....

And again one more question: Do we have to set font in Drawitem() only?
Or in someother function.

I tried in DrawItem(), but did not get good result.

Any suggestion?
 
Share this answer
 
Of course, before you are drawing the text :)

CFont m_cFont could be created in CMyButton::PreSubclassWindow()

and then - used in CMyButton::OnDrawItem():
{
...
   CGdiObject* pcOldFont = pDC->SelectObject(&m_cFont);
   pcDC->DrawText(..);
   pDC->SelectObject(pcOldFont);
...
}
 
Share this answer
 
Control is not coming in "OnDrawItem()".

here's my code:
void CRoundColoredButton::PreSubclassWindow()
{
	// TODO: Add your specialized code here and/or call the base class
	CButton::PreSubclassWindow();
	CRect cRect;
	GetWindowRect(cRect);
	m_cRgn.CreateRoundRectRgn(0, 0, cRect.Width(), cRect.Height(), 100, 100);
	SetWindowRgn(m_cRgn, TRUE);
	m_cFont.CreatePointFont(5, "Arial Black");
}


void CRoundColoredButton::OnDrawItem(int nIDCtl, LPDRAWITEMSTRUCT lpDrawItemStruct)
{
	// TODO: Add your message handler code here and/or call default
	CString strText;
	GetWindowText(strText);
	CButton::OnDrawItem(nIDCtl, lpDrawItemStruct);
	CDC* pDC = new CDC();
	CGdiObject* pOldFont = pDC->SelectObject(&m_cFont);
	pDC->DrawText(strText, &lpDrawItemStruct->rcItem, DT_SINGLELINE|DT_VCENTER|DT_CENTER);
	pDC->SelectObject(pOldFont);
}
 
Share this answer
 
Thanks....

How to make Text align in bottom but in center?

I am trying this:
pDC->DrawText(strText, &lpDrawItemStruct->rcItem, DT_SINGLELINE|DT_VCENTER|DT_CENTER|DT_BOTTOM);


But text is going at top. I have also tried different combinations. but did not get thru. And i do want with Multiline property true.

Any Suggestion?
 
Share this answer
 
v2
You should remove the DT_VCENTER flag :)
 
Share this answer
 
I did this already. I do want Button name say "Computer Data". But this is coming very close to bottom border and name is not looking good.

I do want little bit up from bottom border so that it will look good in appearance.

Try with this Font:

MIDL
m_ptrFont  = new CFont();
m_ptrFont->CreateFont(16, 0, 0, 0, FW_BOLD, FALSE, FALSE, 0, ANSI_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS,
                                            DEFAULT_QUALITY, DEFAULT_PITCH | FF_SWISS, "Arial");


And i also want Multiline property TRUE.
 
Share this answer
 
You could change the rectangle of the text instead,
for example - offset it down :)

Use the description[^] and the flag DT_WORDBREAK
to process a multiline output :)
 
Share this answer
 

Page 2 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