C++Builder Programming Forum
C++Builder  |  Delphi  |  FireMonkey  |  C/C++  |  Free Pascal  |  Firebird
볼랜드포럼 BorlandForum
 경고! 게시물 작성자의 사전 허락없는 메일주소 추출행위 절대 금지
C++빌더 포럼
Q & A
FAQ
팁&트릭
강좌/문서
자료실
컴포넌트/라이브러리
메신저 프로젝트
볼랜드포럼 홈
헤드라인 뉴스
IT 뉴스
공지사항
자유게시판
해피 브레이크
공동 프로젝트
구인/구직
회원 장터
건의사항
운영진 게시판
회원 메뉴
북마크
볼랜드포럼 광고 모집

C++빌더 팁&트릭
C++Builder Programming Tip&Tricks
[1006] 특정한 클래스명, 캡션명 또는 일부 명칭이라도 포함하는 윈도 찾아주는 클래스.
김태선 [cppbuilder] 8721 읽음    2010-07-30 18:20
윈도우에 떠 있거나 숨어 있거나 간에 모든 창의 핸들 그리고
클래스명, 캡션(WindowText)명 중에 원하는 것만 뽑아 내고 싶을 때가 있습니다.
이건 홍익인간 정신에 의해 이미 널리 알려진 것이라,
구현하는 것은 매우 쉽습니다.

그러나 아는 것이고 자료가 풍부하지만 막상 구현하려고 하면 일정한 시간이 걸리게 마련입니다.
또 이 기능을 멋지게 클래스화 까지 시키려면 한두시간 소비하기도 합니다. 콜백 함수가 있어
클래스화 하지 않으면 소스가 좀 방만해지기도 하죠.
그래서 이 기능을 일반성 있게 클래스로 구현한 김에 올려 둡니다.

붙여넣기 신공으로 쉽게 쓸수 있게 만들었습니다.
소스는 아래와 같고, 첨부 파일 내용과 같습니다.



#ifndef __CFindEnumWindow_H
#define __CFindEnumWindow_H

//---------------------------------------------------------------------------
// 지정한 클래스와 특정 문자열을 포함하는 윈도 찾기 클래스
//	 복수개를 찾아주는데, 핸들, 그 윈도 클래스명, 윈도 캡션명을 쉽게 조회할 수 있다.
//
// Written by KTS

class CFindEnumChildWindow
{
private:
	HWND	hParent;
	TList 	*List;
	char  	*sClassName;
	bool	bClassNameSubString;
	char	*sTitle;
	bool	bTitleSubString;
	char	Buffer[1024];

private:
	static BOOL CALLBACK EnumChildWndProc(HWND hwnd, LPARAM lParam)
	{
		CFindEnumChildWindow *This = reinterpret_cast(lParam);
		char *text = This->Buffer;
		if (This->sClassName != NULL)
		{
			if (GetClassName(hwnd, text, 1023))
			{
				//TRACE("%s", text);
				if ((!This->bClassNameSubString && !strcmp(text, This->sClassName)) ||
					(This->bClassNameSubString && strstr(text, This->sClassName)))
				{
					if (This->sTitle != NULL)
					{
						text[0] = 0;
						GetWindowText(hwnd, text, 1023);
						if ((!This->bTitleSubString && !strcmp(text, This->sTitle)) ||
							(This->bTitleSubString && strstr(text, This->sTitle)))
						{
							This->List->Add(hwnd);
						}
					}
					else
						This->List->Add(hwnd);
				}
			}
		}
		else
		{
			if (This->sTitle != NULL)
			{
				text[0] = 0;
				GetWindowText(hwnd, text, 1023);
				if ((!This->bTitleSubString && !strcmp(text, This->sTitle)) ||
					(This->bTitleSubString && strstr(text, This->sTitle)))
				{
					This->List->Add(hwnd);
				}
			}
		}
		return TRUE;
	}
	int	GetCount()
	{
		return List->Count;
	}
	HWND GetHandle(int index)
	{
		if (index >= List->Count || List->Count <= 0)
			return NULL;
		return List->Items[index];
	}
	String 	_GetClassName(int index)
	{
		if (index >= List->Count || List->Count <= 0)
			return NULL;
		char *text = Buffer;
		GetClassName(Handles[index], text, 1023);
		return text;
	}
	String	_GetWindowText(int index)
	{
		if (index >= List->Count || List->Count <= 0)
			return NULL;
		char *text = Buffer;
		GetWindowText(Handles[index], text, 1023);
		return text;
	}

public:
	CFindEnumChildWindow()
	{
		List = new TList;
	}
	~CFindEnumChildWindow()
	{
		delete List;
	}
	bool Scan(HWND parent, char *class_name, char *title, bool class_substring = true, bool title_substring = true)
	{
		List->Clear();
		hParent = parent;
		sClassName = class_name;
		sTitle = title;
		bClassNameSubString = class_substring;
		bTitleSubString = title_substring;
		return EnumChildWindows(hParent, (FARPROC)EnumChildWndProc, (long)this);
	}
	// 찾은 데이타 핸들링.
	//
	__property String ClassName[int index] = { read=_GetClassName };
	__property String WindowText[int index] = { read=_GetWindowText };
	__property HWND Handles[int index] = { read=GetHandle };
	__property int  Count = { read=GetCount };
};


class CFindEnumWindow
{
private:
	TList 	*List;
	char  	*sClassName;
	bool	bClassNameSubString;
	char	*sTitle;
	bool	bTitleSubString;
	char	Buffer[1024];

private:
	static BOOL CALLBACK EnumWndProc(HWND hwnd, LPARAM lParam)
	{
		CFindEnumWindow *This = (CFindEnumWindow *)lParam;
		char *text = This->Buffer;
		if (This->sClassName != NULL)
		{
			if (GetClassName(hwnd, text, 1023))
			{
				if ((!This->bClassNameSubString && !strcmp(text, This->sClassName)) ||
					(This->bClassNameSubString && strstr(text, This->sClassName)))
				{
					if (This->sTitle != NULL)
					{
						text[0] = 0;
						GetWindowText(hwnd, text, 1023);
						if ((!This->bTitleSubString && !strcmp(text, This->sTitle)) ||
							(This->bTitleSubString && strstr(text, This->sTitle)))
						{
							This->List->Add(hwnd);
						}
					}
					else
						This->List->Add(hwnd);
				}
			}
		}
		else
		{
			if (This->sTitle != NULL)
			{
				text[0] = 0;
				GetWindowText(hwnd, text, 1023);
				if ((!This->bTitleSubString && !strcmp(text, This->sTitle)) ||
					(This->bTitleSubString && strstr(text, This->sTitle)))
				{
					This->List->Add(hwnd);
				}
			}
		}
		return TRUE;
	}
	int	GetCount()
	{
		return List->Count;
	}
	HWND GetHandle(int index)
	{
		if (index >= List->Count || List->Count <= 0)
			return NULL;
		return List->Items[index];
	}
	String 	_GetClassName(int index)
	{
		if (index >= List->Count || List->Count <= 0)
			return NULL;
		char *text = Buffer;
		GetClassName(Handles[index], text, 1023);
		return text;
	}
	String	_GetWindowText(int index)
	{
		if (index >= List->Count || List->Count <= 0)
			return NULL;
		char *text = Buffer;
		GetWindowText(Handles[index], text, 1023);
		return text;
	}
public:
	CFindEnumChildWindow	Child;

public:
	CFindEnumWindow()
	{
		List = new TList;
	}
	~CFindEnumWindow()
	{
		delete List;
	}
	bool Scan(char *class_name, char *title, bool class_substring = true, bool title_substring = true)
	{
		List->Clear();
		sClassName = class_name;
		sTitle = title;
		bClassNameSubString = class_substring;
		bTitleSubString = title_substring;
		return EnumWindows((FARPROC)EnumWndProc, (long)this);
	}
	// 찾은 데이타 핸들링.
	//
	__property String ClassName[int index] = { read=_GetClassName };
	__property String WindowText[int index] = { read=_GetWindowText };
	__property HWND Handles[int index] = { read=GetHandle };
	__property int  Count = { read=GetCount };
};


#endif

클래스는 빌더6에서 제작되었기 때문에 RS2010에서 쓰시려면 조금만 손보면 됩니다.
그 정도는 누워서 껌먹기라서 아무나 할수 있을 것입니다.


요건 테스트입니다.
내부가 어떻게 동작하는지 굳이 알지 않아도 아래처럼 아주 쉽게 쓸수 있습니다.
//---------------------------------------------------------------------------

void __fastcall TForm100::Button1Click(TObject *Sender)
{
	CFindEnumWindow win;
	win.Scan("TAppBuilder", "Embarcadero RAD Studio 2010", false, true);
	if (win.Count > 0)
	{
		Edit1->Text = win.WindowText[0];
		Edit2->Text = win.ClassName[0];
	}
}
//---------------------------------------------------------------------------

클래스명은 TAppBuilder인 윈도 중에서(빌더6, 델파이, RS 등 모두 TAppBuilder 죠)
제목 줄에 Embarcadero RAD Studio 2010을
포함하는 창을 찾는 예제입니다.

숙지할 것은 Scan 메소드 정도겠군요.
Scan(char *ClassName, char *WindowTextCaption, bool class_substring = true, bool title_substring = true);
FindWindow 할때와 거의 같습니다.
Scan("TAppBuilder", NULL);
Scan(NULL, "Embarcadero RAD Studio 2010", false, true );
이런 식으로도 할 수 있습니다. 뒤쪽에 붙은 false, true는 Title은 "Embarcadero RAD Studio 2010" 문자열을 포함하는 것은 모두 찾으라 이런 뜻이 되겠죠. false, false 이렇게 주면 완전히 일치하는 것을 찾으라가 됩니다.

찾은 윈도에 대해 새끼 윈도 즉 Child Window를 찾으려면 Child 멤버객체를 이용하면 됩니다.


그럼..

+ -

관련 글 리스트
1006 특정한 클래스명, 캡션명 또는 일부 명칭이라도 포함하는 윈도 찾아주는 클래스. 김태선 8721 2010/07/30
Google
Copyright © 1999-2015, borlandforum.com. All right reserved.