Zdravím.
Takže mám následující problém:
Mám Virtual-Key Code nějaké klávesy (jakékoliv, nejde jen o písmena), a potřebuji uživateli zobrazit název této klávesy, např. "Ctrl", "Home", atd. . Zatím postupuji metodou že VK převedu na ScanCode pomocí API funkce MapVirtualKeyEx, a získaný ScanCode použiji do API funkce GetKeyNameText.
Až potud idylka. Jenže funkce MapVirtualKeyEx ignoruje jestli jde o levé nebo pravé klávesy (levý/pravý Alt atp.), a navíc klávesy jako šipky (VK_UP, VK_DOWN) nebo blok speciálních kláves (Home, Delete, ...) zvesela převede na scanCode kláves na numpadu. Takže při stisku PageUp se objeví "Num 9" atp. Podle dokumentace by měl jít ve MapVirtualKeyEx nastavit parametr uMapType na MAPVK_VK_TO_VSC_EX (4), což by to mělo řešit - ale to pochopitelně nefunguje (ve WinXP vůbec, ve vyšších Win sporadicky - nezkoušel jsem, ale podle komentářů co jsem měl tu čest vidět to nefunguje taky vůbec).
Takže já se ptám zkušenějších - jak docílit toho, abych mohl správně převést Virtual-Key Code na název klávesy bez toho abych na to musel vytvářet nějakou zvrácenou tabulku podle které bych to převáděl?
Dodávám že to píšu v Delphi 7, na Windows XP, a jsem amatér.
Předem děkuji za radu.
Fórum › Delphi
Názvy kláves
Pokud to chceš mít 100%, tak zvrácená tabulka :) Nebo zkusit trochu pohledat a zjistit, jestli už to někdo neřešil http://www.ffuts.org/blog/mapvirtualkey-getkeynametext-and-a-story-of-how-to/.
Samozřejmě jsem hledal, a danou stránku jsem také našel. Bohužel tohle je jenom částečné řešení.
Momentálně si pohrávám se strukturami v knihovnách kbd*.dll. Jenomže dokumentace k tomu je v C (aspoň myslím že je to C), a to já neumím. Většinu sice chápu a daří se mi dané struktury načítat (alespoň tedy pointery na ně), ale neumím převést "null terminated array" na delfácký array (jedině cyklem while, což mi přijde, mno, nic moc).
Takže zatím to vyřešené na 100% nemám.
Jedu asi takhle (je to jenom ukázka, skutečnej kód vypadá trochu jinak a je tam hromada nedodělků, jenom to testuju, a navíc jak jsem zmínil, jsem jenom amatér, tak mě za případný prasárny nekamenujte, jenom upozorněte):
const
LayoutsRegPath = '\System\CurrentControlSet\Control\Keyboard Layouts\';
RegLibValueName = 'Layout File';
ExportedFuncName = 'KbdLayerDescriptor';
TagKbdLayer = Record
pCharModifiers: Pointer;
pVkToWcharTable: Pointer; //ptr to Array of VK_TO_WCHAR_TABL
pDeadKey: Pointer;
pKeyNames: pointer; //ptr to Array of VSC_LPWSTR
pKeyNamesExt: Pointer; //ptr to Array of VSC_LPWSTR
pKeyNamesDead: ^PWideChar;
pusVSCtoVK: Pointer; //ptr to Array of Word
bMaxVSCtoVK: Byte;
pVSCtoVK_E0: Pointer; //ptr to Array of VSC_VK
pVSCtoVK_E1: Pointer; //ptr to Array of VSC_VK
fLocaleFlags: LongWord;
nLgMax: Byte;
cbLgEntry: Byte;
pLigature: Pointer;
dwType: LongWord;
dwSubType: LongWord;
end;
PTagKbdLayer = ^tagKbdLayer;
TKbdLayoutFunc = Function: PtagKbdLayer; stdcall;
var
KbdLayoutFunc: TKbdLayoutFunc;
Function GetSystemFolder: String;
const
CSIDL_SYSTEM = $0025;
var
Path: array[0..MAX_PATH] of Char;
begin
If SHGetSpecialFolderPath(0,Path,CSIDL_SYSTEM,False) then
begin
Result := IncludeTrailingPathDelimiter(Path);
end
else
begin
Result := '';
end;
end;
Function LoadLibraryFce: HModule;
var
Reg: TRegistry;
LibName: String;
LayoutName: String;
begin
Result := 0;
SetLength(LayoutName, KL_NAMELENGTH + 1);
If not GetKeyboardLayoutName(PChar(LayoutName)) then exit;
try
Reg := TRegistry.Create;
try
Reg.RootKey := HKEY_LOCAL_MACHINE;
Reg.OpenKeyReadOnly(LayoutsRegPath + LayoutName);
LibName := Reg.ReadString(RegLibValueName);
finally
Reg.CloseKey;
Reg.Free;
end;
except
exit;
end;
Result := LoadLibrary(PAnsiChar(GetSystemFolder + LibName));
end;
Procedure GetKbdLayout;
var
LibHandle: HModule;
StructPoint: PtagKbdLayer;
begin
LibHandle := LoadLibraryFce;
If LibHandle = 0 then exit;
@KbdLayoutFunc := GetProcAddress(LibHandle,ExportedFuncName);
StructPoint := KbdLayoutFunc;
//...
//a dál už jenom pracuju se strukturama (StructPoint...) co jsem získal z dll knihovny.
No nevím ... než studovat struktury v dll, tak to bych snad udělal tu tabulku :) Ale podle vkusu každého soudruha :) A jenom poznámka ... jak jinak najít konec nulou ukončeného pole než v cyklu?
No a k tomu řešení ... pochopil jsem to tak, že to mapování umí "pojmenovat" v podstatě všechno až na ... a to jsou ty výjimky, které bych řešil ala ta odkazovaná stránka.
Asi takhle - ten program musí fungovat na různých klávesnicích (jazycích), takže tabulka nepřipadá v úvahu. A popravdě mě práce s dll na takovýhle úrovni nepřipadá nijak zvlášť složitá.
Ad. Array - mě nejde o nalezení konce (i když to s tím pochopitelně souvisí), ale o co nejjednodušší převedení na delfáckou Array (která má co jsem tak vyrozuměl trochu jinou strukturu v paměti).
To řešení - právě že to řeší i ty výjimky, a to tak že systémově. Problém zůstává jenom u pár "obskurních" kláves (NumLock, Pause/Break, přehazuje to Enter a NumEnter). Ale zatim nemám prostudovanou celou strukturu, tak snad to ještě vyřešim.
Každopádně každá pomoc je stále vítaná.
Proto se používají virtuální kódy, aby si nebyl závislý na jazyku nebo klávesnici. Jinak každá cesta, která vede k cíli, je správná, takže proč nebrat data z knihoven. A pokud nejsou stejné datové reprezentace, tak si je musíš načíst a programově upravit.
Proto se používají virtuální kódy, aby si nebyl závislý na jazyku nebo klávesnici. Jinak každá cesta, která vede k cíli, je správná, takže proč nebrat data z knihoven. A pokud nejsou stejné datové reprezentace, tak si je musíš načíst a programově upravit.
Zdá se že mi opravdu nezbude nic jiného než array převádět programově, ale to je fuk, to zvládám, jenom jsem doufal že je na to nějaký "fígl".
Jinak virtuální kódy samozřejmě používám, jenom holt potřebuju srozumitelně zobrazit jaké klávese to aktuálně odpovídá, a v tom API funkce zrovna neexcelují.
Ten problém jsem pochopil, jenom se neshodujeme na řešení. Mě by bylo bližší využít co API zvládá a zbytek přes jeden switch nebo tabulku. Dolování dat z knihoven už mi přijde více komplikované (nehledě na to - musí taková knihovna obsahovat vždy všechny klávesy?).
Já bych samozřejmě raději použil API, koneckonců dvě volání funkcí versus celej tenhle cirkus - dál asi netřeba rozvádět. Ale to co vyhazuje API skutečně není to pravé ořechové (prohození pomlčky, čárky a rovnítka, ...). Mě nejde jenom o dobrý pocit že to běží - ale program bude na 100% použit v cizině (včetně Asie), takže to potřebuji ošetřit maximálně systémově a pokud možno bez výjimek.
Jinak ta knihovna neobsahuje všechny klávesy, ale to co potřebuji tam je (převod VSC -> VK, VSC -> název klávesy).
Přidej příspěvek
Ano, opravdu chci reagovat → zobrazí formulář pro přidání příspěvku
×Vložení zdrojáku
×Vložení obrázku
×Vložení videa
Uživatelé prohlížející si toto vlákno
Podobná vlákna
Nazvy slozek do souboru — založil lamka
Dynamické názvy souborů — založil dragon124
Názvy proměnných apod. — založil Jan Sedlák
Názvy souborů s diakritikou — založil LJ1024
GetOpenFileName OFN_ALLOWMULTISELECT - Názvy souborů — založil ProXicT