当一个点(应该)在一个矩形内时,PtInRect 不拾取
PtInRect not picking up when a point (should) be within a rect
我有一个 Win32 程序,我需要在其中检测按钮是否已被单击,但是由于按钮位于另一个控件(选项卡控件)的顶部,该按钮的默认功能已被破坏。我的解决方案是尝试手动检测点击,如下所示:
//within WM_NOTIFY:
case TCN_SELCHANGING:
{
RECT rcButton;
POINT pt;
int i = 0;
ScreenToClient(hWnd, &pt); //"hWnd" is the main window
GetClientRect(button, &rcButton); //"button" is the button's HWND handler
if (PtInRect(&rcButton, pt)) {
MessageBox(hWnd, L"Wonderful! Button was clicked!", L"Info", MB_OK | MB_ICONINFORMATION);
return TRUE; //stop selection from changing if button was clicked
}
return FALSE; //otherwise, allow selection to change
}
这似乎不起作用,因为我没有看到消息框。
我在文档中读到我可能需要“规范化”我的 RECT
。是这里的问题吗?如果可以,我该怎么做?
感谢您的帮助。
您的 POINT pt;
变量在您调用 ScreenToClient(hWnd, &pt);
时 未初始化 ,因此在调用 PtInRect(&rcButton, pt)
时它的值是无效的。在输入时,您必须指定要 ScreenToClient()
转换为客户端坐标的屏幕坐标。
您可以使用GetCursorPos()
获取鼠标光标的当前屏幕坐标。
但是,您正在尝试将屏幕坐标转换为主 window 中的客户端坐标,而不是在按钮中。尝试更像这样的东西:
//within WM_NOTIFY:
case TCN_SELCHANGING:
{
POINT pt;
RECT rcButton;
GetCursorPos(&pt);
ScreenToClient(button, &pt);
GetClientRect(button, &rcButton);
if (PtInRect(&rcButton, pt))
{
MessageBox(hWnd, L"Wonderful! Button was clicked!", L"Info", MB_OK | MB_ICONINFORMATION);
return TRUE; //stop selection from changing if button was clicked
}
return FALSE; //otherwise, allow selection to change
}
或者,您可以获取按钮的客户端矩形,将其转换为屏幕坐标,然后将其与鼠标的屏幕坐标进行比较:
//within WM_NOTIFY:
case TCN_SELCHANGING:
{
RECT rcButton;
POINT pt;
GetClientRect(button, &rcButton);
MapWindowPoints(button, NULL, (LPPOINT)&rcButton, 2);
GetCursorPos(&pt);
if (PtInRect(&rcButton, pt))
{
MessageBox(hWnd, L"Wonderful! Button was clicked!", L"Info", MB_OK | MB_ICONINFORMATION);
return TRUE; //stop selection from changing if button was clicked
}
return FALSE; //otherwise, allow selection to change
}
话虽如此,可以使用鼠标或键盘更改选项卡选择。在您的情况下,您只需要单击鼠标,但 TCN_SELCHANGING
不会告诉您选项卡选择发生变化的原因。为此,您必须子类化选项卡控件以处理 left-click 的 WM_LBUTTONDOWN
消息和箭头、Home 和 End 键的 WM_KEYDOWN
消息。然后您可以相应地标记您的 TCN_SELCHANGING
处理程序。
我有一个 Win32 程序,我需要在其中检测按钮是否已被单击,但是由于按钮位于另一个控件(选项卡控件)的顶部,该按钮的默认功能已被破坏。我的解决方案是尝试手动检测点击,如下所示:
//within WM_NOTIFY:
case TCN_SELCHANGING:
{
RECT rcButton;
POINT pt;
int i = 0;
ScreenToClient(hWnd, &pt); //"hWnd" is the main window
GetClientRect(button, &rcButton); //"button" is the button's HWND handler
if (PtInRect(&rcButton, pt)) {
MessageBox(hWnd, L"Wonderful! Button was clicked!", L"Info", MB_OK | MB_ICONINFORMATION);
return TRUE; //stop selection from changing if button was clicked
}
return FALSE; //otherwise, allow selection to change
}
这似乎不起作用,因为我没有看到消息框。
我在文档中读到我可能需要“规范化”我的 RECT
。是这里的问题吗?如果可以,我该怎么做?
感谢您的帮助。
您的 POINT pt;
变量在您调用 ScreenToClient(hWnd, &pt);
时 未初始化 ,因此在调用 PtInRect(&rcButton, pt)
时它的值是无效的。在输入时,您必须指定要 ScreenToClient()
转换为客户端坐标的屏幕坐标。
您可以使用GetCursorPos()
获取鼠标光标的当前屏幕坐标。
但是,您正在尝试将屏幕坐标转换为主 window 中的客户端坐标,而不是在按钮中。尝试更像这样的东西:
//within WM_NOTIFY:
case TCN_SELCHANGING:
{
POINT pt;
RECT rcButton;
GetCursorPos(&pt);
ScreenToClient(button, &pt);
GetClientRect(button, &rcButton);
if (PtInRect(&rcButton, pt))
{
MessageBox(hWnd, L"Wonderful! Button was clicked!", L"Info", MB_OK | MB_ICONINFORMATION);
return TRUE; //stop selection from changing if button was clicked
}
return FALSE; //otherwise, allow selection to change
}
或者,您可以获取按钮的客户端矩形,将其转换为屏幕坐标,然后将其与鼠标的屏幕坐标进行比较:
//within WM_NOTIFY:
case TCN_SELCHANGING:
{
RECT rcButton;
POINT pt;
GetClientRect(button, &rcButton);
MapWindowPoints(button, NULL, (LPPOINT)&rcButton, 2);
GetCursorPos(&pt);
if (PtInRect(&rcButton, pt))
{
MessageBox(hWnd, L"Wonderful! Button was clicked!", L"Info", MB_OK | MB_ICONINFORMATION);
return TRUE; //stop selection from changing if button was clicked
}
return FALSE; //otherwise, allow selection to change
}
话虽如此,可以使用鼠标或键盘更改选项卡选择。在您的情况下,您只需要单击鼠标,但 TCN_SELCHANGING
不会告诉您选项卡选择发生变化的原因。为此,您必须子类化选项卡控件以处理 left-click 的 WM_LBUTTONDOWN
消息和箭头、Home 和 End 键的 WM_KEYDOWN
消息。然后您可以相应地标记您的 TCN_SELCHANGING
处理程序。