MFC 对话框中的 QWinWidget 不重新绘制或响应 Tab/箭头键

Posted

技术标签:

【中文标题】MFC 对话框中的 QWinWidget 不重新绘制或响应 Tab/箭头键【英文标题】:QWinWidget Inside MFC Dialog Not Repainting or Responding to Tab/Arrow keys 【发布时间】:2009-06-30 21:31:13 【问题描述】:

我在 MFC 对话框中使用 QWinWidget,而 QWinWidget 没有正确绘制自身,也没有正确处理键盘输入。

重绘[未解决]

在 QWinWidget 中,我有一个 QTableWidget。当我滚动 QTableWidget 时,它不会重绘自身,直到我停止滚动,此时它会重绘所有内容。同样,我可以在 QTableWidget 中的单元格中键入内容,并且控件不会更新,直到我通过向上或向下滚动来强制它重新更新(它在滚动停止时重新更新)。

由于这个 QWinWidget 被放置在 MFC CDialog 中,我尝试重写 CDialog 的 OnPaint 方法并只调用 QWinWidget::repaint 方法,但是这有相反的问题,现在只有 QWinWidget 被更新并且 CDialog 永远不会重绘,导致工件。如果我调用 QWinWidget::repaint 和 CDialog::OnPaint,结果与不覆盖 OnPaint 方法相同。有没有人见过这个问题或知道如何解决它?

键盘输入 [已解决]

QWinWidget 中的所有控件都不能正确响应 Tab 键或箭头键。选项卡/箭头键只是跳过整个 QWinWidget(和所有子控件)。即使我在 QWinWidget 内部单击并选择了一个控件,下次我按下 tab 键时,它也会将焦点完全跳过整个 QWinWidget。

我注意到 QWinWidget 有两个函数,QWinWidget::focusNextPrevChild 和 QWinWidget::focusInEvent 并且它们都有一个注释标题“\reimp”。我是否应该覆盖这些功能以获得正确的选项卡功能?如果是这样,如何实现这些功能以获得正确的选项卡功能。

【问题讨论】:

【参考方案1】:

我已经修复了键盘输入问题。 QWinWidget 类需要一些更改:

在QWinWidget::init方法中,必须将WS_TABSTOP添加到窗口样式中:

SetWindowLong(winId(), GWL_STYLE, WS_CHILD | WS_CLIPCHILDREN | WS_CLIPSIBLINGS | WS_TABSTOP);

此外,QWinWidget::winEvent 方法需要响应 WM_GETDLGCODE 以让 Windows 知道它有兴趣接收键/选项卡输入。我必须添加这个 if 块:

if(msg->message == WM_GETDLGCODE)

   *result = DLGC_WANTARROWS | DLGC_WANTTAB;
   return(true);

我仍在努力让小部件正确绘制。

【讨论】:

【参考方案2】:

我不知道您是否需要重新实现 focusNextPrevChild()focusInEvent() 函数,但我知道注释头中的“\reimp”是 Qt 文档生成的一部分,它只是指定函数是父类中另一个函数的重新实现。

【讨论】:

【参考方案3】:

谢谢!这个对我有用!我已经修复了 QWinWidget 中 QTableView 的箭头键导航问题。 我正在使用 Qt5.3.0 和 qtwinmigrate 2.8。 QWinWidget::nativeEvent方法需要修改。

#if QT_VERSION >= 0x050000
bool QWinWidget::nativeEvent(const QByteArray &, void *message, long *result)
#else
...

    ...
    if (msg->message == WM_SETFOCUS) 
        ...
     else if (msg->message == WM_GETDLGCODE) 
        *result = DLGC_WANTALLKEYS;
        return true;
    

    return false;

【讨论】:

这种方法在 Qt 4.8 中也非常适合我。我需要在本机 Win32 对话窗口中嵌入一个 QPlainText 小部件,并且遇到了不接受 Tab 或 Enter 键的问题。当然,我不提倡像您在这里所做的那样修改QWinWidget 本身(在我的情况下,我不能,因为我的代码作为第三方插件运行,但我也不会这样做)。相反,只需派生一个子类并覆盖此方法(或在我的情况下等效的 winEvent 方法)。【参考方案4】:

不知道键盘输入,但关于重绘:您是否尝试过在 CDialog 的 OnPaint 方法中调用 QWinWidget::repaint()AFTER 调用 CDialog::OnPaint()?

【讨论】:

是的。抱歉,我对此不太清楚。我尝试了两种方法,而且很奇怪,在 CDialog::OnPaint 之前或之后调用 QWinWidget::repaint 没有区别。

以上是关于MFC 对话框中的 QWinWidget 不重新绘制或响应 Tab/箭头键的主要内容,如果未能解决你的问题,请参考以下文章

mfc中如何设置编辑框\按钮的外观

ondraw 函数没有在 mfc 中调用?

MFC DLL导出对话框问题

如何将自旋控件关联到 MFC 中的不同编辑框

MFC 如何将一个对话框嵌入到视图中

在MFC 如何设置按钮的颜色