Hilfe Endlosschleife

Anfängerfragen zum Programmieren mit PureBasic.
Sputnik
Beiträge: 8
Registriert: 07.06.2005 11:08

Beitrag von Sputnik »

Zitat PB Hilfe:
Von daher macht man zum updaten immer:
While : WindowEvent() : Wend

Alternativ wäre natürlich auch noch
Repeat : Until WindowEvent() = 0

möglich, was jedoch eher unüblich ist.

Code: Alles auswählen


    Repeat
      Event = WindowEvent()                       
      Debug "Event bei Pause (1): " + Str(Event)    
      If Event = #PB_Event_CloseWindow
       .
       .
      EndIf
      Debug "Event bei Pause (2): " + Str(Event)    
     ; hier hat Event seinen Inhalt verloren --> ist immer 1 
    Until Event = 0 

 
Das Debug vor dem If zeigt den zurückgegebenen Event an.
Und natürlich wird der NULL nämlich dann, wenn keine Message mehr ansteht.
Nach dem EndIf zeigt Debug aber immer >>1<< !!!
Was zwischen IF und EndIf steht wird nur ausgeführt wenn der Schließknopf geklickt wurde.
Der EventLoop hier ist nur dazu da die Events in der Message Queue zu verarbeiten damit sie sich nicht aufstauen während der Delays.
Sicherlich kann man eine Pause Funktion auch auf x andere Arten ohne For Next realisieren
aber ich will jetzt mal nur wissen warum es zu dem Fehler bei dem If kommt.

Gruß
Gerd
Zuletzt geändert von Sputnik am 12.06.2005 21:28, insgesamt 1-mal geändert.
Benutzeravatar
ts-soft
Beiträge: 22292
Registriert: 08.09.2004 00:57
Computerausstattung: Mainboard: MSI 970A-G43
CPU: AMD FX-6300 Six-Core Processor
GraKa: GeForce GTX 750 Ti, 2 GB
Memory: 16 GB DDR3-1600 - Dual Channel
Wohnort: Berlin

Beitrag von ts-soft »

Code: Alles auswählen

If OpenWindow(0, 100, 200, 195, 260, #PB_Window_SystemMenu, "PureBasic Window") = 0 : End : EndIf


Repeat
  Event = WaitWindowEvent()                       
  Debug "Event bei Pause (1): " + Str(Event)   
  If Event = #PB_Event_CloseWindow
    Event = 0
 
  EndIf

  Debug "Event bei Pause (2): " + Str(Event)   
; hier hat Event seinen Inhalt verloren --> ist immer 1
Until Event = 0
So geht es :D
PureBasic 5.73 LTS | SpiderBasic 2.30 | Windows 10 Pro (x64) | Linux Mint 20.1 (x64)
Nutella hat nur sehr wenig Vitamine. Deswegen muss man davon relativ viel essen.
Bild
Kaeru Gaman
Beiträge: 17389
Registriert: 10.11.2004 03:22

Beitrag von Kaeru Gaman »

der code ist für mich schwer durchzusteigen.

du machst ein "FakeReturn", aber willst eine Procedure verlassen.
...böse Falle... lass es.
innerhalb der procs NUR flags setzen, bzw rückgabewert zuweisen,
die behandlung der unterschiedlichen ergebnisse NACH der Proc.

damit bringst du das komplette programmaus dem ruder.

wahrscheinlich springt er an die angegebene adresse, aber der stack enthält noch die rücksprungadresse...

oder irgendso etwas...

löse es einfach völlig anders.

[edit]
...und bevor du jetzt weiterborst, warum die beiden debugs dieses..jenes...

lös es erstmal komplett anders von der struktur her, und schau dann, ob das problem immernoch besteht...
Der Narr denkt er sei ein weiser Mann.
Der Weise weiß, dass er ein Narr ist.
Benutzeravatar
ts-soft
Beiträge: 22292
Registriert: 08.09.2004 00:57
Computerausstattung: Mainboard: MSI 970A-G43
CPU: AMD FX-6300 Six-Core Processor
GraKa: GeForce GTX 750 Ti, 2 GB
Memory: 16 GB DDR3-1600 - Dual Channel
Wohnort: Berlin

Beitrag von ts-soft »

Vielleicht hilft dies hier als Ansatz:

Code: Alles auswählen

;-Window Constants
Enumeration 1
  #Window_frmLB_Main
EndEnumeration
;-Gadget Constants
Enumeration 1
  ;Window_frmLB_Main
  #Gadget_frmLB_Main_Editor
  #Gadget_frmLB_Main_String
  #Gadget_frmLB_Main_StringReturn
EndEnumeration

Procedure.l Window_frmLB_Main()
  If OpenWindow(#Window_frmLB_Main,179,182,640,480,#PB_Window_SystemMenu|#PB_Window_ScreenCentered|#PB_Window_Invisible,"LB-Main")
    If CreateGadgetList(WindowID(#Window_frmLB_Main))
      EditorGadget(#Gadget_frmLB_Main_Editor,0,0,640,450)
      StringGadget(#Gadget_frmLB_Main_String,5,455,630,20,"")
      HideWindow(#Window_frmLB_Main,0)
      AddKeyboardShortcut(#Window_frmLB_Main, #PB_Shortcut_Return, #Gadget_frmLB_Main_StringReturn)
      ProcedureReturn WindowID()
    EndIf
  EndIf
EndProcedure

;-Main Loop
If Window_frmLB_Main()

  quitfrmLB_Main=0
  Repeat
    EventID=WaitWindowEvent()
    Select EventID
      Case #PB_Event_CloseWindow
        If EventWindowID()=#Window_frmLB_Main
          quitfrmLB_Main=1
        EndIf
      Case #PB_Event_Menu
        Select EventMenuID()
          Case #Gadget_frmLB_Main_StringReturn
            AddGadgetItem(#Gadget_frmLB_Main_Editor, #PB_Default, GetGadgetText(#Gadget_frmLB_Main_String))
            SetGadgetText(#Gadget_frmLB_Main_String, "")
        EndSelect
      Case #PB_Event_Gadget
        Select EventGadgetID()
          Case #Gadget_frmLB_Main_Editor
           ActivateGadget(#Gadget_frmLB_Main_String)
          Case #Gadget_frmLB_Main_String
        EndSelect
    EndSelect
  Until quitfrmLB_Main
  CloseWindow(#Window_frmLB_Main)
EndIf
End
@Kaeru
Wenn Du mir jetzt auch sagst, Du verstehst den Code nicht .... :D
PureBasic 5.73 LTS | SpiderBasic 2.30 | Windows 10 Pro (x64) | Linux Mint 20.1 (x64)
Nutella hat nur sehr wenig Vitamine. Deswegen muss man davon relativ viel essen.
Bild
Sputnik
Beiträge: 8
Registriert: 07.06.2005 11:08

Beitrag von Sputnik »

@Kaeru
Wenn Sie aus der Sub-Routine in einen anderen Programmteil ausserhalb dieser Sub-Routine springen möchten (mit dem Befehl Goto), müssen Sie FakeReturn benutzen, um ein Return zu simulieren, ohne es wirklich auszuführen. Wenn Sie diesen Befehl nicht benutzen, wird Ihr Programm abstürzen. Diese Funktion sollte nutzlos sein, da ein ordentlich aufgebautes und strukturiertes Programm kein Goto benutzt. Aber manchmal, aus Geschwindigkeitsgründen, kann es etwas helfen.
Das stimmt FakeReturn steht in der Hilfe bei Gosub aber sollte vom Prinzip her doch auch für Prozeduren verwendbar sein. Es löscht doch nur die Rücksprungadresse um mit Goto woanders hinspringen zu können.
Wenn das Programm aus dem Ruder läuft, dann schon vorher. Im übrigen wird der Teil zwischen IF und EndIf im Debugger immer übersprungen und ist das einzige was funtioniert wenn es ohne Debugger läuft. Die Endlosschleife läßt sich nämlich durch klicken auf den Schließknopf verlassen. Ich geb gern zu daß das kein typisches Windows Programm ist was ich da versuche und es tut mir leid wenn es schwer verständlich ist.
Ich hätte es es auch gar nicht hier reingestellt wenn es mir gelungen wäre den Fehler in einem kleinen Code-Beispiel zu reproduzieren (was ich natürlich auch versucht hatte).

@ts-soft
Sehr schönes Programm!


Also dann, Thema erledigt.

Gruß
Gerd
Kaeru Gaman
Beiträge: 17389
Registriert: 10.11.2004 03:22

Beitrag von Kaeru Gaman »

ermn... sorry, nich ganz...

also, nochmal klar:

laß den scheiß "FakeReturn steht in der Hilfe bei Gosub aber sollte vom Prinzip her doch auch für Prozeduren verwendbar sein"

barn... puke... proggs selber in ASM oder lass es.

..aber komm nich mit 'müßte aber bla blub'

argl..

SPRINGE NICHT MIT EINEM DIREKTEN JUMP AUS EINER PROCEDURE!!!!!

barf... lass es einfach...

und diskutier nich drum rum was müßte...

*aufreg* *angenervt sei*


...okokok... gilt hier "don't feed the trolls" ?

...also, nachdem ich nochmal 3x durchgeatmet hab, ne korrekte antwort:

Ein GOSUB ist einfach nur ein JSR.
Dementsprechend liegt natürlich auch nur die Rücksprungadesse auf dem Stack.

Eine Procedure erzeugt ein komplett neues Environment.
Was hier alles auf den Stack gepackt wird, weiß ich nicht genau,
aber es ist garantiert einiges mehr als eine einzige Adresse.
Sämtliche Variablenzuweisungen werden von externen unterschieden.
Allein der Gedanke, einen Procedure-Aufruf durch simples poppen
der Rücksprungadresse vom Stapel ungeschehen zu machen,
wiederspricht grundsätzlich dem Grundgedanken einer Procedure
(die im Gegensatz zu einer mit Gosub aufgerufenen Subroutine steht)
Zuletzt geändert von Kaeru Gaman am 13.06.2005 01:48, insgesamt 1-mal geändert.
Der Narr denkt er sei ein weiser Mann.
Der Weise weiß, dass er ein Narr ist.
Benutzeravatar
NicTheQuick
Ein Admin
Beiträge: 8809
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

Beitrag von NicTheQuick »

@Sputnik:
Bei einer Procedure werden andere Sachen gepopt oder gepusht wie bei einer Gosub. Daher dürfte bei einer Procedure das FakeReturn nicht zuverlässig funktioniert oder vielleicht sogar gar nicht.

@Kaeru:
Komm mal wieder runter und geh erstmal schlafen. :|
Kaeru Gaman
Beiträge: 17389
Registriert: 10.11.2004 03:22

Beitrag von Kaeru Gaman »

@nic

hast ja recht...

...deshalb hab ich meine erste, spontane antwort ja ge-smallt,
und ne korrekte druntergeschrieben... ;)
Der Narr denkt er sei ein weiser Mann.
Der Weise weiß, dass er ein Narr ist.
Benutzeravatar
freedimension
Admin
Beiträge: 1987
Registriert: 08.09.2004 13:19
Wohnort: Ludwigsburg
Kontaktdaten:

Beitrag von freedimension »

Kaeru Gaman hat geschrieben:...deshalb hab ich meine erste, spontane antwort ja ge-smallt,
...
Hmm, "gelöscht" wäre besser gewesen ;)
Beginne jeden Tag als ob es Absicht wäre!
Bild
BILDblog
Sputnik
Beiträge: 8
Registriert: 07.06.2005 11:08

Beitrag von Sputnik »

Ich sehe gerade erst, daß ihr noch geantwortet habt von wegen 'FakeReturn'. Ich weiß auch nicht wie ich auf den Blödsinn gekommen bin. Ich hab mir eure Kritik zu Herzen genommen und die Sache etwas umgebaut, damit es mehr 'Windows konform' ist. Und dann gings immer noch nicht. Erst als ich das dämliche FakeReturn rausgeschmissen hatte gings auf einmal. Mich wundert daß sich das ausgewirkt hat obwohl es hinter einem If stand. Der Compiler könnte eigentlich auch einen Fehler melden bei sowas. Jedenfalls hab ich den ersten Code gelöscht und bring hier die geänderte Fassung.

Gruß
Gerd

Code: Alles auswählen

;
; Versuch das Mainwin von LibertyBasic nachzubauen
; noch ganz am Anfang, wird vielleicht nich besser
;
#LB_MainWin   = 999
#LB_Editor    = 999
#LB_InputBox  = 1000

LB_Run.l  = 1
Declare LB_MainWin(breite.l,hoehe.l,titel$)

; Funktionen die von Basic aus aufgerufen werden können
Declare LB_Scan()
Declare.s LB_Input(text$)
Declare LB_Cls()
Declare LB_Pause(ms.l)
Declare LB_Print(text$)

If LB_MainWin(660,450,"Liberty Sim") = 0 : End: EndIf   ; anfängliche Fenstergröße und Titel 
                                                        ; können hier angegeben werden

Procedure LB_Proc()
;####################################################### Basic Code kommt hier rein

  For a=32 To 96
    LB_Print(Str(a)+ "  " + Chr(a))
  Next a
  LB_Pause(3000)
  LB_Cls()
  i$ = LB_Input("gib mal was ein :")
  LB_Print("du hast "+i$+ " eingegeben")
  i$ = LB_Input("gib nochmal was ein :")
  LB_Print("du hast "+i$+ " eingegeben")

LB_Print("fertig")
;####################################################### Ende Basic Code
EndProcedure

MainEventHandler:
Repeat
  EventID = WindowEvent()
  Select LB_Run
    Case 1
      LB_Run = 0
      LB_Proc()
    Case 0
      LB_Run = -1
      title$ = GetWindowTitle(#LB_MainWin)
      title$ = " beendet " + title$
      SetWindowTitle(#LB_MainWin, title$)
      ResizeGadget(#LB_Editor, 0, 0, WindowWidth(), WindowHeight())
  EndSelect
  If EventID = #PB_Event_SizeWindow
    ; editor an fenstergröße anpassen
    ResizeGadget(#LB_Editor, 0, 0, WindowWidth(), WindowHeight())
  EndIf
  Delay(10)
Until EventID = #PB_Event_CloseWindow
End


;############################################################ Prozeduren

Procedure.l LB_MainWin(breite.l,hoehe.l,titel$)
;###################################################  
  result.l = 1
  FontID.l = LoadFont(#PB_Any, "Courier New", 10 )

  If OpenWindow(#LB_MainWin, 0, 0, breite, hoehe,  #PB_Window_SystemMenu | #PB_Window_ScreenCentered | #PB_Window_MinimizeGadget | #PB_Window_MaximizeGadget | #PB_Window_SizeGadget | #PB_Window_TitleBar ,titel$)
    If CreateGadgetList(WindowID())
      SetGadgetFont(#PB_Any,UseFont(FontID))
      StringGadget(#LB_InputBox, 0, WindowHeight()-20, WindowWidth(), 20, "",#PB_String_MultiLine|#ES_AUTOVSCROLL)
      EditorGadget(#LB_Editor, 0, 0, WindowWidth(), WindowHeight())
      SendMessage_(GadgetID(#LB_Editor),#EM_SETREADONLY,1,0)
    Else
      result = 0
    EndIf
  Else
    result = 0
  EndIf
  CallDebugger
  ProcedureReturn result
EndProcedure

Procedure.s LB_Input(text$)
;###############################  
  CallDebugger 
  txtLen.l   = Len(text$)
  selstart.l = txtLen
  selend.l   = 0
    
  ResizeGadget(#LB_Editor, 0, 0, WindowWidth(), WindowHeight()-20)
  For n = 1 To 3
    SendMessage_(GadgetID(#LB_Editor), #EM_SCROLL, #SB_LINEDOWN, 0)
  Next n
  SetGadgetText(#LB_InputBox, text$)
  a$ = text$
  ActivateGadget(#LB_InputBox)
  SendMessage_(GadgetID(#LB_InputBox), #EM_SETSEL, txtLen, txtLen)  ; Set cursor Position
  Repeat
    EventID = WindowEvent()
    Select EventID

      Case #PB_EventGadget
        Select EventGadgetID()
            Case #LB_InputBox
              DisableGadget(#LB_InputBox, 0 )
              EventTyp = EventType()
              Select EventTyp
                Case #PB_EventType_LostFocus 
                  ActivateGadget(#LB_InputBox)
                  a$=GetGadgetText(#LB_InputBox)
                  SendMessage_(GadgetID(#LB_InputBox), #EM_SETSEL, Len(a$), Len(a$)) 
                Case #PB_EventType_Change                           
                  SendMessage_(GadgetID(#LB_InputBox), #EM_GETSEL, @selstart, @selend)  
                  If selstart <= txtLen
                    SetGadgetText(#LB_InputBox, a$)
                    SendMessage_(GadgetID(#LB_InputBox), #EM_SETSEL, Len(a$), Len(a$)) 
                  EndIf
                  a$=GetGadgetText(#LB_InputBox)
                  If Left(a$,txtLen) <> text$          
                    SetGadgetText(#LB_InputBox,text$+b$)
                    SendMessage_(GadgetID(#LB_InputBox), #EM_SETSEL, Len(a$), Len(a$)) 
                  Else
                    b$ = Mid(a$, txtLen + 1, $FFFF)
                    pos=FindString(b$,Chr(13)+Chr(10),1)
                    If pos<>0 ; Was Enter pressed on the StringGadget?
                      b$ = ReplaceString(b$,Chr(13)+Chr(10),"")
                      ClearGadgetItemList(#LB_InputBox)
                      DisableGadget(#LB_InputBox, 1 )
                      SendMessage_(GadgetID(#LB_Editor), #EM_SCROLL, #SB_LINEDOWN, 0)
                      ResizeGadget(#LB_Editor, 0, 0, WindowWidth(), WindowHeight())
                      ProcedureReturn b$
                    EndIf
                  EndIf  
              EndSelect
          EndSelect
        
          Case #PB_Event_SizeWindow
          ; editor an fenstergröße anpassen
          ResizeGadget(#LB_Editor, 0, 0, WindowWidth(), WindowHeight()-20)
          ResizeGadget(#LB_InputBox, 0, WindowHeight()-20, WindowWidth(), -1) 
        
          Case #PB_Event_CloseWindow
          ; User will Fenster schliessen
          result = MessageRequester("X","Wollen Sie das Programm abbrechen ?",#PB_MessageRequester_YesNo)
          If result = 6     ; Ja-Schalter wurde gedrückt (Result = 6)
            ResizeGadget(#LB_Editor, 0, 0, WindowWidth(), WindowHeight())
            Goto MainEventHandler
          Else
            ActivateGadget(#LB_InputBox)
          EndIf
      EndSelect
      Delay(1)
    ForEver
  
  EndProcedure 
  
Procedure LB_Pause(ms.l)
;#######################
  pause.l = 10
  iter.l  = Int(ms / pause)
  lc.l
  ResizeGadget(#LB_Editor, 0, 0, WindowWidth(), WindowHeight())
  
  For lc = 1 To iter
    Repeat
      Event = WindowEvent()                    
      If Event = #PB_Event_CloseWindow
        result = MessageRequester("X","Wollen Sie das Programm abbrechen ?",#PB_MessageRequester_YesNo)
        If result = 6     ; Ja-Schalter wurde gedrückt (Result = 6)
          Goto MainEventHandler
        EndIf 
      EndIf
    Until Event = 0
    Delay(pause)
  Next lc    
EndProcedure

Procedure LB_Cls()
;######################
  ClearGadgetItemList(#LB_Editor)
EndProcedure 

Procedure LB_Scan()
;#######################
  CallDebugger
  Repeat
    Event = WindowEvent()
    If Event = #PB_Event_CloseWindow
      result = MessageRequester("X","Wollen Sie das Programm abbrechen ?",#PB_MessageRequester_YesNo)
      If result = 6     ; Ja-Schalter wurde gedrückt (Result = 6)
        Goto MainEventHandler
      EndIf 
    EndIf  
  Until Event = 0  
EndProcedure

Procedure LB_Print(text$)
;#######################  
  AddGadgetItem(#LB_Editor,-1,text$)
  SendMessage_(GadgetID(#LB_Editor), #EM_SCROLL, #SB_LINEDOWN, 0)
EndProcedure

Antworten