Рисовать фигуры можно, кликая по полю (отдельные точки), и проводкой (линии и прямоугольники), удерживая левую кнопку мыши; удерживая Alt можно рисовать диагонали. Всё то же самое плюс Ctrl — стирание нарисованного. Для полной очистки поля воспользуйтесь Clear во время, когда движение фигур полностью остановлено (кнопка Stop, она же Start)
Нарисованные фигуры можно сохранять и в дальнейшем загружать. Сохранённая фигура загружается в видимый центр игрового поля, до нажатия кнопки OK её можно сдвигать в нужное место клавишами стрелок. Само поле можно двигать правой кнопкой мыши. Чтобы отцентровать поле, нажмите Center.
#NoEnv
SetBatchLines, -1
SetWinDelay, 0
IniName := A_ScriptDir "\" RegExReplace(A_ScriptName, "(.*\.).*", "$1ini")
Columns = 500
Rows := Round(Columns*A_ScreenHeight/A_ScreenWidth)
IniRead, Cell, % IniName, Settings, Cell, 8 ; размер клетки
FieldWidth := Columns*Cell - 1 ; полная ширина игрового поля
FieldHeight := Rows*Cell - 1 ; полная высота игрового поля
ButtonField = 55 ; область с элементами управления
AliveBrush1 := 0xFF2A5EA9 ; цвет живых клеток в монохромном режиме
Gosub, CreateWindow
CellArray := [] ; в этом двумерном массиве будут все клетки поля, их координаты и состояние
Loop % Columns
CellArray[A_Index] := []
Loop % Rows
{
r := A_Index
Loop % Columns
CellArray[r][A_Index] := {x: Cell*(A_Index - 1), y: Cell*(r - 1), alive: 0}
}
NextArray := {} ; здесь будут клетки, изменённые в предыдущей итерации и их соседи
; в цикле будем рассматривать только их
OnMessage(0x201, "WM_LBUTTONDOWN")
OnMessage(0x200, "WM_MOUSEMOVE")
OnMessage(0x202, "WM_LBUTTONUP")
OnMessage(0x111, "WM_COMMAND")
OnMessage(0x00F, "WM_PAINT")
OnExit, Exit
Return
CreateWindow:
pToken := Gdip_Startup()
SysGet, GuiW, % SM_CXFULLSCREEN := 16
SysGet, GuiH, % SM_CYFULLSCREEN := 17
SysGet, WBorder, % SM_CXSIZEFRAME := 32
SysGet, HBorder, % SM_CYSIZEFRAME := 33
IniRead, FieldW, % IniName, Size, FieldW, % GuiW - 2*WBorder
IniRead, FieldH, % IniName, Size, FieldH, % GuiH - 2*HBorder - ButtonField
IniRead, GuiX, % IniName, Size, GuiX, 0
IniRead, GuiY, % IniName, Size, GuiY, 0
IniRead, Pause, % IniName, Settings, Pause, 10
IniRead, Multicolor, % IniName, Settings, Multicolor, 0
Gui, Parent: +hwndhParent +Resize ; родительское окно с элементами управления
Gui, Parent:Default
Gui, Color, D4D0C8
Gui, Font, s8, Verdana
Gui, Add, Pic, % "vPic x0 y0 w" FieldW " h" FieldH " hwndhPic" ; будет родительским окном для игрового поля
Gui, Add, Button, % "vStartStop x10 y" FieldH+(ButtonField//2 - 23//2) " w57 h23 gStart", Start
Gui, Add, Button, vNext xp+61 yp wp hp gCycle, Next
Gui, Add, Button, vClear xp+61 yp wp hp gClear, Clear
Gui, Add, Button, vCenter xp+61 yp wp hp gCenter, Center
Gui, Add, Button, vSave xp+77 yp wp hp gSave hwndhSaveButton, Save
Gui, Add, Button, vLoad xp+61 yp wp hp gLoad hwndhLoadButton, Load
Gui, Add, Text, % "vTextSpeed xp+75 yp+" TextD := 5, Speed:
Options := "xp+40 w100 yp-3 h20 Range1-50 ToolTip AltSubmit"
Gui, Add, Slider, vSlider gSpeedSet %Options%, % Speed := Round(51 - Pause/10)
Gui, Add, Text, vSpeed xp+100 yp+3, % Speed
Gui, Add, Text, vTextSize xp+30 yp, Cell size:
Gui, Add, DDL, vDDLSize gDDLSize xp+58 yp-4 h20 w35 r8
, % RegExReplace("4|5|6|7|8|9|10|11", "(" Cell ")", Cell = 11 ? "$1||" : "$1|")
Gui, Add, Checkbox, % "vMulticolor gMulticolor xp+58 yp+5" (Multicolor ? " Checked" : ""), Multicolor
trn := FieldW < 898
Gui, Add, Text, % "vTextGen gClearGen x" (trn ? 788 : FieldW - 110) " yp", Generation
Gui, Font, s9
Gui, Add, Text, % "vGen gClearGen x" (trn ? 858 : FieldW - 40) " yp-1 w35", 0
Gui, Child: -Caption +hwndhField +Parent%hPic% ; окно с игровым полем
hFieldDC := GetDC(hField)
hbm := CreateDIBSection(FieldWidth, FieldHeight)
hdc := CreateCompatibleDC()
obm := SelectObject(hdc, hbm)
G := Gdip_GraphicsFromHDC(hdc)
pAliveBrush1 := Gdip_BrushCreateSolid(Multicolor ? 0xFF30B29E : AliveBrush1)
pAliveBrush2 := Gdip_BrushCreateSolid(0xFFFFC400)
pAliveBrush3 := Gdip_BrushCreateSolid(0xFFC930B8)
pBackBrush := Gdip_BrushCreateSolid(0xFFFFFFFF)
Gosub, FillBackground
Gui, Show, % "x" GuiX " y" GuiY " w" FieldW " h" FieldH + ButtonField
GuiControlGet, Pic, Pos, Pic
x_val := PicW//2 - FieldWidth//2
y_val := PicH//2 - FieldHeight//2
Gui, Child:Show, % "x" x_val " y" y_val " w" FieldWidth " h" FieldHeight
BitBlt(hFieldDC, 0, 0, FieldWidth, FieldHeight, hdc, 0, 0)
Controls = Next|Clear|DDLSize|Save|Load
Return
FillBackground:
Gdip_FillRectangle(G, pBackBrush, -1, -1, FieldWidth+2, FieldHeight+2) ; заливаем бэкграунд
TransparentCell := (0x45 + (Cell - 5)*7)<<24
TransparentGrid := (0x75 + (Cell - 5)*7)<<24
pCellPen := Gdip_CreatePen(TransparentCell|0x7C7A77, 1)
pGridPen := Gdip_CreatePen(TransparentGrid|0x7C7A77, 1)
Loop % Rows - 1
Gdip_DrawLine(G, mod(A_Index, 10) ? pCellPen : pGridPen
, 0, A_Index * Cell - 1, FieldWidth, A_Index * Cell - 1) ; рисуем горизонтали
Loop % Columns - 1
Gdip_DrawLine(G, mod(A_Index, 10) ? pCellPen : pGridPen
, A_Index * Cell - 1, 0, A_Index * Cell - 1, FieldHeight) ; рисуем вертикали
Gdip_DeletePen(pCellPen), Gdip_DeletePen(pGridPen)
Return
#If WinActive("ahk_id " hParent)
Enter::
Start:
if WinExist("ahk_id" hLoad)
Return
GuiControl, Parent:, StartStop, % (StartStop := !StartStop) ? "Stop" : "Start"
Loop, parse, Controls, |
GuiControl, % "Parent:" (StartStop ? "Disable" : "Enable"), %A_LoopField%
if !StartStop
Return
GuiControl, Parent:, Gen, % Gen := 0
SetTimer, Cycle, -1
Return
Cycle:
Loop
{
color := Multicolor ? Mod(Ceil(A_Index/20), 3) : 1
CurrentBrush := color = 1 ? pAliveBrush1 : color = 2 ? pAliveBrush2 : pAliveBrush3
GuiControl, Parent:, Gen, % ++Gen
CurrentArray := {} ; здесь будут клетки, которые изменятся в этой итерации
for k, v in NextArray
{
i := 0, r := v.r, c := v.c
Loop 3 ; проверяем количество живых и мёртвых соседей у претендентов на смену статуса
{
n := c + (p := A_Index) - 2
Loop 3
{
if (p = 2 && A_Index = 2)
Continue
m := r + A_Index - 2
if (CellArray[m][n].alive && ++i = 4) ; достаточно досчитать до четырёх
Break 2
}
}
o := CellArray[r][c], x := o.x, y := o.y
if o.alive
{
if (i < 2 || i = 4) ; если живых соседей меньше двух или больше трёх — живая умирает
CurrentArray[A_Index] := {r: r, c: c, alive: 0}
, Gdip_FillRectangle(G, pBackBrush, x, y, Cell - 1, Cell - 1)
}
Else if i = 3 ; если соседей трое — мёртвая оживает
CurrentArray[A_Index] := {r: r, c: c, alive: 1}
, Gdip_FillRectangle(G, CurrentBrush, x, y, Cell - 1, Cell - 1)
}
NextArray := {} ; опустошаем массив
if !CurrentArray.GetCapacity() ; если ничего не изменилось, значит цикл закончен
{
GuiControl, Parent:, StartStop, Start
Loop, parse, Controls, |
GuiControl, Parent:Enable, %A_LoopField%
Break
}
for k, v in CurrentArray ; заносим в массив NextArray изменившиеся клетки и
{ ; соседние с ними для проверки в следующей итерации
c := v.c, r := v.r, UpdateNextArray(r, c)
, CellArray[r][c].alive := v.alive ; вносим изменения в основной массив
}
BitBlt(hFieldDC, 0, 0, FieldWidth, FieldHeight, hdc, 0, 0)
Sleep, Pause
} Until !StartStop
StartStop := 0
Return
Del::
Clear:
if StartStop
Return
GuiControl, Parent:, Gen, % Gen := 0
for k, v in CellArray
for n, m in v
if m.alive
Update_hDC(m)
BitBlt(hFieldDC, 0, 0, FieldWidth, FieldHeight, hdc, 0, 0)
Return
Center:
GuiControlGet, Pic, Parent:Pos, Pic
x_val := PicW//2 - FieldWidth//2
y_val := PicH//2 - FieldHeight//2
Gui, Child:Show, % "x" x_val " y" y_val " w" FieldWidth " h" FieldHeight
BitBlt(hFieldDC, 0, 0, FieldWidth, FieldHeight, hdc, 0, 0)
Return
Save:
Critical
if !FileExist(A_ScriptDir "\Figures")
FileCreateDir, %A_ScriptDir%\Figures
Gui, Parent: +OwnDialogs
WinGetPos,, Y_Pic,,, ahk_id %hPic%
WinGetPos, XButt,,,, ahk_id %hSaveButton%
GuiControlGet, Field, Parent:Pos, Pic
Loop
{
InputBox, FigureName, Save, Type a Name:,, 200, 120, XButt, Y_Pic + FieldH - 120
if ErrorLevel
Return
BitBlt(hFieldDC, 0, 0, FieldWidth, FieldHeight, hdc, 0, 0)
FigureName = %FigureName%
if (FigureName = "")
MsgBox, Введите название фигуры!
else if found := FileExist(A_ScriptDir "\Figures\" FigureName ".life")
{
MsgBox, 0x34, Название существует, Название фигуры "%FigureName%" уже существует!`nЗаменить?
IfMsgBox, Yes
Break
else
FigureName =
}
} Until FigureName
for r, v in CellArray
{
for c, m in v
{
if m.alive
{
if !once
r_min := r, once := 1
Figure .= r "," c "|"
}
}
}
Figure := SubStr(Figure, 1, -1)
c_min := 1000000000
Loop, parse, Figure, |
{
r_new := RegExReplace(A_LoopField, "(.*),.*", "$1") - r_min
NewFigure .= RegExReplace(A_LoopField, ".*(,.*)", r_new "$1") . "|"
if ((n := RegExReplace(A_LoopField, ".*,(.*)", "$1")) < c_min)
c_min := n
}
NewFigure := SubStr(NewFigure, 1, -1), Figure := ""
Loop, parse, NewFigure, |
{
c_new := RegExReplace(A_LoopField, ".*,(.*)", "$1") - c_min
Figure .= RegExReplace(A_LoopField, "(.*,).*", "$1" c_new) . "|"
}
Figure := SubStr(Figure, 1, -1)
FileDelete, % A_ScriptDir "\Figures\" FigureName ".life"
FileAppend, % Figure, % A_ScriptDir "\Figures\" FigureName ".life"
Figure := NewFigure := once := ""
BitBlt(hFieldDC, 0, 0, FieldWidth, FieldHeight, hdc, 0, 0)
Notify("Фигура сохранена в файл`n" A_ScriptDir "\Figures\" FigureName ".life"
, 0xFF0055BB, "Arial", "s15 x15 y12 cFFFFFFFF Italic", 1500)
Return
Load:
Gui, Load: New, +OwnerParent +hwndhLoad
Gui, Load: Default
Gui, Margin, 15, 10
Gui, Font, s10 q5, Verdana
Gui, Add, DDL, vDDLNames gDDLNames hwndhDDLNames w150 h23 r15, Select a Name:||
Gui, Font, s8, Verdana
Gui, Add, Button, % "x" (150+30-125)//2 " w60 h23", OK
Gui, Add, Button, xp+65 w60 h23", Cancel
GuiControl, Focus, OK
WinGetPos,, Y_Pic,,, ahk_id %hPic%
WinGetPos, XButt,,,, ahk_id %hLoadButton%
GuiControlGet, Field, Parent:Pos, Pic
Gui, Show, Hide, Load
DetectHiddenWindows, On
WinGetPos,,,, LoadH, ahk_id %hLoad%
Gui, Show, % "x" XButt " y" Y_Pic + FieldH - LoadH, Load
Return
DDLNames:
Critical
GuiControlGet, DDLNames, Load:, DDLNames
if DDLNames = No Files
Return
if CurrentFigure
Loop, parse, CurrentFigure, |
{
r := RegExReplace(A_LoopField, "(.*),.*", "$1") + CurrentRow
c := RegExReplace(A_LoopField, ".*,(.*)", "$1") + CurrentColumn
CellArray[r][c].alive := 1, UpdateNextArray(r, c)
}
if !hMemoryBm
{
hMemoryBm := CreateDIBSection(FieldWidth, FieldHeight)
hMemoryDC := CreateCompatibleDC()
oMemoryBm := SelectObject(hMemoryDC, hMemoryBm)
GMemory := Gdip_GraphicsFromHDC(hMemoryDC)
}
BitBlt(hMemoryDC, 0, 0, FieldWidth, FieldHeight, hdc, 0, 0)
FileRead, CurrentFigure, % A_ScriptDir "\Figures\" DDLNames ".life"
max_r := max_c := 0
Loop, parse, CurrentFigure, |
{
max_r := (r := RegExReplace(A_LoopField, "(.*),.*", "$1")) > max_r ? r : max_r
max_c := (c := RegExReplace(A_LoopField, ".*,(.*)", "$1")) > max_c ? c : max_c
}
WinGetPos, X_Field, Y_Field,,, ahk_id %hField%
WinGetPos, X_Pic, Y_Pic, W_Pic, H_Pic, ahk_id %hPic%
XPosField := X_Pic - X_Field
YPosField := Y_Pic - Y_Field
FirstVisibleRow := Ceil(YPosField/Cell) + 1
LastVisibleRow := Ceil((YPosField + H_Pic)/Cell)
FirstVisibleColumn := Ceil(XPosField/Cell) + 1
LastVisibleColumn := Ceil((XPosField + W_Pic)/Cell)
CurrentRow := StartRow := (LastVisibleRow + FirstVisibleRow - max_r)//2
CurrentColumn := StartColumn := (LastVisibleColumn + FirstVisibleColumn - max_c)//2
Loop, parse, CurrentFigure, |
{
r := RegExReplace(A_LoopField, "(.*),.*", "$1") + StartRow
c := RegExReplace(A_LoopField, ".*,(.*)", "$1") + StartColumn
x := CellArray[r][c].x, y := CellArray[r][c].y
Gdip_FillRectangle(G, pAliveBrush1, x, y, Cell - 1, Cell - 1)
}
BitBlt(hFieldDC, 0, 0, FieldWidth, FieldHeight, hdc, 0, 0)
Hotkey, IfWinExist, ahk_id %hLoad%
Hotkey, Left, MoveFigure, On
Hotkey, Right, MoveFigure, On
Hotkey, Up, MoveFigure, On
Hotkey, Down, MoveFigure, On
Return
MoveFigure:
While GetKeyState(A_ThisHotkey, "P") || GetKeyState(A_PriorHotkey, "P")
{
GetKeyState("UP", "P") ? (--CurrentRow = 0 ? ++CurrentRow : CurrentRow)
GetKeyState("Down", "P") ? (++CurrentRow = Rows + 1 ? --CurrentRow : CurrentRow)
GetKeyState("Left", "P") ? (--CurrentColumn = 0 ? ++CurrentColumn : CurrentColumn)
GetKeyState("Right", "P") ? (++CurrentColumn = Columns + 1 ? --CurrentColumn : CurrentColumn)
BitBlt(hdc, 0, 0, FieldWidth, FieldHeight, hMemoryDC, 0, 0)
Loop, parse, CurrentFigure, |
{
r := RegExReplace(A_LoopField, "(.*),.*", "$1") + CurrentRow
c := RegExReplace(A_LoopField, ".*,(.*)", "$1") + CurrentColumn
x := CellArray[r][c].x, y := CellArray[r][c].y
Gdip_FillRectangle(G, pAliveBrush1, x, y, Cell - 1, Cell - 1)
}
BitBlt(hFieldDC, 0, 0, FieldWidth, FieldHeight, hdc, 0, 0)
Sleep, 50
}
Return
#If WinExist("ahk_id" hLoad)
Enter::
LoadButtonOK:
if !CurrentFigure
{
Gui, Load:Destroy
Return
}
Loop, parse, CurrentFigure, |
{
r := RegExReplace(A_LoopField, "(.*),.*", "$1") + CurrentRow
c := RegExReplace(A_LoopField, ".*,(.*)", "$1") + CurrentColumn
CellArray[r][c].alive := 1, UpdateNextArray(r, c)
}
Esc::
LoadGuiClose:
LoadButtonCancel:
Gui, Load:Destroy
if !CurrentFigure
Return
if (A_ThisLabel ~= "Load(ButtonCancel|GuiClose)" || A_ThisHotkey = "Esc")
BitBlt(hdc, 0, 0, FieldWidth, FieldHeight, hMemoryDC, 0, 0)
, BitBlt(hFieldDC, 0, 0, FieldWidth, FieldHeight, hdc, 0, 0)
Hotkey, Left, Off
Hotkey, Right, Off
Hotkey, Up, Off
Hotkey, Down, Off
SelectObject(hMemoryDC, oMemoryBm), DeleteObject(hMemoryBm)
DeleteDC(hMemoryDC), Gdip_DeleteGraphics(GMemory)
hMemoryBm := CurrentFigure := ""
Return
SpeedSet:
GuiControl, Parent:, Speed, % Slider
Pause := (51 - Slider)*10
Return
DDLSize:
Gui, Child:Show, Hide
GuiControlGet, Cell, Parent:, DDLSize
FieldWidth := Columns*Cell - 1
FieldHeight := Rows*Cell - 1
hPrevbm := hbm
hbm := CreateDIBSection(FieldWidth, FieldHeight)
SelectObject(hdc, hbm), DeleteObject(hPrevbm), Gdip_DeleteGraphics(G)
G := Gdip_GraphicsFromHDC(hdc)
Gosub, FillBackground
Loop % Rows
{
r := A_Index
Loop % Columns
{
oCell := CellArray[r][A_Index]
oCell.x := Cell*(A_Index - 1), oCell.y := Cell*(r - 1)
if oCell.alive
Gdip_FillRectangle(G, pAliveBrush1, oCell.x, oCell.y, Cell - 1, Cell - 1)
}
}
GuiControlGet, Pic, Pos, Pic
x_val := PicW//2 - FieldWidth//2
y_val := PicH//2 - FieldHeight//2
Gui, Child:Show, % "x" x_val " y" y_val " w" FieldWidth " h" FieldHeight
SetTimer, Paint1, -10
Return
Multicolor:
GuiControlGet, Multicolor, Parent:, Multicolor
Gdip_DeleteBrush(pAliveBrush1)
pAliveBrush1 := Gdip_BrushCreateSolid(Multicolor ? 0xFF30B29E : AliveBrush1)
Return
ClearGen:
GuiControl, Parent:, Gen, % Gen := 0
Return
ParentGuiSize:
Gui, Parent:Default
GuiControl, Move, Pic, % "w" A_GuiWidth " h" A_GuiHeight - ButtonField
d := A_GuiHeight - ButtonField//2 - 23//2
Controls2 := Controls . "|StartStop|Center"
Loop, parse, Controls2, |
GuiControl, Move, %A_LoopField%, % "y" d
GuiControl, Move, TextSpeed, % "y" d + TextD
GuiControl, Move, Slider, % "y" d + 2
GuiControl, Move, Speed, % "y" d + TextD
GuiControl, Move, TextSize, % "y" d + TextD
GuiControl, Move, Multicolor, % "y" d + TextD
trn := A_GuiWidth < 898
GuiControl, MoveDraw, TextGen, % "x" (trn ? 788 : A_GuiWidth - 110) " y" d + 5
GuiControl, MoveDraw, Gen, % "x" (trn ? 858 : A_GuiWidth - 40) " y" d + 4
Return
#If !WinExist("ahk_id" hLoad) && WinActive("ahk_id" hParent)
Esc::
ParentGuiClose:
ExitApp
Exit:
WinGetPos, X, Y,,, ahk_id %hParent%
WinGet, MinMax, MinMax, ahk_id %hParent%
GuiControlGet, Pic, Parent:Pos, Pic
Gui, Parent:Destroy
Gdip_DeleteBrush(pBackBrush), Gdip_DeleteBrush(pAliveBrush1)
Gdip_DeleteBrush(pAliveBrush2), Gdip_DeleteBrush(pAliveBrush3)
SelectObject(hdc, obm), DeleteObject(hbm), DeleteDC(hdc), Gdip_DeleteGraphics(G)
ReleaseDC(hFieldDC, hField), Gdip_Shutdown(pToken)
IniWrite, % MinMax = -1 ? 0 : X, % IniName, Size, GuiX
IniWrite, % MinMax = -1 ? 0 : Y, % IniName, Size, GuiY
IniWrite, % MinMax = -1 ? 800 : PicW, % IniName, Size, FieldW
IniWrite, % MinMax = -1 ? 500 : PicH, % IniName, Size, FieldH
IniWrite, % Pause, % IniName, Settings, Pause
IniWrite, % Cell, % IniName, Settings, Cell
IniWrite, % Multicolor, % IniName, Settings, Multicolor
ExitApp
#If WinActive("ahk_id" hParent)
RButton:: SendInput, {LButton Down}
RButton Up::
SendInput, {LButton Up}
SetTimer, Move, -20
Return
Move:
WinGetPos, X_Field, Y_Field,,, ahk_id %hField%
WinGetPos, X_Pic, Y_Pic, W_Pic, H_Pic, ahk_id %hPic%
if (X_Field - X_Pic > 0 && Y_Field - Y_Pic > 0)
WinMove, ahk_id %hField%,, 0, 0
else if (X_Field + FieldWidth < X_Pic + W_Pic && Y_Field + FieldHeight < Y_Pic + H_Pic)
WinMove, ahk_id %hField%,, W_Pic - FieldWidth, H_Pic - FieldHeight
else if (X_Field - X_Pic > 0 && !(Y_Field + FieldHeight < Y_Pic + H_Pic))
WinMove, ahk_id %hField%,, 0, Y_Field - Y_Pic
else if (X_Field - X_Pic > 0 && Y_Field + FieldHeight < Y_Pic + H_Pic)
WinMove, ahk_id %hField%,, 0, H_Pic - FieldHeight
else if (Y_Field - Y_Pic > 0 && !(X_Field + FieldWidth < X_Pic + W_Pic))
WinMove, ahk_id %hField%,, X_Field - X_Pic, 0
else if (Y_Field - Y_Pic > 0 && X_Field + FieldWidth < X_Pic + W_Pic)
WinMove, ahk_id %hField%,, W_Pic - FieldWidth, 0
else if (X_Field + FieldWidth < X_Pic + W_Pic)
WinMove, ahk_id %hField%,, W_Pic - FieldWidth, Y_Field - Y_Pic
else if (Y_Field + FieldHeight < Y_Pic + H_Pic)
WinMove, ahk_id %hField%,, X_Field - X_Pic, H_Pic - FieldHeight
BitBlt(hFieldDC, 0, 0, FieldWidth, FieldHeight, hdc, 0, 0)
Return
WM_PAINT() ; поддержка изображения при перерисовке окна
{
global
SetTimer, Paint1, -10
Return
Paint1:
BitBlt(hFieldDC, 0, 0, FieldWidth, FieldHeight, hdc, 0, 0)
SetTimer, Paint2, -50
Return
Paint2:
BitBlt(hFieldDC, 0, 0, FieldWidth, FieldHeight, hdc, 0, 0)
Return
}
Update_hDC(oCell)
{
global
if oCell.alive := !oCell.alive
Gdip_FillRectangle(G, pAliveBrush1, oCell.x, oCell.y, Cell - 1, Cell - 1)
Else
Gdip_FillRectangle(G, pBackBrush, oCell.x, oCell.y, Cell - 1, Cell - 1)
}
WM_LBUTTONDOWN(wp, lp, msg, hwnd)
{
local x, y, c, r, n, m, Time, Figures
static PrevTime = 0
Critical
if A_GuiControl = DDLNames
{
Loop, %A_ScriptDir%\Figures\*.life
Figures .= (A_Index = 1 ? "" : "|") . RegExReplace(A_LoopFileName, "(.*)\..*", "$1")
Sort, Figures, D|
GuiControl,, DDLNames, % Figures ? "|" Figures : "|No Files"
Return
}
else if A_GuiControl = Pic
{
if GetKeyState("RButton", "P")
{
PostMessage, WM_NCLBUTTONDOWN := 0xA1, HTCAPTION := 2,, AutoHotkeyGUI1
Return
}
}
Else if A_GuiControl =
{
PostMessage, WM_NCLBUTTONDOWN := 0xA1, HTCAPTION := 2
Return
}
Time := A_TickCount
if (StartStop || hwnd != hField || Time - PrevTime < 100)
Return
PrevTime := Time
x := lp & 0xFFFF, y := lp >> 16
c := Ceil(x/Cell), r := Ceil(y/Cell)
UpdateNextArray(r, c), Update_hDC(CellArray[r][c])
, BitBlt(hFieldDC, 0, 0, FieldWidth, FieldHeight, hdc, 0, 0)
, StartX := CellArray[r][c].x, StartY := CellArray[r][c].y, StartC := c, StartR := r
if !hPaintDC
{
hPaintDC := GetDC(hPic)
GuiControlGet, Pic, Parent:Pos, Pic
hPaintBm := CreateDIBSection(PicW, PicH)
, hPaintMDC := CreateCompatibleDC()
, oPaintBm := SelectObject(hPaintMDC, hPaintBm)
, GPaint := Gdip_GraphicsFromHDC(hPaintMDC)
WinGetPos, X_Field, Y_Field,,, ahk_id %hField%
WinGetPos, X_Pic, Y_Pic,,, ahk_id %hPic%
XPosField := X_Pic - X_Field, YPosField := Y_Pic - Y_Field
}
}
WM_MOUSEMOVE(wp, lp, msg, hwnd)
{
local x, y, c, r, p, m, n, k
static c_prev, r_prev
if (hwnd != hField || StartStop || !GetKeyState("LButton", "P") || !StartR || !StartX)
Return
x := lp & 0xFFFF, y := lp >> 16
last_c := c := Ceil(x/Cell), last_r := r := Ceil(y/Cell)
if ((c = c_prev && r = r_prev) || !hPaintMDC)
Return
c_prev := c, r_prev := r
BitBlt(hPaintMDC, 0, 0, PicW, PicH, hdc, XPosField, YPosField)
Brush := (CtrlState := GetKeyState("Ctrl", "P")) ? pBackBrush : pAliveBrush1
m := Abs(r - StartR) + 1, n := Abs(c - StartC) + 1
if GetKeyState("Alt", "P") && Var := 1
Loop % ToolTipShow((k := m > n ? m : n) . " diagonal", k)
Gdip_FillRectangle(GPaint, Brush
, StartX + (c > StartC ? 1 : -1)*Cell*(A_Index - 1) - XPosField
, StartY + (r > StartR ? 1 : -1)*Cell*(A_Index - 1) - YPosField
, Cell - 1, Cell - 1)
Else if !GetKeyState("Alt", "P") && Var := 2
{
Loop % m
{
p := A_Index
Loop % ToolTipShow(p . " row`n" . n . " column", n)
Gdip_FillRectangle(GPaint, Brush
, StartX + (c > StartC ? 1 : -1)*Cell*(A_Index - 1) - XPosField
, StartY + (r > StartR ? 1 : -1)*Cell*(p - 1) - YPosField
, Cell - 1, Cell - 1)
}
}
BitBlt(hFieldDC, XPosField, YPosField, PicW, PicH, hPaintMDC, 0, 0)
}
WM_LBUTTONUP(wp, lp, msg, hwnd)
{
local n, m, p
if (hwnd != hField || StartStop)
Return
ToolTip
Critical
m := Abs(last_r - StartR) + 1, n := Abs(last_c - StartC) + 1
if Var = 1
Loop % m > n ? m : n
CurrentR := StartR + (last_r > StartR ? 1 : -1)*(A_Index - 1)
, CurrentC := StartC + (last_c > StartC ? 1 : -1)*(A_Index - 1)
, CellArray[CurrentR][CurrentC].alive := !CtrlState
, UpdateNextArray(CurrentR, CurrentC)
else if Var = 2
{
Loop % m
{
p := A_Index
Loop % n
CurrentR := StartR + (last_r > StartR ? 1 : -1)*(p - 1)
, CurrentC := StartC + (last_c > StartC ? 1 : -1)*(A_Index - 1)
, CellArray[CurrentR][CurrentC].alive := !CtrlState
, UpdateNextArray(CurrentR, CurrentC)
}
}
if !(Var && hPaintDC)
Return
BitBlt(hdc, XPosField, YPosField, PicW, PicH, hPaintMDC, 0, 0)
, SelectObject(hPaintMDC, oPaintBm), DeleteObject(hPaintBm), DeleteDC(hPaintMDC)
, Gdip_DeleteGraphics(GPaint), ReleaseDC(hPaintDC, hPic)
, hPaintDC := Var := StartR := StartX := CtrlState := ""
}
UpdateNextArray(r, c)
{
global NextArray
Loop 3
{
n := c + A_Index - 2
Loop 3
{
m := r + A_Index - 2
if !NextArray.HasKey(m "|" n)
NextArray[m "|" n] := {r: m, c: n}
}
}
}
ToolTipShow(Text, Value)
{
ToolTip % Text
Return Value
}
Notify(Text, ColorWin, FontName, Options, timeout, Alpha = 255, Token = 1)
{
Options .= " q4"
If !Token && !pToken := Gdip_Startup()
{
MsgBox, 48, Ошибка GDI+, Убедитесь в наличии gdiplus.dll в вашей системе!
ExitApp
}
AllStyles = Italic|Bold|Underline|Strikeout
Loop, parse, AllStyles, |
if InStr(Options, A_LoopField)
Styles .= A_LoopField
if !RegExMatch(Options, "i).*s(\d+).*", Found)
{
MsgBox, 0x1010, Notify Error, Не задан размер шрифта!
ExitApp
}
s := Found1
x := RegExMatch(Options, "i).*x(\d+).*", Found) ? Found1 : (10, Options .= " x10")
y := RegExMatch(Options, "i).*y(\d+).*", Found) ? Found1 : (10, Options .= " y10")
c := RegExMatch(Options, "i).*c([0-9A-Fa-f]+)( |$)", Found) ? Found1 : ("FF000000", Options .= " cFF000000")
; WS_EX_LAYERED := 0x80000, WS_EX_TRANSPARENT := 0x20
Gui, Notyfy:New, -Caption +E0x80020 +AlwaysOnTop +ToolWindow +Owner +HwndID
Gui, Notyfy:Show, NA
hbm := CreateDIBSection(1, 1), hdc := CreateCompatibleDC()
obm := SelectObject(hdc, hbm), G := Gdip_GraphicsFromHDC(hdc)
MeasureString(G, Text, FontName, Styles, s, WText, HText)
Width := WText + 2*x, Height := HText + 2*y
SelectObject(hdc, obm), DeleteObject(hbm), Gdip_DeleteGraphics(G)
hbm := CreateDIBSection(Width, Height)
obm := SelectObject(hdc, hbm), G := Gdip_GraphicsFromHDC(hdc), Gdip_SetSmoothingMode(G, 4)
pBrush := Gdip_BrushCreateSolid(ColorWin)
Gdip_FillRoundedRectangle(G, pBrush, 0, 0, Width-1, Height-1, Height//2 > 20 ? 20 : Height//2)
Gdip_DeleteBrush(pBrush)
Gdip_TextToGraphics(G, Text, Options, FontName, Width, Height)
Alpha_ := -10
Loop
{
Alpha_+=10
UpdateLayeredWindow(ID, hdc
, (A_ScreenWidth-Width)//2, (A_ScreenHeight-Height)//2, Width, Height, Alpha_)
Sleep, 10
} Until Alpha_ + 10 > Alpha
UpdateLayeredWindow(ID, hdc
, (A_ScreenWidth-Width)//2, (A_ScreenHeight-Height)//2, Width, Height, Alpha)
Sleep, timeout
Alpha_ := Alpha
Loop
{
Alpha_-=10
UpdateLayeredWindow(ID, hdc
, (A_ScreenWidth-Width)//2, (A_ScreenHeight-Height)//2, Width, Height, Alpha_)
Sleep, 10
} Until Alpha_ - 10 < 0
UpdateLayeredWindow(ID, hdc
, (A_ScreenWidth-Width)//2, (A_ScreenHeight-Height)//2, Width, Height, 0)
Gui, Notify:Destroy
SelectObject(hdc, obm), DeleteObject(hbm), DeleteDC(hdc), Gdip_DeleteGraphics(G)
if !Token
Gdip_Shutdown(pToken)
}
MeasureString(G, Text, FontName, Styles, Size, ByRef WText, ByRef HText)
{
Style = 0
StyleArray := [["Bold", 1], ["Italic", 2], ["Underline", 4], ["Strikeout", 8]]
for key, value in StyleArray
if InStr(Styles, value.1)
Style += value.2
if !hFamily := Gdip_FontFamilyCreate(FontName)
{
MsgBox, Указанный шрифт не поддерживается системой!
ExitApp
}
hFont := Gdip_FontCreate(hFamily, Size, Style)
FormatStyle := NoWrap ? 0x4000 | 0x1000 : 0x4000
hFormat := Gdip_StringFormatCreate(FormatStyle)
VarSetCapacity(RectF, 16)
Result := Gdip_MeasureString(G, Text, hFont, hFormat, RectF)
Gdip_DeleteStringFormat(hFormat)
Gdip_DeleteFont(hFont)
Gdip_DeleteFontFamily(hFamily)
WText := RegExReplace(Result, "(.*?\|){2}(.*?)\|.*", "$2")
HText := RegExReplace(Result, "(.*?\|){3}(.*?)\|.*", "$2")
}
WM_COMMAND(wp, lp)
{
global hDDLNames
CBN_CLOSEUP := 8
if ((wp >> 16 = CBN_CLOSEUP) && lp = hDDLNames)
{
Gui, Load:Default
GuiControl, Focus, OK
GuiControlGet, Choose,, DDLNames
if !Choose
GuiControl,, DDLNames, Select a Name:||
}
}