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/箭头键的主要内容,如果未能解决你的问题,请参考以下文章