EditorGadget - Bug oder Userproblem?

Für allgemeine Fragen zur Programmierung mit PureBasic.
Benutzeravatar
netzer
Beiträge: 26
Registriert: 13.06.2005 20:14
Wohnort: Homeoffice

EditorGadget - Bug oder Userproblem?

Beitrag von netzer »

Hallo zusammen,

ich habe ein Problem bei der Verwendung des EditorGadget:

In meinem Programm befindet sich eine PING-Funktion (ähnelt dem DOS-Befehl), bei Aufruf dieser Funktion soll jeder einzelne Ping an ein EditorGadget mittels AddGadgetItem zurückgegeben werden. Das funktioniert aber erst ab dem 20. Versuch. Um dieses Problem zu beheben, habe ich jetzt eine For-Next-Schleife mit 20x AddGadgetItem(ID, -1, Chr(10)) eingebaut. Sieht nicht schön aus aber funktioniert.

Ist das ein Bug oder ein Userproblem?

Danke und Gruß vom Netzer

PS: PB 4.30
Nobody said it was easy...
Benutzeravatar
cxAlex
Beiträge: 2111
Registriert: 26.06.2008 10:42

Beitrag von cxAlex »

Hm, bei mir funzt das schön:

Nachdem du keinen Code gepostet hast hab ich schnell selbst ein Beispiel geschrieben, so sollte das gehen:

Code: Alles auswählen

EnableExplicit

Define Window, Edit, Address, Ping, Event, Host$

InitNetwork()

Procedure DNS_Lookup(Host$)
  Protected *host.hostent, ret.l
  *host = gethostbyname_(host$)
  If *host
    ret = PeekL(PeekL(*host\h_addr_list))
  Else
    ret = *host
  EndIf
  ProcedureReturn ret
EndProcedure

Procedure ICMP_Ping(ipAddress)
  Protected *Echo.ICMP_ECHO_REPLY, EchoMessage.s, ResultSize, ret, hFile, loop, rtt
  
  EchoMessage = RSet("ICMP ECHO MESSAGE ", 64, "X") ; 64 Bytes senden
  ResultSize = SizeOf(ICMP_ECHO_REPLY) + Len(EchoMessage)
  *Echo = AllocateMemory(ResultSize)
  
  hFile = IcmpCreateFile_()
  For loop = 1 To 3 ; Wie genau?
    If IcmpSendEcho_(hFile, ipAddress, EchoMessage, Len(EchoMessage), 0, *Echo, ResultSize, 1000)
      ret + 1
      rtt = rtt + *Echo\RoundTripTime
    EndIf
  Next
  IcmpCloseHandle_(hFile)
  FreeMemory(*Echo)
  
  If ret
    ret = rtt/ret
  Else
    ret = -1
  EndIf
  
  ProcedureReturn ret
  
EndProcedure

Window = OpenWindow(#PB_Any, 0, 0, 400, 390, "Ping", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
Edit = EditorGadget(#PB_Any, 5, 5, 390, 350, #PB_Editor_ReadOnly)
Address = StringGadget(#PB_Any, 5, 360, 315, 20, "www.google.de")
Ping = ButtonGadget(#PB_Any, 325, 360, 70, 20, "Ping")


Repeat
  Event = WaitWindowEvent()
  Select Event
    Case #PB_Event_Gadget
      Select EventGadget()
        Case Ping
          Host$ = GetGadgetText(Address)
          AddGadgetItem(Edit, -1, "Host: " + Host$ + ", IP: " + IPString(DNS_Lookup(Host$)) + ", Ping: " + Str(ICMP_Ping(DNS_Lookup(Host$)))+" ms")
      EndSelect
  EndSelect
Until Event = #PB_Event_CloseWindow
Projekte: IO.pbi, vcpu
Pausierte Projekte: Easy Network Manager, µC Emulator
Aufgegebene Projekte: ECluster

Bild

PB 5.1 x64/x86; OS: Win7 x64/Ubuntu 10.x x86
Benutzeravatar
netzer
Beiträge: 26
Registriert: 13.06.2005 20:14
Wohnort: Homeoffice

Beitrag von netzer »

Habe jetzt mal in Kurzform gecodet:

Code: Alles auswählen

 Procedure action()
 
 For i = 1 To 20
    AddGadgetItem(0, -1, "Zeile " + Str(i))
    Debug i
    SendMessage_(GadgetID(0),#EM_SCROLL,#SB_BOTTOM,0)
    Delay(200)
 Next
 
 EndProcedure
 
 
  If OpenWindow(0, 0, 0, 200, 170, "Test", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
    EditorGadget(0, 10, 10, 180, 100)
    ButtonGadget(1, 10, 140, 50, 20, "Action!", #PB_Button_MultiLine)
 
    Repeat
    EventID = WaitWindowEvent()
    
    If EventID = #PB_Event_Gadget

      Select EventGadget()
        Case 1
          action()       

          
      EndSelect

    EndIf

  Until EventID = #PB_Event_CloseWindow

EndIf


Wenn man den Button drückt, vergeht eine gewisse Zeit, bis etwas passiert (siehe Debugger). Nach wiederholtem Drücken funktioniert es einwandfrei. :?
In meinem eigentlichen Programm geschieht es erst nach 20 Durchläufen.

Gruß vom Netzer
Nobody said it was easy...
Benutzeravatar
netzer
Beiträge: 26
Registriert: 13.06.2005 20:14
Wohnort: Homeoffice

Beitrag von netzer »

Es hängt mit der Größe des Gadgets zusammen. Habe soeben das EditorGadget vergrößert -> Zeitspanne wird größer... :evil:
Nobody said it was easy...
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 »

> Ist das ein Bug oder ein Userproblem?
Naja, ein Problem des Codes. Solange sich Dein Programm in action()
befindet, werden keine WindowEvents bearbeitet, AddGadgetItem wird zwar
ausgeführt, aber nicht gezeichnet.

Das Delay ist dort vollkommen deplaciert. Du solltest Timer einsetzen,
entweder per API oder ein bissel warten, bis PB4.40 beta erscneint, da gibts
die Timer nativ.

Da Dein Beitrag unter Allgemein gepostet wurde, denke ich mal, das
bekommste jetzt alleine hin.

Gruß

Thomas
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
Benutzeravatar
netzer
Beiträge: 26
Registriert: 13.06.2005 20:14
Wohnort: Homeoffice

Beitrag von netzer »

OK, also ein Userproblem :oops: , danke für die klaren Worte...

Das Delay sollte die pings ein bißchen sanfter ausführen.

Gruß
Netzer
Nobody said it was easy...
Benutzeravatar
netzer
Beiträge: 26
Registriert: 13.06.2005 20:14
Wohnort: Homeoffice

Beitrag von netzer »

Solange sich Dein Programm in action() befindet, werden keine WindowEvents bearbeitet, AddGadgetItem wird zwar ausgeführt, aber nicht gezeichnet.
Die WindowEvents werden ausgeführt, aber erst nach einem bestimmten Durchlauf. Bei erneutem Klicken des Buttons läuft es einwandfrei.
Habe jetzt die Größe noch einmal geändert und das Delay sogar hochgesetzt. Beachtet dabei das EditorGadget und zeitgleich den Debugger. Nach Durchlauf noch einmal action drücken...

Gruß vom Netzer

Code: Alles auswählen

 Procedure action()
 
 For i = 1 To 30
    AddGadgetItem(0, -1, "Zeile " + Str(i))
    Debug i
    SendMessage_(GadgetID(0),#EM_SCROLL,#SB_BOTTOM,0)
    Delay(500)
 Next
 
 EndProcedure
 
 
  If OpenWindow(0, 0, 0, 200, 250, "Test", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
    EditorGadget(0, 10, 10, 180, 190)
    ButtonGadget(1, 10, 210, 50, 20, "Action!", #PB_Button_MultiLine)
 
    Repeat
    EventID = WaitWindowEvent()
    
    If EventID = #PB_Event_Gadget

      Select EventGadget()
        Case 1
          action()       

          
      EndSelect

    EndIf

  Until EventID = #PB_Event_CloseWindow

EndIf
Nobody said it was easy...
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 »

> Die WindowEvents werden ausgeführt, aber erst nach einem bestimmten Durchlauf
Anfangs fallen mehr Events an, die in Deinem Code nicht richtig
abgearbeitet werden, deshalb fällts dort mehr auf.

Delay ist in jeder GUI Anwendung böse :mrgreen:

Per Timer im Eventloop rufste die Procedure auf und fürst nur einen Schritt
der Schleife aus, zählst stattdessen eine statische Variable hoch.

Schon sollte alles laufen wie geschmiert.

Gruß

Thomas
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
Benutzeravatar
netzer
Beiträge: 26
Registriert: 13.06.2005 20:14
Wohnort: Homeoffice

Beitrag von netzer »

Hmm, jetzt habe ich den ganzen Tag ohne Erfolg rumgebastelt :(

Habe den Gedankenanstoß von Thomas verstanden (auch die Funktionsweise), aber es scheitert bei der Umsetzung:
EventGadget (Case 1) und Timer im Eventloop zu vereinen, ist für mich der größte Stolperstein.

Code: Alles auswählen

 Procedure action(i)
 
 
    AddGadgetItem(0, -1, "Zeile " + Str(i))
    Debug i
    SendMessage_(GadgetID(0),#EM_SCROLL,#SB_BOTTOM,0)
    
 
 
 EndProcedure
 
 
  If OpenWindow(0, 0, 0, 200, 250, "Test", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
    SetTimer_(WindowID(0), 0, 500, 0)
    EditorGadget(0, 10, 10, 180, 190)
    ButtonGadget(1, 10, 210, 50, 20, "Action!", #PB_Button_MultiLine)
 
    Repeat
    EventID = WaitWindowEvent()
    
    
    
    
    If EventID = #PB_Event_Gadget

      Select EventGadget()
        Case 1
          action(k) 
                 
      Case #WM_TIMER
        ;Hier wachsen mir die grauen Haare
        ;Timer und Case 1 sollen zusammen arbeiten
          
      EndSelect

    EndIf

  Until EventID = #PB_Event_CloseWindow

EndIf
Vielen Dank für Eure Unterstützung
Gruß
Netzer
Nobody said it was easy...
Benutzeravatar
HeX0R
Beiträge: 3042
Registriert: 10.09.2004 09:59
Computerausstattung: AMD Ryzen 7 5800X
96Gig Ram
NVIDIA GEFORCE RTX 3060TI/8Gig
Win11 64Bit
G19 Tastatur
2x 24" + 1x27" Monitore
Glorious O Wireless Maus
PB 3.x-PB 6.x
Oculus Quest 2 + 3
Kontaktdaten:

Beitrag von HeX0R »

netzer hat geschrieben:Hmm, jetzt habe ich den ganzen Tag ohne Erfolg rumgebastelt :(
Hmm... also, das ist ja nun wirklich ein triviales Problem, was machst du denn, wenn es wirklich mal komplex wird?

Egal, hier:

Code: Alles auswählen

Procedure action(i)

	AddGadgetItem(0, -1, "Zeile " + Str(i))
	Debug i
	SendMessage_(GadgetID(0), #EM_SCROLL, #SB_BOTTOM, 0)

EndProcedure


If OpenWindow(0, 0, 0, 200, 250, "Test", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
	SetTimer_(WindowID(0), 1, 500, 0)
	EditorGadget(0, 10, 10, 180, 190)
	ButtonGadget(1, 10, 210, 50, 20, "Action!", #PB_Button_MultiLine)

	Repeat
		EventID = WaitWindowEvent()

		If EventID = #PB_Event_Gadget
			Select EventGadget()
				Case 1
					If Not Start
						SetGadgetText(1, "Stop!")
					Else
						SetGadgetText(1, "Action!")
					EndIf
					Start ! 1
			EndSelect
		ElseIf EventID = #WM_TIMER
			If Start
				action(k)
				k + 1
			EndIf
		EndIf

	Until EventID = #PB_Event_CloseWindow

EndIf
Antworten