前些日子,有關注我Blog的朋友應該都已經注意到,我發表了Web Browser (Ph) Application上架Marketplace的相關資訊,也分享了退件及通過審核的一些過程。
現在讓我將開發這個應用程式的經驗與大家分享。
Understanding Web Browser Control of Windows Phone 7 – Part 1
文/黃忠成
The Web Browser (Ph) Application
前些日子,有關注我Blog的朋友應該都已經注意到,我發表了Web Browser (Ph) Application上架Marketplace的相關資訊,也分享了退件及通過審核的一些過程。
現在讓我將開發這個應用程式的經驗與大家分享。
除了個人懶惰沒看清認證的一些規則導致退件的經驗之外,Web Browser(Ph)於開發中有兩個問題是最重要的,第一個當然是中文輸入法,此問題的解法其實很簡單,
就是必須要擁有相關的字及注音碼,接著就只要做介面就好了,如果對此有興趣及需要,我建議讀者們參考David老師與光岩資訊提供的控制項(因為我的字庫其實並不完整)。
第二個問題就是,Web Browser (Ph) 是如何知道,使用者點選到了某個輸入框? 又是如何將輸入的中文字放到輸入框裡? Web Browser控制項其實用法分為簡易
與深入兩種,簡易的將其拿來做為顯示某個網頁用,深度的用法則是在顯示網頁後,嘗試將整個網頁的控制權拿在手裡,Web Browser (Ph)即是深度的用法。
OK,那麼Web Browser(Ph)如何知道使用者點選到了某個輸入框?很簡單,Web Browser(Ph)有個函式: InvokeScript,可以讓開發者在Web Browser讀入網頁後,
呼叫網頁中的某個JavaScript,原意是想讓開發者在使用NavigateToString、Navigate瀏覽本機網頁時能有個溝通的管道。
而Web Browser(Ph)將此技術發揮到極致,經測試得知,InvokeScript其實不僅只能在瀏覽本機網頁,瀏覽一般網頁時也可正常運作,這意味著Web Browser(Ph)
可以在使用者瀏覽網頁後,以InvokeScript來呼叫特定的JavaScript函式,那這有什麼用呢?
細想一下,有哪個JavaScript函式可以讓你列舉出網頁上所有的input type=text控制項? document.getElementsByTagName !! 但此路不通,因為InvokeScript僅能呼叫函式,
像getElementsByTagName這種掛在某個物件下的函式是無法透過InvokeScript呼叫的。
所以我們得找另一條路,有哪個函式可以讓InvokeScript正常呼叫,又能達到與getElementsByTagName一樣的效果? 答案很明白,就是eval函式,這個函式可以讓我們執行
大多數的JavaScript程式碼,這便是Web Browser (Ph)所仰賴的關鍵技術。
關於Tel/Sms Tag
Web Browser控制項很強,但是其有一點與內建的IE不同,那就是在內建的IE下是可以解析<a href=”tel:0984xxxxx”/> Tag的,透過這個機制,使用者可以在瀏覽到使用此Tag的網頁時,
點選該連結來撥出電話,但Web Browser控制項目前並不支援這個機制,這是已知的限制。
這些tel tag最常出現在搜尋引擎的網頁,例如Google Maps。
圖1
於內建的IE上點選電話部份的連結,會啟動撥號動作。
圖2
但Web Browser控制項並不支援這種應用,也就是其不認識<a href=”tel:0984xxxxx”/>,要解決這個問題,我們得自己來處理,前面所提到的InvokeScript+Eval的技巧正巧可用上。
首先,我們得想辦法在Web Browser載入網頁後,執行一段JavaScript,搜尋網頁中所有的<a> 元素,緊接著解析其href attribute,只要發現是以tel: 開頭,即將其改為#,
並掛上onclick事件來處理使用者按下連結的後續動作。
MainPage.xaml |
<phone:PhoneApplicationPage x:Class="DetectTelTag.MainPage" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:phone="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone" xmlns:shell="clr-namespace:Microsoft.Phone.Shell;assembly=Microsoft.Phone" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d"d:DesignWidth="480"d:DesignHeight="768" FontFamily="{StaticResourcePhoneFontFamilyNormal}" FontSize="{StaticResourcePhoneFontSizeNormal}" Foreground="{StaticResourcePhoneForegroundBrush}" SupportedOrientations="Portrait"Orientation="Portrait" shell:SystemTray.IsVisible="True">
<!--LayoutRoot is the root grid where all page content is placed--> <Gridx:Name="LayoutRoot"Background="Transparent"> <Grid.RowDefinitions> <RowDefinitionHeight="Auto"/> <RowDefinitionHeight="*"/> </Grid.RowDefinitions>
<!--TitlePanel contains the name of the application and page title--> <StackPanelx:Name="TitlePanel"Grid.Row="0"Margin="12,17,0,28"> <TextBlockx:Name="ApplicationTitle"Text="MY APPLICATION"Style="{StaticResourcePhoneTextNormalStyle}"/> <TextBlockx:Name="PageTitle"Text="Maps"Margin="9,-7,0,0"Style="{StaticResourcePhoneTextTitle1Style}"/> </StackPanel>
<!--ContentPanel - place additional content here--> <Gridx:Name="ContentPanel"Grid.Row="1"Margin="12,0,12,0"> <phone:WebBrowserHorizontalAlignment="Left" Name="webBrowser1"VerticalAlignment="Top"Height="537"Width="456"Margin="0,64,0,0"LoadCompleted="webBrowser1_LoadCompleted"/> <ButtonContent="Go"Height="72"HorizontalAlignment="Left"Name="button1"VerticalAlignment="Top"Width="160"Click="button1_Click" /> </Grid> </Grid>
</phone:PhoneApplicationPage> |
MainPage.xaml.cs |
|
這段程式碼有幾個地方需要特別解釋,一是WebBrowser的IsScriptEnabled屬性,這個屬性值必須在呼叫Navigate來導向某個網頁前設定,當此值設定為true時,InvokeScript才能正常呼叫。
此程式在呼叫Navigate,Web Browser載入網頁後,以InvokeScript+Eval的技巧注入一段JavaScript程式至該網頁中,其中的Initialize便是搜尋網頁中所有的a 元素,並且判別是否是
<a href=”tel:xxx” />格式,如確認為此格式,便先將其href改為#,阻止預設的連結導向行為,接著掛載onclick事件,於使用者點下該連結時,將原先tel: 後面的電話號碼放到currentActiveTel全域變數中。
最後一個步驟就是以DispatcherTime每秒呼叫一次DetectStatus函式來偵測currentActiveTel的狀態,當currentActivceTel有值時,便代表著使用者按下某個tel 連結。
圖3
圖4
類似的sms:xxxx 格式也可以用同樣的手法解決。
範例下載:
http://cid-1e6d55012e5efedb.office.live.com/self.aspx/%e5%85%ac%e9%96%8b/WP7%5E_UWP/DetectTelTag.zip