初心者です。よろしくお願いいたします。
フレーム分割されたページを取得してテキストボックスに
入力したりボタンをクリックする処理をC++で実行できる
用にしたいと考えています。
mshtml.tlbを使用することで実現できると考えて
おりますが、フレーム分割されたページを取得する
プログラムの記述がわかりません。
また、これからコーディングを進めていく上でこの手の問題に
直面したときの調査の仕方を教示していただけたら幸いです。
よろしくお願いいたします。
開発環境は、Windows Xp, VC++.net2002です。
<frameset>タグ内に書かれたURLに対し、再度HTTP-GETすりゃええのでは?
επιστημη さん
HTTP-GETを調べてみましたが、勉強不足のためよくわかりません。
もうしわけありません。
VBAでよくやられている下記のような処理を考えています。
'ドキュメントオブジェクトの代入
Set objFRAME = objIE.document.frames
Set objDOC0 = objFRAME(0).document
'リンクのアンカーオブジェクトをクリックする
Dim ret As Variant
For n = 0 To objDOC0.Links.Length - 1
'Debug.Print objDOC0.Links(n).href 'デバックで表示する
ret = InStr(1, objDOC0.Links(n).href, "FraStkOrder.jsp", vbBinaryCompare)
If ret <> 0 And IsNull(ret) = False Then
objDOC0.Links(n).Click
Exit For
End If
Next n
VBAではできることをC++で実現しようと思っています。
よろしくお願いいたします。
以下のサンプルとVBAのソースを見比べて、どのように対応しているか
確認してみてください。
私は基本的には、VCのインテリセンス機能を使って、メンバ変数やメソッドがあるか確認しました。
IHTMLDocumentPtrやらIHTMLDocument2PtrやらIHTMLDocument3Ptrの使い分けはメンバがあるかないかでしかないです。
サンプル)
// この掲示板のTop→Visual C++のページに移動する
#include <windows.h>
#include <comdef.h>
#import "shdocvw.dll" rename( "FindText", "FindTextIE" )
#import "mshtml.tlb" rename( "TranslateAccelerator", "TranslateAcceleratorHTML" )
HRESULT Test()
{
HRESULT hr;
hr = ::CoInitialize( NULL );
if ( FAILED( hr ) ) return hr;
try
{
SHDocVw::IWebBrowser2Ptr pBrowser;
// IEを立ち上げ、Programming Library を表示
hr = pBrowser.CreateInstance( __uuidof( SHDocVw::InternetExplorer ) );
if ( FAILED( hr ) ) _com_issue_error( hr );
pBrowser->Visible = VARIANT_TRUE;
pBrowser->Navigate( _bstr_t( L"http://madia.world.coocan.jp/" ) );
// ページが表示されるまで待つ
while ( pBrowser->Busy == VARIANT_TRUE ||
pBrowser->ReadyState != READYSTATE_COMPLETE )
::Sleep( 100 );
MSHTML::IHTMLDocument2Ptr pDocument( pBrowser->Document );
// すべてのフレームをチェック
MSHTML::IHTMLFramesCollection2Ptr pFrameCollection( pDocument->frames );
for ( long i = 0L; i < pFrameCollection->length; i++ )
{
MSHTML::IHTMLWindow2Ptr pFrame( pFrameCollection->item( &_variant_t( i ) ) );
MSHTML::IHTMLDocument2Ptr pDoc( pFrame->document );
// すべてのリンクをチェック
MSHTML::IHTMLElementCollectionPtr pCollection( pDoc->links );
for ( long j = 0L; j < pCollection->length; j++ )
{
// ※DispHTMLLinkElementPtrだと、hrefがうまく取れないので、Anchorにしてある
MSHTML::DispHTMLAnchorElementPtr pAnchor( pCollection->item( _variant_t( j ) ) );
// 該当の URL か?
if ( _bstr_t( pAnchor->href ) == _bstr_t( L"http://madia.world.coocan.jp/vc/index.html" ) )
{
pAnchor->click();
// ページが表示されるまで待つ
while ( pBrowser->Busy == VARIANT_TRUE ||
pBrowser->ReadyState != READYSTATE_COMPLETE )
::Sleep( 100 );
break;
}
}
}
}
catch ( _com_error& e )
{
hr = e.Error();
}
::CoUninitialize();
return hr;
}
int main()
{
Test();
return 0;
}
> 'デバックで表示する
デバッグです。
VCでどうしてもかけないのであれば、VBAではなくVBSで該当の動作をするコードを書き
それをVCから起動させるのもありかなぁと。
> if ( _bstr_t( pAnchor->href ) == _bstr_t( L"http://madia.world.coocan.jp/vc/index.html" ) )
ここは pAnchor->href の戻り値は _bstr_t型なんで、単に
if ( pAnchor->href == _bstr_t( L"http://madia.world.coocan.jp/vc/index.html" ) )
でよかったです。
それと、VBAを使っているのであれば、ローカルウィンドウを十分に活用しましょう。
例えば
' VC++掲示板のリンク一覧をイミディエイトウィンドウに列挙
Sub test()
Dim objIE As Object
Dim objAnchor As Object
Set objIE = CreateObject("InternetExplorer.Application")
objIE.Visible = True
objIE.Navigate "http://madia.world.coocan.jp/cgi-bin/Vcbbs/wwwlng.cgi"
While objIE.busy
DoEvents
Wend
For Each objAnchor In objIE.Document.links
Debug.Print objAnchor.href ' ※
Next
Set objIE = Nothing
End Sub
というのをステップ実行して、※のところにブレイクポイントを置き、
ローカルウィンドウで objAnchor の型を確認してみると
Object/HTMLAnchorElement
となっているのが確認できます。
そこから、目星をつけてMSHTML:: で探します。
で、MSHTML::IHTMLAnchorElementPtrでは使いたいメソッドやメンバ変数があ
るかなければ、MSHTML::IHTMLAnchorElement2Ptrではどうかとうチェックしていきます。
ただ、今回の場合は結構わかりやすいオブジェクト名になっているので、
いちいちVBAで確認しなくても
> Set objFRAME = objIE.document.frames
は
MSHTML::IHTMLFramesなんたらPtr かなとわかります。
Blueさん
ご教授いただきましてありがとうございます。
少し時間がたってしまいすいません。
サンプル通り、フレームを取得しリンクページに遷移することが
出来ました。
MSHTML::IHTMLDocument2Ptrを使用してフレームを取得しテキスト
ボックスに入力する際、メンバにgetElementsByNameがないため
使用することができないのですが、他の方法でテキストボックスに
入力する方法はありますか。
とりあえず、VBAレベルのソースを考えてください。
そこからVCのソースにするにはどうすればよいかは前のレスで説明済み。
半月レスがない上に、自分で考えた形跡もないのでは、、、回答者としてはカナリ萎えますよ。
VBAでは下記のような処理になります。
Dim objFRAME As FramesCollection
Dim objDOC0 As IHTMLDocument
Set objFRAME = objIE.document.frames
Set objDOC0 = objFRAME(0).document
objDOC0.all.dscrCDsearch.Value = Range("A1")
教えていただきましたサンプルからフレームのドキュメントを取得する
は実現することができます。
前回、リンクを取得する型が変わらなかったのと同様に、テキストボックス
を取得する型がわからずにいます。
Debug文で型を知ることができるとわかりましたが、
今のVBAからどう記述すればわかるのかわからず。
getElementsByName( TagName )で取得はできますが、IHTMLDocument2Ptrには
メンバになく使うことができません。
どうしたら良いかご教授ください。
宜しくお願いいたします。
IHTMLDocument3PtrにgetElementsByTagNameってのがあるので、そこからタグをinput限定しIHTMLElementCollectionPtrを取得し、
IHTMLElementCollectionPtrからすべてのIHTMLElementPtrをループしgetAttributeで text であるものを取得するとか。
あれ?
> getElementsByName( TagName )で取得はできますが、IHTMLDocument2Ptrには
> メンバになく使うことができません。
getElementsByNameがあるんだったら、それ用にIHTMLDocument3Ptrの変数を用意して取得するだけなのでは?
// 用途によって、利用を切り分ける
MSHTML::IHTMLDocument2Ptr pDocument2( pBrowser->Document );
MSHTML::IHTMLDocument3Ptr pDocument( pBrowser->Document );
ちなみに
> 2006/06/30(金) 00:18:10
のサンプルでは、Frameを取得するためにトップのDocumentはIHTMLDocument2Ptrにしてありますが、
for文の中の
> MSHTML::IHTMLDocument2Ptr pDoc( pFrame->document );
は links プロパティを使いたいがために IHTMLDocument2Ptr にしました。
結局 Aタグ の要素を取得するのであるならば、
MSHTML::IHTMLDocument3Ptr pDoc( pFrame->document );
// すべてのリンクをチェック
MSHTML::IHTMLElementCollectionPtr pCollection( pDoc->getElementsByTagName( _bstr_t( L"A" ) ) );
で同様の動きはできると思います。
ご教授ありがとうございます。
INPUTタグを抽出し目的の名前があった時、
処理をすることで実現することができました。
ありがとうございます。
// すべてのINPUTタグをチェック
MSHTML::IHTMLElementCollectionPtr pCollection( pDoc->getElementsByTagName( _bstr_t( L"INPUT" ) ) );
for ( long j = 0L; j < pCollection->length; j++ )
{
MSHTML::DispHTMLInputElementPtr pInText( pCollection->item( _variant_t( j ) ) );
//INPUTタグにはname要素がない時がある
if ((LPCTSTR)pInText->name != (NULL))
{
if ( _bstr_t( pAnchor->href ) == _bstr_t( L"http" ) )
{
処理内容
}
}
}
> //INPUTタグにはname要素がない時がある
> if ((LPCTSTR)pInText->name != (NULL))
ここは、個人的には
if ( pInText->name.length() == 0 )
です。
ちなみに、テキストボックスかどうかはtypeもみないといけないです。
if ( _wcsicmp( pInText->type, L"text" ) == 0 )
// if ( pInText->type == _bstr_t( L"text" ) )
見たいなので、確認するとよいでしょう。
ツイート | ![]() |