Mfc 使用uxtheme.dll自定义绘图按钮

Mfc 使用uxtheme.dll自定义绘图按钮,mfc,cbutton,Mfc,Cbutton,我已经实现了从CButton继承的自定义按钮,并使用uxtheme.dll(DrawThemeBackground with BP_button)绘制它 一切正常,但我有两种状态(正常和按下),其中热状态是相同的。这意味着当用户将光标放在按钮上时,无论按钮状态如何(按下或未按下),都会以相同方式绘制 这对用户来说有点混乱,我想改变按钮在按下和热状态下的绘制方式。有人知道路吗 我也曾考虑过对整个绘图进行自定义,但按钮使用了渐变、边框、阴影等。因此,要实现自己绘制所有内容的相同外观和感觉并不容易。有

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

一切正常,但我有两种状态(正常和按下),其中热状态是相同的。这意味着当用户将光标放在按钮上时,无论按钮状态如何(按下或未按下),都会以相同方式绘制

这对用户来说有点混乱,我想改变按钮在按下和热状态下的绘制方式。有人知道路吗

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

提前谢谢

哈维尔


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

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

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

我所知道的唯一解决此问题的方法是使用“自定义绘图”,而不是“所有者绘图”。Custom draw随Windows 2000提供,但仅由comctrl32 6.0的按钮控件使用(因此Windows XP以后的版本),没有非常清晰的文档记录,MFC也没有特意提供支持

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

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

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


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

我所知道的唯一解决此问题的方法是使用“自定义绘制”,而不是“所有者绘制”。Custom draw随Windows 2000提供,但仅由comctrl32 6.0的按钮控件使用(因此Windows XP以后的版本),没有非常清晰的文档记录,MFC也没有特意提供支持

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

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

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


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

我终于找到了实现我想要做的事情的方法。这确实很容易

我打了两个电话来打回背景。第一个状态为PBS_按下,第二个状态为PBS_热。然后我做一个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);
当然,这不是全部代码,但我认为足以说明我的观点


谢谢。

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

我打了两个电话来打回背景。第一个状态为PBS_按下,第二个状态为PBS_热。然后我做一个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);
当然,这不是全部代码,但我认为足以说明我的观点


谢谢。

请看一下原始问题中我的注释。谢谢你的帮助。请看一下我在原始问题中的注释。谢谢你的帮助。我看过你的代码,但我不知道这是如何解决我的问题的。最后用PBS_HOT state调用DrawThemeBackground,并用金色边框(HOT state)绘制正常(未按下)按钮。我需要一种方法来绘制与