0

My app have a QLineEdit and a QPushButton which not respond properly to inputs of keyboard and mouse (the QLineEdit is not receiving the keyboard inputs, and both the QLineEdit and QPushButton are not receiving mouse inputs) when my app is handling these Windows Events:

bool MainWindow::winEvent(MSG *msg, long *result)
{
    HWND hWnd = msg->hwnd;
    UINT message = msg->message;
    WPARAM wParam = msg->wParam;
    LPARAM lParam = msg->lParam;

    bool retval = true;
    LRESULT lRet = 0;

    switch(message)
    {
    case WM_PAINT:
    {
        HDC hDC = GetWindowDC(hWnd);
        PaintCustomCaption(hWnd, hDC); //Method responsible to draw the image at the non client area
        DeleteDC(hDC);
        break;
    }
    case WM_NCHITTEST:
    {
        lRet = HitTestNCA(hWnd, lParam); //Method responsible to deal with the window resizing and moving
        DwmDefWindowProc(hWnd, message, wParam, lParam, &lRet);
        break;
    }
    case WM_NCCALCSIZE:
    {
        break;
    }
    default:
    {
        retval = false;
        DwmDefWindowProc(hWnd, message, wParam, lParam, &lRet);
        break;
    }
    }

    *result = lRet;
    if(retval) return true;

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

If I remove such code, my Qt widgets works properly, but I need these codes because my app is drawing an image at the non client area of my window.

Is possible to handle the Windows Events listed above keeping my Qt widgets responsive to keyboard and mouse?

jabaldonedo
  • 25,822
  • 8
  • 77
  • 77
Antonio Dias
  • 2,751
  • 20
  • 40
  • First thing I would have tried is to remove `WM_NCHITTEST` (and possibly `default:` case) and see if that changes anything. I would suspect that for some reason your events might get discarded as hitting non-client area before getting to your controls. BTW Why does your `default:` case call `DwmDefWindowProc`? – j_kubik Jun 12 '13 at 23:27
  • By removing all the `switch`, my controls become responsive again, but the problem is: I need that to draw an image at the non client area. – Antonio Dias Jun 13 '13 at 00:05
  • I did't mean all of them - I just meant the case with `WM_NCHITTEST`. Later on you will worry if it does what you need it for - this is just to figure out why your controls freeze. If after removing this specific `case` they will unfreeze, you will know that your `WM_NCHITTEST` response is source of the problem. – j_kubik Jun 13 '13 at 02:03
  • @j_kubik Here my results: By removing the `WM_NCHITTEST`: controls stays unresponsive. By removing the `WM_NCCALCSIZE` also: controls stays unresponsive. By removing the `WM_NCHITTEST`, `WM_NCCALCSIZE` and the `WM_PAINT` from the `switch`: controls fully responsible, but no image draw. – Antonio Dias Jun 13 '13 at 03:10

2 Answers2

2

You can try calling QCoreApplication::processEvents() periodically while handling those Window Events.

ariwez
  • 1,309
  • 17
  • 20
1

You need to either profile that code and speed it up so it doesn't block the event loop, or you need to run that code in a separate thread.

For profiling, I recommend looking at valgrind, callgrind, and kcachegrind.

As for threads, most Qt applications are single-threaded by default, so if you don't return processing back to the event loop soon enough, UI events will get clogged up in the event loop and not get processed until you return processing to event loop.

Creating new threads is pretty easy in Qt. See this example from the Qt Docs on QThread:

void MyObject::putWorkerInAThread()
{
    Worker *worker = new Worker;
    QThread *workerThread = new QThread(this);

    connect(workerThread, &QThread::started, worker, &Worker::doWork);
    connect(workerThread, &QThread::finished, worker, &Worker::deleteLater);
    worker->moveToThread(workerThread);

    // Starts an event loop, and emits workerThread->started()
    workerThread->start();
}
Cory Klein
  • 51,188
  • 43
  • 183
  • 243
  • The Windows Events aren't asynchronous? – Antonio Dias Jun 12 '13 at 22:50
  • If you connected the `clicked` signal to something in your own code, then the `clicked` signal may fire asynchronously, but the code that it is connected to won't be executed until control returns to the event loop. – Cory Klein Jun 12 '13 at 22:54
  • Painting non-client area of window is very unlikely to create such a problem - it's much more likely that events that you are processing on your own are somehow connected to inactive widgets. – j_kubik Jun 12 '13 at 23:24
  • +1 by the correct way to create threads, however this not solves my problem and I can't accept that answer as correct. – Antonio Dias Jul 04 '13 at 04:07