:setleave()

Moderator: Moderatoren

Antworten
Benutzeravatar
Rudolf
Programmier-Gott
Programmier-Gott
Beiträge: 1418
Registriert: Mo, 02. Jan 2006 23:03
Wohnort: Salzburg/Österreich
Kontaktdaten:

:setleave()

Beitrag von Rudolf »

Hallo,
habe zwar Roger schon geschrieben, aber noch keine verwertbare Antwort erhalten, darum versuche ich es hier.
Ich habe eine Oberfläche im Metro Stil und möchte wenn ich mit der Maus über den rechten Rand komme, ein Menü einblenden, und wenn die Maus wieder ausserhalb des Bereiches ist, das Menü wieder einklappen. Haben dazu eine unsichtbare Staticund mit :setenter() rufe ich das Menü auf. Aber ich kann dann den Menüdialog mit :setleave() Codeblock nicht wieder schließen. Roger weiss nicht dass es diese Methoden gibt und hat mir empfohlen das über callbacks zu lösen, leider habe ich keine Ahnung was er meint, vielleicht kann mir hier jemand helfen.
Grüße
Rudolf



Code zum Aufruf des Menüs rechts

Code: Alles auswählen

@ 2,DSIZE_X-5              DCSTATIC SIZE 10,DSIZE_Y-4 PIXEL  COLOR GRA_CLR_DARKBLUE,GRA_CLR_DARKBLUE OBJECT oMenuStatic EVAL {|o|o:setenter({||xMenu2(getlist)})}

Menü mit setleave()

Code: Alles auswählen

DCREAD GUI TIMEOUT 15 TITLE "Menue" OPTIONS GetOptions EVAL {|o|o:setleave({||DC_ReadGuiEvent(DCGUI_EXIT_OK,GetList)}),DC_SetWindowTransparency(o:getHwnd(),100), Sleep(1), o:show(), ShowNewUserWindow2(o),dc_inspectobject(o)} MODAL PARENT @oDlg
Dateianhänge
2015-01-13_10h24_10.jpg
2015-01-13_10h24_10.jpg (94.25 KiB) 7745 mal betrachtet
Benutzeravatar
Tom
Der Entwickler von "Deep Thought"
Der Entwickler von "Deep Thought"
Beiträge: 9345
Registriert: Do, 22. Sep 2005 23:11
Wohnort: Berlin
Hat sich bedankt: 100 Mal
Danksagung erhalten: 359 Mal
Kontaktdaten:

Re: :setleave()

Beitrag von Tom »

Auf den ersten Blick: Das SetEnter() ist dem Static zugeordnet, das SetLeave() aber dem Dialog, der das Menü trägt. Wahrscheinlich müsste es zum Static oder zu beiden.
Herzlich,
Tom
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: :setleave()

Beitrag von AUGE_OHR »

Rudolf hat geschrieben:Roger weiss nicht dass es diese Methoden gibt und hat mir empfohlen das über callbacks zu lösen, leider habe ich keine Ahnung was er meint, vielleicht kann mir hier jemand helfen.
ich kenne die Methoden o:setenter() / o:leave auch nicht ...
dafür die aber die Events : xbeM_Enter / xbeM_Leave / xbeM_Motion

Code: Alles auswählen

o:enter  := {| aPos, uNIL, self | ... }
o:leave  := {| uNIL1, uNIL2, self | ... }
o:motion := {| aPos, uNIL, self | ... }
gruss by OHR
Jimmy
Benutzeravatar
Rudolf
Programmier-Gott
Programmier-Gott
Beiträge: 1418
Registriert: Mo, 02. Jan 2006 23:03
Wohnort: Salzburg/Österreich
Kontaktdaten:

Re: :setleave()

Beitrag von Rudolf »

Hallo,
wenn ich über einen Handler die Events abfrage, bekomme ich nur von den Pushbuttons auf dem Dialog jeweils einen xbeM_Leave, aber nicht wenn ich über den Dialog mit der Maus rausfahre. Ich werde mal versuchen setleave() von der übergeordneten XbpWindow() Klasse zu setzen.
Grüße
Rudolf

Code: Alles auswählen

DCREAD GUI OPTIONS GetOptions EVAL {|o|DC_SetWindowTransparency(o:getHwnd(),100), Sleep(1), o:show(), ShowNewUserWindow2(o)} MODAL PARENT @oDlg  HANDLER _checkevent



function _checkevent(nEvent, mp1, mp2, oXbp, oDlg,aGetlist, aRef, lOk)
******************************************************************
 if nEvent = xbeM_Leave
     dcqdebug "Leave",nEvent,mp1,mp2,oXbp
endif
return .t.
Benutzeravatar
Tom
Der Entwickler von "Deep Thought"
Der Entwickler von "Deep Thought"
Beiträge: 9345
Registriert: Do, 22. Sep 2005 23:11
Wohnort: Berlin
Hat sich bedankt: 100 Mal
Danksagung erhalten: 359 Mal
Kontaktdaten:

Re: :setleave()

Beitrag von Tom »

Ich tät's der DrawingArea zuordnen.
Herzlich,
Tom
Benutzeravatar
Rudolf
Programmier-Gott
Programmier-Gott
Beiträge: 1418
Registriert: Mo, 02. Jan 2006 23:03
Wohnort: Salzburg/Österreich
Kontaktdaten:

Re: :setleave()

Beitrag von Rudolf »

Hallo Tom,
dann bekomme ich zwar events, aber immer nur wenn ich über Pushbuttons fahre, nicht aber wenn ich über das Dialogfenster rausfahre. Setevent() funktioniert aber, nur leider nicht mit dem Dialogfenster. Bekomme auch dann einen eXpress++ Fehler.
Grüße
Rudolf

Code: Alles auswählen

DCREAD EVAL {|o|testdlg(o)} MODAL PARENT @oDlg 
RETURN .t.

FUNCTION testdlg( oDlg ) 
******************************************************************
oDlg:drawingarea:setleave({||testleave()})
RETURN nil

function testleave()
******************************************************************
dcqdebugoff "leave!"
return .t.


------------------------------------------------------------------------------
ERROR LOG of "v:\Metro\METRO.exe" Date: 14-01-2015 10:44:05

Xbase++ version : Xbase++ (R) Version 1.90.355
Operating system : Windows Vista 06.01 Build 07600
------------------------------------------------------------------------------
oError:args :
-> VALTYPE: O CLASS: XbpIWindow
-> VALTYPE: N VALUE: 0
-> VALTYPE: N VALUE: 0
-> VALTYPE: N VALUE: 1048598
oError:canDefault : N
oError:canRetry : N
oError:canSubstitute: J
oError:cargo : NIL
oError:description : Parameter has a wrong data type
oError:filename :
oError:genCode : 2
oError:operation : :Motion
oError:osCode : 0
oError:severity : 2
oError:subCode : 1025
oError:subSystem : BASE
oError:thread : 1
oError:tries : 0
------------------------------------------------------------------------------
CALLSTACK:
------------------------------------------------------------------------------
Called from DC_GETLIST:EVENTLOOP(4453)
Called from DC_GETLIST:READGUI(3677)
Called from DC_READGUI(101)
Called from XMENU2(769)
Called from (B)MAINDLG(212)
Called from DC_GETLIST:EVENTLOOP(4453)
Called from DC_GETLIST:READGUI(3677)
Called from DC_READGUI(101)
Called from MAINDLG(228)
Called from (B)TASKBARMENU(1504)
Called from DC_GETLIST:READGUI(3630)
Called from DC_READGUI(101)
Called from TASKBARMENU(1504)
Called from PROG_START(98)
Called from PROGMAIN(36)
Called from MAIN(110)
WorkSpaceList :
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: :setleave()

Beitrag von AUGE_OHR »

Rudolf hat geschrieben:wenn ich über einen Handler die Events abfrage, bekomme ich nur von den Pushbuttons auf dem Dialog jeweils einen xbeM_Leave, aber nicht wenn ich über den Dialog mit der Maus rausfahre.
ein Dialog ist eben KEIN Child ... und diese Art von Events finden mit den Childs ( XbParts ) auf dem Parent ( o:DrawingArea ) statt
xbeM_Enter Mauszeiger wurde in einen Xbase Part bewegt.
xbeM_Leave Mauszeiger wurde aus einem Xbase Part heraus bewegt.
des weiteren gilt
Das Ereignis xbeM_Leave wird nur generiert, wenn das Window-Objekt für die automatische Mauszeigerverfolgung konfiguriert ist. Dieses geschieht beim Zuweisen eines Codeblocks an den Callback-Slot :leave automatisch.

Soll der Ereignis allerdings in der Callback-Methode :leave() behandelt werden, muss die Methode in einer abgeleiteten Klasse überladen werden. Weiter muss die Methode :setTrackPointer() explizit aufgerufen werden, zum Beispiel in der :create()-Methode der abgeleiteten Klasse.
du bekommst zwar den Event xbeM_Enter aber nicht von xbeM_Leave
Die Nachricht xbeM_Leave ist eine synchrone Nachricht. Sie wird direkt über die Methode :handleEvent() eines XbpWindow-Objekts gesendet. Der Ereigniscode xbeM_Leave wird deshalb normalerweise nicht durch die Funktion AppEvent() zurückgegeben. Darüberhinaus wird die Nachricht vom Betriebssystem ausgelöst, während der Mauszeiger vom Anwender über die Benutzeroberfläche der Anwendung bewegt wird. Während der Bearbeitung von xbeM_Enter sollten deshalb keine langwierigen Operationen durchgeführt werden.
wenn du nun die Maus "aus" einem Dialog bewegst dann ist die Position des Cursor ausserhalb des Dialog sein.
nun werden Xbase++ Events aber nur "innerhalb" eines Fenster registriert was man am o:Motion am besten erkennt ( siehe Demo )
Rudolf hat geschrieben:Ich werde mal versuchen setleave() von der übergeordneten XbpWindow() Klasse zu setzen.
sobald du keine Events von o:Motion bekommst bist du ausserhalb des Dialog ;)

p.s. Ausgabe erfolgt im Crt "Fenster" welches hinter dem Dialog liegen könnte ...
WOCURSOR.ZIP
(936 Bytes) 209-mal heruntergeladen
gruss by OHR
Jimmy
Benutzeravatar
Rudolf
Programmier-Gott
Programmier-Gott
Beiträge: 1418
Registriert: Mo, 02. Jan 2006 23:03
Wohnort: Salzburg/Österreich
Kontaktdaten:

Re: :setleave()

Beitrag von Rudolf »

Hallo Jimmy,
danke für die Info und Beispiel, scheint doch nicht so einfach zu sein. Habs schon mit motion versucht und geprüft ob die Maus über einen Bereich am linken Rand fährt, aber wenn man zu schnell ist, dann wird der Event nicht registriert. Werde wohl einen close button machen müssen.
Grüße
Rudolf
Benutzeravatar
brandelh
Foren-Moderator
Foren-Moderator
Beiträge: 15688
Registriert: Mo, 23. Jan 2006 20:54
Wohnort: Germersheim
Hat sich bedankt: 65 Mal
Danksagung erhalten: 33 Mal
Kontaktdaten:

Re: :setleave()

Beitrag von brandelh »

Du könntest einen unsichtbaren StaticBereich auf dein Fenster legen, der 3 oder 4 Pixel kleiner als die drawingArea ist.
Der Übergang von DIESEM auf das FENSTER würd man merken und könnte das als Verlassen des Fensters interpretieren ;-)
Gruß
Hubert
Benutzeravatar
Rudolf
Programmier-Gott
Programmier-Gott
Beiträge: 1418
Registriert: Mo, 02. Jan 2006 23:03
Wohnort: Salzburg/Österreich
Kontaktdaten:

Re: :setleave()

Beitrag von Rudolf »

Hallo Huber,
gute Idee, werde das mal probieren. Aber habe eben gesehen dass wenn man die Maus zu schnell bewegt, events verlorengehen. Habe es vorläufig mit killfocus gelöst, also wenn man ausserhalb clickt. Leider kommt ein Windows Ton der sich nicht abstellen lässt, keine Ahnung wieso.
Grüße
Rudolf
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: :setleave()

Beitrag von AUGE_OHR »

Rudolf hat geschrieben:Habs schon mit motion versucht und geprüft ob die Maus über einen Bereich am linken Rand fährt, aber wenn man zu schnell ist, dann wird der Event nicht registriert. Werde wohl einen close button machen müssen.
bei einem Border, mit 3 Pixel, bekommst du kaum ein Ergebnis beim "drüber fahren" ... und wenn der darauf "steht" wird auf ein "resize" gewartet.
Rudolf hat geschrieben:danke für die Info und Beispiel, scheint doch nicht so einfach zu sein.
denkt doch mal "andersrum" ...

du lässt einen Thread laufen der die "Auswertung" von o:Motion überwacht.
wenn du KEIN Ergebnis durch o:Motion innerhalb einer Zeitspanne bekommst rufst du GetCursorPos() direkt ab
und prüfst ob die Maus rechts vom Dialog steht -> Pop-up Menue (per Animation)
Habe es vorläufig mit killfocus gelöst, also wenn man ausserhalb clickt. Leider kommt ein Windows Ton der sich nicht abstellen lässt, keine Ahnung wieso.
o:killfocus ist IMHO für ein GET Object ...

wenn du

Code: Alles auswählen

o::killInputFocus := {| uNIL1, uNIL2, self | ... }
meinst ist das wenn der Eingabefokus von einem Xbase-Part genommen wurde.

für XbpDialog gibt es

Code: Alles auswählen

o:killDisplayFocus := {| uNIL1, uNIL2, self | ... }
nachdem ein Dialogfenster den Anzeigefokus verloren hat.
gruss by OHR
Jimmy
Benutzeravatar
brandelh
Foren-Moderator
Foren-Moderator
Beiträge: 15688
Registriert: Mo, 23. Jan 2006 20:54
Wohnort: Germersheim
Hat sich bedankt: 65 Mal
Danksagung erhalten: 33 Mal
Kontaktdaten:

Re: :setleave()

Beitrag von brandelh »

Du willst also dass dein Programm verschwindet, wenn du mit der Maus aus dem Bereich des Fensters gehst ?

Dafür wäre ein eigener Thread richtig, ich würde aber jeweils die aktuelle Mausposition mit der des Programmfensters vergleichen und nicht die massenhaft auftretenden move events.

Das Fenster verliert seinen Focus erst, wenn mit der Maus auf ein anderes geklickt wurde, das scheint mir daher für obigen Zweck ungeeignet.
Gruß
Hubert
Sören
Rekursionen-Architekt
Rekursionen-Architekt
Beiträge: 205
Registriert: Mo, 07. Aug 2006 10:18
Wohnort: Leipzig
Danksagung erhalten: 11 Mal

Re: :setleave()

Beitrag von Sören »

Hallo Rudolf,

Du musst die Mousecursor-Verfolgung mittels

Code: Alles auswählen

oStatic:setTrackPointer( .T. )
einschalten, andernfalls funktionieren die Methoden bzw.
Callbacks :Enter und :Leave nicht.
Beste Grüße,
Sören
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: :setleave()

Beitrag von AUGE_OHR »

brandelh hat geschrieben:Dafür wäre ein eigener Thread richtig, ich würde aber jeweils die aktuelle Mausposition mit der des Programmfensters vergleichen und nicht die massenhaft auftretenden move events.
also so ...
WOCURSOR_Thread.ZIP
(1.15 KiB) 226-mal heruntergeladen
gruss by OHR
Jimmy
Benutzeravatar
brandelh
Foren-Moderator
Foren-Moderator
Beiträge: 15688
Registriert: Mo, 23. Jan 2006 20:54
Wohnort: Germersheim
Hat sich bedankt: 65 Mal
Danksagung erhalten: 33 Mal
Kontaktdaten:

Re: :setleave()

Beitrag von brandelh »

Sören hat geschrieben:Hallo Rudolf,
Du musst die Mousecursor-Verfolgung mittels

Code: Alles auswählen

oStatic:setTrackPointer( .T. )
einschalten, andernfalls funktionieren die Methoden bzw.
Callbacks :Enter und :Leave nicht.
was es alles gibt, ich sollte doch öffters im Handbuch stöbern ;-)
Gruß
Hubert
Benutzeravatar
Rudolf
Programmier-Gott
Programmier-Gott
Beiträge: 1418
Registriert: Mo, 02. Jan 2006 23:03
Wohnort: Salzburg/Österreich
Kontaktdaten:

Re: :setleave()

Beitrag von Rudolf »

Hallo,
danke für Eure Hilfe, hab jetzt aus den ganzen Infos eine relativ einfache Lösung geschafft.
Grüße
Rudolf

Code: Alles auswählen

FUNCTION xMenu2(aGetlist)
******************************************************************
LOCAL GetList[0], GetOptions,nLine := -10,nBSize := 100,oDlg
LOCAL oMainDlgThread
if !empty(lIsSidemenu)
     return NIL
endif
oMainDlgThread := Thread():new()
lIsSidemenu := .t.
DCGET OPTIONS COLOR GRA_CLR_BLACK SAYWIDTH 0 WINDOWROW 2 WINDOWCOL -300 HIDE BORDER XBPDLG_NO_BORDER NOTITLEBAR  WINDOW HEIGHT DSIZE_Y-200 WINDOW WIDTH 150

...
DCREAD GUI  OPTIONS GetOptions EVAL {|o|o:killDisplayFocus := {||DC_ReadGuiEvent(DCGUI_EXIT_OK,GetList)},oMainDlgThread:Start("CheckMainDlg",o,getlist)} MODAL
oSidemenuDlg := NIL
lIsSidemenu := .f.
RETURN .t.


FUNCTION CheckMainDlg(oMain,aGetlist)
******************************************************************
LOCAL nEvent, mp1, mp2, oXbp
LOCAL aCheck := {0,0}
LOCAL aPos   := {0,0}
LOCAL aSize  := {0,0}
LOCAL oThread := ThreadObject()
nEvent := 0
DO WHILE lIsSidemenu
     nEvent := AppEvent( @mp1, @mp2, @oXbp,100 )
     DO CASE
          CASE nEvent = xbe_None
               aCheck := GetCursorPos()
               aPos   := oMain:CurrentPos()
               aSize  := oMain:CurrentSize()
               IF aCheck[1] < aPos[1]          .OR. ;
                    aCheck[1] > aPos[1]+aSize[1] .OR. ;
                    aCheck[2] < aPos[2]          .OR. ;
                    aCheck[2] > aPos[2]+aSize[2]
                    DC_ReadGuiEvent(DCGUI_EXIT_ABORT,aGetList)
                    lIsSidemenu := .f.
                    //dcqdebugoff "----------- oustsid -------------------"
               ENDIF
          CASE nEvent = xbeM_Motion

          OTHERWISE
          oXbp:handleEvent( nEvent, mp1, mp2 )
     ENDCASE
ENDDO
oThread:quit()
oThread:setInterval(NIL)
oThread := NIL
RETURN NIL


Antworten