4

I am using a QWinWidget inside of an MFC dialog and the QWinWidget is not drawing itself correctly and it is not handling keyboard input correctly.

Repainting [Unsolved]

Within the QWinWidget, I have a QTableWidget. When I scroll the QTableWidget, it does not redraw itself until I stop scrolling, at which point it redraws everything. Similarly, I can type into cells in the QTableWidget and the control is not updated until I force it to re-update by scrolling up or down (it re-updates when the scrolling stops).

Since this QWinWidget is housed in an MFC CDialog, I tried overriding the CDialog's OnPaint method and only call the QWinWidget::repaint method, however this has the opposite problem where now only the QWinWidget is updated and the CDialog is never redrawn, resulting in artifacts. If I call QWinWidget::repaint and CDialog::OnPaint, the result is the same as not overriding the OnPaint method. Has anyone ever seen this problem or know how to resolve it?

Keyboard Input [Solved]

None of the controls within the QWinWidget respond to the tab key or arrow keys correctly. The tab/arrow keys simply skip over the entire QWinWidget (and all child controls). Even if I click inside the QWinWidget and select a control, the next time I press the tab key, it skips the focus completely out of the entire QWinWidget.

I noticed that the QWinWidget has two functions, QWinWidget::focusNextPrevChild and QWinWidget::focusInEvent and both of them have a comment header saying "\reimp". Am I supposed to override these functions in order to get correct tab functionality? If so, how can these functions be implemented for correct tab functionality.

Andrew Garrison
  • 6,977
  • 11
  • 50
  • 77

4 Answers4

4

I have fixed the keyboard input issue. The QWinWidget class needed some changes:

in the QWinWidget::init method, the WS_TABSTOP must be added to the window style:

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

Also, the QWinWidget::winEvent method needs to respond to the WM_GETDLGCODE to let Windows know that it is interested in receiving key/tab inputs. I had to add this if block:

if(msg->message == WM_GETDLGCODE)
{
   *result = DLGC_WANTARROWS | DLGC_WANTTAB;
   return(true);
}

I am still working on getting the widget to paint properly.

Andrew Garrison
  • 6,977
  • 11
  • 50
  • 77
1

I don't know about whether you need to reimplement the focusNextPrevChild() and focusInEvent() functions, but I do know that the "\reimp" in the comment header is part of Qt's documentation generation, which merely specifies that the function was a reimplementation of another function in a parent class.

Caleb Huitt - cjhuitt
  • 14,785
  • 3
  • 42
  • 49
1

Thanks! It works for me! I have fixed an arrow keys navigation issue for a QTableView inside a QWinWidget. I am using Qt5.3.0 and qtwinmigrate 2.8. The QWinWidget::nativeEvent method needs to be modified.

#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;
}
  • This approach worked great for me in Qt 4.8 too. I needed to embed a `QPlainText` widget in a native Win32 dialog window, and had trouble with it not accepting Tab or Enter keys. Of course, I wouldn't advocate modifying `QWinWidget` itself as you've done here (in my case I can't, due to my code operating as a third-party plugin, but I also wouldn't anyway). Instead, just derive a subclass and override this method (or in my case the equivalent `winEvent` method). – paddy Jan 22 '21 at 04:19
0

No idea about the keyboard input, but concerning the repainting: have you tried calling QWinWidget::repaint() in the CDialog's OnPaint method AFTER calling the CDialog::OnPaint()?

fretje
  • 8,322
  • 2
  • 49
  • 61
  • Yes. Sorry I was not more clear about that. I tried it both ways and strangely enough, calling QWinWidget::repaint before or after CDialog::OnPaint makes no difference. – Andrew Garrison Jul 01 '09 at 13:57