Es ist machbar, wenn Sie VCL-Code ändern möchten.
KeyPreview wird in TWinControl.DoKeyDown
Methode behandelt. Wie aus der Codekontrolle hervorgeht, die den Fokus hat, sucht sie nach ihrer übergeordneten Form und ruft ihre Methode DoKeyDown
auf, wenn aktiviert ist.
function TWinControl.DoKeyDown(var Message: TWMKey): Boolean;
var
ShiftState: TShiftState;
Form, FormParent: TCustomForm;
LCharCode: Word;
begin
Result := True;
// Insert modification here
{ First give the immediate parent form a try at the Message }
Form := GetParentForm(Self, False);
if (Form <> nil) and (Form <> Self) then
begin
if Form.KeyPreview and TWinControl(Form).DoKeyDown(Message) then
Exit;
{ If that didn't work, see if that Form has a parent (ie: it is docked) }
if Form.Parent <> nil then
begin
FormParent := GetParentForm(Form);
if (FormParent <> nil) and (FormParent <> Form) and
FormParent.KeyPreview and TWinControl(FormParent).DoKeyDown(Message) then
Exit;
end;
end;
with Message do
begin
ShiftState := KeyDataToShiftState(KeyData);
if not (csNoStdEvents in ControlStyle) then
begin
LCharCode := CharCode;
KeyDown(LCharCode, ShiftState);
CharCode := LCharCode;
if LCharCode = 0 then Exit;
end;
end;
Result := False;
end;
Um dieses Verhalten zu ändern, würden Sie müssen entweder TWinControl.DoKeyDown
Code ändern für Rahmen zu oder abfangen WM_KEYDOWN
und WM_SYSKEYDOWN
für jeden TWinControl
Nachkomme Sie verwenden möchten, scannen und schließlich KeyPreview
Feld Basis Frame-Klasse hinzufügen.
Wahrscheinlich beste Option wäre, IKeyPreview
Schnittstelle zu deklarieren und beim Scannen für übergeordnete Formulare/Frames testen, ob Eltern diese Schnittstelle implementiert. Wenn keiner gefunden wird, können Sie auf den ursprünglichen Code zurückgreifen. Das würde VCL-Code-Änderungen nur in TWinControl.DoKeyDown
Methode enthalten, und Sie können einfach Schnittstelle in Frames wo erforderlich implementieren.
Hinweis: Auf Windows-Steuerelement, das Fokus hat, erhält wichtige Ereignisse. Daher können die obigen Änderungen nur dann Frames finden, wenn einige ihrer Steuerelemente den Fokus haben. Ob die Maus über dem Frame ist oder nicht, hätte keinen Einfluss auf die Funktionalität.
Detailliertere Code würde wie folgt aussehen:
Schnittstellendefinition, dass Rahmen würde umsetzen müssen:
IKeyPreview = interface
['{D7318B16-04FF-43BE-8E99-6BE8663827EE}']
function GetKeyPreview: boolean;
property KeyPreview: boolean read GetKeyPreview;
end;
Funktion für geordneten Rahmen zu finden, die IKeyPreview
-Schnittstelle implementiert, sollte irgendwo in Vcl.Controls
Implementationsabschnitt setzen :
function GetParentKeyPreview(Control: TWinControl): IKeyPreview;
var
Parent: TWinControl;
begin
Result := nil;
Parent := Control.Parent;
while Assigned(Parent) do
begin
if Parent is TCustomForm then Parent := nil
else
if Supports(Parent, IKeyPreview, Result) then Parent := nil
else Parent := Parent.Parent;
end;
end;
TWinControl.DoKeyDown
Änderung (in den obigen ursprünglichen Code einfügen) :
var
PreviewParent: IKeyPreview;
PreviewParent := GetParentKeyPreview(Self);
if PreviewParent <> nil then
begin
if PreviewParent.KeyPreview and TWinControl(PreviewParent).DoKeyDown(Message) then
Exit;
end;
@TLama gibt es kein Ereignis KeyDown für das TFrame –
ich zwingende 'KeyDown' Methode gemeint, aber das scheint nicht damit zu arbeiten ich meinen Kommentar gelöscht haben. – TLama
Lassen Sie es mich wissen, wenn Sie es herausfinden! http://stackoverflow.com/questions/27116331/handle-gestures-when-initiated-from-a-frame (etwas anderes Thema, aber immer noch darüber, wie Frames "Benutzerereignisse" schlucken) –