GetParent() - (Windows Only)
Posted: Sun Apr 17, 2022 4:57 pm
GetParent() to Retrieves the PB Parent Gadget or PB Parent Window number.
It is the equivalent of the GetParent and GetAncestor windows API functions but for PB Gadget and PB Window number.
And also, Count the number of Children's Gadgets or GrandChildren.
But the main reason of this code for me, is the possibility to read Hierarchically the Children And GrandChildren of a Window or a Container Gadget.
Available functions:
It is the equivalent of the GetParent and GetAncestor windows API functions but for PB Gadget and PB Window number.
And also, Count the number of Children's Gadgets or GrandChildren.
But the main reason of this code for me, is the possibility to read Hierarchically the Children And GrandChildren of a Window or a Container Gadget.
Available functions:
- GetParent(#Gadget) : Retrieves the Parent Window Number or the Parent Gadget Number
- GetWindowRoot(#Gadget) : Retrieves the Root Parent Window Number
- GetParentID(#Gadget) : Retrieves the Parent WindowID or the Parent GadgetID
- ParentIsWindow(#Gadget) : Is the Parent a Window
- ParentIsGadget(#Gadget) : Is the Parent a Gadget
- CountChildGadget(#Parent[, GrandChildren = #False]) : Count Child Gadget. Call with #True as 2nd parameter to also count Grand Children
- EnumChildTemplate(#Gadget) : A template to list hierarchically the child gadgets
Code: Select all
; -------------------------------------------------------------------------------------------------
; Name: GetParent.pbi
; Description: Get the PB Parent Gadget or PB Window Number. Get the specified Window Root for a Gadget. Count the number of Children's Gadgets or GrandChildren.
; And also, the main reason for this code, is the possibility to read Hierarchically the Children And GrandChildren of a Window or a Container Gadget.
; Author: ChrisR
; Date: 2022-04-16
; PB-Version: 5.73 x64/x86
; OS: Windows Only.
; Forum: https://www.purebasic.fr/english/viewtopic.php?t=79004
; -------------------------------------------------------------------------------------------------
;- Usage:
;-
; GetParent(#Gadget) : Get the Parent Window Number or the Parent Gadget Number
;
; GetWindowRoot(#Gadget) : Get the Root Parent Window Number
;
; GetParentID(#Gadget) : Get the Parent WindowID or the Parent GadgetID
;
; ParentIsWindow(#Gadget) : Is the Parent a Window
;
; ParentIsGadget(#Gadget) : Is the Parent a Gadget
;
; CountChildGadget(#Parent[, GrandChildren = #False]) : Count Child Gadget. Call with #True as 2nd parameter to also Count Grand Children
;
; EnumChildTemplate(#Gadget) : A template to list Hierarchically the Child and GrandChildren Gadgets
;
; -------------------------------------------------------------------------------------------------
EnableExplicit
Global Dim Window(1, 0)
Global CountWindow
Structure StObject
Level.i ; If = 1, Parent Is a Window Else a Gadget
ObjectID.i
IsContainer.b
ParentObject.i
ParentObjectID.i
GParentObjectID.i ; Temporary Loaded For Child of ScrollArea and Panel, it is then reset to 0
EndStructure
Global NewMap Object.StObject()
Import ""
PB_Object_EnumerateAll(Object, *Object, ObjectData)
PB_Object_Count(PB_Gadget_Objects)
PB_Gadget_Objects.i
PB_Window_Objects.i
EndImport
;- ----- Private -----
Procedure IsContainer(Gadget)
; Procedure IsContainer(Cross-platform) based on procedure IsCanvasContainer by mk-soft here: https://www.purebasic.fr/english/viewtopic.php?t=79002
Select GadgetType(Gadget)
Case #PB_GadgetType_Container, #PB_GadgetType_Panel, #PB_GadgetType_ScrollArea
ProcedureReturn #True
Case #PB_GadgetType_Canvas
CompilerSelect #PB_Compiler_OS
CompilerCase #PB_OS_Windows
If GetWindowLongPtr_(GadgetID(Gadget), #GWL_STYLE) & #WS_CLIPCHILDREN
ProcedureReturn #True
EndIf
CompilerCase #PB_OS_MacOS
Protected sv, count
sv = CocoaMessage(0, GadgetID(Gadget), "subviews")
count = CocoaMessage(0, sv, "count")
ProcedureReturn count
CompilerCase #PB_OS_Linux
Protected GList, count
GList = gtk_container_get_children_(GadgetID(Gadget))
If GList
count = g_list_length_(GList)
g_list_free_(GList)
ProcedureReturn count
EndIf
CompilerEndSelect
EndSelect
ProcedureReturn #False
EndProcedure
Procedure WindowCB(Window, *Window, WindowData)
Window(0, CountWindow) = Window
Window(1, CountWindow) = WindowID(Window)
CountWindow + 1
ProcedureReturn #True
EndProcedure
Procedure ObjectCB(Object, *Object, ObjectData)
With Object(Str(Object))
\ObjectID = GadgetID(Object)
\IsContainer = IsContainer(Object)
; For
\ParentObjectID = GetParent_(\ObjectID)
\GParentObjectID = GetParent_(\ParentObjectID)
EndWith
ProcedureReturn #True
EndProcedure
Procedure CleanUpGParent(ObjectID, Level)
Protected ParentObjectID
PushMapPosition(Object())
ResetMap(Object())
With Object()
While NextMapElement(Object())
If \Level <> Level + 1 : Continue : EndIf
If \ParentObjectID = ObjectID
\GParentObjectID = 0
ElseIf \GParentObjectID = ObjectID
\ParentObjectID = ObjectID
\GParentObjectID = 0
EndIf
Wend
EndWith
PopMapPosition(Object())
EndProcedure
Procedure WinHierarchy(ParentObjectID, ParentObject, FirstPassDone = #False)
Static Level
Protected ObjectType
If FirstPassDone = #False
Level = 0
FirstPassDone = #True
EndIf
Level + 1
PushMapPosition(Object())
ResetMap(Object())
With Object()
While NextMapElement(Object())
If IsGadget(ParentObject) : ObjectType = GadgetType(ParentObject) : Else : ObjectType = 0 : EndIf
If \ParentObjectID = ParentObjectID Or (\GParentObjectID = ParentObjectID And ObjectType & (#PB_GadgetType_Panel | #PB_GadgetType_ScrollArea))
\Level = Level
\ParentObject = ParentObject
If \IsContainer
WinHierarchy(\ObjectID, Val(MapKey(Object())), FirstPassDone)
Level - 1
EndIf
EndIf
Wend
EndWith
PopMapPosition(Object())
EndProcedure
Procedure LoadObject()
Protected I
CountWindow = PB_Object_Count(PB_Window_Objects)
ReDim Window(1, CountWindow - 1)
CountWindow = 0
PB_Object_EnumerateAll(PB_Window_Objects, @WindowCB(), 0)
PB_Object_EnumerateAll(PB_Gadget_Objects, @ObjectCB(), 0)
If MapSize(Object()) > 0
; Pass through the hierarchy for each window
For I = 0 To ArraySize(Window(), 2)
WinHierarchy(Window(1, I), Window(0, I))
Next
; CleanUp ParentObject vs GParentObject
ResetMap(Object())
With Object()
While NextMapElement(Object())
If Object()\IsContainer
CleanUpGParent(Object()\ObjectID, Object()\Level)
EndIf
Wend
EndWith
Else
ProcedureReturn #False
EndIf
ProcedureReturn #True
EndProcedure
;- ----- Private -----
;-
;- ----- Public -----
Procedure GetParent(Gadget)
If MapSize(Object()) = 0 : LoadObject() : EndIf
If FindMapElement(Object(), Str(Gadget))
ProcedureReturn Object(Str(Gadget))\ParentObject
EndIf
ProcedureReturn #PB_Default
EndProcedure
Procedure GetWindowRoot(Gadget)
If MapSize(Object()) = 0 : LoadObject() : EndIf
If FindMapElement(Object(), Str(Gadget))
If Object(Str(Gadget))\Level = 1
ProcedureReturn Object(Str(Gadget))\ParentObject
Else
Gadget = Object(Str(Gadget))\ParentObject
EndIf
Else
ProcedureReturn #PB_Default
EndIf
Repeat
If FindMapElement(Object(), Str(Gadget))
Gadget = Object(Str(Gadget))\ParentObject
EndIf
Until Object(Str(Gadget))\Level = 1
; Parent of Level 1 is the Window Root
If FindMapElement(Object(), Str(Gadget))
Gadget = Object(Str(Gadget))\ParentObject
EndIf
ProcedureReturn Gadget
EndProcedure
Procedure GetParentID(Gadget)
If MapSize(Object()) = 0 : LoadObject() : EndIf
If FindMapElement(Object(), Str(Gadget))
If Object(Str(Gadget))\Level = 1
ProcedureReturn WindowID(Object(Str(Gadget))\ParentObject)
Else
ProcedureReturn GadgetID(Object(Str(Gadget))\ParentObject)
EndIf
EndIf
ProcedureReturn #PB_Default
EndProcedure
Procedure ParentIsWindow(Gadget)
If MapSize(Object()) = 0 : LoadObject() : EndIf
If FindMapElement(Object(), Str(Gadget))
If Object(Str(Gadget))\Level = 1
ProcedureReturn #True
Else
ProcedureReturn #False
EndIf
EndIf
ProcedureReturn #PB_Default
EndProcedure
Procedure ParentIsGadget(Gadget)
If MapSize(Object()) = 0 : LoadObject() : EndIf
If FindMapElement(Object(), Str(Gadget))
If Object(Str(Gadget))\Level > 1
ProcedureReturn #True
Else
ProcedureReturn #False
EndIf
EndIf
ProcedureReturn #PB_Default
EndProcedure
Procedure CountChildGadget(ParentObject, GrandChildren = #False, FirstPassDone = #False)
Static Level, Count
If FirstPassDone = 0
If MapSize(Object()) = 0 : LoadObject() : EndIf
If IsWindow(ParentObject)
Level = 0
ElseIf IsGadget(ParentObject)
If FindMapElement(Object(), Str(ParentObject))
If Not(Object(Str(ParentObject))\IsContainer) : ProcedureReturn #PB_Default : EndIf
Level = Object(Str(ParentObject))\Level
EndIf
Else
ProcedureReturn #PB_Default
EndIf
Count = 0
FirstPassDone = #True
EndIf
Level + 1
PushMapPosition(Object())
ResetMap(Object())
With Object()
While NextMapElement(Object())
If \Level = Level And \ParentObject = ParentObject
Count + 1
If GrandChildren And \IsContainer
CountChildGadget(Val(MapKey(Object())), GrandChildren, FirstPassDone)
Level - 1
EndIf
EndIf
Wend
EndWith
PopMapPosition(Object())
ProcedureReturn Count
EndProcedure
Procedure EnumChildTemplate(ParentObject, FirstPassDone = #False)
Static Level
If FirstPassDone = 0
If MapSize(Object()) = 0 : LoadObject() : EndIf
If IsWindow(ParentObject)
Level = 0
Debug "Enum Child Gadget of Window " + LSet(Str(ParentObject), 10) + "| WindowID " + LSet(Str(WindowID(ParentObject)), 10) + "(Level = 0)"
ElseIf IsGadget(ParentObject)
If FindMapElement(Object(), Str(ParentObject))
If Not(Object(Str(ParentObject))\IsContainer) : ProcedureReturn #PB_Default : EndIf
Level = Object(Str(ParentObject))\Level
Debug "Enum Child Gadget of Gadget " + LSet(Str(ParentObject), 10) + "| GadgetID " + LSet(Str(GadgetID(ParentObject)), 10) + "(Level = " + Str(Level) + ")"
EndIf
Else
ProcedureReturn #PB_Default
EndIf
FirstPassDone = #True
EndIf
Level + 1
PushMapPosition(Object())
ResetMap(Object())
With Object()
While NextMapElement(Object())
If \Level = Level And \ParentObject = ParentObject
Debug LSet("", \Level*3 , " ") + "Gadget " + LSet(MapKey(Object()), 10) + "ParentGadget " + LSet(Str(\ParentObject), 10) + "| GadgetID " + LSet(Str(\ObjectID), 10) + "ParentGadgetID " + LSet(Str(\ParentObjectID), 10) + "(Level = " + Str(\Level) + ")"
If \IsContainer
EnumChildTemplate(Val(MapKey(Object())), FirstPassDone)
Level - 1
EndIf
EndIf
Wend
EndWith
PopMapPosition(Object())
EndProcedure
;- ----- Public -----
;-
;- ----- Demo -----
CompilerIf (#PB_Compiler_IsMainFile)
Enumeration Window
#Window_1
EndEnumeration
Enumeration Gadgets
#ScrollArea_1
#CanvasContainer_1
#Panel_1
#Button_1
#Button_3
#Button_4
#Button_5
EndEnumeration
Global Container_1, Button_2
Global Window_2, SubPanel_2, Button_6
Procedure Open_Window_2(X = 480, Y = 20, Width = 440, Height = 380)
Window_2 = OpenWindow(#PB_Any, X, Y, Width, Height, "Window_2 (#PB_Any)", #PB_Window_SystemMenu)
If Window_2
PanelGadget(#Panel_1, 20, 20, 400, 270)
AddGadgetItem(#Panel_1, -1, "Tab_1 (2)")
SubPanel_2 = PanelGadget(#PB_Any, 20, 20, 350, 190)
AddGadgetItem(SubPanel_2, -1, "SubTab_1 (#PB_Any)")
ButtonGadget(#Button_5, 20, 20, 200, 50, "Button_5 (6)")
AddGadgetItem(SubPanel_2, -1, "SubTab_2 (#PB_Any)")
CloseGadgetList() ; SubPanel_2
AddGadgetItem(#Panel_1, -1, "Tab_2 (2)")
ButtonGadget(#Button_4, 30, 30, 200, 50, "Button_4 (5)")
CloseGadgetList() ; #Panel_1
Button_6 = ButtonGadget(#PB_Any, 20, 310, 200, 50, "Button_6 (#PB_Any)")
EndIf
EndProcedure
Procedure Open_Window_1(X = 20, Y = 20, Width = 440, Height = 380)
If OpenWindow(#Window_1, X, Y, Width, Height, "Window_1 (0)", #PB_Window_SystemMenu)
ScrollAreaGadget(#ScrollArea_1, 20, 20, 400, 270, 1200, 800, 10, #PB_ScrollArea_Raised)
CanvasGadget(#CanvasContainer_1, 20, 20, 330, 160, #PB_Canvas_Border | #PB_Canvas_Container)
Container_1 = ContainerGadget(#PB_Any, 20, 20, 290, 110, #PB_Container_Raised)
ButtonGadget(#Button_1, 20, 20, 200, 50, "Button_1 (3)")
CloseGadgetList() ; Container_1
CloseGadgetList() ; #CanvasContainer_1
Button_2 = ButtonGadget(#PB_Any, 20, 200, 200, 50, "Button_2 (#PB_Any)")
CloseGadgetList() ; #ScrollArea_1
ButtonGadget(#Button_3, 20, 310, 200, 50, "Button_3 (4)")
EndIf
EndProcedure
Open_Window_1()
Open_Window_2()
;- ----- Debug -----
EnumChildTemplate(#Window_1)
Debug "" : Debug "--------------------------------------------------------------------------------" : Debug ""
Debug "#Window_1 : " + Str(#Window_1)
Debug "Count Child Gadget of #Window_1 : " + Str(CountChildGadget(#Window_1))
Debug "Count Child + GrandChildren Gadget of #Window_1 : " + Str(CountChildGadget(#Window_1, #True))
Debug ""
Debug "Parent of #ScrollArea_1 : " + LSet(Str(GetParent(#ScrollArea_1)), 10) + "(Parent: IsWindow=" + Str(ParentIsWindow(#ScrollArea_1)) + ", IsGadget=" + Str(ParentIsGadget(#ScrollArea_1)) + ")"
Debug "Parent of #CanvasContainer_1 : " + LSet(Str(GetParent(#CanvasContainer_1)), 10) + "(Parent: IsWindow=" + Str(ParentIsWindow(#CanvasContainer_1)) + ", IsGadget=" + Str(ParentIsGadget(#CanvasContainer_1)) + ")"
Debug "Parent of Container_1 : " + LSet(Str(GetParent(Container_1)), 10) + "(Parent: IsWindow=" + Str(ParentIsWindow(Container_1)) + ", IsGadget=" + Str(ParentIsGadget(Container_1)) + ")"
Debug "Parent of #Button_1 : " + LSet(Str(GetParent(#Button_1)), 10) + "(Parent: IsWindow=" + Str(ParentIsWindow(#Button_1)) + ", IsGadget=" + Str(ParentIsGadget(#Button_1)) + ")"
Debug "Parent of Button_2 : " + LSet(Str(GetParent(Button_2)), 10) + "(Parent: IsWindow=" + Str(ParentIsWindow(Button_2)) + ", IsGadget=" + Str(ParentIsGadget(Button_2)) + ")"
Debug "Parent of #Button_3 : " + LSet(Str(GetParent(#Button_3)), 10) + "(Parent: IsWindow=" + Str(ParentIsWindow(#Button_3)) + ", IsGadget=" + Str(ParentIsGadget(#Button_3)) + ")"
Debug ""
Debug "Window Root of #Button_1 : " + Str(GetWindowRoot(#Button_1))
Debug "" : Debug "--------------------------------------------------------------------------------" : Debug ""
EnumChildTemplate(Window_2)
Debug "" : Debug "--------------------------------------------------------------------------------" : Debug ""
Debug "Window_2 : " + Str(Window_2)
Debug "Count Child Gadget of Window_2 : " + Str(CountChildGadget(Window_2))
Debug "Count Child + GrandChildren Gadget of Window_2 : " + Str(CountChildGadget(Window_2, #True))
Debug ""
Debug "Parent of #Panel_1 : " + LSet(Str(GetParent(#Panel_1)), 10) + "(Parent: IsWindow=" + Str(ParentIsWindow(#Panel_1)) + ", IsGadget=" + Str(ParentIsGadget(#Panel_1)) + ")"
Debug "Parent of SubPanel_2 : " + LSet(Str(GetParent(SubPanel_2)), 10) + "(Parent: IsWindow=" + Str(ParentIsWindow(SubPanel_2)) + ", IsGadget=" + Str(ParentIsGadget(SubPanel_2)) + ")"
Debug "Parent of #Button_5 : " + LSet(Str(GetParent(#Button_5)), 10) + "(Parent: IsWindow=" + Str(ParentIsWindow(#Button_5)) + ", IsGadget=" + Str(ParentIsGadget(#Button_5)) + ")"
Debug "Parent of #Button_4 : " + LSet(Str(GetParent(#Button_4)), 10) + "(Parent: IsWindow=" + Str(ParentIsWindow(#Button_4)) + ", IsGadget=" + Str(ParentIsGadget(#Button_4)) + ")"
Debug "Parent of Button_6 : " + LSet(Str(GetParent(Button_6)), 10) + "(Parent: IsWindow=" + Str(ParentIsWindow(Button_6)) + ", IsGadget=" + Str(ParentIsGadget(Button_6)) + ")"
Debug ""
Debug "Window Root of #Button_5 : " + Str(GetWindowRoot(#Button_5))
Repeat : Until WaitWindowEvent() = #PB_Event_CloseWindow
CompilerEndIf