Structur an eine Konstante heften

Anfängerfragen zum Programmieren mit PureBasic.
Benutzeravatar
silbersurfer
Beiträge: 175
Registriert: 06.07.2014 12:21

Structur an eine Konstante heften

Beitrag von silbersurfer »

Hallo Leute,
Ich habe mal wieder ein kleines Problem.
Es handelt sich dabei um #PB_Any und Enumeration.

Ich möchte sowohl das meine Proceduren mit Variabeln laufen als auch mit Konstanten
z.b Button=Newbutton(#PB_Any) als auch NewButton(#MeinButton)
aber wie stelle Ich das an, da die Daten ja in einer Strutur gespeichet werden
wie kann Ich eine Verbindung der Structur zur meiner Konstante herstellen ??

Ich hoffe das war verständlich ausgedrückt

hier ein kleines Beispiel wo Ich fest stecke

Code: Alles auswählen

EnableExplicit

Structure Test
	Id.i
	x.i : y.i : w.i : h.i
	text.s
EndStructure	

Enumeration Button
	#meinButton
EndEnumeration

Procedure	Im_NewButton(Gadget.i,x.i,y.i,w.i,h.i,Text.s)
		;Speicher reservieren
		Protected *this.test	=	AllocateMemory(SizeOf(test))
		;Daten der Structur übergeben
		With *this
			\x=x
			\y=y
			\w=w
			\h=h
			;bei #PB_Any das ButtonGadget der Structur übergeben
			If Gadget=#PB_Any
				\id=ButtonGadget(#PB_Any,x,y,w,h,text)
			Else
				;bei Enumeration ButtonGadget erstellen aber wie dann Weiter ?????????
				;wie kann Ich die Structur an das Gadget heften ??????
				ButtonGadget(Gadget,x,y,w,h,text)
				\id=gadget
				SetGadgetData(gadget, *this)
			EndIf 	
		EndWith	
		ProcedureReturn *this\Id
EndProcedure
	
Procedure Im_SetButtonText(*id.test,Text.s)
	*id\text=text
	SetGadgetText(*id,text)
EndProcedure	
	
If OpenWindow(0, 0, 0, 855, 600, "Structur Test", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
	Define button=Im_NewButton(#PB_Any,10,10,60,30,"test")
	Im_NewButton(#meinButton,10,40,60,30,"test")
EndIf	

Repeat
	Define Event=WaitWindowEvent()	
	If event = #PB_Event_CloseWindow
		Define Quit=#True
	EndIf 
	If event=#PB_Event_Gadget
		Select EventGadget()
			Case button
				Debug "du hast Button "+Str(button)+" gedrückt"
				Im_SetButtonText(button,"Gedrückt")
			Case #meinButton
				;hier ensteht der Fehler weil Ich in Moment nicht weiß wie Ich an die Structur komme
				Debug "du hast Button "+Str(#meinButton)+" gedrückt"
				Im_SetButtonText(#meinButton,"Gedrückt")
		EndSelect 
	EndIf 
	
Until  Quit=#True
Intel Quad Core 3,2 Ghz - GTX 1060 - BlitzBasic Plus 1.48 , PureBasic 5.70 LTS / Aktuelles Projekt PureCommander
Benutzeravatar
edel
Beiträge: 3667
Registriert: 28.07.2005 12:39
Computerausstattung: GameBoy
Kontaktdaten:

Re: Structur an eine Konstante heften

Beitrag von edel »

Code: Alles auswählen

ProcedureReturn *this\Id
Hier gibst du gar nicht deinen Zeiger zurueck, sondern lediglich die ID des Gadgets. Mit pb_any ist das eh ein Zeiger, deshalb meckert PB nicht, wenn du darin rumschreibst. Gesund ist das aber nicht.

Probiere es so :

Code: Alles auswählen

EnableExplicit

Structure Test
   Id.i
   x.i : y.i : w.i : h.i
   text.s
EndStructure   

Enumeration Button
   #meinButton
EndEnumeration

Procedure   Im_NewButton(Gadget.i,x.i,y.i,w.i,h.i,Text.s)
      ;Speicher reservieren
      Protected *this.test   =   AllocateMemory(SizeOf(test))
      ;Daten der Structur übergeben
      With *this
         \x=x
         \y=y
         \w=w
         \h=h
         ;bei #PB_Any das ButtonGadget der Structur übergeben
         If Gadget=#PB_Any
         	\id=ButtonGadget(#PB_Any,x,y,w,h,text)
         	SetGadgetData(\id, *this)
         Else
            ;bei Enumeration ButtonGadget erstellen aber wie dann Weiter ?????????
            ;wie kann Ich die Structur an das Gadget heften ??????
            ButtonGadget(Gadget,x,y,w,h,text)
            \id=gadget
            SetGadgetData(gadget, *this)
         EndIf    
      EndWith   
      ProcedureReturn *this\Id
EndProcedure
   
Procedure Im_SetButtonText(id,Text.s)
	Protected *this.test
	
	*this = GetGadgetData(id)
	
	*this\text = text
	
   SetGadgetText(id,*this\text)
EndProcedure   
   
If OpenWindow(0, 0, 0, 855, 600, "Structur Test", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
   Define button=Im_NewButton(#PB_Any,10,10,60,30,"test")
   Im_NewButton(#meinButton,10,40,60,30,"test")
EndIf   

Repeat
   Define Event=WaitWindowEvent()   
   If event = #PB_Event_CloseWindow
      Define Quit=#True
   EndIf 
   If event=#PB_Event_Gadget
      Select EventGadget()
         Case button
            Debug "du hast Button "+Str(button)+" gedrückt"
            Im_SetButtonText(button,"Gedrückt")
         Case #meinButton
            ;hier ensteht der Fehler weil Ich in Moment nicht weiß wie Ich an die Structur komme
            Debug "du hast Button "+Str(#meinButton)+" gedrückt"
            Im_SetButtonText(#meinButton,"Gedrückt")
      EndSelect 
   EndIf 
   
Until  Quit=#True
Benutzeravatar
silbersurfer
Beiträge: 175
Registriert: 06.07.2014 12:21

Re: Structur an eine Konstante heften

Beitrag von silbersurfer »

Danke edel das ist es :allright:
Hier gibst du gar nicht deinen Zeiger zurueck, sondern lediglich die ID des Gadgets. Mit pb_any ist das eh ein Zeiger, deshalb meckert PB nicht, wenn du darin rumschreibst. Gesund ist das aber nicht.
Aber warum ist das so ein Problem wenn Ich die ID zurückgebe und nicht den Zeiger
dieser wird ja dann mit SetGadgetData angeheftet.
Die Id gebe ich wegen der Eventabfrage zurück sonst muß ich das über eine Procedure Abfragen

Code: Alles auswählen

Procedure GetButtonID(*id.test)
	ProcedureReturn *id\Id
EndProcedure	
Und das ist auch nicht so elegant was Ich bis dato so gemacht habe
wenn du da noch was besseres weist würde Ich mich darüber natürlich sehr freuen

gruss Silbersurfer
Intel Quad Core 3,2 Ghz - GTX 1060 - BlitzBasic Plus 1.48 , PureBasic 5.70 LTS / Aktuelles Projekt PureCommander
Benutzeravatar
edel
Beiträge: 3667
Registriert: 28.07.2005 12:39
Computerausstattung: GameBoy
Kontaktdaten:

Re: Structur an eine Konstante heften

Beitrag von edel »

Du brauchst deinenZeiger nicht zurueckgeben, du hast aber versucht ihn hier

Code: Alles auswählen

Procedure Im_SetButtonText(*id.test,Text.s)
zu ubergeben.

Wenn du etwas objektorientiert programmieren moechtest, dann schau dir "Interface" an. Es ist allerdings nicht so flexibel wie in anderen Sprachen...

Code: Alles auswählen

Prototype onclick(self)

Interface iButton
	SetText(Text.s)
	GetText.s()
	OnClick(ClickFunc)
	Free()
EndInterface

Structure sButton
	*vt.integer
	id.i
	onclick.onclick
	clickcounter.i
EndStructure

Procedure _dispatchbuttonevent()
	Protected *self.sButton
	Protected id
	
	id = EventGadget()
	
	If id 			
		*self = GetGadgetData(id)		
		If *self
			*self\onclick(*self)
		EndIf		
	EndIf	
	
EndProcedure

Procedure _setbuttontext(*self.sButton, text.s)
	SetGadgetText(*self\id, text)
EndProcedure

Procedure.s _getbuttontext(*self.sButton, text.s)
	ProcedureReturn GetGadgetText(*self\id)
EndProcedure

Procedure _onbuttonclick(*self.sButton, func)	
	*self\onclick = func
	BindGadgetEvent(*self\id, @_dispatchbuttonevent())		
EndProcedure

Procedure _onbuttonfree(*self.sButton)	
	FreeGadget(*self\id)
	FreeMemory(*self)
EndProcedure

Procedure NewButton(x, y, cx, cy, text.s)
	
	Protected *self.sButton
	
	*self = AllocateMemory(SizeOf(sButton))
	
	If *self
		*self\vt = ?Procedures		
		*self\id = ButtonGadget(#PB_Any, x, y, cx, cy, text.s)
		SetGadgetData(*self\id, *self)
	EndIf
	
	ProcedureReturn *self
	
	DataSection
	 	Procedures:
	 	Data.i @_setbuttontext() 
	 	Data.i @_getbuttontext()
	 	Data.i @_onbuttonclick()
	 	Data.i @_onbuttonfree()
	EndDataSection
		
EndProcedure


;################################# Test

Procedure onClick(self.iButton)
	Protected *self.sButton = self
		
	*self\clickcounter + 1
	self\SetText("gedrueckt : " + *self\clickcounter)
	
EndProcedure

Procedure onExit(self.iButton)
	Protected *self.sButton = self
	
	Select MessageRequester("Ende","Wirklich beenden?", #PB_MessageRequester_YesNo)
		Case #PB_MessageRequester_Yes
			PostEvent(#PB_Event_CloseWindow)
	EndSelect	
	
EndProcedure

Procedure Main()
	Protected Button1.iButton
	Protected Button2.iButton
	Protected Button3.iButton
	Protected Window
	
	Window = OpenWindow(#PB_Any, #PB_Ignore, #PB_Ignore, 500, 500, "", #PB_Window_ScreenCentered)
	
	If Window
		
		Button1 = NewButton(5, 5, 100, 25, "Knopf1")
		Button2 = NewButton(5, 35, 100, 25, "Knopf2")
		Button3 = NewButton(395, 470, 100, 25, "Ende")
		
		Button1\OnClick(@onClick())
		Button2\OnClick(@onClick())
		Button3\OnClick(@onExit())
		
		Repeat			
		Until WaitWindowEvent() = #PB_Event_CloseWindow		
		
	EndIf
	
EndProcedure:Main()
Ich weiss, das hier ist das Anfängerforum. Und ja, ich habe nichts kommentiert, faul wie ich bin... :roll:
Benutzeravatar
NicTheQuick
Ein Admin
Beiträge: 8807
Registriert: 29.08.2004 20:20
Computerausstattung: Ryzen 7 5800X, 64 GB DDR4-3200
Ubuntu 24.04.2 LTS
GeForce RTX 3080 Ti
Wohnort: Saarbrücken

Re: Structur an eine Konstante heften

Beitrag von NicTheQuick »

Um Interfaces etwas besser erklärt zu bekommen, kannst du auch mal in mein Video schauen: [PB] Strukturen und Interfaces
Benutzeravatar
silbersurfer
Beiträge: 175
Registriert: 06.07.2014 12:21

Re: Structur an eine Konstante heften

Beitrag von silbersurfer »

Hallo Leute
NicTheQuick dein Video kenne Ich schon, und es ist auch super Hilfreich gewesen :allright: , aber es geht hier auch nicht um Interface an sich sondern,
Um die möglichkeit eine Structur (den Zeiger davon) an ein neu erstelltes Gadget zu heften.

Ich habe mich an ein Modul versucht wo genau diesen Problem für mich bestand, welches Ich nun Fertiggestellt habe.
Hier der Link zum ImageGadgetModul

edel schrieb:
Du brauchst deinenZeiger nicht zurueckgeben, du hast aber versucht ihn hier
Procedure Im_SetButtonText(*id.test,Text.s)
Ja genau edel weil Ich vorher ja auch den Zeiger zurückgegen habe was ja auch immer super geklappt hat.
Nur wenn Ich dann, wie in PureBasic gewohnt mit Kostanten z.b #MeinButton auch meine Proceduren ansprechen wollte
ging diese lösung so nicht mehr auf, deshalb war die Idee die GadgetID zurück zu geben und mit SetGdgetData den Zeiger anzuheften, was dank deinen ersten Eintrag dann ja auch Super geklappt hat :allright:

du hattest mich nur etwas verwirrt als du geschieben hast
deshalb meckert PB nicht, wenn du darin rumschreibst. Gesund ist das aber nicht.
Intel Quad Core 3,2 Ghz - GTX 1060 - BlitzBasic Plus 1.48 , PureBasic 5.70 LTS / Aktuelles Projekt PureCommander
Benutzeravatar
_sivizius
Beiträge: 98
Registriert: 23.10.2013 15:21

Re: Structur an eine Konstante heften

Beitrag von _sivizius »

Ohai,
die ID kann entweder ein Pointer sein auf die Struktur oder eine Nummer.
Einerseits haben Pointer für gewöhnlich einen Wert weit über 0xffff und andererseits reichen dir vermutlich 65536 Gadgets.
Du kannst daher einfach zwischen einem Pointer und einer echten ID unterscheiden.
Wenn nun die ID als Nummer erkannt wird musst du einfach in einem Array, z.B. mit AllocateMemory(#IntegerLaenge * $100) erstellt, den Pointer zu dem Objekt nachschlagen.
Wenn du das Gadget erstellst ist die ID entweder -1 oder größer gleich 0.
Auch diese Fälle kannst du unterscheiden, bei letzterem schreibst du einfach den erstellten Pointer in jenes Array.
Damit du einfach die Funktion in einem If-Statement nutzen kannst ist es sinnvoll bei beidem den Pointer zurück zu geben.
Jenes Array erstellst du einfach am Anfang und deklarierst es als Global.

Code: Alles auswählen

Structure gadgetliste
  id.i[$100]
EndStructure
Interface classGadget
  Delete()
EndInterface
Structure objGadget
  *class
  ;...
EndStructure
Declare deleteGadget(*self)
DataSection
  methodsGadget: ;{
    Data.i @deleteGadget()
    ;...
  ;}
EndDataSection
Global *gadgetliste.gadgetliste 
*gadgetliste = AllocateMemory(SizeOf(gadgetliste))
Procedure newGadget(gadget.l)
  If gadget > #PB_Any
    If gadget > 65535
      Debug "Gadget-ID zu groß!"
      ProcedureReturn #False
    ElseIf *gadgetliste\id[gadget]
      Debug "Gadget existiert schon!"
      ProcedureReturn #False
    EndIf
  EndIf
  *self.objGadget = AllocateMemory(SizeOf(objGadget))
  If *self
    *self\class = ?methodsGadget
    ;...
    If gadget <> #PB_Any
      *gadgetliste\id[gadget] = *self
    EndIf
  EndIf
  ProcedureReturn *self
EndProcedure
Procedure deleteGadget(*self)
  If *self < 65536 And *self > -1
    *this = *gadgetliste\id[*self]
    If Not *this
      Debug "Gadget existiert nicht!"
      ProcedureReturn #False
    Else
      *gadgetliste\id[*self] = 0
    EndIf
  Else
    *this = *self
  EndIf
  FreeMemory(*this)
  
  ProcedureReturn #True
EndProcedure
*a.classGadget = newGadget(#PB_Any)
Debug "== A =="
Debug *a
Debug *a\Delete()
Debug "== B =="
Debug *gadgetliste\id[2]
*b.classGadget = newGadget(2)
Debug *b
Debug *gadgetliste\id[2]
Debug deleteGadget(2)
Debug *gadgetliste\id[2]
Debug "== C =="
If newGadget(3)
  Debug deleteGadget(3)
EndIf
sorry für die geringe Zahl an Kommentaren^^
mfg
_sivizius
Antworten