Nel mio TComponent
, c'è un punto in cui voglio ascoltare gli eventi dei tasti e intercettare la chiave ESC
e gestirla nel mio componente, consumare/"mangiare" il tasto, in modo che ad esempio il modulo proprietario non lo gestisca a quel punto. Proprio come in TDragObject
quando si avvia, trascinarlo e annullarlo premendo ESC
.Come può il mio TComponent intercettare il tasto ESC e gestirlo?
Il problema è che TDragObject
ha AllocateHWnd
che viene notificato dal suo modulo proprietario con CN_KEYDOWN
. Ma nessuno notifica il mio componente.
Devo sostituire il modulo WindowProc
con il mio? Se sì, allora come farlo correttamente "dal libro" per così dire?
Giusto per essere chiari al 100%:
TMyComponent = class(TComponent)
Ho fatto un piccolo test e sembra funzionare:
TMyComponent = class(TComponent)
private
FOldWindowProc: TWndMethod;
FParentForm: TCustomForm;
procedure FormWindowProc(var Message: TMessage);
public
constructor Create(AOwner: TComponent); override;
destructor Destroy; override;
end;
...
constructor TMyComponent.Create(AOwner: TComponent);
begin
if not (AOwner is TWinControl) then
raise Exception.Create('TMyComponent.Create: Owner must be a TWinControl');
inherited Create(AOwner);
// hook parent form
FParentForm := GetParentForm(TWinControl(Owner));
if Assigned(FParentForm) then
begin
FOldWindowProc := FParentForm.WindowProc;
FParentForm.WindowProc := FormWindowProc;
end;
end;
destructor TMyComponent.Destroy;
begin
// unhook parent form
if Assigned(FParentForm) then
FParentForm.WindowProc := FOldWindowProc;
inherited;
end;
procedure TMyComponent.FormWindowProc(var Message: TMessage);
begin
FOldWindowProc(Message);
if Message.Msg = CM_CHILDKEY then // CM_CHILDKEY -> CM_DIALOGKEY -> CM_DIALOGCHAR
begin
OutputDebugString('CM_CHILDKEY');
if Message.WParam = VK_ESCAPE then
begin
Beep;
// do my stuff...
Message.Result := 1; // consume keystroke
end;
end;
end;
Mi chiedo se questo è il giusto/solo approccio.
Il trascinamento implica un nuovo ciclo modale. Questa non è un'opzione per te. Difficile vedere come puoi farlo in modo pulito senza la collaborazione dell'host. –
@DavidHeffernan, l'OP ha detto "come in TDragObject", è solo un esempio e presumo che l'OP voglia solo il tasto ESC, niente di più, niente di meno. ESC è un tasto di dialogo. Semplicemente non ho il minuto richiesto per cercare il codice/API/windows message adesso. –
@Cosmin Un ciclo modale dell'operazione di trascinamento possiede e pompa la coda. E così può entrare in possesso delle pressioni dei tasti. Ma un componente su un modulo non ha quel lusso. Come proponi di entrare nel ciclo dei messaggi dell'app? –