Проверьте WM_LBUTTONDOWN в теме

0

У меня есть WindowProcess, который создает Thread, когда левая кнопка мыши недоступна:

case WM_LBUTTONDOWN: {
      InvalidateRect(hwnd, NULL, TRUE);
      _beginthread(mouseMoveThread, 0, &params);
      return 0;
}

И нить mouseMoveThread устанавливает Pixel, когда левая кнопка не работает:

void mouseMoveThread(PVOID pvoid)
{
  HDC hdc; 
  PPARAMS pparams = (PPARAMS) pvoid;
  static POINT pt[MAXPOINTS];
  static int iCount;

  while(WM_LBUTTONDOWN){
    if(GetCursorPos(&pt[iCount]))
    {
        if (ScreenToClient(pparams->hwnd, &pt[iCount]))
        {
            iCount++;
            hdc = GetDC(pparams->hwnd);
            SetPixel(hdc, pt[iCount-1].x, pt[iCount-1].y,(COLORREF)RGB(0,255,0));
            ReleaseDC(pparams->hwnd, hdc);
        }
    }
}
_endthread();
}

Но как я могу проверить while-loop, что левая кнопка не работает???

  • 2
    Почему вы хотите в то время как цикл для wm_lbuttondown? Зачем вызывать GetCursorPos, если wm_lbuttondown дал вам координаты?
  • 0
    Как я могу получить координаты через WM_LBUTTONDOWN ?!
Показать ещё 7 комментариев
Теги:
winapi

1 ответ

4

Ваш поток GUI должен перенаправить соответствующие сообщения в поток рендеринга. Возможно, для вашего случая WM_MOUSEMOVE, WM_LBUTTONDOWN, WM_LBUTTONUP. Вы могли бы сообщить об этом, например, с объектами Event.

Если ваш "поток рендеринга" имеет свой собственный цикл сообщений, AttachThreadInput может представлять интерес.

Но это кажется бессмысленным. Просто делайте это в основной теме; нет причин создавать отдельный поток здесь для чего-то, что лучше всего делать в потоке графического интерфейса в любом случае. Вы пытаетесь обрабатывать события WM_MOUSEMOVE чтобы следовать указателю мыши. Для этого требуется только обработка событий в потоке графического интерфейса пользователя. Как вы это делаете, вы будете делать то же самое, кроме как из другого потока. Вы внедрили много сверток для абсолютно никакой выгоды.

Еще пара комментариев о вашем коде:

  • Вы вызываете InvalidateRect который будет вызывать WM_PAINT. SetPixel - это вызов "изгоев" - система не отслеживает это, и если вы SetPixel в WM_PAINT, ваши вызовы SetPixel всегда будут перезаписаны. По этой причине большинство приложений только WM_PAINT в WM_PAINT.
  • Если вы не SetPixel в WM_PAINT, ваши вызовы SetPixel все равно будут забыты, если ваше окно будет скрыто и пересмотрено. Обычным решением для всего этого бизнеса рисования является сохранение "заднего буфера", в котором вы рисуете какой-то частный растровый рисунок, а затем на WM_PAINT вы просто копируете его в окно.
  • Ваша петля потока не имеет смысла, но даже если бы вы могли while(WM_LBUTTONDOWN), это был бы замкнутый цикл. Если ваша мышка оставалась неподвижной, ваш цикл будет продолжать вызывать SetPixel в том же месте снова и снова при 100% CPU.
  • В вашей ветке используются static локальные переменные. Это означает, что все потоки будут использовать одни и те же переменные. Здесь у вас несколько проблем с синхронизацией. Например, если iCount изменяет между вызовами GetCursorPos и ScreenToClient.
  • Вы никогда не проверяете, выходит ли iCount за пределы.
  • Что делать, если пользователь закрывает ваше приложение, пока нажата левая кнопка? Вам нужно больше условий выхода, управляемых родительским потоком.
  • 0
    Может быть, с MessageQueue между WindowProcess и потоком? И WindowProcess отправляет сообщение, когда WM_LBUTTONDOWN имеет место?
  • 0
    Нет, вы должны просто сделать это в главном потоке, обработав эти 3 сообщения.
Показать ещё 4 комментария

Ещё вопросы

Сообщество Overcoder
Наверх
Меню