Seite 1 von 1

Eigenes Programm fernsteuern

Verfasst: 18.01.2009 06:25
von ts-soft
Aufgrund einer Nachfrage hier: http://www.purebasic.fr/german/viewtopi ... 090#228090
und weil die Thematik doch öfter benötigt wird, hab ich mal ein weiteres
Beispiel zur Kommunikation zwischen 2 PB Programmen geschrieben.
Im Beispiel geht die Kommunikation nur in eine Richtung.

Wichtig: Immer erst den Fernseher :wink: starten, danach die
Fernbedienung.

Code Fernseher:

Code: Alles auswählen

; Beispiel ein Programm fernzusteuern
; PB 4.30, Windows only
; Autor: Thomas Schulz aka ts-soft
; 18. Januar 2009

; Hinweis: dieses Programm ist vor der Fernbedienung zu starten!

EnableExplicit

Import ""
  PB_Gadget_SendGadgetCommand(hWnd, EventType)
EndImport 

#MsgRemote = #WM_USER + 500

Structure myhwnds
  hWnd.i
  BtnRed.i
  BtnGreen.i
  BtnBlue.i
EndStructure

Define HandleMap, i, *mem.myhwnds

Procedure CreateSharedMemory(Name.s, Size)
  Shared HandleMap
  HandleMap = CreateFileMapping_(#INVALID_HANDLE_VALUE, 0, #PAGE_READWRITE|#SEC_COMMIT|#SEC_NOCACHE, 0, Size, @Name)
  If HandleMap
    ProcedureReturn MapViewOfFile_(HandleMap, #FILE_MAP_ALL_ACCESS, 0, 0, 0)
  EndIf
EndProcedure

Procedure CloseSharedMemory(MemoryAddress)
  Shared HandleMap
  UnmapViewOfFile_(MemoryAddress)
  CloseHandle_(HandleMap)
EndProcedure

Enumeration ; Gadgets
  #Mattscheibe
  #BtnRed
  #BtnGreen
  #BtnBlue
EndEnumeration

Procedure ErstelleFarbfeld(Nr, w = 30, h = 30, c = 0)
  CreateImage(Nr, w, h)
  StartDrawing(ImageOutput(Nr))
  Select Nr
    Case #Mattscheibe
      FrontColor(c)
    Case #BtnRed
      FrontColor(#Red)
    Case #BtnGreen
      FrontColor(#Green)
    Case #BtnBlue
      FrontColor(#Blue)
  EndSelect
  Box(0, 0, w, h)
  StopDrawing()
EndProcedure

If OpenWindow(0, #PB_Ignore, #PB_Ignore, 200, 190, "Television ;)", #PB_Window_SystemMenu)
  ImageGadget(#Mattscheibe, 5, 5, 190, 140, 0)
  ErstelleFarbfeld(#BtnRed)
  ButtonImageGadget(#BtnRed, 55, 150, 30, 30, ImageID(#BtnRed), #PB_Button_Toggle)
  ErstelleFarbfeld(#BtnGreen)
  ButtonImageGadget(#BtnGreen, 85, 150, 30, 30, ImageID(#BtnGreen), #PB_Button_Toggle)
  ErstelleFarbfeld(#BtnBlue)
  ButtonImageGadget(#BtnBlue, 115, 150, 30, 30, ImageID(#BtnBlue), #PB_Button_Toggle)  
  
  SetGadgetState(#BtnRed, #True)
  ErstelleFarbfeld(#Mattscheibe, GadgetWidth(#Mattscheibe), GadgetHeight(#Mattscheibe), #Red)
  SetGadgetState(#Mattscheibe, ImageID(#Mattscheibe))

  ; wir erstellen ein SharedMemory der auf den Namen "myfernseher" hört
  *mem = CreateSharedMemory("myfernseher", SizeOf(myhwnds))
  ; und belegen den Speicher mit den nötigen Handles
  If *mem
    With *mem
      \hWnd     = WindowID(0)
      \BtnRed   = GadgetID(#BtnRed)
      \BtnGreen = GadgetID(#BtnGreen)
      \btnBlue  = GadgetID(#BtnBlue)
    EndWith
  EndIf
  
  Repeat
    Select WaitWindowEvent()
      Case #PB_Event_CloseWindow
        Break
      Case #MsgRemote
        ; hier werden die Messages der Fernbedienung weitergeleitet
        PB_Gadget_SendGadgetCommand(EventwParam(), EventlParam()) 
        
      Case #PB_Event_Gadget
        ; wenn Buttongedrückt, erstmal alle enttoggln
        If EventGadget() >= #BtnRed And EventGadget() <= #BtnBlue
          For i = #BtnRed To #BtnBlue
            SetGadgetState(i, #False)
          Next
        EndIf
        Select EventGadget()
          Case #BtnRed
            SetGadgetState(#BtnRed, #True)
            ErstelleFarbfeld(#Mattscheibe, GadgetWidth(#Mattscheibe), GadgetHeight(#Mattscheibe), #Red)
            SetGadgetState(#Mattscheibe, ImageID(#Mattscheibe))           
          Case #BtnGreen
            SetGadgetState(#BtnGreen, #True)
            ErstelleFarbfeld(#Mattscheibe, GadgetWidth(#Mattscheibe), GadgetHeight(#Mattscheibe), #Green)
            SetGadgetState(#Mattscheibe, ImageID(#Mattscheibe))           
          Case #BtnBlue
            SetGadgetState(#BtnBlue, #True)
            ErstelleFarbfeld(#Mattscheibe, GadgetWidth(#Mattscheibe), GadgetHeight(#Mattscheibe), #Blue)
            SetGadgetState(#Mattscheibe, ImageID(#Mattscheibe))           
        EndSelect
    EndSelect
  ForEver
EndIf

CloseSharedMemory(*mem)
Code Fernbedienung:

Code: Alles auswählen

; Beispiel ein Programm fernzusteuern
; PB 4.30, Windows only
; Autor: Thomas Schulz aka ts-soft
; 18. Januar 2009

EnableExplicit

#MsgRemote = #WM_USER + 500
#TimeOut = 6000

Structure myhwnds
  hWnd.i
  BtnRed.i
  BtnGreen.i
  BtnBlue.i
EndStructure

Define HandleMap, *mem.myhwnds, time

Procedure OpenSharedMemory(Name.s)
  Shared HandleMap
  HandleMap = OpenFileMapping_(#FILE_MAP_ALL_ACCESS, 0, @Name)
  If HandleMap
    ProcedureReturn MapViewOfFile_(HandleMap, #FILE_MAP_ALL_ACCESS, 0, 0, 0)
  EndIf
EndProcedure

Procedure CloseSharedMemory(MemoryAddress)
  Shared HandleMap
  UnmapViewOfFile_(MemoryAddress)
  CloseHandle_(HandleMap)
EndProcedure

; Als erstes Versuchen wir Kontakt aufzunehmen, indem wir versuchen den SharedMemory zu öffnen
time = ElapsedMilliseconds() + #TimeOut
Repeat
  *mem = OpenSharedMemory("myfernseher")
  Delay(10)
Until *mem Or ElapsedMilliseconds() > time

If Not *mem
  MessageRequester("", "Fernseher ist leider aus")
  End
EndIf

Enumeration ; Gadgets
  #BtnRed
  #BtnGreen
  #BtnBlue
EndEnumeration

Procedure ErstelleFarbfeld(Nr)
  CreateImage(Nr, 30, 30)
  StartDrawing(ImageOutput(Nr))
  Select Nr
    Case #BtnRed
      FrontColor(#Red)
    Case #BtnGreen
      FrontColor(#Green)
    Case #BtnBlue
      FrontColor(#Blue)
  EndSelect
  Box(0, 0, 30, 30)
  StopDrawing()
EndProcedure

If OpenWindow(0, #PB_Ignore, #PB_Ignore, 60, 40, "Remote", #PB_Window_SystemMenu)
  ErstelleFarbfeld(#BtnRed)
  ButtonImageGadget(#BtnRed, 5, 5, 30, 30, ImageID(#BtnRed))
  ErstelleFarbfeld(#BtnGreen)
  ButtonImageGadget(#BtnGreen, 40, 5, 30, 30, ImageID(#BtnGreen))
  ErstelleFarbfeld(#BtnBlue)
  ButtonImageGadget(#BtnBlue, 75, 5, 30, 30, ImageID(#BtnBlue))  
  
  Repeat
    Select WaitWindowEvent()
      Case #PB_Event_CloseWindow
        PostMessage_(*mem\hWnd, #WM_CLOSE, 0, 0); Achtung, Fernseher wird auch ausgeschaltet
        Break
      Case #PB_Event_Gadget
        ; je nach Button senden wir die entsprechende Message
        ; die Handles entnehmen wir dem SharedMemory
        ; weitere Überprüfungen sparen wir uns in diesem Beispiel
        Select EventGadget()
          Case #BtnRed
            PostMessage_(*mem\hWnd, #MsgRemote, *mem\BtnRed, #PB_EventType_LeftClick)
          Case #BtnGreen
            PostMessage_(*mem\hWnd, #MsgRemote, *mem\BtnGreen, #PB_EventType_LeftClick)
          Case #BtnBlue
            PostMessage_(*mem\hWnd, #MsgRemote, *mem\BtnBlue, #PB_EventType_LeftClick)
        EndSelect
    EndSelect
  ForEver
EndIf

CloseSharedMemory(*mem)
Es gibt nur 3 recht eintönige Programme :mrgreen:

Viel Spaß damit, ich hoffe es ist nützlich

Grüsse
Thomas

PS: Fernseher geht immer nur der zuletzt gestartete, Fernbedienungen
gehen alle :wink:

Verfasst: 18.01.2009 09:52
von 7x7
Schönes Beispiel! :)

Edit: Nanu? Hat genau 1x funktioniert. Jetzt (2ter und weitere Starts) kommen nur noch 2 leere Fenster (Television & Remote)

Re: Eigenes Programm fernsteuern

Verfasst: 18.01.2009 10:38
von Little John
ts-soft hat geschrieben:Es gibt nur 3 recht eintönige Programme :mrgreen:
Als das Deutsche Fernsehen startete, gab es nur 1 Schwarz/Weiß-Programm. Du startest immerhin mit 3 Programmen in Farbe. ;-)
ts-soft hat geschrieben:Viel Spaß damit, ich hoffe es ist nützlich
Ja, ist es. Vielen Dank!

Bei mir lassen sich übrigens beide Programme problemlos auch wiederholt starten (Windows XP Pro SP3).

Gruß, Little John

Verfasst: 18.01.2009 10:56
von rolaf
Sauber :allright:

Verfasst: 18.01.2009 14:04
von HeX0R
Solange PB aber bei gewissen Aktionen des Users fleißig Messages verschluckt, sollte man das lieber in einen Callback stecken.

Verfasst: 18.01.2009 14:20
von sechsrad
Jup, klasse Beispiel.

Funktioniert bei mir 100zentig.

mfg

Verfasst: 18.01.2009 20:37
von ts-soft
HeX0R hat geschrieben:Solange PB aber bei gewissen Aktionen des Users fleißig Messages verschluckt, sollte man das lieber in einen Callback stecken.
Hätte ich ja auch gemacht, aber so ist es Einsteigerfreundlicher :wink:

Ich denke mal, das gleichzeitige bewegen des Fernsehers und bedienen der
Fernbedienung ist in diesem Beispiel recht schwierig :mrgreen:

Aber danke für den Hinweis

Gruß
Thomas

Verfasst: 20.01.2009 18:04
von Andesdaf
muss sagen, super code :allright: