I have wondered about how limited is the provided set of messages controllers for CListBox
control. I am already using ON_LBN_SELCHANGE
in the message map of the CDialog
containing this control.
I also would like to use ON_WM_RBUTTONDOWN
, so I have derived a class CMyListBox : public CListBox
, so now i can map that message inside the class, but I would like to map it to the dialog in the same way of ON_LBN_SELCHANGE
works.
My question is whether is possible to re-send that message to parent dialog, so I can handle it from CDialog
message map, and what is the best way of doing this (send_message, post_message or is there a better notification mechanism)?
You can set your control to send WM_PARENTNOTIFY
messages to the parent dialog box (it doesn't, by default) and add an override of the OnParentNotify()
function to your dialog class. The basic procedure would be as outlined below.
First, you'll need to remove the WS_EX_NOPARENTNOTIFY
style from your list-box control, so that it sends the required message to its parent. There are several ways to do this but one quite easy way is to modify the "ex-style" in your OnInitDialog
override, like this:
BOOL MyDialog::OnInitDialog(void)
{
CDialog::OnInitDIalog(); // Call base class
//...
// Other code you need
//
CWnd* pList = GetDlgItem(IDC_MYLISTBOX); // Use the resource ID of the listbox
LONG_PTR exstyle = GetWindowLongPtr(pList->m_hWnd, GWL_EXSTYLE);
// Remove the WS_EX_NOPARENTNOTIFY bit ...
exstyle &= ~WS_EX_NOPARENTNOTIFY;
SetWindowLongPtr(pList->m_hWnd, GWL_EXSTYLE, exstyle); // Set new style
//...
return TRUE; // Assuming you don't explicitly set the focus
}
Then, you'll need to add ON_WM_PARENTNOTIFY
to your dialog's message map:
BEGIN_MESSAGE_MAP(MyDialog, CDialog)
//...
ON_WM_PARENTNOTIFY()
END_MESSAGE_MAP()
Finally, the handler to intercept the notification:
void MyDialog::OnParentNotify(UINT message, LPARAM lParam)
{
CDialog::OnParentNotify(message, lParam); // Always best to call base class for MFC!
if (message == WM_RBUTTONDOWN) {
// Here, we can handle the right-button click!
// lParam will be the cursor position (x in LOWORD and y in HIWORD)
// NOTE: See the caveat mentioned below!
}
}
One (potentially troublesome) issue with this approach is that (as you may have noticed) there is no information passed to the handler function about which control the notification came from. If you only have one control in your dialog that has this behaviour enabled, then that's OK; otherwise, you'll have to do some trickery (using the cursor position given and the control's window rectangle) to determine which control has sent the message.