Treegadget: Wie das Element bei Rechtsclick feststellen

Anfängerfragen zum Programmieren mit PureBasic.
Onetime
Beiträge: 20
Registriert: 15.05.2018 20:02

Treegadget: Wie das Element bei Rechtsclick feststellen

Beitrag von Onetime »

Hallo Leute,

Neu im Forum und schon gleich meine 3. Frage heute...(das sind die gesammelten die mich schon eine weile quälen):

In einem Treegadget will ich mit LinksClick auf einen Eintrag etwas anzeigen. Ein darauffolgender Rechtsclick auf das Element soll dann ein PopupMenu anzeigen.
Gibt's eine Möglichkeit (ohne API) festzustellen auf welchem Element der Click stattgefunden hat ?
Das Problem ist das ich das Popup im Moment dort anzeige wo sich die Maus befindet und der Click kann auch im "Leerraum" unter dem letzten element stattgefunden haben.

Mit anderen Worten: Über #PB_EventType_Change + #PB_EventType_LeftClick krieg ich raus wenn ein element ausgewählt wurde. Wenn dann aber ein RechtsClick auf dem selben Element oder im Leerraum unter dem letzten Element RechtsgeClickt wird gib't kein #PB_EventType_Change und ich kann nicht entscheiden ob die Maus auf dem Element war oder nicht...


Danke!

Gruß
Onetime
Benutzeravatar
Josh
Beiträge: 1028
Registriert: 04.08.2009 17:24

Re: Treegadget: Wie das Element bei Rechtsclick feststellen

Beitrag von Josh »

Bin mir nicht sicher, ob du so was gemeint hast:

Code: Alles auswählen

OpenWindow (0,  0,  0, 200, 650, "TreeGadget", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
TreeGadget (0, 10, 10, 180, 630)

Procedure TreeRightClick ()
  Debug GetGadgetState (0)
EndProcedure

BindGadgetEvent (0, @TreeRightClick(), #PB_EventType_RightClick)

For a = 0 To 10
  AddGadgetItem (0, -1, "Normal Item " + Str(a), 0, 0)
  AddGadgetItem (0, -1, "Node "+Str(a), 0, 0)
  AddGadgetItem (0, -1, "Sub-Item 1", 0, 1)
  AddGadgetItem (0, -1, "Sub-Item 2", 0, 1)
  AddGadgetItem (0, -1, "Sub-Item 3", 0, 1)
  AddGadgetItem (0, -1, "Sub-Item 4", 0, 1)
  AddGadgetItem (0, -1, "File "+Str(a), 0, 0)
Next

Repeat : Until WaitWindowEvent() = #PB_Event_CloseWindow
ccode_new
Beiträge: 1214
Registriert: 27.11.2016 18:13
Wohnort: Erzgebirge

Re: Treegadget: Wie das Element bei Rechtsclick feststellen

Beitrag von ccode_new »

Hallo Onetime,

ich kann dir leider auch nicht weiterhelfen, aber liege ich hiermit (das Problem) richtig ?

Code: Alles auswählen

;Ich glaube hier sieht man das Problem! (Liege ich richtig ?)

;Ich habe aber leider auch keine API-freie Lösung/ platformübergreifende Lösung.

;Klickt man kein Element an wird beim Aktivieren ein Element selektiert. (Unerwünscht!)
;Klickt man in den Freiraum (ohne Eintrag) wird dort das Menü angezeigt (Wegen Mausposition) und es wird z.B. Eintrag 0 ausgewählt. (Unerwünscht!)

Structure Ast
  x.i
  y.i
  w.i
  h.i
EndStructure

Structure MPos
  x.d
  y.d
EndStructure

Global WinMaus.MPos

Global NewList BaumAst.Ast()

Global TestFenster, BaumElement, PopMenu
Global Quit.b = #False
Global KlickElement = -1

Procedure.b OverGadget(*MausPos.MPos, Element)
  If ((*MausPos\x >= GadgetX(Element)) And (*MausPos\x <= (GadgetX(Element) + GadgetWidth(Element))) And (*MausPos\y >= GadgetY(Element)) And (*MausPos\y <= GadgetY(Element) + GadgetHeight(Element)))
    ProcedureReturn #True
  EndIf
  ProcedureReturn #False
EndProcedure

TestFenster = OpenWindow(#PB_Any, 0, 0, 800, 600, "TestFenster", #PB_Window_SystemMenu)
If IsWindow(TestFenster)
  BaumElement = TreeGadget(#PB_Any, 10, 10, 780, 580)
  For i = 0 To 5
    AddGadgetItem(BaumElement, i, "Eintrag: "+Str(i))
    AddElement(BaumAst()) ;Mit diesen Werten könnte man rechnen. (Man müsste Sie nur ermittelt bekommen.)
    BaumAst()\x = 0       ;GetItemPosX(i)?
    BaumAst()\y = 0       ;GetItemPosY(i)?
    BaumAst()\w = 0       ;GetItemWidth(i)?
    BaumAst()\h = 0       ;GetItemHeight(i)?
  Next i 
  
  If CreatePopupMenu(PopMenu)
    MenuItem(1, "Menü-Eintrag 1")
    MenuItem(2, "Menü-Eintrag 2")
    MenuItem(3, "Menü-Eintrag 3")
  EndIf
  
  
  Repeat
    event = WindowEvent()
    Select event
      Case #PB_Event_CloseWindow
        Quit = #True
        
      Case #PB_Event_Menu
        Select EventMenu()
        EndSelect
        
      Case #PB_Event_Gadget
        Select EventGadget()
          Case BaumElement
            If EventType() = #PB_EventType_Change
              KlickElement = GetGadgetState(BaumElement)
            EndIf
            If EventType() = #PB_EventType_LeftClick
              Debug "Linksklick auf: "+Str(KlickElement)
            ElseIf EventType() = #PB_EventType_RightClick
              DisplayPopupMenu(PopMenu, WindowID(TestFenster))
              Debug "Rechtsklick auf: "+Str(KlickElement)
            EndIf
        EndSelect
    EndSelect
  Until Quit = #True
EndIf
End
Zuletzt geändert von ccode_new am 24.11.2018 20:14, insgesamt 1-mal geändert.
Betriebssysteme: div. Windows, Linux, Unix - Systeme

no Keyboard, press any key
no mouse, you need a cat
Onetime
Beiträge: 20
Registriert: 15.05.2018 20:02

Re: Treegadget: Wie das Element bei Rechtsclick feststellen

Beitrag von Onetime »

Vielen Dank schon mal für die Mühe.

Josh + ccode_new,

genau das Problem. Wenn ich in dem Beispiel von ccode_new einen RechtsClick in den leeren Bereich unter Eintrag 5 mache kommt dort das Popupmenü (und es wird behauptet das ich einen Eintrag in der Liste geClickt habe ;-) was ja nicht passiert ist .

Sollte ja nur auf dem Element selber Sinn machen .
ccode_new
Beiträge: 1214
Registriert: 27.11.2016 18:13
Wohnort: Erzgebirge

Re: Treegadget: Wie das Element bei Rechtsclick feststellen

Beitrag von ccode_new »

Hallo!

Kann das jemand für Windows anpassen ?

GTK3-Linux-Version:

Code: Alles auswählen

ImportC ""
  gtk_widget_style_get(*Widget.GtkWidget, PropertyName.P-UTF8, *Value, Null)
EndImport

Procedure.i GetRowHeight(GadgetID.i)
  Protected *Column.GtkTreeViewColumn
  Protected RowHeight.I
  Protected VerticalSeparator.I

  *Column = gtk_tree_view_get_column_(GadgetID(GadgetID), 0)
  gtk_tree_view_column_cell_get_size_(*Column, 0, 0, 0, 0, @RowHeight)
  gtk_widget_style_get(GadgetID(GadgetID), "vertical-separator", @VerticalSeparator, 0)

  ProcedureReturn RowHeight + VerticalSeparator
EndProcedure

Procedure.i GetRowWidth(GadgetID.i)
  Protected *Column.GtkTreeViewColumn
  Protected RowWidth.I
  Protected HorizontalSeparator.I

  *Column = gtk_tree_view_get_column_(GadgetID(GadgetID), 0)
  gtk_tree_view_column_cell_get_size_(*Column, 0, 0, 0, @RowWidth, 0)
  gtk_widget_style_get(GadgetID(GadgetID), "horizontal-separator", @HorizontalSeparator, 0)

  ProcedureReturn RowHeight + HorizontalSeparator
EndProcedure


Structure Ast
  x.i
  y.i
  w.i
  h.i
EndStructure

Structure MPos
  x.d
  y.d
EndStructure

Global WinMaus.MPos

Global NewList BaumAst.Ast()

Global TestFenster, BaumElement, PopMenu
Global Quit.b = #False, start.b = #True
Global KlickElement = -1, ypos = 0

Procedure.b OverGadget(*MausPos.MPos, Element)
  If ((*MausPos\x >= GadgetX(Element)) And (*MausPos\x <= (GadgetX(Element) + GadgetWidth(Element))) And (*MausPos\y >= GadgetY(Element)) And (*MausPos\y <= GadgetY(Element) + GadgetHeight(Element)))
    ProcedureReturn #True
  EndIf
  ProcedureReturn #False
EndProcedure

Procedure.b OverItem(*MausPos.MPos, Element, Eintrag)
  SelectElement(BaumAst(), Eintrag)
  If (*MausPos\y - GadgetY(Element)) < (BaumAst()\y + BaumAst()\h)
    ProcedureReturn #True
  EndIf
  ProcedureReturn #False
EndProcedure

TestFenster = OpenWindow(#PB_Any, 0, 0, 800, 600, "TestFenster", #PB_Window_SystemMenu)
If IsWindow(TestFenster)
  BaumElement = TreeGadget(#PB_Any, 10, 10, 780, 580)
  For i = 0 To 5
    AddGadgetItem(BaumElement, i, "Eintrag: "+Str(i))
  Next i 
  
  If CreatePopupMenu(PopMenu)
    MenuItem(1, "Menü-Eintrag 1")
    MenuItem(2, "Menü-Eintrag 2")
    MenuItem(3, "Menü-Eintrag 3")
  EndIf
  
  Repeat
    event = WindowEvent()
    
    WinMaus\x = WindowMouseX(TestFenster)
    WinMaus\y = WindowMouseY(TestFenster)
    
    Select event
      Case #PB_Event_CloseWindow
        Quit = #True
        
      Case #PB_Event_Menu
        Select EventMenu()
        EndSelect
        
      Case #PB_Event_Gadget
        Select EventGadget()
          Case BaumElement
            KlickElement = GetGadgetState(BaumElement)
            If OverGadget(WinMaus, BaumElement) = #True And OverItem(WinMaus, BaumElement, KlickElement) = #True
              If EventType() = #PB_EventType_LeftClick
                Debug "Linksklick auf: "+Str(KlickElement)
              ElseIf EventType() = #PB_EventType_RightClick
                DisplayPopupMenu(PopMenu, WindowID(TestFenster))
                Debug "Rechtsklick auf: "+Str(KlickElement)
              EndIf
            EndIf
        EndSelect
    EndSelect
    
    If start = #True
      While WindowEvent() : Wend
      For i = 1 To CountGadgetItems(BaumElement)
        AddElement(BaumAst())
        BaumAst()\x = 0
        BaumAst()\y = ypos
        BaumAst()\w = GetRowWidth(BaumElement)
        BaumAst()\h = GetRowHeight(BaumElement)
        ypos = (GetRowHeight(BaumElement) * i)
      Next i
      
;       ForEach BaumAst()
;         Debug BaumAst()\y + BaumAst()\h
;       Next
      
      start = #False
    EndIf
    
  Until Quit = #True
EndIf
End
Betriebssysteme: div. Windows, Linux, Unix - Systeme

no Keyboard, press any key
no mouse, you need a cat
Benutzeravatar
RSBasic
Admin
Beiträge: 8022
Registriert: 05.10.2006 18:55
Wohnort: Gernsbach
Kontaktdaten:

Re: Treegadget: Wie das Element bei Rechtsclick feststellen

Beitrag von RSBasic »

Onetime hat geschrieben:Wenn ich in dem Beispiel von ccode_new einen RechtsClick in den leeren Bereich unter Eintrag 5 mache kommt dort das Popupmenü (und es wird behauptet das ich einen Eintrag in der Liste geClickt habe ;-)
Der Grund ist, dass beim TreeGadget immer ein Element ausgewählt ist. Du kannst die Markierung nicht aufheben, indem du auf eine freie Stelle klickst. Ist genauso wie beim ComboBoxGadget. Sobald ein Eintrag aus der Liste ausgewählt wurde, ist immer ein Eintrag ausgewählt und du kannst nicht per Klick die Auswahl aufheben.
Deshalb funktioniert die Klick-Auswertung auch korrekt.
Was man aber alternativ machen könnte, wäre eine Mauspositionsabfrage, ob der Cursor sich beim Klick innerhalb eines Eintrages befindet. Das kannst du mit GetCursorPos_() und MapWindowPoints_() erreichen. Im Forum gibt es genug Beispiele dafür.
Aus privaten Gründen habe ich leider nicht mehr so viel Zeit wie früher. Bitte habt Verständnis dafür.
Bild
Bild
Onetime
Beiträge: 20
Registriert: 15.05.2018 20:02

Re: Treegadget: Wie das Element bei Rechtsclick feststellen

Beitrag von Onetime »

Danke für die Antworten.

- der Code von ccode_new sieht stark nach Windows API aus wenn's denn übersetzt werden kann. Wollte ich aber vermeiden. Trotzdem Danke!

- RSBasic: Ja im Treeview scheint das blöd gelöst zu sein. Ich hab einzelne Einträge kann aber nicht feststellen ob 'drauf geklickt worden ist. Das mit GetCursorPos_() und MapWindowPoints_() schau ich mir mal an. Evtl ist das ja eine Richtung....

Beste Grüsse
Onetime
ccode_new
Beiträge: 1214
Registriert: 27.11.2016 18:13
Wohnort: Erzgebirge

Re: Treegadget: Wie das Element bei Rechtsclick feststellen

Beitrag von ccode_new »

Windows + Linux (Gtk3)

Code: Alles auswählen

CompilerIf #PB_Compiler_OS = #PB_OS_Linux
  ImportC ""
    gtk_widget_style_get(*Widget.GtkWidget, PropertyName.P-UTF8, *Value, Null)
  EndImport
  
  Procedure.i GetRowHeight(GadgetID.i)
    Protected *Column.GtkTreeViewColumn
    Protected RowHeight.I
    Protected VerticalSeparator.I
    
    *Column = gtk_tree_view_get_column_(GadgetID(GadgetID), 0)
    gtk_tree_view_column_cell_get_size_(*Column, 0, 0, 0, 0, @RowHeight)
    gtk_widget_style_get(GadgetID(GadgetID), "vertical-separator", @VerticalSeparator, 0)
    
    ProcedureReturn RowHeight + VerticalSeparator
  EndProcedure
  
CompilerElseIf #PB_Compiler_OS = #PB_OS_Windows
  #TVM_GETITEMHEIGHT  = $111C
  
  Procedure.i GetRowHeight(GadgetID.i)
    ProcedureReturn SendMessage_(GadgetID(GadgetID),#TVM_GETITEMHEIGHT,0,0)
  EndProcedure

CompilerEndIf


Structure Ast
  y.i
  h.i
EndStructure

Structure MPos
  x.i
  y.i
EndStructure

Global WinMaus.MPos

Global NewList BaumAst.Ast()

Global TestFenster, BaumElement, PopMenu
Global Quit.b = #False, start.b = #True
Global KlickElement = -1, ypos = 0

Procedure.b OverGadget(*MausPos.MPos, Element)
  If ((*MausPos\x >= GadgetX(Element)) And (*MausPos\x <= (GadgetX(Element) + GadgetWidth(Element))) And (*MausPos\y >= GadgetY(Element)) And (*MausPos\y <= GadgetY(Element) + GadgetHeight(Element)))
    ProcedureReturn #True
  EndIf
  ProcedureReturn #False
EndProcedure

Procedure.b OverItem(*MausPos.MPos, Element, Eintrag)
  SelectElement(BaumAst(), Eintrag) ;kleines Abfrage-Problem!
  If (*MausPos\y - GadgetY(Element)) < (BaumAst()\y + BaumAst()\h) ;And (*MausPos\y - GadgetY(Element)) >= BaumAst()\y
    ProcedureReturn #True
  EndIf
  ProcedureReturn #False
EndProcedure

TestFenster = OpenWindow(#PB_Any, 0, 0, 800, 600, "TestFenster", #PB_Window_SystemMenu)
If IsWindow(TestFenster)
  BaumElement = TreeGadget(#PB_Any, 10, 10, 780, 580)
;   For i = 0 To 5
;     AddGadgetItem(BaumElement, i, "Eintrag: "+Str(i))
;   Next i
  
  For i = 1 To 2
    AddGadgetItem (BaumElement, -1, "Item "+ Str(i), 0, 0)
    AddGadgetItem(BaumElement, -1, "Item " + Str(i) + ".1", 0, 1)
    AddGadgetItem(BaumElement, -1, "Item " + Str(i) + ".2", 0, 1)
    AddGadgetItem(BaumElement, -1, "Item " + Str(i) + ".2.1", 0, 2)
    AddGadgetItem(BaumElement, -1, "Item " + Str(i) + ".2.2", 0, 2)
    AddGadgetItem(BaumElement, -1, "Item " + Str(i) + ".3", 0, 1)
  Next i
  
  If CreatePopupMenu(PopMenu)
    MenuItem(1, "Menü-Eintrag 1")
    MenuItem(2, "Menü-Eintrag 2")
    MenuItem(3, "Menü-Eintrag 3")
  EndIf
  
  Repeat
    event = WindowEvent()
    
    WinMaus\x = WindowMouseX(TestFenster)
    WinMaus\y = WindowMouseY(TestFenster)
    
    Select event
      Case #PB_Event_CloseWindow
        Quit = #True
        
      Case #PB_Event_Menu
        Select EventMenu()
        EndSelect
        
      Case #PB_Event_Gadget
        Select EventGadget()
          Case BaumElement
            KlickElement = GetGadgetState(BaumElement)
            If OverGadget(WinMaus, BaumElement) = #True And OverItem(WinMaus, BaumElement, KlickElement) = #True
              If EventType() = #PB_EventType_LeftClick
                Debug "Linksklick auf: "+Str(KlickElement)
              ElseIf EventType() = #PB_EventType_RightClick
                DisplayPopupMenu(PopMenu, WindowID(TestFenster))
                Debug "Rechtsklick auf: "+Str(KlickElement)
              EndIf
            EndIf
        EndSelect
    EndSelect
    
    If start = #True
      While WindowEvent() : Wend
      For i = 1 To CountGadgetItems(BaumElement)
        AddElement(BaumAst())
        BaumAst()\y = ypos
        BaumAst()\h = GetRowHeight(BaumElement) 
        ypos = (GetRowHeight(BaumElement) * i)
      Next i
      
;       ForEach BaumAst()
;         Debug BaumAst()\y + BaumAst()\h
;       Next
      
      start = #False
    EndIf
    
  Until Quit = #True
EndIf
End
Zuletzt geändert von ccode_new am 25.11.2018 14:27, insgesamt 1-mal geändert.
Betriebssysteme: div. Windows, Linux, Unix - Systeme

no Keyboard, press any key
no mouse, you need a cat
Benutzeravatar
RSBasic
Admin
Beiträge: 8022
Registriert: 05.10.2006 18:55
Wohnort: Gernsbach
Kontaktdaten:

Re: Treegadget: Wie das Element bei Rechtsclick feststellen

Beitrag von RSBasic »

Onetime hat geschrieben:- der Code von ccode_new sieht stark nach Windows API aus wenn's denn übersetzt werden kann. Wollte ich aber vermeiden. Trotzdem Danke!
Grundsätzlich ist das kein Problem, wenn man API-Codes verwendet. Es kommt nur darauf an, welche Betriebssysteme du gerne unterstützen möchtest. Wenn du eine Windows- und Linux-Version deiner Anwendung anbieten möchtest, dann kannst du die API-Codes auch verwenden. Vorausgesetzt du hast sowohl den Linux API- als auch Windows API-Code, dann hast du quasi auch eine plattformunabhängige Lösung. Wenn für dich MacOS auch wichtig ist, dann musst du noch warten, bis ein Mac-User für dich den API-Code für MacOS übersetzt.

Dank ccode_new hast du jetzt schon einen Code, der sowohl unter Windows als auch unter Linux funktioniert. Das wäre genauso wie, wenn du eine native PB-Funktion verwendest.
Aus privaten Gründen habe ich leider nicht mehr so viel Zeit wie früher. Bitte habt Verständnis dafür.
Bild
Bild
ccode_new
Beiträge: 1214
Registriert: 27.11.2016 18:13
Wohnort: Erzgebirge

Re: Treegadget: Wie das Element bei Rechtsclick feststellen

Beitrag von ccode_new »

Das ganze verhält sich unter Windows sehr mysteriös.

Manchmal funktioniert es einwandfrei (am Anfang), aber nach kurzer Laufzeit des Programms funktioniert die Eventabfrage nicht mehr korrekt. (Nur bei Windows und beim Rechtsklick!) Sehr seltsames Verhalten.
Betriebssysteme: div. Windows, Linux, Unix - Systeme

no Keyboard, press any key
no mouse, you need a cat
Antworten