AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren

Hook WH_GESTURENOTIFY

Ein Thema von Mossi · begonnen am 28. Jul 2015 · letzter Beitrag vom 29. Jul 2015
Antwort Antwort
Mossi

Registriert seit: 6. Feb 2004
Ort: Wenzenbach
35 Beiträge
 
Delphi 7 Enterprise
 
#1

Hook WH_GESTURENOTIFY

  Alt 28. Jul 2015, 15:19
Hallo zusammen,

ich entwickle an einer Multiscreen-Anwendung und dabei ist eine Aufgabe, dass Eingaben auf dem Hauptbildschirm (Lehrerschirm) auch auf dem zweiten Bildschirm (Projektor, Schülerschirm) ausgegeben werden. Zwichnungen mit der Maus werden dabei mit einem MouseHook (WH_MOUSE) abgefangen und auf dem Schülerschirm ausgegeben.
Jetzt muss ich das Ganze erweitern, um auch Touch-Eingaben auf dem Schülerschirm ausgeben zu können. Dazu hab ich mittlerweile einen zusätzlichen Hook auf WH_GESTURENOTIFY implementiert, der auch angesprochen wird.
Ich hab jetzt schon gelesen, dass man Gestures nicht einfach simulieren kann. Daher hab ich mir gedacht, dass ich die Gestures abfange und in entsprechende MouseEvents umwandle und diese auf dem Schülerschirm ausgeben lasse.
Das Problem an WH_GESTURENOTIFY ist allerdings, dass da noch gar keine Informationen enthalten sind. Dazu denke ich mal, dass ich mit GetGestureInfo die weiteren Informationen abrufen müsste. Aber daran scheitere ich bereits.
Aktuell sieht mein Code im Hook folgendermaßen aus:
Delphi-Quellcode:
lib := LoadLibrary(PChar('user32.dll'))
if lib <> 0 then
begin
  @GetGestureInfo := GetProcAddress(lib, 'GetGestureInfo');
  if @GetGestureInfo <> nil then
  begin
    gestureInfo.cbSize := sizeof(TGestureInfo);
    GetGestureInfo(LongInt(data.lParam), @gestureInfo);
...
Die letzte Zeile liefert mir dann aber false zurück und GetLastError sagt mir "ungültiger Parameter".
Hat jemand Erfahrung damit oder kann mir sagen, was ich da jetzt falsch gemacht habe?

Vielleicht bin ich auch vollkommen auf dem Holzweg und kann mit den Gestures gar nicht arbeiten, sondern müsste stattdessen die WM_TOUCH Events verwenden. Aber jetzt wollte ich es erst einmal nur so probieren, weil WM_TOUCH noch einiges anderes als Vorarbeit verlangen würde.
  Mit Zitat antworten Zitat
Benutzerbild von ULIK
ULIK

Registriert seit: 25. Sep 2006
Ort: Regensburg
393 Beiträge
 
Delphi 11 Alexandria
 
#2

AW: Hook WH_GESTURENOTIFY

  Alt 28. Jul 2015, 15:52
Hi Mossi,

willst Du wirklich WM_GESTURENOTIFY hooken? Ich würde es eher mit WM_GESTURE probieren, da hier dann die relevanten Aktionen stattfinden.

Hier mal ein bischen Code, wie ich ihn bei mir verwende (allerdings will ich da nur Gestures innerhalb des Programms auswerten). Vieleicht hilft's Dir ja

Delphi-Quellcode:
procedure XYZ.WndProc(var Message: TMessage);
var
  bResult: Boolean;
  gi: GESTUREINFO;
  ptPosition: TPoint;
begin
  case Message.Msg of
    WM_GESTURE:
      begin
        ZeroMemory(@gi, SizeOf(gi));
        gi.cbSize := SizeOf(gi);
        bResult := GetGestureInfo(Message.LParam, gi);
        if bResult then
        begin
          case gi.dwID of
            GID_ROTATE: // Drehung
              begin
                case gi.dwFlags of
                  GF_BEGIN: ...;
                  GF_END: ...;
                else
                  ...;
                end;

                // Und weitere Verarbeitung abbrechen
                Message.Result := 1;
                Exit;
              end;

            GID_ZOOM: // Zoom
              begin
                case gi.dwFlags of
                  GF_BEGIN:
                    ...
                       
                    
                  GF_END:
                    begin
                      ...
                    end;
                else
                  FZoomValueTracker.CurrentValue := gi.ullArguments;
                end;

                // Und weitere Verarbeitung abbrechen
                Message.Result := 1;
                Exit;
              end;

            GID_PAN:
              begin
                // aktuelle Position bestimmen
                ptPosition := Point(gi.ptsLocation.x, gi.ptsLocation.y);

                // Panning beginnen oder beenden
                if (gi.dwFlags and GF_BEGIN) = GF_BEGIN then
                begin
                  // Und Position merken
                  FLastPanningPosition := ptPosition;

                  // Panning aktivieren
                  StartPanning(ScreenToClient(ptPosition), False, True);

                  // Feedback verwenden
                  FPanningData.UseFeedback := True;
                  BeginPanningFeedback(Handle);
                end
                else if (gi.dwFlags and GF_END) = GF_END then
                begin
                  // Feredback deaktivieren
                  EndPanningFeedback(Handle, True);
                  CancelPanning;

                  // Und aktuelle Seite aktivieren wenn Gesture-Ende
                  OnEndScroll(self);
                end
                else
                begin
                  // Panning durchführen
                  TrackPanning(ScreenToClient(ptPosition));

                  // Panning Feedback geben
                  if FPanningData.UseFeedback then
                    UpdatePanningFeedback(Handle, -FPanningData.FeedbackOffset.X, -FPanningData.FeedbackOffset.Y, (gi.dwFlags AND GF_INERTIA) = GF_INERTIA);

                end;

                // Und weitere Verarbeitung abbrechen
                Message.Result := 1;
                Exit;
              end;

            GID_END:
              begin
                // zur Sicherheit
                CancelPanning;
              end;
          end;
        end;
      end;

  end;

  inherited WndProc(Message);
end;

Grüße,
Uli
  Mit Zitat antworten Zitat
Mossi

Registriert seit: 6. Feb 2004
Ort: Wenzenbach
35 Beiträge
 
Delphi 7 Enterprise
 
#3

AW: Hook WH_GESTURENOTIFY

  Alt 28. Jul 2015, 21:59
Servus Uli,

das hilft mir auf jeden Fall schon mal ein bisschen weiter, weil ich gesehen hab, dass ich ZeroMemory vergessen habe. Muss ich morgen gleich mal ausprobieren, ob das der Knackpunkt ist.
Urspünglich wollte ich eigentlich WM_GESTURE auswerten, aber da kommt nichts an. Wenn ich im Spy++ schau, bekomme ich lediglich WM_GESTURENOTIFY. Nachdem, was ich gelesen habe, bekommt man immer erst WM_GESTURENOTIFY und müsste dann mit SetGestureConfig festlegen, welche Gestures man auswerten will. Erst dann kann man scheinbar WM_GESTURE auswerten.

Offtopic: Wir müssen mal wieder in Biergarten gehen
  Mit Zitat antworten Zitat
Benutzerbild von ULIK
ULIK

Registriert seit: 25. Sep 2006
Ort: Regensburg
393 Beiträge
 
Delphi 11 Alexandria
 
#4

AW: Hook WH_GESTURENOTIFY

  Alt 29. Jul 2015, 08:43
Servus Mossi,

kommen die die WM_GESTURE Messages an deine Hauptanwendung durch? Ich bin mir grad nicht mehr ganz sicher, aber eventuell mußt Du noch die Touch-Properties in deiner Hauptanwendung setzen:

Delphi-Quellcode:
// Für XE die Touch-Eigenschaften setzen (sonst geht Panning nicht mehr)
  Touch.InteractiveGestureOptions := [igoPanSingleFingerHorizontal, igoPanSingleFingerVertical, igoPanInertia];
  Touch.InteractiveGestures := [igPan, igPressAndTap, igZoom, igRotate];
Müßt ich aber nochmal mit einem frischen Projekt ausprobieren. Ich jedenfalls lang das Zeug inzwischen nur noch an, wenn ich unbedingt muß. Das reagiert manchmal so dermaßen seltsam

Grüße,
Uli

ps: ich meld mich die Tage mal bei Dir.
  Mit Zitat antworten Zitat
Mossi

Registriert seit: 6. Feb 2004
Ort: Wenzenbach
35 Beiträge
 
Delphi 7 Enterprise
 
#5

AW: Hook WH_GESTURENOTIFY

  Alt 29. Jul 2015, 09:32
Jetzt wird's wohl schwierig... Ich häng nämlich immer noch bei Delphi 7 fest und da hab ich keine komfortablen Touch-Properties. Also hab ich schon, aber ich bräuchte die entsprechenden API Aufrufe dafür

Aber, wenn ich nach dieser Seite geh (http://wiki.helpmvp.com/home/notes/touch) muss ich in der Anwendung nur speziell was setzen, wenn ich auf WM_TOUCH gehen will. Das möchte ich aber erst einmal vermeiden, weil ich befürchte, dass es damit noch komplizierter wird.

Gibt es eigentlich irgendeine Möglichkeit, dass ich Touchevents auf einem Nicht-Touch-Fähigen Gerät simuliere? Aktuell ist das ein bisschen unhandlich, wenn ich immer wieder eine neue Exe erstellen muss und dann auf das Surface kopiere, um sie auszuprobieren um dann zu sehen, dass es wieder nicht klappt.
Und Delphi auf dem Surface installieren... Naja. Delphi 7 installieren mit allen notwendigen Komponenten ist einfach kein Spaß und zudem ist das Surface zum Entwickeln auch viel zu klein finde ich.
  Mit Zitat antworten Zitat
Benutzerbild von ULIK
ULIK

Registriert seit: 25. Sep 2006
Ort: Regensburg
393 Beiträge
 
Delphi 11 Alexandria
 
#6

AW: Hook WH_GESTURENOTIFY

  Alt 29. Jul 2015, 10:55
Ok, daran hab ich nicht gedacht.

Was kriegst denn so an Messages rein, wenn Du einfach nur ein Formular nimmst und dessen WNDProc überschreibst und auf WM_GESTURE und WM_GESTURENotify hörst? Und zwar wenn Du ein Panning mit einem und mit zwei Fingern machst, bzw. eine Zoom-Gesture.

Zum Testen: mein Entwicklungsrechner/Monitor ist auch nicht Touchfähig, sprich ich schieb das Programm immer auf das Surface und logge dort die Meldungen mit. Eine andere Möglichkeit kenn ich auch nicht.


Grüße,
Uli
  Mit Zitat antworten Zitat
Mossi

Registriert seit: 6. Feb 2004
Ort: Wenzenbach
35 Beiträge
 
Delphi 7 Enterprise
 
#7

AW: Hook WH_GESTURENOTIFY

  Alt 29. Jul 2015, 11:29
So. Und jetzt bin ich vollkommen verwirrt.
Ich hab ein kleines Testprogramm erstellt. Nur eine Form, ein Memo und eben die wndproc überschrieben, damit die einkommenden Nachrichten ausgegeben werden. Jetzt kommt nur noch MouseMove an und weder Gesture noch GestureNotify noch sonst irgendwas.
Was hab ich denn jetzt wieder übersehen?

Delphi-Quellcode:
  TForm1 = class(TForm)
    Memo1: TMemo;
  private
    { private declarations }
    procedure Output(message: string);
  protected
    procedure wndproc(var message: TMessage); override;
  public
    { public declarations }
  end;

const
  WM_TOUCH = $0240;
  WM_GESTURE = $0119;
  WM_GESTURENOTIFY = $011A;

var
  Form1: TForm1;

implementation

procedure TForm1.Output(message: string);
begin
  OutputDebugString(PChar(message));
  Memo1.Lines.Add(message);
end;

procedure TForm1.wndproc(var message: TMessage);
begin
  inherited wndproc(message);

  case message.msg of
    WM_TOUCH: Output('WM_TOUCH');
    WM_GESTURE: Output('WM_GESTURE');
    WM_GESTURENOTIFY: Output('WM_GESTURENOTIFY');
    WM_MOUSEMOVE: Output('WM_MOUSEMOVE');
  end;
end;

end.
  Mit Zitat antworten Zitat
Benutzerbild von ULIK
ULIK

Registriert seit: 25. Sep 2006
Ort: Regensburg
393 Beiträge
 
Delphi 11 Alexandria
 
#8

AW: Hook WH_GESTURENOTIFY

  Alt 29. Jul 2015, 12:46
Hm,

mehr als Du hab ich ein einem Delphi 2007 Testprogramm grad auch nicht gemacht. Ich schau mal, ob ich noch irgendwo Delphi Delphi 7 hab.

edit: Grad mit Delphi 7 getestet: würde funktionieren und die Messages kommen durch bei Zoomgesture über Memo oder Form

Geändert von ULIK (29. Jul 2015 um 12:54 Uhr) Grund: Test mit D7
  Mit Zitat antworten Zitat
Mossi

Registriert seit: 6. Feb 2004
Ort: Wenzenbach
35 Beiträge
 
Delphi 7 Enterprise
 
#9

AW: Hook WH_GESTURENOTIFY

  Alt 29. Jul 2015, 14:45
Jetzt hab ich es doch mal mit WM_TOUCH probiert. Das Ausgabe-Kontroll auf dem Lehrerschirm hab ich mit RegisterTouchWindow aktiviert und jetzt bekomme ich auch die WM_TOUCH Meldungen.
Jetzt muss das ganze nur noch im Hook verarbeitet werden und da hab ich dann gleich das nächste Problem:

hier meine HookProcedure, wie sie jetzt aussieht:
Delphi-Quellcode:
function TouchHookProc(nCode: Integer; wParam: WPARAM; lParam: LPARAM): LRESULT; stdcall;
var
  GetTouchInputInfo: function (hTouchInput: HTOUCHINPUT; cInputs: UINT;
                     pInputs: PTOUCHINPUT; cbSize: Integer): BOOL; stdcall;
  res: Boolean;
  lib: Cardinal;
  touchInputs: array of TTouchInput;
  data: CWPSTRUCT;
begin
  Result := CallNextHookEx(Touch_HookHandle, nCode, wParam, lParam);
  if nCode < 0 then
    exit;

  if nCode = HC_ACTION then
  begin
    data := PCWPSTRUCT(lParam)^;
    case data.message of
      WM_GESTURENOTIFY: OutputDebugString('WM_GESTURENOTIFY');
      WM_GESTURE: OutputDebugString('WM_GESTURE');
      WM_TOUCH:
       begin
        OutputDebugString('WM_TOUCH');
        OutputDebugString(PChar(IntToStr(data.lParam) + '/' + IntToStr(data.wParam) + '/' + IntToStr(data.message)));
        lib := LoadLibrary(PChar('user32.dll'));
        if lib <> 0 then
        begin
          GetTouchInputInfo := GetProcAddress(lib, 'GetTouchInputInfo');
          if @GetTouchInputInfo <> nil then
          begin
            SetLength(TouchInputs, data.wParam);
            res := GetTouchInputInfo(HTOUCHINPUT(data.lParam),
              data.wParam, @TouchInputs, SizeOf(TTouchInput));
            if not res then
              OutputDebugString(PChar(SysErrorMessage(GetLastError)))
            else
              OutputDebugString(PChar(IntToStr(touchinputs[0].cxContact) + 'x' + IntToStr(touchinputs[0].cyContact)));
          end;
        end;
       end;
    end;
  end;
end;
Ich laufe jetzt leider immer in einen Fehler. Get TouchInputInfo liefert FALSE zurück und der Fehler von GetLastError ist "invalid handle"
Lieg ich da falsch, wenn ich davon ausgehe, dass in lParam das Handle drin steht? Oder ist es zu diesem Zeitpunkt bereits wieder ungültig.
MSDN schreibt folgendes:
Zitat:
The touch input handle received in the LPARAM of a touch message. The function fails with ERROR_INVALID_HANDLE if this handle is not valid. Note that the handle is not valid after it has been used in a successful call to CloseTouchInputHandle or after it has been passed to DefWindowProc, PostMessage, SendMessage or one of their variants.
  Mit Zitat antworten Zitat
Themen-Optionen Thema durchsuchen
Thema durchsuchen:

Erweiterte Suche
Ansicht

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 20:28 Uhr.
Powered by vBulletin® Copyright ©2000 - 2022, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2021 by Daniel R. Wolf