在CDialog上使用QWinWidget使用托管Qt小部件时,键盘输入无法正常工作

时间:2011-12-05 18:59:40

标签: c++ qt mfc

我正在逐步将应用程序从 MFC 迁移到 Qt 并使用 MFCMigrationFramework 来实现此目的。

放置在MFC对话框上的Qt小部件无法处理标签箭头输入 Esc <等关键字/ strong>即可。 选项卡和箭头的问题部分通过this solution解决:

我已经将 QWinWidget 子类化,并做了下面的事情: 构造:

SetWindowLong(winId(), GWL_STYLE, GetWindowLong(winId(), GWL_STYLE) | WS_TABSTOP);

Overriden winEvent:

bool winEvent(MSG *msg, long *result)
{
  switch(msg->message)
  {
    case WM_GETDLGCODE:
      *result = DLGC_WANTARROWS | DLGC_WANTTAB;
      return true;
  }

  return __super::winEvent(msg, result);
}

要复制到剪贴板,请将视图切换为纯文本模式

除了一个问题之外它是有效的:使用 Tab 键无法在父对话框(MFC)上获得控件,仅通过子Qt控件(第一个问题)进行焦点循环

第二个问题输入 Esc 键仅由父MFC对话框处理。例如,按Enter或Esc键关闭打开的组合框弹出窗口(位于Qt小部件上)是不可能的 - 对话框已关闭( CDialog :: OnOK CDialog :: OnCancel 被称为。)

我试过这个

case WM_GETDLGCODE:
  *result = DLGC_WANTARROWS | DLGC_WANTTAB | DLGC_WANTALLKEYS;

但在这种情况下 CDialog 不再处理Esc和Enter键。

处理这种情况的正确解决方案是什么?

1 个答案:

答案 0 :(得分:2)

关于你的第一个问题:对我来说有用的是根据当前的焦点来决定你是否处于焦点链的“终点”。如果您在最后并获得一个标签(或在开头并获得一个班次标签),那么请不要在返回值中包含 DLGC_WANTTAB

else if (msg->message == WM_GETDLGCODE)
{
  // Initialize our result, as we always want arrows
  *result = DLGC_WANTARROWS;

  // Check to see if we want tabs
  if (msg->wParam == VK_TAB)
  {
    // Was this a tab or a backtab?
    QWidget *pFocusChainEndpoint = NULL;
    if (::GetKeyState(VK_SHIFT) < 0)
    {
      pFocusChainEndpoint = m_pFirstTabStop;
    }
    else
    {
      pFocusChainEndpoint = m_pFinalTabStop;
    }

    // Determine our current-focusing widget
    QWidget *pCurrent = focusWidget();
    if (pCurrent == NULL)
    {
      // We have no focus, so we don't want the tab event
      return true;
    }

    // If we are *not* at a relevant endpoint in the focus chain,
    // we want to handle the tab event
    if (pCurrent != pFocusChainEndpoint)
    {
      *result |= DLGC_WANTTAB;
    }
  }

  // This message has been handled
  return true;
}

m_pFirstTabStopm_pFinalTabStopshow()代码中确定:

  // Determine the first link in our focus chain
  m_pFirstTabStop = nextInFocusChain();
  Q_ASSERT(m_pFirstTabStop != NULL);
  if (m_pFirstTabStop == NULL)
  {
    // We have no endpoint
    return;
  }
  QString qstrChainObjectName = m_pFirstTabStop->objectName();
  while (!(m_pFirstTabStop->focusPolicy() & Qt::TabFocus)
    || qstrChainObjectName.left(3) == "qt_")
  {
    m_pFirstTabStop = m_pFirstTabStop->nextInFocusChain();
    if (m_pFirstTabStop == this || m_pFirstTabStop == NULL)
    {
      // We've looped through them all, and none require focus --- perhaps the
      // control is just labels --- so we have a NULL tab stop
      m_pFirstTabStop = NULL;
      return;
    }
    qstrChainObjectName = m_pFirstTabStop->objectName();
  }

  // Determine the last link in our focus chain
  m_pFinalTabStop = previousInFocusChain();
  Q_ASSERT(m_pFinalTabStop != NULL);
  if (m_pFinalTabStop == NULL)
  {
    // We have no endpoint
    return;
  }
  qstrChainObjectName = m_pFinalTabStop->objectName();
  while (!(m_pFinalTabStop->focusPolicy() & Qt::TabFocus)
    || qstrChainObjectName.left(3) == "qt_")
  {
    m_pFinalTabStop = m_pFinalTabStop->previousInFocusChain();
    if (m_pFinalTabStop == this || m_pFinalTabStop == NULL)
    {
      // We've looped through them all, and none require focus --- perhaps the
      // control is just labels --- so we have a NULL tab stop
      m_pFinalTabStop = NULL;
      return;
    }
    qstrChainObjectName = m_pFinalTabStop->objectName();
  }

虽然我没有测试这种情况,但它应该能够正确处理只有非可列表控件的UI(例如只有QLabel)。