1 (изменено: marusa122, 2023-04-23 13:11:05)

Тема: AHK: Проблема с горячими клавишами в скрипте

Здравствуйте. Есть код - назначение горячих клавиш. В форме для редактирования указывается горячая клавиша для создания скриншотов и путь их сохранения. Также в форме есть настройка горячей клавиши для действий в программе (автоматические вызовы). Но Autohotkey не запускает скрипт - появляется ошибка  "Call to nonexistent function". Что здесь не так? Помогите, пожалуйста, я уже не понимаю, что Autohotkey от меня хочет. Я полночи пыталась менять скрипт, но ошибка никуда не уходит.
Код (с последними внесенными изменениями):

MsgBox, 4, ,Program1, Вы хотите изменить настройки запуска? `n,Program1 пропустит этот шаг через несколько секунд..., 5
IfMsgBox Yes
{
IniRead, viKeyScreen, AppLauncher.ini, Settings, KeyScreen, LWin
IniRead, viKeyCall, AppLauncher.ini, Settings, KeyCall, Esc
IniRead, viCordCallx, AppLauncher.ini, Settings, CordCallx, 135
IniRead, viCordCally, AppLauncher.ini, Settings, CordCally, 130
IniRead, viCordTELx, AppLauncher.ini, Settings, CordTELx, 135
IniRead, viCordTELy, AppLauncher.ini, Settings, CordTELy, 150
IniRead, viCordOpenx, AppLauncher.ini, Settings, CordOpenx, 656
IniRead, viCordOpeny, AppLauncher.ini, Settings, CordOpeny, 206
IniRead, viCordSumx, AppLauncher.ini, Settings, CordSumx, 1280
IniRead, viCordSumy, AppLauncher.ini, Settings, CordSumy, 650
IniRead, viFolder, AppLauncher.ini, Settings, Folder, %A_Space%
IniRead, viNames, AppLauncher.ini, Settings, Names, WorkScreen

MyKeyScreen: ; этот фрагмент делает скриншоты при нажатии горячей клавиши KeyScreen (по умолчанию в форме указана LWin)
	{ 
	; Original by SKAN on D293 @ bit.ly/2krOIc9
MakeScreenshot(filename := "%Ed_Names%") 
{
    count := 0
    Loop {
        count += 1
        filename := "%Ed_Folder%\%Ed_Names%(" . count . ").png"
        if !FileExist(filename) {
            break
        }
    }
	X:=0,Y:=0,W:=A_ScreenWidth,H:=A_ScreenHeight
	VarSetCapacity(BITMAPINFO, 40, 0)
	NumPut(32, NumPut(1, NumPut(H, NumPut(W, NumPut(40,BITMAPINFO,"Int"),"Int"),"Int"),"Short"),"Short")
	
	hBM := DllCall("Gdi32.dll\CreateDIBSection", "Ptr",0, "Ptr",&BITMAPINFO, "Int",0, "PtrP",pBits := 0, "Ptr",0, "Int",0, "Ptr")
	sDC := DllCall("User32.dll\GetDC", "Ptr", 0, "Ptr")
	mDC := DllCall("Gdi32.dll\CreateCompatibleDC", "Ptr", 0, "Ptr")
	DllCall("Gdi32.dll\SelectObject", "Ptr",mDC, "Ptr",hBM)
	DllCall("Gdi32.dll\BitBlt", "Ptr",mDC, "Int",0, "Int",0, "Int",W, "Int",H, "Ptr",sDC, "Int",X, "Int",Y, "Int",0x40CC0020)
	
	GDIP("Startup")
	SavePicture(hBM, filename)
	GDIP("Shutdown")
	
	DllCall("Gdi32.dll\DeleteDC", "Ptr",mDC)
	DllCall("User32.dll\ReleaseDC", "Ptr", 0, "Ptr",sDC)
	DllCall("Gdi32.dll\DeleteObject", "Ptr",hBM)
}

; By SKAN on D293 @ bit.ly/2krOIc9
GDIP(C:="Startup") {                                      
	Static SI:=Chr(!(VarSetCapacity(Si,24,0)>>16)), pToken:=0, hMod:=0, Res:=0, AOK:=0
	If (AOK := (C="Startup" and pToken=0) Or (C<>"Startup" and pToken<>0))  {
	If (C="Startup") {
		hMod := DllCall("LoadLibrary", "Str","gdiplus.dll", "Ptr")
		Res  := DllCall("gdiplus\GdiplusStartup", "PtrP",pToken, "Ptr",&SI, "UInt",0)
	} Else { 
		Res  := DllCall("gdiplus\GdiplusShutdown", "Ptr",pToken)
		DllCall("FreeLibrary", "Ptr",hMod),   hMod:=0,   pToken:=0
	}}  
	Return (AOK ? !Res : Res:=0)    
}

; By SKAN on D293 @ bit.ly/2krOIc9
SavePicture(hBM, sFile) {
	Local V,  pBM := VarSetCapacity(V,16,0)>>8,  Ext := LTrim(SubStr(sFile,-3),"."),  E := [0,0,0,0]
	Local Enc := 0x557CF400 | Round({"bmp":0, "jpg":1,"jpeg":1,"gif":2,"tif":5,"tiff":5,"png":6}[Ext])
	E[1] := DllCall("gdi32\GetObjectType", "Ptr",hBM ) <> 7
	E[2] := E[1] ? 0 : DllCall("gdiplus\GdipCreateBitmapFromHBITMAP", "Ptr",hBM, "UInt",0, "PtrP",pBM)
	NumPut(0x2EF31EF8,NumPut(0x0000739A,NumPut(0x11D31A04,NumPut(Enc+0,V,"UInt"),"UInt"),"UInt"),"UInt")
	E[3] := pBM ? DllCall("gdiplus\GdipSaveImageToFile", "Ptr",pBM, "WStr",sFile, "Ptr",&V, "UInt",0) : 1
	E[4] := pBM ? DllCall("gdiplus\GdipDisposeImage", "Ptr",pBM) : 1
	Return E[1] ? 0 : E[2] ? -1 : E[3] ? -2 : E[4] ? -3 : 1  
}
	}
; конец фрагмента

MyKeyCall: ; этот фрагмент выполняет действия в окне браузера для вызова программы-телефонии при нажатии горячей клавиши KeyCall (по умолчанию в форме указана  Esc)
	{
    	MouseMove, %Ed_CordCallx%, %Ed_CordCally%
   	Click %Ed_CordTELx%, %Ed_CordTELy%
   	Sleep 1000
	Click %Ed_CordOpenx%, %Ed_CordOpeny%
	return
	}
; конец фрагмента

HotKey, %viKeyScreen%, MyKeyScreen
HotKey, %viKeyCall%, MyKeyCall


; Создаем окно с заголовками, текстовыми полями и кнопками
Gui, New

Gui, Add, Text, XM Y+M W70 R1, Скриншоты
Gui, Add, Edit, X+10 YP W200 R1 vHotKey_KeyScreen, %viKeyScreen%

Gui, Add, Text, XM Y+M W70 R1, Автозвонки
Gui, Add, Edit, X+10 YP W200 R1 vHotKey_KeyCall, %viKeyCall%

Gui, Add, Text, XM Y+M W280 R1, Настройка скриншотов (кнопка в "Скриншоты")
Gui, Add, Text, XM+20 Y+M W130, Шаг 1. Имена файлов:
Gui, Add, Edit, X+10 YP W120 R1 vEd_Names, %viNames%
Gui, Add, Text, XM+20 Y+M W130, Шаг 2. Рабочая папка:
Gui, Add, Edit, X+10 YP W100 R1 vEd_Folder, %viFolder%
Gui, Add, Button, X+0 YP W20 R1 vBt_Folder gOnButtonFolder, ...
Gui, Add, Text, XM Y+M W280 R1, Настройка автозвонков (клавиша в "Автозвонки"):
Gui, Add, Text, XM+205 YP+15 W20 R1, X
Gui, Add, Text, XM+255 YP W20 R1, Y
Gui, Add, Text, XM+20 Y+M W160 R1, Шаг 1. Кнопка вызова
Gui, Add, Edit, X+10 YP W40 R1 vEd_CordCallx, %viCordCallx%
Gui, Add, Edit, X+10 YP W40 R1 vEd_CordCally, %viCordCally%
Gui, Add, Text, XM+20 Y+M W160 R1, Шаг 2. Выбор телефонии
Gui, Add, Edit, X+10 YP W40 R1 vEd_CordTELx, %viCordTELx%
Gui, Add, Edit, X+10 YP W40 R1 vEd_CordTELy, %viCordTELy%
Gui, Add, Text, XM+20 Y+M W160 R1, Шаг 3. Подтвердить вызов
Gui, Add, Edit, X+10 YP W40 R1 vEd_CordOpenx, %viCordOpenx%
Gui, Add, Edit, X+10 YP W40 R1 vEd_CordOpeny, %viCordOpeny%
Gui, Add, Text, XM Y+M W285 R1, Настройка автосуммы для клиента
Gui, Add, Text, XM+20 Y+M W160 R1, Шаг 1. Выбор суммы заказа
Gui, Add, Edit, X+10 YP W40 R1 vEd_CordSumx, %viCordSumx%
Gui, Add, Edit, X+10 YP W40 R1 vEd_CordSumy, %viCordSumy%

Gui, Add, Button, XM Y+M+10 W285 R3 vBt_Run gOnButtonRun, Начать работу
Gui, Add, Button, XM Y+M W140 R1 vBt_Save gOnButtonSave, Сохранить
Gui, Add, Button, X+5 YP W140 R1 vBt_Exit gOnButtonExit, Выйти

Gui, Show,, App Launcher
Return

; Когда окно закрывается или нажимается кнопка Выйти, сценарий завершается.
GuiClose:
OnButtonExit:
	ExitApp

; Когда вы нажимаете «Сохранить», значения из текстовых полей сохраняются в файл настроек AppLauncher.ini.
OnButtonSave:
	Gui, Submit, NoHide
 	IniWrite, %HotKey_KeyScreen%, AppLauncher.ini, Settings, KeyScreen
 	IniWrite, %HotKey_KeyCall%, AppLauncher.ini, Settings, KeyCall
	IniWrite, %Ed_CordCallx%, AppLauncher.ini, Settings, CordCallx
	IniWrite, %Ed_CordCally%, AppLauncher.ini, Settings, CordCally
	IniWrite, %Ed_CordTELx%, AppLauncher.ini, Settings, CordTELx
	IniWrite, %Ed_CordTELy%, AppLauncher.ini, Settings, CordTELy
	IniWrite, %Ed_CordOpenx%, AppLauncher.ini, Settings, CordOpenx
	IniWrite, %Ed_CordOpeny%, AppLauncher.ini, Settings, CordOpeny
	IniWrite, %Ed_CordSumx%, AppLauncher.ini, Settings, CordSumx
	IniWrite, %Ed_CordSumy%, AppLauncher.ini, Settings, CordSumy
	IniWrite, %Ed_Folder%, AppLauncher.ini, Settings,Folder
	IniWrite, %Ed_Names%, AppLauncher.ini, Settings, Names
	Sleep 1000
	MsgBox, 64, Настройка Program1, настройки Program1 успешно сохранены!, 3
	Return

; Нажатие на кнопку с многоточием открывает окно выбора папки
OnButtonFolder:
	FileSelectFolder, vOutFolder, %A_ScriptDir%, 3, Выберите папку с вашими рабочими скриншотами
	If (ErrorLevel == 0)
	GuiControl, Text, Ed_Folder, %vOutFolder%
Return

; При нажатии на кнопку Start запускаем приложение с данными, указанными в текстовых полях
OnButtonRun:
	TrayTip, Запуск Program1, Program1 запущена!
 	WinHide, A
 	Return

:*:-25::
MouseMove, %Ed_CordSumx%, %Ed_CordSumy%
Click 2
ClipSave=%ClipboardAll%
Clipboard=
Send, ^{c}
ClipWait, 2
Result:=Round(Clipboard-25,2)
MsgBox, 0, Сумма для клиента, %Result% грн,
Clipboard=%ClipSave%
Return


MyKeyScreen(%Ed_Folder%, %Ed_Names%)
MyKeyCall(%Ed_CordCallx%, %Ed_CordCally%, %Ed_CordTELx%, %Ed_CordTELy%, %Ed_CordOpenx%, %Ed_CordOpeny%)
; пыталась убрать содержимое в скобках - не помогло
}

2

Re: AHK: Проблема с горячими клавишами в скрипте

marusa122 пишет:

Что здесь не так?

Здесь вы пытаетесь использовать сложные конструкции, не разобравшись в простых. Почитайте, что такое функции, для чего они нужны, как объявляются, как вызываются, и в чём разница.

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Telegram jollycoder

3 (изменено: marusa122, 2023-04-23 16:09:24)

Re: AHK: Проблема с горячими клавишами в скрипте

teadrinker, можно ликбез для особо одаренных, где у меня ошибка? Я читала про функции, пыталась исправить по документации Autohotkey, но толку никакого.
Сейчас поменяла эти фрагменты:

MyKeyScreen (%Ed_Names%, %Ed_Folder%) ; этот фрагмент делает скриншоты при нажатии горячей клавиши KeyScreen (по умолчанию в форме указана LWin)
MyKeyCall  (%Ed_CordCallx%, %Ed_CordCally%, %Ed_CordTELx%, %Ed_CordTELy%, %Ed_CordOpenx%, %Ed_CordOpeny%) ; этот фрагмент выполняет действия в окне браузера для вызова программы-телефонии при нажатии горячей клавиши KeyCall (по умолчанию в форме указана  Esc)

И в конце:

%HotKey_KeyScreen%:
Var := MyKeyScreen(%Ed_Folder%, %Ed_Names%)

%HotKey_KeyCall%:
Var := MyKeyCall(%Ed_CordCallx%, %Ed_CordCally%, %Ed_CordTELx%, %Ed_CordTELy%, %Ed_CordOpenx%, %Ed_CordOpeny%)

Скрипт запускается (без TrayTip, но значок в трее есть), но не работает от слова "совсем". Форма для редактирования координат и горячих клавиш не открывается.

4

Re: AHK: Проблема с горячими клавишами в скрипте

marusa122 пишет:
MyKeyScreen (%Ed_Names%, %Ed_Folder%)

Посмотрите в доках, как передаются параметры в функции. Вообще ознакомьтесь подробнее с темой Variables and Expressions.

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Telegram jollycoder

5 (изменено: __Михаил__, 2023-04-23 17:51:11)

Re: AHK: Проблема с горячими клавишами в скрипте

%HotKey_KeyScreen%:

Где это видано? Динамичное объявление меток? Это явно что-то за гранью.

Проверить запускаемость метки можно таким способом:

GoTo, Название_Метки

Пробелы недопустимы!

Win10x64, AHK v1.1.37.01 (Unicode 64-bit) | AHK-Wiki | Переменные и выражения | RegEx101

6

Re: AHK: Проблема с горячими клавишами в скрипте

__Михаил__, а как ее объявлять? Горячая клавиша указывается в текстовом поле формы (она может быть любой, написанной согласно документации Autohotkey). И она сохраняется в AppLauncher.ini. По умолчанию это LWin, но другой пользователь может написать RWin, Tab и пр. Как ее написать, если клавиша меняется в зависимости от содержимого AppLauncher.ini?..

7

Re: AHK: Проблема с горячими клавишами в скрипте

marusa122
Один раз придумали название и запускаете её при обработке хоткея, что изменяется динамически. В чём проблема? Это статичные переходы (метки и функции), они должны быть строго объявлены. Переменные можно создавать динамически, они для этого и существуют. Читайте справку и форум, экспериментируйте. Без этого никак.

Win10x64, AHK v1.1.37.01 (Unicode 64-bit) | AHK-Wiki | Переменные и выражения | RegEx101

8

Re: AHK: Проблема с горячими клавишами в скрипте

Пример для установки / изменении динамических хоткеев и меток:

Gui Add, Text, x8 y8 w55 h23, Клавиша:
Gui Add, Hotkey, vHKey x72 y8 w120 h23, F2
Gui Add, Button, gOk vBOk x200 y8 w80 h23, Включить
Gui Add, Text, x8 y32 w45 h23, Метка:
Gui Add, Edit, vHKey_Label x56 y32 w136 h23, HKey1
Gui Add, Button, gTest x200 y32 w80 h23, Проверить
Gui Show, w288 h63, [Пример привязки]
Return

Ok:
If !(SW := !SW){
 HotKey, % HKey, Off
 GuiControl, Enable, HKey
 GuiControl, Enable, HKey_Label
 GuiControl,, BOk, Включить
 Return
}
Gui, Submit, NoHide
If !HKey{
 MsgBox, Клавиша не указана!
 Return
}
If IsLabel(HKey_Label)
 H := HKey_Label
Else{
 H := "HKey1"
 GuiControl,, HKey_Label, % H
}
HotKey, % HKey, % H, On
GuiControl,, BOk, Выключить
GuiControl, Disable, HKey
GuiControl, Disable, HKey_Label
Return

Test:
GuiControlGet, HKey_Label
If IsLabel(HKey_Label)
 MsgBox, Метка действительна
Else
 MsgBox, Метки не обнаружено!
Return

GuiEscape:
GuiClose:
ExitApp

HKey1:
MsgBox, Действие по умолчанию.
Return

HKey2:
MsgBox, Второе действие по умолчанию.
Return

В коде можно по умолчанию применить 2 метки. Если указанной в поле метки нет - примет по умолчанию 'HKey1' метку.

Win10x64, AHK v1.1.37.01 (Unicode 64-bit) | AHK-Wiki | Переменные и выражения | RegEx101