はじめに
久々の perl。突っ込まれるのを期待しつつやってみます。
何から始めよう
IE8 をどこまで操作できるかやってみる。
IE8 を起動
use strict; use warnings; use utf8; system('explorer http://www.google.co.jp/');
IE8 のウィンドウハンドルを取得
use strict; use warnings; use utf8; use Data::Dumper; use Win32::GuiTest qw(:ALL); # これをやっておかないと中で shift-jis 前提で扱われるみたい UnicodeSemantics(1); system('explorer http://www.google.co.jp/'); # IE8 が立ち上がるまで待つ # FindWindowLike の第一引数が 0 だと、デスクトップ上の全ウィンドウに対して検索してくれる sleep(0.2) while (!scalar(FindWindowLike(0, 'Windows Internet Explorer$'))); # IE8 のウィンドウハンドルを表示 print Dumper([FindWindowLike(0, 'Windows Internet Explorer$')]);
WindowText と ClassName を取得してみる。
use strict; use warnings; use utf8; use Data::Dumper; use Win32::GuiTest qw(:ALL); # これをやっておかないと中で shift-jis 前提で扱われるみたい UnicodeSemantics(1); system('explorer http://www.google.co.jp/'); # IE8 が立ち上がるまで待つ # FindWindowLike の第一引数が 0 だと、デスクトップ上の全ウィンドウに対して検索してくれる sleep(0.2) while (!scalar(FindWindowLike(0, 'Windows Internet Explorer$'))); # IE8 のウィンドウハンドルを表示 print Dumper([map { [ GetWindowText($_), GetClassName($_) ] } FindWindowLike(0, 'Windows Internet Explorer$')]);
原因は?
- Googe が読み込まれる前だったから。
そっかー。そういえば HTML の内容で WindowText は変化するから、 ClassName からウィンドウハンドルを取得したほうがいいかもなー。
ちょっと修正
use strict; use warnings; use utf8; use Data::Dumper; use Win32::GuiTest qw(:ALL); # これをやっておかないと中で shift-jis 前提で扱われるみたい UnicodeSemantics(1); system('explorer http://www.google.co.jp/'); my $win = do { my @wins; # ClassName からウィンドウハンドルを取得 sleep(0.2) while (!scalar(@wins = FindWindowLike(0, undef, '^IEFrame$'))); # 1 画面だけ開いている前提で die 'There should be one IE8 Window.' if (scalar(@wins) != 1); shift @wins; }; print Dumper({ title => GetWindowText($win), class => GetClassName($win) });
IE8 のメインウィンドウが持っている子ウィンドウの情報を出す
use strict; use warnings; use utf8; use Data::Dumper; use Win32::GuiTest qw(:ALL); # これをやっておかないと中で shift-jis 前提で扱われるみたい UnicodeSemantics(1); system('explorer http://www.google.co.jp/'); my $win = do { my @wins; # ClassName からウィンドウハンドルを取得 sleep(0.2) while (!scalar(@wins = FindWindowLike(0, undef, '^IEFrame$'))); # 1 画面だけ開いている前提で die 'There should be one IE8 Window.' if (scalar(@wins) != 1); shift @wins; }; print Dumper([ map { # これで $win からの深さが取れるみたい '--' x GetChildDepth($win, $_) . ' ' . GetWindowText($_) . ' (' . GetClassName($_) . ')' } GetChildWindows($win) ]);
UTF8 なので表示できてない場所があるよ!助けてダンコーガイ!
Encode 使う
use strict; use warnings; use utf8; use Data::Dumper; use Win32::GuiTest qw(:ALL); use Encode; # cp932 (Windows で使われてる Shift-jis 的な何か my $cp932 = find_encoding('cp932'); # これをやっておかないと中で shift-jis 前提で扱われるみたい UnicodeSemantics(1); system('explorer http://www.google.co.jp/'); my $win = do { my @wins; # ClassName からウィンドウハンドルを取得 sleep(0.2) while (!scalar(@wins = FindWindowLike(0, undef, '^IEFrame$'))); # 1 画面だけ開いている前提で die 'There should be one IE8 Window.' if (scalar(@wins) != 1); shift @wins; }; # 子孫ウィンドウ for (GetChildWindows($win)) { # 出力は cp932 で print $cp932->encode( # $win からの深さ '--' x GetChildDepth($win, $_) . ' ' . GetWindowText($_) . ' (' . GetClassName($_) . ")\n" ); }
ロケーションバーに WM_GETTEXT を送って URL を取る
Win32::GuiTest では WMGetText という関数を使えば WM_GETTEXT を遅れるみたい。
use strict; use warnings; use utf8; use Data::Dumper; use Win32::GuiTest qw(:ALL); use Encode; # cp932 (Windows で使われてる Shift-jis 的な何か my $cp932 = find_encoding('cp932'); # これをやっておかないと中で shift-jis 前提で扱われるみたい UnicodeSemantics(1); system('explorer http://www.google.co.jp/'); my ($win, $address_band_root, $address_edit, $url) = do { my (@wins, $win, @address_band_roots, $address_band_root, @address_edits, $address_edit, $url); # IEFrame のウィンドウハンドルを取得 sleep(0.2) while (!scalar(@wins = FindWindowLike(0, undef, '^IEFrame$'))); die 'There should be one IE8 Window.' if (scalar(@wins) != 1); $win = shift @wins; # Address Band Root のウィンドウハンドルを取得 sleep(0.2) while (!scalar(@address_band_roots = FindWindowLike($win, undef, 'Address Band Root'))); die 'There should be one IE8 Address Band Root.' if (scalar(@address_band_roots) != 1); $address_band_root = shift @address_band_roots; # Address Band Root の子孫の Edit を探す sleep(0.2) while (!scalar(@address_edits = FindWindowLike($address_band_root, undef, 'Edit'))); die 'There should be one IE8 Address Edit.' if (scalar(@address_edits) != 1); $address_edit = shift @address_edits; # Edit の内容が入るまで待つ sleep(0.2) while(($url = WMGetText($address_edit)) eq ''); # IEFrame, Address Band Root, Edit ウィンドウクラスと WMGetText の結果を返す ($win, $address_band_root, $address_edit, $url); }; print $cp932->encode($url . "\n");
ロケーションバーにキーボードイベントを送ってページ遷移
use strict; use warnings; use utf8; use Data::Dumper; use Win32::GuiTest qw(:ALL); use Encode; # cp932 (Windows で使われてる Shift-jis 的な何か my $cp932 = find_encoding('cp932'); # これをやっておかないと中で shift-jis 前提で扱われるみたい UnicodeSemantics(1); system('explorer http://www.google.co.jp/'); my ($win, $address_band_root, $address_edit, $url) = do { my (@wins, $win, @address_band_roots, $address_band_root, @address_edits, $address_edit, $url); # IEFrame のウィンドウハンドルを取得 sleep(0.2) while (!scalar(@wins = FindWindowLike(0, undef, '^IEFrame$'))); die 'There should be one IE8 Window.' if (scalar(@wins) != 1); $win = shift @wins; # Address Band Root のウィンドウハンドルを取得 sleep(0.2) while (!scalar(@address_band_roots = FindWindowLike($win, undef, 'Address Band Root'))); die 'There should be one IE8 Address Band Root.' if (scalar(@address_band_roots) != 1); $address_band_root = shift @address_band_roots; # Address Band Root の子孫の Edit を探す sleep(0.2) while (!scalar(@address_edits = FindWindowLike($address_band_root, undef, 'Edit'))); die 'There should be one IE8 Address Edit.' if (scalar(@address_edits) != 1); $address_edit = shift @address_edits; # Edit の内容が入るまで待つ sleep(0.2) while(($url = WMGetText($address_edit)) eq ''); # IEFrame, Address Band Root, Edit ウィンドウクラスと WMGetText の結果を返す ($win, $address_band_root, $address_edit, $url); }; # ロケーションバーにフォーカスさせて SetFocus($address_edit); # key を送る("~" はエンターキーの意味) SendKeys('http://www.yahoo.co.jp/~');
あー。ダメだ。Google のトップページの window.onload で、検索ボックスにフォーカス取られちゃうなー。
結果として、検索されちゃった
ロケーションバーの値を直接書き換えて、移動ボタンを押すようにしたい。
移動ボタンを押すには、 Toolbar に SendMessage して構造体を取得しなきゃダメみたい。
SendMessage 自体は Win32::GuiTest で出来るのだけど「構造体の領域を確保して、そのポインタを渡す」なんてことはできるのかなー。
なんか、 AllocateVirtualBuffer を使えば共有メモリをアロケートできそうだ。でも、 TBBUTTON の sizeof を perl から取れない><
やっぱ、 XS しなきゃだめなのかな?
中途半端だけど
もう遅いので寝ます。
来週末あたりにもう一度調べよう。