webブラウザを自作したい!(3)
今回は前回言ってたように戻る進む再読込とかとか
・
・
・
・
ではなく、「サイトのアイコンを適用する」です。
サイトのアイコンを適用する
え?それだけ?
はいそれだけです(それ以外にもちょっとあるよ)
コレがわりと苦労しました。
簡単そうに見えてこれ持ってるプロパティとかなさそうで、html内部からURL探して持ってくる必要がありました。
もっといい方法ありそうですが、とりあえずぶん殴る形式になっちゃいました。知ってる人おしえてください・・・><
それではSSから
まあこんな感じで変わってますね。
ソースコード
private void Browser_Navigated( object sender, WebBrowserNavigatedEventArgs e ) { //this.Text = browser.DocumentTitle; this.urlBox.Text = browser.Url.ToString(); string iconUrl = getIconUrl( e ); this.Icon = getIcon( iconUrl ); } private string getIconUrl( WebBrowserNavigatedEventArgs e ) { foreach( HtmlElement linkTag in this.browser.Document.GetElementsByTagName("link") ) { string relAttribute = linkTag.GetAttribute("rel"); string iconUrl; if( relAttribute == "shortcut icon" || relAttribute == "icon" ) { iconUrl = linkTag.GetAttribute("href"); if( iconUrl.StartsWith("http") ) return iconUrl; else if( iconUrl.StartsWith("/") ) return "http://" + e.Url.Host + iconUrl; else return e.Url.ToString() + iconUrl; } } return "http://" + e.Url.Host + "/favicon.ico"; } //url -> Icon private Icon getIcon( string url ) { WebClient webClient = new WebClient(); using( MemoryStream stream = new MemoryStream( webClient.DownloadData( url ) ) ) { Icon icon = new Icon( stream ); return icon; } } private void Browser_DocumentCompleted( object sender, WebBrowserDocumentCompletedEventArgs e ) { this.Text = browser.DocumentTitle; }
ざっくりいじった所だけ貼りました。
getIconUrl()でアイコンのURLを引っぱってきて、getIcon()でURLからアイコンを取得する感じです。
private string getIconUrl( WebBrowserNavigatedEventArgs e ) { foreach( HtmlElement linkTag in this.browser.Document.GetElementsByTagName("link") ) { string relAttribute = linkTag.GetAttribute("rel"); string iconUrl; if( relAttribute == "shortcut icon" || relAttribute == "icon" ) { iconUrl = linkTag.GetAttribute("href"); if( iconUrl.StartsWith("http") ) return iconUrl; else if( iconUrl.StartsWith("/") ) return "http://" + e.Url.Host + iconUrl; else return e.Url.ToString() + iconUrl; } } return "http://" + e.Url.Host + "/favicon.ico"; }
ホントにぶん殴りコードですね・・・^^;
とりあえずlinkタグのやつを全部抽出してその中のrel探してきて、その属性がicon系なら引っ張るって感じですね。
それでも無かったらfavicon.icoにあるんじゃねってことで最後です。
C#でスクレイピングしたこと無かったので苦戦しました・・・。
でも完成してみたら、割りと読みやすいというかわかりやすいコードになりました。
もっといい方法ないかなぁ(ボソッ
private Icon getIcon( string url ) { WebClient webClient = new WebClient(); using( MemoryStream stream = new MemoryStream( webClient.DownloadData( url ) ) ) { Icon icon = new Icon( stream ); return icon; } }
getIcon()はurlからアイコンを持ってくるメソッドです。
urlの示すデータを読み込んで、それをアイコンとして読み出す、ってイメージでしょうか。
んでそれらを↓でまとめるって感じになってます。
private void Browser_Navigated( object sender, WebBrowserNavigatedEventArgs e ) { //this.Text = browser.DocumentTitle; this.urlBox.Text = browser.Url.ToString(); string iconUrl = getIconUrl( e ); //url持ってきて this.Icon = getIcon( iconUrl ); //アイコンにする }
ここで気がついた人もいるかもですが、タイトルを取得するイベントを
WebBrowser.Navigated()
↓
WebBrowser.DocumentCompleted()
に変更しました。
Navigatedだとまだサイトに案内できただけで、中身をすべてロードできていない(?)状態らしいです。
実際に、Navigatedだとタイトルを取得できないサイトが複数ありました。(←これはタイミングの問題でもあるかも)
DocumentCompletedは、サイトの中身のロードが完了すると発生するイベントなので、これを利用しようという結論になりました。これだと全部タイトルがしっかり適用されました。
大した変更じゃないけど、結構重要なのでやっておきました。
それでは今回はここまで。
次回こそは、戻る進む再読込つくろう!(全然難しくないんだけどね())
webブラウザを自作したい!(2)
URLボックスの実装
見た目
↑こんな風にしっかり変わります。
ちゃんと入力してEnterキーで飛ぶこともできるよ!
これがめちゃめちゃ時間かかったんだよなぁ(なんで)
あとちゃっかりタイトルもサイトによって変わるようにいじってます。
ソースコード
using System; using System.Drawing; using System.Windows.Forms; //mainは割愛 class Browser : Form { WebBrowser browser; TextBox urlBox; public Browser() { //item browser = new WebBrowser() { Location = new Point( 0, 30 ), Size = new Size( 1200, 800 ) }; urlBox = new TextBox() { Location = new Point( 30, 2 ), Size = new Size( 1000, 20 ), Font = new Font( "meiryo", 10 ) }; this.Controls.Add( browser ); this.Controls.Add( urlBox ); //event handler this.Shown += new EventHandler( this.Browser_Load ); this.SizeChanged += new EventHandler( this.ReSized ); } private void Browser_Load( object sender, EventArgs e ) { this.ClientSize = new Size( 1200, 830 ); this.Text = "My Browser"; //script error block browser.ScriptErrorsSuppressed = true; //event handler browser.Navigated += new WebBrowserNavigatedEventHandler( this.Browser_Navigated ); urlBox.KeyDown += new KeyEventHandler( this.urlBox_KeyDown ); //first page string url = "http://www.google.co.jp"; browser.Navigate( url ); } private void urlBox_KeyDown( object sender, KeyEventArgs e ) { if( e.KeyCode == Keys.Enter ) { if( urlBox.Text != string.Empty ) { browser.Navigate( urlBox.Text ); } } } private void Browser_Navigated( object sender, WebBrowserNavigatedEventArgs e ) { this.Text = browser.DocumentTitle; this.urlBox.Text = browser.Url.ToString(); } private void ReSized( object sender, EventArgs e ) { int width = this.ClientSize.Width; int height = this.ClientSize.Height; this.browser.Size = new Size( width, height - 30 ); } }
前回に比べてちょっと増えましたね(当たり前)
urlBox = new TextBox() //URLいれるやつ { Location = new Point( 30, 2 ), Size = new Size( 1000, 20 ), Font = new Font( "meiryo", 10 ) };
TextBoxは結局フォントの大きさでheightが決まるみたいなので適当に目分量で決めました。
ゆるしてくださいなんでもしません。(しません。)
フォントがメイリオなのに深い意味はありません。思いついたのがメイリオだっただけです。
private void Browser_Navigated( object sender, WebBrowserNavigatedEventArgs e ) { this.Text = browser.DocumentTitle; //タイトルを変更 this.urlBox.Text = browser.Url.ToString(); //URLボックスに今のページのURLを格納 }
WebBrowser.Navigatedイベントはページ移動したときに発生するイベントらしいです。(雑)
だったらそこでタイトルとURL更新すればいいじゃないということで更新。
private void urlBox_KeyDown( object sender, KeyEventArgs e ) { if( e.KeyCode == Keys.Enter ) //押されたキーがEnterキーだったら { if( urlBox.Text != string.Empty ) //URLボックスが空じゃなかったら { browser.Navigate( urlBox.Text ); //そのURL先に移動 } } }
TextBox(Control).KeyDownイベントはキーが押下されたときに発生するイベントらしいです。
それ利用して移動させちゃいます。
先程言った時間のかかったポイントは e,KeyCode の部分です。
は?
普通じゃん。
そう今思えば普通なんですね。
ですが僕は Ctrl, Shift, Alt のような修飾キーの押されたモノを持つ Control.ModifierKeys と一生懸命比較していたためできなかった。
雑魚確定ですねorz
ここまでで一応今回の目標(?)は達成なんですが、1つやることがあります。
//script error block browser.ScriptErrorsSuppressed = true;
これです。
これはスクリプトエラーを表示しないというフラグです。
trueで表示しないとなります。(デフォルト:false)
これしないとスクリプトエラー出まくってまともにブラウジングできなかったのでしておきます。
次回は戻る・進む・再読込機能とお気に入り機能付けたいなぁ・・・・(時間をくれ)
webブラウザを自作したい!(1)
今回はC#を用いてwebブラウザを作りたいと思います。
進捗があがり次第記事を書いていく形になると思いますし、完成形は考えて無いので(n)まで続きます。(どこまで続くかわからない)
それと、何故作るかというと...........作りたいからです。(理由はいらないですね)
基盤を作る
(1)なのでとりあえずは基盤というか、そんな感じのモノを作る。
今回作ったのは、実行したらgoogleに繋がるだけの代物。
UIなんて気にするな。↓の感じで。
タイトルバーの下のスペースはアドレスバーとか入れようかなって思って空けた。
ソースコード
using System; using System.Drawing; using System.Windows.Forms; namespace Webbrowser { class Program { [STAThread] static void Main() { Application.EnableVisualStyles(); Application.Run( new Browser() ); } } class Browser : Form { WebBrowser browser; public Browser() { browser = new WebBrowser() { Location = new Point( 0, 30 ), Size = new Size( 1200, 800 ) }; this.Controls.Add( browser ); this.Shown += new EventHandler( this.Browser_Load ); this.SizeChanged += new EventHandler( this.ReSized ); string url = "http://www.google.co.jp"; browser.Navigate( url ); } private void Browser_Load( object sender, EventArgs e ) { this.ClientSize = new Size( 1200, 830 ); this.Text = "My Browser"; } private void ReSized( object sender, EventArgs e ) { int width = this.ClientSize.Width; int height = this.ClientSize.Height; this.browser.Size = new Size( width, height - 30 ); } } }
こんな感じになった。クソコードっていうな
はい。
後々改造していくし、まだハリボテなので許して。
WebBrowser browser;
こいつはwebブラウザに必要な事(低レイヤの部分?)を全部まるっとやってくれるすごいやつだ!
これをAddするだけで表示ができちゃう!正直びっくりした。
コレに頼ればできちゃうけど、中身もちゃんと理解できるようになりたいですね.....。
まあ今は使えるものは使いましょっと^^
string url = "http://www.google.co.jp"; //urlをstring型変数に格納 browser.Navigate( url ); //urlをNavigateメソッドに渡す
WebBrowser.Navigate()は指定したURLに飛んでくれるメソッド。
圧倒的便利感。
//ウインドウのサイズが変更されたときに発火するメソッド private void ReSized( object sender, EventArgs e ) { int width = this.ClientSize.Width; //現在のウインドウの横幅を格納 int height = this.ClientSize.Height; //現在のウインドウの縦幅を格納 this.browser.Size = new Size( width, height - 30 ); //表示領域を現在のモノに更新 }
一応リサイズにも対応できるようにしたよ。
あいさつ。
こんにちは。
当ブログでは僕の勉強記録や思ったこと等を書いていきます。
続くかどうかわからないし本人が忘れる可能性までありますが、どうか温かい目で見ていてくれると嬉しいです。
基本IT関連のブログになるかと思われます。
書いた中で、間違ってる事や補足等があったらガンガンまさかりぶん投げてくれて結構ですのでよろしくお願いします^^
僕がここに書いたことが、僕の後続(初心者)の方々の役に立ったら嬉しいです。
それと更新したら都度ツイートしますが、全然投稿されない.....Twitterには居るのになぁって時は、忘れている可能性大ですので言ってくれると助かります。
それではよろしくお願いします^^
↓最近買ったthink padちゃん(13インチ)
かわゆい
もちろんUS配列