WinAPI管理画笔

时间:2016-09-02 22:18:44

标签: c winapi

我不知道如何处理用于着色静态文本背景的画笔。 起初一切看起来都很好,因为它应该是:

enter image description here

然而,在静态重绘多次后,它们会改为:

enter image description here

我还注意到这取决于我是否在每种情况下直接返回相同的画笔(用于调试)或使用不同情况下的实际代码(首次重绘后的灰色框)。

我的WM_CTLCOLORSTATIC消息处理如下所示:

case WM_CTLCOLORSTATIC:
    {
        HDC hdcStatic = (HDC) wParam;
        SetTextColor(hdcStatic, RGB(0,0,0));
        HBRUSH hbrDefault = CreateSolidBrush(RGB(255,255,255));
        return (INT_PTR)hbrDefault;

(简化调试)

我想这与使用DeleteObject()后释放画笔有关,但是当我需要返回画笔时我怎么能这样做,但我想在离开函数之前删除它们? MSDN资源没有帮助:WM_CTLCOLORSTATIC

编辑:我发现了我的错误。

我将我的画笔声明为全局变量:

HBRUSH hbrBkFoodCat[FOODCAT_LENGTH];
HBRUSH hbrDefault;

然后我在启动时将它们初始化为:

for(int i=0;i<FOODCAT_LENGTH;i++) {
    hbrBkFoodCat[i] = CreateSolidBrush(foodCatClr[i]);
}
HBRUSH hbrDefault = CreateSolidBrush(RGB(255,255,255));

正如您所看到的,我不小心再次声明了hbrDefault,但这次是本地变量,因此在处理消息时我得到了灰色框(NULL画笔)。 我尝试过的(我知道的愚蠢的想法)是在消息处理时初始化它们。由于我只是将初始化复制粘贴到处理中,它再次成为局部变量,但这次是在范围内&#39;为了回报。这导致我假设释放刷子出了问题,因为在获得那个灰色背景之前不得不重新绘制它(但仍然没有得到它)​​。

无论如何,谢谢大家的帮助!

2 个答案:

答案 0 :(得分:2)

该消息的MSDN文档说明你必须释放画笔。但是你不必每次都创建/释放它。只需创建一次并重复使用。当你不再需要它时释放它,但不在消息处理程序中。

答案 1 :(得分:0)

每次处理WM_CTLCOLORSTATIC消息时都不要创建新画笔。那是资源泄漏。在第一次创建静态文本控件时,或者第一次向您发送WM_CTLCOLORSTATIC时,创建画笔一次。继续为每条WM_CTLCOLORSTATIC消息返回相同的画笔:

HBRUSH hbrStaticBkg = NULL;

...

case WM_CTLCOLORSTATIC:
{
    HDC hdc = (HDC) wParam;
    SetTextColor(hdc, RGB(...));
    if (!hbrStaticBkg) hbrStaticBkg = CreateSolidBrush(RGB(...));
    return (LRESULT) hbrStaticBkg;
}

仅在销毁静态文本控件后销毁画笔。

DestroyWindow(hwndStatic);
if (hbrStaticBkg) {
    DeleteObject(hbrStaticBkg);
    hbrStaticBkg = NULL;
}

如果要在静态文本控件的生命周期内更改背景颜色,请销毁画笔并使控件无效以触发重绘,然后在请求时创建新画笔。

COLOREREF clrStaticText = RGB(0,0,0);
COLORREF clrStaticBkg = RGB(255,255,255);
HBRUSH hbrStaticBkg = NULL;

...

case WM_CTLCOLORSTATIC:
{
    HDC hdc = (HDC) wParam;
    SetTextColor(hdc, clrStaticText);
    if (!hbrStaticBkg) hbrStaticBkg = CreateSolidBrush(clrStaticBkg);
    return (LRESULT) hbrStaticBkg;
}

...

clrStaticText = RGB(...);
clrStaticBkg = RGB(...);
if (hbrStaticBkg) {
    DeleteObject(hbrStaticBkg);
    hbrStaticBkg = NULL;
}
InvalidateRect(hwndStatic, NULL, TRUE);