Unable to retrieve title of just created window - c++

I'm trying to retrieve the title of a window when my hook procedure receive an HCBT_ACTIVATE message.
The problem is that when this message is received for the first time the window seems not to have the caption already set. I think I should maybe add some kind of delay to the call to GetWindowText?
(After the window is created and, for example, I receive a HCBT_MOVESIZE or HCBT_DESTROYWND message I can get the correct title)

You should set the hook with SetWindowHookEx, using WH_CALLWNDPROCRET to receive the WM_CREATE notification after the message has been processed.

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.

The CBN_SELCHANGE notification not works when i use the function ComboBox_SetCurSel

I have a ComboBox in a window and i want to execute a function after changing selected item.
When i change the selected item of the combobox by mouse or keyboard,
the CBN_SELCHANGE event in the window message WM_COMMAND works well and my function execute.
But if i use the function ComboBox_SetCurSel for changing the selected item ,it not works.
What window message WM_**** and combox notification do i use for processing the event changing selected item.
In general, when you programmatically manipulate a control, the corresponding notification is not sent to its parent. The notification only gets sent when the user manipulates the control.
So, when you call ComboBox_SetCurSel (which is a macro that performs the same task as sending the CB_SETCURSEL message), that programmatically changes the control's current selection and therefore does not send the CBN_SELCHANGE notification. However, CBN_SELCHANGE does get sent if the user changes the combobox's selection.
This is called out explicitly in the "Remarks" section of the documentation for CBN_SELCHANGE:
The CBN_SELCHANGE notification code is not sent when the current selection is set using the CB_SETCURSEL message.
To work around this, you can do one of two things:
Call your event-handler method directly. For example, in MFC, you would have the framework attach an OnCbnSelChange member function to handle the combobox's CBN_SELCHANGE notification. After your code that called ComboBox_SetCurSel, you would simply call that OnCbnSelChange member function manually:
ComboBox_SetCurSel(hwndComboBox, 0); // select 1st item
this->OnCbnSelChange(); // invoke the change event-handler
Your GUI framework undoubtedly has something similar.
Manually send the CBN_SELCHANGE notification to the control's parent. I don't really know why you would ever do this, because the default window procedure doesn't do anything interesting upon receipt of this notification; you would be much better off just calling your own handler directly.
::PostMessage(hwndParent,
WM_COMMAND,
MAKEWPARAM(IDC_COMBOBOX, CBN_SELCHANGE),
reinterpret_cast<LPARAM>(hwndComboBox);
Or, if you were doing this from a subclass of the combobox:
HWND hwndParent = ::GetAncestor(hwndComboBox, GA_PARENT);
int ctrlID = static_cast<int>(::GetWindowLongPtr(hwndComboBox, GWLP_ID));
::PostMessage(hwndParent,
WM_COMMAND,
MAKEWPARAM(ctrlID, CBN_SELCHANGE),
reinterpret_cast<LPARAM>(hwndComboBox));

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.

How to receive information from a SendMessage() in c++

I got how to SendMessage to another process. Now I am trying to understand how to receive the message on my other process. I know how to extract my items from de COPYDATASTRUCTURE but what is the method that is called on my other process. I found a lot of stuff on how to read the received data but never how to implement it. So basically, what function/event is called when an application receives a message from SendMessage()? You must know here that I have full control on both process.
The send message from another process is exactly like any send message received from the same process: Specifically the window procedure for the window the message is sent to is called with the message as parameters just as you would receive a WM_PAINT or any other op-sys message.
Consider reading this blog post, containing sample code:
Using WM_COPYDATA to marshal message parameters since the window manager otherwise doesn't know how
(You simply handle WM_COPYDATA in the receiver WndProc.)

MFC: MessageBox during a Drag-Drop

I need to display an error message on rejecting a drop in my application.
I tried this in the OnDrop() but then the source application hangs until my message box is dismissed.
How can I do that?
You can always call PostMessage with a private message in the WM_APP range and in the message handler show the error.
That way you show the error after the drag and drop operation is really over and there is no danger of messing up anything.
You're right. But all the data I need to report in the message box is in the OnDrop.
If you need data you can copy it in the OnDrop, store it in some temporary location, then in the WM_APP range message pass the index to the data in temporary location. The handler for the WM_APP message can clean up the temporary data after showing the message box.