Mouse Events

Anfängerfragen zum Programmieren mit PureBasic.
Benutzeravatar
Qnode
Beiträge: 85
Registriert: 19.07.2018 20:41
Computerausstattung: i5, 16GB RAM, Win10, PureBasic 6.00 (Windows - x64)

Mouse Events

Beitrag von Qnode »

Hey,

ich habe mir mal das Example für das ListIconView aus der PB-Hilfe genommen und eine Eventverarbeitung für Mausklicks dazugepackt. Ich wollte einfach mal wissen, was da an Eventverarbeitung rauskommt, weil ich hier und im englischen Forum gelesen habe, dass die Mausklickverarbeitung manchmal tricky ist und es gibt ja auch Workarounds dafür. Na jedenfalls kommt da ein Verhalten raus, zu dem ich ne Frage habe.
Hier ist der Code:

Code: Alles auswählen

; Zeigt mögliche Flags des ListIconGadgets in Aktion...
If OpenWindow(0, 0, 0, 640, 300, "ListIconGadgets", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
  ; linke Spalte
  TextGadget    (6,  10,  10, 300, 20, "ListIcon Standard", #PB_Text_Center)
  ListIconGadget(0,  10,  25, 300, 70, "Column 1", 100)
  TextGadget    (7,  10, 105, 300, 20, "ListIcon with Checkbox", #PB_Text_Center)
  ListIconGadget(1,  10, 120, 300, 70, "Column 1", 100, #PB_ListIcon_CheckBoxes)  ; ListIcon mit Checkbox
  TextGadget    (8,  10, 200, 300, 20, "ListIcon with Multi-Selection", #PB_Text_Center)
  ListIconGadget(2,  10, 215, 300, 70, "Column 1", 100, #PB_ListIcon_MultiSelect) ; ListIcon mit Mehrfachselektion
                                                                                  ; rechte Spalte
  TextGadget    (9, 330,  10, 300, 20, "ListIcon with separator lines",#PB_Text_Center)
  ListIconGadget(3, 330,  25, 300, 70, "Column 1", 100, #PB_ListIcon_GridLines)
  TextGadget   (10, 330, 105, 300, 20, "ListIcon with FullRowSelect and AlwaysShowSelection",#PB_Text_Center)
  ListIconGadget(4, 330, 120, 300, 70, "Column 1", 100, #PB_ListIcon_FullRowSelect | #PB_ListIcon_AlwaysShowSelection)
  TextGadget   (11, 330, 200, 300, 20, "ListIcon Standard with large icons",#PB_Text_Center)
  ListIconGadget(5, 330, 220, 300, 65, "", 200,#PB_ListIcon_GridLines)
  For a = 0 To 4            ; fügt Spalten zu jedem der ersten 5 ListIcons hinzu
    For b = 2 To 4          ; fügt 3 weitere Spalten zu jedem ListIcon hinzu
      AddGadgetColumn(a, b, "Column " + Str(b), 65)
    Next
    For b = 0 To 2          ; fügt 4 Einträge auf jeder Zeile der ListIcons hinzu
      AddGadgetItem(a, b, "Item 1"+Chr(10)+"Item 2"+Chr(10)+"Item 3"+Chr(10)+"Item 4")
    Next
  Next
  ; Hier ändern wir die Anzeige des ListIcons in große Icons und zeigen ein Bild an
  If LoadImage(0, #PB_Compiler_Home+"Examples\Sources\Data\File.bmp")     ; ändern Sie Pfad/Dateiname für Ihr eigenes 32x32 Pixel Bild
    SetGadgetAttribute(5, #PB_ListIcon_DisplayMode, #PB_ListIcon_LargeIcon)
    AddGadgetItem(5, 1, "Picture 1", ImageID(0))
    AddGadgetItem(5, 2, "Picture 2", ImageID(0))
  EndIf  
  Repeat 
    Event = WaitWindowEvent()
    Select Event
      Case  #PB_Event_Gadget
        Select EventGadget()
          Case 0
            Select EventType()
              Case #PB_EventType_LeftClick : Debug "Linksklick auf ListIcon Standard"
              Case #PB_EventType_RightClick : Debug "Rechtsklick auf ListIcon Standard"
              Case #PB_EventType_LeftDoubleClick : Debug "LinksDoppelklick auf ListIcon Standard"
              Case #PB_EventType_RightDoubleClick : Debug "Rechtsdoppelklick auf ListIcon Standard"
            EndSelect
        EndSelect
    EndSelect
    
    
  Until Event = #PB_Event_CloseWindow
EndIf
Und hier ist die Ausgabe:
Rechtsklick auf ListIcon Standard
Rechtsdoppelklick auf ListIcon Standard
Linksklick auf ListIcon Standard
LinksDoppelklick auf ListIcon Standard
Linksklick auf ListIcon Standard
Hier meine Frage:
Ich hatte schon gelesen, dass ein Doppelklick auch immer das Einzelklickevent auslöst. Damit könnte ich leben, das passt sogar zu dem, was ich mit den Mausevents vorhabe (Einzelklick löst eine Aktualisierung der Anzeige in einer Form aus, Doppelklick öffnet eine weitere Form zur Bearbeitung des Datensatzes).
Was mich stutzig macht:
Doppelklick Rechts löst folgende Kette aus: Einzelklickevent-Doppelklickevent
Doppelklick Links löste folgende Kette aus: Einzelklickevent-Doppelklickevent-Einzelklickevent
Warum dieser Unterschied? Ich finde in meinem primitiven Beispielcode nix, was das erklären könnte. Die Case-Fälle zur Eventverarbeitung sind doch alle gleich.

Könnt ihr mir das sagen?
Benutzeravatar
Macros
Beiträge: 1361
Registriert: 23.12.2005 15:00
Wohnort: Olching(bei FFB)
Kontaktdaten:

Re: Mouse Events

Beitrag von Macros »

Ich habe gerade mal getestet und kann das unter Windows bestätigen.
Der zweite Linkslklick löst genau gleichzeitig das Doppel- und das Linksklickevent aus. In der Eventschleife wird dann der Linksdoppelklick zuerst verarbeitet und somit ergibt sich das Muster
Linksklick auf ListIcon Standard (Zur Zeit des ersten Klicks)
LinksDoppelklick auf ListIcon Standard (Zur Zeit des Folgeklicks)
Linksklick auf ListIcon Standard (Zur Zeit des Folgeklicks)
Unter Linux gibt es das Problem nicht, hier verhält sich der Linksklick genau wieder Rechtsklick, sowohl unter dem GTK als auch unter dem QT Subsystem.
Bild
Benutzeravatar
H.Brill
Beiträge: 496
Registriert: 15.10.2004 17:42
Wohnort: 66557 Neunkirchen

Re: Mouse Events

Beitrag von H.Brill »

Ist ja die Frage, wann Windows es als Linksdoppelklick und wann als zwei einzelne Linkskllicks erkennt.
Dürfte irgendwo im 3stelligen Millisekunden-Bereich liegen. Hat man ja manchmal selber, wenn ein Programm
mit Doppelklick gestartet werden soll. Ist man zu langsam, passiert halt einfach nichts.
Probier mal aus, indem du die Geschwindigkeit zwischen 2 Linksklicks (die ja zu einem Doopelklick führen sollten),
änderst.
Da wird PB auch nur mit Wasser kochen. Diese Events gibt es ja auch in Windows :
$0200 : wm_MouseMove
$0201 : wm_LButtonDown
$0202 : wm_LButtonUp
$0203 : wm_LButtonDblClk
$0204 : wm_RButtonDown
$0205 : wm_RButtonUp
$0206 : wm_RButtonDblClk
$0207 : wm_MButtonDown
$0208 : wm_MButtonUp
$0209 : wm_MButtonDblClk
So könnte ich mir das jedenfalls vorstellen.
PB 6.10
Benutzeravatar
STARGÅTE
Kommando SG1
Beiträge: 7031
Registriert: 01.11.2005 13:34
Wohnort: Glienicke
Kontaktdaten:

Re: Mouse Events

Beitrag von STARGÅTE »

Also ich wundere mich gerade auch, dass wenn ich Rechtsklick auf einen beliebigen Spaltenkopf klicke, ich jedes mal ein Event bekomme, obwohl es ja nur eine Meldung geben sollte wenn EventGadget() = 0 ist.
Scheinbar wird gar keine Gadget-Zuweisung vorgenommen. Kann das jemand bestätigen, dann würde ich ein Bug-Report schreiben.
PB 6.01 ― Win 10, 21H2 ― Ryzen 9 3900X, 32 GB ― NVIDIA GeForce RTX 3080 ― Vivaldi 6.0 ― www.unionbytes.de
Aktuelles Projekt: Lizard - Skriptsprache für symbolische Berechnungen und mehr
Benutzeravatar
mk-soft
Beiträge: 3855
Registriert: 24.11.2004 13:12
Wohnort: Germany

Re: Mouse Events

Beitrag von mk-soft »

Kann sein da PB Intern WM_LButtonUP verwendet um immer ein Event zu erhalten.

Mit eigener Callback kann man die Notify explizit auswerten.

Nur Windows:

Code: Alles auswählen

;-TOP

Procedure WinCB(hWnd, uMSg, wParam, lParam)
  Protected r1 = #PB_ProcessPureBasicEvents
  Protected *hdr.NMHDR, *ItemActivate.NMITEMACTIVATE
  
  Select uMsg
    Case #WM_NOTIFY
      *hdr = lParam
      If *hdr\idFrom = 0
        *ItemActivate = lParam
        Select *ItemActivate\hdr\code
          Case #NM_CLICK
            Debug "CB List Click Item " + *ItemActivate\iItem
          Case #NM_DBLCLK
            Debug "CB List DoubleClick Item " + *ItemActivate\iItem
        EndSelect
      EndIf
  EndSelect
  ProcedureReturn r1
EndProcedure

Procedure UpdateWindow()
  Protected dx, dy
  dx = WindowWidth(0)
  dy = WindowHeight(0) - StatusBarHeight(0) - MenuHeight()
  ; Resize Gadgets
  ResizeGadget(0, 5, 5, dx - 10, dy - 10)
EndProcedure

Procedure Main()
  Protected dx, dy
  
  #WinStyle = #PB_Window_SystemMenu | #PB_Window_SizeGadget | #PB_Window_MaximizeGadget | #PB_Window_MinimizeGadget
  
  If OpenWindow(0, #PB_Ignore, #PB_Ignore, 600, 400, "Test Window", #WinStyle)
    ; MenuBar
    CreateMenu(0, WindowID(0))
    MenuTitle("File")
    
    ; StatusBar
    CreateStatusBar(0, WindowID(0))
    AddStatusBarField(#PB_Ignore)
    
    ; Gadgets
    dx = WindowWidth(0)
    dy = WindowHeight(0) - StatusBarHeight(0) - MenuHeight()
    ListIconGadget(0, 5, 5, dx - 10, dy - 10, "Column 0", 200, #PB_ListIcon_FullRowSelect)
    For i = 0 To 9
      AddGadgetItem(0, -1, "Item " +i)
    Next
    
    ; Bind Events
    BindEvent(#PB_Event_SizeWindow, @UpdateWindow(), 0)
    
    SetWindowCallback(@WinCB(), 0, #PB_Window_ProcessChildEvents)
    
    ; Main Loop
    Repeat
      Select WaitWindowEvent()
        Case #PB_Event_CloseWindow
          Select EventWindow()
            Case 0
              Break
          EndSelect
          
        Case #PB_Event_Menu
          Select EventMenu()
              
          EndSelect
          
        Case #PB_Event_Gadget
          Select EventGadget()
            Case 0
              Select EventType()
                Case #PB_EventType_LeftClick : Debug "Linksklick auf ListIcon Standard"
                Case #PB_EventType_RightClick : Debug "Rechtsklick auf ListIcon Standard"
                Case #PB_EventType_LeftDoubleClick : Debug "LinksDoppelklick auf ListIcon Standard"
                Case #PB_EventType_RightDoubleClick : Debug "Rechtsdoppelklick auf ListIcon Standard"
              EndSelect
          EndSelect
      EndSelect
    ForEver
    
  EndIf
  
EndProcedure : Main()
Alles ist möglich, fragt sich nur wie...
Projekte ThreadToGUI / EventDesigner V3 / OOP-BaseClass-Modul
Downloads auf MyWebspace / OneDrive
Benutzeravatar
mk-soft
Beiträge: 3855
Registriert: 24.11.2004 13:12
Wohnort: Germany

Re: Mouse Events

Beitrag von mk-soft »

STARGÅTE hat geschrieben: 29.02.2024 20:23 Also ich wundere mich gerade auch, dass wenn ich Rechtsklick auf einen beliebigen Spaltenkopf klicke, ich jedes mal ein Event bekomme, obwohl es ja nur eine Meldung geben sollte wenn EventGadget() = 0 ist.
Scheinbar wird gar keine Gadget-Zuweisung vorgenommen. Kann das jemand bestätigen, dann würde ich ein Bug-Report schreiben.
Stimmt.
Kann ich als Bug bestätigen. PB v6.04 und v6.10

P.S. Aber nur wenn das ListIconGadget die Nummer '0' hat

Wenn es nicht null hat, gibt es kein Event auf dem Column Click

Code: Alles auswählen

;-TOP

Procedure WinCB(hWnd, uMSg, wParam, lParam)
  Protected r1 = #PB_ProcessPureBasicEvents
  Protected *hdr.NMHDR, *ItemActivate.NMITEMACTIVATE
  
  Select uMsg
    Case #WM_NOTIFY
      *hdr = lParam
      If *hdr\idFrom = 1 Or *hdr\idFrom = 2
        *ItemActivate = lParam
        Select *ItemActivate\hdr\code
          Case #NM_CLICK
            Debug "CB List Click Gadget " + *hdr\idFrom + " Item " + *ItemActivate\iItem
          Case #NM_DBLCLK
            Debug "CB List DoubleClick Gadget " + *hdr\idFrom + " Item " + *ItemActivate\iItem
        EndSelect
      EndIf
  EndSelect
  ProcedureReturn r1
EndProcedure

Procedure UpdateWindow()
  Protected dx, dy
  dx = WindowWidth(0)
  dy = WindowHeight(0) - StatusBarHeight(0) - MenuHeight()
  ; Resize Gadgets
  ResizeGadget(3, 5, 5, dx - 10, dy - 10)
EndProcedure

Procedure Main()
  Protected dx, dy
  
  #WinStyle = #PB_Window_SystemMenu | #PB_Window_SizeGadget | #PB_Window_MaximizeGadget | #PB_Window_MinimizeGadget
  
  If OpenWindow(0, #PB_Ignore, #PB_Ignore, 600, 400, "Test Window", #WinStyle)
    ; MenuBar
    CreateMenu(0, WindowID(0))
    MenuTitle("File")
    
    ; StatusBar
    CreateStatusBar(0, WindowID(0))
    AddStatusBarField(#PB_Ignore)
    
    ; Gadgets
    dx = WindowWidth(0)
    dy = WindowHeight(0) - StatusBarHeight(0) - MenuHeight()
    
    id1 = 0 ; <- Here set to 1
    id2 = 2
    ListIconGadget(id1, 5, 5, dx - 10, dy - 10, "Column 0", 200, #PB_ListIcon_FullRowSelect)
    For i = 0 To 9
      AddGadgetItem(id1, -1, "Item " +i)
    Next
    ListIconGadget(id2, 5, 5, dx - 10, dy - 10, "Column 0", 200, #PB_ListIcon_FullRowSelect)
    For i = 0 To 9
      AddGadgetItem(id2, -1, "Item " +i)
    Next
    SplitterGadget(3, 5, 5, dx - 10, dy - 10, id1, id2)
    
    ; Bind Events
    BindEvent(#PB_Event_SizeWindow, @UpdateWindow(), 0)
    
    SetWindowCallback(@WinCB(), 0, #PB_Window_ProcessChildEvents)
    
    ; Main Loop
    Repeat
      Select WaitWindowEvent()
        Case #PB_Event_CloseWindow
          Select EventWindow()
            Case 0
              Break
          EndSelect
          
        Case #PB_Event_Menu
          Select EventMenu()
              
          EndSelect
          
        Case #PB_Event_Gadget
          Select EventGadget()
            Case 0 To 3
              Select EventType()
                Case #PB_EventType_LeftClick : Debug "Linksklick auf ListIcon Standard"
                Case #PB_EventType_RightClick : Debug "Rechtsklick auf ListIcon Standard"
                Case #PB_EventType_LeftDoubleClick : Debug "LinksDoppelklick auf ListIcon Standard"
                Case #PB_EventType_RightDoubleClick : Debug "Rechtsdoppelklick auf ListIcon Standard"
              EndSelect
          EndSelect
      EndSelect
    ForEver
    
  EndIf
  
EndProcedure : Main()
Alles ist möglich, fragt sich nur wie...
Projekte ThreadToGUI / EventDesigner V3 / OOP-BaseClass-Modul
Downloads auf MyWebspace / OneDrive
Benutzeravatar
H.Brill
Beiträge: 496
Registriert: 15.10.2004 17:42
Wohnort: 66557 Neunkirchen

Re: Mouse Events

Beitrag von H.Brill »

Könnte evtl. auch damit zusammenhängen, da Qnode das OpenWindow schon mit 0 versehen hat
und später ein ListIconGadget auch noch mal.
Ich würde da nicht die gleichen verwenden, sondern beim OpenWindow mit 0 anfangen und dann
immer um 1 weiter (Enumeration). Enumeration erleichtert es ja, daß man fortlaufende Nummern
hat und daß man keine doppelten hat.

Aber es kommt ja auch darauf an, wie das PB-System die WindowProc intern managed.
PB 6.10
Benutzeravatar
Qnode
Beiträge: 85
Registriert: 19.07.2018 20:41
Computerausstattung: i5, 16GB RAM, Win10, PureBasic 6.00 (Windows - x64)

Re: Mouse Events

Beitrag von Qnode »

Donnerwetter... und ich dachte, dass ich da als Hobbyprogger einfach was nicht verstanden hatte :mrgreen:

Vielen Dank für die Hinweise, das hilft mir schon weiter.
Benutzeravatar
mk-soft
Beiträge: 3855
Registriert: 24.11.2004 13:12
Wohnort: Germany

Re: Mouse Events

Beitrag von mk-soft »

H.Brill hat geschrieben: 01.03.2024 08:34 Könnte evtl. auch damit zusammenhängen, da Qnode das OpenWindow schon mit 0 versehen hat
und später ein ListIconGadget auch noch mal.
Ich würde da nicht die gleichen verwenden, sondern beim OpenWindow mit 0 anfangen und dann
immer um 1 weiter (Enumeration). Enumeration erleichtert es ja, daß man fortlaufende Nummern
hat und daß man keine doppelten hat.

Aber es kommt ja auch darauf an, wie das PB-System die WindowProc intern managed.
Das ist nicht richtig und verursacht unnötige Speicherverschwendung.
Windows haben ihr eigene Objekt Array und Gadgets haben hier eigenes Objekt Array. Wie Images, Fonts, etc
Siehe PB-Hilfe -> PureBasic Objekte

Code: Alles auswählen

Enumeration Windows
  #Main
EndEnumeration

Enumeration MenuBar
  #MainMenu
EndEnumeration

Enumeration MenuItems 
  #MainMenuAbout
  #MainMenuExit
EndEnumeration

Enumeration Gadgets
  
EndEnumeration

Enumeration StatusBar
  #MainStatusBar
EndEnumeration

Enumeration Fonts
  
EndEnumeration

Enumeration Images
  
EndEnumeration
Alles ist möglich, fragt sich nur wie...
Projekte ThreadToGUI / EventDesigner V3 / OOP-BaseClass-Modul
Downloads auf MyWebspace / OneDrive
Benutzeravatar
H.Brill
Beiträge: 496
Registriert: 15.10.2004 17:42
Wohnort: 66557 Neunkirchen

Re: Mouse Events

Beitrag von H.Brill »

Das wußte ich jetzt auch noch nicht.
Ich hatte nur vor ein paar Jahren irgendwo gelesen, daß Controls auch nur Fenster für Windows sind,
also auch so behandelt werden. Ob jetzt zusammengesetzte oder einzelne sei hier mal egal.

Davon bin ich auch ausgegangen, daß Window mir eine ID, unabhängig ob Fenster oder Control, beim
Ertellen zurück gibt. Ich fand das immer schon etwas merkwürdig, warum PB da zwei Varianten
(selbst gewählte Nr|PB_Any) anbietet. Ich persönlich arbeite da lieber mit der von Windows zurück
gegebenen ID (PB_Any), so wie ich es von anderen Sprachen gewohnt bin.
PB 6.10
Antworten