프날 오토핫키 강좌

[프날 오토핫키] GDI+ (gdip) #6: 특정 창 이미지 가져오기

728x90

지난 강좌에서는 스크린 전체, 혹은 특정 영역에서 비트맵을 가져오는 함수로 Gdip_BitmapFromScreen()함수를 배웠습니다.

이번 강좌는 조금 쉬어가는 시간으로, 스크린 기준으로 비트맵을 가져오는 것이 아닌 특정 창에서 비트맵을 가져오는 방법을 배워보겠습니다.

 


 윈도우 핸들(hWnd) 

우선적으로, '핸들'에 대해서 이해하셔야합니다. 이미 알고계신 분은 이 부분을 건너뛰셔도 좋습니다.

 

원래 '핸들'은 서로 다른 구성 요소끼리 겹치지 않는 고유의 이름을 뜻합니다. 종류에 따라 파일 핸들, 윈도우 핸들, 그래픽 객체 핸들(ex: 펜 핸들, 브러시 핸들) 등으로 불립니다.

 

이 중에서도 우리가 다룰 '윈도우 핸들'이란, 이름에서도 알 수 있듯 창끼리 겹치지 않는 고유 넘버입니다. 같은 타이틀을 가진 창은 있을 수 있어도, 같은 핸들값을 가진 창은 없다는 뜻입니다. 따라서, 핸들 값을 이용하면 특정한 창에서만 비트맵을 가져올 수 있습니다.

 

여담으로, 윈도우 핸들을 hWnd라고도 하는데, h(handle)와 Wnd(Window)가 합쳐진 말입니다.


 타이틀로 핸들 구하는 법 

GDI+는 윈도우 타이틀보단 핸들 값으로 윈도우를 특정 짓는 경우가 많습니다. 따라서 우리는 타이틀만으로 핸들 값을 구할 수 있어야 GDI+에서 써먹을 수 있습니다.

 

오토핫키에는 내장 된 명령어로 크게 두 가지 방법이 있는데, 하나는 WinGet 명령어를 이용하는 것이고 하나는 WinExist()함수를 이용하는 것입니다.

 

우리는 WinExist() 함수를 이용하여 구해보겠습니다. 내장되어있는 함수이기 때문에 따로 정의할 필요는 없습니다.

  • 매개 변수: 핸들 값을 구하고자 하는 창의 타이틀
  • 반환 값: 해당 타이틀을 가진 창의 핸들 값

예를 들어, 아래와 같은 식입니다.

hWnd := WinExist("제목 없음 - Windows 메모장")

→ 변수 hWnd에는 "제목 없음 - Windows 메모장"의 핸들 값이 들어갑니다.

 


 특정 창에서 비트맵 가져오기 

이제 본격적으로 특정 창에서 비트맵을 가져오겠습니다. 저번 강에서 배웠던 함수와 비슷한 이름인 Gdip_BitmapFromHWND() 함수를 이용하겠습니다.

Gdip_BitmapFromHWND()

기능: 특정 핸들 값을 가진 창에서 비트맵을 가져온다.
  • 매개 변수: 비트맵을 가져 올 창의 핸들 값
  • 반환 값: 가져온 비트맵의 메모리 주소

감이 오시죠? 저번 강에서와 방법은 동일한데, Gdip_BitmapFromScreen()이 아닌 Gdip_BitmapFromHWND()를 써 주어야 한다는 점과 핸들 값을 구하는 과정을 먼저 해주어야 한다는 점이 다르네요.

 

#Include Gdip_All.ahk
pToken := Gdip_Startup()

pBitmap := Gdip_BitmapFromHwnd(WinExist("제목  없음 - Windows 메모장"))
Gdip_SaveBitmapToFile(pBitmap, A_Desktop "\result.png")
Gdip_DisposeImage(pBitmap)

Gdip_Shutdown(pToken)
ExitApp

Test.ahk
0.00MB

지난 강에서 배웠던 Gdip_SaveBitmapToFile()을 통해 가져온 비트맵을 파일로 저장해주었고, 더이상 쓰지 않는 비트맵을 Dispose해주었습니다.

 

Gdip_BitmapFromHWND()함수의 매개변수로 WinExist()함수를 직접 넣어줌으로써 핸들 값을 넘겨주었다는 점 또한 보실 수 있습니다.

 


 저장된 사진이랑 실제 UI랑은 다릅니다 

** 여담입니다. 안 읽으셔도 됩니다. **

 

위 예제로 저장된 사진을 보시면, 실제로 여러분들이 보시던 창과는 다르게 캡처되어있는 모습을 볼 수 있습니다. 물론 안 그런 사람도 있고요.

 

GDI+에는 printWindow라는 가상의 창을 제작해서 붙여주는 함수가 있습니다. (이렇게 간단히 설명드리지 못하는 건데, 조금 많이 잘못 설명드려보았습니다. DC라는 것의 개념을 아셔야지 설명이 되어서요.) Gdip_BitmapFromHWND는 이 printWindow함수를 참조하는데, 이 함수가 만들어내는 '가상의 창'이 아마 여러분의 UI와는 좀 다를 것입니다. 뭐 같을수도 있고요. 이건 PC환경의 차이니까요.

 

Windows 10이 대중화된 요즘엔 이 윈도우 테두리의 차이로 인해 저장된 이미지와 실제 윈도우끼리의 좌표 차이가 조금 날 것 처럼 보이는 것도 사실입니다. 실제로 사진만 놓고 보면 가로 8px쯤 차이가 납니다.

 

하지만 괜찮습니다. 여러분이 Windows 10을 쓰고 있더라도, 실제 여러분이 보시는 창의 좌표는 여러분이 직접 캡처한 그 사진과 같은 식으로 계산되기 때문에 좌표가 달리 계산될 일은 없습니다.

 

못 믿으시겠다고요? Windows Spy를 켜고 Windows 10에서 메모장을 켠 뒤, 왼쪽 테두리보다 아주아주 살짝 더 왼쪽 위치에 마우스를 위치시킨 후에 Window(Relative, Defult) 좌표를 읽어보세요. 분명 마우스는 창보다 왼쪽에 있는데, X 좌표는 음수가 아닌 것을 볼 수 있습니다. 이는 여러분이 실제 보시는 화면(왼쪽 사진)이 아닌, 가상으로 생성된 창(오른쪽 사진)을 기준으로 좌표를 계산하기 때문입니다. 좌표 작업을 하실 때 이런 차이는 신경을 안쓰셔도 된다는 뜻입니다.

왼쪽: 실제 윈도우 / 오른쪽: GDI+를 이용해 캡처


 이번 강에서의 gdip 함수 

Gdip_BitmapFromHWND()

매개 변수: 핸들 값
반환 값: 받은 핸들 값에서 가져온 비트맵의 메모리 주소

 

 

 

 

반응형