;매크로상수,전역변수, 스크립트의 속성을 정의한다. 라이브러리를 로드한다.
#Include Gdip.ahk ; 비활성 윈도우의 이미지를 가져오는데 필요한 라이브러리, 현재 dx11이상 opengl로 출력되는 화면은 제대로 검출못함
#Include Gdip_ImageSearch.ahk ; 2개 이미지를 비교하는데 필요한 라이브러리
bmp폴더:=A_WorkingDir "\img\"
WinTitle:="Bluestacks App Player" ; 작업할 윈도우 타이틀
작업프로그램:="C:\Program Files\BlueStacks\HD-StartLauncher.exe" ; 작업프로그램실행파일. 경로포함
SetBatchLines, -1 ; 스크립트라인 실행후 10ms(기본값)의 지연을 없에므로써 최상의속도를 구현한다.
#NoEnv  ; 변수명을 해석할 때, 환경 변수를 무시한다. 변수명중복오류 방지. 빈값의 환경변수는 패싱해 특정명령문에서 속도를 높인다
#WinActivateForce ; 오토핫키에 특정윈도우활성화권한을 줌, 블루스택창 활성화에 사용

; 전역변수설정 ; 여기서 선언한 변수는 global을 사용안해도 전역변수가 됩니다.
global 자식창_핸들, 자식창_이름, 자식창x, 자식창y, 자식창w, 자식창h ; 여기선 복수개의 변수를 선언할거기 때문에 global 씀

; 매크로 구동전 초기화 자동실행
블루스택자식창핸들찾기() ; 블루스택2의 좌표정보, PostMessage입력에 사용될 (블루스택)핸들을 찾아냅니다.

;Gui 꾸미기
Gui, Font, S20 CDefault Bold, Verdana
Gui, Add, Text, x12 y10 h50 +Center , 스크립트중지/진행:F1키
Gui, Add, Button, x12 y50 h50 +Center gMainMacro, 스크립트시작:Insert키
Gui, Add, Button, x12 y100 h60 gGuiClose, 프로그램종료:Delete키
Gui, Font, S12 CDefault Bold, Verdana
Gui, Add, Text, x12 y170 h50 +Center , 블루스택비활성스샷 PrintScreen키로 `n 작동여부를 테스트해볼 수 있습니다.`n capture폴더에 저장
Gui, Show, Center AutoSize, 블루스택2 비활성매크로

return ; 위까지 자동실행 영역. 끝 /*핫키를 만나면 스크립트가 멈추기 때문에 핫키는 아래에 등록*/

; MainMacro: 서브루틴 안에 매크로 스크립트를 작성합니다. 메크로시작 insert키
MainMacro:
{
;Loop ; 무한루프
;{
/* 테스트 입니다.
무한루프안에 매크로를 만들면 매크로가 멈추지 않고 진행됩니다.  매크로를 일시정지/재진행하려면 F1키를 토글합니다.
무한루프안의 매크로 진행중에 다른 핫키 사용됩니다. ex) 매크로진행중 핫키PrintScreen::블루스택비활성스샷() 실행
*/
비활성드래그(300,300,500,500,2) ; x300,y300 -> x500,y500 좌표로 2의 속도로 드래그합니다. 속도크기를 높이면 슬라이딩을 줄입니다.
sleep,500
비활성드래그(500,500,300,300,2) ; x500,y500 -> x300,y300 좌표로 2의 속도로 드래그합니다.
sleep,500
if 비활성찾기("test",x,y,400,200,500,300) ; 비활성이미지를 찾으면 해당 좌표 비활성클릭을 합니다. \img폴더에 test.bmp 파일넣고 테스트
{
MsgBox,% "찾은좌표는 x" x " y" y " 입니다"
;비활성클릭(x,y) ; 위에서 찾은 x,y좌표를 클릭합니다. 비활성클릭(500,600)처럼 값을 지정하면, 500,600을 클릭합니다.
}
/* 비활성찾고클릭() 함수는 사용편의를 위해 찾기,클릭을 합쳐 놓았습니다.
전체화면검색시 비활성찾고클릭("이미지이름") 으로 간편하게 사용할 수 있고,
필요에 따라 세부옵션을 함수인자에 넣어 조정할 수 있습니다.
찾는범위를 줄이면 실행속도가 빨라집니다. 또한, 비슷한 이미지 다른좌표 찾는것을 방지할 수 있습니다.
비활성찾고클릭("이미지이름", 시작x,시작y,마지막x,마지막y,색상범위,제외할색상(0~0xFFFFFF) (이미지이름외 생략가능)
*/
if 비활성찾고클릭("test",400,200,500,300,7,0xFFFFFF) ; 검정색을 무시하고, 색상범위7이내의 400,200,500,300범위 안의 이미지를 찾음.
MsgBox, 비활성 찾고클릭 성공
else
MsgBox, 비활성 찾고클릭 실패

;sleep,100 ; 적당한 지연시간은 cpu과부하를 막아줍니다.
;}
}
return



; 핫키설정, 이벤트반응, 서브루틴 등등..
f1::pause ; 오토핫키 일시정지
f2::Reload
PrintScreen::블루스택비활성스샷()
insert::Gosub, MainMacro ; 메인매크로 스크립트 시작

delete:: ; delete 키를 눌렀을때 아래를 실행. 아래서브루틴들도 각각 아래 스크립트내용을 실행함.
GuiClose: ; Gui창이 닫히는 이벤트에 오토핫키를 종료.
{
BlockInput, MouseMoveoff ; 마우스 이동방지 끔
ifWinExist, %WinTitle%
{
CenterWindow(WinTitle) ; 종료시 블루스택을 화면 가운데로 가져와 활성화 시킵니다
WinActivate,%WinTitle% ;
}
else
{
Gui,Destroy
MsgBox, %wintitle% 프로그램은 실행중이 아닙니다
}
ExitApp ; 오토핫키 종료
}

; 함수를 정의합니다.

CenterWindow(WinTitle) ; 해당 윈도우를 모니터화면 가운데로 이동합니다.
{
    WinGetPos,,, Width, Height, %WinTitle%
    WinMove, %WinTitle%,, (A_ScreenWidth/2)-(Width/2), (A_ScreenHeight/2)-(Height/2)
}

블루스택자식창핸들찾기() ; 블루스택2의 좌표정보, PostMessage입력에 사용될 (블루스택)핸들을 찾아냅니다.
{
global 자식창_핸들, 자식창_이름, 자식창x, 자식창y, 자식창w, 자식창h, 블루스택핸들, WinTitle ; 이미 선언된 전역변수 값을 함수내에서 공유합니다.
IfWinNotExist,%WinTitle% ; 블루스택2가 실행되지 않으면 함수를 종료합니다.
{
MsgBox, 오류, 블루스택2가 실행되지 않았습니다.
Run C:\Program Files\BlueStacks\HD-StartLauncher.exe
sleep,5000
return 블루스택자식창핸들찾기()
}
WinActivate,%WinTitle%
while !WinActive(WinTitle) ; 블루스택2창 활성화될때까지
sleep,100
WinGetPos,x,y,,,%WinTitle% ; 블루스택2창의 좌상단 x,y좌표를 구합니다.
MouseMove, x+10, y+40, 0 ; 마우스커서를 블루스택창에서 자식윈도우위로 옮깁니다.
MouseGetPos, , , 자식창_핸들, 자식창_이름 ; 마우스커서 위치의 자식창이름, 자식창핸들을 얻음
MouseGetPos, , , ,블루스택핸들,3 ; 마우스커서 위치의 자식윈도우의핸들을 찾아서 hclwnd변수에 넣음
WinMove,%WinTitle%,,0,0 ; 해당 윈도우의 좌표를 이동하고 [사이즈를 조절], 비활성작업시 모니터해상도를 벗어나게 만들면 숨길 수 있습니다.  ex)WinMove,%WinTitle%,,2000,0
ControlGetPos, 자식창x, 자식창y, 자식창w, 자식창h, %자식창_이름%, ahk_id %자식창_핸들% ; 자식창의 x,y와 폭w 높이h를 받음
return
}

;비활성찾고클릭("이미지이름", 시작x,시작y,마지막x,마지막y,색상범위,제외할색상(0~0xFFFFFF) (이미지이름외 생략가능)
비활성찾고클릭(image, sx=0, sy=0, ex="", ey="", n=0, trans=0) ; 비활성이미지서치 찾고클릭 간소화함수, 이미지 찾아서 클릭하고 참값을 돌려주어 조건문에 활용가능
{
if 비활성찾기(image,x,y,sx,sy,ex,ey,n,trans)
{
비활성클릭(x,y)
return true
}
return false
}

;비활성찾기("이미지이름", 찾은x,찾은y,시작x,시작y,마지막x,마지막y,색상범위,제외할색상(0~0xFFFFFF) (이미지이름외 생략가능)
비활성찾기(image, byref vx="", byref vy="", sx=0, sy=0, ex="", ey="", n=0, trans=0 ) ; 이미지파일 비교검색에 \img폴더의 bmp파일을 사용합니다.
{
global 자식창_핸들, 자식창x, 자식창y, 자식창w, 자식창h,bmp폴더 ; 이미 선언된 전역변수 값을 함수내에서 공유합니다.
if ex=
ex:=자식창w ; ex인자 생략하면 블루스택화면 w값
else
ex:=자식창x+ex ; 자식창시작위치에 사용자가 원하는 검색끝x값을 더해 완성
if ey=
ey:=자식창h ; ey인자 생략하면 블루스택화면 h값
else
ey:=자식창y+ey ; 자식창시작위치에 사용자가 원하는 검색끝y값을 더해 완성
image=%image%.bmp
같은이미지찾음:=0
if !fileExist(bmp폴더 image) ; 비교할 이미지파일이 없으면 함수종료
{
MsgBox, 오류, 비교할 이미지파일 "%image%"이 `n%bmp폴더% 폴더에 존재하지 않습니다.
return false
}
pToken:=Gdip_Startup() ; Gdip 활성화
pBitmapHayStack := Gdip_BitmapFromHWND(자식창_핸들) ; 자식창에서 비활성화면을 가져온 후 pBitmap에 저장
loop,100 ; 블루스택2 비활성, 제대로 나온화면 찾기 100회 시도
{
Gdip_FromARGB(Gdip_GetPixel(pBitmapHayStack, 10, 30),A,R,G,B) ; 10,30 좌표의
if !R and !G and !B ; 검정픽셀이면(rgb각각 0값)
{
if a_index=100
{
MsgBox, 오류, BlackScreen! 블루스택2 비활성 화면을 찾지 못했습니다.
break
}
pBitmapHayStack := Gdip_BitmapFromHWND(자식창_핸들) ; 자식창에서 비활성화면을 가져온 후 pBitmap에 저장
}
else ; 블랙스크린이 아니면, 이미지비교시작
{
pBitmapHayStack := Gdip_CloneBitmapArea(pBitmapHayStack, 자식창x, 자식창y, ex, ey)
pBitmapNeedle:=Gdip_CreateBitmapFromFile(bmp폴더 image) 
;if Gdip_ImageSearch(pBitmapHayStack,pBitmapNeedle,list,0,0,0,0,10,0x000000,1,1)
if Gdip_ImageSearch(pBitmapHayStack,pBitmapNeedle,list,sx,sy,ex,ey,n,trans)
{  
StringSplit, LISTArray, LIST, `,  
vx:=LISTArray1
vy:=LISTArray2
같은이미지찾음:=1
}
else
같은이미지찾음:=0
break
}
}
Gdip_DisposeImage(pBitmapHayStack), Gdip_DisposeImage(pBitmapNeedle)
Gdip_Shutdown(pToken)
return 같은이미지찾음
}

블루스택비활성스샷()
{
global 자식창_핸들, 자식창x, 자식창y, 자식창w, 자식창h
if !자식창_핸들
return false
캡쳐폴더명=capture ; 캡쳐폴더명 설정
if not fileExist(A_WorkingDir "\" 캡쳐폴더명) ; 캡쳐폴더가 존재하지 않으면
FileCreateDir, %캡쳐폴더명% ; 캡쳐폴더 생성
월일시간:=% a_mm "월" a_dd "일 " A_Hour "시" A_MM "분" A_Sec "초"
캡쳐파일명:=A_WorkingDir "\" 캡쳐폴더명 "\" 월일시간 ".png" ; 확장명에 따라 저장방식이 달라짐. 원본화질의 용량적은 png로 저장
pToken := Gdip_Startup() ; Gdip 활성화
pBitmap := Gdip_BitmapFromHWND(자식창_핸들) ; 자식창에서 비활성화면을 가져온 후 pBitmap에 저장
IfWinExist,Bluestacks App Player ; 블루스택용
{
loop,100
{
Gdip_FromARGB(Gdip_GetPixel(pBitmap, 10, 30),A,R,G,B) ; 비활성 블루스택이미지의 10,30좌표 1개의 픽셀색상정보
if !R and !G and !B ; 검정픽셀이면(블랙스크린이면)
{
if A_Index=100
{
MsgBox, 오류, BlackScreen! 블루스택2 비활성 화면을 찾지 못했습니다.
break
}
pBitmap := Gdip_BitmapFromHWND(자식창_핸들) ; 자식창에서 비활성화면을 가져온 후 pBitmap에 저장
}
else ; 블랙스크린이 아니면
{
pBitmap := Gdip_CloneBitmapArea(pBitmap, 자식창x, 자식창y, 자식창w, 자식창h) ; 자식창 좌표에 맞게 이미지 잘라낸 후 pBitmap에 다시 저장, 이줄을 생략해주면 부모창 그대로 캡쳐한다.
If (pBitmap = -1) ; pBitmap에 오류가 없는지.. 이상없으면 chord소리내고 이미지파일 저장함
MsgBox, 오류, 이미지가 없습니다.
else
{
SoundPlay, %A_WinDir%\Media\chord.wav
Gdip_SaveBitmapToFile(pBitmap, 캡쳐파일명) ; 비트맵hex코드가 담긴 pBitmap을 파일로 저장
}
break
}
}
}
Gdip_DisposeImage(pBitmap) ;  pBitmap 이미지데이터 메모리에서 지움
Gdip_Shutdown(pToken) ; Gdip 종료
return
}

/* 비활성 클릭,드래그
*/
비활성클릭(x,y)
{
global 블루스택핸들 ; 이미 선언된 전역변수 값을 함수내에서 공유합니다.
lparam:=x|y<<16 ; x,y 좌표값
PostMessage,0x201,0x0000,%lparam%,,ahk_Id %블루스택핸들% ; PostMessage 왼쪽 마우스버튼 down
PostMessage,0x202,0x0000,%lparam%,,ahk_Id %블루스택핸들% ; PostMessage 왼쪽 마우스버튼 up
return
}

비활성드래그(sx,sy,ex,ey,speed="") ; sx,sy는 드래그시작지점, ex,et는 드래그 도착지점입니다. (speed로 감도를 조절합니다. 생략가능)
{
global 블루스택핸들 ; 이미 선언된 전역변수 값을 함수내에서 공유합니다.
if speed= ; 마우스스피드 생략하면 오토핫키 기본값 2 가져옴
speed:=A_DefaultMouseSpeed
else if ( speed<0 or speed>100 )
{
MsgBox, speed값에 음수는 넣을 수 없습니다. (0~100범위 입력가능)
return false
}
lparam:=sx|sy<<16 ; 시작좌표
PostMessage,0x201,0x0000,%lparam%,,ahk_Id %블루스택핸들% ; PostMessage 왼쪽 마우스버튼 down
loop,% speed-1 ; 목표지점까지 drag를 위해 반복합니다. speed 값을 결국 드래그 감도에 영향을 줍니다.
{
sleep, 20 ; 너무 낮은값을 주면 제대로 클릭이 안되고 반대로 너무 높은값은 시간이 오래걸립니다.
x:=Round(sx+(ex-sx)/speed*a_index) ; 목표지점까지 조금씩 이동할 x좌표를 구합니다.
y:=Round(sy+(ey-sy)/speed*a_index) ; 목표지점까지 조금씩 이동할 y좌표를 구합니다.
lparam:=x|y<<16 ; 조금씩이동되는 좌표
PostMessage,0x200,0x0001,%lparam%,,ahk_Id %블루스택핸들% ; PostMessage 왼쪽버튼 down유지(wparam값 0x0001)하면서 마우스이동
}
lparam:=ex|ey<<16 ; 마지막좌표
sleep, 100 ; 값이 낮을수록 드래그후 슬라이딩하는 길이가 길어짐.
PostMessage,0x200,0x0001,%lparam%,,ahk_Id %블루스택핸들% ; PostMessage 왼쪽버튼 down유지(wparam값 0x0001)하면서 마우스이동
sleep, 100 ; 여기서 슬립생략하면 슬라이딩 안함.
PostMessage,0x202,0x0000,%lparam%,,ahk_Id %블루스택핸들% ; PostMessage 왼쪽 마우스버튼 up
return
}



답글