스크립트의 호환성

AutoHotkey 1.0으로 작성된 스크립트는 대부분 AutoHotkey 1.1 위에서 아무 변경없이 실행됩니다. 그러나 몇 가지 기능은 두 버전 사이의 어떨 수 없는 차이점 때문에 제대로 작동하지 않을 수 있습니다. 가장 문제가 되는 차이점은 DllCall() 같은 고급 기능에만 영향을 미치기 때문에, 대부분의 사용자는 신경쓸 필요가 없습니다.

AutoHotkey 1.1은 "AutoHotkey_L"이라고도 알려져 있는데, 반면에 AutoHotkey 1.0은 역으로 "AutoHotkey Basic"이라는 라벨이 붙었습니다. AutoHotkey_L의 예전 버전 중에는 1.0.* 버전 번호를 사용합니다. 그래서 명확하게 하기 위해, 이 문서는 오토핫키의 두 분기를 버전 번호가 아니라 이름으로 지칭합니다.

주의: 가장 흔한 문제는 유니코드 텍스트를 지원하도록 변경한 때문인데, 이는 그냥 ANSI 버전의 AutoHotkey_L를 사용하면 피할 수 있습니다.

목차

기본

큰 충격:

중간 충격:

작은 충격:

고급

기본

구문 에러

AutoHotkey Basic에서 용인되었던 어떤 구문 에러는 이제 더 이상 AutoHotkey_L에서 용납하지 않습니다. 그런 에러는 대부분 식별하기만 하면 쉽게 교정할 수 있습니다. 다음 에러는 스크립트를 AutoHotkey_L에서 기동하자 마자 즉시 탐지됩니다. 교정해야 스크립트를 실행할 수 있습니다:

다른 어떤 구문 에러는 스크립트가 실행 중일 때 탐지됩니다. 에러 메시지를 먼저 보여준 다음에 현재 쓰레드를 종료합니다:

어떤 구문 에러는 현재 탐지되지 않지만, AutoHotkey_L에 문제를 일으킵니다:

FileRead

FileRead는 보통의 경우 코드 페이지 사이에 텍스트를 변환합니다. 그러므로 부패한 이진 데이터를 출력할 가능성이 있습니다. 이를 피하려면 *c 옵션을 추가하거나 대신에 FileOpen()을 사용하십시오.

변수 이름과 함수 이름

[, ] 그리고 ?표현식에 사용이 예약되어 있습니다. 그래서 더 이상 변수 이름으로 유효하지 않습니다. 결론적으로, ?는 (삼진 연산에 사용됨) 더 이상 양쪽에 스페이스가 없어도 됩니다. 객체 구문을 참조하십시오.

에러는 자동으로 탐지될 수도 있고 아닐 수도 있습니다:

DPI 스케일링

DPI scaling is enabled by default for script GUIs to ensure they scale according to the system DPI setting. If enabled and the system DPI setting is not 96 (100%), positions and sizes accepted by or returned from Gui commands are not compatible with other commands. To disable DPI scaling, use Gui -DPIScale.

Transform

Transform 하위-명령어 중 일부는 유니코드 버전의 AutoHotkey_L에서 변경되거나 사용할 수 없습니다:

기본 스크립트

AutoHotkey_L가 스크립트를 지정하지 않고 기동하면, .ini 파일 대신에 .ahk 파일이 적재됩니다. 이 파일의 이름은 현재 실행파일의 파일이름에 따라 다릅니다. 더 자세한 것은 스크립트에 명령어 줄 매개변수를 건네기를 참조하십시오.

SetFormat, Integer[Fast], H

대문자 H가 사용되면, 십육진수 A-F도 대문자가 됩니다. AutoHotkey Basic은 언제나 소문자를 사용합니다. SetFormat을 참조하십시오.

A_LastError

다음 명령어는 이제 A_LastError를 설정해 디버깅을 돕습니다: FileAppend, FileRead, FileReadLine, FileDelete, FileCopy, FileMove, FileGetAttrib/Time/Size/Version, FileSetAttrib/Time, FileCreateDir, RegRead, RegWrite, RegDelete. 이 명령어를 사용하면 A_LastError의 이전 값이 덮어 씌여집니다.

MsgBox

MsgBox의 똑똑한 쉼표 처리가 다른 모든 명령어와 일관성이 있게 그리고 유연하게 개선되었습니댜. 대부분의 경우, MsgBox는 의도한 대로 잘 작동합니다. 어떤 경우는 스크립트가 예전의 기묘한 행위에 의존하는 경우 행위에 변화가 보일 수 있습니다. 예를 들면:

; 다음은 이제 표현식 (Options) 다음에 텍스트 (Title)로 번역됩니다.
; 여러 부-표현식을 가진 단일 표현식 (Text) 으로 번역되지 않습니다 :
MsgBox % x, y
; 반괄호를 추가하면 예전의 번역을 강제할 수 있습니다:
MsgBox % (x, y)

; 다음은 이제 텍스트 "0, Title" 대신에 빈 대화상자를 보여줍니다:
MsgBox 0, Title
; 다음은 AutoHotkey_L 그리고 AutoHotkey Basic에서 모두 예상대로 행위합니다:
MsgBox 0, Title, % ""   ; 빈 대화상자를 보여줍니다.
MsgBox 0`, Title        ; 텍스트 "0, Title"을 보여줍니다.

; 다음은 이제 텍스트 ", Title" 대신에 빈 대화상자를 보여줍니다:
MsgBox,, Title

Gui +Owner

+Owner 옵션을 Gui에 적용하면 WS_CHILD 스타일이 제거되고 WS_POPUP 스타일이 설정됩니다. 이 때문에 스타일을 설정한 다음에 +Owner를 사용하여 Gui의 부모 창을 설정한 스크립트는 깨질 수 있습니다.

Windows Vista 이후의 Sound 명령어

SoundSet, SoundGet, SoundSetWaveVolume 그리고 SoundGetWaveVolume Windows Vista 이후에 개선되었습니다. 전형적인 행위의 변화로:

~틸드와 맞춤 조합 핫키

[v1.1.14] 부터, 틸드 접두 심볼은 맞춤 조합에 수식 키로 사용될 때 키가 작동하는 방식에 영향을 미칩니다.

맞춤 조합키와 Down/Up 핫키

틸드 접두 심볼이 사용되는 경우를 제외하고, 키-다운과 키-업 핫키가 맞춤 수식 키로 정의되어 있다면, 키를 뗄 때 둘 모두 촉발 됩니다. 예를 들어, x & y::이면 x를 뗄 때 x::x up::가 모두 촉발 됩니다. 예전에는 x::가 촉발 되지 않았습니다.

If var is type

If var is type는 시스템 로케일을 무시합니다. 단, StringCaseSense, Locale이 사용되었다면 예외입니다.

창 그룹

GroupActivate는 활성화 할 창을 발견하지 못하면 ErrorLevel에 1을 설정합니다, 그렇지 않으면 0을 설정합니다. 이전에는 ErrorLevel을 변경하지 않고 그대로 두었습니다.

GroupAddLabel 매개변수는 창 그룹에 전체적으로 적용됩니다. 그룹 안의 특정 창 규격 하나에만 적용되지 않습니다. 이 변경에 관한 토론이 포럼에 있습니다. 그렇지만, 이 매개변수를 사용하는 것은 추천 하지 않습니다; 대신에 GroupActivate를 호출한 후에 ErrorLevel을 점검하십시오.

Run / RunWait

AutoHotkey_L은 RunRunWait 명령어가 목표(Target) 매개변수를 번역하는 방식이 약간 개선되었습니다. 이 때문에 아주 희귀한 경우이기는 하지만, 예전에는 작동하지 않던 것들이 작동하게 되어 AutoHotkey Basic에서 이미 잘 작동하는 스크립트에 영향을 미칠 수 있습니다. 새로운 행위는 다음과 같습니다:

Control-Z

Loop Read 그리고 FileReadLine는 더 이상 문자 Ctrl+Z (0x1A)를 파일 끝 표식으로 이해하지 않습니다. Ctrl+Z는 모두, 파일 맨 끝에 오더라도, 그대로 적재됩니다. FileRead는 이미 이 문자를 무시합니다. 그래서 이 문제에 영향을 받지 않습니다.

호환 모드

스크립트를 실행하는 데 사용된 EXE 파일의 특성에 호환 모드가 Windows 95, 98/ME 또는 NT4로 설정되었다면, 그 스크립트는 올바르게 작동하지 못합니다. 왜냐하면 호환 모드 때문에 특정 버전의 Windows가 어플리케이션에 보고되지만, AutoHotkey_L은 이런 버전을 지원하지 않기 때문입니다. 예를 들어, 호환 모드를 Windows 95 or 98/ME에 설정하면 MsgBox %A_OSVersion%WIN_NT4라고 보고합니다.

A_IsCompiled

A_IsCompiled는 스크립트가 컴파일되지 않았다면 빈 문자열로 정의됩니다. 이전에는 정의되지 않은 채 그대로 두었습니다. 그 때문에 스크립트가 컴파일되지 않았음에도 A_IsCompiled := 1와 같은 할당이 유효했었습니다. 이제는 모든 경우에 읽기 전용 내장 변수로 취급됩니다.

공백 문자 피신

`t` 같은 피신 공백문자는 더 이상 각 인자의 앞 뒤에서 제거되지 않습니다. 예를 들어, StringReplace s, s, `t는 이제 유효하며 모든 탭 문자를 s로부터 제거합니다.

Unicode vs ANSI

Note: This section builds on topics covered in other parts of the documentation: Strings, String Encoding.

Within a string (text value), the numeric character code and size (in bytes) of each character depends on the native encoding of the script or AutoHotkey executable; i.e. Unicode or ANSI. 이런 세부 사항은 다음과 같은 일을 하려는 스크립트에 전형적으로 중요합니다:

한 가지 형식만 염두에 두고 설계된 스크립트는 종종 엉뚱한 버전의 AutoHotkey로 실행할 때 문제에 봉착합니다. 예를 들면, 어떤 스크립트가 AutoHotkey Basic용으로 작성되었다면 ANSI 버전의 AutoHotkey_L에서는 잘 작동하지만 유니코드 버전에서는 실패합니다. 어느 버전을 사용하고 있는지 잘 모르겠다면, 다음 스크립트를 실행해 보십시오:

MsgBox % A_IsUnicode ? "Unicode" : "ANSI"

ANSI: 각 문자는 한 바이트 (8 비트)입니다. 127을 넘는 문자 코드는 시스템의 언어 설정에 따라 달라집니다.

Unicode: 각 문자는 두 바이트 (16 비트)입니다. 문자 코드는 UTF-16 형식으로 정의됩니다.

의미구조 주의: 기술적으로, 어떤 유니코드 문자는 두 개의 16-비트 코드 단위로 표현됩니다. 합쳐서 "대리 쌍(surrogate pair)"라고 부릅니다. 비슷하게, 어떤 ANSI 코드 페이지는 (보통 DBCS(Double Byte Character Sets)라고 부름) 두 바이트 문자를 담고 있습니다. 그렇지만, 실용적인 이유로, 이것들을 거의 언제나 두 개의 개별 단위로 취급합니다 (단순하게 하기 위해 그냥 "문자(characters)"라고 부릅니다).

VarSetCapacity

VarSetCapacity는 변수의 가용 능력을 바이트 단위로 설정합니다. 변수의 가용능력을 문자의 개수에 기반하여 설정하려면, 문자의 크기를 반드시 고려해야 합니다. 예를 들어:

VarSetCapacity(ansi_var,    capacity_in_chars)
VarSetCapacity(unicode_var, capacity_in_chars * 2)
VarSetCapacity(native_var,  capacity_in_chars * (A_IsUnicode ? 2 : 1))
VarSetCapacity(native_var,  t_size(capacity_in_chars))  ; 아래 참조

다음은 VarSetCapacity의 두 가지 주요 사용법입니다:

  1. 예측한 개수의 문자를 보유하도록 변수를 확장합니다. 그리하여 점진적 결합을 통해 문자열을 구성할 때 수행성능을 개선할 수 있습니다. 예를 들어, VarSetCapacity(var, 1000)는 1000 바이트를 허용합니다. 이것은 유니코드 버전의 AutoHotkey_L에서는 500 문자에 불과합니다. 이렇게 하면 수행성능에 영향을 미칠 수 있지만, 스크립트는 여전히 올바르게 작동합니다.
  2. 변수 크기를 조정해 이진 구조체를 담습니다. 구조체에 직접적으로 텍스트가 담겨 있다면, 그 텍스트의 형식을 반드시 고려해야 합니다. 형식은 구조체에 따라 다릅니다 - 어떤 경우는 유니코드 버전의 AutoHotkey_L에서도 ANSI 텍스트가 사용됩니다. 변수가 너무 작으면, 스크립트는 충돌하거나 아니면 예상하지 못한 행위를 할 수 있습니다 (구조체를 어떻게 사용하는가에 따라).

DllCall

"Str" 유형이 사용될 때, 현재 빌드의 고유 유형의 문자열이라는 뜻입니다. 어떤 함수는 특정한 형태의 문자열을 요구하거나 돌려주기 때문에, 다음의 문자열 유형을 사용할 수 있습니다:

 문자 크기C / Win32 유형인코딩
WStr16-비트wchar_t*, WCHAR*, LPWSTR, LPCWSTRUTF-16
AStr8-비트char*, CHAR*, LPSTR, LPCSTRANSI (시스템 기본 ANSI 코드 페이지)
Str--TCHAR*, LPTSTR, LPCTSTR유니코드 빌드의 WStr 그리고 ANSI 빌드의 AStr과 동등.

"Str" 또는 현재 빌드에 대하여 그와 동등한 유형이 매개변수로 사용되면, 그 문자열 또는 변수의 주소가 함수에 건네집니다. 그렇지 않으면 대신에 문자열의 임시 사본이 원하는 포맷으로 생성되고 건네집니다. 일반적으로, "AStr" 그리고 "WStr"은 함수가 그 매개변수에 변수를 쓸 때 사용하면 안 됩니다.

주의: "AStr" 그리고 "WStr"은 매개변수에 대하여 그리고 그 함수의 반환 값에 대하여 똑 같이 유효합니다.

일반적으로, 스크립트가 문자열을 매개변수로 받는 함수를 DllCall()를 통하여 호출하면, 다음 접근법 중 하나를 취해야 합니다:

  1. 함수를 Unicode (W) 버전과 ANSI (A) 버전으로 모두 사용할 수 있으면, 현재 빌드에 대하여 적절한 버전을 호출합니다. 다음 예제에서, "DeleteFile"은 내부적으로 "DeleteFileA" 또는 "DeleteFileW"이라고 부릅니다. "DeleteFile" 자체는 실제로 존재하지 않으므로, DllCall()은 자동으로 현재 빌드에 대하여 적절하게 "A" 또는 "W"를 시도합니다:
    DllCall("DeleteFile", "Ptr", &filename)
    DllCall("DeleteFile", "Str", filename)

    다음 예제에서, &filename은 문자열의 주소를 정확하게 있는 그대로 건넵니다. 그래서 함수는 문자열을 "Str" 유형과 같은 형식이라고 예상해야 합니다. AutoHotkey Basic에서 "UInt"를 "Ptr" 대신에 사용할 수 있습니다. 그러나 결과 코드는 64-비트와 호환되지 않습니다.

    주의: 함수를 정확하게 지정된 대로 발견할 수 없으면, AutoHotkey_L은 어느 DLL이 지정되어 있는가에 상관 없이 "A" 또는 "W" 접두사를 덧붙입니다. 그렇지만, AutoHotkey Basic은 User32.dll, Kernel32.dll, ComCtl32.dll, 또는 Gdi32.dll에 있는 함수에 대해서만 "A" 접두사를 붙입니다.

  2. 함수가 오직 특정 유형이 문자열만 입력으로 받는다면, 그 스크립트는 적절한 문자열 유형을 사용할 수 있습니다:
    DllCall("DeleteFileA", "AStr", filename)
    DllCall("DeleteFileW", "WStr", filename)
  3. 함수가 (비-고유 형식으로) 문자열을 수정해야 한다면, 스크립트는 버퍼를 위에 기술한 대로 할당하고 그의 주소를 함수에 건네야 합니다. 매개변수가 입력을 받는다면, 스크립트는 또한 입력 문자열도 적절한 형식으로 변환해야 합니다; StrPut()을 사용하면 변환할 수 있습니다.

NumPut / NumGet

NumPut()이나 NumGet()이 문자열에 사용될 때, 주어진 유형의 문자열에 대하여 오프셋과 유형이 정확해야 합니다. 다음을 지침으로 삼으십시오:

;  8-bit/ANSI   strings:  size_of_char=1  type_of_char="Char"
; 16-bit/UTF-16 strings:  size_of_char=2  type_of_char="UShort"
nth_char := NumGet(var, (n-1)*size_of_char, type_of_char)
NumPut(nth_char, var, (n-1)*size_of_char, type_of_char)

var에 음수 형태의 문자열이 들어 있다면, 적절한 값은 A_IsUnicode에 기반하여 결정할 수 있습니다:

nth_char := NumGet(var, t_size(n-1), t_char())
NumPut(nth_char, var, t_size(n-1), t_char())

; 편리성과 명료성을 위해 함수를 정의합니다:
t_char() {
    return A_IsUnicode ? "UShort" : "Char"
}
t_size(char_count=1) {
    return A_IsUnicode ? char_count*2 : char_count
}

포인터 크기

포인터 크기는 32-비트 빌드에 대하여 4 바이트 (AutoHotkey Basic 포함) 64-비트 빌드에 대하여 8 바이트입니다. 구조체나 DllCall을 사용하는 스크립트는 두 플랫폼에서 모두 올바르게 작동하려면 이 사실을 고려할 필요가 있습니다. 영향을 받는 구체적인 영역은 다음과 같습니다:

크기와 오프셋 계산은 A_PtrSize을 사용하십시오. DllCal()l, NumPut() 그리고 NumGet()에는 적절하게 Ptr 유형을 사용하십시오.

필드의 오프셋은 보통 그 앞에 있는 모든 필드의 전체 크기임을 기억하십시오. 또 핸들도 (HWND와 HBITMAP 같은 유형을 포함하여) 본질적으로 포인터-유형임을 명심하십시오.

/*
  typedef struct _PROCESS_INFORMATION {
    HANDLE hProcess;    // Ptr
    HANDLE hThread;
    DWORD  dwProcessId; // UInt (4 bytes)
    DWORD  dwThreadId;
  } PROCESS_INFORMATION, *LPPROCESS_INFORMATION;
*/
VarSetCapacity(pi, A_PtrSize*2 + 8) ; Ptr + Ptr + UInt + UInt
DllCall("CreateProcess", <omitted for brevity>, "Ptr", &pi, <omitted>)
hProcess    := NumGet(pi, 0)         ; Defaults to "Ptr".
hThread     := NumGet(pi, A_PtrSize) ;
dwProcessId := NumGet(pi, A_PtrSize*2,     "UInt")
dwProcessId := NumGet(pi, A_PtrSize*2 + 4, "UInt")