c++ - Windows API : Why does button hover effect gets jammed after a while?

标签 c++ windows button

最近开始使用 Windows API 进行开发,我认为需要一些交互性。因此计划是使用 Owner Drawn 按钮,当鼠标进入其矩形区域时,该按钮会更改背景颜色,并在鼠标离开时变回原始颜色。

我制作了 3 个这样的按钮,并使用它们自己的自定义窗口过程对它们进行了子类化。现在,因为确实不存在 WM_MOUSEENTER 消息,所以我使用了 WM_MOUSEMOVE 和一些鼠标跟踪来用某种颜色填充窗口。这基本上意味着每次光标在窗口内移动时矩形都会被填充。

当鼠标指针移到按钮矩形之外时,我还使用 WM_MOUSELEAVE 来填充按钮。

一开始这似乎工作正常,但过了一会儿,矩形填充将停止,背景将停留在悬停颜色或默认颜色。

这是代码

#ifndef UWMENU_H_INCLUDED
#define UWMENU_H_INCLUDED
#endif // UWMENU_H_INCLUDED

#include <iostream>
using namespace std;

LRESULT CALLBACK DBWndProc(HWND, UINT, WPARAM, LPARAM);
WNDPROC DBWndProcOld[3];

class UWMenu{
    public:
    //WINDOW PROCEDURE FOR NEWS BUTTON
    static LRESULT CALLBACK DBWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam){
        HBRUSH BG_btnOne = CreateSolidBrush(NAV_BTN_DEF_CLR);
        HBRUSH BG_btnOneOver = CreateSolidBrush(NAV_BTN_OVER_CLR);

        int btnID = GetDlgCtrlID(hwnd);
        cout << btnID << "\n";

        switch(msg){
            case WM_MOUSEMOVE:{

                cout << "Mouse is hovering over button\n";
                SetCursor(LoadCursor(NULL, IDC_HAND));
                HDC hdc = GetDC(hwnd);
                RECT rc;
                rc.left = 0;                            //Top left X coordinate of button's rectangular area
                rc.top = 0;                             //Top left Y coordinate of button's rectangular area
                rc.right = NAV_BTN_WIDTH;               //Bottom right X coordinate of button's rectangular area
                rc.bottom = NAV_BTN_HEIGHT;             //Bottom right Y coordinate of button's rectangular area

                printf("Repainting button background color\n");
                FillRect(hdc, &rc, BG_btnOneOver);
                SetTextColor(hdc, RGB(255,255,255));
                SetBkMode(hdc, TRANSPARENT);

                if(btnID == NBID_NEWS){DrawText(hdc, TXT_BN_NEWS, -1, &rc, DT_SINGLELINE | DT_CENTER | DT_VCENTER);}
                if(btnID == NBID_TOOLS){DrawText(hdc, TXT_BN_TOOLS, -1, &rc, DT_SINGLELINE | DT_CENTER | DT_VCENTER);}
                if(btnID == NBID_EDITOR){DrawText(hdc, TXT_BN_EDITORS, -1, &rc, DT_SINGLELINE | DT_CENTER | DT_VCENTER);}
                ReleaseDC(hwnd, hdc);

                TRACKMOUSEEVENT tme;
                tme.cbSize = sizeof(TRACKMOUSEEVENT);
                tme.dwFlags = TME_LEAVE;
                tme.hwndTrack = hwnd;
                tme.dwHoverTime = HOVER_DEFAULT;
                TrackMouseEvent(&tme);
            }
            break;

            case WM_MOUSELEAVE:{
                printf("You left me\n");
                SetCursor(LoadCursor(NULL, IDC_ARROW));

                HDC hdc = GetDC(hwnd);
                RECT rc;
                rc.left = 0;                                //Top left X coordinate of button's rectangular area
                rc.top = 0;                                 //Top left Y coordinate of button's rectangular area
                rc.right = NAV_BTN_WIDTH;                   //Bottom right X coordinate of button's rectangular area
                rc.bottom = NAV_BTN_HEIGHT;                 //Bottom right Y coordinate of button's rectangular area

                FillRect(hdc, &rc, BG_btnOne);
                SetTextColor(hdc, RGB(255,255,255));
                SetBkMode(hdc, TRANSPARENT);
                if(btnID == NBID_NEWS){DrawText(hdc, TXT_BN_NEWS, -1, &rc, DT_SINGLELINE | DT_CENTER | DT_VCENTER);}
                if(btnID == NBID_TOOLS){DrawText(hdc, TXT_BN_TOOLS, -1, &rc, DT_SINGLELINE | DT_CENTER | DT_VCENTER);}
                if(btnID == NBID_EDITOR){DrawText(hdc, TXT_BN_EDITORS, -1, &rc, DT_SINGLELINE | DT_CENTER | DT_VCENTER);}
                ReleaseDC(hwnd, hdc);

                TRACKMOUSEEVENT tme;
                tme.cbSize = sizeof(TRACKMOUSEEVENT);
                tme.dwFlags = TME_CANCEL;
                tme.hwndTrack = hwnd;
                tme.dwHoverTime = HOVER_DEFAULT;
                TrackMouseEvent(&tme);
            }
            break;
        }
        return CallWindowProc(DBWndProcOld[btnID-200], hwnd, msg, wParam, lParam);
    }
};

mouse_move 消息正在被处理,当鼠标移动到按钮上时,printf()cout 的输出将在 Debug模式下显示。

有什么办法可以解决这个问题吗?也许与鼠标跟踪有关?

我认为问题在于,当指针位于其矩形内时,该按钮有点被 FillRect() 垃圾邮件淹没。

感谢任何帮助。

最佳答案

这个问题现在已经解决了。这是由于 GDI 泄漏造成的。通过删除在父窗口过程中重复创建的画笔解决了该问题。

关于c++ - Windows API : Why does button hover effect gets jammed after a while?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35795469/

相关文章:

c++ - 关于 C++ 中的 exit() 函数

c++ - 模板和类继承

windows - 从卷偏移或扇区获取文件名(Windows)

android - react native 运行 Hello World

c# - 如何阻止按钮控件中的文本在 Winforms 中将单词分成多行?

c++ - 如何在不包含头文件和重复项的情况下调用 C++ 函数?

C++如何同时计算和写入

.net - 如何在显示 UAC 对话框窗口时运行我的应用程序?

ios - 用动画显示按钮网格?

javascript - 按钮重定向到不同的页面