With reference to this question, and more specifically to this answer, it seems that dead keys are captured on a keyboad hook only after a MSB manipulation. The author of the answer left a fixed code, but I do not know what the Delphi equivalent is.
My actual code:
program Project1;
{$APPTYPE CONSOLE}
{$R *.res}
uses
Windows,
Messages,
SysUtils;
var
hhk: HHOOK;
Msg: TMsg;
{==================================================================================}
function ReverseBits(b: Byte): Byte;
var
i: Integer;
begin
Result := 0;
for i := 1 to 8 do
begin
Result := (Result shl 1) or (b and 1);
b := b shr 1;
end;
end;
function GetCharFromVirtualKey(Key: Word): string;
var
keyboardState: TKeyboardState;
keyboardLayout: HKL;
asciiResult: Integer;
begin
GetKeyboardState(keyboardState);
keyboardLayout := GetKeyboardLayout(0);
SetLength(Result, 2);
asciiResult := ToAsciiEx(Key, ReverseBits(MapVirtualKey(Key, MAPVK_VK_TO_CHAR)), keyboardState, @Result[1], 0, keyboardLayout);
case asciiResult of
0:
Result := '';
1:
SetLength(Result, 1);
2:
;
else
Result := '';
end;
end;
{==================================================================================}
function LowLevelKeyboardProc(nCode: Integer; wParam: wParam; lParam: lParam): LRESULT; stdcall;
type
PKBDLLHOOKSTRUCT = ^TKBDLLHOOKSTRUCT;
TKBDLLHOOKSTRUCT = record
vkCode: cardinal;
scanCode: cardinal;
flags: cardinal;
time: cardinal;
dwExtraInfo: Cardinal;
end;
PKeyboardLowLevelHookStruct = ^TKeyboardLowLevelHookStruct;
TKeyboardLowLevelHookStruct = TKBDLLHOOKSTRUCT;
var
LKBDLLHOOKSTRUCT: PKeyboardLowLevelHookStruct;
begin
case nCode of
HC_ACTION:
begin
if wParam = WM_KEYDOWN then
begin
LKBDLLHOOKSTRUCT := PKeyboardLowLevelHookStruct(lParam);
Writeln(GetCharFromVirtualKey(LKBDLLHOOKSTRUCT^.vkCode));
end;
end;
end;
Result := CallNextHookEx(hhk, nCode, wParam, lParam);
end;
procedure InitHook;
begin
hhk := SetWindowsHookEx(WH_KEYBOARD_LL, @LowLevelKeyboardProc, HInstance, 0);
if hhk = 0 then
RaiseLastOSError;
end;
procedure KillHook;
begin
if (hhk <> 0) then
UnhookWindowsHookEx(hhk);
end;
begin
try
InitHook;
while GetMessage(Msg, 0, 0, 0) do
begin
TranslateMessage(Msg);
DispatchMessage(Msg);
end;
except
on E: Exception do
Writeln(E.ClassName, ': ', E.Message);
end;
end.