delphi로 IE 컨트롤
1. 기본적인 사항
모든 웹브라우저 컴퍼넌트는 IWebBrowser2 라는
인터페이스를 사용합니다.
델파이로만들던 VC로 만들던 VB로 만들던지
암튼간에 무조건 저 인터페이스를 사용합니다.
델파이의 TWebBrowser라는 컴퍼넌트
역시 MS의 웹브라우저 컴포넌트를 포장해서 쓰는관계로
IWebBrowser2 인터페이스를 가지고 있습니다.
바로 OleObject 퍼로퍼티가 그 놈입니다.
IWebBrowser2 외에도 관련된 인터페이스들이 있는데,
계보를 따져보면 아래와 같습니다.
IUnknown
|
IDispatch
|
IWebBrowser
|
IWebBrowserApp
|
IWebBrowser2
이 인터페이스들은 델파이의 컴포넌트 계보와 개념이 비슷합니다.
우리는 IWebBrowser2 의 값을 알고 있기 때문에 필요하다면
그 상위의 인터페이스들을 알아 낼수도 있습니다.
IWebBrowser2로 IWebBrowserApp를
액세스 하기위해서는 이렇게 하면 됩니다.
Web : IWebBrowser2;
WebbApp : IWebBrowserApp;
// Web에는 이미 값이 들어가 잇음
if Web.QueryInterface(IID_IWebBrowserApp, WebApp)=S_OK
then 성공적으로 얻어옴
else 실패함
이렇게 하면 됩니다.
하지만 실패할 일이 절대로 없다는 확신이 설때에는 그냥
(Web as IWebBrowserApp)
이렇게만 하면 됩니다.
2. TWebBrowser 컴포넌트 조작상에 알아두면 좋은 팁들
2.1. 컴퍼넌트 초기화 하기
웹브라우저 컴퍼넌트를 초기화하려면
무슨 문서라도 하나 읽어와야 합니다.
보통은 라는 간단한 텍스트를 a.htm 등에 담아 놓고
WebBrowser.Navigate('file://c:/.../a.htm');
이렇게 하면됩니다.
하지만 이건 저같이 무식한 사람이 앞뒤 안가리고 그냥 쓰는 방법이고
좀더 세련되게 흔적없이 하려면
WebBrowser.Navigate('about:blank');
이렇게 하면 됩니다.
2.2. 소스 보기
HTML을 읽은 브라우저에서 소스를 뽑아내기란 아주 복잡한 작업입니다.
느려터진 MSDN의 관련 클래스들을 뒤지다 보면 아마도
Document 클래스안에 DocumentElement 클래스안에
OuterHTML 이라는 프로퍼티를 찾을 수 있습니다.
소스를 메모장에다가 보여주고 싶다면
Memo1.Lines.Text := WebBrowser.OleObject.Document.DocumentElement.OuterHTML;
이렇게 하면됩니다.
이렇게 간단한데 뭐가 복잡하냐구요?
이건 소스는 소스지만 조작된 소스입니다.
IE의 HTML파서를 거쳐서 정형화된 소스입니다.
웹브라우저로 로딩을 하면
그놈이 그놈이지만 소스를 보면 분명 원래 소스와는 차이가 있죠.
그렇다면 원래 모양 그대로 뽑아낼려면 어떻게 해야할까요?
뽑아서 스트림으로 저장하는걸 보면 이래요..
function TMainForm.RevealSource(const Document : IHTMLDocument2; Buf : TStream) : Boolean;
var
WebS : IPersistStreamInit;
begin
Result := False;
if SUCCEEDED( Document.QueryInterface(IID_IPersistStreamInit, WebS) ) then
if SUCCEEDED( WebS.Save(TStreamAdapter.Create(Buf), True) ) then Result:=True;
end;
또는 한줄로 간단히
(Document as IPersistStreamInit).Save(TStreamAdapter.Create(Buf), True)
이렇게 하면 되겠죠.
파일로 저장할때는 TFileStream을 넣고
그냥 보여줄때는 TMemoryStream을 넣고 등등으로 하면 되겠네요.
--; 별로 복잡하지 않다고요?
원래는 IStream, TOleStream 등을 써서 아주 복잡하게 만들었었는데,
인터넷에 뒤져보니 저런 쉬운방법이 있길래 저걸로 바꿨습니다.
반대로 스트림에 들어 있는 HTML을 웹브라우저로 집어 넣을때는
(Document as IPersistStreamInit).Load(TStreamAdapter.Create(Buf));
이렇게 하면 됩니다. 아주 간단하죠.
주) IHTMLDocument2 클래스를 사용하기 위해서는
MSHTML 을 uses 구문에 추가해야 합니다.
이 놈은 WebBrowser.Document 입니다. 혹은 WebBrowser.OleObject.Document
2.3. HTML 문서를 리소스에 넣기
BMP,WAVE 들도 다 리소스에 들어가는데
HTML문서라고 리소스에 들어가지 말란 법 있나요.
HTML문서를 일단 밀어 넣어 보자구요.
TEST.RC 파일에다가
HTML1 23 "html\test1.htm"
HTML2 23 "html\test2.htm"
이렇게 넣고 res로 컴파일합니다.
{$R TEST.RES}
이렇게 넣고
WebBrowser.Navigate('RES://' + Application.ExeName + '/HTML1');
이렇게 하면 된답니다. (저도 안 해봤습니다만)
안돼는걸 된다고 올려놓았을리는 없으니 틀림없이 되겠죠.
3. TWebBrowser말고 외부의 IWebBrowser2 인터페이스 얻어오기
이 부분은 외부의 IE창의 웹브라우저를 조작하기 위한 부분입니다.
다 필요없고 우리가 필요한건 오직 IWebBrowser2 인터페이스 입니다.
이 놈만 얻어오면 내 프로그램의 컴포넌트처럼 조작할 수 있습니다.
전역 변수 혹은 폼 클래스 변수로 이놈을 선언 합니다.
var
FShellWindow : IShellWindows;
프로그램 초기화 루틴 혹은 폼 클래스 OnCreate 부분에 이걸 넣어 초기화 시킵니다.
FShellWindow := CreateComObject(CLASS_ShellWindows) as IShellWindows;
IShellWindows 는 윈도우상의
모든 쉘윈도우를 관리하기 위한 인터페이스입니다.
CreateComObject 는 쉘윈도우 관리자를
새로 만드는게 아니라 기존의 관리자의
인터페이스를 얻어오게 됩니다.
왜냐하면 Single Instance 이기 때문에
우리는 이제 필요할때마다
이 관리자에게 쉘에대해 물어 보면 그때그때의 열린 쉘들을
친절하게 가르쳐 줍니다.
여기서 쉘이란 IE만을 가르키는게 아닙니다.
윈도우즈탐색기, 제어판, IE창, IE - FTP모드 창 등의
모든 쉘들을 다 가르쳐 주기때문에 웹브라우저를
선별하는 작업을 따로 해주어야합니다.
Count := FShellWindow.Count; // 현재 열린 쉘들의 갯수
if Count>0 then
For I:=0 to Count-1 do begin
if WebBrowserCheck(FShellWindow.Item(I) as IWebBrowser2) then begin
// 이 놈은 웹브라우저 이다.
end;
end;
이런식으로...
여기서 선별하는 방식은 정석인지 아닌지 모릅니다.
그냥 제가 쓰는 방법을 적은 것일 뿐입니다.
간단하게 Document 인터페이스를 가지고 있는지 아닌지로 판단 합니다.
일단 탐색기나 제어판 등은 Document 인터페이스가 없습니다.
function WebBrowserCheck(const Webb : IWebBrowser2) : Boolean;
var
WebV : Variant;
Buf : String;
begin
WebV := Webb;
Result := False;
if Assigned(Webb) then
try Buf := WebV.Document.URL;
// Document 인터페이스가 할당 되어 있지 않으면 예외오류 발생
Result := True;
except ;
end;
end;
해보지는 않았지만 어쩌면 FShellWindow.QueryInterface로
체크해보면 제대로된 IwebBrowser2를
걸러낼 수 있을지도 모르겠어요.
암튼 이렇게 IWebBrowser2를 얻어 왔다면 모든게 순조롭게
진행이 되겠죠.
예을 들어 그 IE 창을 닫아 버리고 싶다면?
Webb : IWebBrowser2;
WebbApp : IWebBrowserApp;
WebV : Variant;
일 경우
if Webb.QueryInterface(IID_IWebBrowserApp, WebApp)=S_OK then
WebApp.Quit;
이렇게,
그 창의 URL을 얻어오고 싶다면
WebV := Webb;
URL := WebV.Document.URL;
여기서 잠깐..
왜 Variant 타입의 변수에 넣어서 엑세스 하냐면요.
그냥 하면 에러가 납니다.
왜냐면 Webb.Dcocument 는 IDispatch 형이기때문에 URL이란 프로퍼티가
없기 때문이죠.
물론 (Webb.Get_Document as IHTMLDocument2).URL
이렇게 해도 되겠죠.
'Delphi Tip > 인터넷' 카테고리의 다른 글
Internet explorer 띄우기 (0) | 2021.12.01 |
---|---|
Capture element click in Internet Explorer (0) | 2021.11.30 |
IE 현재 열려있는 주소값 읽어오기 (0) | 2021.11.25 |
Indy9 파일전송 예제 (0) | 2021.11.24 |
ActiveX Form기초부터 배포까지 (0) | 2021.11.23 |
댓글