How to draw a bitmap on top of button?
-
I want to draw a small arrow bitmap on top of already drawn button. I tried with calling default drawing proc before my code for drawing bitmap but it gives me some error.
OnDrawItem(int nIDCtl, LPDRAWITEMSTRUCT lpDrawItemStruct) { CDialog::OnDrawItem(nIDCtl, lpDrawItemStruct); HDC thdc = CreateCompatibleDC(lpDrawItemStruct->hDC); HGDIOBJ tobj = SelectObject(thdc, LoadBitmap(AfxGetInstanceHandle(), MAKEINTRESOURCE(IDB_ARROW_DOWN))); TransparentBlt(lpDrawItemStruct->hDC, lpDrawItemStruct->rcItem.right - 20, lpDrawItemStruct->rcItem.top + (lpDrawItemStruct->rcItem.bottom - lpDrawItemStruct->rcItem.top - 16) / 2, 16, 16, thdc, 0, 0, 16, 16, RGB(255, 0, 255)); SelectObject(thdc, tobj); DeleteDC(thdc); }
if i exclude "CDialog::OnDrawItem(nIDCtl, lpDrawItemStruct);" then code works, but there is no borders and caption text, just my bitmap. -
I want to draw a small arrow bitmap on top of already drawn button. I tried with calling default drawing proc before my code for drawing bitmap but it gives me some error.
OnDrawItem(int nIDCtl, LPDRAWITEMSTRUCT lpDrawItemStruct) { CDialog::OnDrawItem(nIDCtl, lpDrawItemStruct); HDC thdc = CreateCompatibleDC(lpDrawItemStruct->hDC); HGDIOBJ tobj = SelectObject(thdc, LoadBitmap(AfxGetInstanceHandle(), MAKEINTRESOURCE(IDB_ARROW_DOWN))); TransparentBlt(lpDrawItemStruct->hDC, lpDrawItemStruct->rcItem.right - 20, lpDrawItemStruct->rcItem.top + (lpDrawItemStruct->rcItem.bottom - lpDrawItemStruct->rcItem.top - 16) / 2, 16, 16, thdc, 0, 0, 16, 16, RGB(255, 0, 255)); SelectObject(thdc, tobj); DeleteDC(thdc); }
if i exclude "CDialog::OnDrawItem(nIDCtl, lpDrawItemStruct);" then code works, but there is no borders and caption text, just my bitmap.Igor Jerosimic wrote:
but it gives me some error.
Whats the error? After making the button owner draw, you have to draw the entire button your self. the DrawItem() function of CButton only contains
Assert(FALSE);
, which will result in a Abort-Retry--Ignore dialog.nave
-
I want to draw a small arrow bitmap on top of already drawn button. I tried with calling default drawing proc before my code for drawing bitmap but it gives me some error.
OnDrawItem(int nIDCtl, LPDRAWITEMSTRUCT lpDrawItemStruct) { CDialog::OnDrawItem(nIDCtl, lpDrawItemStruct); HDC thdc = CreateCompatibleDC(lpDrawItemStruct->hDC); HGDIOBJ tobj = SelectObject(thdc, LoadBitmap(AfxGetInstanceHandle(), MAKEINTRESOURCE(IDB_ARROW_DOWN))); TransparentBlt(lpDrawItemStruct->hDC, lpDrawItemStruct->rcItem.right - 20, lpDrawItemStruct->rcItem.top + (lpDrawItemStruct->rcItem.bottom - lpDrawItemStruct->rcItem.top - 16) / 2, 16, 16, thdc, 0, 0, 16, 16, RGB(255, 0, 255)); SelectObject(thdc, tobj); DeleteDC(thdc); }
if i exclude "CDialog::OnDrawItem(nIDCtl, lpDrawItemStruct);" then code works, but there is no borders and caption text, just my bitmap.Igor Jerosimic wrote:
OnDrawItem(int nIDCtl, LPDRAWITEMSTRUCT lpDrawItemStruct) { CDialog::OnDrawItem(nIDCtl, lpDrawItemStruct);
As told by Navin, you need to do all drawing stuff in case of owner drawn controls. And should not call base version, as this function is supposed to override in derived control.
Prasad Notifier using ATL | Operator new[],delete[][^]
-
Igor Jerosimic wrote:
but it gives me some error.
Whats the error? After making the button owner draw, you have to draw the entire button your self. the DrawItem() function of CButton only contains
Assert(FALSE);
, which will result in a Abort-Retry--Ignore dialog.nave
It stops on some ASSERT... I know that i have to draw the entire button by myself, but my question is how do i let windows draw that button for me (with al it's visual styles) and i just want to draw small bitmap in right corner of button?
-
It stops on some ASSERT... I know that i have to draw the entire button by myself, but my question is how do i let windows draw that button for me (with al it's visual styles) and i just want to draw small bitmap in right corner of button?
why dont u use CBitmapButton? Another way is to handle the WM_PAINT message of the button and draw the bitmap after the default paint.For this you need to derive a class from CButton and make control variable of button of this class type.I am not sure about this technique. eg: void CMyBotton::OnPaint() { CButton::OnPaint(); // Draw the bitmap }
nave
-
why dont u use CBitmapButton? Another way is to handle the WM_PAINT message of the button and draw the bitmap after the default paint.For this you need to derive a class from CButton and make control variable of button of this class type.I am not sure about this technique. eg: void CMyBotton::OnPaint() { CButton::OnPaint(); // Draw the bitmap }
nave
Naveen R wrote:
CButton::OnPaint();
Should not call base class. :)
Prasad Notifier using ATL | Operator new[],delete[][^]
-
Naveen R wrote:
CButton::OnPaint();
Should not call base class. :)
Prasad Notifier using ATL | Operator new[],delete[][^]
-
prasad_som wrote:
Should not call base class
why? I said him to do so in a non owner draw button.
nave
It doesn't have any effect there.
Prasad Notifier using ATL | Operator new[],delete[][^]
-
I want to draw a small arrow bitmap on top of already drawn button. I tried with calling default drawing proc before my code for drawing bitmap but it gives me some error.
OnDrawItem(int nIDCtl, LPDRAWITEMSTRUCT lpDrawItemStruct) { CDialog::OnDrawItem(nIDCtl, lpDrawItemStruct); HDC thdc = CreateCompatibleDC(lpDrawItemStruct->hDC); HGDIOBJ tobj = SelectObject(thdc, LoadBitmap(AfxGetInstanceHandle(), MAKEINTRESOURCE(IDB_ARROW_DOWN))); TransparentBlt(lpDrawItemStruct->hDC, lpDrawItemStruct->rcItem.right - 20, lpDrawItemStruct->rcItem.top + (lpDrawItemStruct->rcItem.bottom - lpDrawItemStruct->rcItem.top - 16) / 2, 16, 16, thdc, 0, 0, 16, 16, RGB(255, 0, 255)); SelectObject(thdc, tobj); DeleteDC(thdc); }
if i exclude "CDialog::OnDrawItem(nIDCtl, lpDrawItemStruct);" then code works, but there is no borders and caption text, just my bitmap.Have you see this?
"Approved Workmen Are Not Ashamed" - 2 Timothy 2:15
"Judge not by the eye but by the heart." - Native American Proverb
-
I want to draw a small arrow bitmap on top of already drawn button. I tried with calling default drawing proc before my code for drawing bitmap but it gives me some error.
OnDrawItem(int nIDCtl, LPDRAWITEMSTRUCT lpDrawItemStruct) { CDialog::OnDrawItem(nIDCtl, lpDrawItemStruct); HDC thdc = CreateCompatibleDC(lpDrawItemStruct->hDC); HGDIOBJ tobj = SelectObject(thdc, LoadBitmap(AfxGetInstanceHandle(), MAKEINTRESOURCE(IDB_ARROW_DOWN))); TransparentBlt(lpDrawItemStruct->hDC, lpDrawItemStruct->rcItem.right - 20, lpDrawItemStruct->rcItem.top + (lpDrawItemStruct->rcItem.bottom - lpDrawItemStruct->rcItem.top - 16) / 2, 16, 16, thdc, 0, 0, 16, 16, RGB(255, 0, 255)); SelectObject(thdc, tobj); DeleteDC(thdc); }
if i exclude "CDialog::OnDrawItem(nIDCtl, lpDrawItemStruct);" then code works, but there is no borders and caption text, just my bitmap. -
WhiteSky wrote:
See A Better Bitmap Button Class[^] if helpfuls
i liked it sometime before
"Opinions are neither right nor wrong. I cannot change your opinion. I can, however, change what influences your opinion." - David Crow
cheers, Alok Gupta VC Forum Q&A :- I/ IV Support CRY- Child Re
-
It doesn't have any effect there.
Prasad Notifier using ATL | Operator new[],delete[][^]
-
prasad_som wrote:
It doesn't have any effect there.
Whats do you mean. If I didnt called the default procedure for WM_PAINT, then how will the button get painted? Nothing will appear in the place of button. Isn't it?
nave
Naveen R wrote:
Whats do you mean. If I didnt called the default procedure for WM_PAINT, then how will the button get painted?
You are confusing between painting a control and drawing a control. In case of of non-owner drawn control windows takes care of drawing/creating control.
WM_PAINT
message is meant to paint invalidated area. Now about calling base classOnPaint
. It simply does default painting routines and validates invalidated area. So Consider this function,void CMyButton::OnPaint()
{
CButton::OnPaint();//
//Here at above line invlaidated client area will be validated
and code following has no effect
CPaintDC dc(this); // device context for painting
//drawing routine follows
}Consider another scenario,
void CMyButton::OnPaint()
{
CPaintDC dc(this); // device context for painting
//drawing routine follows
//till this point due to call toCPaintDC
c'tor
invalidated area will be validated and
CButton::OnPaint has no effect.
CButton::OnPaint();//}
Hope this clears your doubts.
Prasad Notifier using ATL | Operator new[],delete[][^]
-
Naveen R wrote:
Whats do you mean. If I didnt called the default procedure for WM_PAINT, then how will the button get painted?
You are confusing between painting a control and drawing a control. In case of of non-owner drawn control windows takes care of drawing/creating control.
WM_PAINT
message is meant to paint invalidated area. Now about calling base classOnPaint
. It simply does default painting routines and validates invalidated area. So Consider this function,void CMyButton::OnPaint()
{
CButton::OnPaint();//
//Here at above line invlaidated client area will be validated
and code following has no effect
CPaintDC dc(this); // device context for painting
//drawing routine follows
}Consider another scenario,
void CMyButton::OnPaint()
{
CPaintDC dc(this); // device context for painting
//drawing routine follows
//till this point due to call toCPaintDC
c'tor
invalidated area will be validated and
CButton::OnPaint has no effect.
CButton::OnPaint();//}
Hope this clears your doubts.
Prasad Notifier using ATL | Operator new[],delete[][^]
prasad_som wrote:
void CMyButton::OnPaint(){ CButton::OnPaint();// //Here at above line invlaidated client area will be validated and code following has no effect CPaintDC dc(this); // device context for painting //drawing routine follows}
I never said to create another CPaintDC below the CButton::OnPaint(); He can use CClientDC dc(this) to create a device context and do painting to it. Surely it will work.
nave
-
prasad_som wrote:
void CMyButton::OnPaint(){ CButton::OnPaint();// //Here at above line invlaidated client area will be validated and code following has no effect CPaintDC dc(this); // device context for painting //drawing routine follows}
I never said to create another CPaintDC below the CButton::OnPaint(); He can use CClientDC dc(this) to create a device context and do painting to it. Surely it will work.
nave
I already tried something with WM_PAINT, but it didn't work. And after reading this article in MSDN i give up on WM_PAINT... "Handling WM_PAINT The most extreme choice is to implement a WM_PAINT handler and do all the painting yourself." http://msdn2.microsoft.com/en-us/library/ms364048(vs.80).aspx
-
I want to draw a small arrow bitmap on top of already drawn button. I tried with calling default drawing proc before my code for drawing bitmap but it gives me some error.
OnDrawItem(int nIDCtl, LPDRAWITEMSTRUCT lpDrawItemStruct) { CDialog::OnDrawItem(nIDCtl, lpDrawItemStruct); HDC thdc = CreateCompatibleDC(lpDrawItemStruct->hDC); HGDIOBJ tobj = SelectObject(thdc, LoadBitmap(AfxGetInstanceHandle(), MAKEINTRESOURCE(IDB_ARROW_DOWN))); TransparentBlt(lpDrawItemStruct->hDC, lpDrawItemStruct->rcItem.right - 20, lpDrawItemStruct->rcItem.top + (lpDrawItemStruct->rcItem.bottom - lpDrawItemStruct->rcItem.top - 16) / 2, 16, 16, thdc, 0, 0, 16, 16, RGB(255, 0, 255)); SelectObject(thdc, tobj); DeleteDC(thdc); }
if i exclude "CDialog::OnDrawItem(nIDCtl, lpDrawItemStruct);" then code works, but there is no borders and caption text, just my bitmap.OK thank you all for your answers, i will try it out and let you know if it's woking. In case my english is so bad that nobody understood what i want to do :), I want to draw something like this http://img252.imageshack.us/img252/2254/codeprojectkc1.png
-
I already tried something with WM_PAINT, but it didn't work. And after reading this article in MSDN i give up on WM_PAINT... "Handling WM_PAINT The most extreme choice is to implement a WM_PAINT handler and do all the painting yourself." http://msdn2.microsoft.com/en-us/library/ms364048(vs.80).aspx
-
I will try.
-
prasad_som wrote:
void CMyButton::OnPaint(){ CButton::OnPaint();// //Here at above line invlaidated client area will be validated and code following has no effect CPaintDC dc(this); // device context for painting //drawing routine follows}
I never said to create another CPaintDC below the CButton::OnPaint(); He can use CClientDC dc(this) to create a device context and do painting to it. Surely it will work.
nave
Naveen R wrote:
I never said to create another CPaintDC below the CButton::OnPaint();
Yes, but it is what should be used in
OnPaint
messages.CClientDC
associated with whole client area of window, as opposed toCPaintDC
which is associated to invalidated rect only. So consider how logical is it to useCClientDC
there. BTW,havn't you come across this line whenever addedWM_PAINT
message handler throught class wizard ? // Do not call CButton::OnPaint() for painting messagesPrasad Notifier using ATL | Operator new[],delete[][^]
-
Can you explain how do you think that i should use CBitmapButton class? As i see that class only helps in inserting bitmaps on to buttons, but it still needs me to draw the button (because my bitmap is displayed only on one small portion of button).