2010-05-04 102 views
0

我已经实现了我的自定义按钮继承自CButton并使用uxtheme.dll(DrawThemeBackground与BP_PUSHBUTTON)绘制它。使用uxtheme.dll自定义绘制按钮

一切工作正常,但我有两个状态(普通和按下),热状态是相同的。这意味着当用户将光标放在按钮上时,无论按钮状态如何(按下或不按下),它都会被画出。

这对用户来说有点令人困惑,我想改变按钮在Pressed & Hot状态下的绘制方式。有人知道一种方式吗?

我也想过定制整个绘图,但按钮使用渐变,边框,阴影等。因此,要自己绘制所有东西并不容易。有没有办法找到DLL的源代码或知道如何做到这一点?

在此先感谢。

哈维尔

注:我想我可能能才达到我想要使用CMFCButton并重写OnDraw的方法来做。让控件在OnDrawBorder上绘制按钮,然后自己绘制内部按钮。但是我需要知道按下时控件如何绘制内部按钮。这是一个渐变,我无法猜测它是如何完成的。有人有线索吗?

回答

1

我终于想出了如何实现我想要做的事情。确实很容易。

我使用两次调用DrawThemeBackground。第一个是PBS_PRESSED,第二个是PBS_HOT。然后我做一个ExcludeClipRect以避免在按钮的中心上画图。

事情是这样的:

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

当然,这并不是全部的代码,但我认为这是足以让我的观点。

谢谢。

1

在回答你的第二个问题,如果你从CMFCButton而不是CButton派生可以覆盖OnDraw()OnDrawText()而不是通常的DrawItem()。这样就会绘制默认的按钮背景,然后执行您的绘图代码。

+0

请看看我在原始问题中的注释。并感谢您的帮助。 – 2010-05-05 08:35:35

1

我知道真正解决这个问题的唯一方法是使用'自定义绘制',而不是'所有者绘制'。自定义绘图与Windows 2000一起提供,但只有通过comctrl32 6.0(所以Windows XP以上版本)的按钮控件才能使用,并没有非常明确的文档记载,并且MFC不会支持它。

无论如何,关于自定义绘制的好处在于它可以让你在绘制过程中的各个点上挂钩,而不像所有者绘制,这使得你处理整个事情。在NM_CUSTOMDRAW通知消息中查看MSDN。

对于问题的其他部分,检测'热'状态,最简单的方法是使用WM_MOUSEMOVE消息和TrackMouseEvent()函数来跟踪鼠标是否在按钮上。

不幸的是,这是一个模糊的答案:你需要演示一个使用自定义绘制按钮的代码数量太多,无法输入到这些答案框中!我有一个演示这种技术的项目,使用自定义绘制按钮(回退到老版本的Windows版本的所有者绘制),向按钮添加一个小箭头。您可以通过获取

Windows_UI_source.zip

打开它看看源代码,看看在“DropArrowButton”级。重要的是OnCustomDraw()处理程序及其帮助程序函数DrawControl():它们在各种按钮绘制阶段被调用,并使用UxTheme来适当地绘制控件。

+0

我看了一下你的代码,但我没有看到如何解决我的问题。您最终以PBS_HOT状态调用DrawThemeBackground并绘制带有金色边框(热状态)的正常(未按下)按钮。我需要一种方法来绘制带有金色边框(热状态)的按下(PBS_PRESSED)状态。无论如何非常感谢你。 – 2010-05-12 05:57:09

+0

我的错误:我误解了你的问题。我不认为有什么办法可以让DrawThemeBackground()完成你想要的任何事情:我可以建议的所有方法都是按下背景,然后将alpha混合到“热”状态矩形中。如果你总是这样做的“热”矩形,你应该可以得到一个可以通过的效果。 – DavidK 2010-05-12 06:16:34

+0

这与我所做的相似。事实上,如果没有使用AlphaBlend,效果相当不错(如果有人抱怨,我会试一试!)。不幸的是,当我看到您的评论时,我已经接受了我的回答,我无法取消我的接受。否则我会接受你的回答。谢谢。 – 2010-05-12 06:39:00