Это выполнимо, если вы хотите изменить код VCL.
KeyPreview обрабатывается в TWinControl.DoKeyDown
методе. Как видно из кода, который имеет фокус, будет искать свою родительскую форму и вызывать его метод DoKeyDown
, если включен KeyPreview
.
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;
Чтобы изменить это поведение, вам нужно будет либо изменить TWinControl.DoKeyDown
код для сканирования кадров слишком или перехватывать WM_KEYDOWN
и WM_SYSKEYDOWN
для каждого TWinControl
потомка вы хотите использовать, и, наконец, добавить KeyPreview
поле для базового класса Frame.
Вероятно, лучшим вариантом было бы объявить интерфейс IKeyPreview
и при сканировании родительских форм/фреймов, если родитель реализует этот интерфейс. Если их не найти, вы можете вернуться к исходному коду. Это будет содержать изменения кода VCL только до TWinControl.DoKeyDown
, и вы можете легко реализовать интерфейс в Frames, где это необходимо.
Примечание: В ОС Windows, в фокусе которого присутствуют ключевые события. Поэтому выше модификаций можно было бы найти фрейм, только если некоторые из его элементов управления имеют фокус. Независимо от того, будет ли мышь над кадром или нет, это не повлияет на функциональность.
Более подробный код будет выглядеть следующим образом:
определение интерфейса, что рамка будет иметь для реализации:
IKeyPreview = interface
['{D7318B16-04FF-43BE-8E99-6BE8663827EE}']
function GetKeyPreview: boolean;
property KeyPreview: boolean read GetKeyPreview;
end;
Функции для нахождения родительского кадра, который реализует IKeyPreview
интерфейса, следует поместить где-то в Vcl.Controls
секции реализации :
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
модификация (insert in выше оригинальный код) :
var
PreviewParent: IKeyPreview;
PreviewParent := GetParentKeyPreview(Self);
if PreviewParent <> nil then
begin
if PreviewParent.KeyPreview and TWinControl(PreviewParent).DoKeyDown(Message) then
Exit;
end;
@TLama нет KeyDown событие для TFrame –
я означало переопределение 'метод KeyDown', но это, кажется, не значит, работать я удалил свой комментарий. – TLama
Сообщите мне, когда узнаете! http://stackoverflow.com/questions/27116331/handle-gestures-when-initiated-from-a-frame (немного другой предмет, но все же о том, как кадры «проглатывают» пользовательские события) –