#NoTrayIcon
#include <WindowsConstants.au3>
#include <GUIConstants.au3>
#include <GDIPlus.au3>
#include <WinAPISysWin.au3>
#include <Math.au3>
#include <TrayConstants.au3>
#include <MsgBoxConstants.au3>
Opt("TrayAutoPause", 0)
Opt("GUIOnEventMode", 1)
Opt("GUIResizeMode", $GUI_DOCKLEFT + $GUI_DOCKRIGHT + $GUI_DOCKMENUBAR)
Global Const $GUI_TITLE = "Тест"
Global Const $QUESTION_FILE = @ScriptDir & "\Тестовые вопросы и ответы.txt"
Global Const $ANSWER_CORRECT_PAUSE = 10 ;мин.
Global Const $ANSWER_INCORRECT_PAUSE = 1 ;мин.
Global Const $GUI_WIDTH = 325
Global Const $PIC_SIZE = 75
Global Const $PIC_ONLYREDUCE = False
Global Const $LABEL_HEIGHT = 20
Global Const $BUTTON_HEIGHT = 30
Global Const $CONTROL_INDENT = 10
Global Enum $TST_QUESTION, $TST_CORRECT, $TST_PIC, $TST_ANSWERS, $TST_MAX
Global Enum $ANS_ID, $ANS_TEXT, $ANS_MAX
Global $g_hGUI, $g_idQuest, $g_idInfo, $g_idPic, _
$g_aTest[][$TST_MAX] = [[0, -1]], $g_hTimer
_GUI_Init()
_Test_Init()
_Test_Start()
While Sleep(10)
WEnd
Func _GUI_Init()
$g_hGUI = GUICreate($GUI_TITLE, $GUI_WIDTH)
GUISetOnEvent($GUI_EVENT_CLOSE, "_Exit")
Local $iY = $CONTROL_INDENT, $iFullWidth = $GUI_WIDTH - $CONTROL_INDENT * 2
$g_idQuest = GUICtrlCreateLabel("", $CONTROL_INDENT, $iY, $iFullWidth, $LABEL_HEIGHT, BitOR($SS_CENTERIMAGE, $SS_CENTER))
$iY += $LABEL_HEIGHT + $CONTROL_INDENT
$g_idPic = GUICtrlCreatePic("", ($GUI_WIDTH - $PIC_SIZE) / 2, $iY, $PIC_SIZE, $PIC_SIZE, $SS_CENTERIMAGE)
GUICtrlSetState(-1, $GUI_HIDE)
$iY += $PIC_SIZE + $CONTROL_INDENT
$g_idInfo = GUICtrlCreateLabel("", $CONTROL_INDENT, $iY, $iFullWidth, $LABEL_HEIGHT, BitOR($SS_CENTERIMAGE, $SS_CENTER))
GUICtrlSetColor(-1, 0xFF0000)
GUICtrlSetState(-1, $GUI_HIDE)
EndFunc ;==>_GUI_Init
Func _Test_Init()
Local $sRead = FileRead($QUESTION_FILE)
Local $aData = StringRegExp($sRead, "(?i)Вопрос \d+\R(.+?)\R((?s).+?)\RПравильный:\R(.+)", $STR_REGEXPARRAYGLOBALMATCH)
If @error Then Exit MsgBox($MB_ICONERROR + $MB_TOPMOST, $GUI_TITLE, StringFormat('Вопросы не найдены -> "%s"', $QUESTION_FILE))
Local $iIdx, $iCount = UBound($aData)
Dim $g_aTest[$iCount / 3 + 1][$TST_MAX] = [[0, -1]]
For $i = 0 To $iCount - 1 Step 3
$g_aTest[0][0] += 1
$iIdx = $g_aTest[0][0]
$g_aTest[$iIdx][$TST_QUESTION] = $aData[$i]
$g_aTest[$iIdx][$TST_CORRECT] = $aData[$i + 2]
_Test_MakeSubData($aData[$i + 1])
Next
EndFunc ;==>_Test_Init
Func _Test_MakeSubData($sData)
Local $aSubData, $iIdx = $g_aTest[0][0], $iOffset = 1
$aSubData = StringRegExp($sData, "(?i)Адрес:\R(.+)", $STR_REGEXPARRAYMATCH)
If Not @error Then
$g_aTest[$iIdx][$TST_PIC] = $aSubData[0]
$iOffset = @extended
EndIf
Local $aSplit, $sAnswers = "Некорректный вопрос (без ответов)", $bCorrect
$aSubData = StringRegExp($sData, "(?i)Ответы:\R((?s).+)", $STR_REGEXPARRAYMATCH, $iOffset)
If Not @error Then $sAnswers = $aSubData[0]
$aSplit = StringSplit(StringStripCR($sAnswers), @LF)
Local $aAnswers[$aSplit[0] + 1][$ANS_MAX] = [[$aSplit[0]]]
For $i = 1 To $aSplit[0]
$aAnswers[$i][$ANS_TEXT] = $aSplit[$i]
If Not $bCorrect Then $bCorrect = $g_aTest[$iIdx][$TST_CORRECT] = $aAnswers[$i][$ANS_TEXT]
Next
If Not $bCorrect Then MsgBox($MB_ICONERROR + $MB_TOPMOST, $GUI_TITLE, StringFormat('Верный ответ не найден -> "%s"', $g_aTest[$iIdx][$TST_QUESTION]))
$g_aTest[$iIdx][$TST_ANSWERS] = $aAnswers
EndFunc ;==>_Test_MakeSubData
Func _Test_Start()
Local $iIdx = $g_aTest[0][1]
Do
$iIdx = Random(1, $g_aTest[0][0], 1)
Until $iIdx <> $g_aTest[0][1]
GUICtrlSetData($g_idQuest, $g_aTest[$iIdx][$TST_QUESTION])
Local $iY = $CONTROL_INDENT * 2 + $LABEL_HEIGHT, $iFullWidth = $GUI_WIDTH - $CONTROL_INDENT * 2
If $g_aTest[$iIdx][$TST_PIC] Then
_GUICtrlPic_SetImageWithResize($g_idPic, $g_aTest[$iIdx][$TST_PIC], $PIC_ONLYREDUCE)
GUICtrlSetState($g_idPic, $GUI_SHOW)
$iY += $PIC_SIZE + $CONTROL_INDENT
Else
GUICtrlSetState($g_idPic, $GUI_HIDE)
EndIf
$aAnswers = $g_aTest[$iIdx][$TST_ANSWERS]
For $i = 1 To $aAnswers[0][0]
$aAnswers[$i][$ANS_ID] = GUICtrlCreateButton($aAnswers[$i][$ANS_TEXT], $CONTROL_INDENT, $iY, $iFullWidth, $BUTTON_HEIGHT)
GUICtrlSetOnEvent(-1, "_Test_Proc")
$iY += $BUTTON_HEIGHT + $CONTROL_INDENT
Next
$g_aTest[$iIdx][$TST_ANSWERS] = $aAnswers
GUICtrlSetPos($g_idInfo, Default, $iY)
$iY += $BUTTON_HEIGHT + $LABEL_HEIGHT + $CONTROL_INDENT
WinMove($g_hGUI, "", Default, $g_aTest[0][1] == -1 ? (@DesktopHeight - $iY) / 2 : Default, Default, $iY)
$g_aTest[0][1] = $iIdx
GUISetState()
EndFunc ;==>_Test_Start
Func _Test_Proc()
Local $iIdx = $g_aTest[0][1], $aAnswers
If GUICtrlRead(@GUI_CtrlId) = $g_aTest[$iIdx][$TST_CORRECT] Then
GUISetState(@SW_HIDE)
$aAnswers = $g_aTest[$iIdx][$TST_ANSWERS]
For $i = 1 To $aAnswers[0][0]
GUICtrlDelete($aAnswers[$i][$ANS_ID])
Next
TraySetState($TRAY_ICONSTATE_SHOW)
Sleep($ANSWER_CORRECT_PAUSE * 1000 * 60)
TraySetState($TRAY_ICONSTATE_HIDE)
_Test_Start()
Else
_Test_SetState($GUI_DISABLE)
$g_hTimer = TimerInit()
GUICtrlSetState($g_idInfo, $GUI_SHOW)
AdlibRegister("_Test_Timer")
EndIf
EndFunc ;==>_Test_Proc
Func _Test_SetState($iState)
Local $iIdx = $g_aTest[0][1], $aAnswers = $g_aTest[$iIdx][$TST_ANSWERS]
For $i = 1 To $aAnswers[0][0]
GUICtrlSetState($aAnswers[$i][$ANS_ID], $iState)
Next
EndFunc ;==>_Test_SetState
Func _Test_Timer()
Local $sInfo = StringFormat("Неверный ответ, до нового вопроса осталось: %i сек.", $ANSWER_INCORRECT_PAUSE * 60 - Round(TimerDiff($g_hTimer) / 1000))
If GUICtrlRead($g_idInfo) <> $sInfo Then GUICtrlSetData($g_idInfo, $sInfo)
If TimerDiff($g_hTimer) >= $ANSWER_INCORRECT_PAUSE * 1000 * 60 Then
AdlibUnRegister("_Test_Timer")
GUICtrlSetState($g_idInfo, $GUI_HIDE)
_Test_SetState($GUI_ENABLE)
EndIf
EndFunc ;==>_Test_Timer
Func _GUICtrlPic_SetImageWithResize($idPic, $sFile, $bOnlyReduce = True)
Local $tRect, $iPicW, $iPicH
$tRect = _WinAPI_GetWindowRect(GUICtrlGetHandle($idPic))
$iPicW = DllStructGetData($tRect, "Right") - DllStructGetData($tRect, "Left")
$iPicH = DllStructGetData($tRect, "Bottom") - DllStructGetData($tRect, "Top")
_GDIPlus_Startup()
Local $hImage, $iImageW, $iImageH, $iScale, $hImageSc, $hHBMP, $hPrevImage
$hImage = _GDIPlus_BitmapCreateFromFile($sFile)
$iImageW = _GDIPlus_ImageGetWidth($hImage)
$iImageH = _GDIPlus_ImageGetHeight($hImage)
$iScale = _Min($iPicW / $iImageW, $iPicH / $iImageH)
If $bOnlyReduce Then $iScale = _Min($iScale, 1)
$hImageSc = _GDIPlus_ImageScale($hImage, $iScale, $iScale)
$hHBMP = _GDIPlus_BitmapCreateDIBFromBitmap($hImageSc)
$hPrevImage = GUICtrlSendMsg($idPic, $STM_SETIMAGE, 0, $hHBMP)
If $hPrevImage Then _WinAPI_DeleteObject($hPrevImage)
_GDIPlus_BitmapDispose($hImage)
_GDIPlus_BitmapDispose($hImageSc)
_WinAPI_DeleteObject($hHBMP)
_GDIPlus_Shutdown()
EndFunc ;==>_GUICtrlPic_SetImageWithResize
Func _Exit()
Exit
EndFunc ;==>_Exit