윈도우 핸들이란 무엇인지 알아봅시다

Posted by 겨울에
2014. 11. 15. 10:02 scrap/ Visual Basic
출처 : http://cluster1.cafe.daum.net/_c21_/bbs_search_read?grpid=qvQp&fldid=8mOp&datanum=23&openArticle=true&docid=qvQp8mOp2320060320174013
         비베전문가되기 - [API 응용 팁] 윈도우 핸들이란 무엇인지 알아봅시다
            글쓴이 : 서당개3년 

'먼저 프로젝트 --> 모듈 추가 를 눌러서 표준 모듈을 하나 생성합니다.

'폼에는 ListBox 한개를 그립니다.

'표준모듈에서 프로시져를 하나 작성합니다

'Public Sub Main()

'아래 그림과 같이 시작개체를 변경합니다.



Option Explicit -표준 모듈 부분 -

'외부적인 프로그램 제어를 할때 우리는 흔히 "핸들을 얻는다" 라는 표현을 쓴다.
'핸들이란 무엇인가? 자동차에도 핸들이 있다
'우리가 원하는 방향으로 자유로운 이동을 가능하게 해주는 도구이다
'그럼 윈도우 핸들이란 무엇인가?
'멀티태스킹이 가능한 윈도우 체제로 넘어오면서 동시에 여러가지 작업이 가능하다보니
'우리의 화면에는 수많은 윈도우들이 보여질때가 있다
'이때 시스템에서는 이들을 구분할수 있는 무언가가 필요하게 되었고
'간략하게 말하면 구분이 되는 근거가 바로 핸들이란것이다
'우리는 이 핸들이란걸 구해서 많은 일들을 할수 있게 된다
'내가 만든 프로그램이 아니어도 내가 원하는 방식으로 재 동작할수 있게끔 유도할수도 있는것이다.
'오늘은 이 핸들이란걸 구하는 많은 방식중의 한가지를 알아본다

 

Public Declare Function FindWindow Lib "user32" Alias "FindWindowA" ( _
   ByVal lpClassName As String, _
   ByVal lpWindowName As String) As Long
'FindWindow : 현재 실행중인 윈도우에서 특정윈도우를 찾는다
'lpClassName : 클래스명
'lpWindowName : 캡션명

Public Declare Function EnumChildWindows Lib "user32" ( _
   ByVal hWndParent As Long, _
   ByVal lpEnumFunc As Long, _
   ByVal lParam As Long) As Long

'EnumChildWindows : 부모윈도우의 핸들값을 근거로 모든 자식 윈도우를 반환한다
'hWndParent :부모 윈도우 핸들
'lpEnumFunc : 부모 윈도우가 소유한 모든 자식윈도우를 콜백함수로 전달한다(프로시져의 주소)
'lParam : 콜백함수가 참조할 값

 

Public Declare Function GetClassName Lib "user32" Alias "GetClassNameA" ( _
   ByVal hwnd As Long, _
   ByVal lpClassName As String, _
   ByVal nMaxCount As Long) As Long

'GetClassName : 핸들값을 근거로 해당 윈도우의 클래스명을 얻는다
'hwnd : 핸들
'lpClassName : 구한 클래스명을 담게될 문자변수
'nMaxCount : 문자의 범위 지정

 

Public lngParent As Long
Public sClass As String
Public Const iBuff As Integer = 255

Public Sub main()

   '프로젝트가 시작하면서 Daum 사이트에 연결된 브라우져를 찾습니다
   lngParent = FindWindow("IEFrame", "Daum - 우리 인터넷, Daum - Microsoft Internet Explorer")
   If lngParent <> 0 Then '찾았으면 핸들값을 찾지 못하면 0 을
      '부모 윈도우의 핸들값을 넘겨주면 모든 자식 윈도우를 찾는 API 함수
      'EnumChildWindows 함수는 모든 자식윈도우를 처리하기 전까지는 True 를 갖게되고
      '모든 처리가 완료되면 False 를 반환하며 이때 함수가 종료됩니다.
      '프로시져의 주소를 넘겨주었고 함수는 해당 프로시져를 실행하고 옵니다.
      '해당 프로시져는 Function 이므로 실행하고 올때는 반환값을 가지고 오겠죠
      EnumChildWindows lngParent, AddressOf EnumChild, 0
      'AddressOf 연산자는 프로시져의 주소를 넘겨줍니다
      '넘어가는 프로시져는 반드시 "표준 모듈" 의 프로시져이어야 합니다.
      '그래서 시작개체를 Form1 이 아닌 sub main() 으로 변경해 준겁니다.
   End If
   '모든 처리가 끝났으니 폼1을 보이고
   frmHandle.Show
   '폼1의 캡션을 찾은 자식윈도우 갯수로 바꾼다.
   frmHandle.Caption = CStr(frmHandle.List1.ListCount)
End Sub

Public Function EnumChild(ByVal hwnd As Long, ByVal lp As Long) As Boolean
   Dim tmp As String * 255 '문자변수가 갖을수 있는 문자의 범위를 255로 지정
   Dim ret As Long
   
   '넘겨받은 자식윈도의 핸들값으로 클래스명을 갖는다
   'hwnd : 자식윈도 핸들값
   'tmp : 클래스명을 받아올 문자변수
   'iBuff : 문자가 최대수용가능한 길이를 지정한 숫자변수
   ret = GetClassName(hwnd, tmp, iBuff)
   '최대공간을 255문자로 지정해서 클래스명을 받아오는 문자변수에는
   'Null 값이 포함되서 넘어온다 Null 값을 찾아서 걸러주는 역활을 한다
   sClass = Left(tmp, InStr(tmp, Chr(0)) - 1)
   '폼1 의 리스트박스에 해당 값을 쓴다
   frmHandle.List1.AddItem sClass & "     " & CStr(hwnd)
   EnumChild = True
End Function

'바로 이어서 이렇게 구해진 핸들을 가지고 많은 일들을 할수가 있는데

'그중 간단한 예제를 하나 들어보겠습니다

'폼에 커맨드버튼 하나를 생성해주고 아래와 같이 코딩해 줍니다.

Option Explicit -폼 모듈 부분-
'특정 윈도우의 문자를 바꾸어주는 함수

Private Declare Function SetWindowText Lib "user32" Alias "SetWindowTextA" ( _
   ByVal hwnd As Long, _
   ByVal lpString As String) As Long

 

Private Sub Command1_Click()
   '이전 글 에서 설명한데로 FindWindow 함수로 구해진 부모핸들을 이용해
   '익스플로러 제목 표시줄에 뜬 문자를 바꾸어줍니다
   SetWindowText lngParent, "내맘데로 원하는데로"
End Sub


'아래와 같이 바뀌는걸 확인할수 있습니다. 

'비슷한 방법으로 자동 접속을 시도한다던지 마우스나 키보드를 직접 제어하지 않고도

'API 함수를 이용해서 클릭효과나 이벤트 발생등등 여러가지를 할수가 있게 됩니다

'그건 다음에 또 기회가 되면 올리도록 하지요

'그럼 즐공하세요