[EnumWindows()]

Posted by 겨울에
2011. 9. 26. 13:05 scrap/ C/C++
출처 : http://blog.naver.com/ratmsma?Redirect=Log&logNo=40027853699



 >FindWindow는 탐색기건 뭐건간에 타이틀 바만 동일한 것의 윈도우 핸들을 반환하므로

>FindWindow()해서 가져온 것이 제가 작성한 프로그램이 아닐수가 있지 않습니까?

FindWindow는 타이틀 바(FindWindow의 두번째 인자, 즉 윈도우 네임) 뿐 아니라,
클래스 네임(첫번째인자)으로도 윈도우 탐색 작업이 가능합니다.

그러나 정작 FindWindow를 사용할 때의 문제점은 동일 클래스명, 동일 윈도우명을 가진 윈도우가
두 개 이상 다수 존재할 때, 그 중 첫번째 윈도우 만을 검색한 후 바로 탐색 작업을 중지한다는 데 있습니다.

즉, FindWindow를 for나 while 루프로 감싸 반복실행시켜도 언제나 똑같은 윈도우 핸들만을
리턴할 우려가 다분하다는 거지요.

해서, 이럴 경우엔 EnumWindows나 때에 따라서는 EnumChildWindows를 곁들여 사용하시는 것이
가장 속편할 듯 싶습니다.

// EnumWindows 사용법.

::EnumWindows (hWnd, EnumProc, NULL);

BOOL CALLBACK EnumProc(HWND hwnd, LPARAM lParam)
{
TCHAR buf[100];

GetClassName (hwnd, (LPTSTR)&buf, 100);
if ( _tcscmp( buf, _T("class_name") ) != 0 ) return TRUE;

// 타이틀바에 쓰여진 문자열 비교시엔 GetClassName대신 GetWindowText 사용.

// 원하는 코드 수행
return FALSE;
}

위 콜백함수에서 TRUE를 리턴하면 데스크탑 상의 모든 윈도우가 조회될 때까지 
콜백 루프가 반복해서 돌아갑니다. 반면 FALSE를 리턴하면 그 순간 탐색작업은 중단되지요.

만일 자작 윈도우와 기존 윈도우의 클래스 네임과 타이틀 네임이 정확하게 일치한다 했을 때는
두 윈도우(혹은 다수 윈도우)의 핸들이 모두 리턴되는데, 이때 특정 윈도우의 구별을 위해선
생각하기에 따라서 여러 방법을 다양하게 구사하실 수 있을 듯 싶습니다.

이를 테면, 윈도우 사이즈 비교라든가 아니면 윈도우들간 zorder 상의 위치,
혹은 어떤 child widnow나 parent 윈도우를 포함하고 있는지 등등... 

만일 자작 윈도우인 경우라면, 클래스 네임을 타 윈도우와 구별가능하게끔 독특하게 지어보세요.
그럼 EnumWindows까지 사용하실 필요없이 FindWindow로도 쉽게 검색하실 수 있을 듯 싶은데요.

 

 

 

[사용예]

탐색기를 닫는걸로 예를 들겠습니다...

dlg에서 예를 들자면,,,,,

initdlg()에서, 함수를 호출해주죠...

 

EnumWindows(CloseExplorer, 0);

 

고럼 이 함수는,,,,

 

BOOL CALLBACK CTest ::CloseExplorer(HWND hwnd, LPARAM lParam)

{

       TCHAR buf[100];

       GetClassName (hwnd, (LPTSTR)&buf, 100);
       if ( _tcscmp( buf, _T("ExplorerwClass") ) != 0 )

           PostMessage(hwnd, WM_CLOSE, 0, 0);  //ExplorerwClass는 스파이+에서 찾으셈..

 

      return true;

}


 요래하면 되겠죵?? ^ㅡ^

 

음... 난 또 다른 방법으로..탐색기를 죽였는데요...아래처럼.. ㅎ

 

 

bool CTEst::KillExplorer()
{
        char  szClass[MAX_PATH];
        HWND  hParent, hChild;  
 
        hParent = GetWindow(GetDesktopWindow(), GW_CHILD);//차일드 윈도우나 컨트롤의 윈도우 포인터를 얻는다.  
        hChild = GetWindow(hParent, GW_HWNDFIRST);
        while (hChild != NULL)
        {
                GetClassName(hChild, szClass, MAX_PATH);
                if (strcmp(szClass, "ExploreWClass") == 0)
                PostMessage(hChild, WM_CLOSE, 0, 0);
                hChild = GetWindow(hChild, GW_HWNDNEXT);
         }

 

        return true;

}

 

 

===>정리하자면,

 

탐색기창  클래스명     : ExploreWClass
내 컴퓨터 창 클래스명 : CabinetWClass
인터넷 창 클래스명     : IEFrame
static BOOL CALLBACK CloseExplorer(HWND hwnd, LPARAM lParam);//선언

EnumWindows(CloseExplorer, 0);//init()등 필요 함수에서 호출

BOOL CALLBACK CTest ::CloseExplorer(HWND hwnd, LPARAM lParam)
{
     TCHAR buf[100];
     GetClassName (hwnd, (LPTSTR)&buf, 100);
     if ( _tcscmp( buf, _T("ExplorerwClass") ) != 0 )
        PostMessage(hwnd, WM_CLOSE, 0, 0);  //ExplorerwClass는 스파이+에서 찾으셈.. 
     return true;

=>또는 ,
    CWnd* pdw;
    pdw=CWnd::FindWindow(_T("ExploreWClass"), NULL);
    if(pdw && ::IsWindow(*pdw))
       pdw->PostMessage(WM_CLOSE);
    return TRUE;    
}