在我的TComponent
中,有一點我想要聽重要事件並攔截ESC
鍵並在我的組件中處理它,消耗/「吃」擊鍵,以便例如所有者窗體不會處理它在那個階段。就像在TDragObject
開始時一樣,通過按ESC
拖動並取消它。我的TComponent如何攔截ESC鍵並處理它?
問題是TDragObject
已通過AllocateHWnd
通知它的所有者窗體爲CN_KEYDOWN
。但沒有人通知我的組件。
我需要用自己的表格替換表格WindowProc
嗎?如果是的話,那麼如何正確「按書」這樣說呢?
只是要100%清楚:
TMyComponent = class(TComponent)
我做了一個小測試,它似乎工作:
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;
我不知道這是否是正確/唯一的方法。
拖動涉及一個新的模態循環。這不適合你。很難看到你如何在沒有主人合作的情況下乾淨地做到這一點。 –
@DavidHeffernan,OP說「就像在TDragObject」一樣,這只是一個例子,我假設OP只想要ESC鍵,沒有什麼比這更簡單了。 ESC是一個對話框鍵。我現在只有1分鐘沒有查找代碼/ API/windows消息。 –
@Cosmin拖動操作的模態循環擁有並泵送隊列。所以可以抓住按鍵。但是一個表單上的組件並不具備這種奢侈。你打算如何進入應用程序的消息循環? –