2009-12-26 8 views
13

Wygląda na to, że jeśli zadzwonisz pod numer ToAscii() lub ToUnicode() podczas globalnego hakowania WH_KEYBOARD_LL i zostanie naciśnięty klawisz martwy, zostanie on "zniszczony".ToAscii/ToUnicode w haku klawiatury niszczy martwe klawisze

Załóżmy na przykład, że język konfiguracji został skonfigurowany w systemie Windows jako hiszpański i chcesz wpisać w programie akcentowaną literę á. Zwykle naciskasz przycisk pojedynczego cytowania (martwy klucz), a następnie literę "a", a następnie na ekranie zostanie wyświetlony akcentowany á, zgodnie z oczekiwaniami.

Ale to nie zadziała, jeśli zadzwonisz pod numer ToAscii() lub ToUnicode() w funkcję podnośnika klawiatury niskiego poziomu. Wygląda na to, że martwy klucz jest zniszczony, więc na ekranie nie pojawia się akcentowany list á. Usunięcie wywołania powyższych funkcji rozwiązuje problem ... ale niestety, muszę mieć możliwość wywoływania tych funkcji.

Przez kilka dni używałem Google'a i chociaż wiele osób miało ten problem, nie dostarczono dobrego rozwiązania.

Każda pomoc będzie bardzo ceniona!

EDIT: Dzwonię ToAscii() do konwersji wirtualnego kod klucza i kodu skanowania odebrany w moim LowLevelKeyboardProc funkcji haka do otrzymanego znaku, który będzie wyświetlany na ekranie przez użytkownika.

Próbowałem MapVirtualKey(kbHookData->vkCode, 2), ale nie jest to "kompletne" funkcja jako ToAscii(); na przykład, jeśli naciśniesz Shift + 2, otrzymasz "2", a nie "@" (lub dowolny inny Shift + 2 dla układu klawiatury/języka użytkownika).

ToAscii() jest idealny ... aż do naciśnięcia przycisku martwego.

EDIT2: Oto funkcja hak, ze znaczenia informacji usunięte:

LRESULT CALLBACK keyboard_LL_hook_func(int code, WPARAM wParam, LPARAM lParam) { 

    LPKBDLLHOOKSTRUCT kbHookData = (LPKBDLLHOOKSTRUCT)lParam; 
    BYTE keyboard_state[256]; 

    if (code < 0) { 
     return CallNextHookEx(keyHook, code, wParam, lParam); 
    } 

    WORD wCharacter = 0; 

    GetKeyboardState(&keyboard_state); 
    int ta = ToAscii((UINT)kbHookData->vkCode, kbHookData->scanCode, 
        keyboard_state, &wCharacter, 0); 

    /* If ta == -1, a dead-key was pressed. The dead-key will be "destroyed" 
    * and you'll no longer be able to create any accented characters. Remove 
    * the call to ToAscii() above, and you can then create accented characters. */ 

    return CallNextHookEx(keyHook, code, wParam, lParam); 
} 
+0

Proszę podać kod połączenia do ToUnicode(). Skąd masz parametr lpKeyState? – jdigital

+0

@jdigital: Cóż, osobiście dzwonię do ToAscii, ale przeczytałem, że dzieje się również z ToUnicode. Moje wywołanie to zasadniczo ToAscii (kbHookData-> vkCode, kbHookData-> scanCode, GetKeyboardState(), & lpchar, 0) w funkcji przechwytywania WH_KEYBOARD_LL. Kiedy wywołanie ToAscii zwraca -1, oznacza to, że wciśnięty został klawisz martwy ... a martwy klucz jest "zniszczony", jak to wyjaśniłem powyżej. – 00010000

+0

Usunąłem moją odpowiedź, była ona całkowicie niepoprawna w oparciu o założenie, że odwoływałeś się do funkcji c-runtime do konwersji łańcuchów, a nie Win32 apis do konwersji skanerów ... przepraszam. –

Odpowiedz

3
  1. zaprzestać używania ToAscii() i używać ToUncode()
  2. pamiętać, że ToUnicode może zwrócić Ci nic na martwych klawiszy - dlatego nazywa się je martwymi kluczami.
  3. Każdy klawisz będzie zawierał kod scancode lub kod klucza wirtualnego, ale nie jest potrzebny znak.

Nie należy łączyć przycisków ze znakami - zakładając, że dowolny klawisz/przycisk ma reprezentację tekstową (Unicode) jest błędny.

Więc:

  • dla tekstu wejściowego użyć znaki zgłoszone przez Windows
  • do sprawdzania wciśnięty używać kody skanowe lub klawiszy wirtualnych (prawdopodobnie (EX gry). klucze wirtualne są lepsze).
  • dla skróty klawiaturowe używać klucze wirtualne kodów.
+0

Próbowałem używać ToUnicode(), ale to samo się dzieje ... "martwy klucz" jest zniszczony, a więc akcent podwójny pojawia się po naciśnięciu klawisza akcentu i nie mogę tworzyć żadnych akcentowanych liter. Odinstalowanie haka natychmiast rozwiązuje problem. Brak wywołania ToAscii() lub ToUnicode() natychmiast rozwiązuje również problem. – 00010000

+0

Spróbuj utworzyć kopię struktury stanu klawiatury, aby uniemożliwić systemowi Windows zmianę oryginalnego. – sorin

2

połączeń Funkcja 'ToAscii' dwa razy do prawidłowego przetwarzania martwego-key, jak w:

int ta = ToAscii((UINT)kbHookData->vkCode, kbHookData->scanCode, 
       keyboard_state, &wCharacter, 0); 
int ta = ToAscii((UINT)kbHookData->vkCode, kbHookData->scanCode, 
       keyboard_state, &wCharacter, 0); 
If (ta == -1) 
... 
+3

To tylko "zabija" martwy klucz dla mnie. Na przykład. "ë" staje się "e", ale dwukrotne naciśnięcie martwego klawisza nadal daje np.¨¨ –

2

Wywołanie ToAscii lub ToUnicode dwukrotnie jest odpowiedzią. Znalazłem to i przekonwertowałem na Delphi i działa!

cnt:=ToUnicode(VirtualKey, KeyStroke, KeyState, chars, 2, 0); 
cnt:=ToUnicode(VirtualKey, KeyStroke, KeyState, chars, 2, 0); //yes call it twice 
+0

Jest nieco lepszy, ponieważ mój znak "^" jest wyświetlany po drugim naciśnięciu klawisza, zgodnie z oczekiwaniami, ale nie działa, ponieważ akcent nie pasuje do litery, ponieważ powinien powodować "ô", ale tylko produkuje 'o' – Flox

+0

Właściwie twoja odpowiedź jest taka sama jak @ Niebieskie oczy poniżej: https: //stackoverflow.com/a/3625039/2165463 – Flox

0

kopiuję vkCode w kolejce i zrobić konwersję z innego wątku

@HOOKPROC 
def keyHookKFunc(code,wParam,lParam): 
    global gkeyQueue 
    gkeyQueue.append((code,wParam,kbd.vkCode)) 
    return windll.user32.CallNextHookEx(0,code,wParam,lParam) 

Ma to tę zaletę, że nie opóźnia przetwarzanie klucza przez os

1

Dość stary gwintu. Niestety nie zawierał odpowiedzi, której szukałem i żadna z odpowiedzi nie działała prawidłowo. W końcu rozwiązałem problem, sprawdzając funkcję MSB funkcji MapVirtualKey przed wywołaniem ToUnicode/ToAscii. Wydaje się działać jak czar:

if(!(MapVirtualKey(kbHookData->vkCode, MAPVK_VK_TO_CHAR)>>(sizeof(UINT)*8-1) & 1)) { 
    ToAscii((UINT)kbHookData->vkCode, kbHookData->scanCode, 
     keyboard_state, &wCharacter, 0); 
} 

Cytowanie MSDN na wartości zwracanej MapVirtualKey, jeśli jest stosowany MAPVK_VK_TO_CHAR:

[...] Martwe klawisze (znaki diakrytyczne) są wskazane przez ustawienie górny bit wartości zwracanej. [...]

+0

czy mógłbyś bardziej rozwinąć więcej? Nie dostaję twojego kodu, a co jeśli nie wprowadzisz if()? nic nie robić? –

+1

W przypadku, gdy nie jest wprowadzane, jeśli bieżący klawisz jest wciśnięty, jest to martwy klawisz. W zależności od tego, co chcesz osiągnąć, możesz na nie zareagować lub po prostu zignorować, na wypadek, gdybyś chciał tylko słuchać nieumartych naciśnięć klawiszy. Mam nadzieję że to pomoże. –

+0

Dziękuję, mam to –

Powiązane problemy