본문 바로가기
이미지맥스 그리고 루아(lua)/[응용] 보다 효율적인 사용법

[이미지맥스] 앱플레이어 hwnd 윈도우핸들 취득 방법 FindWindow(), FindWindowEx(), PostMessage(), SendMessage(), WM_MESSAGE

by 위치결정 2021. 7. 10.
반응형
-- 블루스택5 윈도우 핸들 취득
hwnd1 = FindWindow('Qt5154QWindowOwnDCIcon', 'BlueStacks')
hwnd2 = FindWindowEx(hwnd1, '', 'plrNativeInputWindowClass', 'plrNativeInputWindow')
hwnd3 = FindWindowEx(hwnd2, '', 'BlueStacksApp', '_ctl.Window')


-- LD앱플레이어 윈도우 핸들 취득
hwnd1 = FindWindow('LDPlayerMainFrame', caption)
hwnd2 = FindWindowEx(hwnd1, '', 'RenderWindow', 'TheRender')
hwnd3 = FindWindowEx(hwnd2, '', 'subWin', 'sub')

 

블루스택5 기준 hwnd 를 취득하는 코드입니다.

부모핸들링인 hwnd1 의 경우 window name 을 변경한 경우 'BlueStacks' 문자열을 블루스택 윈도우 이름에 맞춰 변경하시면 됩니다.

 

특별히 변경하지 않았다면 설치시 메인으로 설치되는 블루스택의 이름의 기본값은 BlueStacks 입니다.

hwnd1은 부모핸들로 블루스택 윈도우 최상단 클래스

hwnd2는 hwnd1의 자식핸들로 내부 인게임 화면틀이 되는 클래스

hwnd3는 hwnd2의 자식핸들로 내부 인게임 화면의 클래스

 

통상적으로 PostMessage()나 SendMessage() 활용시 hwnd2 를 사용하시면 됩니다.

Window spy++ 기준 블루스택5 hwnd 윈도우 클래스와 윈도우 이름 (변경 없이 초기설정일시)

 

-- WM CONSTANTS
VK_BACK = 8
VK_TAB = 9
VK_RETURN = 13
VK_SHIFT = 16
VK_CONTROL = 17
VK_ESCAPE = 27
VK_SPACE = 32

WM_SETTEXT = 12
WM_CLOSE = 16

WM_MOUSEMOVE = 512
WM_LBUTTONDOWN = 513
WM_LBUTTONUP = 514
WM_LBUTTONDBLCLK = 515
WM_RBUTTONDOWN = 516
WM_RBUTTONUP = 517
WM_RBUTTONDBLCLK = 518
WM_MBUTTONDOWN = 519
WM_MBUTTONUP = 520
WM_MBUTTONDBLCLK = 521
WM_MOUSEWHEEL = 522

WM_KEYFIRST = 256
WM_KEYDOWN = 256
WM_KEYUP = 257

WM_SYSKEYDOWN = 260
WM_SYSKEYUP = 261
WM_SYSCHAR = 262

WM_CHAR = 258
WM_PASTE = 770

-- 블루스택5 부모핸들, 자식핸들 취득
function findBluestack5(_string_caption)
    caption = _string_caption or 'BlueStacks'
    local hwnd1 = FindWindow('Qt5154QWindowOwnDCIcon', _string_caption)
    local hwnd2 = FindWindowEx(hwnd1, '', 'plrNativeInputWindowClass', 'plrNativeInputWindow')
    local hwnd3 = FindWindowEx(hwnd2, '', 'BlueStacksApp', '_ctl.Window')
    print('hwnd1 : '..hwnd1, 'hwnd2 : '..hwnd2, 'hwnd3 : '..hwnd3)
    return hwnd1, hwnd2, hwnd3
end

-- LD앱플레이어 부모핸들, 자식핸들 취득
function findLd(_string_caption)
    caption = _string_caption or 'LDPlayer'
    local hwnd1 = FindWindow('LDPlayerMainFrame', _string_caption)
    local hwnd2 = FindWindowEx(hwnd1, '', 'RenderWindow', 'TheRender')
    local hwnd3 = FindWindowEx(hwnd2, '', 'subWin', 'sub')
    print('hwnd1 : '..hwnd1, 'hwnd2 : '..hwnd2, 'hwnd3 : '..hwnd3)
    return hwnd1, hwnd2, hwnd3
end

-- 문자열 타이핑
function postString(_hwnd, _string)
    for i = 1, #_string do
        local string2char = _string:sub(i,i)
        local char2int = string.byte(string2char)
        PostMessage(_hwnd, WM_CHAR, char2int, '')
        print(string2char, char2int)
    end
    print('PostMessage : '.._string)
end

-- 엔터키 누름
function postReturn(_hwnd)
    PostMessage(_hwnd, WM_KEYDOWN, VK_RETURN, 0)
    print('PostMessage : <Enter>')
end

-- 키보드 누름
function postKeyDown(_hwnd, _int_key)
    PostMessage(_hwnd, WM_KEYDOWN, _int_key, 1)
    print('PostMessage_WM_KEYDOWN : '.._int_key)
end

-- 키보드 뗌
function postKeyUp(_hwnd, _int_key)
    PostMessage(_hwnd, WM_KEYUP, _int_key, 0)
    print('PostMessage_WM_KEYUP : '.._int_key)
end

-- 마우스 누름
function postMouseDown(_hwnd, _x, _y)
    PostMessage(_hwnd, WM_LBUTTONDOWN, 1, (_y * 0x10000) + _x)
    print('PostMessage_WM_NCLBUTTONDOWN : '.._x, _y)
end

-- 마우스 뗌
function postMouseUp(_hwnd, _x, _y)
    PostMessage(_hwnd, WM_LBUTTONUP, 0, (_y * 0x10000) + _x)
    print('PostMessage_WM_NCLBUTTONUP : '.._x, _y)
end

-- 마우스 클릭 (눌렀다 0.01초 후 뗌)
function postMouseClick(_hwnd, _x, _y)
    sendMouseDown(_hwnd, _x, _y)
    Sleep(10)
    sendMouseUp(_hwnd, _x, _y)
end

-- 부모 핸들 윈도우 종료
function postAppClose(_hwnd)
    PostMessage(_hwnd, WM_CLOSE, 0, 0)
end

 

이렇게 취득한 핸들링에 PostMessage() 함수를 이용하여 WM메세지를 송신할수있습니다.

문자열을 타이핑하는 함수 sendString(), Enter버튼을 누르는 sendReturn(), 각종 특수버튼 (ctrl, shift등)을 눌러야 할때 사용할 sendKey(), 키누름, 키뗌 sendKeydown(), sendKeyup(), 마우스좌버튼누름, 버튼뗌 sendMousedown(), sendMouseup() 등 활용해보시면 좋을듯하네요.

 

윈도우 핸들을 다룰수 있게 되면, 사실상 동작 자체는 이미지맥스에 이미 내장되어있는 키보드 함수 Keybd() 와 마우스 함수 Mouse() 동일합니다만, 인식앱을 변경하지 않아도 현재 인식앱을 벗어나 실행중인 다른 윈도우까지 콘트롤을 할수 있게 된다는 강점이 생깁니다.

 

윈도우 핸들 취득하여 인식대상 외부의 앱을 제어하는 방법도 좋지만, 이미지맥스 내부함수를 활용하여 필요에 따라 스크립트를 변경하여 인식대상을 변경하는것이 정신건강에 좋습니다.

반응형

댓글