virtual key code to OEM char

0

pisze pod windows, mam input w postaci virtualnych kodow, a potrzebuje je przetlumaczyc na znaki, zgodnie z layoutem klawiatury. Czyli zamienic A na a jesli shift wylaczony, etc. Cos takiego jak TranslateMessage(), ale zeby zwrocilo a nie wysylalo do kolejki.

Znalazlem kilka funkcji ktore moga to robic, ale niestety wymagaja 256 tablicy z GetKeyboardState().

Wywolanie tej funkcji jest bezcelowe, bo gdy dostane znak to znaczy ze shift juz zostal usuniety z kolejki.
Zeby chociaz GetKeyboardState() zwracalo aktualny stan... Moge zawsze or'owac najwyzszy i najnizszy bit, powinno dzialac ale takie rozwiazanie to ostatecznosc.

Czy ejst jaks sposob, by skopiowac dzialanie TranslateMessage() i uzyskac wynik?

0

tu masz w delphi (chyba) cały kod do pobrania nazwy klawisza. Działa na 100% bo używam tego przy wirtualnej klawiaturze. Jednakże nie jest to unicode więc jak sobie włączysz np. grecką klawiaturę to dostaniesz same puste nazwy. Najprawdopodobniej pomoże zamiast ToAscii zastosowanie ToUnicode

  TKey    = (vkA=0, vkB, vkC, vkD, vkE, vkF, vkG, vkH, vkI, vkJ, vkK, vkL, vkM, vkN,
    vkO, vkP, vkQ, vkR, vkS, vkT, vkU, vkV, vkW, vkX, vkY, vkZ,
    vk0=26, vk1, vk2, vk3, vk4, vk5, vk6, vk7, vk8, vk9,
    vkF1, vkF2, vkF3, vkF4, vkF5, vkF6, vkF7, vkF8, vkF9, vkF10, vkF11, vkF12,
    vkSubtract, vkEqual, vkSpace, vkBackspace, vkLBracket, vkRBracket,
    vkSemicolon, vkQuote, vkComma, vkDot, vkSlash, vkBackSlash,
    vkTab, vkEsc, vkEnter, vkShift, vkControl, vkLAlt, vkRAlt,
    vkCapsLock, vkNumLock,
    vkInsert, vkDelete, vkHome, vkEnd, vkPgUp, vkPgDown,
    vkLeft, vkRight, vkUp, vkDown,
    vkNum0, vkNum1, vkNum2, vkNum3, vkNum4, vkNum5, vkNum6, vkNum7, vkNum8, vkNum9,
    vkDecimal, vkGrayDivide, vkGrayMultiply, vkGraySubtract, vkGrayAdd);

procedure TIKeyButton.SetCaption;
var
  KeyCaption: string;
  OldCaption: string;
begin
  //jesli numlock off to trzeba podmienic klawisze na sterujace
  if FKey in [vkNum0 .. vkDecimal] then
  begin
    FProperKey := FKey;
    case FKey of
      vkNum0: if GetNumLockState then
          FProperKey := vkInsert;
      vkNum1: if GetNumLockState then
          FProperKey := vkEnd;
      vkNum2: if GetNumLockState then
          FProperKey := vkDown;
      vkNum3: if GetNumLockState then
          FProperKey := vkPgDown;
      vkNum4: if GetNumLockState then
          FProperKey := vkLeft;
      vkNum5: if GetNumLockState then
          FProperKey := vk5;
      vkNum6: if GetNumLockState then
          FProperKey := vkRight;
      vkNum7: if GetNumLockState then
          FProperKey := vkHome;
      vkNum8: if GetNumLockState then
          FProperKey := vkUp;
      vkNum9: if GetNumLockState then
          FProperKey := vkPgUp;
      vkDecimal: if GetNumLockState then
          FProperKey := vkDelete;
    end;
    CalcData;
  end;

  KeyCaption := GetCharFromVKey(FProperKey);
  if (Length(Trim(KeyCaption)) = 0) or (FProperKey in [vkBackspace]) then
    KeyCaption := KeyName(FProperKey);


  if KeyCaption = '&' then
    KeyCaption := '&&'
  else if AnsiLowerCase(KeyCaption) = 'insert' then
    KeyCaption := 'Ins'
  else if AnsiLowerCase(KeyCaption) = 'delete' then
    KeyCaption := 'Del'
  else if AnsiLowerCase(KeyCaption) = 'page up' then
    KeyCaption := 'PgUp'
  else if AnsiLowerCase(KeyCaption) = 'page down' then
    KeyCaption := 'PgDn'
  else if FProperKey = vkCapsLock then
    KeyCaption := 'Caps'
  else if FProperKey = vkRAlt then
    KeyCaption := 'Pl';

  OldCaption := KeyCaption;
  case FProperKey of
    vkBackspace: KeyCaption := '¬ľ';
    vkEnter: KeyCaption := 'ż';
    vkLeft: KeyCaption := '¬';
    vkRight: KeyCaption := '®';
    vkUp: KeyCaption := '­';
    vkDown: KeyCaption := 'Ż';
  end;

  if KeyCaption <> OldCaption then
    Font.Name := 'Symbol'
  ELSE
    Font.Name := 'Microsoft Sans Serif';

  Caption := KeyCaption;
end;

function TIKeyButton.GetNumLockState: boolean;
var
  KeyState: TKeyboardState;
begin
  Win32Check(GetKeyboardState(KeyState));
  Result := KeyState[VK_NUMLOCK] = $0;
end;

function TIKeyButton.GetCharFromVKey(Key: TKey): string;
var
  KeyState: TKeyboardState;
  RetCode:  integer;
begin
  Win32Check(GetKeyboardState(KeyState));
  if ((KeyState[VK_CONTROL] and $80) = $80) and ((KeyState[VK_MENU] and $80) = $0) then
    KeyState[VK_CONTROL] := KeyState[VK_CONTROL] and $7F;

  SetLength(Result, 2);
  RetCode := ToAscii(TKeyToVKey(Key), MapVirtualKey(TKeyToVKey(Key), 0),
    KeyState, @Result[1], 0);
  case RetCode of
    1: SetLength(Result, 1);
    2: ;
    else
      Result := '';
  end;
end;

function TIKeyButton.KeyName(Key: TKey): string;
var
  vKey: cardinal;
begin
  vKey := TKeyToVKey(Key);
  vKey := MapVirtualKey(vKey, 0);
  if Key in ExtKey then
    vKey := vkey or $100;
  SetLength(Result, 128);
  SetLength(Result, GetKeynameText(vKey shl 16, @Result[1], Length(Result)));
end;

function TIKeyButton.TKeyToVKey(Key: TKey): smallint;
begin
  case Key of
    vkA: Result  := VkKeyScan('A');
    vkB: Result  := VkKeyScan('B');
    vkC: Result  := VkKeyScan('C');
    vkD: Result  := VkKeyScan('D');
    vkE: Result  := VkKeyScan('E');
    vkF: Result  := VkKeyScan('F');
    vkG: Result  := VkKeyScan('G');
    vkH: Result  := VkKeyScan('H');
    vkI: Result  := VkKeyScan('I');
    vkJ: Result  := VkKeyScan('J');
    vkK: Result  := VkKeyScan('K');
    vkL: Result  := VkKeyScan('L');
    vkM: Result  := VkKeyScan('M');
    vkN: Result  := VkKeyScan('N');
    vkO: Result  := VkKeyScan('O');
    vkP: Result  := VkKeyScan('P');
    vkQ: Result  := VkKeyScan('Q');
    vkR: Result  := VkKeyScan('R');
    vkS: Result  := VkKeyScan('S');
    vkT: Result  := VkKeyScan('T');
    vkU: Result  := VkKeyScan('U');
    vkV: Result  := VkKeyScan('V');
    vkW: Result  := VkKeyScan('W');
    vkX: Result  := VkKeyScan('X');
    vkY: Result  := VkKeyScan('Y');
    vkZ: Result  := VkKeyScan('Z');
    vk0: Result  := VkKeyScan('0');
    vk1: Result  := VkKeyScan('1');
    vk2: Result  := VkKeyScan('2');
    vk3: Result  := VkKeyScan('3');
    vk4: Result  := VkKeyScan('4');
    vk5: Result  := VkKeyScan('5');
    vk6: Result  := VkKeyScan('6');
    vk7: Result  := VkKeyScan('7');
    vk8: Result  := VkKeyScan('8');
    vk9: Result  := VkKeyScan('9');
    vkF1: Result := VK_F1;
    vkF2: Result := VK_F2;
    vkF3: Result := VK_F3;
    vkF4: Result := VK_F4;
    vkF5: Result := VK_F5;
    vkF6: Result := VK_F6;
    vkF7: Result := VK_F7;
    vkF8: Result := VK_F8;
    vkF9: Result := VK_F9;
    vkF10: Result := VK_F10;
    vkF11: Result := VK_F11;
    vkF12: Result := VK_F12;
    vkSubtract: Result := VkKeyScan('-');
    vkEqual: Result := VkKeyScan('=');
    vkBackspace: Result := VK_BACK;
    vkLBracket: Result := VkKeyScan('[');
    vkRBracket: Result := VkKeyScan(']');
    vkSemicolon: Result := VkKeyScan(';');
    vkQuote: Result := VkKeyScan('''');
    vkComma: Result := VkKeyScan(',');
    vkDot: Result := VkKeyScan('.');
    vkSlash: Result := VkKeyScan('/');
    vkBackSlash: Result := VkKeyScan('\');
    vkTab: Result := VK_TAB;
    vkEsc: Result := VK_ESCAPE;
    vkSpace: Result := VK_SPACE;
    vkEnter: Result := VK_RETURN;
    vkShift: Result := VK_SHIFT;
    vkControl: Result := VK_CONTROL;
    vkLAlt: Result := VK_MENU;
    vkRAlt: Result := VK_RMENU;
    vkCapsLock: Result := VK_CAPITAL;
    vkNumLock: Result := VK_NUMLOCK;
    vkInsert: Result := VK_INSERT;
    vkDelete: Result := VK_DELETE;
    vkHome: Result := VK_HOME;
    vkEnd: Result := VK_END;
    vkPgUp: Result := VK_PRIOR;
    vkPgDown: Result := VK_NEXT;
    vkLeft: Result := VK_LEFT;
    vkRight: Result := VK_RIGHT;
    vkUp: Result := VK_UP;
    vkDown: Result := VK_DOWN;
    vkNum0: Result := VK_NUMPAD0;
    vkNum1: Result := VK_NUMPAD1;
    vkNum2: Result := VK_NUMPAD2;
    vkNum3: Result := VK_NUMPAD3;
    vkNum4: Result := VK_NUMPAD4;
    vkNum5: Result := VK_NUMPAD5;
    vkNum6: Result := VK_NUMPAD6;
    vkNum7: Result := VK_NUMPAD7;
    vkNum8: Result := VK_NUMPAD8;
    vkNum9: Result := VK_NUMPAD9;
    vkGrayDivide: Result := VK_DIVIDE;
    vkGrayMultiply: Result := VK_MULTIPLY;
    vkGraySubtract: Result := VK_SUBTRACT;
    vkGrayAdd: Result := VK_ADD;
    vkDecimal: Result := VK_DECIMAL;
    else
      Result := 0;
  end;
end;

  ExtKey := [vkUp, vkDown, vkLeft, vkRight, vkHome, vkEnd, vkPgUp,
    vkPgDown, vkInsert, vkDelete, vkNumLock, vkGrayDivide, vkRAlt];
  ChangeKey := [vkNumLock, vkCapsLock, vkShift, vkRAlt];
  OneClickKey := [vkShift, vkLAlt, vkRAlt, vkControl];
  OnOffKey := [vkNumLock, vkCapsLock];
0

To jakas kpina chyba, nie mam zamiaru recznie sprawdzac klawiszy shift/alt/ctrl i innych bo takowe moga sie pojawic/juz sa.

TranslateMessage bierze virtual code (WM_KEYDOWN), sprawdza klawisze kontrolne (num/shift/caps i mase innych) w zaleznosci od tablicy 'keyboard layout' i uwzgledniajac wszsytkie te parametry wysyla WM_CHAR z kodem znaku.

Oczywiscie mam zamiar pracowac tylko na unicode, czyli kazdy znak = 2 bajty. Tak zeby nie bylo problemow, bardziej uniwersalne.

0

a kto ci każe - widać, że nie zrozumiałeś tego kodu. Ja nie operuję na virtual code tylko na własnym typie - TKey. Do zamiany tego typu na virtual code służy funkcja TKeyToVKey.

Poza tym napisy np. insert, page down, itp są dla mnie za długie dlatego zamieniam je na krótsze. Zauważ, że dla & dostajesz &, który jeśli go dasz jako text przycisku nic ci nie pokaże - trzeba go też zamienić na &&. Na koniec backspace, enter i strzałki zamieniam na ich graficzne odpowiedniki.

BTW nie zdziw się jak ci ToAscii zwróci niepoprawny text dla klawiszy numerycznych przy włączonym numlock'u.

Następnym razem dostaniesz odpowiedź zawężającą się do 3 słów:
ToAscii, ToUnicode, GetKeynameText + F1
i szukaj sobie sam co z tym zrobić...

0

moze i nie zrozumialem tego kodu bo nie znam delphi w najmniejszym stopniu.
pisze tylko w c i asm, wiec wymacz, ze twor stworzony tylko pod windows ktorego uzytkowanie (afair) jest nielegalne nie jest mi znany.

po prostu skojazylem ten kod z tona podobnego jakiego znalazlem w necie, glownie keyloggery.

Moj program kozysta z WH_KEYBOARD_LL i dostaje input w postaci wm_keydown/wm_syskeydown.

W prawdzie to jest wszsytko co mi wystarczy do obsluzenia interfejsu, ale jednak wolalbym prawdziwe znaki jakie sa wysylane do aplikacji. Wiem ze program nie musi wcale wywolywac translatemessage(), i dlatego wolalbym cos co dziala jak TranslateMessage() i przetlumaczyc virtual key na dwubajtowy kod znaku unicode jaki zostanie wyslany do okna.

0
OEMchar napisał(a)

moze i nie zrozumialem tego kodu bo nie znam delphi w najmniejszym stopniu. pisze tylko w c i asm,
aaaa kolejny mastahhhhhh. Ja z programowania żyję i to całkiem fajnie a nie bawię się w "tylko asm i c"

twor stworzony tylko pod windows ktorego uzytkowanie (afair) jest nielegalne nie jest mi znany.
co ty pierniczysz o jakimś nielegalnym tworze???

BTW WH_KEYBOARD_LL, wm_keydown, translatemessage używasz pod linuxem i macos'em tak?

BTW2 dla mnie EOT, odpowiedź dostałeś, za cienki jestem aby z tobą dyskutować...

0

Znowu kolega h3x, to się już nudne robi, SK-asmzealot, który boi się dokumentacji jak święconej wody... Chyba będzie trzeba coś z tym zrobić.

0

nie teraz chce zrozumiec jak dzialaja tlumaczenia znakow.

keyboard wysyla scan cody.
sa one tlumaczone na virtual cody przez driver - jest 256 virtual codow, tylko tyle klawiatura moze wyslac.
teraz jak to sie ma do jezykow.

japonski czy chinski driver tez tlumaczy scan na virtual, i co wtedy jakis drut kolczasty moze byc = 'A', a inny 'B'?
nastepnie TranslateMessage tlumaczy to 'A' czy 'B' na 2 bajtowy kod bedacy reprezentacja tego czegos i wysyla to do okna.
Okno rysuje obra... znak zgodnie z kodem unicode. ansi = wyzszy bajt = 0.

tak to dziala?

...
Czy moglbys sie nie wypowiadac w moich tematach?
Przychodze zmeczany w nadzieji ze mam odpowiedz, otwieram strone i co widze? Durny komentaz kogos jaki do ja jestem 'zly'.
I prosze, moze zadaje durne pytania ale ja != h3x, wiec odpusc sobie te porownania. Dokumentacje czytam jak czas pozwoli ale ona nie jest ze tak powiem - scisla. Czesc rzeczy trzeba sie domyslac a to powoduje bledy w rozumieniu, co z kolei prowadzi do moich postow. Jakbys ty czytal te rzeczy wiedzial bys doskonale, a moze wiesz, tylko udajesz debila?
Tak czy inaczej, chyba faktycznie EOT, na innym forum dostalem calkiem ladny opis tego co sie dzieje w systemie z virtual codami i na razie mi to wystarczy.

1 użytkowników online, w tym zalogowanych: 0, gości: 1