Jump to content

Recommended Posts

Posted
#include <WinAPISysWin.au3>
#include <APISysConstants.au3>
#include <WinAPISys.au3>
#include <WinAPI.au3>
#include <GUIConstantsEx.au3>

Global $g_hLabelStatus, $g_hMutex = 0, $g_iForkID = 0

; Global Unique Windows Messages for IPC
Global Const $g_idMsgGo = _WinAPI_RegisterWindowMessage("GameShow_GoSignal")
Global Const $g_idMsgWin = _WinAPI_RegisterWindowMessage("GameShow_WinnerSignal")
Global Const $g_idMsgBye = _WinAPI_RegisterWindowMessage("GameShow_GameOver")

; Unique Mutex Name for the Forks to fight over
Global Const $g_sMutexName = "Local\GameShowBuzzerMutex"

; Determine mode based on command line arguments
Switch ($CmdLine[0] > 0) ? $CmdLine[1] : ""
    Case "/Main"
        RunMain()
    Case "/Fork"
        RunFork(($CmdLine[0] > 1) ? $CmdLine[2] : 0)
    Case Else
        ; If run with no arguments, act as the launcher
        ConsoleWrite("Launcher: Starting Main. Bye." & @CRLF)
        ShellExecute(@AutoItExe, '"' & @ScriptFullPath & '" /Main')
EndSwitch


; ==========================================
; Main loop
; ==========================================
Func RunMain()
    ; Create Main Window to receive messages
    Local $hMainGUI = GUICreate("Game Main", 400, 200)
    Local $hLabel = GUICtrlCreateLabel("Spawning contestants...", 20, 40, 360, 100)
    GUICtrlSetFont(-1, 12, 800)
    GUISetState(@SW_SHOW)

    ; Allow lower-privilege (UIPI) messages on admin/user mix running forks
;~  _WinAPI_ChangeWindowMessageFilterEx($hMainGUI, $g_idMsgWin, 1)

    ; Register to listen for the Winner signal
    GUIRegisterMsg($g_idMsgWin, "Main_OnWinnerReceived")

    ; Spawn 3 Forks, passing their Fork ID (1, 2, 3) as an extra argument
    For $i = 1 To 3
        ShellExecute(@AutoItExe, '"' & @ScriptFullPath & '" /Fork ' & $i)
        Sleep(200) ; Give them a brief moment to initialize their GUIs
    Next

    Sleep(1000)
    GUICtrlSetData($hLabel, "Ready... SET... GO!!!")
    ConsoleWrite("Main: Broadcasting GO signal!" & @CRLF)

    ; BROADCAST THE GO SIGNAL
    _WinAPI_BroadcastSystemMessage($g_idMsgGo, 0, 0, $BSF_POSTMESSAGE)

    ; Keep Main alive to await the winner
    Do
    Until GUIGetMsg() = $GUI_EVENT_CLOSE
EndFunc   ;==>RunMain

Func Main_OnWinnerReceived($hWnd, $iMsg, $wParam, $lParam)
    ; $wParam contains the winning Fork's ID.
    MsgBox(64, "Main Decides!", "We have a winner! Fork #" & Int($wParam) & " hit the buzzer first!", 60, $hWnd)
    _WinAPI_BroadcastSystemMessage($g_idMsgBye, 0, 0, $BSF_POSTMESSAGE) ; tell the forks to exit.
    GUIDelete()
    Exit
EndFunc   ;==>Main_OnWinnerReceived


; ==========================================
; Fork loop
; ==========================================
Func RunFork($iID)
    ; Create Fork Window to listen for Main's broadcast
    Local $hForkGUI = GUICreate("Fork " & $iID, 250, 150, 150 * $iID, 150 * $iID)
    $g_hLabelStatus = GUICtrlCreateLabel("Waiting for Main's GO...", 20, 50, 210, 50)
    GUICtrlSetFont(-1, 10, 600)
    GUISetState(@SW_SHOW)

    ; Allow UIPI bypass for the GO signal from Main
;~  _WinAPI_ChangeWindowMessageFilterEx($hMainGUI, $g_idMsgWin, 1)

    ; Store the ID globally so the message handler can access it
    $g_iForkID = $iID

    ; Listen for the GO signal
    GUIRegisterMsg($g_idMsgGo, "Fork_OnGoSignal")
    GUIRegisterMsg($g_idMsgBye, "Fork_GameOver")

    ; Register the clean-up function on exit
    OnAutoItExitRegister("Fork_CleanUp")

    ; ... wait ?
    Do
    Until GUIGetMsg() = $GUI_EVENT_CLOSE
EndFunc   ;==>RunFork

Func Fork_OnGoSignal($hWnd, $iMsg, $wParam, $lParam)

    ; --- THE RACE IS ON! Try to create/lock the Mutex ---
    ; Open/Create a named mutex. If it already exists, @error or LastError will tell us.
    $g_hMutex = _WinAPI_CreateMutex($g_sMutexName, True) ; True = Attempt to take initial ownership

    ; If LastError is ERROR_ALREADY_EXISTS (183), some fork beat us to it!
    If _WinAPI_GetLastError() = 183 Then
        ; LOOSER! 😢
        GUICtrlSetData($g_hLabelStatus, "LOOSER! 😭" & @CRLF & "Too slow!")
        _WinAPI_CloseHandle($g_hMutex) ; Clean up the handle
    Else
        ; WINNER! 🏆
        GUICtrlSetData($g_hLabelStatus, "WINNER! 🏆" & @CRLF & "Slammed the buzzer first!")

        ; Broadcast back to the Main, passing the Fork ID in the wParam!
        _WinAPI_BroadcastSystemMessage($g_idMsgWin, $g_iForkID, 0, $BSF_POSTMESSAGE)
    EndIf
EndFunc   ;==>Fork_OnGoSignal

Func Fork_CleanUp()
    ; If this instance holds an open Mutex handle, close it now!
    If IsDeclared("g_hMutex") And $g_hMutex <> 0 Then
        _WinAPI_CloseHandle($g_hMutex)
        ConsoleWrite("Fork: Mutex handle closed." & @CRLF) ; no one is gonna see it. meh.
    EndIf
EndFunc   ;==>Fork_CleanUp

Func Fork_GameOver($hWnd, $iMsg, $wParam, $lParam)
    GUIDelete()
    Exit
EndFunc   ;==>Fork_GameOver

Is it an example ?, is it a game ?, ...yes, is an example.
They compete to be first to hit the buzzer ( is a mutex but buzzer sounds more fun ).

Enjoy the game example :) 

Follow the link to my code contribution ( and other things too ).
FAQ - Please Read Before Posting  image.gif.922e3a93535f431de08b31ee669cc446.gif
autoit_scripter_blue_userbar.png

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
×
×
  • Create New...