Als je aan het programmeren bent en je snel wat knoppen in je vensters zet, is het belangrijk om die knoppen een relevante naam te geven.
Bv een nieuwe knop Button1 krijgt de naam buttonQuit of in mijn geval btQuit (ik kort de prefix voor het schermobjecttype af tot 2 of 4 lettertekens zoals bt, lsbx, cmbx, enz).
De knoppen hebben ook een functie naar de gebruiker, je moet ze dus ook een etiket geven voor de gebruiker, de Text property: Button1.Text of bij mij: btQuit.Text=”Quit”.
Zie je de luiheid al opkomen? In de nieuwere versies van Gambas (Gambas3) wordt de Button1.Name ook weergegeven op de knop als je zelf nog geen tekst erin zette; dit is bijzonder handig tijdens het programmeren.
Maar als die tekst eens ineens kan blijven staan als goede tekst? In mijn geval zou btQuit wel de opdruk “Quit” moeten krijgen, dus de twee letterjes prefix van het type moeten eraf. Right(Button1.Text, -2) als het ware.
Daar gaan we dus:
In een steeds in mijn projecten voorkomende schermfunctiesverzameling plant ik deze:
MForm
Public Sub doNameButtons(hMainObject As Object) ' Dim hObject As Object Dim hButton As Button Dim iChildrenCount As Integer ' Debug hMainObject.Name & " " & TypeOf(hMainObject) ' Try iChildrenCount = hMainObject.Children.Count ' If Not Error ' For Each hObject In hMainObject.Children ' Try hButton = hObject ' If Not Error If Left(hObject.Name, 2) = "bt" And hButton.Text = "" Debug "CHANGE TO " & Right(hObject.Name, -2) hButton.Text = Right(hObject.Name, -2) Else ' not named with naming convention of buttons, this is a way to let you exclude empty-text buttons from this auto-name ' name not empty, so it stays as it is - and can be translated Debug "NO CHANGE: " & hObject.Name Endif Else ' recursion Debug hObject.Name & " is no button; check for .children : " doNameButtons(hObject) Endif Next Else Debug "Error hMainObject.Children.Count " & hMainObject.Name & " " & iChildrenCount Endif End '
In mijn FMain (en alle andere schermen die ik snel in elkaar flikker) roep ik dat zo aan voor iedere container met buttons in (soms nog eens in een container – dus recursief):
FMain
Public Sub Form_Open() ' MForm.doNameButtons(HBox1) ' ... End
Alle knoppen in de Form die al een opschrift hebben, houden die. De anderen krijgen één, afgeleid van de knopnaam.
Let op!
Dit is alleen handig tijdens het programmeren, als de knoppen nog van functie en naam veranderen enz.
Eens het project zo ver af is dat je het gaat vertalen zul je toch de Text properties van de knoppen moeten invullen, anders werkt het vertaalsysteem niet.
Check eerst of het een button is:
TypeOf(hObject) = TypeOf(hButton)
Dit is geen oplossing, omdat er niet zo’n fijn onderscheid wordt gemaakt tussen objecten in TypeOf; beiden zijn “16” (een constante voor gb.Object); ook een HBox of VBox behoort daartoe.
Ik vond geen andere methode dan het child object proberen toe te wijzen aan een button; bij fout is het geen button, anders wel.
Zelfs tussen buttons kan er een ander object staan zoals een leeg tekstveld om als “spacer” te gebruiken; tekst leeg maar expand=TRUE zodat het een knop aan de rechterkant naar rechts tot aan het einde van de container (bv HBox) duwt.
Hernoemen uitvoeren op button object met naam beginnend met “bt”, de anderen worden overgeslagen.
Recursie
Als het object geen button was, kan het altijd nog een container zijn die ook weer buttons bevat, dus wordt dat gecheckt en kan de hernoem-test opnieuw beginnen.
Daarom wordt de procedure zelf terug opgeroepen.
Ik vond ook geen mooie manier om te testen of het een container is, en als er geen children objecten zijn, crasht
For Each hObject In hMainObject.Children
Daarom test ik eerst of een Children.Count wel kan:
Try iChildrenCount += hMainObject.Children.Count
‘
If Not Error
‘
(het optellen heeft niet echt zin)
Upd 13092017: bug fix: crash bij ander object dan button en helemaal herwerkt.