Are DialogBox messages sent to a custom message loop? - c++

I have an application that currently has a message loop. If I were to create a modal dialog box with the DialogBox method would the current message loop receive messages from the dialog as well or would they be withheld by the runtime?

DialogBox creates its own message loop so your message loop will not run. From the documentation:
The function displays the dialog box (regardless of whether the
template specifies the WS_VISIBLE style), disables the owner window,
and starts its own message loop to retrieve and dispatch messages for
the dialog box.

Your existing message loop will not receive the messages for the dialog box. All messages for the dialog would be received by the DLGPROC method that you're passing as the last parameter to the DialogBox function.

Related

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));

Calling the event handler programmatically in an MFC application

I am working on an MFC application (C++)
My checkbox has an event hander mapped to the ON_BN_CLICKED.
It works fine when the user check/uncheck the box, i.e. the event handler is called.
However, when I check the box programmatically: ((CButton *)this->GetDlgItem(x))-> ->SetCheck(1); the event handler is not called.
What should I do in order to call the event handler programmatically?
This is a normal behavior. The WM_COMMAND is sent when a "click" or "user entry" changed the button.
This is not contignous with child controls. Other child controls like an edit control also send a WM_COMMAND EN_CHANGE message when SetWindowText is executed by the program (the MFC blocks this message in a DoDataExchange).
Try to send BN_CLICKED:
this->SendMessage(WM_COMMAND,
MAKELONG(IDC_BUTTON1, BN_CLICKED),
((CButton *)this->GetDlgItem(x))->GetSafeHwnd());

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 close a MessageBox window by its handle with C++

I have a multi-threaded application that may display a MessageBox for a user's interaction. The message box itself is displayed from a worker thread, after a user picks a context menu command from the app's system tray icon, so the user can technically continue using the app while the message box is displayed. This works great until a user issues "Exit" command, at which point I need to find a way to close any open message boxes.
I did my homework and I was able to obtain HWND handle for the main (dialog) window of the message box (using this method.) I checked the HWND to be correct using Spy++, so HWND itself is not the issue. What happens is that when I do PostMessage(hMsgBoxWnd, WM_CLOSE, 0, 0); from another thread to the message box, it simply ignores this message and doesn't close.
Any idea how to close the message-box by its window handle?
MessageBox() simply does not process WM_CLOSE in all sitations:
SendMessage/PostMessage WM_CLOSE to MessageBox window does not always work
You should use PostThreadMessage to post to the threads specific message queue

How I can get a focus message in MFC?

I have a dialog box with some CListCtrl. I want that when I click on one of them, receive killfocus or setfocus message.
How I can get it?
The CListCtrl class wraps the Win32 ListView control. That control communicates with its parent (your dialog) via WM_NOTIFY messages.
So you can process WM_NOTIFY messages from your list control in your dialog class. Use the Properties window to create an OnChildNotify handler function and write a switch statement that handles the notification message(s) of interest.
The possible notification messages are listed here in the Windows SDK documentation.