2013-06-12 6 views
0

내 앱이 키보드 및 마우스의 입력에 올바르게 응답하지 않는 QLineEditQPushButton이 있습니다. QLineEdit은 키보드 입력을 수신하지 않으며 QLineEditQPushButton은 내 Windows 이벤트를 처리 할 때 마우스 입력을 수신하지 않습니다. :Windows 이벤트를 처리하는 동안 키보드 및 마우스에 응답하는 Qt 위젯을 유지하는 방법은 무엇입니까?

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); 
} 

나는 그런 코드를 제거하면, 내 Qt는 위젯이 제대로 작동하지만 내 응용 프로그램 내 창의 비 클라이언트 영역에서 이미지를 그리기 때문에 나는이 코드가 필요합니다.

위에 나열된 Windows 이벤트를 처리하여 Qt 위젯을 키보드 및 마우스에 맞게 유지할 수 있습니까?

+0

내가 처음 시도한 것은 WM_NCHITTEST (그리고 아마도'default :'case)를 제거하고 그 것이 변경되는지 확인하는 것이다. 어떤 이유로 귀하의 이벤트가 귀하의 컨트롤에 도달하기 전에 비 클라이언트 영역을 타격하여 폐기 될 수 있다고 의심됩니다. 왜'default :'의 경우'DwmDefWindowProc'를 호출합니까? –

+0

모든 스위치를 제거하면 컨트롤이 다시 반응하지만 문제는 다음과 같습니다. 비 클라이언트 영역에서 이미지를 그려야합니다. –

+0

나는 그 모든 것을 의미하지는 않는다. - 나는 단지 WM_NCHITTEST로 그 사건을 의미했다. 나중에 당신이 필요로하는 일을한다면 걱정할 것입니다. 이것은 당신의 통제가 왜 멈추는 지 알아내는 것입니다. 이 특별한'case'를 제거한 후에 해제하면,'WM_NCHITTEST' 응답이 문제의 근원임을 알게 될 것입니다. –

답변

1

이벤트 루프를 차단하지 않도록 코드의 프로필을 작성하고 속도를 높여야합니다. 그렇지 않으면 별도의 스레드에서 해당 코드를 실행해야합니다.

프로파일 링을 위해 valgrind, callgrind 및 kcachegrind를 살펴 보는 것이 좋습니다.

스레드의 경우 대부분의 Qt 응용 프로그램은 기본적으로 단일 스레드이므로 이벤트 루프로 곧 처리를 되돌리지 않으면 UI 이벤트가 이벤트 루프에서 막히게되어 사용자가 처리를 이벤트 루프로 리턴하십시오.

새로운 스레드를 만드는 것은 Qt에서 매우 쉽습니다. QThread에 Qt는 문서에서이 예제를 참조하십시오 : 그 윈도우 이벤트를 처리하는 동안

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(); 
} 
+0

Windows 이벤트가 비동기 적이 아닙니까? –

+0

자신의 코드에서'clicked '신호를 연결했다면,'clicked'신호는 비동기 적으로 발생하지만 제어가 이벤트 루프로 돌아 오기 전까지는 연결된 코드는 실행되지 않습니다. –

+0

창의 클라이언트가 아닌 영역을 그릴 경우 이러한 문제가 발생하지 않을 가능성이 높습니다. 직접 처리하는 이벤트가 비활성 위젯에 연결되는 가능성이 훨씬 커집니다. –

2

당신은 정기적으로 QCoreApplication::processEvents()를 호출 시도 할 수 있습니다.