MFC button can not receive touch event - mfc

the list control can receive the touch event, but the push button can not receive the touch event, it always receive the mouse move event.
I want to send the touch event to the button's parent, how to resole this?
code like below can tell if it is a mouse or touch event, but can not forward the event to its parent to handle the touch event.
#define MOUSEEVENTF_FROMTOUCH 0xFF515700
if ((GetMessageExtraInfo() & MOUSEEVENTF_FROMTOUCH) == MOUSEEVENTF_FROMTOUCH) {
// Click was generated by wisptis / Windows Touch
}else{
// Click was generated by the mouse.
}
by the way, how to stop converting touch event to mouse event?

With WM_TOUCH/WM_GESTURE you get a handle to the touch input event list. The TOUCHINPUT data isn't dedicated to a specific window. Different to GESTUREINFO. But it shouldn't be complicated to translate the info.
An unhandled WM_GESTURE message passed to DefWindowProc will be propagated to the parent window. When forwarding gesture messages between windows, avoid sending messages from parent to child windows in order to prevent closed loops from occurring.
http://msdn.microsoft.com/en-us/library/ee220935.aspx
For a WM_TOUCH message you can use a user defined message and post this message with the lParam value to the parent of the button. But you must handle this message there and need to call CloseTouchInputHandle
If you don't pass the WM_TOUCH/WM_GESTURE message to DefWidnowProc no further translation is done.
Touch events are converted to mouse messages in the DefWindowProc processing.
What gestures are supported and converted to mouse messages is listed here.

The list control can receive the touch event, but the push button or textedit can not receive the touch event, it always receive the mouse move event.
code like below can tell if it is a mouse or touch event, but when flick up & down for a while, it can not receive the event.
Then flick left & right can always receive the mouse move event
#define MOUSEEVENTF_FROMTOUCH 0xFF515700
if ((GetMessageExtraInfo() & MOUSEEVENTF_FROMTOUCH) == MOUSEEVENTF_FROMTOUCH) {
// Click was generated by wisptis / Windows Touch
}else{
// Click was generated by the mouse.
}
I put this button in a scrollview which has the vertical scroll bar.

Related

How to capture user's click action when clicking on notifications

Currently, I want to show a balloon notification on Windows, then I want to capture the action when a user clicks on the balloon notification.
Then I will do another action after capturing this action.
How can I do that?
And can I do that on all of the Windows platforms (from Windows 7 to Windows 10)?
You said in comments that you are using Shell_NotifyIcon() to display the balloon. The answer to your question is in the documentation:
As of Windows XP (Shell32.dll version 6.0), if a user passes the mouse pointer over an icon with which a balloon notification is associated, the Shell sends the following messages:
NIN_BALLOONSHOW. Sent when the balloon is shown (balloons are queued).
NIN_BALLOONHIDE. Sent when the balloon disappears. For example, when the icon is deleted. This message is not sent if the balloon is dismissed because of a timeout or if the user clicks the mouse.
As of Windows 7, NIN_BALLOONHIDE is also sent when a notification with the NIIF_RESPECT_QUIET_TIME flag set attempts to display during quiet time (a user's first hour on a new computer). In that case, the balloon is never displayed at all.
NIN_BALLOONTIMEOUT. Sent when the balloon is dismissed because of a timeout.
NIN_BALLOONUSERCLICK. Sent when the balloon is dismissed because the user clicked the mouse.
In addition to those messages, as of Windows Vista (Shell32.dll version 6.0.6), if a user passes the mouse pointer over an icon with which a balloon notification is associated, the Windows Vista Shell also adds the following messages:
NIN_POPUPOPEN. Sent when the user hovers the cursor over an icon to indicate that the richer pop-up UI should be used in place of a standard textual tooltip.
NIN_POPUPCLOSE. Sent when a cursor no longer hovers over an icon to indicate that the rich pop-up UI should be closed.
Regardless of the operating system version, you can select which way the Shell should behave by calling Shell_NotifyIcon with dwMessage set to NIM_SETVERSION. Set the uVersion member of the NOTIFYICONDATA structure pointed to by lpdata to indicate whether you want Windows 2000, Windows Vista, or pre-version 5.0 (Windows 95) behavior.
Note The messages discussed above are not conventional Windows messages. They are sent as the lParam value of the application-defined message that is specified in the uCallbackMessage member of the NOTIFYICONDATA structure pointed to by lpdata, when Shell_NotifyIcon is called with the NIM_ADD flag set in dwMessage.
So, to receive these messages, you need to specify an HWND and Callback message ID in the NOTIFYICONDATA struct when calling Shell_NotifyIcon() with dwMessage set to NIM_ADD or NIM_MODIFY:
hWnd
Type: HWND
A handle to the window that receives notifications associated with an icon in the notification area.
...
uCallbackMessage
Type: UINT
An application-defined message identifier. The system uses this identifier to send notification messages to the window identified in hWnd. These notification messages are sent when a mouse event or hover occurs in the bounding rectangle of the icon, when the icon is selected or activated with the keyboard, or when those actions occur in the balloon notification.
When the uVersion member is either 0 or NOTIFYICON_VERSION, the wParam parameter of the message contains the identifier of the taskbar icon in which the event occurred. This identifier can be 32 bits in length. The lParam parameter holds the mouse or keyboard message associated with the event. For example, when the pointer moves over a taskbar icon, lParam is set to WM_MOUSEMOVE.
When the uVersion member is NOTIFYICON_VERSION_4, applications continue to receive notification events in the form of application-defined messages through the uCallbackMessage member, but the interpretation of the lParam and wParam parameters of that message is changed as follows:
LOWORD(lParam) contains notification events, such as NIN_BALLOONSHOW, NIN_POPUPOPEN, or WM_CONTEXTMENU.
HIWORD(lParam) contains the icon ID. Icon IDs are restricted to a length of 16 bits.
GET_X_LPARAM(wParam) returns the X anchor coordinate for notification events NIN_POPUPOPEN, NIN_SELECT, NIN_KEYSELECT, and all mouse messages between WM_MOUSEFIRST and WM_MOUSELAST. If any of those messages are generated by the keyboard, wParam is set to the upper-left corner of the target icon. For all other messages, wParam is undefined.
GET_Y_LPARAM(wParam) returns the Y anchor coordinate for notification events and messages as defined for the X anchor.
...
If you set the NIF_INFO flag in the uFlags member, the balloon-style notification is used. For more discussion of these notifications, see Balloon tooltips.
So, to answer your question, in the WndProc for the HWND that you specify in the NOTIFYICONDATA::hWnd field, you would look for the message ID you specify in the NOTIFYICONDATA::uCallbackMessage field, and then look for the NIN_BALLOONUSERCLICK notification in the message's lParam or LOWORD(lParam) value, depending on how you set the NOTIFYICONDATA::uVersion field.

MFC Message flow for controls?

In MFC, suppose I have a dialog box, and in this box, it has a child CListCtrl, then I use mouse to click this CListCtrl, we know that eventually an WM_LBUTTONDOWN message is sent to CListCtrl. My question is: How does this WM_LBUTTONDOWN message get there?
Two possibilities:
Dialog box first gets this WM_LBUTTONDOWN message , and it finds that mouse click occurs in its child window, then it forwards this message to CListCtrl.
CListCtrl first gets this WM_LBUTTONDOWN message, it can process this message, and if it doesn't care it will forward this message to parent window, i.e. dialog box for further processing.
Which one is true?
Thanks.
Input messages are never sent to a window. They are posted to the message queue associated with a window, waiting to be retrieved through one of the message retrieval functions (GetMessage, PeekMessage, etc.).
Depending on whether the dialog box is modal or modeless, messages are retrieved by the nested modal loop (for modal dialogs) or the application's message loop. The message is then passed on to DispatchMessage, to find the recipient (starting from the topmost visible window under the mouse pointer, that is neither disabled nor transparent), and call into the associated window's window procedure. The window procedure can decide, whether it handles the message or not. A window procedure typically calls DefWindowProc to perform default processing, if it doesn't handle a message.
To summarize: The application's message loop (or the nested modal message loop) gets to see the message first, and instructs the window manager to deliver the message to the respective recipient.
A thorough description on Windows message processing is available at About Messages and Message Queues. The description is specific to the Windows API. Since MFC is just a wrapper around the Windows API, the contents apply to MFC as well, even though some of the concepts are hidden in a typical MFC application.

Unhandled LButtonUp windows message in COleControl

I have a COleControl object in my project.
Inside this COleControl, I have a CRectTracker object.
I want to handle the windows message (event) of WM_LButtonUp. (when the user stops to press the left mouse button).
In my .h file I wrote:
afx_msg void OnLButtonUp(UINT nFlags, CPoint point);
In my .cpp file, in
BEGIN_MESSAGE_MAP(CMyControl, COleControl)
I added
ON_WM_LBUTTONUP()
Then I developed a method of
void CMyControl::OnLButtonUp(UINT nFlags, CPoint point)
I did the same thing for the windows message LButtonDown.
When I leave the left mouse button inside my control, method get handles and everything works fine.
The problem occurs when I leave the left mouse button when the mouse tracker is on the CRectTracker object. In this case, the mouse LButtonUp message does not get handled.
I tried to use Spy++ and I can see that the windows message WM_LButtonUp exists and occurs as expected. But it my code, it does not get handled (just in the case of mouse on the CRectTracker).
The LButtonDown event get handled successfully all the time, even when I press the mouse button while the mouse is on the CRectTracker.
What can be the problem with the LButtonUp message?
Thanks
That is just an inevitable side-effect of the way the tracker works. Once you click on the tracker or one of the sizing handles then MFC captures the mouse and starts a modal message loop. Which is going to pick off mouse-move and button-up messages to implement the tracking operation. That loop doesn't exit until the left button-up message is seen, the Escape key is seen or the capture is lost. Accordingly, your OnLButtonUp() function cannot run while that loop is active, the message was intercepted before it could be dispatched.
You'll need to do this differently, not relying on OnLButtonUp(). Hard to give specific advice since you didn't describe why you need it. The source code for the modal loop is in atlmfc/src/mfc/trckrect.cpp, CRectTracker::TrackHandle() if you need more insight.

Visual C++ MFC Application- Event not receiving in child dialog

I have created a derived control handling events as mouse movement, left button down up,down etc.
And I have a popup dialog and within that dialog, three child dialogs.
When I use the derived control in my popup dialog, it is working properly.
But when I place my control in any of the child dialog, the mouse events are not handled.
Please suggest a solution.
Thanks in advance,
Madhan
Must to pass forward the events. Catch them on the child dialog with the respective message handlers and then forward them using the ::SendMessage method.
The popup dialog possibly catched up automatically the mouse events and enabled to be forwarded towards.

"?" help button triggers WM_HELP _and_ WM_LBUTTONUP

I have a Windows application that registers one CALLBACK procedure that handles WM_HELP messages for the dialog, and one CALLBACK procedure that handles WM_LBUTTONUP messages for a custom button.
Now, when the user clicks the "?" button, then clicks the custom button, the help opens up as expected (on mouse down), BUT if the help window is not occluding the button, a WM_LBUTTONUP message is triggered as well for the custom button (on mouse up). This causes the button to trigger when the user was only asking for help.
Is there any way to stop the WM_LBUTTONUP message from being sent if the button press is for help?
EDIT: The custom button is implemented using a STATIC control. I believe this is because it needs to have an image and no border. So, it does not send BN_CLICKED notifications. In fact, it does not seem to trigger WM_COMMAND in the parent at all.
Thanks
This is normal. Be sure to use the button's BN_CLICKED notification to see the difference. Generated when the user clicks the button, not generated when the user uses the help cursor. The button still sees the normal button up/down messages so that's not a good trigger to detect a click. Extra bonus is that the button can now also be clicked with the keyboard (space bar).
A good class library takes care of these nasty little details.
A better way would be to create ? as a custom control with BS_CHECKBOX | BS_PUSHLIKE style and capture the mouse. After that you will get all the WM_LBUTTONDOWN message to this custom control and then you can use WindowFromPoint to get the window where the WM_LBUTTONDOWN happened and can send a custom notification to the parent window. The parent window can then show a the tooltip or open the help doc or discard it.
The advantage is, you create the control only once and you can use it in multiple places.
Okay, I fixed it by creating the custom button (static control) with the SS_NOTIFY style, then handling the STN_CLICKED notification in the WM_COMMAND message. (SS_NOTIFY causes WM_COMMAND to trigger in the parent when it is clicked.) This does not trigger when using the "?" button. Thanks!