2014-02-01 2 views
0

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

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

И нить mouseMoveThread устанавливает пиксель, во время левой кнопки вниз:

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

Почему вы хотите, чтобы цикл while для wm_lbuttondown? Зачем вызывать GetCursorPos, если wm_lbuttondown дал вам coords? – Xearinox

+0

Как я могу получить координаты через WM_LBUTTONDOWN ?! – Oni1

+0

http://msdn.microsoft.com/en-us/library/windows/desktop/ms645607(v=vs.85).aspx – Xearinox

ответ

4

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

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

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

Пару другие комментарии о коде:

  • Вы звоните InvalidateRect, которые индуцируют WM_PAINT. SetPixel - это вызов «изгоев» - система не отслеживает это, и если вы рисуете в WM_PAINT, то ваши звонки SetPixel будут всегда перезаписаны. По этой причине большинство приложений только do painting in WM_PAINT.
  • Если вы не рисуете в WM_PAINT, ваши звонки SetPixel будут по-прежнему забыты, если ваше окно будет скрыто и пересмотрено. Обычным решением для всего этого бизнеса рисования является сохранение «заднего буфера», в котором вы рисуете какой-то частный растровый рисунок, затем на WM_PAINT вы просто копируете его в окно.
  • Цикл вашей нити не имеет смысла, но даже если бы вы могли while(WM_LBUTTONDOWN), это была бы плотная петля. Если ваша мышь осталась неподвижной, ваш цикл продолжил бы называть SetPixel в том же месте снова и снова с 100% -ным CPU.
  • В вашей ветке используются местные переменные static. Это означает, что все потоки будут использовать одни и те же переменные. Здесь у вас несколько проблем с синхронизацией. Например, если iCount изменяется между вызовами на GetCursorPos и ScreenToClient.
  • Вы никогда не тестируете, если iCount выходит за пределы.
  • Что делать, если пользователь закрывает приложение, пока нажата левая кнопка? Вам нужно больше условий выхода, управляемых родительским потоком.
+0

Возможно с MessageQueue между WindowProcess и Thread? И WindowProcess отправляет сообщение, когда имеет место WM_LBUTTONDOWN? – Oni1

+0

Нет, вы должны просто сделать это в основном потоке, обработав эти 3 сообщения. – tenfour

+0

Я уже пробовал это, но теперь я хотел сделать это таким образом ... – Oni1

Смежные вопросы