0

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

一切正常,但我有两种状态(正常和按下),热状态是相同的。这意味着当用户将光标放在按钮上时,无论按钮状态(按下与否),它都会被绘制。

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

我也考虑过对整个绘图进行自定义,但按钮使用渐变、边框、阴影等。所以要实现相同的外观和感觉自己绘制所有东西并不容易。有没有办法找到dll的源代码或者知道怎么做?

提前致谢。

哈维尔

注意:我想我可以通过使用 CMFCButton 并覆盖 OnDraw 方法来实现我想要做的事情。让控件在 OnDrawBorder 上绘制按钮,然后自己绘制内部按钮。但我需要知道控件在按下时如何绘制内部按钮。这是一个渐变,我猜不出它是如何完成的。有人有线索吗?

4

3 回答 3

1

我知道真正解决这个问题的唯一方法是使用“自定义抽奖”,而不是“所有者抽奖”。自定义绘图随 Windows 2000 一起提供,但仅由 comctrl32 6.0(因此 Windows XP 及更高版本)的按钮控件使用,没有非常清楚的文档记录,也不是 MFC 竭尽全力支持的东西。

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

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

不幸的是,这是一个有点模糊的答案:演示使用自定义绘图的按钮所需的代码量有点太多,无法输入到这些答案框中!我确实有一个演示此类技术的项目,使用自定义绘制按钮(在旧 Windows 版本上回退到所有者绘制),该按钮向按钮添加了一个小箭头。您可以通过获取查看源代码

Windows_UI_source.zip

打开它并查看“DropArrowButton”类。重要的一点是 OnCustomDraw() 处理程序及其辅助函数 DrawControl():它们在各个按钮绘制阶段被调用,并使用 UxTheme 适当地绘制控件。

于 2010-05-11T15:19:12.470 回答
1

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

于 2010-05-04T13:52:41.427 回答
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);

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

谢谢。

于 2010-05-12T06:35:07.890 回答