Eigenes Programm fernsteuern

Hier könnt Ihr gute, von Euch geschriebene Codes posten. Sie müssen auf jeden Fall funktionieren und sollten möglichst effizient, elegant und beispielhaft oder einfach nur cool sein.
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

Eigenes Programm fernsteuern

Beitrag 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:
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
7x7
Beiträge: 591
Registriert: 14.08.2007 15:41
Computerausstattung: ganz toll
Wohnort: Lelbach

Beitrag von 7x7 »

Schönes Beispiel! :)

Edit: Nanu? Hat genau 1x funktioniert. Jetzt (2ter und weitere Starts) kommen nur noch 2 leere Fenster (Television & Remote)
- alles was ich hier im Forum sage/schreibe ist lediglich meine Meinung und keine Tatsachenbehauptung
- unkommentierter Quellcode = unqualifizierter Müll
Little John

Re: Eigenes Programm fernsteuern

Beitrag 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
Benutzeravatar
rolaf
Beiträge: 3843
Registriert: 10.03.2005 14:01

Beitrag von rolaf »

Sauber :allright:
:::: WIN 10 :: PB 5.73 :: (x64) ::::
Benutzeravatar
HeX0R
Beiträge: 3040
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 »

Solange PB aber bei gewissen Aktionen des Users fleißig Messages verschluckt, sollte man das lieber in einen Callback stecken.
sechsrad
Rüpel
Beiträge: 112
Registriert: 01.02.2008 13:31

Beitrag von sechsrad »

Jup, klasse Beispiel.

Funktioniert bei mir 100zentig.

mfg
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 »

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
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
Andesdaf
Moderator
Beiträge: 2671
Registriert: 15.06.2008 18:22
Wohnort: Dresden

Beitrag von Andesdaf »

muss sagen, super code :allright:
Win11 x64 | PB 6.20
Antworten