2011-01-19 51 views
6

Tôi đang thực hiện một ứng dụng trò chuyện thoại sử dụng phím push-to-talk. Tôi đã làm một cái móc để nó sẽ đăng ký push-to-talk bên ngoài ứng dụng quá.Bàn phím Các vấn đề về móc

HHOOK hHook = SetWindowsHookEx(WH_KEYBOARD_LL,(HOOKPROC)pushtotalk,0,0); 



LRESULT CALLBACK pushtotalk(int key, WPARAM wParam,LPARAM lParam) { 
if (key < 0) { 
    return (CallNextHookEx(hook,key,wParam,lParam)); 
} 
else if (connected) { 
    KBDLLHOOKSTRUCT* kbdll = (KBDLLHOOKSTRUCT*)lParam; 
    if (kbdll ->vkCode == 75 && wParam == WM_KEYDOWN) { 
     MessageBox(mainhWnd,"KEYSTART","KEYSTART",0); 
    } 
    else if (kbdll ->vkCode == 75 && wParam == WM_KEYUP) { 
     MessageBox(mainhWnd,"KEYSTOP","KEYSTOP",0); 

    } 
} 

return (CallNextHookEx(hook,key,wParam,lParam)); 
} 

Sự cố;

1) Đôi khi, (ví dụ như việc thực hiện đầu tiên của proc trong ứng dụng), proc gây ra một hệ thống đóng băng 5 giây trước khi tiếp tục. Tại sao?

2) Móc chỉ hoạt động trên quy trình đã được bắt đầu trước khi ứng dụng của tôi bắt đầu, nếu tôi bắt đầu một chương trình văn bản sau khi bắt đầu ứng dụng của tôi, móc sẽ không đăng ký. có cách sửa nào cho nó không?

3) Nếu tôi giữ phím trong ~ 3 giây, rất nhiều MessageBox hiển thị rõ ràng, nhưng sau đó, proc sẽ không bao giờ đăng ký một phím khác bị đẩy xuống, vì vậy tôi đoán bằng cách nào đó tôi bị ngắt kết nối khỏi chuỗi móc?

Cheers

EDIT: Đây là vòng lặp thông điệp chính về việc áp dụng

LRESULT CALLBACK WindowProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { 
switch(message) { 
    case WM_COMMAND: 
     switch (LOWORD(wParam)) { 
      case ID_MENU_EXIT: 
       SendMessage(hWnd,WM_CLOSE,0,0); 
       break; 

      case ID_MENU_PREFERENCES: 
       voiceManager->send((void*) "1"); 
       break; 

      case ID_BUTTON_CONNECT: 
       onConnect(hWnd); 
       break; 

      case ID_BUTTON_DISCONNECT: 
       onDisconnect(hWnd); 
       break; 

      case ID_BUTTON_SEND: 
       onSendText(hWnd); 
       break; 

      default: 
       break; 
     } 
     break; 
    case SOCKET_TCP: 
     switch (lParam) { 
      case FD_READ: 
       { 
       // Disable repeated FD_READ call while we process message 
       WSAAsyncSelect(wParam,hWnd,SOCKET_TCP, FD_WRITE | FD_ACCEPT | FD_CLOSE); 

       // first four bytes is packet size 
       // second four bytes are used to identify type of msg 
       char* psize = (char*)malloc(5); 
       char* ptype = (char*)malloc(5); 
       psize[4] = '\0'; 
       ptype[4] = '\0'; 

       recv(wParam,psize,4,0); 
       recv(wParam,ptype,4,0); 

       // allocate memory for the buffer 
       int size_to_recv = atoi(psize);  
       char* textbuff = (char*)malloc(size_to_recv); 

       // receive 
       int i = size_to_recv; 
       while (i > 0) { 
        int read = recv(wParam,textbuff,i,0); 
        i = i - read; 
       } 

       // handle msg depending on type 
       switch(identifyMsg(ptype)) { 
        case 1: 
         // handle 'text' msg 
         onReadText(hWnd,textbuff); 
         break; 

        case 2: 
         // handle 'name' msg 
         onReadName(hWnd,textbuff); 
         break; 
        case 3: 
         // handle 'list' msg 
         onReadList(hWnd,textbuff); 
         break; 
        case 4: 
         // handle 'remv' msg 
         onReadRemv(hWnd,textbuff,size_to_recv); 
         break; 
        case 5: 
         // handle 'ipad' msg -- add ip 
         voiceManager->addParticipant(inet_addr(textbuff)); 
         break; 
        case 6: 
         // handle 'iprm' msg -- remove ip 
         voiceManager->removeParticipant(inet_addr(textbuff)); 
         break; 

        default: 
         break; 
       } 

       // re-enable FD_READ 
       WSAAsyncSelect(wParam,hWnd,SOCKET_TCP, FD_WRITE | FD_ACCEPT | FD_READ | FD_CLOSE); 

       // free resources 
       free(psize); 
       free(ptype); 
       free(textbuff); 
       break; 
       } 

      case FD_WRITE: 
       break; 

      case FD_CONNECT: 
       break; 

      case FD_CLOSE: 
       onDisconnect(hWnd); 
       break; 

      default: 
      break; 
     } 
     break; 



    case WM_PAINT: 
     paintText(hWnd); 
     break; 

    case WM_DESTROY: 
     shutdownConnection(hWnd); 
     // reset window procs 
     SetWindowLong(GetDlgItem(hWnd,ID_EDIT_SEND), GWL_WNDPROC,(LONG) OriginalEditProc); 
     SetWindowLong(GetDlgItem(hWnd,ID_EDIT_IP), GWL_WNDPROC,(LONG) OriginalEditProc); 
     PostQuitMessage(0); 
     return 0; 
     break; 

    case WM_CLOSE: 
     DestroyWindow(hWnd); 
     break; 

    default: 
     break; 
} 


return DefWindowProc(hWnd, message, wParam, lParam); 
} 


LRESULT CALLBACK sendEditProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { 
if (message == WM_CHAR) { 
    if (wParam == VK_RETURN) { 
     onSendText(GetParent(hWnd)); 
     return 0; 
    } 
} 
if (message == WM_KEYUP || message == WM_KEYDOWN) { 
    if (wParam == VK_RETURN) { 
     return 0; 
    } 
} 
return CallWindowProc(OriginalEditProc, hWnd, message, wParam,lParam); 
} 

đâu sendEditProc là một phụ/lớp cha được thiết kế để đánh chặn 'nhập' phím khi bên trong một kiểm soát chỉnh sửa 'gửi' Liệu sự giúp đỡ này?

Đây là vòng lặp tin nhắn; đó là tiêu chuẩn để không có gì lạ mắt có thể đi sai afaik :)

while (GetMessage(&msg, NULL,0,0)) { 
    TranslateMessage(&msg); 
    DispatchMessage(&msg); 
} 
+0

Đây có phải là tệp DLL không? – soulseekah

+0

Không, vì tôi đã sử dụng WH_KEYBOARD_LL, tôi đã đặt proc trong ứng dụng chính. – KaiserJohaan

+0

Nếu bạn nhận xét các cuộc gọi MessageBox (hoặc thay thế bằng một cái gì đó như MessageBeep), bạn vẫn có những vấn đề tương tự? – Tadmas

Trả lời

3

Bạn đang gọi CallNextHookEx một lần quá nhiều lần. Nếu key < 0 return CallNextHookEx, nếu không return 0.

Sự cố bạn đang gặp phải liên quan đến lặp lại bàn phím và các phương thức MessageBox hoặc MessageBeep là các cuộc gọi rất tốn kém. Hãy thử kiểm tra này:

HHOOK hHook; 
BOOL bTalkEnabled = FALSE; 

LRESULT CALLBACK pushtotalk(int key, WPARAM wParam, LPARAM lParam) 
{ 
    if (key < 0) 
     return CallNextHookEx(hHook, key, wParam, lParam); 

    KBDLLHOOKSTRUCT* kbdll = (KBDLLHOOKSTRUCT*)lParam; 
    if (kbdll->vkCode == VK_F11) 
    { 
     BOOL bStarted = FALSE; 
     BOOL bStopped = FALSE; 

     if (wParam == WM_KEYDOWN) 
     { 
      if (!bTalkEnabled) 
      { 
       bStarted = TRUE; 
       bTalkEnabled = TRUE; 
      } 
     } 
     else if (wParam == WM_KEYUP) 
     { 
      if (bTalkEnabled) 
      { 
       bStopped = TRUE; 
       bTalkEnabled = FALSE; 
      } 
     } 

     if (bStarted) 
      OutputDebugString(L"Pushed\r\n"); 
     if (bStopped) 
      OutputDebugString(L"Released\r\n"); 
    } 

    return 0; 
} 

Bạn có thể giám sát các chuỗi debug bằng cách chạy ứng dụng trong trình gỡ lỗi (kiểm tra cửa sổ Output), hoặc bạn có thể nhận DebugView và xem đó.

Lưu ý rằng tôi không kiểm tra connected như bạn đã làm. Bạn không muốn thực hiện việc kiểm tra trong móc, làm điều đó bên ngoài móc và chỉ sử dụng móc để xác định nếu phím được nhấn hoặc không ép.

+0

Tôi sẽ kiểm tra như thế nào 'kết nối' và không sử dụng móc nếu thiết lập của nó sai? Bạn có nghĩa là để tạo ra các móc khi kết nối và xóa nó khi ngắt kết nối ví dụ? Ngoài ra, nếu tôi trả về 0 như bạn đã làm ở cuối của proc, không phải là 'đánh chặn' các thông điệp báo chí quan trọng và cản trở chúng được gửi đến các ứng dụng hiện đang tập trung? Ví dụ, nếu tôi viết "k" trong một trình soạn thảo văn bản trong khi chương trình của tôi đang chạy, tôi muốn bắt "k" nhưng tôi cũng không muốn can thiệp vào đầu ra của trình soạn thảo. CallNextHook chuyển tin nhắn đến cho anh chàng actuall, người được mệnh danh là đúng? – KaiserJohaan

+0

Bạn cần biết trạng thái của phím push-to-talk (xuống hoặc lên). Làm điều đó trong trình xử lý như tôi đã làm ở đây. Bạn có thể sẽ muốn làm một cái gì đó khác với 'OutputDebugString' trong phản ứng và mã đó có thể kiểm tra trạng thái kết nối. – Tergiver

+0

Đối với 'CallNextHookEx', bạn là chính xác. Tôi đã xử lý móc của tôi bối rối. Bạn đã sửa nó lần đầu tiên. http://msdn.microsoft.com/en-us/library/ms644985.aspx – Tergiver

Các vấn đề liên quan