Thread: Owner-draw button

  1. #1
    Reverse Engineer maxorator's Avatar
    Join Date
    Aug 2005
    Location
    Estonia
    Posts
    2,318

    Owner-draw button

    How can I make a simple owner-draw button?
    For example an owner-draw button with gradient?

    C++, Win32, Dev-C++

  2. #2
    erstwhile
    Join Date
    Jan 2002
    Posts
    2,227
    Give the button the BS_OWNERDRAW style, handle the WM_DRAWITEM message of the parent window and use GradientFill to effect the smooth shading.

    msdn example of owner drawn button.
    CProgramming FAQ
    Caution: this person may be a carrier of the misinformation virus.

  3. #3
    Reverse Engineer maxorator's Avatar
    Join Date
    Aug 2005
    Location
    Estonia
    Posts
    2,318
    Wow, thanks. I wonder why I didn't find articles about this from google...

  4. #4
    Reverse Engineer maxorator's Avatar
    Join Date
    Aug 2005
    Location
    Estonia
    Posts
    2,318
    Now, do you know any tutorials on owner-draw buttons? I couldn't find any, all of them were using MFC. I already looked MSDN example... wasn't very helpful. I made an owner-draw button, but I don't know how to attach a normal button border onto it and I don't really know, how to make the appearance change when the button is pressed.

  5. #5
    erstwhile
    Join Date
    Jan 2002
    Posts
    2,227
    The whole point of an owner drawn button is that you draw it yourself. You can either do this entirely dynamically at runtime or prepare a 'button up' and a 'button pressed' bitmap and simply blit those to the dc of the DRAWITEMSTRUCT (WM_DRAWITEM message LPARAM); the msdn example I provided a link to in my initial post should show you how to respond to the WM_DRAWITEM message. The rest is really up to you.

    If you need more specific examples, I suggest you search the web; you should have more than enough keywords now to make an effective search.

    This board, too, should have some sample code and further discussion that might be of interest.
    CProgramming FAQ
    Caution: this person may be a carrier of the misinformation virus.

  6. #6
    Reverse Engineer maxorator's Avatar
    Join Date
    Aug 2005
    Location
    Estonia
    Posts
    2,318
    I got the basic thing working (an owner-draw button with gradient). Yes, I searched the board, found my solution to the "button pressed" thing. I wan't to make the owner-draw button without using bitmaps, but I don't know how to make it have the normal border of a button.

    By the way, can I make an owner-draw caption?
    Last edited by maxorator; 09-12-2006 at 08:34 AM.

  7. #7
    erstwhile
    Join Date
    Jan 2002
    Posts
    2,227
    The way that windows does it is by maintaining two or three different shades for the button edges. You'll need to experiment to find shades that are appropriate for your needs but it might be worthwhile to experiment by emulating the drawing of a normal, non-winxp styled button using the system colours to see for yourself how it's done.
    CProgramming FAQ
    Caution: this person may be a carrier of the misinformation virus.

  8. #8
    Reverse Engineer maxorator's Avatar
    Join Date
    Aug 2005
    Location
    Estonia
    Posts
    2,318
    And draw those pixels out one by one?

  9. #9
    erstwhile
    Join Date
    Jan 2002
    Posts
    2,227
    Look to the available gdi functions - there's lots of options there(for example FrameRect, ExtFloodFill etc).

    >>By the way, can I make an owner-draw caption?<<

    Use TextOut, ExtTextOut, DrawText etc.
    CProgramming FAQ
    Caution: this person may be a carrier of the misinformation virus.

  10. #10
    Reverse Engineer maxorator's Avatar
    Join Date
    Aug 2005
    Location
    Estonia
    Posts
    2,318
    What I want is the opposite of WS_EX_CLIENTEDGE style...
    With FrameRect I can make single-dimensional border only and I really can't get ExtFloodFill working.
    Last edited by maxorator; 09-12-2006 at 09:22 AM.

  11. #11
    Yes, my avatar is stolen anonytmouse's Avatar
    Join Date
    Dec 2002
    Posts
    2,544
    Have a look at DrawFrameControl or DrawEdge for the frame. I would avoid ExtFloodFill in favour of FillRect or whatever drawing you require.

  12. #12
    Reverse Engineer maxorator's Avatar
    Join Date
    Aug 2005
    Location
    Estonia
    Posts
    2,318
    Ok, thanks... I'll test them out as soon as possible.

  13. #13
    Reverse Engineer maxorator's Avatar
    Join Date
    Aug 2005
    Location
    Estonia
    Posts
    2,318
    DrawEdge was very useful. Thanks for help.
    I can just use EDGE_RAISED with the button and when it's pressed, I can use EDGE_SUNKEN.

    But I still have a problem with it. If you click multiple times on it very quickly, it doesn't react on some clicks. This does not happen to normal buttons...
    Last edited by maxorator; 09-13-2006 at 05:47 AM.

  14. #14
    erstwhile
    Join Date
    Jan 2002
    Posts
    2,227
    This simplest way to resolve this issue is to subclass the button control and handle its WM_LBUTTONDBLCLK message by forwarding it to the button control's default, system WM_LBUTTONDOWN handler(use CallWindowProc). This effectively means that both single and double-clicks are treated the same by the button control.

    msdn: subclassing.
    CProgramming FAQ
    Caution: this person may be a carrier of the misinformation virus.

  15. #15
    Reverse Engineer maxorator's Avatar
    Join Date
    Aug 2005
    Location
    Estonia
    Posts
    2,318
    First declared these variables:
    Code:
    LRESULT CALLBACK ButtonProcedure(HWND hwnd,UINT message,WPARAM wParam,LPARAM lParam);
    WNDPROC OldWndProc;
    After creating the button with CreateWindowEx subclassed it (controls[0] is the handle to my button):
    Code:
    OldWndProc=(WNDPROC)SetWindowLongPtr(controls[0],GWLP_WNDPROC,(LONG_PTR)ButtonProcedure);
    Then added WM_LBUTTONDBLCLK message handler to the main window procedure:
    Code:
    		case WM_LBUTTONDBLCLK:
    			CallWindowProc(OldWndProc,controls[0],WM_LBUTTONDOWN,wParam,lParam);
    			break;
    This is the button procedure:
    Code:
    LRESULT CALLBACK ButtonProcedure (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam){
    	switch (message){
            default:
                return DefWindowProc (hwnd, message, wParam, lParam);
        }
        return 0;
    }
    And then the button just disappeared! I thought maybe I need to put the WM_DRAWITEM to the button procedure, but that didn't help. What am I doing wrong?

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Problems defining classes
    By esmeco in forum C++ Programming
    Replies: 47
    Last Post: 10-24-2007, 01:13 PM
  2. My BS_OWNERDRAW button draw as white when clicked...
    By Jonathan Beaubi in forum Windows Programming
    Replies: 1
    Last Post: 08-16-2007, 10:41 AM
  3. owner draw...
    By Devil Panther in forum Windows Programming
    Replies: 6
    Last Post: 03-12-2004, 01:19 PM
  4. owner draw?
    By Devil Panther in forum Windows Programming
    Replies: 4
    Last Post: 02-29-2004, 11:08 AM
  5. Owner draw button with bitmap
    By Mithoric in forum Windows Programming
    Replies: 2
    Last Post: 11-30-2003, 03:14 PM