Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/apache/8.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Delphi WM_NCHITTEST是否应该由Win10以100'的频率永久生成;秒,即使鼠标空闲?_Delphi_Winapi_Vcl_Delphi Xe7 - Fatal编程技术网

Delphi WM_NCHITTEST是否应该由Win10以100'的频率永久生成;秒,即使鼠标空闲?

Delphi WM_NCHITTEST是否应该由Win10以100'的频率永久生成;秒,即使鼠标空闲?,delphi,winapi,vcl,delphi-xe7,Delphi,Winapi,Vcl,Delphi Xe7,我在WM\n chittest消息中遇到了一种奇怪的行为 总之,一旦我将鼠标放在目标(即:钩住)控件上并使鼠标保持静止(或空闲),我每秒就会收到无数WM\u NCHITTEST消息。无论我是使用WindowProc()对该控件的WndProc进行子类化,还是在子类中重写WndProc方法(为了简单起见,我在下面的代码中进行子类化),都会发生这种情况 就我从在线Win32 API文档和其他来源所能找到的而言,我怀疑此消息是否以这种频率发出,但我可能错了。或者可能有一个明显的解释我完全错过了,或者可

我在
WM\n chittest
消息中遇到了一种奇怪的行为

总之,一旦我将鼠标放在目标(即:钩住)控件上并使鼠标保持静止(或空闲),我每秒就会收到无数
WM\u NCHITTEST
消息。无论我是使用
WindowProc()
对该控件的
WndProc
进行子类化,还是在子类中重写
WndProc
方法(为了简单起见,我在下面的代码中进行子类化),都会发生这种情况

就我从在线Win32 API文档和其他来源所能找到的而言,我怀疑此消息是否以这种频率发出,但我可能错了。或者可能有一个明显的解释我完全错过了,或者可能在API中发生了一些我不知道的变化。无论如何,我真的很想知道这是什么,或者正在发生什么

我已经在两个不同的系统上测试了相同的代码(下面的示例),结果相同,尽管两个系统的Delphi/OS版本和配置相同。我尝试在IDE之外运行应用程序(因此没有调试挂钩),在调试和发布配置(后者没有调试信息)中,以32位和64位为目标,我总是得到相同的结果

我正在用DelphiXe7 Enterprise开发Win10 Pro 64位版本20H2(我相信是最新的Windows版本)

这里有一个非常简单的程序来重现我的体验:一个带有
TPanel
TForm
、一个
TCheckBox
和一个
TLabel
。选中复选框时,面板是挂接的控件,标签显示通过
WndProc()
方法接收的
WM\u nchitest
消息数:

unit Unit5;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.ExtCtrls, Vcl.StdCtrls;

type
  TForm5 = class(TForm)
    CheckBox1: TCheckBox;
    Label1: TLabel;
    Panel1: TPanel;
    procedure FormDestroy(Sender: TObject);
    procedure CheckBox1Click(Sender: TObject);
  private
    FHookedCtrl: TControl;
    FHookedCtrlWndProc: TWndMethod;
    FMessageCount: Integer;
    procedure SetHookedCtrl(const Value: TControl);
  public
    procedure ControlWndProc(var Message: TMessage);
    property HookedCtrl: TControl read FHookedCtrl write SetHookedCtrl;
  end;

var
  Form5: TForm5;

implementation

{$R *.dfm}

{ TForm5 }

procedure TForm5.CheckBox1Click(Sender: TObject);
begin
  //checkbox activates or deactivates the hook
  if CheckBox1.Checked then
    //hook the panel's WndProc by subclassing
    HookedCtrl := Panel1
    //release the hook on WndProc
  else HookedCtrl := nil;
end;

procedure TForm5.ControlWndProc(var Message: TMessage);
begin
  case Message.Msg of
    WM_NCHITTEST:
      begin
        //show how many messages received with the label's caption
        Inc(FMessageCount);
        Label1.Caption := FormatFloat('##,##0 messages', FMessageCount);
      end;
  end;
  //not really handling the messsage, just counting.
  FHookedCtrlWndProc(Message);
end;

procedure TForm5.FormDestroy(Sender: TObject);
begin
  //make sure to clear the hook if assigned
  HookedCtrl := nil;
end;

procedure TForm5.SetHookedCtrl(const Value: TControl);
begin
  if (Value <> FHookedCtrl) then
  begin
    if Assigned(FHookedCtrl) then
    begin
      //release the hook
      FHookedCtrl.WindowProc := FHookedCtrlWndProc;
      FHookedCtrlWndProc := nil;
      FMessageCount := 0;
    end;
    FHookedCtrl := Value;
    if Assigned(FHookedCtrl) then
    begin
      //hook the panel (i.e. Value)
      FHookedCtrlWndProc := FHookedCtrl.WindowProc;
      FHookedCtrl.WindowProc := ControlWndProc;
    end;
  end;
end;

end.
单元5;
接口
使用
Winapi.Windows、Winapi.Messages、System.SysUtils、System.Variants、System.Classes、Vcl.Graphics、,
控件、窗体、对话框、ExtCtrls、StdCtrls;
类型
TForm5=类(TForm)
复选框1:t复选框;
标签1:TLabel;
小组1:TPanel;
销毁程序表(发送方:TObject);
程序检查框1单击(发送方:ToObject);
私有的
fhookedtrl:t控制;
fhookedtrlwndproc:TWndMethod;
FMessageCount:整数;
程序SETDCTRL(常数值:t控制);
公众的
过程控制WNDPROC(变量消息:TMessage);
属性hookedtrl:t控制读取fhookedtrl写入设置hookedtrl;
结束;
变量
表5:TForm5;
实施
{$R*.dfm}
{TForm5}
程序t用于M5.复选框1单击(发送方:ToObject);
开始
//复选框激活或停用挂钩
如果复选框1.选中,则
//通过子类化钩住面板的WndProc
hookedtrl:=配电盘1
//松开WndProc上的挂钩
否则,dctrl:=nil;
结束;
过程TForm5.ControlWndProc(变量消息:TMessage);
开始
case Message.Msg of of
WM_NCHITTEST:
开始
//显示收到的带有标签标题的邮件数
Inc(FMessageCount);
标签1.标题:=FormatFloat(“##,###0消息”,FMessageCount);
结束;
结束;
//不是真的处理信息,只是计算。
FHookedCtrlWndProc(消息);
结束;
程序TForm5.FormDestroy(发送方:ToObject);
开始
//如果指定,请确保清除挂钩
hookedtrl:=零;
结束;
程序TForm5.sethookedtrl(常量值:TControl);
开始
如果(值fhookedtrl),则
开始
如果分配(FHookedCtrl),则
开始
//松开钩子
fhookedtrl.WindowProc:=fhookedtrlwndproc;
fhookedtrlwndproc:=零;
FMessageCount:=0;
结束;
fhookedtrl:=值;
如果分配(FHookedCtrl),则
开始
//钩住面板(即值)
fhookedtrlwndproc:=fhookedtrl.WindowProc;
fhookedtrl.WindowProc:=ControlWndProc;
结束;
结束;
结束;
结束。
复制:运行应用程序,选中复选框,将鼠标悬停在面板上,使其处于空闲状态(静止)。在我的例子中,我每秒收到100条
WM\u nchitest
消息,而且它从未停止过。这种情况会发生吗

有人能解释一下这里发生了什么吗?

我使用这个工具来查看发生了什么以及什么时候发生的

它是WM_NCHITTEST处理程序中的以下行

Label1.Caption := FormatFloat('##,##0 messages', FMessageCount);
这就是问题的根源。当您删除它时,不再有所有这些
WM\u nchitest
消息。要查看消息数量,请使用间隔1秒的
t定时器
,并在标签中显示消息计数。您将看到,每当计时器启动时(如果有空的OnTimer处理程序,您仍然会收到一条消息),当然,当鼠标移动时,都会收到一条消息

以下是我使用的代码:

unit Unit5;


interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.ExtCtrls, Vcl.StdCtrls;

type
  TForm5 = class(TForm)
    Label1: TLabel;
    CheckBox1: TCheckBox;
    Panel1: TPanel;
    Timer1: TTimer;
    procedure FormDestroy(Sender: TObject);
    procedure CheckBox1Click(Sender: TObject);
    procedure Timer1Timer(Sender: TObject);
  private
    FHookedCtrl: TControl;
    FHookedCtrlWndProc: TWndMethod;
    FMessageCount: Integer;
    procedure SetHookedCtrl(const Value: TControl);
  public
    procedure ControlWndProc(var Message: TMessage);
    property HookedCtrl: TControl read FHookedCtrl write SetHookedCtrl;
  end;

var
  Form5: TForm5;

implementation

{$R *.dfm}

{ TForm5 }

procedure TForm5.CheckBox1Click(Sender: TObject);
begin
  //checkbox activates or deactivates the hook
  if CheckBox1.Checked then
    //hook the panel's WndProc by subclassing
    HookedCtrl := Panel1
  else
    //release the hook on WndProc
    HookedCtrl := nil;
end;

procedure TForm5.ControlWndProc(var Message: TMessage);
begin
  case Message.Msg of
    WM_NCHITTEST:
        //Count how many messages received
        Inc(FMessageCount);
  end;
  //not really handling the messsage, just counting.
  FHookedCtrlWndProc(Message);
end;

procedure TForm5.FormDestroy(Sender: TObject);
begin
  //make sure to clear the hook if assigned
  HookedCtrl := nil;
end;

procedure TForm5.SetHookedCtrl(const Value: TControl);
begin
  if (Value <> FHookedCtrl) then begin
    if Assigned(FHookedCtrl) then begin
      //release the hook
      FHookedCtrl.WindowProc := FHookedCtrlWndProc;
      FHookedCtrlWndProc := nil;
      FMessageCount := 0;
    end;
    FHookedCtrl := Value;
    if Assigned(FHookedCtrl) then begin
      //hook the panel (i.e. Value)
      FHookedCtrlWndProc := FHookedCtrl.WindowProc;
      FHookedCtrl.WindowProc := ControlWndProc;
    end;
  end;
end;

procedure TForm5.Timer1Timer(Sender: TObject);
begin
   // Show how many message received
   Label1.Caption := FormatFloat('##,##0 messages', FMessageCount);
end;

end.
单元5;
接口
使用
Winapi.Windows、Winapi.Messages、System.SysUtils、System.Variants、System.Classes、Vcl.Graphics、,
控件、窗体、对话框、ExtCtrls、StdCtrls;
类型
TForm5=类(TForm)
标签1:TLabel;
复选框1:t复选框;
小组1:TPanel;
定时器1:TTimer;
销毁程序表(发送方:TObject);
程序检查框1单击(发送方:ToObject);
程序定时器1定时器(发送方:TObject);
私有的
fhookedtrl:t控制;
fhookedtrlwndproc:TWndMethod;
FMessageCount:整数;
程序SETDCTRL(常数值:t控制);
公众的
过程控制WNDPROC(变量消息:TMessage);
属性hookedtrl:t控制读取fhookedtrl写入设置hookedtrl;
结束;
变量
表5:TForm5;
实施
{$R*.dfm}
{TForm5}
程序t用于M5.复选框1单击(发送方:ToObject);
开始
//复选框激活或停用挂钩
如果复选框1.选中,则
//通过子类化钩住面板的WndProc
hookedtrl:=配电盘1
其他的
//松开WndProc上的挂钩
hookedtrl:=零;
结束;
过程TForm5.ControlWndProc(变量消息:TMessage);
开始
case Message.Msg of of
WM_NCHITTEST:
//