Hook WH_GESTURENOTIFY
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:
Die letzte Zeile liefert mir dann aber false zurück und GetLastError sagt mir "ungültiger Parameter".
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); ... 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. |
AW: Hook WH_GESTURENOTIFY
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 |
AW: Hook WH_GESTURENOTIFY
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 |
AW: Hook WH_GESTURENOTIFY
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:
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 :?
// Für XE die Touch-Eigenschaften setzen (sonst geht Panning nicht mehr)
Touch.InteractiveGestureOptions := [igoPanSingleFingerHorizontal, igoPanSingleFingerVertical, igoPanInertia]; Touch.InteractiveGestures := [igPan, igPressAndTap, igZoom, igRotate]; Grüße, Uli ps: ich meld mich die Tage mal bei Dir. |
AW: Hook WH_GESTURENOTIFY
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. |
AW: Hook WH_GESTURENOTIFY
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 |
AW: Hook WH_GESTURENOTIFY
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. |
AW: Hook WH_GESTURENOTIFY
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 |
AW: Hook WH_GESTURENOTIFY
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:
Ich laufe jetzt leider immer in einen Fehler. Get TouchInputInfo liefert FALSE zurück und der Fehler von GetLastError ist "invalid handle"
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; 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:
|
Alle Zeitangaben in WEZ +1. Es ist jetzt 02:20 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