【问题标题】:Detect when dialog sets focus to various combo controls using PreTranslateMessage使用 PreTranslateMessage 检测对话框何时将焦点设置到各种组合控件
【发布时间】:2020-06-02 19:39:36
【问题描述】:

我有一个CDialog,我正在尝试像这样覆盖PreTranslateMessage

BOOL CWeekendMeetingDlg::PreTranslateMessage(MSG* pMsg)
{

    if (pMsg->message == WM_SETFOCUS)
    {
        if (::GetDlgCtrlID(pMsg->hwnd) != IDC_COMBO_PT_CHAIRMAN &&
            ::GetDlgCtrlID(pMsg->hwnd) != IDC_COMBO_PT_OPEN_PRAYER &&
            ::GetDlgCtrlID(pMsg->hwnd) != IDC_COMBO_WT_CLOSE_PRAYER &&
            ::GetDlgCtrlID(pMsg->hwnd) != IDC_COMBO_WEEKEND_HOST &&
            ::GetDlgCtrlID(pMsg->hwnd) != IDC_COMBO_WEEKEND_COHOST &&
            ::GetDlgCtrlID(pMsg->hwnd) != IDC_COMBO_PT_READER)
        {
            if (m_gridAssignHist.GetRowCount() != 1)
            {
                m_gridAssignHist.SetRowCount(1);
            }
        }
    }

    return CDialog::PreTranslateMessage(pMsg);
}

它不工作。我想要做的是在其他控件获得焦点时将我的CGridCtrl 行数重置为 1(例如:编辑组合)。但是,如果我在第一个 if 中放置一个断点,它就永远不会被拦截。

目前我唯一能想到的就是对对话框中的所有组合 ID 重新编号,以便它们是连续的,然后使用 OnSetFocus 的命令范围并在该处理程序中检测。但也有一些CEdit 控件。

我不能使用 PTM 并避免这种情况吗?对我来说,这似乎是最简单的。

这是对话框:

目前我有 7 个组合 OnSetFocus 处理程序。当他们触发时,右侧网格中会显示特定的分​​配历史记录。

因此,如果用户移动到对话框上的任何其他控件,则分配历史控件将不适用。这就是为什么我想将历史记录重置为标题行。我希望用 PTM 做到这一点。

【问题讨论】:

  • 你可以直接使用CBN_SETFOCUS
  • @dxiv,对不起,这就是我的意思,我已经为我的特定组合实现了该消息的那些处理程序。我想我找到了解决办法。
  • 不确定为什么“handlers”的复数形式。 CBN_SETFOCUS 将在父窗口(对话框)中捕获,并且所有子 ID 在您的情况下只需要一个处理程序。
  • @dxiv 是的,我明白了,但我仍然需要检测其他类型的控件。我认为计时器是一个足够简单的分辨率。
  • 不确定,但是评论太长了,所以我将其发布为答案。

标签: visual-c++ mfc setfocus


【解决方案1】:

通过WM_COMMAND 消息在父对话框中接收儿童控制通知。覆盖 MFC 对话框的 OnCommand 会捕获这些通知(CBN_SETFOCUSEN_SETFOCUS 等)。

void DoSomething()
{   /* ... */ }

BOOL CWeekendMeetingDlg::OnCommand(WPARAM wParam, LPARAM /*unused*/)
{
    switch (HIWORD(wParam))
    {
    case CBN_SETFOCUS:
        switch (LOWORD(wParam))
        {
        case IDC_COMBO_PT_CHAIRMAN:
        // ...more combobox IDCs
            DoSomething();
            break; // or return TRUE to bypass any message map handlers
        }
        break;

    case EN_SETFOCUS:
        switch (LOWORD(wParam))
        {
        case IDC_EDIT_WHATEVER:
        // ...more editbox IDCs
            DoSomething();
            break;
        }
        break;

    // ...more notification codes
    }
    return CDialog::OnCommand(wParam, lParam);
}

【讨论】:

  • 谢谢,我会试试这个。看起来我需要为下拉列表的组合框处理 CBN_DROPDOWN ,为按钮处理 BN_SETFOCUS 。会更新你。
【解决方案2】:

我在对话框中添加了一个 2 秒计时器:

void CWeekendMeetingDlg::OnTimer(UINT_PTR nIDEvent)
{
    if (nIDEvent == 1)
    {
        CWnd* pControl = GetFocus();
        if (pControl != nullptr)
        {
            CWnd* pParent = pControl->GetParent();
            if (pParent != nullptr)
            {
                int iCtrlID = pParent->GetDlgCtrlID();

                if (iCtrlID != IDC_COMBO_PT_CHAIRMAN &&
                    iCtrlID != IDC_COMBO_PT_OPEN_PRAYER &&
                    iCtrlID != IDC_COMBO_WT_CLOSE_PRAYER &&
                    iCtrlID != IDC_COMBO_WEEKEND_HOST &&
                    iCtrlID != IDC_COMBO_WEEKEND_COHOST &&
                    iCtrlID != IDC_COMBO_PT_READER)
                {
                    if (m_gridAssignHist.GetRowCount() != 1)
                    {
                        m_gridAssignHist.SetRowCount(1);

                        UpdateData(TRUE);
                        m_strAssignHistLabel = _T("Assignment:");
                        UpdateData(FALSE);
                    }
                }

            }

        }

    }

    CDialog::OnTimer(nIDEvent);
}

这似乎工作正常。

【讨论】:

    猜你喜欢
    • 2011-12-04
    • 1970-01-01
    • 1970-01-01
    • 2017-01-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-01-21
    • 1970-01-01
    相关资源
    最近更新 更多