Ich habe es jetzt nach einigen Experimenten hinbekommen. Die Lösung baut auf dem schon geposteten Versuch auf, die Keyboard-Messages über ein TApplicationEvents-Objekt abzufangen und an das Control mit dem Focus weiterzuleiten, also sowohl an die eigenen als auch an die
DLL.
Allerdings müssen dazu nicht nur die WM_KEYDOWN und WM_KEYUP-Messages weitergeleitet werden. Darüber hinaus müssen die WM_KEYDOWN-Messages noch mit TranslateMessage in eine WM_CHAR oder WM_DEADCHAR-Message umgewandelt werden, welche dann auch noch weitergeleitet werden müssen. Außerdem dürfen die Tabulator oder Enter-Taste nicht weitergeleitet werden, sonst verlieren sie ihre spezielle Funktion. Keine Idee, woran das liegen könnte.
Was jetzt funktioniert:
- Sämtliche Zeichen können erzeugt werden, auch Akzente (Dead-Chars), [ALT GR]-Zeichen usw.
- Pfeiltasten, Home, End, PgUp, PgDn usw. können erzeugt werden
- Die Hostanwendung funktioniert nach meiner Beobachtung genauso wie vorher ([Tab]: Focuswechsel, Return: Default-Button, [ALT]+MenuAccel: Tastenkürzel, ...)
Was allerdings (noch) nicht funktioniert:
- [TAB] innerhalb des DLL-Fensters wechselt nicht den Focus innerhalb desselben, sondern springt zum nächsten Control der Hostanwendung
- Der Focuswechsel durch [TAB] in der Hostanwendung überspringt das DLL-Fenster
- MenuAccels im DLL-Fenster funktionieren nicht, also z. B. Button-Captions wie '&OK' können nicht mit [ALT]+[O] aktiviert werden
Mit diesen Einschränkunten kann ich allerdings erstmal leben
.
Um die Tabulator-Geschichte hinzubiegen, kam mir schon folgende Idee: Man könnte das Panel in den Focuswechsel mit einbeziehen (TPanel.TabStop := True) und sich das
Handle des aktuell angezeigten
DLL-Fensters von selbiger erfragen. Dann kann man im TPanel.OnEnter-Event-Handler das Fenster per Windows-
API aktivieren, mit SetFocus(HandleOfCurrentDLL). Aber für weitere Experimente habe ich immo leider keine Zeit. Falls es jemand ausprobiert, bitte (Miss-)Erfolgsbereichte hier posten 8)
Hier nun der Code für das TApplicationEvents.OnMessage in der Hostanwendung:
Delphi-Quellcode:
procedure TConfigForm.ApplicationKeyboardEventsMessage(
var Msg: tagMSG;
var Handled: Boolean);
const
DONT_FORWARD_KEYS:
set of Byte = [VK_RETURN, VK_TAB];
var
Handle: THandle;
VKey: Byte;
begin
// This event handler forwards the keyboard events to the DLL window.
// Without it some keys would not be sent to the DLL window. This seems
// to be an issue of either Delphi or the Windows message handling.
case Msg.
message of
WM_KEYDOWN:
begin
// Translate the virutal key into a character key (0..255)
VKey := Lo(MapVirtualKey(Msg.wParam, 2));
// If no translation has to be made, MapVirtualKey returns 0.
if (VKey = 0)
then VKey := Lo(Msg.wParam);
// Don't handle the DONT_FORWARD_KEYS keys as they have special
// functions and must be handled by the application itself.
if not (VKey
in DONT_FORWARD_KEYS)
then
begin
// Get current focused control
Handle := GetFocus;
// Forward the message to it
SendMessage(
Handle, Msg.
message, Msg.wParam, Msg.lParam);
// Process message by translating the WM_KEYUP message into a
// WM_CHAR message.
Handled := TranslateMessage(Msg);
end;
end;
WM_KEYUP:
begin
// Translate the virutal key into a character key (0..255)
VKey := Lo(MapVirtualKey(Msg.wParam, 2));
// If no translation has to be made, MapVirtualKey returns 0.
if (VKey = 0)
then VKey := Lo(Msg.wParam);
// Don't handle the DONT_FORWARD_KEYS keys as they have special
// functions and must be handled by the application itself.
if not (VKey
in DONT_FORWARD_KEYS)
then
begin
// Get current focused control
Handle := GetFocus;
// Forward the message to it
SendMessage(
Handle, Msg.
message, Msg.wParam, Msg.lParam);
Handled := True;
end;
end;
WM_DEADCHAR,
WM_CHAR:
begin
VKey := Msg.wParam;
// Don't handle the DONT_FORWARD_KEYS keys as they have special
// functions and must be handled by the application itself.
if not (VKey
in DONT_FORWARD_KEYS)
then
begin
// Get current focused control
Handle := GetFocus;
// Forward the message to it
SendMessage(
Handle, Msg.
message, Msg.wParam, Msg.lParam);
Handled := True;
end;
end;
end;
end;
Gruß,
Christian