最近开始使用Windows API开发,我决定了一些交互性。所以计划是使用所有者绘制的按钮,当鼠标进入矩形区域时会改变背景颜色,当鼠标离开时会改变回原来的颜色。
我制作了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
的输出会以调试模式显示。
有什么方法可以解决这个问题吗?可能与鼠标跟踪有关吗?
我认为问题在于,当指针位于矩形内部时,按钮会被FillRect()
发送垃圾邮件。
感谢任何帮助。
答案 0 :(得分:2)
此问题现已解决。这是由于GDI泄漏。通过删除在父窗口过程中重复创建的画笔来解决该问题。