How can I make a simple owner-draw button?
For example an owner-draw button with gradient?
C++, Win32, Dev-C++
How can I make a simple owner-draw button?
For example an owner-draw button with gradient?
C++, Win32, Dev-C++
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.
Wow, thanks. I wonder why I didn't find articles about this from google...
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.
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.
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.
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.
And draw those pixels out one by one?
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.
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.
Have a look at DrawFrameControl or DrawEdge for the frame. I would avoid ExtFloodFill in favour of FillRect or whatever drawing you require.
Ok, thanks... I'll test them out as soon as possible.
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.
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.
First declared these variables:
After creating the button with CreateWindowEx subclassed it (controls[0] is the handle to my button):Code:LRESULT CALLBACK ButtonProcedure(HWND hwnd,UINT message,WPARAM wParam,LPARAM lParam); WNDPROC OldWndProc;
Then added WM_LBUTTONDBLCLK message handler to the main window procedure:Code:OldWndProc=(WNDPROC)SetWindowLongPtr(controls[0],GWLP_WNDPROC,(LONG_PTR)ButtonProcedure);
This is the button procedure:Code:case WM_LBUTTONDBLCLK: CallWindowProc(OldWndProc,controls[0],WM_LBUTTONDOWN,wParam,lParam); break;
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?Code:LRESULT CALLBACK ButtonProcedure (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam){ switch (message){ default: return DefWindowProc (hwnd, message, wParam, lParam); } return 0; }