Seite 1 von 3

UngültigerLesezugriff bei Examine Mouse und Keyboard

Verfasst: 21.04.2014 10:40
von Sauer-RAM
Guten morgen.

Ich programmiere gerade einen SleepHelper der die beste Aufwachzeit errechnet. Eigentlich geht es mir bei dem Programm nicht um die Funktion an sich sonder ausschließlich um die GUI (Ich will danach was ähnliches Programmieren, mit einer noch übertriebeneren GUI und ich will da erstmal ein paar Erfahrungen sammeln). Und genau die bugt gerade umher.
Manchmal bekomme ich ein Lesefehler bei ExamineMouse() und manchmal bei FlipBuffers() nachdem ich per ESC das Programm geschlossen habe.

Ich schick euch mal den Code, vielleicht habt ihr ja eine Idee was daran nicht stimm soll...

Code: Alles auswählen

Global From = #True
Global MouseOverINPUTButton = #False

Enumeration
  #TitelFont
  #StandartUmrandungsFont
  #DATAUmrandungsFont
EndEnumeration

#StandartFontColor = 16776960
#StandartFrontColor = 16776960
#Backcolor = 5456896
#MouseOverButtonColor = 10190848


#EEGUmrandungsTextHoehe = 15
#EEG1UmrandungsTextBreite = 70
#EEG2UmrandungsTextBreite = 98
#SYNCUmrandungsTextBreite = 98
#DATAUmrandungsTextHoehe = 19
#DATAINPUTUmrandungsTextBreite = 90
#DATAOUTPUTUmrandungsTextBreite= 99
#DATAINPUTFROMLength = 28
#DATAINPUTTOLength = 14

Procedure Error(Erg,String.s)
  If Erg = 0
    MessageRequester("Error",String)
    End
  EndIf
  ProcedureReturn Erg
EndProcedure
Global Window

Window = Error(OpenWindow(#PB_Any,30,30,1200,650,"Sleep Helper"),"Konnte Fenster nicht öffnen")
Error(InitSprite(),"Konnte Sprites nicht initiieren")
Error(OpenWindowedScreen(WindowID(Window),0,0,1200,650),"Konnte den Screen nicht öffnen")
Error(InitMouse(),"Konnte die Maus nicht initiieren")
Error(InitKeyboard(),"Konnte die Tastatur nicht initiieren")
Error(LoadFont(#TitelFont,"Consolas", 24, #PB_Font_Bold),"Konnte Titelfont nicht laden")
Error(LoadFont(#StandartUmrandungsFont,"Consolas", 10),"Konnte die Umrandungsfont nicht laden")
Error(LoadFont(#DATAUmrandungsFont,"Consolas", 12),"Konnte die DATA-Umrandungsfont nicht laden")


Procedure Wave(Param)
  Wavesprite = Error(CreateSprite(#PB_Any,900,160),"Konnte das Wellensprite nicht erstellen")
EndProcedure

Procedure MouseHandler(Param)
  WhatThaFuck:
  Repeat
    If 0 = ExamineMouse()
      Debug "HELP"
      Delay(50)
      Goto WhatThaFuck
    EndIf
    MouseX = WindowMouseX(Window)
    MouseY = WindowMouseY(Window)

    If MouseButton(#PB_MouseButton_Left)   ;Linke Maustaste gedrückt
      If MouseX < 827 And MouseX > 813     ;Vertikal im Bereich der Checkboxen vom DATA-INPUT
        If MouseY < 77 And MouseY > 63     ;Es wurde im Bereich der FROM-Checkbox geklickt
          From = #True
        ElseIf MouseY < 117 And MouseY > 103  ;Es wurde im Bereich der TO-Checkbox geklickt
          From = #False
        EndIf
      EndIf
    EndIf
    
    If Mousex < 1180 And MouseX > 1090 And MouseY < 105 And MouseY > 75   ;MouseOver DATAINPUT Button
      MouseOverINPUTButton = #True
    Else
      MouseOverINPUTButton = #False
    EndIf
      
    Delay(5)
  ForEver
EndProcedure

Procedure KeyboardHandler(Param)
  Repeat
    ExamineKeyboard()
    If KeyboardPushed(#PB_Key_Escape)
      End
    EndIf
    Delay(5)
  ForEver
EndProcedure



CreateThread(@MouseHandler(),0)
CreateThread(@KeyboardHandler(),0)
Repeat
  StartDrawing(ScreenOutput())
  FrontColor(#StandartFrontColor)
  Box(0,0,1200,650,#Backcolor)      ;Hintergrund zeichnen
  If MouseOverINPUTButton = #True   ;MouseOver DATAINPUT Button
    Box(1090,75,90,30,#MouseOverButtonColor)
  EndIf
  DrawingMode(#PB_2DDrawing_Outlined|#PB_2DDrawing_Transparent)
  Box(10,40,590,150)               ;Obere EEG-Umrandung
  Box(10,240,590,150)               ;Untere EEG-Umrandung
  Box(610,40,130,350)               ;SYNC-Umrandung
  Box(750,520,440,120)              ;DATA-Output-Umrandung
  Box(750,40,440,100)               ;DATA-Input-Umrandung
  Box(860,60,220,60)                ;DATA-Input innere Umrandung
  Box(1090,75,90,30)                ;DATA-Input Button
  Circle(820,70,7)                  ;Die äußeren Kreise der Checkboxen
  Circle(820,110,7)
  Box(9,399,632,242)                ;Äußere Hülle der Liste
  Box(10,400,630,240)               ;Innere Hülle der Liste
  Box(10,424,630,2)                 ;Die Unterteilungen der Ersten Zeile Zeichnen
  Box(40,400,2,240)                  ;# Spalte
  Box(180,400,2,240)                 ;START Spalte
  Box(320,400,2,240)                 ;END Spalte
  Box(440,400,2,240)                 ;LENGTH Spalte  
  Box(690,55,40,320)                ;SYNC-Ladebalken zeichnen
  Box(910,150,260,120)              ;Sinuserklärungsbox zeichnen
  
  For n = 1 To 8
    Box(10,424 + n*24,630,1)
  Next
  DrawingMode(#PB_2DDrawing_Transparent)
  
  If From = #True           ;Zeichnen der Inneren Kreise der Checkboxen
    Circle(820,70,4)
    LineXY(827,70,832,70)
    LineXY(832,70,852,90)
  Else
      Circle(820,110,4)
      LineXY(827,110,832,110)
      LineXY(832,110,852,90)
  EndIf
  LineXY(852,90,860,90)
    
  
  Box(12,30,#EEG1UmrandungsTextBreite + 5,#EEGUmrandungsTextHoehe,#Backcolor)     ;Obere EEG-Umrandung ausschneiden
  Box(12,230,#EEG2UmrandungsTextBreite + 6,#EEGUmrandungsTextHoehe,#Backcolor)    ;Untere EEG-Umrandung ausschneiden
  Box(612,30,#SYNCUmrandungsTextBreite + 6,#EEGUmrandungsTextHoehe,#Backcolor)    ;SYNC-Umrandung ausschneiden
  Box(752,510,#DATAOUTPUTUmrandungsTextBreite + 6,#DATAUmrandungsTextHoehe,#Backcolor) ;DATAOUTPUT-Umrandung ausschneiden
  Box(752,30,#DATAINPUTUmrandungsTextBreite + 6,#DATAUmrandungsTextHoehe,#Backcolor) ;DATAINPUT-Umrandung ausschneiden
  
  DrawingFont(FontID(#TitelFont))                                       ;Titelfont
  DrawText(20,-3,"SLEEP HELPER",#StandartFontColor)                     ;Titel zeichnen
  
  DrawingFont(FontID(#StandartUmrandungsFont))                          ;StandartUmrandungsfont setzen
  DrawText(15,32,"EEG TARGET",#StandartFontColor)                       ;Die Umrandungsbeschriftungen zeichnen
  DrawText(15,232,"EEG CALCULATED",#StandartFontColor)
  DrawText(615,32,"SYNCRONIZATION",#StandartFontColor)
  DrawText(1107,82,"SIMULATE",#StandartFontColor)
  DrawText(807 - #DATAINPUTFROMLength,63,"FROM")
  DrawText(807 - #DATAINPUTTOLength,103,"TO")
  DrawText(750,160,"LIGHT (STATE I+II)")
  DrawingFont(FontID(#DATAUmrandungsFont))
  DrawText(20,402,"#")
  DrawText(88,402,"START")
  DrawText(237,402,"END")
  DrawText(354,402,"LENGTH")
  DrawText(456,402,"TACTICAL ASSESSMENT")
  ;DrawText(450,402,"TACTICAL ASSESSMENT")
;   Debug "INPUT"
;   Debug TextWidth("DATA INPUT")
;   Debug "output"
;   Debug TextWidth("DATA OUTPUT")
;   Debug "height"
;   Debug TextHeight("DATA INPUT")  
  DrawText(755,510,"DATA OUTPUT",#StandartFontColor)
  DrawText(755,30,"DATA INPUT",#StandartFontColor)
  ;DrawText(
  
  StopDrawing()
  FlipBuffers()
  
  If WindowEvent() = #PB_Event_CloseWindow
    End
  EndIf
ForEver
PS: Ist natürlich noch nicht fertig. Wenn es soweit ist, stell ich hier gerne auch mal das Endprodukt rein.

Danke schonmal für die Hilfe^^

Viele Grüße

Sauer-RAM

Re: UngültigerLesezugriff bei Examine Mouse und Keyboard

Verfasst: 21.04.2014 12:33
von NicTheQuick
Eigentlich ganz einfach. Die ganzen DirectX- bzw. OpenGL-spezifischen Befehle sind nicht Threadfähig. Zumindest war das noch so als ich das Zeugs öfter mal benutzt hatte. Falls es jetzt nicht mehr so ist, lasse ich mich auch gerne eines besseren belehren.

Re: UngültigerLesezugriff bei Examine Mouse und Keyboard

Verfasst: 21.04.2014 13:09
von STARGÅTE
Das ist auch immer noch so.
Hinweis: Benutzen Sie innerhalb von Threads kein DirectX (MS Windows Einschränkung)!
Und Libraries die DirectX nutzen sind:
Screen, Sprite, Sound, Joystick, Keyboard, Mouse

Re: UngültigerLesezugriff bei Examine Mouse und Keyboard

Verfasst: 21.04.2014 15:12
von Sauer-RAM
Oh... Das hab ich nicht gewusst.. Danke ^^

Was heißt das Threadverbot eigentlich genau? Ich kann nicht threadübergreifend im selben Output arbeiten (Also Screen, und den dazugehörigen Mausbehandlungsteil in verschiedenen Threads) aber ich kann nebenher in nem Thread ein Sprite erstellen und das dem Hauptthread übergeben, oder ganz genereles Threadverbot für alles was irgendwie mit DirectX zu tun hat?

Ich wollte eigentlich in nem Thread permanent ein Sprite zeichnen lassen in dem sich eine Sinuswelle bewegt und dann dieses Sprite dann durch den Hauptthread am Bildschirm anzeigen. Wäre das möglich?

Re: UngültigerLesezugriff bei Examine Mouse und Keyboard

Verfasst: 21.04.2014 15:21
von STARGÅTE
Sauer-RAM hat geschrieben:Was heißt das Threadverbot eigentlich genau?
Alle DirectX Befehle dürfen nur in einem einzigen Thread stecken, nämlich dem Hauptprogramm.
Sauer-RAM hat geschrieben:Ich wollte eigentlich in nem Thread permanent ein Sprite zeichnen lassen in dem sich eine Sinuswelle bewegt und dann dieses Sprite dann durch den Hauptthread am Bildschirm anzeigen. Wäre das möglich?
Nein.

Da du das Sprite es nur in jedem Frame siehst, reicht es auch aus, die Sinuswelle in jedem Frame zu zeichnen.
Dafür brauchst du keinen Thread.

Re: UngültigerLesezugriff bei Examine Mouse und Keyboard

Verfasst: 21.04.2014 18:20
von captain_hesse
Hallo
der Fehler liegt darin das du das Programm einfach im Thread mit end beendest während das Hauptprogramm gerade eine Schreibaktion im Bildschirmspeicher vornimmt. Das ist so als wenn du gerade was auf ein Blatt Papier schreiben willst und dann kommt jemand und zieht dir das Blatt ganz plötzlich weg dann malst du auf den Tisch. Du solltest den end Befehl nicht in einem Thread verwenden weil sonst das Programm wahrscheinlich nicht ordentlich beendet wird. Am besten beendest du das Programm immer am ende von der Eventschleife des Hauptprogramms wenn alle Befehle soweit ausgeführt wurden. Ich habe dein obiges Beispiel mal ein wenig abgeändert der Thread beendet nun nicht mehr das Programm sondern schickt ein Signal ans Hauptprogramm und dann wird erst beendet.

Code: Alles auswählen

Global From = #True
Global MouseOverINPUTButton = #False

Global signal=#False

Enumeration
  #TitelFont
  #StandartUmrandungsFont
  #DATAUmrandungsFont
EndEnumeration

#StandartFontColor = 16776960
#StandartFrontColor = 16776960
#Backcolor = 5456896
#MouseOverButtonColor = 10190848


#EEGUmrandungsTextHoehe = 15
#EEG1UmrandungsTextBreite = 70
#EEG2UmrandungsTextBreite = 98
#SYNCUmrandungsTextBreite = 98
#DATAUmrandungsTextHoehe = 19
#DATAINPUTUmrandungsTextBreite = 90
#DATAOUTPUTUmrandungsTextBreite= 99
#DATAINPUTFROMLength = 28
#DATAINPUTTOLength = 14

Procedure Error(Erg,String.s)
  If Erg = 0
    MessageRequester("Error",String)
    End
  EndIf
  ProcedureReturn Erg
EndProcedure
Global Window

Window = Error(OpenWindow(#PB_Any,30,30,1200,650,"Sleep Helper"),"Konnte Fenster nicht öffnen")
Error(InitSprite(),"Konnte Sprites nicht initiieren")
Error(OpenWindowedScreen(WindowID(Window),0,0,1200,650),"Konnte den Screen nicht öffnen")
Error(InitMouse(),"Konnte die Maus nicht initiieren")
Error(InitKeyboard(),"Konnte die Tastatur nicht initiieren")
Error(LoadFont(#TitelFont,"Consolas", 24, #PB_Font_Bold),"Konnte Titelfont nicht laden")
Error(LoadFont(#StandartUmrandungsFont,"Consolas", 10),"Konnte die Umrandungsfont nicht laden")
Error(LoadFont(#DATAUmrandungsFont,"Consolas", 12),"Konnte die DATA-Umrandungsfont nicht laden")


Procedure Wave(Param)
  Wavesprite = Error(CreateSprite(#PB_Any,900,160),"Konnte das Wellensprite nicht erstellen")
EndProcedure

Procedure MouseHandler(Param)
  WhatThaFuck:
  Repeat
    If 0 = ExamineMouse()
      Debug "HELP"
      Delay(50)
      Goto WhatThaFuck
    EndIf
    MouseX = WindowMouseX(Window)
    MouseY = WindowMouseY(Window)

    If MouseButton(#PB_MouseButton_Left)   ;Linke Maustaste gedrückt
      If MouseX < 827 And MouseX > 813     ;Vertikal im Bereich der Checkboxen vom DATA-INPUT
        If MouseY < 77 And MouseY > 63     ;Es wurde im Bereich der FROM-Checkbox geklickt
          From = #True
        ElseIf MouseY < 117 And MouseY > 103  ;Es wurde im Bereich der TO-Checkbox geklickt
          From = #False
        EndIf
      EndIf
    EndIf
    
    If Mousex < 1180 And MouseX > 1090 And MouseY < 105 And MouseY > 75   ;MouseOver DATAINPUT Button
      MouseOverINPUTButton = #True
    Else
      MouseOverINPUTButton = #False
    EndIf
      
    Delay(5)
  ForEver
EndProcedure

Procedure KeyboardHandler(Param)
  Repeat
    ExamineKeyboard()
    If KeyboardPushed(#PB_Key_Escape)
      signal=#True
      ;End
    EndIf
    Delay(5)
  ForEver
EndProcedure



Global maus=CreateThread(@MouseHandler(),0)
Global keyb=CreateThread(@KeyboardHandler(),0)

Repeat
  StartDrawing(ScreenOutput())
  FrontColor(#StandartFrontColor)
  Box(0,0,1200,650,#Backcolor)      ;Hintergrund zeichnen
  If MouseOverINPUTButton = #True   ;MouseOver DATAINPUT Button
    Box(1090,75,90,30,#MouseOverButtonColor)
  EndIf
  DrawingMode(#PB_2DDrawing_Outlined|#PB_2DDrawing_Transparent)
  Box(10,40,590,150)               ;Obere EEG-Umrandung
  Box(10,240,590,150)               ;Untere EEG-Umrandung
  Box(610,40,130,350)               ;SYNC-Umrandung
  Box(750,520,440,120)              ;DATA-Output-Umrandung
  Box(750,40,440,100)               ;DATA-Input-Umrandung
  Box(860,60,220,60)                ;DATA-Input innere Umrandung
  Box(1090,75,90,30)                ;DATA-Input Button
  Circle(820,70,7)                  ;Die äußeren Kreise der Checkboxen
  Circle(820,110,7)
  Box(9,399,632,242)                ;Äußere Hülle der Liste
  Box(10,400,630,240)               ;Innere Hülle der Liste
  Box(10,424,630,2)                 ;Die Unterteilungen der Ersten Zeile Zeichnen
  Box(40,400,2,240)                  ;# Spalte
  Box(180,400,2,240)                 ;START Spalte
  Box(320,400,2,240)                 ;END Spalte
  Box(440,400,2,240)                 ;LENGTH Spalte  
  Box(690,55,40,320)                ;SYNC-Ladebalken zeichnen
  Box(910,150,260,120)              ;Sinuserklärungsbox zeichnen
  
  For n = 1 To 8
    Box(10,424 + n*24,630,1)
  Next
  DrawingMode(#PB_2DDrawing_Transparent)
  
  If From = #True           ;Zeichnen der Inneren Kreise der Checkboxen
    Circle(820,70,4)
    LineXY(827,70,832,70)
    LineXY(832,70,852,90)
  Else
      Circle(820,110,4)
      LineXY(827,110,832,110)
      LineXY(832,110,852,90)
  EndIf
  LineXY(852,90,860,90)
    
  
  Box(12,30,#EEG1UmrandungsTextBreite + 5,#EEGUmrandungsTextHoehe,#Backcolor)     ;Obere EEG-Umrandung ausschneiden
  Box(12,230,#EEG2UmrandungsTextBreite + 6,#EEGUmrandungsTextHoehe,#Backcolor)    ;Untere EEG-Umrandung ausschneiden
  Box(612,30,#SYNCUmrandungsTextBreite + 6,#EEGUmrandungsTextHoehe,#Backcolor)    ;SYNC-Umrandung ausschneiden
  Box(752,510,#DATAOUTPUTUmrandungsTextBreite + 6,#DATAUmrandungsTextHoehe,#Backcolor) ;DATAOUTPUT-Umrandung ausschneiden
  Box(752,30,#DATAINPUTUmrandungsTextBreite + 6,#DATAUmrandungsTextHoehe,#Backcolor) ;DATAINPUT-Umrandung ausschneiden
  
  DrawingFont(FontID(#TitelFont))                                       ;Titelfont
  DrawText(20,-3,"SLEEP HELPER",#StandartFontColor)                     ;Titel zeichnen
  
  DrawingFont(FontID(#StandartUmrandungsFont))                          ;StandartUmrandungsfont setzen
  DrawText(15,32,"EEG TARGET",#StandartFontColor)                       ;Die Umrandungsbeschriftungen zeichnen
  DrawText(15,232,"EEG CALCULATED",#StandartFontColor)
  DrawText(615,32,"SYNCRONIZATION",#StandartFontColor)
  DrawText(1107,82,"SIMULATE",#StandartFontColor)
  DrawText(807 - #DATAINPUTFROMLength,63,"FROM")
  DrawText(807 - #DATAINPUTTOLength,103,"TO")
  DrawText(750,160,"LIGHT (STATE I+II)")
  DrawingFont(FontID(#DATAUmrandungsFont))
  DrawText(20,402,"#")
  DrawText(88,402,"START")
  DrawText(237,402,"END")
  DrawText(354,402,"LENGTH")
  DrawText(456,402,"TACTICAL ASSESSMENT")
  ;DrawText(450,402,"TACTICAL ASSESSMENT")
;   Debug "INPUT"
;   Debug TextWidth("DATA INPUT")
;   Debug "output"
;   Debug TextWidth("DATA OUTPUT")
;   Debug "height"
;   Debug TextHeight("DATA INPUT")  
  DrawText(755,510,"DATA OUTPUT",#StandartFontColor)
  DrawText(755,30,"DATA INPUT",#StandartFontColor)
  ;DrawText(
  
  StopDrawing()
  FlipBuffers()
  
  If WindowEvent() = #PB_Event_CloseWindow Or signal=#True
    KillThread(maus)
    KillThread(keyb)
    End
  EndIf
ForEver
Gruß Armin

Re: UngültigerLesezugriff bei Examine Mouse und Keyboard

Verfasst: 21.04.2014 18:25
von NicTheQuick
Das "End" ist aber nicht das Problem, sondern dass man einfach kein DirectX in einem anderen Thread als dem Hauptthread benutzen darf.

Und das bisschen Tastatur- und Mausabfrage hindern ja den Programmfluss nicht. Wenn tatsächlich noch viel berechnet werden muss nach einer Eingabe, dann kann man die Eingabe vom Hauptthread aus in eine Queue setzen und von einem zweiten Thread abarbeiten lassen. Dieser kann dann wiederum Werte ändern, die dann vom Hauptthread übernommen werden. Es geht aber sicherlich noch geschickter als mit Queues.

Re: UngültigerLesezugriff bei Examine Mouse und Keyboard

Verfasst: 21.04.2014 18:26
von ts-soft
@captain_hesse
Das ändert nichts daran, das Threads für DirectX nicht möglich ist. Fehler bleibt bestehen und wird durch Deine
Änderung auch nicht behoben :wink:

Re: UngültigerLesezugriff bei Examine Mouse und Keyboard

Verfasst: 21.04.2014 18:32
von captain_hesse
Na ja aber nach der Änderung bekomme ich bei mir keine Fehlermeldung mehr wenn ich das Programm mit Escape beende.

Re: UngültigerLesezugriff bei Examine Mouse und Keyboard

Verfasst: 21.04.2014 18:39
von ts-soft
captain_hesse hat geschrieben:Na ja aber nach der Änderung bekomme ich bei mir keine Fehlermeldung mehr wenn ich das Programm mit Escape beende.
Das ist ja das Problem bei Threads. Da hilft kein Try & Error. Der Fehler kann nach einmaligem Starten auftreten oder wenns der Zufall will,
erst nach dem 100sten mal. Bei Threads sollte man sich unbedingt an die Dokumentation halten. Bei mir kam der Fehler bereits beim ersten
Start, danach lief es ein paar mal ohne.

Try & Error ist oft lehrreich, aber bei Thread-Programmierung kein gangbarer Weg!