如何使静态 window 在鼠标悬停时增加大小
How to make static window increase size on mouse hover
我有一堆 windows 在另一个 window 里面。
Child Windows 是在 MainWindow
class 的 CreateBoard()
方法中创建的。 MainWindow
和 GemWindow
的 Create()
方法来自 MS Documentation BaseWindow
摘要 class 并且这是每个 class 注册的地方致电 RegisterClass()
template <class DERIVED_TYPE>
class BaseWindow
{
public:
static LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
DERIVED_TYPE* pThis = NULL;
if (uMsg == WM_NCCREATE)
{
CREATESTRUCT* pCreate = (CREATESTRUCT*)lParam;
pThis = (DERIVED_TYPE*)pCreate->lpCreateParams;
SetWindowLongPtr(hwnd, GWLP_USERDATA, (LONG_PTR)pThis);
pThis->m_hwnd = hwnd;
}
else
{
pThis = (DERIVED_TYPE*)GetWindowLongPtr(hwnd, GWLP_USERDATA);
}
if (pThis)
{
//getting read access violation here why?
//because on resize you are not initializing tiles
//but resizing the thing
return pThis->HandleMessage(uMsg, wParam, lParam);
}
else
{
return DefWindowProc(hwnd, uMsg, wParam, lParam);
}
}
BaseWindow() : m_hwnd(NULL) { }
BOOL Create(
PCWSTR lpWindowName,
DWORD dwStyle,
DWORD dwExStyle = 0,
int x = CW_USEDEFAULT,
int y = CW_USEDEFAULT,
int nWidth = CW_USEDEFAULT,
int nHeight = CW_USEDEFAULT,
HWND hWndParent = 0,
HMENU hMenu = 0
)
{
WNDCLASS wc = { 0 };
wc.lpfnWndProc = DERIVED_TYPE::WindowProc;
wc.hInstance = GetModuleHandle(NULL);
wc.lpszClassName = ClassName();
RegisterClass(&wc);
m_hwnd = CreateWindowEx(
dwExStyle, ClassName(), lpWindowName, dwStyle, x, y,
nWidth, nHeight, hWndParent, hMenu, GetModuleHandle(NULL), this
);
return (m_hwnd ? TRUE : FALSE);
}
//returns handle
HWND Window() const { return m_hwnd; }
protected:
virtual PCWSTR ClassName() const = 0;
virtual LRESULT HandleMessage(UINT uMsg, WPARAM wParam, LPARAM lParam) = 0;
HWND m_hwnd;
};
CreateBoard()
方法在棋盘中创建宝石。
BOOL MainWindow::CreateBoard()
{
for (unsigned int i = 0; i < GetcGem(); i++)
{
for (unsigned int j = 0; j < GetcGem(); j++)
{
if (Gems[i][j].Create(L"gem", WS_CHILDWINDOW | WS_VISIBLE, NULL,
5 + i * GetsGem().cx + i * 10,
5 + j * GetsGem().cy + j * 10, GetsGem().cx, GetsGem().cy, Window(), NULL))
{
//pass from main window to Gem object
Gems[i][j].SetSize(GetsGem().cx, GetsGem().cy);
Gems[i][j].SetPosition(5 + i * GetsGem().cx + i * 10, 5 + j * GetsGem().cy + j * 10);
HBRUSH hbrush = CreateSolidBrush(RGB(125,125,125));
HBRUSH hOldBrush = (HBRUSH)SetClassLongPtr(Gems[i][j].Window(), GCLP_HBRBACKGROUND, (LONG_PTR)hbrush);
DeleteObject(hOldBrush);
InvalidateRect(Gems[i][j].Window(), NULL, TRUE);
}
else
{
return FALSE;
}
}
}
return TRUE;
}
我希望每个 child window 在鼠标悬停时将它们的大小分别增加 4 个像素。但是,在扩大尺寸后,它们会留下痕迹,有时将鼠标悬停在 single-window 上会增加整行或整列的尺寸。 Referer 为图片,例如:
我有每个 child window 的处理代码如下。 tracking
是 GemWindow
class
中的一个 static BOOL
BOOL GemWindow::tracking = false;
LRESULT GemWindow::HandleMessage(UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch (uMsg)
{
case WM_DESTROY:
DestroyWindow(Window());
break;
case WM_MOUSEMOVE:
{
if (!tracking) {
TrackMouse();
tracking = true;
}
}break;
case WM_MOUSEHOVER:
{
MoveWindow(Window(), GetSize().cx + 4, GetSize().cy + 4, GetPosition().x - 2, GetPosition().y - 2, TRUE);
InvalidateRect(Window(), NULL, TRUE);
OutputDebugString(L"MOUSE ENTERED\n");
}break;
case WM_MOUSELEAVE:
{
MoveWindow(Window(), GetSize().cx, GetSize().cy, GetPosition().x, GetPosition().y, TRUE);
InvalidateRect(Window(), NULL, TRUE);
OutputDebugString(L"MOUSE LEFT\n");
tracking = false;
}break;
case WM_PAINT:
{
PAINTSTRUCT ps;
HDC hdc = BeginPaint(m_hwnd, &ps);
//FillRect(hdc, &ps.rcPaint, CreateSolidBrush(color));
EndPaint(m_hwnd, &ps);
//OutputDebugString(L"PAINT\n");
}
return 0;
default:
return DefWindowProc(m_hwnd, uMsg, wParam, lParam);
}
return TRUE;
}
TrackMouse()
是 GemWindow
的一个方法,它初始化一个 TRACKMOUSEEVENT
并调用 TrackMouseEvent()
//method for tracking mouse
void TrackMouse(/*reusability enhanced if you add arguments in the future*/)
{
TRACKMOUSEEVENT tme;
tme.cbSize = sizeof(TRACKMOUSEEVENT);
tme.dwFlags = TME_HOVER | TME_LEAVE; //Type of events to track & trigger.
tme.dwHoverTime = 1; //How long the mouse has to be in the window to trigger a hover event.
tme.hwndTrack = Window();
TrackMouseEvent(&tme);
}
我认为这是因为我没有更新区域,但这样做并没有改变任何东西。我对这个错误感到困惑,想不出任何好的理由。
感谢所有花时间提供帮助的人。
BOOL MoveWindow(
HWND hWnd,
int X, //The new position of the left side of the window.
int Y, //The new position of the top of the window.
int nWidth, //The new width of the window.
int nHeight, //The new height of the window.
BOOL bRepaint
);
修改以下代码:
case WM_MOUSEHOVER:
{
// MoveWindow(Window(), GetSize().cx + 4, GetSize().cy + 4, GetPosition().x - 2, GetPosition().y - 2, TRUE);
MoveWindow(Window(), GetPosition().x - 2, GetPosition().y - 2, GetSize().cx + 4, GetSize().cy + 4, TRUE);
...
case WM_MOUSELEAVE:
{
// MoveWindow(Window(), GetSize().cx, GetSize().cy, GetPosition().x, GetPosition().y, TRUE);
MoveWindow(Window(), GetPosition().x, GetPosition().y, GetSize().cx, GetSize().cy, TRUE);
...
调试:
我有一堆 windows 在另一个 window 里面。
Child Windows 是在 MainWindow
class 的 CreateBoard()
方法中创建的。 MainWindow
和 GemWindow
的 Create()
方法来自 MS Documentation BaseWindow
摘要 class 并且这是每个 class 注册的地方致电 RegisterClass()
template <class DERIVED_TYPE>
class BaseWindow
{
public:
static LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
DERIVED_TYPE* pThis = NULL;
if (uMsg == WM_NCCREATE)
{
CREATESTRUCT* pCreate = (CREATESTRUCT*)lParam;
pThis = (DERIVED_TYPE*)pCreate->lpCreateParams;
SetWindowLongPtr(hwnd, GWLP_USERDATA, (LONG_PTR)pThis);
pThis->m_hwnd = hwnd;
}
else
{
pThis = (DERIVED_TYPE*)GetWindowLongPtr(hwnd, GWLP_USERDATA);
}
if (pThis)
{
//getting read access violation here why?
//because on resize you are not initializing tiles
//but resizing the thing
return pThis->HandleMessage(uMsg, wParam, lParam);
}
else
{
return DefWindowProc(hwnd, uMsg, wParam, lParam);
}
}
BaseWindow() : m_hwnd(NULL) { }
BOOL Create(
PCWSTR lpWindowName,
DWORD dwStyle,
DWORD dwExStyle = 0,
int x = CW_USEDEFAULT,
int y = CW_USEDEFAULT,
int nWidth = CW_USEDEFAULT,
int nHeight = CW_USEDEFAULT,
HWND hWndParent = 0,
HMENU hMenu = 0
)
{
WNDCLASS wc = { 0 };
wc.lpfnWndProc = DERIVED_TYPE::WindowProc;
wc.hInstance = GetModuleHandle(NULL);
wc.lpszClassName = ClassName();
RegisterClass(&wc);
m_hwnd = CreateWindowEx(
dwExStyle, ClassName(), lpWindowName, dwStyle, x, y,
nWidth, nHeight, hWndParent, hMenu, GetModuleHandle(NULL), this
);
return (m_hwnd ? TRUE : FALSE);
}
//returns handle
HWND Window() const { return m_hwnd; }
protected:
virtual PCWSTR ClassName() const = 0;
virtual LRESULT HandleMessage(UINT uMsg, WPARAM wParam, LPARAM lParam) = 0;
HWND m_hwnd;
};
CreateBoard()
方法在棋盘中创建宝石。
BOOL MainWindow::CreateBoard()
{
for (unsigned int i = 0; i < GetcGem(); i++)
{
for (unsigned int j = 0; j < GetcGem(); j++)
{
if (Gems[i][j].Create(L"gem", WS_CHILDWINDOW | WS_VISIBLE, NULL,
5 + i * GetsGem().cx + i * 10,
5 + j * GetsGem().cy + j * 10, GetsGem().cx, GetsGem().cy, Window(), NULL))
{
//pass from main window to Gem object
Gems[i][j].SetSize(GetsGem().cx, GetsGem().cy);
Gems[i][j].SetPosition(5 + i * GetsGem().cx + i * 10, 5 + j * GetsGem().cy + j * 10);
HBRUSH hbrush = CreateSolidBrush(RGB(125,125,125));
HBRUSH hOldBrush = (HBRUSH)SetClassLongPtr(Gems[i][j].Window(), GCLP_HBRBACKGROUND, (LONG_PTR)hbrush);
DeleteObject(hOldBrush);
InvalidateRect(Gems[i][j].Window(), NULL, TRUE);
}
else
{
return FALSE;
}
}
}
return TRUE;
}
我希望每个 child window 在鼠标悬停时将它们的大小分别增加 4 个像素。但是,在扩大尺寸后,它们会留下痕迹,有时将鼠标悬停在 single-window 上会增加整行或整列的尺寸。 Referer 为图片,例如:
我有每个 child window 的处理代码如下。 tracking
是 GemWindow
class
static BOOL
BOOL GemWindow::tracking = false;
LRESULT GemWindow::HandleMessage(UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch (uMsg)
{
case WM_DESTROY:
DestroyWindow(Window());
break;
case WM_MOUSEMOVE:
{
if (!tracking) {
TrackMouse();
tracking = true;
}
}break;
case WM_MOUSEHOVER:
{
MoveWindow(Window(), GetSize().cx + 4, GetSize().cy + 4, GetPosition().x - 2, GetPosition().y - 2, TRUE);
InvalidateRect(Window(), NULL, TRUE);
OutputDebugString(L"MOUSE ENTERED\n");
}break;
case WM_MOUSELEAVE:
{
MoveWindow(Window(), GetSize().cx, GetSize().cy, GetPosition().x, GetPosition().y, TRUE);
InvalidateRect(Window(), NULL, TRUE);
OutputDebugString(L"MOUSE LEFT\n");
tracking = false;
}break;
case WM_PAINT:
{
PAINTSTRUCT ps;
HDC hdc = BeginPaint(m_hwnd, &ps);
//FillRect(hdc, &ps.rcPaint, CreateSolidBrush(color));
EndPaint(m_hwnd, &ps);
//OutputDebugString(L"PAINT\n");
}
return 0;
default:
return DefWindowProc(m_hwnd, uMsg, wParam, lParam);
}
return TRUE;
}
TrackMouse()
是 GemWindow
的一个方法,它初始化一个 TRACKMOUSEEVENT
并调用 TrackMouseEvent()
//method for tracking mouse
void TrackMouse(/*reusability enhanced if you add arguments in the future*/)
{
TRACKMOUSEEVENT tme;
tme.cbSize = sizeof(TRACKMOUSEEVENT);
tme.dwFlags = TME_HOVER | TME_LEAVE; //Type of events to track & trigger.
tme.dwHoverTime = 1; //How long the mouse has to be in the window to trigger a hover event.
tme.hwndTrack = Window();
TrackMouseEvent(&tme);
}
我认为这是因为我没有更新区域,但这样做并没有改变任何东西。我对这个错误感到困惑,想不出任何好的理由。
感谢所有花时间提供帮助的人。
BOOL MoveWindow(
HWND hWnd,
int X, //The new position of the left side of the window.
int Y, //The new position of the top of the window.
int nWidth, //The new width of the window.
int nHeight, //The new height of the window.
BOOL bRepaint
);
修改以下代码:
case WM_MOUSEHOVER:
{
// MoveWindow(Window(), GetSize().cx + 4, GetSize().cy + 4, GetPosition().x - 2, GetPosition().y - 2, TRUE);
MoveWindow(Window(), GetPosition().x - 2, GetPosition().y - 2, GetSize().cx + 4, GetSize().cy + 4, TRUE);
...
case WM_MOUSELEAVE:
{
// MoveWindow(Window(), GetSize().cx, GetSize().cy, GetPosition().x, GetPosition().y, TRUE);
MoveWindow(Window(), GetPosition().x, GetPosition().y, GetSize().cx, GetSize().cy, TRUE);
...
调试: