원하는 윈도우 찾고 포커스하기(getHwnd)

원하는 윈도우 찾고 포커스하기(getHwnd)

getHwnd라는 메소드를 직접 만들었다. 우선, 띄워져 있는 윈도우 목록을 전부 찾을 수 있는 EnumWindows 을 활용해 창을 전부 조사한다. 이후 클래스 네임, 제목표시줄 등을 이용해 핸들값(HWND)을 얻는다. 얻은 핸들값에 대해 ShowWindow를 사용해서 최소화 복원을 하고, SetForegroundWindow를 사용해서 윈도우를 포커스한다.

찾는 법은 핸들의 클래스네임, 제목표시줄, x좌표 세 가지를 이용해 찾을 수 있다.

(1) 클래스네임으로 윈도우 찾기

HWND hwnd=m.getHwnd(“IEFrame”,null,null);

라고 쓰면 “IEFrame”, 즉 인터넷 익스플로러를 찾는다.

(2) 제목표시줄로 윈도우 찾기

HWND hwnd=m.getHwnd(null,”네이버”,null);

라고 쓰면 제목표시줄에 “네이버”라는 스트링이 포함된 창을 찾는다. indexOf를 사용했다.

(3) 창의 x좌표로 윈도우 찾기

HWND hwnd=m.getHwnd(null,null,500);

라고 쓰면 창의 x좌표가 500보다 같거나 큰 창을 불러온다. 만약 -500을 주면 500보다 같거나 작은 창을 불러온다.

주의할 점은 여러 개의 핸들이 해당되어도 단 한개의 핸들(HWND)만 리턴된다는 점이다. 그러므로 (1),(2),(3)의 조합을 섞어 사용하여 한 개의 핸들만 띄워질 수 있도록 해야 한다.

참고)showWindow

 

SW_HIDE 0 보이지 않도록 한다.

SW_SHOWNORMAL 1 윈도우를 보이도록 하되 최대화 or 최소화 되어있다면 원래상태로 되돌린다.

SW_SHOWMINIMIZED 2 윈도우를 활성화 하고 최소화 한다.

SW_MAXIMIZE 3 최대화 한다.

SW_SHOWNOACTIVATE 4 윈도우를 보이도록 하지만 활성화 하지 않는다.

SW_SHOW  5 윈도우를 보이도록 한다.

SW_MINIMIZE 6 최소화 한 후 이전 윈도우를 활성화한다.

SW_SHOWMINNOACTIVE 7 윈도우를 최소화 하지만 활성화 하지는 않는다.

SW_SHOWNA 8 윈도우를 보이도록 하지만 활성화 하지는 않는다.

SW_RESTORE 9 원 상태로 되돌린다.

SW_SHOWDEFAULT 10 윈도우 생성시의 Flag 값에 따라 설정합니다.

SW_FORCEMINIMIZE 11 최소화 한다.

package com;

import com.sun.jna.Native;
import com.sun.jna.Pointer;
import com.sun.jna.platform.win32.*;
import com.sun.jna.platform.win32.WinDef.HWND;
import com.sun.jna.platform.win32.WinDef.RECT;
import com.sun.jna.platform.win32.WinUser.WNDENUMPROC;

public class MainClass {

 public static void main(String[] args) {
 MainClass m=new MainClass();
  
 HWND hwnd=m.getHwnd(null,”getnum2″,null);
 if(hwnd!=null){
  User32.INSTANCE.ShowWindow(hwnd,9);//최소화 되어있을 경우 복원
  User32.INSTANCE.SetForegroundWindow(hwnd);
 }
 else{
  System.out.println(“윈도우를 찾을 수 없습니다.”);
 }
 }
 
 
 
 public String wcls;
 public String wtitle;
 public static Integer wx;
 public static HWND res;

 public HWND getHwnd(String cls,String title, Integer x){

  res=null;
  wcls=cls;
  wtitle=title;
  wx=x;
 
  try{
   User32.INSTANCE.EnumWindows(new WNDENUMPROC() {
             int count = 0;

             public boolean callback(HWND hWnd, Pointer arg1) {
                 char[] windowText = new char[512];
                 User32.INSTANCE.GetWindowText(hWnd, windowText, 512);
                 String wText = Native.toString(windowText);
                 RECT rectangle = new RECT();
                 User32.INSTANCE.GetWindowRect(hWnd, rectangle);
                
                 //숨겨져 있는 창은 제외하고 찾는다. 최소화 되어있는 창은 포함한다.
                 //rectangle.left값이 -32000일 경우 최소화되어 있는 창이다.
                 if (wText.isEmpty() ||
                    !(User32.INSTANCE.IsWindowVisible(hWnd))) {
                    return true;
                 }
                
                 //핸들의 클래스 네임 얻기
                 char[] c=new char[512];
                 User32.INSTANCE.GetClassName(hWnd, c, 512);
                 String clsName=String.valueOf(c).trim();
                
                 //조건 세 개를 만족하면, 핸들을 돌려줌
                 int check=0;
                
                 //조건1: 요청 클래스네임이 널이거나, 클래스네임과 일치할 경우 체크를 증가
                 if(wcls==null){//”IEFrame”
                  check++;
                 }
                 else if(clsName.equals(wcls)){ //&& wcls!=null
                  check++;
                 }
                
                 //조건2: 제목표시줄이 널이거나, 원하는 글자가 포함되어 있다면 체크를 증가
                 if(wtitle==null){
                  check++;
                 }
                 else if(wText.indexOf(wtitle)>=0){
                  check++;
                 }
                
                 //조건3
                 if(wx==null){
                  //널이라면 안적은걸로 간주
                  check++;
                 }
                 else if(wx>0){
                  if(rectangle.left>=wx){
                   //wx가 500이라면  x좌표가 500 이상인 창만 합격
                   check++;
                  }
                 }
                 else if(wx<0){
                  if(rectangle.left<=(-wx)){
                   //wx가 -500이라면  x좌표가 500 이하인 창만 합격
                   check++;
                  }
                 }
                 //조건 3개를 충족했다면 핸들을 돌려줌
                 if(check==3){
                 res=hWnd;
                
                 System.out.println(
                          “hwnd:”+hWnd+”,”+
                          “번호:” + (++count) + “,텍스트:” + wText+”,”+
                          “위치:(“+rectangle.left+”,”+rectangle.top+”)~(“+rectangle.right+”,”+rectangle.bottom+”),”+
                          “클래스네임:”+clsName+”,”+
                          “상태:”+User32.INSTANCE.IsWindowVisible(hWnd));
                 }
                 return true;
             }
         }, null);
  
  }catch(Exception ex){System.out.println(ex.getMessage());}
 
  return res;
 
 }

}