웹, HTML

IE 인터페이스 사용하여 IE 페이지 조정해보기

디버그정 2016. 3. 3. 03:35

IE_구성요소_사용.mht

 

 

sample_code.zip

 

 

일본 페이지 구글 자동 번역한 것입니다.

http://www.nitoyon.com/vc/tips/ie_component.htm#howto2

 

VC ++ 사용

IE 구성 요소 사용

IE4.0에서 IE 구성 요소를 사용할 수있게되었습니다. IE 구성 요소는 Donut 등의 국산 탭 브라우저 외에도 다양한 응용 프로그램에서 사용할 수 있습니다.

IE 구성 요소는 MFC의 CHTMLView 절대로 쉽게 만들 수 있지만 MFC를 사용하고 싶지 않은 경우도 있습니다. 이 경우 ATL을 선택하는 것이 일반적이지만, 세상 문서의 대부분은 ATL과 AppWizard를 결합한 방법 밖에 실려 있지 않습니다. 여기에서는 SDK으로 IE 구성 요소를 사용하는 방법을 설명합니다.


 

샘플 코드는 여기 (35.9KB) (2002.12.15 미리 컴파일 된 헤더를 찾을 수없는 오류가 발생하지 않도록했습니다). 이를 DL 해 해동 해주세요. 자세한 내용은 소스 파일의 주석 참조 말하는 것으로 부탁합니다. 100 줄 정도의 소스이므로 꼭 읽어보십시오.

이 샘플은 대화에 IE 구성 요소를 붙여 사용하고 있습니다. 대화에 IE 구성 요소를 붙이는는 VC ++ 리소스 편집기에서 대화를 열고 대화에서 "오른쪽 클릭 → ActiveX 컨트롤 삽입 → Microsoft Web Browser"를 선택하면 OK입니다.

스크린 샷
스크린 샷

VC ++ NET에서의 주의점

자원에서 만든 대화의 ID를 IDD_DIALOG_MAIN으로이 대화에 붙여 ActiveX는 IE 구성 요소의 ID를 IDC_EXPLORER1이라고합니다.

xxx.rc 파일을 텍스트로 열고 다음 부분을 수정

CONTROL ""IDC_EXPLORER1 "{8856F961-340A-11D0-A96B-00C04FD705A2}"

에서

CONTROL "{8856F961-340A-11D0-A96B-00C04FD705A2}", IDC_EXPLORER1 "AtlAxWin71"

수정합니다. (후지사와 님, 문의 감사합니다.)

IE 구성 요소의 사용법 2

여기에서는 IE 구성 요소를 CreateWindow 함수에서 생성하는 샘플을 게재합니다.


 

샘플 코드는 여기 (38.4KB) . 이를 DL 해 해동 해주세요. 자세한 내용은 소스 파일의 주석 참조 말하는 것으로 부탁합니다. 100 줄 정도의 소스이므로 꼭 읽어보십시오.

AtlAxWinInit ()를 호출하면, CreateWindow 함수의 클래스 이름에 "AtlAxWin"제목에 ProgID와 CLSID (IE 컨트롤의 경우 URL에서도 OK)을 입력하면 ActiveX 컨트롤을 만들 수 있습니다. IE 컨트롤의 ProgID는 Shell.Explorer.2 따라서 저자는 이것을 사용했습니다. 자세한 내용은 HOWTO : Dynamically Add ActiveX Controls to ATL Composite Control (Q218442) 을 참조하십시오.

HWND hwndIE = CreateWindow ( "AtlAxWin", "Shell.Explorer.2" 
		WS_CHILD | WS_VISIBLE, 
		0, 0, 100, 100, 
		hWnd, (HMENU) 0, hInstance, NULL);

// ActiveX 컨트롤 인터페이스를 요구
CComPtr <IUnknown> punkIE;
if (AtlAxGetControl (hwndIE & punkIE) == S_OK)
{
	// 포인터에 저장
	pWB2 = punkIE;
}


 

윈도우에서 주소창에 URL을 입력하고 GO 버튼을 누르면 URL을 열 수 있습니다. 그러나 열린 페이지에서 링크를 클릭하면 주소 표시 줄의 URL은 변경되지 않습니다. 부실 들켜 들켜. 이를 구현하려면 IE 구성 요소에 DWebBrowserEvents2에서 이벤트가 발생하면 알리도록 부탁해야합니다. 이 방법은 다음 절에서 뽑아 있습니다.

스크린 샷
스크린 샷

VC ++ NET에서의 주의점

CreateWindow의 첫 번째 인수의 클래스 이름을 AtlAxWin에서 AtlAxWin71로 변경하십시오. (후지사와 님, 문의 감사합니다)

Visual C ++ 2005 AtlAxWin80 할 필요가있었습니다.

이벤트를 얻는 방법

IE 구성 요소에서 발생한 이벤트를 얻는 방법을 소개합니다. 이벤트는 페이지를 표시하기 전에 호출되는 BeforeNavigate2 및 상태 표시 줄이 변화하기 전에 호출되는 CommandStateChange 새로운 윈도우가 표시되기 전에 호출되는 NewWindow2 등이 있습니다. 이벤트의 종류에 관해서는 DWebBrowserEvents2 Interface (MSDN) 를 참조하십시오.


 

샘플 코드는 여기 (34.8KB) . 이를 DL 해 해동 해주세요. 자세한 내용은 소스 파일의 주석 참조 말하는 것으로 부탁합니다.

이 샘플에서는 다음과 같은 기능을 추가했습니다.

  • BeforeNavigate2가 호출되면 앞으로 보려고하는 URL을 검색 주소창의 문자열을 변경합니다. (단, 프레임을 사용한 페이지에서도 프레임에 페이지를 표시 할 때마다 주소 표시 줄이 변경되어 버린다)
  • NewWindow2에서 VARIANT_BOOL * & Cancel에 VALIANT_TRUE을 설정하여 새 창에서 열지 못하도록한다.
  • IE 컨트롤의 키 입력 (Tab 키 등)를 올바르게 처리하도록 변경 (03/01/04부터). WebBrowser Keystroke Problems 를 참조했습니다.
    • 주소 표시 줄에서 BS를 누르면 다시 버리는 문제에 대응 (03/07/13부터)


 

다음은 얻은 지식을 간단하게 설명합니다. 실수 많다고 생각하지만 용서 잠깐.

IE 구성 요소에서 발생한 이벤트를 받으려면 IDispatch 인터페이스를 지원해야합니다. 이벤트를받는 객체의 수를 COM 세계의 말로 싱크 (sink)이라고합니다.

ATL 절대로 CComObjectRootEx과 IDispEventImpl에서 클래스를 상속하여 쉽게 동기화를 구현할 수 있습니다. 또한 IDispatch를 지원하는 것을 선언하기 위해 BEGIN_COM_MAP 매크로를 실제 이벤트를 처리하기 위해 BEGIN_SINK_MAP 매크로를 사용합니다. 또한 실제로 IE 컴퍼넌트에 통지 할 때 DispEventAdvise 함수를 사용합니다.

응 이렇게 썼습니다도 이해하기 어렵 네요. 실제로 소스를보고 느낌을 잡으십시오.


 

COM에서 이벤트 수수은 COM에서 이벤트를 잡을 방법 이 도움이 될 것입니다. 일본어 문서 곳이 기쁘구나. 꽤 참고시켜주었습니다. 성실하게 공부한다면 책을 사는 것이 좋을까요지만 ....

IE 컨트롤에서 마우스 오른쪽 클릭했을 때 발생하는 이벤트를 붙잡 으면 컨텍스트 메뉴를 직접 설정 한 것으로 대체 할 수있는 것으로 알려졌다. 그러나이를 구현하기 위해서는 HTML 문서에 대해 IDocHostUIHandler를 취득 알 필요가있는 것 같습니다. 응, 대단하다. 자세한 내용은 HOWTO) Control the Context Menu in an ATL HTML Control (Q274202) 을 참조하십시오.

페이지를 분석 / 변경

IHTMLDocument2 인터페이스를 사용하면 HTML 문장의 태그를 열거하거나 태그를 추가 할 수 있습니다. IHTMLDocument2를 취득하려면 IWebBrowser2 포인터가 pWB2라고하면

CComPtr <IDispatch> pDisp;
pWB2-> get_Document (& pDisp);
CComQIPtr <IHTMLDocument2> pDoc = pDisp;

로 가져올 수 있습니다. 하지만 오류 처리는 생략하고 있습니다. 취득시기는 DWebBrowserEvents2의 DocumentComplete 이벤트가 발생했을 때이 충 분 (2002.10.1 수정). IHTMLDocument2는 새로운 페이지를 열 때마다 취득하지 않으면 안됩니다. IWebBrowser2 인터페이스가 IE 컨트롤마다 존재하도록 IHTMLDocument2 인터페이스는 페이지마다 존재합니다.


 

그런데, 취득한 IHTMLDocument2의 조리법을 소개합시다. Adding a custom search feature to CHtmlViews 를 참조하십시오. 이처럼 HTML 문장을 검색하거나 하이라이트 할 수 있지요. 하이라이트는 검색에 걸린 문자를 <span> 태그 사이에 두는 것으로 실현하고 있습니다.

또 하나는 Using CHtmlView as a control 입니다. 여기에서는 "MSHTML 편집 플랫폼 '을 사용하는 방법에 대해 다루고 있습니다. 어려운 것은 필요 없습니다, pDoc-> put_designMode (L "On");라고하면, WYSIWYG로 HTML을 편집 할 수 있습니다.

편집 플랫폼
편집 플랫폼

위의 이미지는 링크에서 마우스 오른쪽 클릭하여 대상을 변경할 수있는 곳입니다. 그 외에도 Word에서 문장 충돌로 문장을 변경할 수 있습니다. 이제 당신도 HTML 편집기를 만들 수 있을지도. 단, 제작 넣자으로 IE 구성 요소의 수렁에 빠지는 것 같은 생각은 합니다만 ···.

마지막 예는 Example of Handling HTML Element Events in Microsoft Internet Explorer 입니다. 여기에서는 특정 태그에서 발생한 이벤트를 얻는 방법을 쓰고 있습니다. 이벤트는 onmouseout와 onkeypress 등이 있습니다. 이러한 이벤트에 반응하는 코드를 작성하면 사용자의 태그에 대한 조작에 반응하여 프로그램에서 HTML을 다시 작성할 수있게합니다.

페이지를 분석 / 변경하기 2

IE7 탭 브라우저가 될 것 같네요. 분명 IE 구성 요소에 탭 기능이 붙는 거죠. 하지만 인터페이스가 부풀어하면 프로그래머가 확인을하는 시간이 많아지고 슬픈 거죠 ....


 

자, 이번에는 "IE 컴포넌트의 인터페이스 = JavaScript 인터페이스"라는 것을 강조하고 싶습니다.

document.all ( "temp"). innerHTML = "hogehoge";

라는 JavaScript가 있었다고합니다. 이 스크립트는 페이지를 동적으로 쓰고 換る 때 잘 보면 예입니다. id가 temp라는 태그의 내용이 써 달라집니다 (예 : <span id = "temp">). 이것을, COM에서하려고 생각되면 다음과 같은 소스입니다.

// document의 취득
CComPtr <IDispatch> pDisp;
pWB2-> get_Document (& pDisp);
CComQIPtr <IHTMLDocument2> pDoc = pDisp;

// all 취득
CComPtr <IHTMLElementCollection> pCol;
pDoc-> get_all (& pCol);
long lSize;
pCol-> get_length (& lSize);

if (lSize! = 0)
{
	// all 내용을 나열
	USES_CONVERSION;
	for (long i = 0; i <lSize; i ++)
	{
		CComQIPtr <IHTMLElement> pElement;
		CComVariant vintName (i);
		CComVariant vintIndex (0);
		CComPtr <IDispatch> pdsp2;
		pCol-> item (vintName, vintIndex & pdsp2);
		pElement = pdsp2;

		// id가 temp라면
		BSTR bstrId;
		pElement-> get_id (& bstrId);
		char * pszBuf = bstrId? OLE2T (bstrId) : "";
		 if (strcmp (pszBuf "temp") == 0)
		{
			// innerHTML을 설정
			pElement-> put_innerHTML (L "hogehoge");
		}
	}
}

어떻습니까. JavaScript에 비해 대단히 긴하지만,하고있는 것은 같네요. JavaScript는 원래 IE 구성 요소 조종하기위한 수단 이군요. 그래서 IE 구성 요소를 만지는 위해 일일이 컴파일하는 것이 귀찮은 경우는 JavaScript로 실험 할 수 있습니다. 뿐만 아니라 IE 구성 요소의 인터페이스 및 Tips를 찾는 것은 어려운 일이므로, JavaScript 사전 같은 페이지에서 확인을하는 것이 빠를지도 모르겠네요.


 

마지막으로, 훌륭한 Tips 페이지를 소개하고 끝으로합시다. IE Powertoys Plus! + miniToys 입니다. 이 페이지에서는 JavaScript에서 여러하려고하고 있습니다. 무엇보다, JavaScript 그래서 소스를 볼 수있는 곳이 최고 네요. 특히 miniToys 분은 아이 자료집으로 최고입니다. 댓글 태그 해제 줌 그레이 스케일 화 등보기 만해도 군침이 나올 것 같은 소재 가득합니다.

또한 JavaScript for CSS 를 추가. 홈페이지는 사라지고 있지만 DOM을 사용하여 주로 스타일 시트를 변경하는 방법이 써 있습니다.

다른 Tips

여러 가지 조사 결과를 메모 대신 써 둡니다. IE 구성 요소 관계에서 보면이 페이지가 비교적 걸려 쉽기 때문에 나름대로의 정보를 올려 두지 않으면 ...

문자열을 검색하는 방법

여기에서는 IWebBrowser2의 get_LocationURL을 사용하는 방법을 보여 보겠습니다. 여기에 기술 된 방법을 이용하면, IHTMLElement2의 get_innerHTML처럼 BSTR *를 인수에 함수를 호출 할 수 있습니다.

USES_CONVERSION;
BSTR bstrBuf;
pWB2-> get_LocationURL (& bstrBuf);
char * pszUrl = (bstrBuf? OLE2T (bstrBuf) : "");

USES_CONVERSION 매크로를 사용하면 OLE2T 등의 매크로 블록 (함수 등 {}로 둘러싸인 범위)에서 사용할 수 있습니다. OLE2T은 BSTR 등의 UNICODE를 SJIS로 변환 해줍니다. 변환 된 문자열은 free과 LocalFree 할 필요가없는 점에 유의하십시오.

여기에서는 pszUrl에 NULL이 저장되는 것을 싫어하고 (bstrBuf? OLE2T (bstrBuf) : "");하고 있습니다.

다운로드 도중의 IHTMLDocument2 개체를 얻을

일반적으로 IHTMLDocument2를 얻기 위해서는 DWebBrowserEvents2의 DocumentComplete 이벤트가 발생하고 최선으로되어 있습니다. 그러나이 DocumentComplete 이벤트는 페이지의 이미지도 다운로드 끝나지 않으면 발생하지 않습니다. 이런 일도 다운로드하는 동안 동시에 문서를 분석하고 싶은 경우도있을 것입니다.

IWebBrowser2 개체 만 얻을 수 있다면, 다운로드중인 HTML 문서를 순차적으로 취득 할 수있는 것을 확인할 수 있었다 (IE6). 따라서 새 페이지를 볼 때 새로운 스레드를 만들고 스레드에서 DocumentComplete이 불릴 때까지 몇 초 간격으로 IHTMLDocument2를 얻을 계속이 좋습니다.

about : blank 페이지에 동적으로 페이지를 넣어 넣 싶다

메모리에 페이지를 표시하는 기술입니다. 일부 2ch 브라우저도이 방법을 사용하는 것입니다 (오른쪽 클릭에서 등록 정보를 보면 about : blank를 표시된다). 임시 파일을 만들 필요가 없을 것입니다.

이 근처를 참고하여 만들어 보았다. 심은 심은! (코딩 스타일이 붕괴 한 것은 여러 곳에서 복사 해 온 내용의 합성이기 때문입니다)

	CComVariant vempty, vUrl (L "about : blank");
	pWB2-> Navigate2 (& vUrl & vempty & vempty & vempty & vempty);
	CComPtr <IDispatch> pdisp;
	CComQIPtr <IHTMLDocument2> pDoc;
	while (1)
	{
		HRESULT hr = pWB2-> get_Document (& pdisp);
		if (SUCCEEDED (hr) && pdisp! = NULL)
		{
			pDoc = pdisp;
			if (pDoc! = NULL)
			{
				break ;
			}
		}
		Sleep (100);
	}

	HRESULT hresult = S_OK;
	VARIANT * param;
	SAFEARRAY * sfArray;
	BSTR bstr = SysAllocString (OLESTR ( "<html> <body> <b> hoge </ b> adfsf <hr> </ body> </ html>"));

	sfArray = SafeArrayCreateVector (VT_VARIANT, 0, 1);
	
	if (sfArray == NULL || pDoc == NULL) {
		 Goto cleanup;
	}

	hresult = SafeArrayAccessData (sfArray (LPVOID *) & param);
	param-> vt = VT_BSTR;
	param-> bstrVal = bstr;
	hresult = SafeArrayUnaccessData (sfArray);
	hresult = pDoc-> write (sfArray);

cleanup :
	SysFreeString (bstr);
	if (sfArray! = NULL) {
		SafeArrayDestroy (sfArray);
	}

onclick이나 onmouseover 등의 이벤트를 처리하고자

(HOWTO) Sink HTML Document Events for WebBrowser Host 를 참조하십시오.

그 밖에도 Handling HTML Element Events in Internet ExplorerPopup Blocker 등의 샘플이 있습니다 만, 아무래도 홈브류에 통합 할 수 없습니다 .... 누군가, ATL에서 잘하는 것이 있으면, vc@nitoyon.com 까지 연락 주시면 감사하겠습니다.

윈도우 핸들에서 IWebBrowser2 싶어

Internet Explorer_Server 클래스의 윈도우 핸들을 주면 거기에서 CComPtr <IWebBrowser2>을 돌려줍니다. Keystroke Logger and More, Part 3 당을 참고로했습니다.

CComPtr <IWebBrowser2> GetIEPtr (HWND hWnd)
{
	HWND hWndChild = hWnd;
	if (hWndChild)
	{
		CComPtr <IHTMLDocument2> spDoc;
		LRESULT lRes;

		UINT nMsg = :: RegisterWindowMessage (_T ( "WM_HTML_GETOBJECT"));
		:: SendMessageTimeout (hWndChild, nMsg, 0L, 0L, SMTO_ABORTIFHUNG 1000 (DWORD *) & lRes);

		HRESULT hr;
		hr = ObjectFromLresult (lRes, __uuidof (IHTMLDocument2), 0, ( void **) & spDoc);
		 if (SUCCEEDED (hr))
		{
			CComQIPtr <IServiceProvider> psp1 = spDoc;
			CComQIPtr <IServiceProvider> psp2;
			CComPtr <IWebBrowser2> pWB2;
			
			if (psp1)
			{
				psp1-> QueryService (SID_STopLevelBrowser, IID_IServiceProvider ( void **) (& psp2));
				 if (psp2)
				{
					psp2-> QueryService (SID_SWebBrowserApp, IID_IWebBrowser2 ( void **) (& pWB2));
					 return pWB2;
				}
			}
		}
	}
	return NULL;
}

영어를 읽고 싶지

IE 구성 요소에 한정된 것은 아니지만, 영어를 읽을 수없는 경우 엄격합니다. 하지만 나도 일본어 문서가 읽기 쉬우므로 일본어 문서가 없을 때에 만 영어 문장을 읽습니다. IE 구성 요소에서는 일본어 문서도 그다지 많지 않아 영어 문서를 읽을 수있는 기회가 많아지고 만다는 생각합니다 ...

IE 구성 요소 관계 참고 URL

COM과 IE 구성 요소 관계에 도움이 될 URL을 참고로 게재 해 둔다.

원본 텍스트