因為不是走Web開發的,這塊對於筆者滿陌生的,一直滿好奇Facebook打入網址後會顯示的預覽畫面是怎樣做的。抽空參閱Creating a Facebook Like Website Previewer這篇並試玩了一下,發現沒有想像中的困難,只是很單純的從網頁內容中擷取資訊而已,這邊稍稍對此做個整理。

[C#]How to Build a Facebook-like Web Preview

這邊我們可以先來檢視一下奇摩的原始碼,對照上圖在FB所擷取到的資訊,我們不難看出資訊都是從網頁原始碼中擷取出來的。

[C#]How to Build a Facebook-like Web Preview

其中網頁預覽中的標題部份對應到的是這個HTML標籤所包的值,可以用下面的正規表示式將之擷取出來:</p> <div class="highlight"><pre tabindex="0" class="chroma"><code class="language-csharp" data-lang="csharp"><span class="line"><span class="cl"><span class="p"><</span><span class="n">title</span><span class="p">></span><span class="err">\</span><span class="n">s</span><span class="p">*(?<</span><span class="n">Title</span><span class="p">>[^<>]+)</span><span class="err">\</span><span class="n">s</span><span class="p">*</</span><span class="n">title</span><span class="p">></span> </span></span></code></pre></div><p>而網頁預覽中的網頁描述部份則是對應到name值為description的meta標籤,可以用下面的正規表示式將之擷取出來:</p> <div class="highlight"><pre tabindex="0" class="chroma"><code class="language-xml" data-lang="xml"><span class="line"><span class="cl"><span class="nt"><meta</span><span class="err">\s+</span><span class="na">name=</span><span class="s">"description"</span><span class="err">\s+content\s*=\s*"(?<Description</span><span class="nt">></span>[^<span class="err"><</span>>"]*)" </span></span></code></pre></div><p>至於網頁預覽中的縮圖部份,可能是來自rel值為image_src的link標籤或是來自img標籤,圖片的網址部份要盡可能完整才收進來,可以用下面的正規表示式將之擷取出來:</p> <div class="highlight"><pre tabindex="0" class="chroma"><code class="language-xml" data-lang="xml"><span class="line"><span class="cl"><span class="err"><</span>(?:img\s+src\s*=|link\s+rel\s*=\s*"image_src"\s+ href\s*=)"(?<span class="nt"><Thumbnail></span>http://[\w/.]+(?:jpg|bmp|gif))" </span></span></code></pre></div><p>實際在做擷取時,就會像下面這樣:</p> <div class="highlight"><pre tabindex="0" class="chroma"><code class="language-csharp" data-lang="csharp"><span class="line"><span class="cl"><span class="p">...</span> </span></span><span class="line"><span class="cl"><span class="cp">#region</span> <span class="n">Const</span> </span></span><span class="line"><span class="cl"><span class="kd">private</span> <span class="kd">const</span> <span class="kt">string</span> <span class="n">TITLE_MATCH_PATTERN</span> <span class="p">=</span> <span class="s">@"<title>\s*(?<Title>[^<>]+)\s*</title>"</span><span class="p">;</span> </span></span><span class="line"><span class="cl"><span class="kd">private</span> <span class="kd">const</span> <span class="kt">string</span> <span class="n">DESCRIPTION_MATCH_PATTERN</span> <span class="p">=</span> <span class="s">@"<meta\s+name=""description""\s+content\s*=\s*""(?<Description>[^<>""]*)"""</span><span class="p">;</span> </span></span><span class="line"><span class="cl"><span class="kd">private</span> <span class="kd">const</span> <span class="kt">string</span> <span class="n">THUMBNAIL_MATCH_PATTERN</span> <span class="p">=</span> <span class="s">@"<(?:img\s+src\s*=|link\s+rel\s*=\s*""image_src""\s+ href\s*=)""(?<Thumbnail>http://[\w/.]+(?:jpg|bmp|gif))"""</span><span class="p">;</span> </span></span><span class="line"><span class="cl"><span class="cp">#endregion</span> </span></span><span class="line"><span class="cl"><span class="p">...</span> </span></span><span class="line"><span class="cl"><span class="kt">string</span> <span class="n">htmlSourceCode</span><span class="p">;</span> </span></span><span class="line"><span class="cl"><span class="p">...</span> </span></span><span class="line"><span class="cl"><span class="kt">var</span> <span class="n">title</span> <span class="p">=</span> <span class="n">Regex</span><span class="p">.</span><span class="n">Match</span><span class="p">(</span><span class="n">htmlSourceCode</span><span class="p">,</span> <span class="n">TITLE_MATCH_PATTERN</span><span class="p">).</span><span class="n">Groups</span><span class="p">[</span><span class="s">"Title"</span><span class="p">].</span><span class="n">Value</span><span class="p">;</span> </span></span><span class="line"><span class="cl"><span class="kt">var</span> <span class="n">description</span> <span class="p">=</span> <span class="n">Regex</span><span class="p">.</span><span class="n">Match</span><span class="p">(</span><span class="n">htmlSourceCode</span><span class="p">,</span><span class="n">DESCRIPTION_MATCH_PATTERN</span><span class="p">).</span><span class="n">Groups</span><span class="p">[</span><span class="s">"Description"</span><span class="p">].</span><span class="n">Value</span><span class="p">;</span> </span></span><span class="line"><span class="cl"><span class="kt">var</span> <span class="n">thumbnailURLs</span> <span class="p">=</span> <span class="n">Regex</span><span class="p">.</span><span class="n">Matches</span><span class="p">(</span><span class="n">htmlSourceCode</span><span class="p">,</span> <span class="n">THUMBNAIL_MATCH_PATTERN</span><span class="p">,</span> <span class="n">RegexOptions</span><span class="p">.</span><span class="n">IgnorePatternWhitespace</span><span class="p">).</span><span class="n">Cast</span><span class="p"><</span><span class="n">Match</span><span class="p">>().</span><span class="n">Select</span><span class="p">(</span><span class="n">m</span> <span class="p">=></span> <span class="n">m</span><span class="p">.</span><span class="n">Groups</span><span class="p">[</span><span class="s">"Thumbnail"</span><span class="p">].</span><span class="n">Value</span><span class="p">);</span> </span></span></code></pre></div><p>這邊筆者在測試時隨手將這功能簡單的包了一下。</p> <div class="highlight"><pre tabindex="0" class="chroma"><code class="language-csharp" data-lang="csharp"><span class="line"><span class="cl"> <span class="kd">public</span> <span class="k">class</span> <span class="nc">WebPreview</span> </span></span><span class="line"><span class="cl"> <span class="p">{</span> </span></span><span class="line"><span class="cl"> <span class="cp">#region</span> <span class="n">Const</span> </span></span><span class="line"><span class="cl"> <span class="kd">private</span> <span class="kd">const</span> <span class="kt">string</span> <span class="n">TITLE_MATCH_PATTERN</span> <span class="p">=</span> <span class="s">@"<title>\s?(?<Title>[^<>]+)\s?</title>"</span><span class="p">;</span> </span></span><span class="line"><span class="cl"> <span class="kd">private</span> <span class="kd">const</span> <span class="kt">string</span> <span class="n">DESCRIPTION_MATCH_PATTERN</span> <span class="p">=</span> <span class="s">@"<meta\s+name=""description""\s+content\s?=""(?<Description>[^<>""]*)"">"</span><span class="p">;</span> </span></span><span class="line"><span class="cl"> <span class="kd">private</span> <span class="kd">const</span> <span class="kt">string</span> <span class="n">THUMBNAIL_MATCH_PATTERN</span> <span class="p">=</span> <span class="s">@"<(?:img\s+src\s*=|link\s+rel\s*=\s*""image_src""\s+ href\s*=)""(?<Thumbnail>http://[\w/.]+(?:jpg|bmp|gif))"""</span><span class="p">;</span> </span></span><span class="line"><span class="cl"> <span class="cp">#endregion</span> </span></span><span class="line"><span class="cl"> </span></span><span class="line"><span class="cl"> <span class="cp">#region</span> <span class="n">Var</span> </span></span><span class="line"><span class="cl"> <span class="kd">private</span> <span class="kt">string</span> <span class="n">_sourceCode</span><span class="p">;</span> </span></span><span class="line"><span class="cl"> <span class="kd">private</span> <span class="kt">string</span> <span class="n">_title</span><span class="p">;</span> </span></span><span class="line"><span class="cl"> <span class="kd">private</span> <span class="kt">string</span> <span class="n">_description</span><span class="p">;</span> </span></span><span class="line"><span class="cl"> <span class="kd">private</span> <span class="n">IEnumerable</span><span class="p"><</span><span class="n">String</span><span class="p">></span> <span class="n">_thumbnailURLs</span><span class="p">;</span> </span></span><span class="line"><span class="cl"> <span class="cp">#endregion</span> </span></span><span class="line"><span class="cl"> </span></span><span class="line"><span class="cl"> <span class="cp">#region</span> <span class="n">Private</span> <span class="n">Property</span> </span></span><span class="line"><span class="cl"> <span class="kd">public</span> <span class="kt">string</span> <span class="n">m_SourceCode</span> </span></span><span class="line"><span class="cl"> <span class="p">{</span> </span></span><span class="line"><span class="cl"> <span class="k">get</span> </span></span><span class="line"><span class="cl"> <span class="p">{</span> </span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">_sourceCode</span> <span class="p">??</span> <span class="p">(</span><span class="n">_sourceCode</span> <span class="p">=</span> <span class="n">GetHTMLSourceCode</span><span class="p">(</span><span class="n">URL</span><span class="p">));</span> </span></span><span class="line"><span class="cl"> <span class="p">}</span> </span></span><span class="line"><span class="cl"> <span class="p">}</span> </span></span><span class="line"><span class="cl"> <span class="cp">#endregion</span> </span></span><span class="line"><span class="cl"> </span></span><span class="line"><span class="cl"> <span class="cp">#region</span> <span class="n">Public</span> <span class="n">Property</span> </span></span><span class="line"><span class="cl"> <span class="cs">/// <summary></span> </span></span><span class="line"><span class="cl"> <span class="cs">/// Gets or sets the URL.</span> </span></span><span class="line"><span class="cl"> <span class="cs">/// </summary></span> </span></span><span class="line"><span class="cl"> <span class="cs">/// <value>The URL.</value></span> </span></span><span class="line"><span class="cl"> <span class="kd">public</span> <span class="kt">string</span> <span class="n">URL</span> <span class="p">{</span> <span class="k">get</span><span class="p">;</span> <span class="kd">private</span> <span class="k">set</span><span class="p">;</span> <span class="p">}</span> </span></span><span class="line"><span class="cl"> </span></span><span class="line"><span class="cl"> <span class="cs">/// <summary></span> </span></span><span class="line"><span class="cl"> <span class="cs">/// Gets the title.</span> </span></span><span class="line"><span class="cl"> <span class="cs">/// </summary></span> </span></span><span class="line"><span class="cl"> <span class="cs">/// <value>The title.</value></span> </span></span><span class="line"><span class="cl"> <span class="kd">public</span> <span class="kt">string</span> <span class="n">Title</span> </span></span><span class="line"><span class="cl"> <span class="p">{</span> </span></span><span class="line"><span class="cl"> <span class="k">get</span> </span></span><span class="line"><span class="cl"> <span class="p">{</span> </span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">_title</span> <span class="p">??</span> <span class="p">(</span><span class="n">_title</span> <span class="p">=</span> <span class="n">Regex</span><span class="p">.</span><span class="n">Match</span><span class="p">(</span><span class="n">m_SourceCode</span><span class="p">,</span> <span class="n">TITLE_MATCH_PATTERN</span><span class="p">).</span><span class="n">Groups</span><span class="p">[</span><span class="s">"Title"</span><span class="p">].</span><span class="n">Value</span><span class="p">);</span> </span></span><span class="line"><span class="cl"> <span class="p">}</span> </span></span><span class="line"><span class="cl"> <span class="p">}</span> </span></span><span class="line"><span class="cl"> </span></span><span class="line"><span class="cl"> <span class="cs">/// <summary></span> </span></span><span class="line"><span class="cl"> <span class="cs">/// Gets the description.</span> </span></span><span class="line"><span class="cl"> <span class="cs">/// </summary></span> </span></span><span class="line"><span class="cl"> <span class="cs">/// <value>The description.</value></span> </span></span><span class="line"><span class="cl"> <span class="kd">public</span> <span class="kt">string</span> <span class="n">Description</span> </span></span><span class="line"><span class="cl"> <span class="p">{</span> </span></span><span class="line"><span class="cl"> <span class="k">get</span> </span></span><span class="line"><span class="cl"> <span class="p">{</span> </span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">_description</span> <span class="p">??</span> <span class="p">(</span><span class="n">_description</span> <span class="p">=</span> <span class="n">Regex</span><span class="p">.</span><span class="n">Match</span><span class="p">(</span><span class="n">m_SourceCode</span><span class="p">,</span><span class="n">DESCRIPTION_MATCH_PATTERN</span><span class="p">).</span><span class="n">Groups</span><span class="p">[</span><span class="s">"Description"</span><span class="p">].</span><span class="n">Value</span><span class="p">);</span> </span></span><span class="line"><span class="cl"> <span class="p">}</span> </span></span><span class="line"><span class="cl"> <span class="p">}</span> </span></span><span class="line"><span class="cl"> </span></span><span class="line"><span class="cl"> <span class="kd">public</span> <span class="n">IEnumerable</span><span class="p"><</span><span class="n">String</span><span class="p">></span> <span class="n">ThumbnailURLs</span> </span></span><span class="line"><span class="cl"> <span class="p">{</span> </span></span><span class="line"><span class="cl"> <span class="k">get</span> </span></span><span class="line"><span class="cl"> <span class="p">{</span> </span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">_thumbnailURLs</span> <span class="p">??</span> <span class="p">(</span><span class="n">_thumbnailURLs</span> <span class="p">=</span> <span class="n">Regex</span><span class="p">.</span><span class="n">Matches</span><span class="p">(</span><span class="n">m_SourceCode</span><span class="p">,</span> <span class="n">THUMBNAIL_MATCH_PATTERN</span><span class="p">,</span> <span class="n">RegexOptions</span><span class="p">.</span><span class="n">IgnorePatternWhitespace</span><span class="p">).</span><span class="n">Cast</span><span class="p"><</span><span class="n">Match</span><span class="p">>().</span><span class="n">Select</span><span class="p">(</span><span class="n">m</span> <span class="p">=></span> <span class="n">m</span><span class="p">.</span><span class="n">Groups</span><span class="p">[</span><span class="s">"Thumbnail"</span><span class="p">].</span><span class="n">Value</span><span class="p">));</span> </span></span><span class="line"><span class="cl"> <span class="p">}</span> </span></span><span class="line"><span class="cl"> <span class="p">}</span> </span></span><span class="line"><span class="cl"> <span class="cp">#endregion</span> </span></span><span class="line"><span class="cl"> </span></span><span class="line"><span class="cl"> <span class="cp">#region</span> <span class="n">Constructor</span> </span></span><span class="line"><span class="cl"> <span class="kd">public</span> <span class="n">WebPreview</span> <span class="p">(</span><span class="kt">string</span> <span class="n">url</span><span class="p">)</span> </span></span><span class="line"><span class="cl"> <span class="p">{</span> </span></span><span class="line"><span class="cl"> <span class="k">this</span><span class="p">.</span><span class="n">URL</span> <span class="p">=</span> <span class="n">url</span><span class="p">;</span> </span></span><span class="line"><span class="cl"> <span class="p">}</span> </span></span><span class="line"><span class="cl"> <span class="cp">#endregion</span> </span></span><span class="line"><span class="cl"> </span></span><span class="line"><span class="cl"> <span class="cp">#region</span> <span class="n">Private</span> <span class="n">Method</span> </span></span><span class="line"><span class="cl"> <span class="kd">private</span> <span class="kt">string</span> <span class="n">GetHTMLSourceCode</span><span class="p">(</span><span class="kt">string</span> <span class="n">url</span><span class="p">)</span> </span></span><span class="line"><span class="cl"> <span class="p">{</span> </span></span><span class="line"><span class="cl"> <span class="n">HttpWebRequest</span> <span class="n">request</span> <span class="p">=</span> <span class="p">(</span><span class="n">WebRequest</span><span class="p">.</span><span class="n">Create</span> <span class="p">(</span><span class="n">url</span><span class="p">))</span> <span class="k">as</span> <span class="n">HttpWebRequest</span><span class="p">;</span> </span></span><span class="line"><span class="cl"> <span class="n">HttpWebResponse</span> <span class="n">response</span> <span class="p">=</span> <span class="n">request</span><span class="p">.</span><span class="n">GetResponse</span><span class="p">()</span> <span class="k">as</span> <span class="n">HttpWebResponse</span><span class="p">;</span> </span></span><span class="line"><span class="cl"> <span class="k">using</span> <span class="p">(</span><span class="n">StreamReader</span> <span class="n">sr</span> <span class="p">=</span> <span class="k">new</span> <span class="n">StreamReader</span><span class="p">(</span><span class="n">response</span><span class="p">.</span><span class="n">GetResponseStream</span><span class="p">()))</span> </span></span><span class="line"><span class="cl"> <span class="p">{</span> </span></span><span class="line"><span class="cl"> <span class="k">return</span> <span class="n">sr</span><span class="p">.</span><span class="n">ReadToEnd</span><span class="p">();</span> </span></span><span class="line"><span class="cl"> <span class="p">}</span> </span></span><span class="line"><span class="cl"> <span class="p">}</span> </span></span><span class="line"><span class="cl"> <span class="cp">#endregion</span> </span></span><span class="line"><span class="cl"> <span class="p">}</span> </span></span></code></pre></div><p>使用起來就只要在建立物件時帶入網址就可以了。</p> <div class="highlight"><pre tabindex="0" class="chroma"><code class="language-csharp" data-lang="csharp"><span class="line"><span class="cl"><span class="k">using</span> <span class="nn">System</span><span class="p">;</span> </span></span><span class="line"><span class="cl"><span class="k">using</span> <span class="nn">System.Collections.Generic</span><span class="p">;</span> </span></span><span class="line"><span class="cl"><span class="k">using</span> <span class="nn">System.ComponentModel</span><span class="p">;</span> </span></span><span class="line"><span class="cl"><span class="k">using</span> <span class="nn">System.Data</span><span class="p">;</span> </span></span><span class="line"><span class="cl"><span class="k">using</span> <span class="nn">System.Drawing</span><span class="p">;</span> </span></span><span class="line"><span class="cl"><span class="k">using</span> <span class="nn">System.Linq</span><span class="p">;</span> </span></span><span class="line"><span class="cl"><span class="k">using</span> <span class="nn">System.Text</span><span class="p">;</span> </span></span><span class="line"><span class="cl"><span class="k">using</span> <span class="nn">System.Windows.Forms</span><span class="p">;</span> </span></span><span class="line"><span class="cl"> </span></span><span class="line"><span class="cl"><span class="k">namespace</span> <span class="nn">WindowsFormsApplication36</span> </span></span><span class="line"><span class="cl"><span class="p">{</span> </span></span><span class="line"><span class="cl"> <span class="kd">public</span> <span class="kd">partial</span> <span class="k">class</span> <span class="nc">Form1</span> <span class="p">:</span> <span class="n">Form</span> </span></span><span class="line"><span class="cl"> <span class="p">{</span> </span></span><span class="line"><span class="cl"> <span class="kd">private</span> <span class="kt">int</span> <span class="n">m_Index</span> <span class="p">{</span> <span class="k">get</span><span class="p">;</span> <span class="k">set</span><span class="p">;</span> <span class="p">}</span> </span></span><span class="line"><span class="cl"> <span class="kd">private</span> <span class="kt">string</span><span class="p">[]</span> <span class="n">m_ThumbnailURLs</span> <span class="p">{</span> <span class="k">get</span><span class="p">;</span> <span class="k">set</span><span class="p">;</span> <span class="p">}</span> </span></span><span class="line"><span class="cl"> </span></span><span class="line"><span class="cl"> <span class="kd">public</span> <span class="n">Form1</span><span class="p">()</span> </span></span><span class="line"><span class="cl"> <span class="p">{</span> </span></span><span class="line"><span class="cl"> <span class="n">InitializeComponent</span><span class="p">();</span> </span></span><span class="line"><span class="cl"> <span class="p">}</span> </span></span><span class="line"><span class="cl"> </span></span><span class="line"><span class="cl"> <span class="kd">private</span> <span class="k">void</span> <span class="n">UpdateThumbnailIndexStatus</span><span class="p">()</span> </span></span><span class="line"><span class="cl"> <span class="p">{</span> </span></span><span class="line"><span class="cl"> <span class="n">lblIndexStatus</span><span class="p">.</span><span class="n">Text</span> <span class="p">=</span> <span class="kt">string</span><span class="p">.</span><span class="n">Format</span><span class="p">(</span><span class="s">"{0}/{1}"</span><span class="p">,</span> <span class="n">m_Index</span> <span class="p">+</span> <span class="m">1</span><span class="p">,</span> <span class="n">m_ThumbnailURLs</span><span class="p">.</span><span class="n">Length</span><span class="p">);</span> </span></span><span class="line"><span class="cl"> <span class="p">}</span> </span></span><span class="line"><span class="cl"> </span></span><span class="line"><span class="cl"> <span class="kd">private</span> <span class="k">void</span> <span class="n">btnGO_Click</span><span class="p">(</span><span class="kt">object</span> <span class="n">sender</span><span class="p">,</span> <span class="n">EventArgs</span> <span class="n">e</span><span class="p">)</span> </span></span><span class="line"><span class="cl"> <span class="p">{</span> </span></span><span class="line"><span class="cl"> <span class="kt">var</span> <span class="n">preview</span> <span class="p">=</span> <span class="k">new</span> <span class="n">WebPreview</span><span class="p">(</span><span class="n">tbxUrl</span><span class="p">.</span><span class="n">Text</span><span class="p">);</span> </span></span><span class="line"><span class="cl"> <span class="n">lblTitle</span><span class="p">.</span><span class="n">Text</span> <span class="p">=</span> <span class="n">preview</span><span class="p">.</span><span class="n">Title</span><span class="p">;</span> </span></span><span class="line"><span class="cl"> <span class="n">lblUrl</span><span class="p">.</span><span class="n">Text</span> <span class="p">=</span> <span class="n">preview</span><span class="p">.</span><span class="n">URL</span><span class="p">;</span> </span></span><span class="line"><span class="cl"> <span class="n">lblDescription</span><span class="p">.</span><span class="n">Text</span> <span class="p">=</span> <span class="n">preview</span><span class="p">.</span><span class="n">Description</span><span class="p">;</span> </span></span><span class="line"><span class="cl"> </span></span><span class="line"><span class="cl"> <span class="n">m_Index</span> <span class="p">=</span> <span class="m">0</span><span class="p">;</span> </span></span><span class="line"><span class="cl"> <span class="n">m_ThumbnailURLs</span> <span class="p">=</span> <span class="n">preview</span><span class="p">.</span><span class="n">ThumbnailURLs</span><span class="p">.</span><span class="n">ToArray</span><span class="p">();</span> </span></span><span class="line"><span class="cl"> <span class="n">UpdateThumbnailIndexStatus</span><span class="p">();</span> </span></span><span class="line"><span class="cl"> </span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">m_ThumbnailURLs</span><span class="p">.</span><span class="n">Length</span> <span class="p">==</span> <span class="m">0</span><span class="p">)</span> </span></span><span class="line"><span class="cl"> <span class="k">return</span><span class="p">;</span> </span></span><span class="line"><span class="cl"> </span></span><span class="line"><span class="cl"> <span class="n">pbxThumbnail</span><span class="p">.</span><span class="n">ImageLocation</span> <span class="p">=</span> <span class="n">m_ThumbnailURLs</span><span class="p">[</span><span class="n">m_Index</span><span class="p">];</span> </span></span><span class="line"><span class="cl"> <span class="p">}</span> </span></span><span class="line"><span class="cl"> </span></span><span class="line"><span class="cl"> <span class="kd">private</span> <span class="k">void</span> <span class="n">btnNext_Click</span><span class="p">(</span><span class="kt">object</span> <span class="n">sender</span><span class="p">,</span> <span class="n">EventArgs</span> <span class="n">e</span><span class="p">)</span> </span></span><span class="line"><span class="cl"> <span class="p">{</span> </span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">m_Index</span> <span class="p">==</span> <span class="n">m_ThumbnailURLs</span><span class="p">.</span><span class="n">Length</span> <span class="p">-</span> <span class="m">1</span><span class="p">)</span> </span></span><span class="line"><span class="cl"> <span class="k">return</span><span class="p">;</span> </span></span><span class="line"><span class="cl"> <span class="n">m_Index</span> <span class="p">+=</span> <span class="m">1</span><span class="p">;</span> </span></span><span class="line"><span class="cl"> <span class="n">pbxThumbnail</span><span class="p">.</span><span class="n">ImageLocation</span> <span class="p">=</span> <span class="n">m_ThumbnailURLs</span><span class="p">[</span><span class="n">m_Index</span><span class="p">];</span> </span></span><span class="line"><span class="cl"> <span class="n">UpdateThumbnailIndexStatus</span><span class="p">();</span> </span></span><span class="line"><span class="cl"> <span class="p">}</span> </span></span><span class="line"><span class="cl"> </span></span><span class="line"><span class="cl"> <span class="kd">private</span> <span class="k">void</span> <span class="n">btnPrevious_Click</span><span class="p">(</span><span class="kt">object</span> <span class="n">sender</span><span class="p">,</span> <span class="n">EventArgs</span> <span class="n">e</span><span class="p">)</span> </span></span><span class="line"><span class="cl"> <span class="p">{</span> </span></span><span class="line"><span class="cl"> <span class="k">if</span> <span class="p">(</span><span class="n">m_Index</span> <span class="p">==</span> <span class="m">0</span><span class="p">)</span> </span></span><span class="line"><span class="cl"> <span class="k">return</span><span class="p">;</span> </span></span><span class="line"><span class="cl"> <span class="n">m_Index</span> <span class="p">-=</span> <span class="m">1</span><span class="p">;</span> </span></span><span class="line"><span class="cl"> <span class="n">pbxThumbnail</span><span class="p">.</span><span class="n">ImageLocation</span> <span class="p">=</span> <span class="n">m_ThumbnailURLs</span><span class="p">[</span><span class="n">m_Index</span><span class="p">];</span> </span></span><span class="line"><span class="cl"> <span class="n">UpdateThumbnailIndexStatus</span><span class="p">();</span> </span></span><span class="line"><span class="cl"> <span class="p">}</span> </span></span><span class="line"><span class="cl"> <span class="p">}</span> </span></span><span class="line"><span class="cl"><span class="p">}</span> </span></span></code></pre></div><p>運行的結果如下:</p> <p><img alt="[C#]How to Build a Facebook-like Web Preview" decoding="async" height="223" loading="lazy" src="/images/posts/ca63594b-5f89-4ee2-a87c-a7c50712dc45/image_thumb_2.png" width="468"></p> <p><img alt="[C#]How to Build a Facebook-like Web Preview" decoding="async" height="223" loading="lazy" src="/images/posts/ca63594b-5f89-4ee2-a87c-a7c50712dc45/image_thumb_3.png" width="468"></p> <h2 id="link">Link<a hidden class="anchor" aria-hidden="true" href="#link">#</a></h2> <ul> <li>Creating a Facebook Like Website Previewer</li> </ul> </div> <footer class="post-footer"> <ul class="post-tags"> <li><a href="http://larrynung.github.io/tags/csharp/">CSharp</a></li> </ul> </footer> <nav class="related-posts" aria-label="Related posts"> <h2 class="related-posts-title">相關文章</h2> <ul> <li><a href="/posts/eyedisposable-il-instrumenter-to-help-detect-idisposable-leaks-in-net-programs/">EyeDisposable - IL instrumenter to help detect IDisposable leaks in .NET programs</a></li> <li><a href="/posts/remote-desktop-with-microsoft-terminal-services-control/">Remote desktop with Microsoft Terminal Services control</a></li> <li><a href="/posts/dotnet-4-0-new-feature-code-contracts-part-1-concepts-and-introduction/">.NET 4.0 New Feature - Code Contracts (Part 1) Concepts and Introduction</a></li> <li><a href="/posts/dotnet-4-0-new-feature-code-contracts-part-5-interface-contracts-and-abstract-method-contracts/">.NET 4.0 New Feature - Code Contracts (Part 5) Interface Contracts and Abstract Method Contracts</a></li> <li><a href="/posts/4f45e11a-1310-411b-84fd-ed2efe4f66a8/">Alias Be Gone - A C# alias to .NET CLR type replacer extension</a></li> </ul> </nav> </article> </main> <footer class="footer"> <span>{year} Larry Nung</span> · <span> Powered by <a href="https://gohugo.io/" rel="noopener noreferrer" target="_blank">Hugo</a> & <a href="https://github.com/adityatelange/hugo-PaperMod/" rel="noopener" target="_blank">PaperMod</a> </span> </footer> <a href="#top" aria-label="go to top" title="Go to Top (Alt + G)" class="top-link" id="top-link" accesskey="g"> <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 12 6" fill="currentColor"> <path d="M12 6H0l6-6z" /> </svg> </a><script src="https://cdn.jsdelivr.net/npm/mermaid@10/dist/mermaid.min.js"></script> <script> mermaid.initialize({ startOnLoad: true }); </script> <script> let menu = document.getElementById('menu') if (menu) { menu.scrollLeft = localStorage.getItem("menu-scroll-position"); menu.onscroll = function () { localStorage.setItem("menu-scroll-position", menu.scrollLeft); } } document.querySelectorAll('a[href^="#"]').forEach(anchor => { anchor.addEventListener("click", function (e) { e.preventDefault(); var id = this.getAttribute("href").substr(1); if (!window.matchMedia('(prefers-reduced-motion: reduce)').matches) { document.querySelector(`[id='${decodeURIComponent(id)}']`).scrollIntoView({ behavior: "smooth" }); } else { document.querySelector(`[id='${decodeURIComponent(id)}']`).scrollIntoView(); } if (id === "top") { history.replaceState(null, null, " "); } else { history.pushState(null, null, `#${id}`); } }); }); </script> <script> var mybutton = document.getElementById("top-link"); window.onscroll = function () { if (document.body.scrollTop > 800 || document.documentElement.scrollTop > 800) { mybutton.style.visibility = "visible"; mybutton.style.opacity = "1"; } else { mybutton.style.visibility = "hidden"; mybutton.style.opacity = "0"; } }; </script> <script> document.getElementById("theme-toggle").addEventListener("click", () => { if (document.body.className.includes("dark")) { document.body.classList.remove('dark'); localStorage.setItem("pref-theme", 'light'); } else { document.body.classList.add('dark'); localStorage.setItem("pref-theme", 'dark'); } }) </script> </body> </html>