MapPoint BeforeDblClick / BeforeClick Event

Rund um MS-MapPoint

Moderator: Moderatoren

Antworten
Benutzeravatar
AUGE_OHR
Marvin
Marvin
Beiträge: 12903
Registriert: Do, 16. Mär 2006 7:55
Wohnort: Hamburg
Hat sich bedankt: 19 Mal
Danksagung erhalten: 44 Mal

MapPoint BeforeDblClick / BeforeClick Event

Beitrag von AUGE_OHR »

hi,

bislang habe ich ja nur Property und Methoden benutzt. Nun denke ich an folgendes :

User Dblclickt auf ein Pushpin und/oder Note. Ich habe nun dem Pushpin als ID die Kundennummer
gegeben. Ich müsste ja an den Namen der ID kommen mit oPushPin:Name.

Damit müsste ich doch ein SEEK(ID) machen können um den User dann in der Xbase++ Application
den Kunden anzeigen zu können.

Nun gibt es ja nicht viele Events bei MapPoint Control und der BeforeDblClick Event scheint
interessant zu sein ...

Code: Alles auswählen

Occurs after the user double-clicks on the map but before MapPoint has processed the action.

    object.BeforeDblClick(Button, Shift, X, Y, Cancel)

    'Name jedes Objekts anzeigen, auf das der Benutzer auf der Karte doppelklickt
    Set objResults = objMap.ObjectsFromPoint(X, Y)
    For Each objResult In objResults
      MsgBox objResult.Name
    Next
wieso hab ich da eine FOR/NEXT bei einem click ? sind das dann mehrere Resultate ?
ich verstehe noch nicht "was" Mappoint als "Action" meint und ob ich den Name als ID nun nehmen
kann ?

p.s. ich habe den Titel erweitert
Zuletzt geändert von AUGE_OHR am Fr, 17. Okt 2008 9:59, insgesamt 1-mal geändert.
gruss by OHR
Jimmy
Benutzeravatar
Martin Altmann
Foren-Administrator
Foren-Administrator
Beiträge: 16501
Registriert: Fr, 23. Sep 2005 4:58
Wohnort: Berlin
Hat sich bedankt: 111 Mal
Danksagung erhalten: 48 Mal
Kontaktdaten:

Re: MapPoint BeforeDblClick event

Beitrag von Martin Altmann »

Hallo Jimmy,
nur eine Idee, da ich MapPoint ja nicht nutze:
Wegen der Zoom-Stufe?
Stell Dir vor, Du hast Deutschland in der Übersicht. In Hamburg hast Du 300 Kunden, wobei Hamburg in der Gesamtansicht (Deutschland komplett) nur relativ klein dargestellt wird. Du hast also nicht 300 sichtbare Pushpins, sondern wesentlich weniger, da sich hinter jedem Punkt mehrere Kunden verbergen.
Wenn Du jetzt auf einen doppelt klickst, willst Du alle Kunden haben, die sich in der Gegend befinden.
Ist die Zoom-Stufe natürlich so klein, dass Du für jeden Kunden einen einzelnen Pushpin siehst, brauchst Du die FOR-Schleife sicherlich nicht!

Viele Grüße,
Martin
:grommit:
Webseite mit XB2.NET und ausschließlich statischem Content in Form von HTML-Dateien: https://www.altem.de/
Webseite mit XB2.NET und ausschließlich dynamischem Content in Form von in-memory-HTML: https://meldungen.altem.de/

Mitglied der XUG Osnabrück
Vorsitzender des Deutschsprachige Xbase-Entwickler e. V.
Benutzeravatar
AUGE_OHR
Marvin
Marvin
Beiträge: 12903
Registriert: Do, 16. Mär 2006 7:55
Wohnort: Hamburg
Hat sich bedankt: 19 Mal
Danksagung erhalten: 44 Mal

Re: MapPoint BeforeDblClick event

Beitrag von AUGE_OHR »

hi,
Martin Altmann hat geschrieben: Ist die Zoom-Stufe natürlich so klein, dass Du für jeden Kunden einen einzelnen Pushpin siehst, brauchst Du die FOR-Schleife sicherlich nicht!
ja klar daran hatte ich nicht gedacht ...
gruss by OHR
Jimmy
Benutzeravatar
AUGE_OHR
Marvin
Marvin
Beiträge: 12903
Registriert: Do, 16. Mär 2006 7:55
Wohnort: Hamburg
Hat sich bedankt: 19 Mal
Danksagung erhalten: 44 Mal

Re: MapPoint BeforeDblClick / BeforeClick Event

Beitrag von AUGE_OHR »

hi,

ich habe den Title erweitert und mache mal einen Sprung zum BeforeClick Event :

Code: Alles auswählen

cEventName := "BeforeClick"
xVar       := oApp:oMap:isEventPublished(cEventName)
IF xVar <> Nil
  lSuccess := oApp:oMap:SubscribeEvent(xVar,{| Button, Shift, X, Y, Cancel | ;
                            oApp:MPBeforeClick(Button, Shift, X, Y, Cancel) })
ENDIF
...

METHOD XbMap:MPBeforeClick(Button, Shift, X, Y, Cancel)
LOCAL oLoc := ::oMap:ActiveMap:XYToLocation(X,Y)
oLoc:GoTo()
RETURN self
klasse macht er wie im Beispiel angegeben, aber leider macht er das nun bei jedem Click auch die
rechte Maustaste ...
ok ich habe die Parameter (Button, Shift, X, Y, Cancel) noch nicht "ausgewertet", aber auch
wenn ich auf eine :Note von einem Balloon clicke wird die Aktion ausgelöst ...

also wieder zurück zum BeforeDblClick Event der die selben Parameter hat ... aber auch da das
Problem wenn ich auf eine :Note DblClick das er dann gleich losrennt.

Nur wenn ich einen PushPin direkt "treffe" scheint der SelectionChange Event einzutreffen und
ich bekomme die neue Location und den :Name = Kunden ID

achso der 4th Parameter Cancel :
Cancel Boolean. False, wenn das Ereignis eintritt. Wenn die Ereignisprozedur dieses Argument
auf True setzt, wird der Klick ignoriert.
em ... äh ... wie "setzte" ich den den Parameter in einem Event ?

@Martin : Du hast Recht mit ObjectsFromPoint(X, Y) bekomme ich fast immer > 1 zurück,
allerdings hab ich andere Probleme damit was ich in einem anderen Thread ansprechen werde.
gruss by OHR
Jimmy
Benutzeravatar
AUGE_OHR
Marvin
Marvin
Beiträge: 12903
Registriert: Do, 16. Mär 2006 7:55
Wohnort: Hamburg
Hat sich bedankt: 19 Mal
Danksagung erhalten: 44 Mal

Re: MapPoint BeforeDblClick / BeforeClick Event

Beitrag von AUGE_OHR »

hi,

warum einfach wenn man es auch kompliziert machen kann ...

also ... ein "einfaches" SubscribeEvent() reicht nicht aus. Ich kann zwar damit "den" Event erreichen
aber es gibt ja noch "andere" ... alle activeX laufen ja auch noch durch "ihren" COMDefaultHandler.

Der "Effekt" war unter anderem das "alles" für ihn ein BeforeClick Event war, egal was ich "getroffen"
hatte. Ich will aber nur "Meine PushPin" und Waypoints haben.

Nun hab ich mir also doch einen eigenen COMDefaultHandler eingebaut und schon kam das
nächste "Problem" ... ich brauche die "nDispID" dafür !?

hm ... was ist das nun schon wieder ... zum Glück fand ich mal was im Xbase++ Help File
:isEventPublished( <cName> ) --> nDISPID
na ... aber das hab ich doch ...

Code: Alles auswählen

cEventName := "SelectionChange"
xVar       := oApp:oMap:isEventPublished(cEventName)
IF xVar <> Nil
   lSuccess := oApp:oMap:SubscribeEvent(xVar,{| NewSelection, OldSelection|;
                         oApp:MPSelectionChange(NewSelection, OldSelection) })
   MPDISPID_SelectionChange := xVar
ENDIF
MPDISPID_ ist nun wiederum ein Element aus einem Array welche ich über #xtranslate anspreche

Code: Alles auswählen

#xtranslate MPDISPID_AfterRedraw          => DispID[\1]
#xtranslate MPDISPID_AfterViewChange      => DispID[\2]
#xtranslate MPDISPID_BeforeClick          => DispID[\3]
#xtranslate MPDISPID_BeforeClose          => DispID[\4]
#xtranslate MPDISPID_BeforeDblClick       => DispID[\5]
#xtranslate MPDISPID_BeforeSave           => DispID[\6]
#xtranslate MPDISPID_DataMapChange        => DispID[\7]
#xtranslate MPDISPID_MouseDown            => DispID[\8]
#xtranslate MPDISPID_MouseMove            => DispID[\9]
#xtranslate MPDISPID_MouseUp              => DispID[\10]
#xtranslate MPDISPID_New                  => DispID[\11]
#xtranslate MPDISPID_NewDataSet           => DispID[\12]
#xtranslate MPDISPID_Open                 => DispID[\13]
#xtranslate MPDISPID_Quit                 => DispID[\14]
#xtranslate MPDISPID_ReadyStateChange     => DispID[\15]
#xtranslate MPDISPID_RouteAfterCalculate  => DispID[\16]
#xtranslate MPDISPID_RouteAfterOptimize   => DispID[\17]
#xtranslate MPDISPID_SelectionChange      => DispID[\18]

STATIC DispID := {}

AADD( DispID, ARRAY( 18 ) )
MPDISPID_AfterRedraw         := NIL
MPDISPID_AfterViewChange     := NIL
MPDISPID_BeforeClick         := NIL
MPDISPID_BeforeClose         := NIL
MPDISPID_BeforeDblClick      := NIL
MPDISPID_BeforeSave          := NIL
MPDISPID_DataMapChange       := NIL
MPDISPID_MouseDown           := NIL
MPDISPID_MouseMove           := NIL
MPDISPID_MouseUp             := NIL
MPDISPID_New                 := NIL
MPDISPID_NewDataSet          := NIL
MPDISPID_Open                := NIL
MPDISPID_Quit                := NIL
MPDISPID_ReadyStateChange    := NIL
MPDISPID_RouteAfterCalculate := NIL
MPDISPID_RouteAfterOptimize  := NIL
MPDISPID_SelectionChange     := NIL

METHOD XbMap:COMDefaultHandler( nDISPID, mp1, mp2, mp3, mp4, mp5, ;
                                             mp6, mp7, mp8, mp9, mp10 )
DO CASE
      CASE nDISPID == MPDISPID_AfterRedraw
      CASE nDISPID == MPDISPID_AfterViewChange
      CASE nDISPID == MPDISPID_BeforeClick
         PostAppEvent( xbeE_BeforeClick        , mp1, mp2, self )
      CASE nDISPID == MPDISPID_BeforeClose
      CASE nDISPID == MPDISPID_BeforeDblClick
         PostAppEvent( xbeE_BeforeDblClick     , mp1, mp2, self )
      CASE nDISPID == MPDISPID_BeforeSave
      CASE nDISPID == MPDISPID_DataMapChange
      CASE nDISPID == MPDISPID_MouseDown
      CASE nDISPID == MPDISPID_MouseMove
      CASE nDISPID == MPDISPID_MouseUp
      CASE nDISPID == MPDISPID_New
      CASE nDISPID == MPDISPID_NewDataSet
      CASE nDISPID == MPDISPID_Open
      CASE nDISPID == MPDISPID_Quit
      CASE nDISPID == MPDISPID_ReadyStateChange
      CASE nDISPID == MPDISPID_RouteAfterCalculate
      CASE nDISPID == MPDISPID_RouteAfterOptimize
      CASE nDISPID == MPDISPID_SelectionChange
         PostAppEvent( xbeE_SelectionChange    ,mp1, mp2, self )
OTHERWISE
      xReturn := ::oMap:COMDefaultHandler( nDISPID, @mp1, @mp2,;
                                            @mp3, @mp4, @mp5, @mp6,;
                                            @mp7, @mp8, @mp9, @mp10 )
ENDCASE
hatte ich schon gesagt das wir noch einige USERDEF Events brauchen ... ?
der COMDefaultHandler sollte "nur" den COM Event "handle´n", aber bloss nichts in die
(zeitkritische) Schleife schreiben, sondern ein PostAppEvent() an die Xbase++ Application
schicken !!!

Code: Alles auswählen

#define xbeE_AfterRedraw             xbeP_User+11
#define xbeE_AfterViewChange         xbeP_User+12
#define xbeE_BeforeClick             xbeP_User+13
#define xbeE_BeforeClose             xbeP_User+14
#define xbeE_BeforeDblClick          xbeP_User+15
#define xbeE_BeforeSave              xbeP_User+16
#define xbeE_DataMapChange           xbeP_User+17
#define xbeE_MouseDown               xbeP_User+18
#define xbeE_MouseMove               xbeP_User+19
#define xbeE_MouseUp                 xbeP_User+20
#define xbeE_New                     xbeP_User+21
#define xbeE_NewDataSet              xbeP_User+22
#define xbeE_Open                    xbeP_User+23
#define xbeE_Quit                    xbeP_User+24
#define xbeE_ReadyStateChange        xbeP_User+25
#define xbeE_RouteAfterCalculate     xbeP_User+26
#define xbeE_RouteAfterOptimize      xbeP_User+27
#define xbeE_SelectionChange         xbeP_User+28

METHOD XbMap:HandleEvent( nEvent, mp1, mp2 )
   DO CASE
     CASE nEvent == xbeE_AfterRedraw
     CASE nEvent == xbeE_AfterViewChange
     CASE nEvent == xbeE_BeforeClick
        ::MPBeforeClick(mp1, mp2 )
        IF ValType(::MPBeforeClick) == "B"
           Eval( ::MPBeforeClick, mp1, mp2, self )
        ENDIF
     CASE nEvent == xbeE_BeforeClose
     CASE nEvent == xbeE_BeforeDblClick
     CASE nEvent == xbeE_BeforeSave
     CASE nEvent == xbeE_DataMapChange
     CASE nEvent == xbeE_MouseDown
     CASE nEvent == xbeE_MouseMove
     CASE nEvent == xbeE_MouseUp
     CASE nEvent == xbeE_New
     CASE nEvent == xbeE_NewDataSet
     CASE nEvent == xbeE_Open
     CASE nEvent == xbeE_Quit
     CASE nEvent == xbeE_ReadyStateChange
     CASE nEvent == xbeE_RouteAfterCalculate
     CASE nEvent == xbeE_RouteAfterOptimize
     CASE nEvent == xbeE_SelectionChange
        ::MPSelectionChange(mp1, mp2 )
        IF ValType(::MPSelectionChange) == "B"
           Eval( ::MPSelectionChange, mp1, mp2, self )
        ENDIF
   OTHERWISE
       RETURN ::oMap:HandleEvent( nEvent, mp1, mp2 )
ENDCASE
wir haben also den COM Event "abgefangen" und an unseren Xbase++ HandleEvent() weiter-
gereicht wo wir nun unsere Methode ausführen können.

Code: Alles auswählen

METHOD XbMap:MPBeforeClick(Button, Shift, X, Y, Cancel)
LOCAL oLoc
   oLoc := ::oMap:ActiveMap:XYToLocation(X,Y)
   oLoc:GoTo()
RETURN self
...

METHOD XbMap:MPSelectionChange(NewSelection, OldSelection)
LOCAL oLoc
LOCAL cName
LOCAL cSeek

   IF VALTYPE(NewSelection) = "O"
      // bei einem hierarchisch aufgebauten OOP System kann das Item
      // von verschiedenen Interface genutzt werden. 
      cName := UPPER( NewSelection:interfaceName() )

      // Ich brauche :
      // o:PushPin:Location() oder o:Waypoint:Location()
      IF cName = "PUSHPIN"  .OR. cName = "WAYPOINT"
         oLoc := NewSelection:Location()
         oLoc:GoTo()

         cSeek := oLoc:Name()
         // übertrage Kunden ID ins SLE
         ::oDlgMap:oSeek:setdata( cSeek )
      ELSE
*         MSGBOX("Object ist "+cName)
      ENDIF
   ENDIF

RETURN self
so und nun bin ich endlich langsam da wo ich hin wollte. jetzt muss ich "nur noch" die restlichen
Events mit Code "auffüllen" um die "maximal mögliche" Kontrolle über das activeX zu bekommen.
gruss by OHR
Jimmy
Benutzeravatar
AUGE_OHR
Marvin
Marvin
Beiträge: 12903
Registriert: Do, 16. Mär 2006 7:55
Wohnort: Hamburg
Hat sich bedankt: 19 Mal
Danksagung erhalten: 44 Mal

Re: MapPoint BeforeDblClick / BeforeClick Event

Beitrag von AUGE_OHR »

moin,
Mit Ausnahme des ReadyStateChange-Ereignisses bilden alle Ereignisse ein Pass-Through des gleichen Ereignisses, das auf das Map-Objekt wirkt.
Vermeiden Sie es, mitten in einem Ereignishandler Meldungs- oder Dialogfelder anzuzeigen.
Diesen Satz hätte ich mal gleich zu Anfang lesen sollen dann wäre mir einiges erspart geblieben.

Die Application läuft schon ganz gut, aber einige User haben es trotzdem geschafft einen Fehler
mit dem activeX zu erzeugen ... besonders die "Power" User ... und die "Anfänger".

Ich habe ja nun den BeforeClick Event abgefangen und leite damit eine Aktion ein, aber während
die Aktion "läuft" könnte der User ja "clicken" ... es könnte ja auch ein BeforeDblClick Event sein ...

tja, der "Power" User macht also 2x click und es klappt zu 99% als BeforeDblClick und bei 1% -> peng
ist er "zu langsam" und die Aktion "läuft schon". Bei den Anfängern ist es nun genau anderes rum
den die "clicken" 2x hintereinander "zu langsam" ... die Aktion "läuft schon" -> peng

Leider gibt es nun kein IsBusy() und die Events laufen ja auf "danach" raus ... ich muss es aber
"davor" abfangen ...

tja was nun ... es gibt auch noch einen MouseDown / MouseUp Event ...

was ich also bräuchte wäre ein "Timer" Event über den ich dann, nach Ablauf der Zeit, eine
Aktion ausführe ... je nachdem ob nun innerhalb der Zeitfensters nochmals ge"clickt" wurde.

Die Lösung ist im Prinzip ganz einfach : man baut "in" den Event Handler noch eine AppEvent
Schleife ein wobei der 4th Parameter als "timeout" gesetzt werden kann und nach Ablauf dann
Xbe_None erzeugt (nur 1x click). Somit kann der User jetzt im Setup "seine" Geschwindigkeit
selbst einstellen und ein 3x click wird auch "nur" als BeforeDblClick verarbeitet :)

Noch kein Tip : Es scheint mir bei solchen "zeitkritischen" Dingen besser zu sein wenn man den
Codeblock von einem :activate oder :select in eine Methode verlagert wenn man mehrere "," im
Codeblock hat.

Code: Alles auswählen

von :
oXbp:activate := { || tu1(), tu2(), tu3() .... }

nach :
oXbp:activate := { || tualle() }
Methode App:tualle()
IF .NOT. ::isBusy
   tu1()
   tu2()
   tu3()
...
ENDIF
RETURN self
den selbstverständlich müssen auch die Event der XbParts berücksichtigt werden wenn der User
nun darauf clickt statt auf das activeX.
gruss by OHR
Jimmy
Antworten