3

我想知道提供的用于CListBox控制的消息控制器集有多么有限。我已经在包含此控件ON_LBN_SELCHANGE的消息映射中使用。CDialog

我也想使用ON_WM_RBUTTONDOWN,所以我派生了 a class CMyListBox : public CListBox,所以现在我可以在类中映射该消息,但我想以相同的ON_LBN_SELCHANGE工作方式将它映射到对话框。

我的问题是是否可以将该消息重新发送到父对话框,以便我可以从CDialog消息映射中处理它,以及这样做的最佳方法是什么(send_message、post_message 或是否有更好的通知机制)?

4

2 回答 2

3

我想我也会向您展示这种方法作为替代方案,这样可以节省派生自己的CListBox课程的需要。

  1. 选择您的对话类。
  2. 在“属性”窗格中选择“消息”图标。
  3. 在列表中找到WM_CONTEXTMENU并通过下拉菜单添加处理程序。

添加处理程序

这个处理程序的描述说:

通知窗口用户希望出现上下文菜单。用户可能在窗口中单击了鼠标右键(右键单击),按下了 Shift+F10 或按下了某些键盘上可用的应用程序键(上下文菜单键)。

wParam- 用户右键单击鼠标的窗口句柄。这可以是接收消息的窗口的子窗口。有关处理此消息的更多信息,请参阅备注部分。

您需要取消注释要在生成的处理程序中使用的参数。例如:

void CMFCApplication4Dlg::OnContextMenu(CWnd* pWnd, CPoint /*point*/)
{
    if (pWnd->GetSafeHwnd() == m_lbList.GetSafeHwnd())
    {
        AfxMessageBox(_T("User right-clicked on the listbox control"));
    }
}

结果:

在此处输入图像描述

当然,像您所做的那样派生自己的类并处理鼠标按钮和使用通知系统并没有错。我并不是说这种方法更好。我只是将其作为检测对话框上控件右键单击的替代方法。


注意:这里还有其他关于使用这种方法的答案,但我发现的答案没有显示截图。

于 2021-04-14T19:18:06.387 回答
1

您可以将控件设置为将WM_PARENTNOTIFY消息发送到父对话框(默认情况下不发送),并将该OnParentNotify()函数的覆盖添加到您的对话框类。基本程序如下所述。

首先,您需要WS_EX_NOPARENTNOTIFY从列表框控件中删除样式,以便它将所需的消息发送到其父级。有几种方法可以做到这一点,但一种非常简单的方法是修改OnInitDialog覆盖中的“ex-style”,如下所示:

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
}

然后,您需要添加ON_WM_PARENTNOTIFY到对话框的消息映射:

BEGIN_MESSAGE_MAP(MyDialog, CDialog)
    //...
    ON_WM_PARENTNOTIFY()
END_MESSAGE_MAP()

最后,拦截通知的处理程序:

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!
    }
}

这种方法的一个(可能是麻烦的)问题是(您可能已经注意到)没有传递给处理函数的有关通知来自哪个控件的信息。如果您的对话框中只有一个控件启用了此行为,那没关系;否则,您将不得不做一些诡计(使用给定的光标位置和控件的窗口矩形)来确定哪个控件发送了消息。

于 2021-04-14T12:15:06.153 回答