#WM_* messages in verbindung mit WindowFromPoint_()?

Windowsspezifisches Forum , API ,..
Beiträge, die plattformübergreifend sind, gehören ins 'Allgemein'-Forum.
Benutzeravatar
nicolaus
Moderator
Beiträge: 1175
Registriert: 11.09.2004 13:09
Kontaktdaten:

#WM_* messages in verbindung mit WindowFromPoint_()?

Beitrag von nicolaus »

Ich bin hier gerade auf ne komische sache gestossen.
Ich frage in nem callback verschiedene statuse der maus ab z.b. #wm_mousemove , #wm_lbuttondown u.s.w.
Ich prüfe unter anderem ob sich der cursor über dem nem bestimmten controll befindet
Beispiel:

Code: Alles auswählen

....
  GetCursorPos_(MousePos.POINT)
  Select message
      Case #wm_mousemove 
        If WindowFromPoint_(MousePos\x,MousePos\y) <> mein_controll_handle
          MessageRequester("","is not over",0)
        EndIf
....
und dabei habe ich festgestellt dies wie im obigen beispiel nur mit Statischen formen geht jedoch nicht mit buttons oder so. Liegt das an der funktion WindowFromPoint() aus der API?

Nico
Benutzeravatar
nicolaus
Moderator
Beiträge: 1175
Registriert: 11.09.2004 13:09
Kontaktdaten:

Beitrag von nicolaus »

Also an WindowFromPoint() kann es nicht liegen denn wenn ich mit der mouse über nem button bin und frage im callback die message #wm_lbuttonup ab und drücke dann auf nen button und lasse die mouse los bekomme ich nicht die message #wm_lbuttonup. Bekomme die message genausowenig wenn ich in nen listicongadget klicke und lasse die taste wieder los.
Wieso das denn nich?
Benutzeravatar
Danilo
-= Anfänger =-
Beiträge: 2284
Registriert: 29.08.2004 03:07

Beitrag von Danilo »

nicolaus hat geschrieben:Wieso das denn nich?
Ich rate jetzt einfach mal: Du meinst den Fenstercallback den
Du mit SetWindowCallback() setzt, oder?

Diese MouseMessages kommen aber nicht in diesem Callback
an, sondern im Callback des jeweiligen Controls. Verarbeitet
das Control die Message nicht, wird sie weitergeleitet an das
darüberliegende Fenster (z.B. Static Controls ohne Verarbeitung
der MouseMessages).

Du mußt also mit SetWindowLong direkt den Callback des
Controls ändern, wenn Du diese Nachrichten abfangen/abfragen/
manipulieren möchtest.
cya,
...Danilo
"Ein Genie besteht zu 10% aus Inspiration und zu 90% aus Transpiration" - Max Planck
Benutzeravatar
nicolaus
Moderator
Beiträge: 1175
Registriert: 11.09.2004 13:09
Kontaktdaten:

Beitrag von nicolaus »

Erst mal danke für die schnelle antwort und ja du hast richtig geraten ich meine das Callback vom hauptfenster.
Ich bin davon ausgegangen das ein Controll was in nem fenster ist die message auch immer an das Hauptfenster schickt.
Das ist natürlich jetzt erst mal ein wenig blöd da ich ja nich für hunderte von controlls mit SetWindowLong die callbacks abfragen kann.
Benutzeravatar
Danilo
-= Anfänger =-
Beiträge: 2284
Registriert: 29.08.2004 03:07

Beitrag von Danilo »

nicolaus hat geschrieben:Ich bin davon ausgegangen das ein Controll was in nem fenster ist die message auch immer an das Hauptfenster schickt.
Diese Nachrichten kommen direkt bei dem Control an und
werden von diesem verarbeitet. Stellt das Control dann z.B.
einen MausKlick fest, sendet es dafür eine Nachricht an das
darüberliegende Fenster.
nicolaus hat geschrieben:Das ist natürlich jetzt erst mal ein wenig blöd da ich ja nich für
hunderte von controlls mit SetWindowLong die callbacks abfragen kann.
Du mußt ja nicht für jedes Control eine eigene Callbackprozedur
machen. Eine Prozedur und eine entsprechende Schleife kann es
auch tun, je nachdem was Du genau machen möchtest.
cya,
...Danilo
"Ein Genie besteht zu 10% aus Inspiration und zu 90% aus Transpiration" - Max Planck
Benutzeravatar
nicolaus
Moderator
Beiträge: 1175
Registriert: 11.09.2004 13:09
Kontaktdaten:

Beitrag von nicolaus »

Also um zu wissen für was ich das brauche:
Ich habe nen nen OGL Conext auf nem ContainerGadget. Die Sicht der OGL Scene habe ich mit der Maus verschiebbar gemacht und zwar wenn die linke Maustaste gedrückt ist. Dafür habe ich mir ne Variable angelegt die bei #WM_LBUTTONDOWN in verbindung mit Mouse über dem Container des OGL auf 1 gesetzt wird. Kommt nun die message #WM_LBUTTONUP wird die variable wieder auf 0 gesetzt. (die Variable brauch ich halt noch für andere sachen)
Jetzt gibts aber in dem Programm auch noch ein verschiebbares menu was nix anderes ist wie ein Fenster auf dem untereinander buttons liegen.
Nun versuche ich abzufangen ob bei nem mousemove der cursor über dem Container mit dem OGL Conext ist oder nicht. Sprich wenn ich die Map verschiebe und dabei mit der Mouse über das menu komme soll die variable auf 0 gesetzt werden.
Das geht auch jedoch nur wenn ich über nem bereich des Menüs bin der statisch ist. Sobald ich über nem Button des Menüfensters bin gehts nicht. Auch geht da halt das #WM_LBUTTONUP nicht. (kann ja sein das verschoben wird und genau über nem button die Maustaste losgelassen wird.)

Hoffe das is halbwegs verständlich ausgedrückt
Benutzeravatar
Danilo
-= Anfänger =-
Beiträge: 2284
Registriert: 29.08.2004 03:07

Beitrag von Danilo »

nicolaus hat geschrieben:Hoffe das is halbwegs verständlich ausgedrückt
Naja. :D

So ungefähr habe ich es verstanden. Dein Problem ist scheinbar
das etwas durcheinander kommt, d.h. das sich das Zeug gegenseitig
beeinflußt.

Hier mal ein kleines Beispiel wie Du mit OpenGL die Camera,
Objekte usw. steuern könntest. Dabei sind 3 voneinander
unabhängige Steuerelemente vorhanden: 2 Buttons und
1 ContainerGadget (Dein OpenGL-Screen, wie Du sagtest).

Jedes der SteuerElemente hat eine unabhängige Prozedur,
die dann aufgerufen wird, wenn mit gedrückter Maustaste
der Mauszeiger verschoben wird. Als Parameter haben die
Prozeduren x und y, das ist die Verschiebung seit dem letzten
Aufruf in Pixeln.

Code: Alles auswählen

;
; by Danilo, 2005/10/26
;
Structure ML
  hWnd.l
  EventProc.l
  oldCallback.l
  ButtonDown.l
  oldPt.POINT
EndStructure

NewList MoverList.ML()

Procedure MoverCallback(hWnd,Msg,wParam,lParam)
  ForEach MoverList()
    If MoverList()\hWnd = hWnd
      Select Msg
        Case #WM_LBUTTONDOWN
          SetCapture_(hWnd)
          MoverList()\ButtonDown = 1
          GetCursorPos_(pt.POINT)
          MoverList()\oldPT\X = pt\X
          MoverList()\oldPT\Y = pt\Y
          ;ProcedureReturn 1
        Case #WM_LBUTTONUP
          ReleaseCapture_()
          MoverList()\ButtonDown = 0
          ;ProcedureReturn 1
        Case #WM_MOUSEMOVE
          If MoverList()\ButtonDown
            GetCursorPos_(pt.POINT)
            CallFunctionFast(MoverList()\EventProc,pt\X-MoverList()\oldPt\X,pt\Y-MoverList()\oldPt\Y)
            MoverList()\oldPt\X = pt\X
            MoverList()\oldPt\Y = pt\Y
          EndIf
          ProcedureReturn 1
      EndSelect
      ProcedureReturn CallWindowProc_(MoverList()\oldCallback,hWnd,Msg,wParam,lParam)
    EndIf
  Next
EndProcedure

Procedure MouseMover(hWnd, EventProc)
  AddElement(MoverList())
  MoverList()\hWnd        = hWnd
  MoverList()\EventProc   = EventProc
  MoverList()\oldCallback = SetWindowLong_(hWnd,#GWL_WNDPROC,@MoverCallback())
EndProcedure




;=========================================
; MOUSE MOVER DEMO
;=========================================

Procedure Mover1(x,y)
  Static CameraX, CameraY
  CameraX + x
  CameraY + y
  SetGadgetText(11,"CameraPos: "+Str(CameraX)+","+Str(CameraY))
EndProcedure

Procedure Mover2(x,y)
  Static RotateX, RotateY
  RotateX + x
  RotateY + y
  SetGadgetText(12,"Rotate: "+Str(RotateX)+","+Str(RotateY))
EndProcedure

Procedure Mover3(x,y)
  Static MoveX, MoveY
  MoveX + x
  MoveY + y
  SetGadgetText(13,"Move: "+Str(MoveX)+","+Str(MoveY))
EndProcedure



OpenWindow(0,0,0,740,500,#PB_Window_SystemMenu|#PB_Window_ScreenCentered,"Mover")
  CreateGadgetList(WindowID())
  MouseMover(ContainerGadget(1,0,0,640,480,#PB_Container_Single),@Mover1())
             CloseGadgetList()

  MouseMover(ButtonGadget(2,650,10,80,30,"Rotate"),@Mover2())
  MouseMover(ButtonGadget(3,650,50,80,30,"Move"),@Mover3())

  TextGadget(11,010,481,150,20,"CameraPos: 0,0")
  TextGadget(12,170,481,150,20,"Rotate: 0,0")
  TextGadget(13,330,481,150,20,"Move: 0,0")


Repeat:Until WaitWindowEvent()=#PB_Event_CloseWindow
Mit dieser Methode könntest Du direkt im OpenGL-Screen
Objekte positionieren, zoomen, drehen.
Oder eben die Kamera drehen und verschieben...

Auch wenn Du über die anderen Gadgets kommst, hier bekommt
immer das Gadget den Input, welches Du angeklickt hast.

Hoffe es hilft.
cya,
...Danilo
"Ein Genie besteht zu 10% aus Inspiration und zu 90% aus Transpiration" - Max Planck
Benutzeravatar
Danilo
-= Anfänger =-
Beiträge: 2284
Registriert: 29.08.2004 03:07

Beitrag von Danilo »

Habe mal noch 2 ImageGadgets hinzugefügt:

Code: Alles auswählen

;
; by Danilo, 2005/10/26
;
Structure ML
  hWnd.l
  EventProc.l
  oldCallback.l
  ButtonDown.l
  oldPt.POINT
EndStructure

NewList MoverList.ML()

Procedure MoverCallback(hWnd,Msg,wParam,lParam)
  ForEach MoverList()
    If MoverList()\hWnd = hWnd
      Select Msg
        Case #WM_LBUTTONDOWN
          SetCapture_(hWnd)
          MoverList()\ButtonDown = 1
          GetCursorPos_(pt.POINT)
          MoverList()\oldPT\X = pt\X
          MoverList()\oldPT\Y = pt\Y
          ;ProcedureReturn 1
        Case #WM_LBUTTONUP
          ReleaseCapture_()
          MoverList()\ButtonDown = 0
          ;ProcedureReturn 1
        Case #WM_MOUSEMOVE
          If MoverList()\ButtonDown
            GetCursorPos_(pt.POINT)
            CallFunctionFast(MoverList()\EventProc,pt\X-MoverList()\oldPt\X,pt\Y-MoverList()\oldPt\Y)
            MoverList()\oldPt\X = pt\X
            MoverList()\oldPt\Y = pt\Y
          EndIf
          ProcedureReturn 1
      EndSelect
      ProcedureReturn CallWindowProc_(MoverList()\oldCallback,hWnd,Msg,wParam,lParam)
    EndIf
  Next
EndProcedure

Procedure MouseMover(hWnd, EventProc)
  AddElement(MoverList())
  MoverList()\hWnd        = hWnd
  MoverList()\EventProc   = EventProc
  MoverList()\oldCallback = SetWindowLong_(hWnd,#GWL_WNDPROC,@MoverCallback())
EndProcedure




;=========================================
; MOUSE MOVER DEMO
;=========================================

Procedure Mover1(x,y)
  Static CameraX, CameraY
  CameraX + x
  CameraY + y
  SetGadgetText(11,"CameraPos: "+Str(CameraX)+","+Str(CameraY))
EndProcedure

Procedure Mover2(x,y)
  Static RotateX, RotateY
  RotateX + x
  RotateY + y
  SetGadgetText(12,"Rotate: "+Str(RotateX)+","+Str(RotateY))
EndProcedure

Procedure Mover3(x,y)
  Static MoveX, MoveY
  MoveX + x
  MoveY + y
  SetGadgetText(13,"Move: "+Str(MoveX)+","+Str(MoveY))
EndProcedure

Procedure Mover4(x,y)
  Static Gray.f, Value
  Gray + x * 2.5
  If Gray >  255: Gray =  255: EndIf
  If Gray < -255: Gray = -255: EndIf
  UseImage(1)
  hDC = StartDrawing(ImageOutput())
  If hDC
    If Gray>=0
      Circle(40,40,35,RGB(Gray,Gray,Gray))
    Else
      Circle(40,40,35,RGB(Abs(Gray),Abs(Gray),0))
    EndIf
    StopDrawing()
  EndIf
  SetGadgetState(4,ImageID())
EndProcedure

Procedure Mover5(x,y)
  Static Value
  Value + ((x+y)/2)
  If Value >  999: Value = 999: EndIf
  If Value <   0 : Value =  0 : EndIf
  UseImage(2)
  If StartDrawing(ImageOutput())
    Box(0,0,80,18,RGB($00,$00,$FF))
    BackColor($00,$00,$FF)
    DrawText(Str(Value))
    StopDrawing()
  EndIf
  SetGadgetState(5,ImageID())
EndProcedure



If CreateImage(1,80,80)
  hDC = StartDrawing(ImageOutput())
  If hDC
    Box(0,0,80,80,GetSysColor_(#COLOR_BTNFACE))
    rect.RECT
    rect\top    = 0  : rect\left   = 0
    rect\bottom = 80 : rect\right  = 80
    DrawEdge_(hDC,rect,#EDGE_SUNKEN,#BF_RECT)
    Circle(40,40,35,0)
    StopDrawing()
  EndIf
EndIf

If CreateImage(2,80,16)
  If StartDrawing(ImageOutput())
    Box(0,0,80,18,RGB($00,$00,$FF))
    BackColor($00,$00,$FF)
    DrawText("0")
    StopDrawing()
  EndIf
EndIf

OpenWindow(0,0,0,740,500,#PB_Window_SystemMenu|#PB_Window_ScreenCentered,"Mover")
  CreateGadgetList(WindowID())
  MouseMover(ContainerGadget(1,0,0,640,480,#PB_Container_Single),@Mover1())
             CloseGadgetList()

  MouseMover(ButtonGadget(2,650,10,80,30,"Rotate"),@Mover2())
  MouseMover(ButtonGadget(3,650,50,80,30,"Move"),@Mover3())
  MouseMover(ImageGadget( 4,650,90,80,80,UseImage(1)),@Mover4())
  MouseMover(ImageGadget( 5,650,180,80,16,UseImage(2)),@Mover5())

  TextGadget(11,010,481,150,20,"CameraPos: 0,0")
  TextGadget(12,170,481,150,20,"Rotate: 0,0")
  TextGadget(13,330,481,150,20,"Move: 0,0")


Repeat:Until WaitWindowEvent()=#PB_Event_CloseWindow
Damit kann man also auch selbstgemalte Gadgets machen
die per MausMove Werte erhöhen. Eine Lautstärkeanzeige
und -regelung ist damit schnell gemacht (mal als Beispiel).
cya,
...Danilo
"Ein Genie besteht zu 10% aus Inspiration und zu 90% aus Transpiration" - Max Planck
Benutzeravatar
nicolaus
Moderator
Beiträge: 1175
Registriert: 11.09.2004 13:09
Kontaktdaten:

Beitrag von nicolaus »

Hi Danilo
Erst mal danke für deine Beispiele. Ich habe aber jetzt mal nen screenshot gemacht damit man mal sieht was genau ich meine.

Also das Fenster mit den Button´s drin (Bewegbares Menü) befindet sich innerhalb des Rects der OGL scene. Wenn ich nun mit der Maus die sene verschiebe und dabei mit der Maus auf einmal uber dem bereich des Fensters mit den Buttons bin soll die Hilfsvariable (von der ich nen post weiter oben geschrieben hatte) auf 0 zurück gesetzt werden.

Das Geht auch jedoch nur wenn ich über dem blauen bereich des Menüfensters bin da dieser Statisch ist. Wenn ich über den buttons bin wird das nicht erkannt.
Bild

hier mal der teil aus dem callback in dem ich versuche die abfrage zu machen wo sich die Maus befindet.

Code: Alles auswählen

   .....
      Case #wm_mousemove  ;{
        If WindowFromPoint_(MousePos\x,MousePos\y) <> hcon_karte And LMBD = 1
          LMBD = 0
        EndIf 
   .....
LMBD ist die Hilfsvariable und hcon_karte ist das handle des Containrs auf dem sich der OGL Context befindet. wenn LMBD nun 1 ist (also die linke Maustaste gedrückt ist und die Maus sich über dem Container mit Context befindet) und das Handle, was von WindowFromPoint zurückgegeben wird, ungleich dem des Containers mit Context ist soll LMBD wieder 0 werden.
Und da liegt das prob da sich das zurückgegebene Handle von WindowFromPoint nur bei Stytischen Formen verändert jedoch nicht bei Buttons.
Benutzeravatar
Danilo
-= Anfänger =-
Beiträge: 2284
Registriert: 29.08.2004 03:07

Beitrag von Danilo »

nicolaus hat geschrieben:

Code: Alles auswählen

   .....
      Case #wm_mousemove  ;{
        If WindowFromPoint_(MousePos\x,MousePos\y) <> hcon_karte And LMBD = 1
          LMBD = 0
        EndIf 
   .....
LMBD ist die Hilfsvariable und hcon_karte ist das handle des Containrs auf dem sich der OGL Context befindet. wenn LMBD nun 1 ist (also die linke Maustaste gedrückt ist und die Maus sich über dem Container mit Context befindet) und das Handle, was von WindowFromPoint zurückgegeben wird, ungleich dem des Containers mit Context ist soll LMBD wieder 0 werden.
Und da liegt das prob da sich das zurückgegebene Handle von WindowFromPoint nur bei Stytischen Formen verändert jedoch nicht bei Buttons.
Dann checke doch nicht mit der Funktion WindowFromPoint_(),
sondern von Hand.

Code: Alles auswählen

   .....
      Case #wm_mousemove  ;{
        GetWindowRect_(menu,r.RECT)
        If LMBD = 1
          If MousePos\x >= r\left And MousePos\x <= r\right
            If MousePos\y >= r\top And MousePos\y <= r\bottom
              ; Cursor ueber Menüfenster
              LMBD = 0
            EndIf
          EndIf
        EndIf 
   .....
Ist das einzige und einfachste was mir dazu einfällt, da ich
nicht weiß was Du da noch so gecodet hast.
cya,
...Danilo
"Ein Genie besteht zu 10% aus Inspiration und zu 90% aus Transpiration" - Max Planck
Antworten