AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Code-Bibliothek Neuen Beitrag zur Code-Library hinzufügen Delphi Multitouch Anwendung unter Delphi 7
Thema durchsuchen
Ansicht
Themen-Optionen

Multitouch Anwendung unter Delphi 7

Ein Thema von ich2 · begonnen am 21. Nov 2010 · letzter Beitrag vom 23. Nov 2010
Antwort Antwort
Benutzerbild von ich2
ich2

Registriert seit: 7. Dez 2005
Ort: Würzburg
54 Beiträge
 
#1

Multitouch Anwendung unter Delphi 7

  Alt 21. Nov 2010, 21:46
Hallo zusammen...

da ich mir ein Multitouch fähiges Tablet gekönnt habe, will ich natürlich auch gerne diese schöne Eigenschaft ausnutzen. Und das natürlich gerne unter Delphi 7!

Diese ganze Geschichte ist ja in Delphi 2010 bereits fest initialisiert, aber wir schauen einfach nach den nötigen Funktionen und Definitionen und holen sie uns nach Delphi 7. Eine kleine Einführung gibt bereits diese Seite:
http://wiki.helpmvp.com/home/notes/touch

Ich wollte aber noch zusätzlich die Anzahl der Finger und die Positionen der Finger haben, also mußte das Ganze noch mit dem WM_TOUCH -Event erweitert werden...

erstmal ein paar Definitionen:
Delphi-Quellcode:
const
  WM_GESTURENOTIFY = $011A;
  WM_GESTURE = $0119;
  WM_TOUCH = $0240;

  WM_TABLET_DEFBASE = $02C0;
  WM_TABLET_FLICK = WM_TABLET_DEFBASE + 11;

type
  TGestureNotifyStruct = record
    cbSize: UINT; // size, in bytes, of this structure
    dwFlags: DWORD; // unused
    hwndTarget: HWND; // handle to window targeted by the gesture
    ptsLocation: TSmallPoint; // starting location
    dwInstanceID: DWORD; // internally used
  end;
  PGestureNotifyStruct = ^TGestureNotifyStruct;

  TWMGestureNotify = packed record
    Msg: Cardinal;
    Unused: WPARAM;
    NotifyStruct: PGestureNotifyStruct;
    Result: Integer;
  end;

  HTOUCHINPUT = THandle;

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

...

  TForm1 = class(TForm)
  protected
    procedure WMTOUCH(var Msg: TMessage); message WM_TOUCH;
    procedure WMGestureNotify(var Msg: TWMGestureNotify); message WM_GESTURENOTIFY;
    procedure WMGesture(var Msg: TMessage); message WM_GESTURE;
    procedure WMTabletFlick(var Msg: TMessage); message WM_TABLET_FLICK;
  private
    { Private declarations }
  public
    { Public declarations }
  end;
...dann holen wir uns noch die nötigen Funktionen aus der User32.dll (ACHTUNG: das funktioniert nur unter Windows 7 !!)...

Delphi-Quellcode:
  function CloseTouchInputHandle(hTouchInput: HTOUCHINPUT): BOOL; stdcall;
  function CloseTouchInputHandle; external user32 name 'CloseTouchInputHandle';

  function PhysicalToLogicalPoint(hWnd: HWND; var lpPoint: TPoint): BOOL; stdcall;
  function PhysicalToLogicalPoint; external user32 name 'PhysicalToLogicalPoint';

  function GetTouchInputInfo(hTouchInput: HTOUCHINPUT; cInputs: UINT; pInputs: PTOUCHINPUT; cbSize: Integer): BOOL; stdcall;
  function GetTouchInputInfo; external user32 name 'GetTouchInputInfo';

  function RegisterTouchWindow(hwnd: HWND; ulFlags: Cardinal): BOOL; stdcall;
  function RegisterTouchWindow; external user32 name 'RegisterTouchWindow';

  function UnregisterTouchWindow(hwnd: HWND): BOOL; stdcall;
  function UnregisterTouchWindow; external user32 name 'UnregisterTouchWindow';
...und schon kann man die Eingaben abholen...

Delphi-Quellcode:
procedure TForm1.WMGestureNotify(var Msg: TWMGestureNotify);
begin
  Msg.Result := DefWindowProc(Form1.Handle, Msg.Msg, Msg.Unused, Longint(Msg.NotifyStruct));
end;

procedure TForm1.WMGesture(var Msg: TMessage);
begin
  Msg.Result := DefWindowProc(Form1.Handle, Msg.Msg, Msg.WParam, Msg.LParam);
end;

procedure TForm1.WMTabletFlick(var Msg: TMessage);
begin
  Msg.Result := DefWindowProc(Form1.Handle, Msg.Msg, Msg.WParam, Msg.LParam);
end;

procedure TForm1.WMTOUCH(var Msg: TMessage);
  function TouchPointToPoint(const TouchPoint: TTouchInput): TPoint;
  begin
    Result := Point(TouchPoint.X div 100, TouchPoint.Y div 100);
    PhysicalToLogicalPoint(Form1.Handle, Result);
  end;

var
  TouchInputs: array of TTouchInput;
  counter: Integer;
  Handled: Boolean;
  Point: TPoint;
begin
  Handled := False;
  SetLength(TouchInputs, Msg.WParam);
  GetTouchInputInfo(Msg.LParam, Msg.WParam, @TouchInputs[0], SizeOf(TTouchInput));

  try
    for counter := 1 to Length (TouchInputs) do begin
      Point := TouchPointToPoint(TouchInputs [counter-1]);
      // ...
    end;

    Handled := True;
  finally
    if Handled then
      CloseTouchInputHandle(Msg.LParam)
    else
      inherited;
  end;
end;
...mit dem obigen Code bekommen wir noch keine Fingereingaben...wir müssen noch das Fenster-Handle registrieren...

Delphi-Quellcode:
procedure TForm1.FormCreate(Sender: TObject);
begin
  RegisterTouchWindow ( Form1.Handle, 0 );
end;

procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
  UnRegisterTouchWindow ( Form1.Handle );
end;
...und schon funktioniert es...

viel Spaß beim Spielen
Wissen ist Macht. Das ändert aber so gut wie nichts an der Übermacht der Dummheit.
  Mit Zitat antworten Zitat
Benutzerbild von sx2008
sx2008

Registriert seit: 16. Feb 2008
Ort: Baden-Württemberg
2.332 Beiträge
 
Delphi 2007 Professional
 
#2

AW: Multitouch Anwendung unter Delphi 7

  Alt 21. Nov 2010, 21:57
Schön, aber du hast noch einen heftigen Bug in deinem Code:
Delphi-Quellcode:
procedure TForm1.WMGestureNotify(var Msg: TWMGestureNotify);
begin
  Msg.Result := DefWindowProc(Form1.Handle, Msg.Msg, Msg.Unused, Longint(Msg.NotifyStruct));
end;
Was würde wohl passieren, wenn von der Formular-Klasse TForm1 mehrere Objekte (also Formulare) erzeugt werden?
  Mit Zitat antworten Zitat
Benutzerbild von rollstuhlfahrer
rollstuhlfahrer

Registriert seit: 1. Aug 2007
Ort: Ludwigshafen am Rhein
1.529 Beiträge
 
Delphi 7 Professional
 
#3

AW: Multitouch Anwendung unter Delphi 7

  Alt 21. Nov 2010, 22:33
Ums kurz zu machen: Da muss Self.Handle rein.

Bernhard

PS: Grund: Wenn du mehr als 1 Form hast, dann wird bei allen außer der ersten das falsche Handle genommen, nämlich das der ersten. Wenn du jetzt allerdings alle Forms auf die Variable Form1 erzeugst, dann hast du für alle außer der neusten Form den Fehler.
Bernhard
Iliacos intra muros peccatur et extra!
  Mit Zitat antworten Zitat
21. Nov 2010, 22:36
Dieses Thema wurde am "21. Nov 2010, 22:36 Uhr" von "Matze" aus dem Forum "Programmieren allgemein" in das Forum "Neuen Beitrag zur Code-Library hinzufügen" verschoben.
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
44.184 Beiträge
 
Delphi 12 Athens
 
#5

AW: Multitouch Anwendung unter Delphi 7

  Alt 21. Nov 2010, 22:53
Hab mal ein bissl am Exceptionhandling rumgespielt.
TouchPointToPoint wird in den Private-Abschnitt der TForm1 verschoben.
Und die angesprochenen Form1 entfernt.

Delphi-Quellcode:
procedure TForm1.WMGestureNotify(var Msg: TWMGestureNotify);
begin
  Msg.Result := DefWindowProc(Handle, Msg.Msg, Msg.Unused, Longint(Msg.NotifyStruct));
end;

procedure TForm1.WMGesture(var Msg: TMessage);
begin
  Msg.Result := DefWindowProc(Handle, Msg.Msg, Msg.WParam, Msg.LParam);
end;

procedure TForm1.WMTabletFlick(var Msg: TMessage);
begin
  Msg.Result := DefWindowProc(Handle, Msg.Msg, Msg.WParam, Msg.LParam);
end;

function TForm1.TouchPointToPoint(const TouchPoint: TTouchInput): TPoint;
begin
  Result := Point(TouchPoint.X div 100, TouchPoint.Y div 100);
  PhysicalToLogicalPoint(Handle, Result);
end;

procedure TForm1.WMTouch(var Msg: TMessage);
var
  TouchInputs: array of TTouchInput;
  counter: Integer;
  Point: TPoint;
begin
  SetLength(TouchInputs, Msg.WParam);
  GetTouchInputInfo(Msg.LParam, Msg.WParam, @TouchInputs[0], SizeOf(TTouchInput));
  try
    for counter := 0 to High(TouchInputs) do begin
      Point := TouchPointToPoint(TouchInputs[counter]);

      // ...

    end;
  finally
    CloseTouchInputHandle(Msg.LParam);
  end;
  inherited;
end;

Tipp: Verschiebe einfach mal diese globale Variable aus deiner Unit in die DPR.
Bzw. lösch diese aus deinen Unit und erstelle eine Dummy: TForm; in deiner DPR und benenne alle Form-Variablen in diese um.

Wenn danach dein Programm noch funktioniert, dann hast du es richtig gemacht.


Diese Globale ist einfach nur was Schreckliches und gehört abgeschafft.
$2B or not $2B

Geändert von himitsu (21. Nov 2010 um 23:01 Uhr)
  Mit Zitat antworten Zitat
Benutzerbild von ich2
ich2

Registriert seit: 7. Dez 2005
Ort: Würzburg
54 Beiträge
 
#6

AW: Multitouch Anwendung unter Delphi 7

  Alt 21. Nov 2010, 22:59
Danke für die schnelle Antworten und die Tips...

werde sie in meinen Projekten berücksichtigen...
Wissen ist Macht. Das ändert aber so gut wie nichts an der Übermacht der Dummheit.
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
44.184 Beiträge
 
Delphi 12 Athens
 
#7

AW: Multitouch Anwendung unter Delphi 7

  Alt 21. Nov 2010, 23:06
oder eventuell auch so
Delphi-Quellcode:
procedure TForm1.WMTOUCH(var Msg: TMessage);
var
  TouchInputs: array of TTouchInput;
  TouchPoints: array of TPoint;
  counter: Integer;
begin
  SetLength(TouchInputs, Msg.WParam);
  SetLength(TouchPoints, Msg.WParam);
  GetTouchInputInfo(Msg.LParam, Msg.WParam, @TouchInputs[0], SizeOf(TTouchInput));
  CloseTouchInputHandle(Msg.LParam);
  for counter := 0 to High(TouchInputs) do
  begin
    TouchPoints[counter] := Point(TouchInputs[counter].X div 100, TouchInputs[counter].Y div 100);
    PhysicalToLogicalPoint(Handle, TouchPoints[counter]);
  end;


  // ...
  for counter := 0 to High(TouchPoints) do begin
    // TouchPoints[counter]

  end;
  // ...

  inherited;
end;

und alles zusammen, aber dennoch getrennt
Delphi-Quellcode:
type
  TForm1 = class(TForm)
  protected
    procedure WndProc(var Message: TMessage); override;
  private
    { Private declarations }
  public
    { Public declarations }
    procedure OnTouchPoints(const TouchPoints: TTouchPoints);
  end;

procedure TForm1.WndProc(var Message: TMessage);
var
  TouchInputs: array of TTouchInput;
  TouchPoints: array of TPoint;
  counter: Integer;
begin
  if Message.msg = WM_GESTURENOTIFY then
    Msg.Result := DefWindowProc(Handle, Msg.Msg, Msg.Unused, Longint(Msg.NotifyStruct))
  else
  if Message.msg = WM_GESTURE then
    Msg.Result := DefWindowProc(Handle, Msg.Msg, Msg.WParam, Msg.LParam)
  else
  if Message.msg = WM_TABLET_FLICK then
    Msg.Result := DefWindowProc(Form1.Handle, Msg.Msg, Msg.WParam, Msg.LParam)
  else
  if Message.msg = WM_TOUCH then
  begin
    SetLength(TouchInputs, Msg.WParam);
    SetLength(TouchPoints, Msg.WParam);
    GetTouchInputInfo(Msg.LParam, Msg.WParam, @TouchInputs[0], SizeOf(TTouchInput));
    CloseTouchInputHandle(Msg.LParam);
    for counter := 0 to High(TouchInputs) do
    begin
      TouchPoints[counter] := Point(TouchInputs[counter].X div 100, TouchInputs[counter].Y div 100);
      PhysicalToLogicalPoint(Handle, TouchPoints[counter]);
    end;
    OnTouchPoints(TouchPoints);
    inherited;
  end else
    inherited;
end;

procedure TForm1.OnTouchPoints(const TouchPoints: TTouchPoints);
begin
  // ...
end;
$2B or not $2B

Geändert von himitsu (21. Nov 2010 um 23:15 Uhr)
  Mit Zitat antworten Zitat
greenmile

Registriert seit: 17. Apr 2003
1.107 Beiträge
 
Delphi 10.3 Rio
 
#8

AW: Multitouch Anwendung unter Delphi 7

  Alt 23. Nov 2010, 10:38
Hallo,

ich denke da fehlt noch etwas ganz wichtiges. Nachdem Windows "WMGestureNotify" gesendet hat, muss man mittels "SetGestureConfig" definieren, welche Gesturen man gerne bekommen möchte (im Zweifelsfall GC_ALLGESTURES):

TGestureStruct = packed record
dwID: DWord; // gesture ID
dwWant: Dword; // settings related to gesture ID that are to be turned on
dwBlock: DWord; // settings related to gesture ID that are to be turned off
End;
PGestureStruct = ^TGestureStruct;


procedure TForm1.WMGestureNotify(var Msg: TWMGestureNotify);
var GCGestureStruct;
begin
GC.dwID := Msg.NotifyStruct.dwInstanceID;
GC.dwWant := 1; // GC_ALLGESTURES;
SetGestureConfig(Msg.NotifyStruct.hwndTarget, 0, 3, @gc, SizeOf(TGestureStruct));

Msg.Result := DefWindowProc(Handle, Msg.Msg, Msg.Unused, Longint(Msg.NotifyStruct));
end;

Anschließend sollte WMGesture ankommen. Klappt bei mir allerdings nicht, ich denke ich habe nen Fehler im Struct.
  Mit Zitat antworten Zitat
Antwort Antwort


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 06:19 Uhr.
Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz