Seite 1 von 1

Button ausgrauen und mehr

Verfasst: 13.02.2009 10:25
von Tom123
Hallo Forum,

als Purebasic-Anfänger komme ich jetzt einfach nicht mehr weiter und bitte um Mithilfe bei meinen Verständnisproblemen - ich hoffe, ich treffe den "Forumston"... :D

Anbei der "problematische Code":
**common.pb**

Code: Alles auswählen

; PureBasic Visual Designer v3.95 build 1485 (PB4Code)


;- Window Constants
;
Enumeration
  #Window_0
EndEnumeration

;- Gadget Constants
;
Enumeration
  #btnOSP
  #btnM0001
  #btnM0000
  #btnGET
  #Frame3D_0
  #txtAnzeige
  #btnExit
EndEnumeration


Procedure Open_Window_0()
  If OpenWindow(#Window_0, 375, 191, 800, 600, "RS232",  #PB_Window_SystemMenu | #PB_Window_SizeGadget | #PB_Window_TitleBar | #PB_Window_ScreenCentered | #PB_Window_WindowCentered )
    ;If CreateGadgetList(WindowID(#Window_0))
      ButtonGadget(#btnOSP, 40, 530, 120, 40, "Open Serial Port")
      ButtonGadget(#btnM0001, 340, 530, 120, 40, "Mode0001")
      ButtonGadget(#btnM0000, 190, 530, 120, 40, "Mode0000")
      ButtonGadget(#btnGET, 490, 530, 120, 40, "Get Data")
      Frame3DGadget(#Frame3D_0, 30, 30, 740, 480, "", #PB_Frame3D_Double)
      TextGadget(#txtAnzeige, 40, 40, 720, 460, "")
      ButtonGadget(#btnExit, 640, 530, 120, 40, "Exit")
      
    ;EndIf
  EndIf
EndProcedure

**GUI_1.pb**

Code: Alles auswählen

EnableExplicit
IncludeFile "Common.pb"
Global Anzeige$

Procedure Send_Delay (Befehl$)
Define i.i
For i= 1 To Len(Befehl$)
 If WriteSerialPortString(1, Mid(Befehl$, i, 1))
 ;PrintN("Ok")
 Else
 Print("Fehler:")
 PrintN(Str(SerialPortError(1)))
 EndIf
 Delay(5)
Next i
EndProcedure

Procedure Mode0000()
Send_Delay("mode0000"+Chr(13))
Delay(200)
Send_Delay("mode0000"+Chr(13))
Anzeige$=Anzeige$+"MODE0000"+Chr(13)
EndProcedure

Procedure Mode0001()
Send_Delay("mode0001"+Chr(13))
Anzeige$=Anzeige$+"MODE0001"+Chr(13)
EndProcedure

Procedure.s ReadSerialPortString()
Define  bInput.b, Puffer$
While AvailableSerialPortInput ( 1 ) > 0 ; Solange Empfangen wie Daten vorhanden sind.
  ReadSerialPortData ( 1 , @bInput , SizeOf ( BYTE ) ) ; Byte abholen.
  Puffer$=Puffer$+Chr(bInput)
Wend 
ProcedureReturn Puffer$
EndProcedure

Procedure Werte_abfragen(Anzahl.w)
Define Test$, i.w
Delay(1000)
Test$=ReadSerialPortString() ;die erste Sekunde wird nicht berücksichtigt
For i=1 To Anzahl
Delay(1000)
Test$=ReadSerialPortString()
Anzeige$=Anzeige$+Test$
SetGadgetText(#txtAnzeige,Anzeige$)
Next i
EndProcedure

Define Ereignis.w
Define WindowID.w
Define GadgetID.w
Define Ereignistyp.w
Anzeige$=""
Open_Window_0()
Repeat ; Start of the event loop
  Ereignis = WaitWindowEvent() ; This line waits until an event is received from Windows
  WindowID = EventWindow() ; The Window where the event is generated, can be used in the gadget procedures
  GadgetID = EventGadget() ; Is it a gadget event?
  Ereignistyp = EventType() ; The event type
  If Ereignis = #PB_Event_Gadget
    If      GadgetID = #btnOSP
            OpenSerialPort(1, "COM6", 19200, #PB_SerialPort_NoParity, 8, 1, #PB_SerialPort_NoHandshake, 1024, 1024)
    ElseIf GadgetID = #btnM0001
            Mode0001()
    ElseIf GadgetID = #btnM0000
            Mode0000()
    ElseIf GadgetID = #btnGET
            Werte_abfragen(10)
    ElseIf GadgetID = #btnExit
      End
    EndIf
    SetGadgetText(#txtAnzeige, Anzeige$)
  EndIf
Until Ereignis = #PB_Event_CloseWindow ; End of the event loop
CloseSerialPort(1)
End

Das Hauptprogramm öffnet die RS232-schnittstelle zu einem Messgerät, schaltet verschiedene Modi um, und holt sich auch ein paar Daten - alles erfolgreich.
Aber: Wenn ich die Messdaten hole, dauert das wegen der Delay()-Funktionen natürlich absichtlich etliche Sekunden (ist Absicht, das Gerät sendet automatisch alle 1000 ms Informationen); während dieser Zeit ist der Button "Get Data" im "Angeklickt"-Zustand. Nun meine Fragen:

1.) Warum schaltet der Button während dieser Zeit nicht wieder um, er wurde ja bereits gedrückt?
2.) Warum nimmt der Button / das Programm, obwohl er wie gedrückt erscheint, scheinbar noch Clicks an (wenn ich mehrmals darauf drücke, werden mehrmals die 10 Datensätze abgefragt?
3.) Muss ich den Button in dem Moment zurückprogrammieren?
4.) Kann man die Mehrfach-Clicks unterbinden, z. B. indem man "ausgraut", also inaktiviert?
5.) Komme ich hier evtl. voll in die Thread-Problematik rein?

Für Hilfe wäre ich sehr dankbar,

Euer


Tom123

Verfasst: 13.02.2009 11:55
von Andesdaf
> 1.) Warum schaltet der Button während dieser Zeit nicht wieder um, er wurde ja bereits gedrückt?
Ich denke das hat etwas mit den Delays zu tun da die die gesamte Programmausführung
anhalten...

> 4.) Kann man die Mehrfach-Clicks unterbinden, z. B. indem man "ausgraut", also inaktiviert?
DisableGadget()

Verfasst: 13.02.2009 12:26
von ts-soft

Code: Alles auswählen

Define Ereignis.w
Define WindowID.w
Define GadgetID.w
Define Ereignistyp.w 
Was soll das? Du programmiert hier nicht für ein 8-Bit System :mrgreen:
Der schnellste Typ ist Integer und denn sollteste auch immer nehmen für
Ganzzahlen, es sei den Du brauchst aus bestimmten Gründen was anderes.
Das spart keinen Memory solange es nicht in Structuren oder ähnlich
verwendet wird, es kostet nur Zeit und führt zu Fehlern, weil die Ereignisse
dort garnicht hineinpassen.

Ansonsten kannste das mit Delay in einer GUI-Anwendung vergessen, das
kann nichts werden. Du müßtest die GUI solange komplett Disablen und
tote Fenster sind unschön.

Entweder eine Timerprocedure, die alle 1000ms angesprungen wird und
prüft ob sie jetzt was am port machen soll, oder entsprechende timevar
im eventloop, der per elapsedmillisecond() abfragt ob 1000 ms um sind
und es was zu tun gibt.

Dein derzeitiger Codestil entspricht nicht dem eines Windowsprogrammes,
eher eines DOS oder Consolenprogrmmes :wink:

Gruß
Thomas

Verfasst: 13.02.2009 13:05
von Tom123
:shock:

Okok, scheinbar komme ich also von dem Delphi/VB-Trip nicht mehr runter.

Ist wohl besser da zu bleiben...

Herzlichen Dank für die Tipps,


Tom123

Verfasst: 13.02.2009 13:15
von ts-soft
Du solltest lediglich delays in Proceduren vermeiden. Die Wartezeit im
Eventloop messen, damit das Fensterhandling weiter funktioniert!

WaitWindowEvent(timeout) nutzen, bei 0 Ereignis prüfen ob die Zeit um ist,
um den seriellen port erneut zu prüfen usw., dann funktioniert auch alles wie
gewollt.

Wenn das noch zu kompliziert ist, dann nimm ein

Code: Alles auswählen

DisableWindow(0, #True)
mit rein, solange Du in der Procedure mit Delay bist.

Ist doch kein Grund gleich die Flinte ins Korn zu werfen :wink:

Verfasst: 13.02.2009 18:08
von Tom123
Hab es mit der DoEvents()-Prozedur wie gewünscht hinbekommen :mrgreen:

Schönes Wochenende,


Tom123