원하는 윈도우 찾고 포커스하기(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;
}
}