Problemi con gancio tastiera proc
-
24-09-2019 - |
Domanda
Lo sfondo: La mia forma ha un TWebBrowser. Voglio chiudere il modulo con ESC ma il TWebBrowser mangia le sequenze di tasti -. Così ho deciso di andare con un hook di tastiera
Il problema è che la forma può essere aperto in più istanze allo stesso tempo.
Non importa quello che faccio, in alcune situazioni, se ci sono due istanze aperte della mia forma, chiudendo uno di loro chiude l'altro pure.
Ho allegato alcuni esempi di codice. Tutte le idee su ciò che causa il problema?
var
EmailDetailsForm: TEmailDetailsForm;
KeyboardHook: HHook;
implementation
function KeyboardHookProc(Code: Integer; wParam, lParam: LongInt): LongInt; stdcall;
var
hWnd: THandle;
I: Integer;
F: TForm;
begin
if Code < 0 then
Result := CallNextHookEx(KeyboardHook, Code, wParam, lParam)
else begin
case wParam of
VK_ESCAPE:
if (lParam and $80000000) <> $00000000 then
begin
hWnd := GetForegroundWindow;
for I := 0 to Screen.FormCount - 1 do
begin
F := Screen.Forms[I];
if F.Handle = hWnd then
if F is TEmailDetailsForm then
begin
PostMessage(hWnd, WM_CLOSE, 0, 0);
Result := HC_SKIP;
break;
end;
end; //for
end; //if
else
Result := CallNextHookEx(KeyboardHook, Code, wParam, lParam);
end; //case
end; //if
end;
function TEmailDetailsForm.CheckInstance: Boolean;
var
I, J: Integer;
F: TForm;
begin
Result := false;
J := 0;
for I := 0 to Screen.FormCount - 1 do
begin
F := Screen.Forms[I];
if F is TEmailDetailsForm then
begin
J := J + 1;
if J = 2 then
begin
Result := true;
break;
end;
end;
end;
end;
procedure TEmailDetailsForm.FormCreate(Sender: TObject);
begin
if not CheckInstance then
KeyboardHook := SetWindowsHookEx(WH_KEYBOARD, @KeyboardHookProc, 0, GetCurrentThreadId());
end;
procedure TEmailDetailsForm.FormDestroy(Sender: TObject);
begin
if not CheckInstance then
UnHookWindowsHookEx(KeyboardHook);
end;
Soluzione
Si potrebbe fare questo con TApplicationEvents.OnMessage
invece. Eliminare un componente TApplicationEvents sulla forma principale dell'applicazione con questo codice:
procedure TMainForm.ApplicationEvents1Message(var Msg: tagMSG;
var Handled: Boolean);
var
C: TControl;
H: HWND;
begin
if (Msg.message = WM_KEYDOWN) and (Msg.wParam = VK_ESCAPE) then begin
H := Msg.hwnd;
while GetParent(H) <> 0 do
H := GetParent(H);
C := FindControl(H);
if C is TEmailDetailsForm then begin
TEmailDetailsForm(C).Close;
Handled := True;
end;
end;
end;
Se si desidera continuare a utilizzare un hook di tastiera, invece, si deve collegare solo una volta, piuttosto che una sola volta per ogni forma, soprattutto perché si sta sovrascrivendo una variabile globale. Prova ad aggiungere una variabile globale HookCount, e solo agganciare / sganciare se è l'unica forma.
Altri suggerimenti
Lo sfondo: La mia forma ha un TWebBrowser. Voglio chiudere il modulo con ESC ma il TWebBrowser mangia il battiture - così ho deciso di andare con un tastiera gancio.
Ci potrebbe essere una soluzione più semplice. Hai provato l'impostazione del KeyPreview proprietà True
?
Bene, entrambe le forme sono firmati per ricevere l'avviso della tastiera, in modo che entrambi vicini. Hai bisogno di mettere il codice in là delle scelte "è questo ESC per me?". Forse determinando se sei la finestra con il fuoco o meno. Se non è la tua fuga, quindi non chiudere.
Ma, tutto questo sembra piuttosto drastico. Ci deve essere un modo più semplice non-invasivi per rilevare la CES all'interno di questa applicazione, senza la necessità di monitorare la tastiera per l'intero sistema.