Reputation: 57
I have a Win32 program in which I need to detect if a button has been clicked, however the button's default functionality has been broken due to it being located on top of another control (a tab control). My solution to this has been to try and detect a click manually, like so:
//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
}
This doesn't seem to work, as I do not see the meassage box.
I read in the documentation that I may need to "normalize" my RECT
s. Is that the problem here? If so, how do I do so?
Thank you for your help.
Upvotes: 0
Views: 386
Reputation: 597101
Your POINT pt;
variable is uninitialized when you are calling ScreenToClient(hWnd, &pt);
, and thus its value is invalid for use when calling PtInRect(&rcButton, pt)
. On input, you have to specify the screen coordinates that you want ScreenToClient()
to convert into client coordinates.
You can use GetCursorPos()
to get the current screen coordinates of the mouse cursor.
However, you are trying to convert screen coordinates into client coordinates withing the main window, not within the button. Try something more like this instead:
//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
}
Alternatively, you can get the button's client rectangle, convert it into screen coordinates, and then compare that with the screen coordinates of the mouse:
//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
}
Now, that being said, a tab selection can be changed using either the mouse or the keyboard. In your case, you want only mouse clicks, but TCN_SELCHANGING
doesn't tell you WHY the tab selection is changing. For that, you will have to subclass the tab control to handle WM_LBUTTONDOWN
messages for left-click, and WM_KEYDOWN
messages for Arrow, Home, and End keys. Then you can flag your TCN_SELCHANGING
handler accordingly.
Upvotes: 1