Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • World
  • Users
  • Groups
Skins
  • Light
  • Cerulean
  • Cosmo
  • Flatly
  • Journal
  • Litera
  • Lumen
  • Lux
  • Materia
  • Minty
  • Morph
  • Pulse
  • Sandstone
  • Simplex
  • Sketchy
  • Spacelab
  • United
  • Yeti
  • Zephyr
  • Dark
  • Cyborg
  • Darkly
  • Quartz
  • Slate
  • Solar
  • Superhero
  • Vapor

  • Default (No Skin)
  • No Skin
Collapse
Code Project
  1. Home
  2. General Programming
  3. C / C++ / MFC
  4. How to draw a bitmap on top of button?

How to draw a bitmap on top of button?

Scheduled Pinned Locked Moved C / C++ / MFC
graphicshelptutorialquestion
27 Posts 6 Posters 0 Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • I Igor Jerosimic

    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.

    P Offline
    P Offline
    prasad_som
    wrote on last edited by
    #3

    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[][^]

    1 Reply Last reply
    0
    • N Naveen

      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 Offline
      I Offline
      Igor Jerosimic
      wrote on last edited by
      #4

      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?

      N 1 Reply Last reply
      0
      • I Igor Jerosimic

        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?

        N Offline
        N Offline
        Naveen
        wrote on last edited by
        #5

        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

        P 1 Reply Last reply
        0
        • N Naveen

          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

          P Offline
          P Offline
          prasad_som
          wrote on last edited by
          #6

          Naveen R wrote:

          CButton::OnPaint();

          Should not call base class. :)

          Prasad Notifier using ATL | Operator new[],delete[][^]

          N 1 Reply Last reply
          0
          • P prasad_som

            Naveen R wrote:

            CButton::OnPaint();

            Should not call base class. :)

            Prasad Notifier using ATL | Operator new[],delete[][^]

            N Offline
            N Offline
            Naveen
            wrote on last edited by
            #7

            prasad_som wrote:

            Should not call base class

            why? I said him to do so in a non owner draw button.

            nave

            P 1 Reply Last reply
            0
            • N Naveen

              prasad_som wrote:

              Should not call base class

              why? I said him to do so in a non owner draw button.

              nave

              P Offline
              P Offline
              prasad_som
              wrote on last edited by
              #8

              It doesn't have any effect there.

              Prasad Notifier using ATL | Operator new[],delete[][^]

              N 1 Reply Last reply
              0
              • I Igor Jerosimic

                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.

                D Offline
                D Offline
                David Crow
                wrote on last edited by
                #9

                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

                1 Reply Last reply
                0
                • I Igor Jerosimic

                  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.

                  H Offline
                  H Offline
                  Hamid Taebi
                  wrote on last edited by
                  #10

                  See A Better Bitmap Button Class[^] if helpfuls


                  WhiteSky


                  T 1 Reply Last reply
                  0
                  • H Hamid Taebi

                    See A Better Bitmap Button Class[^] if helpfuls


                    WhiteSky


                    T Offline
                    T Offline
                    ThatsAlok
                    wrote on last edited by
                    #11

                    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

                    1 Reply Last reply
                    0
                    • P prasad_som

                      It doesn't have any effect there.

                      Prasad Notifier using ATL | Operator new[],delete[][^]

                      N Offline
                      N Offline
                      Naveen
                      wrote on last edited by
                      #12

                      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

                      P 1 Reply Last reply
                      0
                      • N Naveen

                        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

                        P Offline
                        P Offline
                        prasad_som
                        wrote on last edited by
                        #13

                        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 class OnPaint. 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 to CPaintDC 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[][^]

                        N 1 Reply Last reply
                        0
                        • P prasad_som

                          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 class OnPaint. 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 to CPaintDC 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[][^]

                          N Offline
                          N Offline
                          Naveen
                          wrote on last edited by
                          #14

                          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 P 2 Replies Last reply
                          0
                          • N Naveen

                            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 Offline
                            I Offline
                            Igor Jerosimic
                            wrote on last edited by
                            #15

                            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

                            N 1 Reply Last reply
                            0
                            • I Igor Jerosimic

                              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 Offline
                              I Offline
                              Igor Jerosimic
                              wrote on last edited by
                              #16

                              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

                              1 Reply Last reply
                              0
                              • I Igor Jerosimic

                                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

                                N Offline
                                N Offline
                                Naveen
                                wrote on last edited by
                                #17

                                Why dont you use the class CBitmapButton???

                                nave

                                I 2 Replies Last reply
                                0
                                • N Naveen

                                  Why dont you use the class CBitmapButton???

                                  nave

                                  I Offline
                                  I Offline
                                  Igor Jerosimic
                                  wrote on last edited by
                                  #18

                                  I will try.

                                  1 Reply Last reply
                                  0
                                  • N Naveen

                                    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

                                    P Offline
                                    P Offline
                                    prasad_som
                                    wrote on last edited by
                                    #19

                                    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 to CPaintDC which is associated to invalidated rect only. So consider how logical is it to use CClientDC there. BTW,havn't you come across this line whenever added WM_PAINT message handler throught class wizard ? // Do not call CButton::OnPaint() for painting messages

                                    Prasad Notifier using ATL | Operator new[],delete[][^]

                                    1 Reply Last reply
                                    0
                                    • N Naveen

                                      Why dont you use the class CBitmapButton???

                                      nave

                                      I Offline
                                      I Offline
                                      Igor Jerosimic
                                      wrote on last edited by
                                      #20

                                      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).

                                      N 1 Reply Last reply
                                      0
                                      • I Igor Jerosimic

                                        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 Offline
                                        I Offline
                                        Igor Jerosimic
                                        wrote on last edited by
                                        #21

                                        CImageButton class is very lousy way of replacing API function DrawFrameControl and i definitely don't need that... All that code is easily replaced with these 4 lines of code: CPaintDC dc(this); CRect rc; GetClientRect(&rc); dc.DrawFrameControl(&rc, DFC_BUTTON, DFCS_BUTTONPUSH); http://img214.imageshack.us/img214/6206/drawingfx6.png

                                        1 Reply Last reply
                                        0
                                        • I Igor Jerosimic

                                          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).

                                          N Offline
                                          N Offline
                                          Naveen
                                          wrote on last edited by
                                          #22

                                          that's a problem :) .. I will tell you another way. Make the button owner draw, in the DrawItem Function,do as follows DrawItem() { DrawFrameControl();// This function will draw a statndard button. // here , draw your bitmap }

                                          nave

                                          I 1 Reply Last reply
                                          0
                                          Reply
                                          • Reply as topic
                                          Log in to reply
                                          • Oldest to Newest
                                          • Newest to Oldest
                                          • Most Votes


                                          • Login

                                          • Don't have an account? Register

                                          • Login or register to search.
                                          • First post
                                            Last post
                                          0
                                          • Categories
                                          • Recent
                                          • Tags
                                          • Popular
                                          • World
                                          • Users
                                          • Groups