2024年10月
    1 2 3 4 5
6 7 8 9 10 11 12
13 14 15 16 17 18 19
20 21 22 23 24 25 26
27 28 29 30 31    
無料ブログはココログ

 

« 株:現物売り約定(セブン銀行) | トップページ | 今週届いた本 »

2017年7月30日 (日)

IEのCOMインターフェイスでSJISとかUTF-8をOnMemoryで表示させる方法

プログラムから(ファイルを使わないで)IEを起動しXMLを開く方法からの派生。

IEのCOMインターフェイスで、OnMemoryからIEで表示する方法としてMSHTML::HTMLDocument2::write(BSTR)を提示したが、BSTRで渡すIFである以上、UNICODE(UTF-16)=WideCharしか渡せないので、SHIFT-JISやUTF-8のようなMultiByteコードで表示できなかった。
これで何が問題になるかというと、inputタグに漢字コードを渡すhiddenなやつがあるとURLエンコードの結果がエンコードに引っ張られてUTF-8のみに固定されてしまったのだ。(なぜUTF-16にならないのかはよくわかっていないが、javascriptがUTF-8前提になっているのでHTML界隈ではUTF-8で扱うことになっているのだろう?)
んで、BSTR型ではない方法で、IEに内容を渡すIFがないのか探していたのだが、(お仕事で実装がほとんど終わったこの時期に)やり方を見つけた。

↓ここを参考にしましたんで、詳細はこちらを参照してください。
Loading HTML content from a Stream

※:GlobalFree()で解放例外が出るなーと思っていたら、CreateStreamOnHGlobal()の第二引数をfalseにしないとダメじゃないですか?

Visual Studio 2017からVisual C++  Win32コンソールアプリケーションから作成(文字セットをUNICODEから設定なしにしておく)。

#include "stdafx.h"
//#include <Strsafe.h>
#include <stdio.h>
#include <tchar.h>

#import <shdocvw.dll>
#import <mshtml.tlb>

bool writeHtml(SHDocVw::IWebBrowser2Ptr &pIE, const TCHAR* pszHTMLText)
{
bool ret = false;

HRESULT hr;
IStream* pStream = NULL;
IDispatch* pHtmlDoc = NULL;
IPersistStreamInit* pPersistStreamInit = NULL;

MSHTML::IHTMLDocument2Ptr pDoc(pIE->Document);
//if (pDoc == nullptr) {
if (pDoc == NULL) {
goto FUNC_END;
}

//size_t cchMax = 256;
size_t cchLength = _tcslen(pszHTMLText);
HGLOBAL hHTMLText = GlobalAlloc(GPTR, cchLength + 1);
if (hHTMLText == NULL) {
goto FUNC_END;
}
//StringCchCopy((TCHAR*)hHTMLText, cchLength + 1, pszHTMLText);
_tcscpy_s((TCHAR*)hHTMLText, cchLength + 1, pszHTMLText);
hr = CreateStreamOnHGlobal(hHTMLText, FALSE, &pStream);
if (FAILED(hr)) {
goto FUNC_END;
}

// Call the helper function to load the browser from the stream.
// Query for IPersistStreamInit.
hr = pDoc->QueryInterface(IID_IPersistStreamInit, (void**)&pPersistStreamInit);
if (FAILED(hr)) {
goto FUNC_END;
}

// Initialize the document.
hr = pPersistStreamInit->InitNew();
if (FAILED(hr)) {
goto FUNC_END;
}

// Load the contents of the stream.
hr = pPersistStreamInit->Load(pStream);
if (FAILED(hr)) {
goto FUNC_END;
}

ret = true;

FUNC_END:
pPersistStreamInit->Release();
pStream->Release();
//pDoc->Release();
pDoc->close();
GlobalFree(hHTMLText);

return ret;
}

// IEを起動してhtmlデータを書き込む
// IEをコントロールしたい(IEを閉じるなど)場合は、WebBrowserのインスタンスを外に出して管理した方がよい
void openIE(const TCHAR* pszHTMLText)
{
SHDocVw::IWebBrowser2Ptr pIE;

// IE 起動+HTMLデータ設定+表示
HRESULT hr = pIE.CreateInstance(__uuidof(SHDocVw::InternetExplorer));
if (FAILED(hr)) {
return;
}

pIE->Navigate(L"about:blank"); //何か設定しないでHTMLを書き込むと例外が発生する。空文字を入れると"http:///"となる

bool bRslt = writeHtml(pIE, pszHTMLText);
if (!bRslt)
{
return;
}
pIE->Visible = VARIANT_TRUE; // IEを表示状態にする。ここで見えるようになる。

pIE = NULL;
}

int main(int argc, char* argv[])
{
int rtn = -1;
HANDLE hFile = INVALID_HANDLE_VALUE;
DWORD dwFileSize = 0;
TCHAR* fileData = NULL;

HRESULT hr = ::CoInitializeEx(NULL, COINIT_MULTITHREADED);

if (argc != 2) {
fprintf(stderr,
"INVALID ARGUMENT.\n"
" Please Input HTML FileName(FULL PATH).\n"
);
goto FUNC_END;
}

hFile = CreateFile(argv[1], GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (hFile == INVALID_HANDLE_VALUE) {
goto FUNC_END;
}
dwFileSize = GetFileSize(hFile, NULL);
fileData = new TCHAR[dwFileSize + 1];
DWORD dwReadSize = 0;
BOOL bRslt = ReadFile(hFile, (LPVOID)fileData, dwFileSize, &dwReadSize, NULL);
if (!bRslt) {
goto FUNC_END;
}
CloseHandle(hFile);
hFile = INVALID_HANDLE_VALUE;
fileData[dwFileSize] = '\0';

openIE(fileData);
rtn = 0;

FUNC_END:
if (fileData != NULL) {
delete[]fileData;
}
if (hFile != INVALID_HANDLE_VALUE) {
CloseHandle(hFile);
}
::CoUninitialize();

return rtn;

確認したHTMLファイルは以下。それぞれSHIFT-JISとUTF-8de保存し、引数にファイル名を設定すればOK
なお、UNICODE(UTF-16)で保存されたファイルはNG。
●sjis.html

<html>
<head>
<meta charset="SHIFT_JIS">
</head>
<body>
文字コード:SJIS
</body>
</html>

●utf8.html

<html>
<head>
<meta charset="UTF-8">
</head>
<body>
文字コード:UTF-8
</body>
</html>

« 株:現物売り約定(セブン銀行) | トップページ | 今週届いた本 »

コメント

コメントを書く

(ウェブ上には掲載しません)

トラックバック


この記事へのトラックバック一覧です: IEのCOMインターフェイスでSJISとかUTF-8をOnMemoryで表示させる方法:

« 株:現物売り約定(セブン銀行) | トップページ | 今週届いた本 »