最近开始使用 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/