API-Gegenstück zu SetGadgetItemColor bei TreeView

Windowsspezifisches Forum , API ,..
Beiträge, die plattformübergreifend sind, gehören ins 'Allgemein'-Forum.
Benutzeravatar
uweb
Beiträge: 461
Registriert: 13.07.2005 08:39

API-Gegenstück zu SetGadgetItemColor bei TreeView

Beitrag von uweb »

Hallo,

bei API-Geschichten habe ich dank google oft nach ein paar Minuten schon die Lösung.
Manchmal suche ich mir aber einen Wolf. So einen Fall habe ich nun.

>> Ich möchte in dem TreeGadget die Zeilen abwechselnd hell/dunkel einfärben.

Mit SetGadgetItemColor geht das ja auch prima.
Wenn ein Knoten mit ungerader Anzahl an Subitems geöffnet oder geschlossen wird stimmt der Farbwechsel aber nicht mehr.
Außerdem ist es nicht notwendig die nicht sichtbaren Subitems einzufärben.
Auch die Items oberhalb des öffnenden oder schließenden Knoten brauchen nicht geändert werden.
Ich denke mit #TVM_GETNEXTITEM in der While-Schleife bin ich da auf einem guten Weg.

>> Nun brauche ich aber ein API-Gegenstück zu SetGadgetItemColor, weil ich mit dem OS-Handel arbeiten muß.

Auch wenn ich glaube, dass dazu kein Code notwendig wäre, habe ich, um auch alle glücklich zu machen, ein Dummy (sogar mit EnableExplicit) vorbereitet.
:)

Code: Alles auswählen

EnableExplicit

#TVM_SETBKCOLOR = 4381


Enumeration ; Gadgets
  #TV01
EndEnumeration


Global TreeGadget_brightBackColor.i = $FFFFEE
Global TreeGadget_darkBackColor.i = $EEEECC

Define hwndTV, dwStyle 
Define DefaultTreeCallback.I


Procedure TreeGadget_BackColor( Gadget, Item )
  Protected hItem.l, hwndTV.i
  hwndTV = GadgetID(Gadget)
  
  Debug Item
  hItem.l = GadgetItemID(Gadget, Item)
  Debug hItem 
  hItem = SendMessage_(hwndTV, #TVM_GETNEXTITEM, #TVGN_NEXTVISIBLE , hItem)
  
  While hItem ; der Farbwechsel kommt später - sobald es überhaupt läuft
    Debug hItem      
    ;SetGadgetItemColor(Gadget,  Item+1, #PB_Gadget_BackColor,  TreeGadget_darkBackColor)
    hItem = SendMessage_(hwndTV, #TVM_GETNEXTITEM, #TVGN_NEXTVISIBLE , hItem)
  Wend
EndProcedure

Procedure CustomTreeGadgetCallback(WindowHandle.I, Msg.I, WParam.L, LParam.L) ; eine Proc für alle TreeGadgets - individuelles an anderer Stelle
  Shared DefaultTreeCallback.I
  Protected HitTest.TV_HITTESTINFO
  Protected TVItem.TV_ITEM
 
  If Msg = #WM_LBUTTONDOWN ; Markierung auf geklicktes Item setzen
    HitTest\pt\x = LParam & $FFFF
    HitTest\pt\y = (LParam >> 16) & $FFFF
   
    If SendMessage_(WindowHandle, #TVM_HITTEST, 0, HitTest)
      If HitTest\flags = #TVHT_ONITEMSTATEICON
        TVItem\mask = #TVIF_PARAM   
        TVItem\hItem = HitTest\hItem
        SendMessage_(WindowHandle, #TVM_GETITEM, 0, TVItem)
        SetGadgetState(0, TVItem\lParam)
      EndIf
    EndIf
  EndIf
 
  ProcedureReturn CallWindowProc_(DefaultTreeCallback, WindowHandle, Msg, WParam, LParam)
EndProcedure

Procedure PrepareTreeGadget(Gadget)
  AddGadgetItem(Gadget,-1,"Testitem 0",0,0)
  AddGadgetItem(Gadget,-1,"Subitem",0,1)
  AddGadgetItem(Gadget,-1,"Testitem 1",0,0)
  AddGadgetItem(Gadget,-1,"Subitem",0,1)
  AddGadgetItem(Gadget,-1,"Subitem",0,1)
  AddGadgetItem(Gadget,-1,"Subitem",0,1)
  AddGadgetItem(Gadget,-1,"Testitem 2",0,0)
EndProcedure

If OpenWindow(0,0,0,500,250,"Window",#PB_Window_SystemMenu|#PB_Window_ScreenCentered)
  TreeGadget(#TV01,10,10,480,230,#PB_Tree_NoLines)
  DefaultTreeCallback = SetWindowLongPtr_(GadgetID(#TV01), #GWL_WNDPROC, @CustomTreeGadgetCallback())
  PrepareTreeGadget(#TV01)
  
  hwndTV = GadgetID(#TV01)
  
  SendMessage_(hwndTV,#TVM_SETBKCOLOR,0,RGB(255,255,192))
  
  SetGadgetItemColor(#TV01,  1, #PB_Gadget_FrontColor, $FF0000,  1) ; sinnlos - nur zum Test
  SetGadgetItemColor(#TV01,  2, #PB_Gadget_BackColor,  $00FF00, -1)
  SetGadgetItemColor(#TV01,  3, #PB_Gadget_BackColor,  $0000FF,  1)
  
  
  SetGadgetItemColor(#TV01,  0, #PB_Gadget_BackColor,  TreeGadget_darkBackColor)
  TreeGadget_BackColor( #TV01, 0 ) ; soll alle nachfolgenden Items abwechseld hell/dunkel färben
  
  
  dwStyle = GetWindowLongPtr_(hwndTV,#GWL_STYLE);
  dwStyle = dwStyle|#TVS_FULLROWSELECT
  SetWindowLongPtr_(hwndTV,#GWL_STYLE, dwStyle)
  
  
  Repeat : Until WaitWindowEvent() = #PB_Event_CloseWindow
EndIf  
Benutzeravatar
uweb
Beiträge: 461
Registriert: 13.07.2005 08:39

Re: API-Gegenstück zu SetGadgetItemColor bei TreeView

Beitrag von uweb »

Ein kleinse Stück bin ich schon voran gekommen.
Die Lösung mit der Repeat-Until-Schleife ist zwar weder elegant noch schnell aber sie funktioniert.
Noch langsamer wird das ganze dadurch, dass ich es bis jetzt nicht geschafft habe im Callback das entsprechende Item zu ermitteln und an TreeGadget_BackColor zu übergeben.
Statt dessen beginne ich immer bei 0.

>> Vielleicht hat ja noch jemand eine elegantere Lösung oder kann mir beim ermitteln des entsprechenden Items helfen.

Zur Not könnte ich im Callback einfach nur eine globale Variable setzen und TreeGadget_BackColor abhängig davon bei der normalen Eventverarbeitung aufrufen.
Zumindest sieht man nun worum es geht.

Code: Alles auswählen

EnableExplicit

#TVM_SETBKCOLOR = 4381

Enumeration ; Gadgets
  #TV01
EndEnumeration

Global TreeGadget_brightBackColor.i = $FFFFEE
Global TreeGadget_darkBackColor.i = $EEEECC

Define hwndTV, dwStyle, Event


Procedure TreeGadget_BackColor( Gadget, Item )
  Protected hItem.l, hwndTV.i, ItemColor
  hwndTV = GadgetID(Gadget)
  
  If GetGadgetItemColor(Gadget, Item, #PB_Gadget_BackColor) = TreeGadget_brightBackColor
    ItemColor = TreeGadget_darkBackColor
  Else
    ItemColor = TreeGadget_brightBackColor
  EndIf  
  
  hItem.l = GadgetItemID(Gadget, Item)
  hItem = SendMessage_(hwndTV, #TVM_GETNEXTITEM, #TVGN_NEXTVISIBLE , hItem)
  
  While hItem 
    Debug hItem      
    Repeat : Item = Item + 1 : Until GadgetItemID(Gadget, Item) = hItem
    SetGadgetItemColor(Gadget,  Item, #PB_Gadget_BackColor,  ItemColor)
    If ItemColor = TreeGadget_brightBackColor
      ItemColor = TreeGadget_darkBackColor
    Else
      ItemColor = TreeGadget_brightBackColor
    EndIf  
    hItem = SendMessage_(hwndTV, #TVM_GETNEXTITEM, #TVGN_NEXTVISIBLE , hItem)
  Wend
  SendMessage_(hwndTV,#TVM_SETBKCOLOR,0,ItemColor)
EndProcedure


Procedure.l Callback(hWnd, Msg, wParam, lParam)
  Protected *pnmtv.NM_TREEVIEW
  
  Select Msg
    Case #WM_LBUTTONDOWN
      Debug "#WM_LBUTTONDOWN"
    Case #WM_NOTIFY
      *pnmtv = lParam
      Select *pnmtv\hdr\code
        Case #TVN_ITEMEXPANDED
          Debug "#TVN_ITEMEXPANDED"
          TreeGadget_BackColor( #TV01, 0 )
      EndSelect
  EndSelect
  ProcedureReturn #PB_ProcessPureBasicEvents
EndProcedure


Procedure PrepareTreeGadget(Gadget)
  AddGadgetItem(Gadget,-1,"Testitem 0",0,0)
  AddGadgetItem(Gadget,-1,"Subitem",0,1)
  AddGadgetItem(Gadget,-1,"Testitem 1",0,0)
  AddGadgetItem(Gadget,-1,"Subitem",0,1)
  AddGadgetItem(Gadget,-1,"Subitem",0,1)
  AddGadgetItem(Gadget,-1,"Subitem",0,1)
  AddGadgetItem(Gadget,-1,"Testitem 2",0,0)
EndProcedure


If OpenWindow(0,0,0,500,250,"Window",#PB_Window_SystemMenu|#PB_Window_ScreenCentered)
  TreeGadget(#TV01,10,10,480,230,#PB_Tree_NoLines)
  SetWindowCallback(@Callback())
  PrepareTreeGadget(#TV01)
  
  SetGadgetItemColor(#TV01,  0, #PB_Gadget_BackColor,  TreeGadget_darkBackColor)
  TreeGadget_BackColor( #TV01, 0 ) ; soll alle NACHFOLGENDEN Items abwechseld hell/dunkel färben
  
  hwndTV = GadgetID(#TV01)
  dwStyle = GetWindowLongPtr_(hwndTV,#GWL_STYLE);
  dwStyle = dwStyle|#TVS_FULLROWSELECT
  SetWindowLongPtr_(hwndTV,#GWL_STYLE, dwStyle)
  
  Repeat
    Event = WaitWindowEvent()
    Select Event
      Case #PB_Event_Gadget
        Select EventGadget()
          Case #TV01
            Select EventType() 
              Case #PB_EventType_LeftClick
                Debug "Item Nr." + GetGadgetState(#TV01) + " hat LeftClick"
              Case #PB_EventType_RightClick  
                Debug "Item Nr." + GetGadgetState(#TV01) + " hat RightClick"
            EndSelect
        EndSelect
        
      Case #PB_Event_Menu
        Select EventMenu()
        EndSelect
    EndSelect
  Until Event = #PB_Event_CloseWindow
EndIf  
Benutzeravatar
Deluxe0321
Beiträge: 336
Registriert: 19.05.2006 00:31
Kontaktdaten:

Re: API-Gegenstück zu SetGadgetItemColor bei TreeView

Beitrag von Deluxe0321 »

Damit ermittelst du das entsprechende Item und das Parent Item.

Code: Alles auswählen

Procedure Tree_GadgetItemNumber(Gadget, ItemID)
  Count = CountGadgetItems(Gadget)
  For i = 0 To Count
    If GadgetItemID(Gadget, i) = ItemID
      ProcedureReturn i
    EndIf
  Next i
  ProcedureReturn -1
EndProcedure

Procedure Tree_GetParentItemID(Gadget.i,Item.i)
  Protected hWnd.i, hItem.i
 
  hWnd.i  = GadgetID(Gadget)
  hItem.i = GadgetItemID(Gadget, Item.i)
  
  ProcedureReturn SendMessage_(hWnd, #TVM_GETNEXTITEM, #TVGN_PARENT, hItem)
EndProcedure

Procedure Tree_GetCurrentItemID(Gadget.i)
  Protected hWnd.i
  hWnd.i = GadgetID(Gadget.i)
  ProcedureReturn SendMessage_(hWnd.i,#TVM_GETNEXTITEM,#TVGN_CARET,#Null)  
EndProcedure


Procedure.l Callback(hWnd, Msg, wParam, lParam)
  Protected *pnmtv.NM_TREEVIEW
  Protected *lp.NMHDR = lParam
  
  Select Msg
    Case #WM_LBUTTONDOWN
      Debug "#WM_LBUTTONDOWN"
    Case #WM_NOTIFY
      *pnmtv = lParam
      *lp = lparam
      
      ;more info: http://msdn.microsoft.com/en-us/library/windows/desktop/ff486107%28v=vs.85%29.aspx
      If *pnmtv\hdr\code = #TVN_ITEMEXPANDED Or *lp\code = #NM_CLICK
        ;item was expanded or clicked...
        Debug "expand/click!"
        
        CurrentItem.i= GetGadgetState(#TV01)
        If CurrentItem.i > -1
          
          ;determite all needed information
          CurrentItemID.i = Tree_GetCurrentItemID(#TV01)
          ParentItemID.i  = Tree_GetParentItemID(#TV01,CurrentItem.i)
          
          ;check if this item have a parent item
          If ParentItemID.i
            ParentItem.i = Tree_GadgetItemNumber(#TV01, ItemID) 
          EndIf
          
          Debug "CurrentID: "+ CurrentItemID.i
          Debug Space(4)     + "CurrentItem: "+ CurrentItem.i
          Debug "ParentID:  "+ ParentItemID.i
          Debug Space(4)     + "ParentItem: " + ParentItem.i
          
        EndIf
        
      EndIf
  EndSelect
  ProcedureReturn #PB_ProcessPureBasicEvents
EndProcedure
Grüße,
Deluxe0321
Ich habe keine Lösung, aber ich bewundere das Problem.
Benutzeravatar
uweb
Beiträge: 461
Registriert: 13.07.2005 08:39

Re: API-Gegenstück zu SetGadgetItemColor bei TreeView

Beitrag von uweb »

Hallo Deluxe0321,
vielen Dank für die Mühe die du dir gemacht hast!
Da hätte ich auch selbst drauf kommen könnnen.
Manchmal sieht man den Wald vor lauter Bäumen nicht.
Schließlich hatte ich die TVGN's für TVM_GETNEXTITEM und meine Repeat-Schleife ja schon.
Wahrscheinlich habe ich einfach zu sehr nach einer direkteren (Ein-Befehl-)Lösung gesucht.
LG
Uwe
Antworten