Question

I have implemented my custom button inheriting from CButton and drawing it by using uxtheme.dll (DrawThemeBackground with BP_PUSHBUTTON).

Everything works fine but I have two statuses (Normal and Pressed) which Hot status is the same. It means when the user places the cursor over the button it is drawn alike regardless the button status (Pressed or not).

This is a bit confusing to the user and I would like to change the way the button is drawn in Pressed & Hot status. Does anybody know a way?

I have also thought about custumizing the whole drawing but the buttons use gradients, borders, shadows, etc. So it is not easy to achive the same look&feel drawing everything by myself. Is there a way to find the source code of the dll or know how to do it?

Thanks in advance.

Javier

Note: I think I could be able to achive what I want to do by using CMFCButton and overriding the OnDraw method. Let the control draw the button on OnDrawBorder and then drawing the inside button myself. But I need to know how the control draws the inside button when pressed. It is a gradient and I can't guess how it's done. Does anybody have a clue?

Was it helpful?

Solution 3

I finally figured out how to achive what I want to do. It's pretty easy indeed.

I use two calls to DrawThemeBackground. The first one with PBS_PRESSED and the second one with state PBS_HOT. Then I make a ExcludeClipRect to avoid from drawing over the center of the button.

Something like this:

        DrawThemeBackground(    hTheme,
                                pCustomDraw->hdc, 
                                BP_PUSHBUTTON,
                                PBS_PRESSED,
                                &pCustomDraw->rc, 
                                NULL);

        CDC *pDC = CDC::FromHandle(pCustomDraw->hdc);

        CRect rectClient;
        GetClientRect(rectClient);
        CRect rectInternal = rectClient;

        rectInternal.DeflateRect(4,4);
        pDC->SelectClipRgn(NULL);
        pDC->ExcludeClipRect(&rectInternal);

        DrawThemeBackground(    hTheme,
                                pCustomDraw->hdc, 
                                BP_PUSHBUTTON,
                                PBS_HOT,
                                &pCustomDraw->rc, 
                                NULL);

        pDC->SelectClipRgn(NULL);

Of course this is not the whole code but I think is enough to make my point.

Thanks.

OTHER TIPS

In answer to your second question, if you derive from CMFCButton instead of CButton you can override OnDraw() or OnDrawText() instead of the usual DrawItem(). That way the default button background will be drawn, and then your drawing code is executed.

The only way I know of to really tackle this is to use 'custom draw', rather than 'owner draw'. Custom draw came in with Windows 2000, but is only used by button controls with comctrl32 6.0 (so Windows XP onwards), isn't very clearly documented, and isn't something MFC goes out of its way to support.

Anyway, the good thing about custom draw is that it lets you hook in at various points in the drawing process, unlike owner draw, which makes you deal with the whole thing. Have a look in MSDN at the NM_CUSTOMDRAW notification message.

For the other part of your problem, detecting the 'hot' state, the easiest way to do this is to use WM_MOUSEMOVE messages and the TrackMouseEvent() function to track whether the mouse is over your button.

Unfortunately this is a bit of a vague answer: the amount of code you need to demonstrate a button that uses custom draw is a bit too much to type into these answer boxes! I do have a project that demonstrates such techniques, using a custom draw button (falling back to owner draw on older Windows versions) that adds a little arrow to the button. You can have a look at the source code by getting

Windows_UI_source.zip

Open it and have a look at the "DropArrowButton" class. The important bit is the OnCustomDraw() handler and its helper function DrawControl(): these get called at the various button drawing phases, and use UxTheme to draw the control appropriately.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top