gpt4 book ai didi

windows - Delphi:系统菜单是否打开?

转载 作者:可可西里 更新时间:2023-11-01 09:56:48 27 4
gpt4 key购买 nike

我是 Delphi,我需要一个函数来确定系统菜单(resp. 窗口菜单,单击图标时出现的菜单)是否打开。原因是我正在编写一个反键盘记录器功能,它将垃圾发送到当前事件的 editcontrol(这也阻止了读取 WinAPI 消息以读取内容的键盘记录器)。但是如果打开系统菜单,editcontrol 仍然有焦点,所以垃圾将调用快捷方式。

如果我在我的 TForm1 中使用消息 WM_INITMENUPOPUP,我可以确定系统菜单何时打开,但我希望我不必更改 TForm,因为我想编写一个非可视化组件,它不需要对 TForm 派生类本身进行任何修改。

//I do not want that solution since I have to modify TForm1 for that!
procedure TForm1.WMInitMenuPopup(var Message: TWMInitMenuPopup);
begin
if message.MenuPopup=getsystemmenu(Handle, False) then
begin
SystemMenuIsOpened := true;
end;
end;

TApplicaton.HookMainWindow() 不会将 WM_INITMENUPOPUP 发送到我的 Hook 函数。

function TForm1.MessageHook(var Msg: TMessage): Boolean;  
begin
Result := False;
if (Msg.Msg = WM_INITMENUPOPUP) then
begin
// Msg.Msg IS NEVER WM_INITMENUPOPUP!
if LongBool(msg.LParamHi) then
begin
SystemMenuIsOpened := true;
end;
end;
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
Application.HookMainWindow(MessageHook);
end;

procedure TForm1.FormDestroy(Sender: TObject);
begin
Application.UnhookMainWindow(MessageHook);
end;

即使经过很长时间的研究,我也没有找到任何关于如何查询系统菜单是否打开的信息。我找不到任何方法来确定该菜​​单的打开和关闭。

有人能帮我解决吗?

问候
丹尼尔·编码(marshal)

最佳答案

Application.HookMainWindow 并不像您想象的那样。它 Hook 隐藏的应用程序窗口,而不是主窗体。要拦截特定表单上的 WM_INITMENUPOPUP,您需要做的就是为它编写一个处理程序,如您所见。

要对组件的任何所有者窗体执行此操作,您可以分配窗体的 WindowProc 属性来放置 Hook :

unit FormHook;

interface

uses
Windows, Classes, SysUtils, Messages, Controls, Forms;

type
TFormMessageEvent = procedure(var Message: TMessage; var Handled: Boolean) of object;

TFormHook = class(TComponent)
private
FForm: TCustomForm;
FFormWindowProc: TWndMethod;
FOnFormMessage: TFormMessageEvent;
protected
procedure FormWindowProc(var Message: TMessage); virtual;
public
constructor Create(AOwner: TComponent); override;
destructor Destroy; override;
published
property OnFormMessage: TFormMessageEvent read FOnFormMessage write FOnFormMessage;
end;

procedure Register;

implementation

procedure Register;
begin
RegisterComponents('Test', [TFormHook]);
end;

procedure TFormHook.FormWindowProc(var Message: TMessage);
var
Handled: Boolean;
begin
if Assigned(FFormWindowProc) then
begin
Handled := False;

if Assigned(FOnFormMessage) then
FOnFormMessage(Message, Handled);

if not Handled then
FFormWindowProc(Message);
end;
end;

constructor TFormHook.Create(AOwner: TComponent);
begin
inherited Create(AOwner);
FFormWindowProc := nil;
FForm := nil;
while Assigned(AOwner) do
begin
if AOwner is TCustomForm then
begin
FForm := TCustomForm(AOwner);
FFormWindowProc := FForm.WindowProc;
FForm.WindowProc := FormWindowProc;
Break;
end;
AOwner := AOwner.Owner;
end;
end;

destructor TFormHook.Destroy;
begin
if Assigned(FForm) and Assigned(FFormWindowProc) then
begin
FForm.WindowProc := FFormWindowProc;
FFormWindowProc := nil;
FForm := nil;
end;
inherited Destroy;
end;

end.

然后您可以在表单上使用此组件:

procedure TForm1.FormHook1FormMessage(var Message: TMessage; var Handled: Boolean);
begin
case Message.Msg of
WM_INITMENUPOPUP:
...
end;
end;

问题可能是,如果表单有任何其他组件做同样的事情,那么您需要确保以相反的顺序取消 Hook (最后 Hook ,首先取消 Hook )。上面的示例在构造函数中 Hook 并在析构函数中取消 Hook ;这似乎适用于同一表单上的多个实例。

关于windows - Delphi:系统菜单是否打开?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3899246/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com