gpt4 book ai didi

Delphi VCL - WM_Touch RegisterTouchWindow(Handle, 0);触摸面板时不会处理消息

转载 作者:行者123 更新时间:2023-12-02 06:51:29 27 4
gpt4 key购买 nike

我正在使用 Delphi 10.1 Berlin,VCL 项目。我尝试使用触摸屏和 Windows 生成的 WM_Touch 消息同时移动多个面板。我基于 Chris Benson 博客中的示例代码:http://chrisbensen.blogspot.com/2009/11/touch-demo.html

只有当我先触摸背景表单上的某个位置,然后将手指拖到面板上时,它才在一定程度上起作用。如果我先触摸背景,面板将随着我的手指移动。据我所知,当我触摸窗体顶部的面板时,似乎 TForm1.WMTouch 过程不会被调用。除非我先触摸表单,否则我不会收到 WM_Touch 消息。

在 Chris 的博客中,他调用了 RegisterTouchWindow(Handle, 0);在表单创建中。我认为这就是为什么当您触摸表单时会调用该过程的原因。每当我触摸面板时,如何调用 WM_Touch 过程?

-我尝试使用面板的 OnClick 事件,但这不起作用,因为它似乎没有将触摸注册为 OnClick 事件。

-这是我应该使用 Inherit 类的东西吗?如果是这样,我该怎么做?

预先感谢您的任何想法!

unit Unit2;

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
TOUCHINPUT = record
x: Integer;
y: Integer;
hSource: THandle;
dwID: DWORD;
dwFlags: DWORD;
dwMask: DWORD;
dwTime: DWORD;
dwExtraInfo: ULONG_PTR;
cxContact: DWORD;
cyContact: DWORD;
end;

type
TForm1 = class(TForm)
Panel1: TPanel;
Panel2: TPanel;
Panel3: TPanel;

procedure WMTouch(var Message: TMessage); message wm_Touch;
procedure FormCreate(Sender: TObject);
procedure FormClose(Sender: TObject; var Action: TCloseAction);

end;

var
Form1: TForm1;

implementation
//==============================================================================

//======================== FORM CREATE =========================================

procedure TForm1.FormCreate(Sender: TObject);
begin
// inherited;
RegisterTouchWindow(Handle, 0);
end;

procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
UnregisterTouchWindow(Handle);
end;

//==============================================================================

//========================= WM TOUCH ===========================================

procedure TForm1.WMTouch(var Message: TMessage);
//==============
function TouchPointToPoint(const TouchPoint: TTouchInput): TPoint;
begin
Result := Point(TouchPoint.X div 100, TouchPoint.Y div 100);
PhysicalToLogicalPoint(Handle, Result);
end;
//==============
var
TouchInputs: array of TTouchInput;
TouchInput: TTouchInput;
Handled: Boolean;
Point: TPoint;

begin
Handled := False;
SetLength(TouchInputs, Message.WParam);
GetTouchInputInfo(Message.LParam, Message.WParam,
@TouchInputs[0], SizeOf(TTouchInput));
try
for TouchInput in TouchInputs do
begin
Point := TouchPointToPoint(TouchInput);
if PtInRect(Panel1.BoundsRect,Point) then
begin
label1.Caption:='Touch ID: ' + inttostr(TouchInput.dwID);
panel1.Top:=point.Y-100;
end;
if PtInRect(Panel2.BoundsRect,Point) then
begin
label1.Caption:='Touch ID: ' + inttostr(TouchInput.dwID);
panel2.Top:=point.Y-100;
end;
if PtInRect(Panel3.BoundsRect,Point) then
begin
label1.Caption:='Touch ID: ' + inttostr(TouchInput.dwID);
panel3.Top:=point.Y-100;
end;
end;
Handled := True;
finally
if Handled then
CloseTouchInputHandle(Message.LParam)
else
// inherited;
end;
end;
end.

最佳答案

From what I can tell, it seems like the TForm1.WMTouch procedure will not get called when I touch a panel that is on top of the Form. I don't receive WM_Touch messages unless I touch the form first.

正确,因为您没有触摸表单本身,而是触摸了表单顶部的面板。

In Chris' blog he calls the RegisterTouchWindow(Handle, 0); in the Form Create. Which I assume is why the procedure will get called when you touch the Form.

是的。

How would I go about getting the WM_Touch procedure called whenever I touch the panel?

您必须注册面板的 HWND 而不是表单的 HWND。并对每个面板单独执行此操作。这甚至在 RegisterTouchWindow() 中也有同样的说明。文档:

Note RegisterTouchWindow must be called on every window that will be used for touch input. This means that if you have an application that has multiple windows within it, RegisterTouchWindow must be called on every window in that application that uses touch features. Also, an application can call RegisterTouchWindow any number of times for the same window if it desires to change the modifier flags. A window can be marked as no longer requiring touch input using the UnregisterTouchWindow function.

您还必须对每个面板进行子类化以处理每个面板的 WM_TOUCH 消息,因为它将直接发送到每个注册的面板而不是表单。

如果您希望表单上的每个面板都具有触摸功能,一个简单的插入器类就足够了:

unit Unit2;

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
TPanel = class(Vcl.ExtCtrls.TPanel)
protected
procedure CreateWnd; override;
procedure DestroyWnd; override;
procedure WMTouch(var Message: TMessage); message WM_TOUCH;
end;

TForm1 = class(TForm)
Panel1: TPanel;
Panel2: TPanel;
Panel3: TPanel;
end;

var
Form1: TForm1;

implementation

type
TOUCHINPUT = record
x: Integer;
y: Integer;
hSource: THandle;
dwID: DWORD;
dwFlags: DWORD;
dwMask: DWORD;
dwTime: DWORD;
dwExtraInfo: ULONG_PTR;
cxContact: DWORD;
cyContact: DWORD;
end;

procedure TPanel.CreateWnd;
begin
inherited;
RegisterTouchWindow(Handle, 0);
end;

procedure TPanel.DestroyWnd;
begin
UnregisterTouchWindow(Handle);
inherited;
end;

procedure TPanel.WMTouch(var Message: TMessage);
function TouchPointToPoint(const TouchPoint: TTouchInput): TPoint;
begin
Result := Point(TouchPoint.X div 100, TouchPoint.Y div 100);
PhysicalToLogicalPoint(Handle, Result);
end;
var
TouchInputs: array of TTouchInput;
TouchInput: TTouchInput;
Handled: Boolean;
Point: TPoint;
begin
Handled := False;
SetLength(TouchInputs, Message.WParam);
GetTouchInputInfo(Message.LParam, Message.WParam,
@TouchInputs[0], SizeOf(TTouchInput));
try
for TouchInput in TouchInputs do
begin
Point := TouchPointToPoint(TouchInput);
if PtInRect(BoundsRect, Point) then
begin
//labelX.Caption := 'Touch ID: ' + IntToStr(TouchInput.dwID);
Top := Point.Y - 100;
end;
Handled := True;
end;
finally
if Handled then
CloseTouchInputHandle(Message.LParam)
else
inherited;
end;
end;

end.

关于Delphi VCL - WM_Touch RegisterTouchWindow(Handle, 0);触摸面板时不会处理消息,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58348375/

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