<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-4754237190569973724</id><updated>2012-01-18T16:08:02.115+08:00</updated><category term='Skin'/><category term='Python'/><category term='ApplicationDomain'/><category term='Decompiler'/><category term='Game'/><category term='Flash Remoting'/><category term='mask'/><category term='DataGrid'/><category term='CI'/><category term='ByteArray'/><category term='plug-in | add-on | wrapper'/><category term='Unity3D'/><category term='Security'/><category term='EveryDNS'/><category term='Flash'/><category term='flash.text.engine'/><category term='Flash Player'/><category term='FlexUnit'/><category term='SWC'/><category term='Flex Builder'/><category term='swf format'/><category term='Google API'/><category term='Hudson'/><category term='Flex'/><category term='BitmapData'/><category term='Obfuscate'/><category term='Video'/><category term='Flash CS4'/><category term='CSS'/><category term='Pixel Bender'/><category term='Office'/><category term='Webcam'/><category term='AS3'/><category term='Server'/><category term='Local Connection'/><category term='AS3DMod'/><category term='Adobe AIR'/><category term='XML'/><category term='YouTube'/><category term='FlexMonkey'/><category term='Java'/><category term='Away3D'/><category term='PV3D'/><category term='Google App Engine'/><category term='JSFL'/><category term='Browser'/><category term='pureMVC'/><category term='DB'/><category term='Data Binding'/><category term='Class Loader'/><category term='PageFlip'/><category term='徵才'/><category term='Ant'/><category term='Robotleg'/><category term='.NET'/><category term='Books'/><title type='text'>邦邦的部落格</title><subtitle type='html'></subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://blog.ben.idv.tw/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4754237190569973724/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://blog.ben.idv.tw/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><link rel='next' type='application/atom+xml' href='http://www.blogger.com/feeds/4754237190569973724/posts/default?start-index=101&amp;max-results=100'/><author><name>Ben Chang</name><uri>http://www.blogger.com/profile/01921640246111819069</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>180</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-4754237190569973724.post-6047236736031154243</id><published>2012-01-04T18:35:00.001+08:00</published><updated>2012-01-04T18:35:39.505+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='JSFL'/><category scheme='http://www.blogger.com/atom/ns#' term='AS3'/><category scheme='http://www.blogger.com/atom/ns#' term='Flash'/><title type='text'>Flash 匯出連續 PNG 圖檔</title><content type='html'>需要將 MovieClip 的影格，以連續圖檔的方式匯出使用，懶得自己寫 JSFL，找了幾篇文章：&lt;br /&gt;&lt;br /&gt;Batch image exporting from .fla&lt;br /&gt;http://journal.reallyenglish.com/2010/01/30/batch-image-exporting-from-fla.html&lt;br /&gt;&lt;br /&gt;JSFL for Exporting Layers as Individual PNGs&lt;br /&gt;http://summitprojectsflashblog.wordpress.com/2008/11/03/jsfl-for-exporting-layers-as-individual-pngs/&lt;br /&gt;&lt;br /&gt;Export Flash library items as PNG’s with JSFL&lt;br /&gt;http://abitofcode.com/2011/11/export-flash-library-items-as-pngs-with-jsfl/&lt;br /&gt;&lt;br /&gt;最後組出以下程式，&lt;br /&gt;將主時間軸上，每個 layer 的每個 frame 都會獨自輸出一張 png 圖檔，輸出檔名是由 layer.name 與 frame 組合而成。&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush:as3"&gt;var doc = fl.getDocumentDOM();&lt;br /&gt;var lyrs = doc.getTimeline().layers;&lt;br /&gt;&lt;br /&gt;var len = lyrs.length;&lt;br /&gt;var lyr;&lt;br /&gt;var originalType;&lt;br /&gt;var i;&lt;br /&gt;&lt;br /&gt;// Get a save location.&lt;br /&gt;var saveDir = fl.browseForFolderURL("Choose a folder in which to save your exported PNGs:");&lt;br /&gt;if (saveDir) {&lt;br /&gt; // Get the Flash document's name, and strip off the final ".fla", and build a base name for the exported files.&lt;br /&gt; fl.outputPanel.clear();&lt;br /&gt; var docName = doc.name;&lt;br /&gt; var extensionIndex = docName.lastIndexOf(".fla");&lt;br /&gt; if (extensionIndex == docName.length - 4) {&lt;br /&gt;  docName = docName.substring(0, extensionIndex);&lt;br /&gt; }&lt;br /&gt; &lt;br /&gt; // Acceptable values are "normal", "guide", "guided", "mask", "masked", and "folder".&lt;br /&gt; var originalTypes = new Array();&lt;br /&gt;&lt;br /&gt; // Grab all original layer types.  Need to do this before setting to guide, because otherwise a mask layer turned&lt;br /&gt; // to guide would would turn a masked layer into a normal layer.&lt;br /&gt; for (i=0; i &amp;lt; len; i++) {&lt;br /&gt;  lyr = lyrs[i];&lt;br /&gt;  originalTypes[i] = lyr.layerType;&lt;br /&gt; };&lt;br /&gt;&lt;br /&gt; // Guide all layers.&lt;br /&gt; for (i=0; i &amp;lt; len; i++) {&lt;br /&gt;  lyr = lyrs[i];&lt;br /&gt;  lyr.layerType = "guide";&lt;br /&gt;  lyr.visible = false;&lt;br /&gt; };&lt;br /&gt;&lt;br /&gt; var tl = doc.getTimeline();&lt;br /&gt; var frameCount = tl.frameCount;&lt;br /&gt;&lt;br /&gt; // Save layers that were originally "normal" as PNGs, one-by-one.&lt;br /&gt; for (i=0; i &amp;lt; len; i++) {&lt;br /&gt;  lyr = lyrs[i];&lt;br /&gt;  originalType = originalTypes[i]&lt;br /&gt;  if (originalType == "normal" || originalType == "guided") {&lt;br /&gt;   lyr.layerType = "normal";&lt;br /&gt;   lyr.visible = true;&lt;br /&gt;   for(var k=0; k&amp;lt;frameCount; k++){&lt;br /&gt;    tl.currentFrame = k;&lt;br /&gt;    exportPng(lyr.name + "_" + k);&lt;br /&gt;   }&lt;br /&gt;   lyr.layerType = "guide";&lt;br /&gt;   lyr.visible = false;&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  // In this case, we need to loop backwards until we find the mask layer, then re-mask this layer, before we export.&lt;br /&gt;  if (originalType == "masked") {&lt;br /&gt;   for (var j=i; j &amp;gt;= 0; j--) {&lt;br /&gt;    if (originalTypes[j] == "mask") {&lt;br /&gt;     var maskLyrSearch = lyrs[j];&lt;br /&gt;     maskLyrSearch.layerType = "mask";&lt;br /&gt;     lyr.layerType = "masked";&lt;br /&gt;     maskLyrSearch.visible = true;&lt;br /&gt;     lyr.visible = true;&lt;br /&gt;     for(var k=0; k&amp;lt;frameCount; k++){&lt;br /&gt;      tl.currentFrame = k;&lt;br /&gt;      exportPng(lyr.name + "_" + k);&lt;br /&gt;     }&lt;br /&gt;     maskLyrSearch.layerType = "guide";&lt;br /&gt;     lyr.layerType = "guide";&lt;br /&gt;     maskLyrSearch.visible = false;&lt;br /&gt;     lyr.visible = false;&lt;br /&gt;     break;&lt;br /&gt;    }&lt;br /&gt;   };&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt; };&lt;br /&gt;&lt;br /&gt; // Reset all layers to their original types.&lt;br /&gt; for (i=0; i &amp;lt; len; i++) {&lt;br /&gt;  lyr = lyrs[i];&lt;br /&gt;  lyr.layerType = originalTypes[i];&lt;br /&gt;  lyr.visible = true;&lt;br /&gt; };&lt;br /&gt;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;function exportPng(fn) {&lt;br /&gt; var pngName = saveDir + "/" + fn + ".png";&lt;br /&gt; doc.exportPNG(pngName, true, true);&lt;br /&gt; fl.trace("Exported: " + pngName);&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4754237190569973724-6047236736031154243?l=blog.ben.idv.tw' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.ben.idv.tw/feeds/6047236736031154243/comments/default' title='張貼意見'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4754237190569973724&amp;postID=6047236736031154243' title='1 個意見'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4754237190569973724/posts/default/6047236736031154243'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4754237190569973724/posts/default/6047236736031154243'/><link rel='alternate' type='text/html' href='http://blog.ben.idv.tw/2012/01/flash-png.html' title='Flash 匯出連續 PNG 圖檔'/><author><name>Ben Chang</name><uri>http://www.blogger.com/profile/01921640246111819069</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4754237190569973724.post-4013049006601937733</id><published>2011-11-29T13:58:00.001+08:00</published><updated>2011-11-29T14:47:50.078+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Unity3D'/><title type='text'>初探 Unity3D</title><content type='html'>最近開始看 Unity3D，原因：&lt;br&gt;&lt;br&gt;&lt;ul&gt;&lt;li&gt;未來的藍圖中，預計會支援可輸出 Flash&lt;/li&gt;&lt;li&gt;開發工具，免費，除非你要用到 Pro 級功能，版本比較：&lt;a href="http://unity3d.com/unity/licenses.html" target="_blank"&gt;http://unity3d.com/unity/licenses.html&lt;/a&gt;&lt;/li&gt;&lt;li&gt;有了視覺化開發工具，至少調整物體座標、貼圖、增加粒子引擎、設定物理碰撞...都可以輕易的達成&lt;/li&gt;&lt;li&gt;若要自己寫 Script，它支援 JavaScript、C#、Boo Script，雖然第三種聽都沒聽過，不過能 google 到的範例大多以 JS 寫成，上手不難&lt;/li&gt;&lt;li&gt;若有天想發佈到 iOS / Android 平台&lt;/li&gt;&lt;li&gt;Web Player 很小，就算未來對 Flash 輸出的支援程度有限制，也可考慮直接輸出 Unity3D 自己的版本，安裝 plug-in 時不用重新啟動瀏覽器，無痛&lt;/li&gt;&lt;/ul&gt;&lt;br&gt;&lt;a href="http://blog.ben.idv.tw/2011/11/unity3d.html#more"&gt;閱讀更多 »&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4754237190569973724-4013049006601937733?l=blog.ben.idv.tw' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.ben.idv.tw/feeds/4013049006601937733/comments/default' title='張貼意見'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4754237190569973724&amp;postID=4013049006601937733' title='0 個意見'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4754237190569973724/posts/default/4013049006601937733'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4754237190569973724/posts/default/4013049006601937733'/><link rel='alternate' type='text/html' href='http://blog.ben.idv.tw/2011/11/unity3d.html' title='初探 Unity3D'/><author><name>Ben Chang</name><uri>http://www.blogger.com/profile/01921640246111819069</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/-Z1Si1PIpaes/TtR9Fr3EpKI/AAAAAAAANj8/fR0qOU1dN8U/s72-c/Clipboard01.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4754237190569973724.post-3560436849704491562</id><published>2011-11-14T18:10:00.000+08:00</published><updated>2011-11-14T18:10:39.912+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Server'/><category scheme='http://www.blogger.com/atom/ns#' term='Security'/><category scheme='http://www.blogger.com/atom/ns#' term='AS3'/><title type='text'>使用 SecureSocket 連接 Socket Server - Part 2</title><content type='html'>繼上一篇 &lt;a target="_blank" href="http://blog.ben.idv.tw/2011/11/securesocket-socket-server.html"&gt;使用 SecureSocket 連接 Socket Server&lt;/a&gt; 後，實際放到網路環境測試時，這才發現到，透過 SecureSocket 向 Socket Server 索取 policy file 時，也會經過編碼，所以 Socket Server 必須做些調整以支援此機制。&lt;br&gt;&lt;a href="http://blog.ben.idv.tw/2011/11/securesocket-socket-server-part-2.html#more"&gt;閱讀更多 »&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4754237190569973724-3560436849704491562?l=blog.ben.idv.tw' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.ben.idv.tw/feeds/3560436849704491562/comments/default' title='張貼意見'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4754237190569973724&amp;postID=3560436849704491562' title='0 個意見'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4754237190569973724/posts/default/3560436849704491562'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4754237190569973724/posts/default/3560436849704491562'/><link rel='alternate' type='text/html' href='http://blog.ben.idv.tw/2011/11/securesocket-socket-server-part-2.html' title='使用 SecureSocket 連接 Socket Server - Part 2'/><author><name>Ben Chang</name><uri>http://www.blogger.com/profile/01921640246111819069</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/-HpuYOc8ht30/TsDnGVEVgzI/AAAAAAAANiY/F212STaBGGE/s72-c/Clipboard01.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4754237190569973724.post-6616444124845518964</id><published>2011-11-03T15:41:00.003+08:00</published><updated>2011-11-03T16:06:38.836+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Server'/><category scheme='http://www.blogger.com/atom/ns#' term='Webcam'/><category scheme='http://www.blogger.com/atom/ns#' term='Video'/><title type='text'>FMS Stream live media over HTTP</title><content type='html'>這兩天在研究 FMS 4.5，透過 HTTP 看 live stream 的作法。&lt;br&gt;&lt;a href="http://blog.ben.idv.tw/2011/11/fms-stream-live-media-over-http.html#more"&gt;閱讀更多 »&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4754237190569973724-6616444124845518964?l=blog.ben.idv.tw' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.ben.idv.tw/feeds/6616444124845518964/comments/default' title='張貼意見'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4754237190569973724&amp;postID=6616444124845518964' title='4 個意見'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4754237190569973724/posts/default/6616444124845518964'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4754237190569973724/posts/default/6616444124845518964'/><link rel='alternate' type='text/html' href='http://blog.ben.idv.tw/2011/11/fms-stream-live-media-over-http.html' title='FMS Stream live media over HTTP'/><author><name>Ben Chang</name><uri>http://www.blogger.com/profile/01921640246111819069</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/-thEiKMoxDPI/TrIx3fV32_I/AAAAAAAANg4/tZvX8L3GWNY/s72-c/Clipboard01.png' height='72' width='72'/><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4754237190569973724.post-6860122038939753356</id><published>2011-11-01T15:15:00.001+08:00</published><updated>2011-11-01T15:15:45.326+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Server'/><category scheme='http://www.blogger.com/atom/ns#' term='Security'/><category scheme='http://www.blogger.com/atom/ns#' term='AS3'/><title type='text'>使用 SecureSocket 連接 Socket Server</title><content type='html'>繼上一篇 &lt;a href="http://blog.ben.idv.tw/2011/10/securesocket-https.html"&gt;使用 SecureSocket 連接 HTTPS &lt;/a&gt; 後，接下來要測試的是連接 SSL Socket Server。&lt;br&gt;&lt;a href="http://blog.ben.idv.tw/2011/11/securesocket-socket-server.html#more"&gt;閱讀更多 »&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4754237190569973724-6860122038939753356?l=blog.ben.idv.tw' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.ben.idv.tw/feeds/6860122038939753356/comments/default' title='張貼意見'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4754237190569973724&amp;postID=6860122038939753356' title='3 個意見'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4754237190569973724/posts/default/6860122038939753356'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4754237190569973724/posts/default/6860122038939753356'/><link rel='alternate' type='text/html' href='http://blog.ben.idv.tw/2011/11/securesocket-socket-server.html' title='使用 SecureSocket 連接 Socket Server'/><author><name>Ben Chang</name><uri>http://www.blogger.com/profile/01921640246111819069</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/-wcdEtjZGXEM/Tq-P1w7ywpI/AAAAAAAANeo/dsedEYx6rqM/s72-c/Clipboard01.png' height='72' width='72'/><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4754237190569973724.post-5478914701102107745</id><published>2011-10-31T14:43:00.000+08:00</published><updated>2011-10-31T14:43:31.460+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Server'/><category scheme='http://www.blogger.com/atom/ns#' term='Security'/><category scheme='http://www.blogger.com/atom/ns#' term='AS3'/><title type='text'>使用 SecureSocket 連接 HTTPS</title><content type='html'>為了研究 FP11 的 SecureSocket 功能，作了以下的測試。&lt;br&gt;&lt;a href="http://blog.ben.idv.tw/2011/10/securesocket-https.html#more"&gt;閱讀更多 »&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4754237190569973724-5478914701102107745?l=blog.ben.idv.tw' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.ben.idv.tw/feeds/5478914701102107745/comments/default' title='張貼意見'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4754237190569973724&amp;postID=5478914701102107745' title='1 個意見'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4754237190569973724/posts/default/5478914701102107745'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4754237190569973724/posts/default/5478914701102107745'/><link rel='alternate' type='text/html' href='http://blog.ben.idv.tw/2011/10/securesocket-https.html' title='使用 SecureSocket 連接 HTTPS'/><author><name>Ben Chang</name><uri>http://www.blogger.com/profile/01921640246111819069</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/-FwRF41_tmGM/Tq488EbpUdI/AAAAAAAANd4/5xN-n4u-LUE/s72-c/Clipboard01.png' height='72' width='72'/><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4754237190569973724.post-1243337865187368854</id><published>2011-10-28T12:52:00.000+08:00</published><updated>2011-10-28T12:52:50.254+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Server'/><category scheme='http://www.blogger.com/atom/ns#' term='Robotleg'/><category scheme='http://www.blogger.com/atom/ns#' term='Adobe AIR'/><title type='text'>使用 Adobe AIR 2 開發 Socket Server 應用</title><content type='html'>曾有一個機會，去參觀了某科大的畢展，看到學生使用 Flash 作多人連線遊戲時，使用的技術仍是透過 web server 來廣播訊息，然而 http 是 stateless，並不是真正的即時廣播，而是需要仰賴每個 flash client &amp;quot;定期&amp;quot; 向 web server 撈更新的資料來呈現。&lt;br&gt;&lt;br&gt;這類的應用通常 server 端都是以 socket server 實作，你可以找 open source 的 java server，或是 Adobe Flash Media Server (FMS) 皆可，然後就可以自己撰寫 server 端的商業邏輯、遊戲引擎。然而若是你不想多學一套程式語言 (通常是 Java 或 .NET)，只想使用 ActionScript 的話，而 FMS 的 Server 開發使用 AS2 又令你覺得很不習慣的話，可以嘗試使用 Adobe AIR 2 自己寫一個 socket server。&lt;br&gt;&lt;a href="http://blog.ben.idv.tw/2011/10/adobe-air-2-socket-server.html#more"&gt;閱讀更多 »&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4754237190569973724-1243337865187368854?l=blog.ben.idv.tw' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.ben.idv.tw/feeds/1243337865187368854/comments/default' title='張貼意見'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4754237190569973724&amp;postID=1243337865187368854' title='0 個意見'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4754237190569973724/posts/default/1243337865187368854'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4754237190569973724/posts/default/1243337865187368854'/><link rel='alternate' type='text/html' href='http://blog.ben.idv.tw/2011/10/adobe-air-2-socket-server.html' title='使用 Adobe AIR 2 開發 Socket Server 應用'/><author><name>Ben Chang</name><uri>http://www.blogger.com/profile/01921640246111819069</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/-ozKOsgRha8A/Tqo0TgcYaZI/AAAAAAAANds/PVm2e1DkO-M/s72-c/Clipboard01.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4754237190569973724.post-5489122003938618307</id><published>2011-10-21T07:28:00.002+08:00</published><updated>2011-10-21T07:31:55.771+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Flex Builder'/><category scheme='http://www.blogger.com/atom/ns#' term='Flash'/><title type='text'>Flash 相關工具的開發流程</title><content type='html'>提一下 Flash 相關的開發工具與搭配方式。&lt;br&gt;&lt;a href="http://blog.ben.idv.tw/2011/10/flash-relate-tools-and-workflow.html#more"&gt;閱讀更多 »&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4754237190569973724-5489122003938618307?l=blog.ben.idv.tw' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.ben.idv.tw/feeds/5489122003938618307/comments/default' title='張貼意見'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4754237190569973724&amp;postID=5489122003938618307' title='0 個意見'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4754237190569973724/posts/default/5489122003938618307'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4754237190569973724/posts/default/5489122003938618307'/><link rel='alternate' type='text/html' href='http://blog.ben.idv.tw/2011/10/flash-relate-tools-and-workflow.html' title='Flash 相關工具的開發流程'/><author><name>Ben Chang</name><uri>http://www.blogger.com/profile/01921640246111819069</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4754237190569973724.post-1767998152023520895</id><published>2011-10-19T20:34:00.001+08:00</published><updated>2011-10-19T20:34:32.438+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Robotleg'/><category scheme='http://www.blogger.com/atom/ns#' term='AS3'/><title type='text'>初探 Robotlegs</title><content type='html'>最近看了一下 robotlegs 的電子書，有興趣學習這項 framework 的人可以參考官網的資源：&lt;br&gt;&lt;a href="http://www.robotlegs.org/"&gt;http://www.robotlegs.org/&lt;/a&gt;&lt;br&gt;&lt;br&gt;或以下這本電子書：&lt;br&gt;&lt;a href="http://www.wowebook.pro/book/actionscript-developers-guide-to-robotlegs/"&gt;http://www.wowebook.pro/book/actionscript-developers-guide-to-robotlegs/&lt;/a&gt;&lt;br&gt;&lt;br&gt;&lt;a href="http://blog.ben.idv.tw/2011/10/robotlegs.html#more"&gt;閱讀更多 »&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4754237190569973724-1767998152023520895?l=blog.ben.idv.tw' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.ben.idv.tw/feeds/1767998152023520895/comments/default' title='張貼意見'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4754237190569973724&amp;postID=1767998152023520895' title='0 個意見'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4754237190569973724/posts/default/1767998152023520895'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4754237190569973724/posts/default/1767998152023520895'/><link rel='alternate' type='text/html' href='http://blog.ben.idv.tw/2011/10/robotlegs.html' title='初探 Robotlegs'/><author><name>Ben Chang</name><uri>http://www.blogger.com/profile/01921640246111819069</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/--KN2lNQBl8c/Tp7C-oS3h_I/AAAAAAAANc0/5vAgDEraoW4/s72-c/Clipboard01.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4754237190569973724.post-3141051882096485392</id><published>2011-10-14T01:48:00.002+08:00</published><updated>2011-10-14T02:12:11.233+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Local Connection'/><category scheme='http://www.blogger.com/atom/ns#' term='AS3'/><title type='text'>動態切換負責廣播的 Local Connection 角色，避免受到 FPS 降低的影響</title><content type='html'>前年底，曾寫了這麼一篇文章：&lt;br&gt;&lt;br&gt;&lt;a href="http://blog.ben.idv.tw/2009/12/local-connection.html"&gt;多 Local Connection 彼此維護名單的機制&lt;/a&gt; &lt;br&gt;&lt;br&gt;當時的想法是，在 &amp;quot;一個遊戲大廳&amp;quot; 負責廣播訊息給 &amp;quot;多個遊戲桌&amp;quot; 的系統中，嘗試做到每個遊戲桌都可以成為替代遊戲大廳負責廣播的角色，使得遊戲大廳不必要存在。&lt;br&gt;&lt;br&gt;然而，實務上，遊戲大廳 通常不會只具有廣播、控管中心...的角色，有可能在視覺上仍提供其他功能給玩家，譬如遊戲列表、會員帳戶管理、其它服務...，所以沒有 &amp;quot;移除遊戲大廳&amp;quot; 的需要。&lt;br&gt;&lt;br&gt;而，這兩天我正在思考一個新的 &amp;quot;策略&amp;quot;，不再考慮沒有 遊戲大廳 的情況，但可以考慮 &amp;quot;主訊息廣播者&amp;quot; 這個角色是否可以被變更？！&lt;br&gt;&lt;br&gt;&lt;a href="http://blog.ben.idv.tw/2011/10/local-connection-fps.html#more"&gt;閱讀更多 »&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4754237190569973724-3141051882096485392?l=blog.ben.idv.tw' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.ben.idv.tw/feeds/3141051882096485392/comments/default' title='張貼意見'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4754237190569973724&amp;postID=3141051882096485392' title='0 個意見'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4754237190569973724/posts/default/3141051882096485392'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4754237190569973724/posts/default/3141051882096485392'/><link rel='alternate' type='text/html' href='http://blog.ben.idv.tw/2011/10/local-connection-fps.html' title='動態切換負責廣播的 Local Connection 角色，避免受到 FPS 降低的影響'/><author><name>Ben Chang</name><uri>http://www.blogger.com/profile/01921640246111819069</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4754237190569973724.post-8029203986860078456</id><published>2011-10-05T18:17:00.001+08:00</published><updated>2011-10-05T18:19:49.313+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Obfuscate'/><category scheme='http://www.blogger.com/atom/ns#' term='Security'/><category scheme='http://www.blogger.com/atom/ns#' term='AS3'/><title type='text'>使用 embed text 保護敏感字串</title><content type='html'>若有段敏感字串，不希望當 swf 被反組譯之後被看到，可透過 embed text 的作法將之編為 ByteArray，就不是明碼了，可增加被破解的困難度。&lt;br&gt;&lt;br&gt;&lt;a href="http://blog.ben.idv.tw/2011/10/ember-text.html#more"&gt;閱讀更多 »&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4754237190569973724-8029203986860078456?l=blog.ben.idv.tw' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.ben.idv.tw/feeds/8029203986860078456/comments/default' title='張貼意見'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4754237190569973724&amp;postID=8029203986860078456' title='0 個意見'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4754237190569973724/posts/default/8029203986860078456'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4754237190569973724/posts/default/8029203986860078456'/><link rel='alternate' type='text/html' href='http://blog.ben.idv.tw/2011/10/ember-text.html' title='使用 embed text 保護敏感字串'/><author><name>Ben Chang</name><uri>http://www.blogger.com/profile/01921640246111819069</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4754237190569973724.post-697833735368758436</id><published>2011-10-03T17:59:00.000+08:00</published><updated>2011-10-03T17:59:18.168+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Obfuscate'/><category scheme='http://www.blogger.com/atom/ns#' term='AS3'/><title type='text'>Obfuscate 兩個主從 SWF 後如何使用 Singleton</title><content type='html'>基本上，這篇只是上一篇的延伸，最後一樣是透過 metadata 去尋找指定 method name。只不過這篇的情況又更複雜一點，當 main.swf 與 external.swf 欲使用同一個 class 的 singleton 物件時，該如何達到。&lt;br&gt;&lt;br&gt;&lt;a href="http://blog.ben.idv.tw/2011/10/obfuscate-swf-singleton.html#more"&gt;閱讀更多 »&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4754237190569973724-697833735368758436?l=blog.ben.idv.tw' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.ben.idv.tw/feeds/697833735368758436/comments/default' title='張貼意見'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4754237190569973724&amp;postID=697833735368758436' title='0 個意見'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4754237190569973724/posts/default/697833735368758436'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4754237190569973724/posts/default/697833735368758436'/><link rel='alternate' type='text/html' href='http://blog.ben.idv.tw/2011/10/obfuscate-swf-singleton.html' title='Obfuscate 兩個主從 SWF 後如何使用 Singleton'/><author><name>Ben Chang</name><uri>http://www.blogger.com/profile/01921640246111819069</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4754237190569973724.post-5199699232335275682</id><published>2011-09-28T08:43:00.002+08:00</published><updated>2011-09-30T11:29:48.672+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Obfuscate'/><category scheme='http://www.blogger.com/atom/ns#' term='AS3'/><title type='text'>Obfuscate 兩個主從 SWF 後，如何仍能正確執行 method</title><content type='html'>在 PTT 看到一些人問起，Main.swf 載入 External.swf 後，如何呼叫 External.swf 提供的 method；或是載入之後，如何使用 External.swf 中所包含的 Class 建立物件，並且呼叫該物件所提供的 method。&lt;br&gt;&lt;br&gt;&lt;a href="http://blog.ben.idv.tw/2011/09/obfuscate-swf-method.html#more"&gt;閱讀更多 »&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4754237190569973724-5199699232335275682?l=blog.ben.idv.tw' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.ben.idv.tw/feeds/5199699232335275682/comments/default' title='張貼意見'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4754237190569973724&amp;postID=5199699232335275682' title='0 個意見'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4754237190569973724/posts/default/5199699232335275682'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4754237190569973724/posts/default/5199699232335275682'/><link rel='alternate' type='text/html' href='http://blog.ben.idv.tw/2011/09/obfuscate-swf-method.html' title='Obfuscate 兩個主從 SWF 後，如何仍能正確執行 method'/><author><name>Ben Chang</name><uri>http://www.blogger.com/profile/01921640246111819069</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4754237190569973724.post-5141352562156310735</id><published>2011-09-23T11:34:00.000+08:00</published><updated>2011-09-23T11:34:24.292+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Ant'/><category scheme='http://www.blogger.com/atom/ns#' term='Java'/><category scheme='http://www.blogger.com/atom/ns#' term='Flex Builder'/><title type='text'>Flash Builder 4 使用 Ant 遇到 JRE heap memory 不足的處理方法</title><content type='html'>若使用 Flash Builder 4.x 整合 Ant 工具，使用 flexTasks.jar 提供的 task 要編譯 Flex / AS 專案時，遇到記憶體不足的情況，只要提供 JVM 多一點 heap memory 即可。&lt;br&gt;&lt;br&gt;&lt;a href="http://blog.ben.idv.tw/2011/09/flash-builder-4-ant-jre-heap-memory.html#more"&gt;閱讀更多 »&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4754237190569973724-5141352562156310735?l=blog.ben.idv.tw' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.ben.idv.tw/feeds/5141352562156310735/comments/default' title='張貼意見'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4754237190569973724&amp;postID=5141352562156310735' title='0 個意見'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4754237190569973724/posts/default/5141352562156310735'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4754237190569973724/posts/default/5141352562156310735'/><link rel='alternate' type='text/html' href='http://blog.ben.idv.tw/2011/09/flash-builder-4-ant-jre-heap-memory.html' title='Flash Builder 4 使用 Ant 遇到 JRE heap memory 不足的處理方法'/><author><name>Ben Chang</name><uri>http://www.blogger.com/profile/01921640246111819069</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/-v7sJTa0zk-g/Tnv8o21JXhI/AAAAAAAANcc/nn-ADnZlB8Y/s72-c/Clipboard01.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4754237190569973724.post-3996097219890578222</id><published>2011-09-15T07:54:00.002+08:00</published><updated>2011-09-30T11:42:40.079+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Obfuscate'/><category scheme='http://www.blogger.com/atom/ns#' term='Robotleg'/><category scheme='http://www.blogger.com/atom/ns#' term='AS3'/><title type='text'>Robotleg 與 Obfuscator</title><content type='html'>在 ActionScript Developer&amp;#39;s Guide to Robotlegs 書中，看到一段話，Robotleg 中只要求 Custom Command 具有 execute() 方法，除非為了便利性才需要繼承自 Robotleg 的 Command 類別，Robotleg 會透過映射去執行 execute() 方法。這件事情讓我小小擔心是否 &amp;quot;SWF 混淆&amp;quot; 會造成影響。&lt;br&gt;&lt;br&gt;&lt;a href="http://blog.ben.idv.tw/2011/09/robotleg-obfuscator.html#more"&gt;閱讀更多 »&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4754237190569973724-3996097219890578222?l=blog.ben.idv.tw' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.ben.idv.tw/feeds/3996097219890578222/comments/default' title='張貼意見'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4754237190569973724&amp;postID=3996097219890578222' title='0 個意見'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4754237190569973724/posts/default/3996097219890578222'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4754237190569973724/posts/default/3996097219890578222'/><link rel='alternate' type='text/html' href='http://blog.ben.idv.tw/2011/09/robotleg-obfuscator.html' title='Robotleg 與 Obfuscator'/><author><name>Ben Chang</name><uri>http://www.blogger.com/profile/01921640246111819069</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/-qosxwyAimhU/TnE5aeQxkdI/AAAAAAAANbs/CC99WkNLbWM/s72-c/Clipboard01.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4754237190569973724.post-2026867906842538535</id><published>2011-08-08T02:10:00.004+08:00</published><updated>2011-09-30T11:49:34.419+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='CI'/><category scheme='http://www.blogger.com/atom/ns#' term='Ant'/><category scheme='http://www.blogger.com/atom/ns#' term='FlexUnit'/><category scheme='http://www.blogger.com/atom/ns#' term='Flex Builder'/><category scheme='http://www.blogger.com/atom/ns#' term='Hudson'/><category scheme='http://www.blogger.com/atom/ns#' term='Flex'/><category scheme='http://www.blogger.com/atom/ns#' term='Flash'/><category scheme='http://www.blogger.com/atom/ns#' term='FlexMonkey'/><title type='text'>FlexMonkey 與 Hudson 整合進行 UI 測試</title><content type='html'>這是一個複雜的演練，花了約四個小時的嘗試，得到的結果卻還有一些問題，總之先介紹今晚的過程。&lt;br&gt;&lt;br&gt;FlexMonkey 我不多作介紹，它定位在為 Flex App 或 AIR App 進行 UI 測試，可進行自動化測試，觀念是先將 UI 操作錄製下來，FlexMonkey 可將一系列的動作轉成 FlexUnit AS3 code，然後就可以被 Ant 執行測試了。&lt;a href="http://blog.ben.idv.tw/2011/08/flexmonkey-hudson-ui.html#more"&gt;閱讀更多 »&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4754237190569973724-2026867906842538535?l=blog.ben.idv.tw' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.ben.idv.tw/feeds/2026867906842538535/comments/default' title='張貼意見'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4754237190569973724&amp;postID=2026867906842538535' title='0 個意見'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4754237190569973724/posts/default/2026867906842538535'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4754237190569973724/posts/default/2026867906842538535'/><link rel='alternate' type='text/html' href='http://blog.ben.idv.tw/2011/08/flexmonkey-hudson-ui.html' title='FlexMonkey 與 Hudson 整合進行 UI 測試'/><author><name>Ben Chang</name><uri>http://www.blogger.com/profile/01921640246111819069</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/-AcBhFLGUz64/Tj7RgyVvDWI/AAAAAAAANao/Sr4qdoou3NQ/s72-c/Clipboard01.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4754237190569973724.post-6347046125686216750</id><published>2011-08-05T01:29:00.001+08:00</published><updated>2011-09-30T11:50:33.824+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='CI'/><category scheme='http://www.blogger.com/atom/ns#' term='Ant'/><category scheme='http://www.blogger.com/atom/ns#' term='Flex Builder'/><category scheme='http://www.blogger.com/atom/ns#' term='Hudson'/><category scheme='http://www.blogger.com/atom/ns#' term='Flex'/><category scheme='http://www.blogger.com/atom/ns#' term='Flash'/><title type='text'>Hudson 建置多專案</title><content type='html'>遇到切專案、或是共用 Library 的情況，自動建置就必須由 SCM 下載多份專案後，才依照順序或依賴關係先後 build code，若是某人改壞了共用元件庫的程式，這時候就會使得其他人的專案建置失敗，CI-Server 便可以於 Daily Build 發現這個問題並通知相關 RD，隔天早上負責人便可第一時間解決，而非等其他專案負責人下次從 SCM update 共用元件庫的 code 時，才發現自己專案無法編譯。&lt;br&gt;&lt;br&gt;&lt;a href="http://blog.ben.idv.tw/2011/08/hudson.html#more"&gt;閱讀更多 »&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4754237190569973724-6347046125686216750?l=blog.ben.idv.tw' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.ben.idv.tw/feeds/6347046125686216750/comments/default' title='張貼意見'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4754237190569973724&amp;postID=6347046125686216750' title='0 個意見'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4754237190569973724/posts/default/6347046125686216750'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4754237190569973724/posts/default/6347046125686216750'/><link rel='alternate' type='text/html' href='http://blog.ben.idv.tw/2011/08/hudson.html' title='Hudson 建置多專案'/><author><name>Ben Chang</name><uri>http://www.blogger.com/profile/01921640246111819069</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/-MXK1Srp9bAg/TjrQUZSTGxI/AAAAAAAANZ4/gRECDmK-Fec/s72-c/Clipboard01.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4754237190569973724.post-3964237665366912675</id><published>2011-08-02T15:32:00.002+08:00</published><updated>2012-01-03T15:53:56.456+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='徵才'/><title type='text'>徵才</title><content type='html'>&lt;a href="http://www.104.com.tw/jobbank/cust_job/job.cfm?j=524049743e4c455c373840693e443d231646648724e624427272727233f312c2b826j50"&gt;Flash Programmer&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;1. 兩年以上 Flash Game 經驗&lt;br /&gt;2. 熟悉 ActionScript3 語法、物件導向&lt;br /&gt;3. 熟悉 時間軸觀念，能與設計師討論與程式有關的動畫架構&lt;br /&gt;4. 略懂 Flash 特效所需之 Open Source Libs，如 TweenLite、Box2D、Away3D…等&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.104.com.tw/jobbank/cust_job/job.cfm?j=4e4c45263648415833343c653a40391f26062446e4a5e4023232323653c2d2827563j01"&gt;Flex Programmer&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;1. 兩年以上 Flex UI Component 客製化經驗&lt;br /&gt;2. MX / Spark Component 的 Skin 開發&lt;br /&gt;3. 熟悉 PureMVC&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;a href="www.104.com.tw/jobbank/cust_job/job.cfm?j=58784b31504e475e393a426b40463f25366684a74506446292929292540592e2d008j56"&gt;Apple App Developer&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;1. 熟悉 iOS SDK、Cocoa Touch Framework，並具備一年以上 iPhone/iPad 遊戲開發經驗&lt;br /&gt;2. 熟悉 cocos2d&lt;br /&gt;3. 有 Corona + Lua 或 Unity + C# 或 Adobe AIR + ActionScript 等相關手機遊戲開發經驗者尤佳&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4754237190569973724-3964237665366912675?l=blog.ben.idv.tw' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.ben.idv.tw/feeds/3964237665366912675/comments/default' title='張貼意見'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4754237190569973724&amp;postID=3964237665366912675' title='20 個意見'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4754237190569973724/posts/default/3964237665366912675'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4754237190569973724/posts/default/3964237665366912675'/><link rel='alternate' type='text/html' href='http://blog.ben.idv.tw/2011/08/blog-post.html' title='徵才'/><author><name>Ben Chang</name><uri>http://www.blogger.com/profile/01921640246111819069</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>20</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4754237190569973724.post-504254426701088611</id><published>2011-08-02T00:35:00.006+08:00</published><updated>2011-08-03T10:17:54.964+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='CI'/><category scheme='http://www.blogger.com/atom/ns#' term='Ant'/><category scheme='http://www.blogger.com/atom/ns#' term='Flex Builder'/><category scheme='http://www.blogger.com/atom/ns#' term='Hudson'/><category scheme='http://www.blogger.com/atom/ns#' term='Flex'/><category scheme='http://www.blogger.com/atom/ns#' term='Flash'/><title type='text'>FlexPMD 與 Hudson</title><content type='html'>Adobe Open Source 有提供 FlexPMD，它可用來檢查 AS3-base 的專案原始碼，是否存在一些潛在問題、或壞習慣。&lt;a href="http://blog.ben.idv.tw/2011/08/flexpmd-hudson.html#more"&gt;閱讀更多 »&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4754237190569973724-504254426701088611?l=blog.ben.idv.tw' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.ben.idv.tw/feeds/504254426701088611/comments/default' title='張貼意見'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4754237190569973724&amp;postID=504254426701088611' title='0 個意見'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4754237190569973724/posts/default/504254426701088611'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4754237190569973724/posts/default/504254426701088611'/><link rel='alternate' type='text/html' href='http://blog.ben.idv.tw/2011/08/flexpmd-hudson.html' title='FlexPMD 與 Hudson'/><author><name>Ben Chang</name><uri>http://www.blogger.com/profile/01921640246111819069</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/-xNwwB9Fsrn0/Tjba0jNt-bI/AAAAAAAANY4/No2YUMPdZZo/s72-c/Clipboard01.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4754237190569973724.post-6990685659525149662</id><published>2011-07-31T23:44:00.006+08:00</published><updated>2011-08-03T10:18:38.237+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='CI'/><category scheme='http://www.blogger.com/atom/ns#' term='Ant'/><category scheme='http://www.blogger.com/atom/ns#' term='Flex Builder'/><category scheme='http://www.blogger.com/atom/ns#' term='Hudson'/><category scheme='http://www.blogger.com/atom/ns#' term='Flex'/><category scheme='http://www.blogger.com/atom/ns#' term='Flash'/><title type='text'>Flash 與 Hudson</title><content type='html'>7/29 剛參加完 2011 JavaTwo 活動，這次活動吸引我去聽的講題是 Hudson CI Server；今晚趁夜深人靜、沒有小孩在旁邊跑來跑去的時候，練習了一下整個環境建置過程。&lt;a href="http://blog.ben.idv.tw/2011/07/flash-hudson.html#more"&gt;閱讀更多 »&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4754237190569973724-6990685659525149662?l=blog.ben.idv.tw' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.ben.idv.tw/feeds/6990685659525149662/comments/default' title='張貼意見'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4754237190569973724&amp;postID=6990685659525149662' title='0 個意見'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4754237190569973724/posts/default/6990685659525149662'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4754237190569973724/posts/default/6990685659525149662'/><link rel='alternate' type='text/html' href='http://blog.ben.idv.tw/2011/07/flash-hudson.html' title='Flash 與 Hudson'/><author><name>Ben Chang</name><uri>http://www.blogger.com/profile/01921640246111819069</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/-DudkDceR3aY/TjV9oPhfoXI/AAAAAAAANYw/bl9i6u6zkiM/s72-c/Clipboard01.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4754237190569973724.post-5594085327768409855</id><published>2011-07-04T10:37:00.005+08:00</published><updated>2011-09-30T11:51:32.160+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='PageFlip'/><category scheme='http://www.blogger.com/atom/ns#' term='AS3DMod'/><category scheme='http://www.blogger.com/atom/ns#' term='Away3D'/><category scheme='http://www.blogger.com/atom/ns#' term='AS3'/><title type='text'>使用 AS3DMod Bend Modifier 搭配 Away3D 作翻頁效果</title><content type='html'>古老的翻書效果，使用三角函數硬算，決定遮罩角度，以陰影輔助產生立體感。&lt;br&gt;&lt;br&gt;另一種翻書效果，使用 3D 模型、貼圖，透過 AS3DMod 來改變此模型的彎曲程度。&lt;a href="http://blog.ben.idv.tw/2011/07/as3dmod-bend-modifier-away3d.html#more"&gt;閱讀更多 »&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4754237190569973724-5594085327768409855?l=blog.ben.idv.tw' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.ben.idv.tw/feeds/5594085327768409855/comments/default' title='張貼意見'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4754237190569973724&amp;postID=5594085327768409855' title='0 個意見'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4754237190569973724/posts/default/5594085327768409855'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4754237190569973724/posts/default/5594085327768409855'/><link rel='alternate' type='text/html' href='http://blog.ben.idv.tw/2011/07/as3dmod-bend-modifier-away3d.html' title='使用 AS3DMod Bend Modifier 搭配 Away3D 作翻頁效果'/><author><name>Ben Chang</name><uri>http://www.blogger.com/profile/01921640246111819069</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/-6Cnnq3KD0rM/ThEoFElbYCI/AAAAAAAANYc/2wG-TJtDdSI/s72-c/Clipboard01.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4754237190569973724.post-8152774201350647656</id><published>2011-06-24T16:06:00.004+08:00</published><updated>2011-10-01T11:45:08.791+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='AS3'/><category scheme='http://www.blogger.com/atom/ns#' term='Data Binding'/><title type='text'>Binding 到 Function</title><content type='html'>被問到，當 Binding 的 function 不是設計成 setter 時，當該 function 發生 change 事件時，純 AS 的程式碼該如何監聽並作反應。&lt;a href="http://blog.ben.idv.tw/2011/06/binding-function.html#more"&gt;閱讀更多 »&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4754237190569973724-8152774201350647656?l=blog.ben.idv.tw' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.ben.idv.tw/feeds/8152774201350647656/comments/default' title='張貼意見'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4754237190569973724&amp;postID=8152774201350647656' title='0 個意見'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4754237190569973724/posts/default/8152774201350647656'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4754237190569973724/posts/default/8152774201350647656'/><link rel='alternate' type='text/html' href='http://blog.ben.idv.tw/2011/06/binding-function.html' title='Binding 到 Function'/><author><name>Ben Chang</name><uri>http://www.blogger.com/profile/01921640246111819069</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4754237190569973724.post-7889439764219254058</id><published>2011-05-11T15:49:00.007+08:00</published><updated>2011-10-01T11:47:52.358+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='DataGrid'/><category scheme='http://www.blogger.com/atom/ns#' term='Flex Builder'/><category scheme='http://www.blogger.com/atom/ns#' term='Skin'/><category scheme='http://www.blogger.com/atom/ns#' term='AS3'/><category scheme='http://www.blogger.com/atom/ns#' term='Flex'/><title type='text'>自訂 Spark 版 DataGrid 的表頭外框</title><content type='html'>這兩天在研究使用 Spark 版 DataGrid 換 skin 的作法，目標是 &amp;quot;自定表頭背景外框造型&amp;quot;，簡單來說就是要將 表頭第一欄與最後一欄 作導圓角的動作。&lt;a href="http://blog.ben.idv.tw/2011/05/spark-datagrid.html#more"&gt;閱讀更多 »&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4754237190569973724-7889439764219254058?l=blog.ben.idv.tw' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.ben.idv.tw/feeds/7889439764219254058/comments/default' title='張貼意見'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4754237190569973724&amp;postID=7889439764219254058' title='0 個意見'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4754237190569973724/posts/default/7889439764219254058'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4754237190569973724/posts/default/7889439764219254058'/><link rel='alternate' type='text/html' href='http://blog.ben.idv.tw/2011/05/spark-datagrid.html' title='自訂 Spark 版 DataGrid 的表頭外框'/><author><name>Ben Chang</name><uri>http://www.blogger.com/profile/01921640246111819069</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/-cXNmNmB4hRc/Tco_lCDelWI/AAAAAAAANXs/SR4KsWNWYds/s72-c/Clipboard02.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4754237190569973724.post-6661583725466784381</id><published>2011-04-08T12:12:00.003+08:00</published><updated>2011-08-03T10:20:29.159+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Obfuscate'/><category scheme='http://www.blogger.com/atom/ns#' term='AS3'/><title type='text'>使用擾亂器 (ActionScript obfuscator) 要注意的事情</title><content type='html'>使用擾亂器 (ActionScript obfuscator) 要注意的事情：&lt;br&gt;&lt;br&gt;因為：&lt;br&gt;* package、class 名稱會被改變&lt;br&gt;* 屬性、變數、函式 名稱會被改變&lt;br&gt;&lt;br&gt;所以：&lt;br&gt;* 小心使用映射 Reflection&lt;br&gt;* 小心使用字串找物件的作法&lt;br&gt;* 小心 E4X 的語法&lt;br&gt;* 盡量使用強型別，避免擾亂不一致的情況&lt;a href="http://blog.ben.idv.tw/2011/04/actionscript-obfuscator.html#more"&gt;閱讀更多 »&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4754237190569973724-6661583725466784381?l=blog.ben.idv.tw' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.ben.idv.tw/feeds/6661583725466784381/comments/default' title='張貼意見'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4754237190569973724&amp;postID=6661583725466784381' title='0 個意見'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4754237190569973724/posts/default/6661583725466784381'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4754237190569973724/posts/default/6661583725466784381'/><link rel='alternate' type='text/html' href='http://blog.ben.idv.tw/2011/04/actionscript-obfuscator.html' title='使用擾亂器 (ActionScript obfuscator) 要注意的事情'/><author><name>Ben Chang</name><uri>http://www.blogger.com/profile/01921640246111819069</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4754237190569973724.post-3453807994218253303</id><published>2011-01-31T18:10:00.011+08:00</published><updated>2011-10-01T11:50:54.279+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='AS3'/><category scheme='http://www.blogger.com/atom/ns#' term='Flex'/><category scheme='http://www.blogger.com/atom/ns#' term='Flash'/><category scheme='http://www.blogger.com/atom/ns#' term='pureMVC'/><title type='text'>給 Flash / Flex / AS3 讀書會 的 PureMVC 範例</title><content type='html'>上週五，參加 PTT Flash 版版主舉辦的 Flash / Flex / AS3 讀書會，並訂定了下次聚會要討論的主題：PureMVC。&lt;br&gt;&lt;br&gt;以下，我寫一個範例來概略說明 PureMVC 的用途，這個範例提供了一個 Login 輸入介面，以及成功失敗的處理。&lt;a href="http://blog.ben.idv.tw/2011/01/for-puremvc-sample.html#more"&gt;閱讀更多 »&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4754237190569973724-3453807994218253303?l=blog.ben.idv.tw' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.ben.idv.tw/feeds/3453807994218253303/comments/default' title='張貼意見'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4754237190569973724&amp;postID=3453807994218253303' title='4 個意見'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4754237190569973724/posts/default/3453807994218253303'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4754237190569973724/posts/default/3453807994218253303'/><link rel='alternate' type='text/html' href='http://blog.ben.idv.tw/2011/01/for-puremvc-sample.html' title='給 Flash / Flex / AS3 讀書會 的 PureMVC 範例'/><author><name>Ben Chang</name><uri>http://www.blogger.com/profile/01921640246111819069</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/-ReSbQFJULIE/TVjGod4N5aI/AAAAAAAANW8/TcdCJE0HbHI/s72-c/Clipboard01.jpg' height='72' width='72'/><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4754237190569973724.post-5218521252755889473</id><published>2011-01-28T16:09:00.006+08:00</published><updated>2011-08-03T10:21:37.017+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Books'/><title type='text'>近幾年翻過的書</title><content type='html'>剛在 Amazon 上偶然發現購買紀錄，以下是我這幾年買過的 Flash / Flex / AS3 書籍：&lt;a href="http://blog.ben.idv.tw/2011/01/blog-post.html#more"&gt;閱讀更多 »&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4754237190569973724-5218521252755889473?l=blog.ben.idv.tw' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.ben.idv.tw/feeds/5218521252755889473/comments/default' title='張貼意見'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4754237190569973724&amp;postID=5218521252755889473' title='1 個意見'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4754237190569973724/posts/default/5218521252755889473'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4754237190569973724/posts/default/5218521252755889473'/><link rel='alternate' type='text/html' href='http://blog.ben.idv.tw/2011/01/blog-post.html' title='近幾年翻過的書'/><author><name>Ben Chang</name><uri>http://www.blogger.com/profile/01921640246111819069</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4754237190569973724.post-3455390812119036764</id><published>2011-01-18T20:38:00.009+08:00</published><updated>2011-08-03T10:22:04.076+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Skin'/><category scheme='http://www.blogger.com/atom/ns#' term='AS3'/><category scheme='http://www.blogger.com/atom/ns#' term='Flex'/><title type='text'>客製化 Component 的 Skin 切換</title><content type='html'>需求：&lt;br&gt;1. 有一 Component，具有兩種狀態，不同狀態下會有不同的視覺效果，&lt;br&gt;2. 可以設定此 Component 要使用的 Skin，Skin 是由美術設計提供的客製化介面，只規範了必要的 instance name，&lt;br&gt;3. 切換狀態、切換 Skin 後，同一用途的 UI 都要保持原功能，&lt;br&gt;&lt;a href="http://blog.ben.idv.tw/2011/01/component-skin.html#more"&gt;閱讀更多 »&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4754237190569973724-3455390812119036764?l=blog.ben.idv.tw' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.ben.idv.tw/feeds/3455390812119036764/comments/default' title='張貼意見'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4754237190569973724&amp;postID=3455390812119036764' title='0 個意見'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4754237190569973724/posts/default/3455390812119036764'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4754237190569973724/posts/default/3455390812119036764'/><link rel='alternate' type='text/html' href='http://blog.ben.idv.tw/2011/01/component-skin.html' title='客製化 Component 的 Skin 切換'/><author><name>Ben Chang</name><uri>http://www.blogger.com/profile/01921640246111819069</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/_HsFEtLMw5zU/TTWOwDuTgrI/AAAAAAAANUw/rz2IiETjtws/s72-c/Clipboard01.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4754237190569973724.post-4016263818668478941</id><published>2010-07-06T17:15:00.002+08:00</published><updated>2011-08-02T16:14:47.580+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Server'/><title type='text'>與 FMIS、FMLE 有關的資源</title><content type='html'>記錄幾個與 Flash Media Interactive Server 錄影技術相關的連結&lt;br /&gt;&lt;br /&gt;[自動化控制 Flash Media Live Encoder]&lt;br /&gt;&lt;br /&gt;How to pragrammatically control Flash Encod&lt;br /&gt;http://forums.adobe.com/thread/27425&lt;br /&gt;&lt;br /&gt;How to Programmatically Control Adobe Flash Media Encoder&lt;br /&gt;http://flex.sys-con.com/node/388456&lt;br /&gt;&lt;br /&gt;Start Flash Media Live Encoder in command-line mode&lt;br /&gt;http://help.adobe.com/en_US/FlashMediaLiveEncoder/3.0/Using/WS5b3ccc516d4fbf351e63e3d11c104babd5-7ffc.html&lt;br /&gt;&lt;br /&gt;[讓 FMIS 支援 Digital Video Recorder]&lt;br /&gt;&lt;br /&gt;Create server-side DVR application to be able to record DVR in FMS&lt;br /&gt;http://stackoverflow.com/questions/805897/create-server-side-dvr-application-to-be-able-to-record-dvr-in-fms&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4754237190569973724-4016263818668478941?l=blog.ben.idv.tw' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.ben.idv.tw/feeds/4016263818668478941/comments/default' title='張貼意見'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4754237190569973724&amp;postID=4016263818668478941' title='10 個意見'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4754237190569973724/posts/default/4016263818668478941'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4754237190569973724/posts/default/4016263818668478941'/><link rel='alternate' type='text/html' href='http://blog.ben.idv.tw/2010/07/fmisfmle.html' title='與 FMIS、FMLE 有關的資源'/><author><name>Ben Chang</name><uri>http://www.blogger.com/profile/01921640246111819069</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>10</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4754237190569973724.post-2773539306889764005</id><published>2010-07-02T17:50:00.010+08:00</published><updated>2011-08-03T10:22:55.963+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Class Loader'/><category scheme='http://www.blogger.com/atom/ns#' term='Skin'/><category scheme='http://www.blogger.com/atom/ns#' term='AS3'/><category scheme='http://www.blogger.com/atom/ns#' term='Flash'/><title type='text'>既有的 FLA 專案改成動態載入畫面元素</title><content type='html'>如果有一天，上面說，希望將現有的 Flash 介面，換掉部分元素後，賣給其他客戶。&lt;br&gt;&lt;br&gt;這裡指的 &amp;quot;換掉部分元素&amp;quot;，是在不變更設計、或不影響原程式座標邏輯之下，改變顏色、風格的需求。&lt;br&gt;&lt;br&gt;作法一，將整份 FLA 複製一份，改完 UI 設計，輸出！&lt;br&gt;優：最快&lt;br&gt;缺：每份 FLA 都有程式邏輯，每次異動，都要重新發佈所有 FLA&lt;br&gt;&lt;br&gt;作法二，調整一些程式，動態載入要更換的元素，放在與原設計相同的座標、縮放、旋轉角度、層級中。&lt;br&gt;優：邏輯只有一份，不同的 UI 可被動態載入&lt;br&gt;缺：有一堆苦工要作，可大可小&lt;br&gt;&lt;a href="http://blog.ben.idv.tw/2010/07/blog-post.html#more"&gt;閱讀更多 »&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4754237190569973724-2773539306889764005?l=blog.ben.idv.tw' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.ben.idv.tw/feeds/2773539306889764005/comments/default' title='張貼意見'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4754237190569973724&amp;postID=2773539306889764005' title='0 個意見'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4754237190569973724/posts/default/2773539306889764005'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4754237190569973724/posts/default/2773539306889764005'/><link rel='alternate' type='text/html' href='http://blog.ben.idv.tw/2010/07/blog-post.html' title='既有的 FLA 專案改成動態載入畫面元素'/><author><name>Ben Chang</name><uri>http://www.blogger.com/profile/01921640246111819069</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/_HsFEtLMw5zU/TC24btR0LwI/AAAAAAAANSc/XDDprp1_8co/s72-c/Clipboard01.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4754237190569973724.post-4331284238860555094</id><published>2010-06-07T19:35:00.004+08:00</published><updated>2011-08-03T10:32:06.954+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='.NET'/><category scheme='http://www.blogger.com/atom/ns#' term='Flex'/><category scheme='http://www.blogger.com/atom/ns#' term='Flash Remoting'/><title type='text'>透過 FluorineFx 使用 Flex Remoting 與 .NET 溝通</title><content type='html'>今天研究了一下透過 FluorineFx 讓 Flex 與 .NET 溝通，並找出最基本需要佈署的 FluorineFx 檔案有哪些，以下是簡單的步驟記錄：&lt;br&gt;&lt;a href="http://blog.ben.idv.tw/2010/06/fluorinefx-flex-remoting-net.html#more"&gt;閱讀更多 »&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4754237190569973724-4331284238860555094?l=blog.ben.idv.tw' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.ben.idv.tw/feeds/4331284238860555094/comments/default' title='張貼意見'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4754237190569973724&amp;postID=4331284238860555094' title='2 個意見'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4754237190569973724/posts/default/4331284238860555094'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4754237190569973724/posts/default/4331284238860555094'/><link rel='alternate' type='text/html' href='http://blog.ben.idv.tw/2010/06/fluorinefx-flex-remoting-net.html' title='透過 FluorineFx 使用 Flex Remoting 與 .NET 溝通'/><author><name>Ben Chang</name><uri>http://www.blogger.com/profile/01921640246111819069</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/_HsFEtLMw5zU/TAzdL977CfI/AAAAAAAANRg/s0-l2bLzFfk/s72-c/Clipboard01.jpg' height='72' width='72'/><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4754237190569973724.post-3165695808744455910</id><published>2010-06-04T15:35:00.010+08:00</published><updated>2011-08-03T10:30:14.231+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='.NET'/><category scheme='http://www.blogger.com/atom/ns#' term='Flex'/><category scheme='http://www.blogger.com/atom/ns#' term='Flash Remoting'/><title type='text'>當然，Flex Remoting 是 Call by Value</title><content type='html'>最近測試 WebORB，發現一個問題，若是 .NET 程式中，A.dll 中的 PackageA.ClassA，提供了 getB() 的 method，但是回傳物件是屬於 B.dll 中的 PackageB.ClassB 的話，當 invoke getB() 時便會發生 gateway 解析不出自定類別物件 ClassB 的情況。&lt;br&gt;&lt;a href="http://blog.ben.idv.tw/2010/06/flex-remoting-call-by-value.html#more"&gt;閱讀更多 »&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4754237190569973724-3165695808744455910?l=blog.ben.idv.tw' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.ben.idv.tw/feeds/3165695808744455910/comments/default' title='張貼意見'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4754237190569973724&amp;postID=3165695808744455910' title='0 個意見'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4754237190569973724/posts/default/3165695808744455910'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4754237190569973724/posts/default/3165695808744455910'/><link rel='alternate' type='text/html' href='http://blog.ben.idv.tw/2010/06/flex-remoting-call-by-value.html' title='當然，Flex Remoting 是 Call by Value'/><author><name>Ben Chang</name><uri>http://www.blogger.com/profile/01921640246111819069</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/_HsFEtLMw5zU/TAivZzxZxzI/AAAAAAAANQw/4NdHTyZvp34/s72-c/Clipboard01.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4754237190569973724.post-6599068473283163260</id><published>2010-06-04T02:07:00.008+08:00</published><updated>2011-08-03T10:32:52.932+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='.NET'/><category scheme='http://www.blogger.com/atom/ns#' term='Flex'/><category scheme='http://www.blogger.com/atom/ns#' term='Flash Remoting'/><title type='text'>透過 WebORB 使用 Flex Remoting 與 .NET 溝通</title><content type='html'>今天研究了一下透過 WebORB 讓 Flex 與 .NET 溝通，並找出最基本需要佈署的 WebORB 檔案有哪些，以下是簡單的步驟記錄：&lt;br&gt;&lt;a href="http://blog.ben.idv.tw/2010/06/weborb-flex-remoting-net.html#more"&gt;閱讀更多 »&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4754237190569973724-6599068473283163260?l=blog.ben.idv.tw' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.ben.idv.tw/feeds/6599068473283163260/comments/default' title='張貼意見'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4754237190569973724&amp;postID=6599068473283163260' title='0 個意見'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4754237190569973724/posts/default/6599068473283163260'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4754237190569973724/posts/default/6599068473283163260'/><link rel='alternate' type='text/html' href='http://blog.ben.idv.tw/2010/06/weborb-flex-remoting-net.html' title='透過 WebORB 使用 Flex Remoting 與 .NET 溝通'/><author><name>Ben Chang</name><uri>http://www.blogger.com/profile/01921640246111819069</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4754237190569973724.post-1983761942442635668</id><published>2010-05-05T16:38:00.005+08:00</published><updated>2011-08-03T10:30:49.222+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Skin'/><category scheme='http://www.blogger.com/atom/ns#' term='CSS'/><category scheme='http://www.blogger.com/atom/ns#' term='AS3'/><category scheme='http://www.blogger.com/atom/ns#' term='Flex'/><category scheme='http://www.blogger.com/atom/ns#' term='Flash'/><title type='text'>製作動態載入 Theme，Part 2</title><content type='html'>上一篇介紹，以 Flash IDE 製作的 swf，被當作 Flex 的素材，以 css 的方式定義，並將 css 轉成 swf 讓 Flex 應用程式動態載入，程式可透過 css 取得 Class，動態建立視覺物件。&lt;br&gt;&lt;a target="_blank" href="http://blog.ben.idv.tw/2010/05/flex-flash-theme.html"&gt;http://blog.ben.idv.tw/2010/05/flex-flash-theme.html&lt;/a&gt;&lt;br&gt;&lt;br&gt;這篇，少掉 Flex 的架構 (雖然我是用 Flex Builder 的 ActionScript 專案在開發)，以 Flash IDE 製作的 swf 直接被當作動態載入的 Theme 資源，載入後直接由其中取出 Class，動態建立視覺物件。&lt;br&gt;&lt;a href="http://blog.ben.idv.tw/2010/05/themepart-2.html#more"&gt;閱讀更多 »&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4754237190569973724-1983761942442635668?l=blog.ben.idv.tw' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.ben.idv.tw/feeds/1983761942442635668/comments/default' title='張貼意見'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4754237190569973724&amp;postID=1983761942442635668' title='10 個意見'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4754237190569973724/posts/default/1983761942442635668'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4754237190569973724/posts/default/1983761942442635668'/><link rel='alternate' type='text/html' href='http://blog.ben.idv.tw/2010/05/themepart-2.html' title='製作動態載入 Theme，Part 2'/><author><name>Ben Chang</name><uri>http://www.blogger.com/profile/01921640246111819069</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_HsFEtLMw5zU/S-E0EWFPOOI/AAAAAAAANI0/a0ID3entsic/s72-c/Clipboard01.jpg' height='72' width='72'/><thr:total>10</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4754237190569973724.post-4477429795580579171</id><published>2010-05-04T02:12:00.006+08:00</published><updated>2011-08-03T10:31:04.149+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Skin'/><category scheme='http://www.blogger.com/atom/ns#' term='CSS'/><category scheme='http://www.blogger.com/atom/ns#' term='AS3'/><category scheme='http://www.blogger.com/atom/ns#' term='Flex'/><category scheme='http://www.blogger.com/atom/ns#' term='Flash'/><title type='text'>於 Flex 使用 Flash 素材，與製作動態載入 Theme</title><content type='html'>最近工作上，花了很多時間在處理 Flash 與 Flex 之間的合作。&lt;br&gt;&lt;br&gt;目標是，美術製作的 Flash 素材，Flex 可以直接使用，不用重新依照 Flash 的設計而在 Flex 中重新以 MXML 組合 layout；並且要能支援動態載入外部 *.swf 素材，達到切換 theme 的機制。&lt;br&gt;&lt;a href="http://blog.ben.idv.tw/2010/05/flex-flash-theme.html#more"&gt;閱讀更多 »&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4754237190569973724-4477429795580579171?l=blog.ben.idv.tw' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.ben.idv.tw/feeds/4477429795580579171/comments/default' title='張貼意見'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4754237190569973724&amp;postID=4477429795580579171' title='2 個意見'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4754237190569973724/posts/default/4477429795580579171'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4754237190569973724/posts/default/4477429795580579171'/><link rel='alternate' type='text/html' href='http://blog.ben.idv.tw/2010/05/flex-flash-theme.html' title='於 Flex 使用 Flash 素材，與製作動態載入 Theme'/><author><name>Ben Chang</name><uri>http://www.blogger.com/profile/01921640246111819069</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/_HsFEtLMw5zU/S98SQ_mqzTI/AAAAAAAANHs/hCiSA79BHMo/s72-c/Clipboard01.jpg' height='72' width='72'/><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4754237190569973724.post-4891719410329305414</id><published>2010-04-08T19:49:00.004+08:00</published><updated>2011-08-03T10:31:17.206+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='DataGrid'/><category scheme='http://www.blogger.com/atom/ns#' term='XML'/><category scheme='http://www.blogger.com/atom/ns#' term='AS3'/><title type='text'>XMLListCollection 的異動對於 DataGrid 的 selectedIndex 的影響</title><content type='html'>今天花了很多時間在研究 &amp;quot;XMLListCollection 的異動對於 DataGrid 的 selectedIndex 的影響&amp;quot; ，寫了以下的範例程式來說明這一切，區分 新增、刪除、修改 資料的情況，有空想了解的人，看程式碼註解吧～&lt;br&gt;&lt;a href="http://blog.ben.idv.tw/2010/04/xmllistcollection-datagrid.html#more"&gt;閱讀更多 »&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4754237190569973724-4891719410329305414?l=blog.ben.idv.tw' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.ben.idv.tw/feeds/4891719410329305414/comments/default' title='張貼意見'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4754237190569973724&amp;postID=4891719410329305414' title='0 個意見'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4754237190569973724/posts/default/4891719410329305414'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4754237190569973724/posts/default/4891719410329305414'/><link rel='alternate' type='text/html' href='http://blog.ben.idv.tw/2010/04/xmllistcollection-datagrid.html' title='XMLListCollection 的異動對於 DataGrid 的 selectedIndex 的影響'/><author><name>Ben Chang</name><uri>http://www.blogger.com/profile/01921640246111819069</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4754237190569973724.post-4099890958583875598</id><published>2010-03-25T19:47:00.010+08:00</published><updated>2011-08-03T10:31:51.064+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Flex Builder'/><category scheme='http://www.blogger.com/atom/ns#' term='Flash Player'/><category scheme='http://www.blogger.com/atom/ns#' term='Flash CS4'/><title type='text'>使用 Flash CS4 製作含有 3D 座標的 swc 給 Flex Builder 3 當作素材的問題</title><content type='html'>使用 Flash CS4 製作 *.swc 給 Flex Builder 3 當作素材時，遇到一個有趣的現象。&lt;br&gt;&lt;a href="http://blog.ben.idv.tw/2010/03/flash-cs4-3d-swc-flex-builder-3.html#more"&gt;閱讀更多 »&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4754237190569973724-4099890958583875598?l=blog.ben.idv.tw' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.ben.idv.tw/feeds/4099890958583875598/comments/default' title='張貼意見'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4754237190569973724&amp;postID=4099890958583875598' title='2 個意見'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4754237190569973724/posts/default/4099890958583875598'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4754237190569973724/posts/default/4099890958583875598'/><link rel='alternate' type='text/html' href='http://blog.ben.idv.tw/2010/03/flash-cs4-3d-swc-flex-builder-3.html' title='使用 Flash CS4 製作含有 3D 座標的 swc 給 Flex Builder 3 當作素材的問題'/><author><name>Ben Chang</name><uri>http://www.blogger.com/profile/01921640246111819069</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/_HsFEtLMw5zU/S6tNTctaKPI/AAAAAAAANGo/pZwgan95WEo/s72-c/Clipboard01.jpg' height='72' width='72'/><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4754237190569973724.post-2604117384978253005</id><published>2009-12-23T16:48:00.008+08:00</published><updated>2011-08-03T10:33:34.185+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Obfuscate'/><category scheme='http://www.blogger.com/atom/ns#' term='AS3'/><category scheme='http://www.blogger.com/atom/ns#' term='ApplicationDomain'/><title type='text'>擾亂器 與 ApplicationDomain</title><content type='html'>遇到一個 擾亂器 與 ApplicationDomain 的問題。&lt;br&gt;&lt;br&gt;以下是測試程式的步驟：&lt;br&gt;&lt;br&gt;1. ApplicationDomainTest.swf 載入 ExternalSWF.swf&lt;br&gt;2. 取得 ExternalSWF.swf 中的 ExternalSWF 類別&lt;br&gt;3. 因為 ExternalSWF 實作 ISwf2 介面，所以 ApplicationDomainTest 可以透過對 ISwf2 的認識，而執行 doA(ISwf1) 將自己當作參數帶入。&lt;br&gt;4. 當 ExternalSWF 的 doA(ISwf1) 被執行時，可以透過對 ISwf1 的認識，而執行 ApplicationDomainTest 的 doA(ISwf2)。&lt;br&gt;5. ApplicationDomainTest 的 doA(ISwf2) 被執行時，會在畫面上顯示 &amp;quot;success&amp;quot; 文字。&lt;br&gt;&lt;a href="http://blog.ben.idv.tw/2009/12/applicationdomain.html#more"&gt;閱讀更多 »&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4754237190569973724-2604117384978253005?l=blog.ben.idv.tw' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.ben.idv.tw/feeds/2604117384978253005/comments/default' title='張貼意見'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4754237190569973724&amp;postID=2604117384978253005' title='3 個意見'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4754237190569973724/posts/default/2604117384978253005'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4754237190569973724/posts/default/2604117384978253005'/><link rel='alternate' type='text/html' href='http://blog.ben.idv.tw/2009/12/applicationdomain.html' title='擾亂器 與 ApplicationDomain'/><author><name>Ben Chang</name><uri>http://www.blogger.com/profile/01921640246111819069</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_HsFEtLMw5zU/SzHb1piSelI/AAAAAAAAMQM/u24Q7oup6M8/s72-c/Clipboard01.jpg' height='72' width='72'/><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4754237190569973724.post-3483169719109390927</id><published>2009-12-22T11:33:00.006+08:00</published><updated>2011-10-14T00:55:40.781+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Local Connection'/><category scheme='http://www.blogger.com/atom/ns#' term='AS3'/><category scheme='http://www.blogger.com/atom/ns#' term='Flash'/><title type='text'>多 Local Connection 彼此維護名單的機制</title><content type='html'>有時候我們作 Local Connection 的應用時，都需要一個 &amp;quot;主 Flash&amp;quot; 負責管理有多少個 Flash 端點，我這裡說的不是只有兩個 Flash 在互相連線而已，而是多個 Flash 需要互相連線、交換資訊的情況。&lt;br&gt;&lt;br&gt;這個情況可以想像是 &amp;quot;遊戲大廳&amp;quot; 與 &amp;quot;各遊戲&amp;quot; 之間的關係，不管各遊戲開開關關，只要遊戲大廳還存在，就可以負責為各遊戲之間作資料交換的工作。但假使遊戲大廳不存在呢？那麼各遊戲就都必須充當遊戲大廳的角色去認識所有其他遊戲才行。&lt;br&gt;&lt;a href="http://blog.ben.idv.tw/2009/12/local-connection.html#more"&gt;閱讀更多 »&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4754237190569973724-3483169719109390927?l=blog.ben.idv.tw' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.ben.idv.tw/feeds/3483169719109390927/comments/default' title='張貼意見'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4754237190569973724&amp;postID=3483169719109390927' title='4 個意見'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4754237190569973724/posts/default/3483169719109390927'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4754237190569973724/posts/default/3483169719109390927'/><link rel='alternate' type='text/html' href='http://blog.ben.idv.tw/2009/12/local-connection.html' title='多 Local Connection 彼此維護名單的機制'/><author><name>Ben Chang</name><uri>http://www.blogger.com/profile/01921640246111819069</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/_HsFEtLMw5zU/SzBKSJurjtI/AAAAAAAAMQE/J2YnAn-Vz3k/s72-c/Clipboard01.jpg' height='72' width='72'/><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4754237190569973724.post-4004056117206912254</id><published>2009-11-11T19:05:00.005+08:00</published><updated>2011-08-02T16:13:11.961+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Away3D'/><category scheme='http://www.blogger.com/atom/ns#' term='Flash'/><title type='text'>Away3DLite 使用 Collada</title><content type='html'>Away3DLite 1.0 出一陣子了：&lt;br /&gt;http://away3d.com/away3d-lite-v1-0-fastest-and-smallest-3d-engine-in-flash&lt;br /&gt;&lt;br /&gt;號稱很小、很快，因為使用了 Flash Player 10 提供的 3D 語法，所以限制一定要使用 FP10 瀏覽才行。&lt;br /&gt;&lt;br /&gt;以下，我作一個簡單的範例，載入一個 Collada 格式的 *.dae 模型檔案，這個 *.dae 可由各種 3D 建模軟體加上外掛輸出而成，或是像我偷懶去網路上找現成的借用一下。&lt;br /&gt;&lt;br /&gt;Collada Test Model Bank: https://collada.org/owl/&lt;br /&gt;我沒研究這個地方的版權說明，總之，借用者別用作營利用途就好～&lt;br /&gt;&lt;br /&gt;範例原始碼：&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;package&lt;br /&gt;{&lt;br /&gt; import away3dlite.core.base.Object3D;&lt;br /&gt; import away3dlite.loaders.Collada;&lt;br /&gt; import away3dlite.materials.WireframeMaterial;&lt;br /&gt; import away3dlite.templates.BasicTemplate;&lt;br /&gt; &lt;br /&gt; import flash.events.Event;&lt;br /&gt; import flash.events.MouseEvent;&lt;br /&gt; import flash.net.URLLoader;&lt;br /&gt; import flash.net.URLRequest;&lt;br /&gt;&lt;br /&gt; [SWF(width=640, height=480)]&lt;br /&gt; public class Away3DLite_TestCollada extends BasicTemplate&lt;br /&gt; {&lt;br /&gt;  public function Away3DLite_TestCollada()&lt;br /&gt;  {&lt;br /&gt;   super();&lt;br /&gt;  }&lt;br /&gt;  &lt;br /&gt;  private const ROTATION_DY_MAX:Number = 5;&lt;br /&gt;  private var rotation_dy:Number = 0;&lt;br /&gt;  &lt;br /&gt;  private const ROTATION_DX_MAX:Number = 5;&lt;br /&gt;  private var rotation_dx:Number = 0;&lt;br /&gt;  &lt;br /&gt;  private var _myCollada:Object3D&lt;br /&gt;&lt;br /&gt;  override protected function onInit():void{&lt;br /&gt;   camera.z = 0;&lt;br /&gt;   camera.zoom = 300;&lt;br /&gt;   &lt;br /&gt;   view.mouseEnabled3D = false;&lt;br /&gt;   &lt;br /&gt;   var loader:URLLoader = new URLLoader();&lt;br /&gt;   loader.addEventListener(Event.COMPLETE, onColladaLoaded);&lt;br /&gt;   loader.load(new URLRequest("collada.dae"));&lt;br /&gt;  }  &lt;br /&gt;  &lt;br /&gt;  private function onColladaLoaded(e:Event):void{&lt;br /&gt;   addColladaObj((e.currentTarget as URLLoader).data);&lt;br /&gt;   &lt;br /&gt;   stage.addEventListener(MouseEvent.MOUSE_MOVE, onMouseMove);&lt;br /&gt;   stage.addEventListener(MouseEvent.MOUSE_WHEEL, onMouseWheel);&lt;br /&gt;  }&lt;br /&gt;  &lt;br /&gt;  private function addColladaObj(data:*):void{&lt;br /&gt;   var collada:Collada = new Collada();&lt;br /&gt;   collada.material = new WireframeMaterial();&lt;br /&gt;   _myCollada = collada.parseGeometry(data);&lt;br /&gt;   &lt;br /&gt;   scene.addChild(_myCollada);&lt;br /&gt;  }&lt;br /&gt;  &lt;br /&gt;  private function onMouseMove(e:MouseEvent):void{&lt;br /&gt;   var dmx:Number = mouseX - width/2;&lt;br /&gt;   dmx = Math.min(Math.max(dmx, -width/2), width/2);&lt;br /&gt;   rotation_dy = ROTATION_DY_MAX * (dmx / (width/2));&lt;br /&gt;   &lt;br /&gt;   var dmy:Number = mouseY - height/2;&lt;br /&gt;   dmy = Math.min(Math.max(dmy, -height/2), height/2);&lt;br /&gt;   rotation_dx = ROTATION_DX_MAX * (dmy / (height/2));&lt;br /&gt;  }&lt;br /&gt;  &lt;br /&gt;  private function onMouseWheel(e:MouseEvent):void{&lt;br /&gt;   camera.z += (10 * e.delta);&lt;br /&gt;   camera.z = Math.min(camera.z, 0);&lt;br /&gt;  }&lt;br /&gt;  &lt;br /&gt;  override protected function onPreRender():void{&lt;br /&gt;   if(_myCollada!=null){&lt;br /&gt;    _myCollada.rotationY += rotation_dy;&lt;br /&gt;    _myCollada.rotationX += rotation_dx;&lt;br /&gt;   }&lt;br /&gt;  }&lt;br /&gt;  &lt;br /&gt; }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;載入 *.dae 後，可用滑鼠在畫面上移動，根據滑鼠 x, y 座標來使模型沿著 y 軸旋轉、x 軸旋轉，另外可用滑鼠滾輪控制 camera 的前進後退。&lt;br /&gt;&lt;br /&gt;看效果：&lt;br /&gt;http://sites.google.com/site/benrbchang/Away3DLite-Collada&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4754237190569973724-4004056117206912254?l=blog.ben.idv.tw' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.ben.idv.tw/feeds/4004056117206912254/comments/default' title='張貼意見'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4754237190569973724&amp;postID=4004056117206912254' title='7 個意見'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4754237190569973724/posts/default/4004056117206912254'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4754237190569973724/posts/default/4004056117206912254'/><link rel='alternate' type='text/html' href='http://blog.ben.idv.tw/2009/11/away3dlite-collada_11.html' title='Away3DLite 使用 Collada'/><author><name>Ben Chang</name><uri>http://www.blogger.com/profile/01921640246111819069</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>7</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4754237190569973724.post-8255785072773737295</id><published>2009-10-01T10:24:00.003+08:00</published><updated>2011-08-02T16:22:58.432+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='mask'/><category scheme='http://www.blogger.com/atom/ns#' term='AS3'/><category scheme='http://www.blogger.com/atom/ns#' term='Flash'/><title type='text'>Flash IDE 的遮罩在 reparentting 後的問題</title><content type='html'>遇到一個問題，在 Flash IDE 中的時間軸上所設計的遮罩，若是用程式將他 reparentting 後，會導致在新的 container(該遮罩的parent) 中，所有 child index 在該遮罩之上的 display object，都會被該遮罩所遮到。&lt;br /&gt;&lt;br /&gt;下圖是 UI 的配置，mask_mc 遮 contain_mc，在這組遮罩的上下各有一個 green_mc 與 blue_mc：&lt;br /&gt;&lt;br /&gt;&lt;a target="_blank" href="http://3.bp.blogspot.com/_HsFEtLMw5zU/SsQS9NY80UI/AAAAAAAALPQ/6ta-vZQ6U7o/s1600-h/Clipboard02.jpg"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 400px; height: 321px;" src="http://3.bp.blogspot.com/_HsFEtLMw5zU/SsQS9NY80UI/AAAAAAAALPQ/6ta-vZQ6U7o/s400/Clipboard02.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5387451897017585986" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;以下是程式碼，主要工作是建立一個新的 mc1 放到 MainTimeline 上，然後將 MainTimeline 上的所有 DisplayObject 都移進 mc1 中，並在動作前後都作一些 trace：&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;var mc1:MovieClip = new MovieClip();&lt;br /&gt;mc1.name = "NewContainer";&lt;br /&gt;addChild(mc1);&lt;br /&gt;&lt;br /&gt;function traceInfo(container:DisplayObjectContainer):void{&lt;br /&gt; trace("traceInfo()", container.name);&lt;br /&gt; for(var i:int=0; i&lt;container.numChildren; i++){&lt;br /&gt;  trace(i, container.getChildAt(i).name);&lt;br /&gt; }&lt;br /&gt; trace("");&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;trace("初始時的 MainTimeline");&lt;br /&gt;traceInfo(this);&lt;br /&gt;&lt;br /&gt;for(var i:int = numChildren-1; i&gt;=0; i--){&lt;br /&gt; var obj:DisplayObject = getChildAt(i);&lt;br /&gt; if(obj!=mc1){&lt;br /&gt;  mc1.addChildAt(obj, 0);&lt;br /&gt; }&lt;br /&gt;}&lt;br /&gt;_mc.getC&lt;br /&gt;trace("reparentting 後的 MainTimeline");&lt;br /&gt;traceInfo(this);&lt;br /&gt;&lt;br /&gt;trace("reparentting 後的 NewContainer");&lt;br /&gt;traceInfo(mc1);&lt;br /&gt;&lt;br /&gt;var yellowLine:MovieClip = new YellowLine();&lt;br /&gt;yellowLine.name = "yellowLine";&lt;br /&gt;mc1.addChild(yellowLine);&lt;br /&gt;&lt;br /&gt;trace("在 NewContainer 新加入 DisplayObject 後");&lt;br /&gt;traceInfo(mc1);&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;執行後的畫面：&lt;br /&gt;&lt;br /&gt;&lt;a target="_blank" href="http://4.bp.blogspot.com/_HsFEtLMw5zU/SsQS9uK783I/AAAAAAAALPY/YwmOX6w47Eg/s1600-h/Clipboard04.jpg"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 400px; height: 278px;" src="http://4.bp.blogspot.com/_HsFEtLMw5zU/SsQS9uK783I/AAAAAAAALPY/YwmOX6w47Eg/s400/Clipboard04.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5387451905817178994" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;從第一段 trace 可以看出，在 Flash IDE 中所設計的遮罩，從 child index 來說，mask_mc (index=1) 會在 content_mc (index=2) 的下面。&lt;br /&gt;&lt;br /&gt;第三、四段 trace 可以看出，所有 DisplayObject 在移動前後的 child index 都是沒有改變的，但是從畫面上來看，除了 blueLine (index=0) 之外的所有 DisplayObject 都會被 mask_mc 所遮蔽，即使是最後用程式加入的 yellowLine (index=4) 也不例外。&lt;br /&gt;&lt;br /&gt;感覺上，Flash IDE 設計的遮罩，會將 child index 在其上面的 DisplayObject 都遮蔽，或許還會有一個變數來定義遮多少個(亂猜的)，而當 reparentting 後為何會影響到所有在其上的物件，這點我還沒想出來。&lt;br /&gt;&lt;br /&gt;正在研究 DisplayObject.mask 的相關說明，不過有可能 Flash IDE 設計的遮罩有不同的實作方式也說不一定。&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4754237190569973724-8255785072773737295?l=blog.ben.idv.tw' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.ben.idv.tw/feeds/8255785072773737295/comments/default' title='張貼意見'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4754237190569973724&amp;postID=8255785072773737295' title='2 個意見'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4754237190569973724/posts/default/8255785072773737295'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4754237190569973724/posts/default/8255785072773737295'/><link rel='alternate' type='text/html' href='http://blog.ben.idv.tw/2009/10/flash-ide-reparentting.html' title='Flash IDE 的遮罩在 reparentting 後的問題'/><author><name>Ben Chang</name><uri>http://www.blogger.com/profile/01921640246111819069</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/_HsFEtLMw5zU/SsQS9NY80UI/AAAAAAAALPQ/6ta-vZQ6U7o/s72-c/Clipboard02.jpg' height='72' width='72'/><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4754237190569973724.post-7366573764763644510</id><published>2009-09-18T15:10:00.000+08:00</published><updated>2009-09-18T15:11:23.284+08:00</updated><title type='text'>酷炫新SHOW開發創意大賽</title><content type='html'>Show出創意 打造夢想 豐富人生&lt;br /&gt;酷炫新Show開發創意大賽是針對手機娛樂領域開發者所舉辦的大賽，由Sony Ericsson 開發者世界 主辦，大會宗旨在提升在校大學生手機領域學習者和廣大在校手機玩家的創新性與積極性，提供展現自我的創意舞台，打造參賽者未來職場生涯之路。&lt;br /&gt;&lt;br /&gt;見證奇蹟 由此開始&lt;br /&gt;Sony Ericsson開發者世界尊重每位參賽者的原創性，更重視每份參賽作品的用心﹔&lt;br /&gt;獲獎者即可優先獲得Sony Ericsson北京總部研發中心的實習機會；&lt;br /&gt;只是參賽”入圍者”皆可獲得Sony Ericsson開發者世界的榮譽證書；&lt;br /&gt;所有入圍作品皆有機會與Sony Ericsson PlaynowTM合作，打造屬於自已的酷炫手機!&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;參賽得獎者皆可得到優渥的獎學金和Sony Ericsson的手機&lt;br /&gt;誘人的大獎正在向你招手 還在等什麼 加快腳步動起來吧！&lt;br /&gt;&lt;br /&gt;詳情請參閱活動網站&lt;br /&gt;&lt;a href="http://developer.sonyericsson.com/universityawards" target="_blank"&gt;http://developer.sonyericsson.com/universityawards&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;活動專線：02-2516-1255#108 &lt;br /&gt;作品繳交期間： 2009年7月－10月20日&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4754237190569973724-7366573764763644510?l=blog.ben.idv.tw' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.ben.idv.tw/feeds/7366573764763644510/comments/default' title='張貼意見'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4754237190569973724&amp;postID=7366573764763644510' title='0 個意見'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4754237190569973724/posts/default/7366573764763644510'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4754237190569973724/posts/default/7366573764763644510'/><link rel='alternate' type='text/html' href='http://blog.ben.idv.tw/2009/09/show.html' title='酷炫新SHOW開發創意大賽'/><author><name>Ben Chang</name><uri>http://www.blogger.com/profile/01921640246111819069</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4754237190569973724.post-584481283385808013</id><published>2009-08-07T16:07:00.006+08:00</published><updated>2011-08-02T16:13:11.967+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Webcam'/><category scheme='http://www.blogger.com/atom/ns#' term='BitmapData'/><category scheme='http://www.blogger.com/atom/ns#' term='Books'/><category scheme='http://www.blogger.com/atom/ns#' term='AS3'/><title type='text'>ActionScript 3.0 Image Effects</title><content type='html'>颱風天在家裡，甚麼事情也不能做，更扯的是餐城也進不去，詭異的是我老婆可以...$%&amp;amp;@#，這時候只能暗自猜想 playfish 該不會將我的電腦變成拒絕往來戶了吧。既然沒有遊戲可以玩，只好趁機花點時間再繼續看看之前買的書：&lt;br /&gt;&lt;br /&gt;ActionScript 3.0 Image Effects&lt;br /&gt;http://tlsj.tenlong.com.tw/WebModule/BookSearch/bookSearchViewAction.do?isbn=1430218711&amp;amp;sid=50458&lt;div&gt;&lt;br /&gt;&lt;div&gt;&lt;img src="http://1.bp.blogspot.com/_HsFEtLMw5zU/SnvhuYaaRFI/AAAAAAAALNg/iuC8dXCdiCc/s400/1430218711.jpg" style="cursor: pointer; width: 334px; height: 400px;" alt="" id="BLOGGER_PHOTO_ID_5367131567885534290" border="0" /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;本書的章節如下：&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;1. The Drawing API&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;無廢話，直接快速帶過常用的 API 語法。甚至會提到 Flash Player 10 才支援的語法，譬如 Graphics 的：&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style=";font-family:Tahoma;font-size:13px;"  &gt;&lt;div class="summarySignature" style="text-indent: -20px; padding-left: 20px;"&gt;&lt;a href="http://livedocs.adobe.com/flex/3/langref/flash/display/Graphics.html#copyFrom%28%29" class="signatureLink" style="font-weight: bold; color: rgb(0, 0, 204); text-decoration: none;"&gt;copyFrom&lt;/a&gt;(sourceGraphics:&lt;a href="http://livedocs.adobe.com/flex/3/langref/flash/display/Graphics.html" style="color: rgb(0, 0, 204); text-decoration: none;"&gt;&lt;/a&gt;&lt;a href="http://livedocs.adobe.com/flex/3/langref/flash/display/Graphics.html" style="color: rgb(0, 0, 204); text-decoration: none;"&gt;Graphics&lt;/a&gt;):&lt;a href="http://livedocs.adobe.com/flex/3/langref/specialTypes.html#void" style="color: rgb(0, 0, 204); text-decoration: none;"&gt;void&lt;/a&gt;&lt;/div&gt;&lt;div class="summaryTableDescription" style="color: rgb(51, 51, 51);"&gt;Copies all of drawing commands from the source Graphics object into the calling Graphics object.&lt;/div&gt;&lt;div class="summaryTableDescription" style="color: rgb(51, 51, 51);"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="summaryTableDescription" style="color: rgb(51, 51, 51);"&gt;&lt;span class="Apple-style-span" style="color: rgb(0, 0, 0);"&gt;&lt;div class="summarySignature" style="text-indent: -20px; padding-left: 20px;"&gt;&lt;a href="http://livedocs.adobe.com/flex/3/langref/flash/display/Graphics.html#lineBitmapStyle%28%29" class="signatureLink" style="font-weight: bold; color: rgb(0, 0, 204); text-decoration: none;"&gt;lineBitmapStyle&lt;/a&gt;(bitmap:&lt;a href="http://livedocs.adobe.com/flex/3/langref/flash/display/BitmapData.html" style="color: rgb(0, 0, 204); text-decoration: none;"&gt;&lt;/a&gt;&lt;a href="http://livedocs.adobe.com/flex/3/langref/flash/display/BitmapData.html" style="color: rgb(0, 0, 204); text-decoration: none;"&gt;BitmapData&lt;/a&gt;, matrix:&lt;a href="http://livedocs.adobe.com/flex/3/langref/flash/geom/Matrix.html" style="color: rgb(0, 0, 204); text-decoration: none;"&gt;&lt;/a&gt;&lt;a href="http://livedocs.adobe.com/flex/3/langref/flash/geom/Matrix.html" style="color: rgb(0, 0, 204); text-decoration: none;"&gt;Matrix&lt;/a&gt; = null, repeat:&lt;a href="http://livedocs.adobe.com/flex/3/langref/Boolean.html" style="color: rgb(0, 0, 204); text-decoration: none;"&gt;&lt;/a&gt;&lt;a href="http://livedocs.adobe.com/flex/3/langref/Boolean.html" style="color: rgb(0, 0, 204); text-decoration: none;"&gt;Boolean&lt;/a&gt; = true, smooth:&lt;a href="http://livedocs.adobe.com/flex/3/langref/Boolean.html" style="color: rgb(0, 0, 204); text-decoration: none;"&gt;&lt;/a&gt;&lt;a href="http://livedocs.adobe.com/flex/3/langref/Boolean.html" style="color: rgb(0, 0, 204); text-decoration: none;"&gt;Boolean&lt;/a&gt; = false):&lt;a href="http://livedocs.adobe.com/flex/3/langref/specialTypes.html#void" style="color: rgb(0, 0, 204); text-decoration: none;"&gt;void&lt;/a&gt;&lt;/div&gt;&lt;div class="summaryTableDescription" style="color: rgb(51, 51, 51);"&gt;Specifies a bitmap to use for the line stroke when drawing lines.&lt;/div&gt;&lt;div class="summaryTableDescription" style="color: rgb(51, 51, 51);"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="summaryTableDescription" style="color: rgb(51, 51, 51);"&gt;&lt;span class="Apple-style-span" style="color: rgb(0, 0, 0);"&gt;&lt;div class="summarySignature" style="text-indent: -20px; padding-left: 20px;"&gt;&lt;a href="http://livedocs.adobe.com/flex/3/langref/flash/display/Graphics.html#drawTriangles%28%29" class="signatureLink" style="font-weight: bold; color: rgb(0, 0, 204); text-decoration: none;"&gt;drawTriangles&lt;/a&gt;(vertices:&lt;a href="http://livedocs.adobe.com/flex/3/langref/Vector.html" style="color: rgb(0, 0, 204); text-decoration: none;"&gt;Vector&lt;/a&gt;.&lt;&lt;a href="http://livedocs.adobe.com/flex/3/langref/Number.html" style="color: rgb(0, 0, 204); text-decoration: none;"&gt;Number&lt;/a&gt;&gt;, indices:&lt;a href="http://livedocs.adobe.com/flex/3/langref/Vector.html" style="color: rgb(0, 0, 204); text-decoration: none;"&gt;Vector&lt;/a&gt;.&lt;&lt;a href="http://livedocs.adobe.com/flex/3/langref/int.html" style="color: rgb(0, 0, 204); text-decoration: none;"&gt;int&lt;/a&gt;&gt; = null, uvtData:&lt;a href="http://livedocs.adobe.com/flex/3/langref/Vector.html" style="color: rgb(0, 0, 204); text-decoration: none;"&gt;Vector&lt;/a&gt;.&lt;&lt;a href="http://livedocs.adobe.com/flex/3/langref/Number.html" style="color: rgb(0, 0, 204); text-decoration: none;"&gt;Number&lt;/a&gt;&gt; = null, culling:&lt;a href="http://livedocs.adobe.com/flex/3/langref/String.html" style="color: rgb(0, 0, 204); text-decoration: none;"&gt;&lt;/a&gt;&lt;a href="http://livedocs.adobe.com/flex/3/langref/String.html" style="color: rgb(0, 0, 204); text-decoration: none;"&gt;String&lt;/a&gt; = "none"):&lt;a href="http://livedocs.adobe.com/flex/3/langref/specialTypes.html#void" style="color: rgb(0, 0, 204); text-decoration: none;"&gt;void&lt;/a&gt;&lt;/div&gt;&lt;div class="summaryTableDescription" style="color: rgb(51, 51, 51);"&gt;Renders a set of triangles, typically to distort bitmaps and give them a three-dimensional appearance.&lt;/div&gt;&lt;div class="summaryTableDescription" style="color: rgb(51, 51, 51);"&gt;&lt;br /&gt;&lt;/div&gt;&lt;/span&gt;&lt;/div&gt;&lt;/span&gt;&lt;/div&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;"繪製命令" 本身也可以被當作物件來操作、管理，那要做 undo 應該就會更容易些。還有像是使用 BitmapData 當作畫線的素材，這也是之前所沒有的。至於繪製三角形組的語法，若是搭配 BitmapData 填圖的話，那就可以用來實作 3D 貼圖的效果。&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;2. Filters and Blend Modes&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;介紹大部分的 Filter 與 Blend Modes，與其他書本類似。&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;會提到類似這篇文章的內容：&lt;a href="http://blog.ben.idv.tw/2008/09/convolutionfilter.html"&gt;http://blog.ben.idv.tw/2008/09/convolutionfilter.html&lt;/a&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;3. Bitmaps and BitmapData&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;談到點陣圖、像素、位元等等的基本知識。加上搭配 ColorTransform 做一些特效變化。&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;4. Advanced Bitmap Manipulation&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;談到 BitmapData.noise()、perlinNoise()、copyChannel()，還有像是數位相機常會提供影像光譜資訊的功能：&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style=";font-family:Tahoma;font-size:13px;"  &gt;&lt;div class="summarySignature" style="text-indent: -20px; padding-left: 20px;"&gt;&lt;a href="http://livedocs.adobe.com/flex/3/langref/flash/display/BitmapData.html#histogram%28%29" class="signatureLink" style="font-weight: bold; color: rgb(0, 0, 204); text-decoration: none;"&gt;histogram&lt;/a&gt;(hRect:&lt;a href="http://livedocs.adobe.com/flex/3/langref/flash/geom/Rectangle.html" style="color: rgb(0, 0, 204); text-decoration: none;"&gt;&lt;/a&gt;&lt;a href="http://livedocs.adobe.com/flex/3/langref/flash/geom/Rectangle.html" style="color: rgb(0, 0, 204); text-decoration: none;"&gt;Rectangle&lt;/a&gt; = null):&lt;a href="http://livedocs.adobe.com/flex/3/langref/Vector.html" style="color: rgb(0, 0, 204); text-decoration: none;"&gt;Vector&lt;/a&gt;.&lt;&lt;a href="http://livedocs.adobe.com/flex/3/langref/__AS3__/vec/Vector.html" style="color: rgb(0, 0, 204); text-decoration: none;"&gt;Vector&lt;/a&gt;&gt;&lt;/div&gt;&lt;div class="summaryTableDescription" style="color: rgb(51, 51, 51);"&gt;Computes a 256-value binary number histogram of a BitmapData object.&lt;/div&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;接著會提到 threshold()，也就是我們會用來做 webcam 動態偵測時所需要的功能：&lt;a href="http://blog.ben.idv.tw/2008/08/webcam.html"&gt;http://blog.ben.idv.tw/2008/08/webcam.html&lt;/a&gt;&lt;/div&gt;&lt;div&gt;甚至可以用來做動態去背的機制。&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;另外也會再多談到幾個 photoshop 中所提供的功能 要如何用 AS3 做到。&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;5. Pixel Bender and Shaders&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;帶過 Pixel Bender Toolkit 的使用，想當然不會離題太遠而提到 Pixel Bender language 的語法，然後接著就是在 AS3 中如何使用 Shader 載入 *.pbj，以及如何在 AS3 中提供 kernel 所需的參數。&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;6. ActionScript in the Third Dimension&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;很有用的章節，會先將 2.5D 解釋完，然後用一點點簡單的範例說明。&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;談到用 Vector3D、Matrix3D 來對每個 3D 座標作位移、距離計算等等。&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;因為 3D 的 z，跟實際上每個 DisplayObject 被加進 Display List 的順序所造成的 Depth 不同，所以需要 Transform 類別新加的方法來處理以計算每個 3D 的 z 換成 2D 後的大小：&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style=";font-family:Tahoma;font-size:13px;"  &gt;&lt;div class="summarySignature" style="text-indent: -20px; padding-left: 20px;"&gt;&lt;a href="http://livedocs.adobe.com/flex/3/langref/flash/geom/Transform.html#getRelativeMatrix3D%28%29" class="signatureLink" style="font-weight: bold; color: rgb(0, 0, 204); text-decoration: none;"&gt;getRelativeMatrix3D&lt;/a&gt;(relativeTo:&lt;a href="http://livedocs.adobe.com/flex/3/langref/flash/display/DisplayObject.html" style="color: rgb(0, 0, 204); text-decoration: none;"&gt;&lt;/a&gt;&lt;a href="http://livedocs.adobe.com/flex/3/langref/flash/display/DisplayObject.html" style="color: rgb(0, 0, 204); text-decoration: none;"&gt;DisplayObject&lt;/a&gt;):&lt;a href="http://livedocs.adobe.com/flex/3/langref/flash/geom/Matrix3D.html" style="color: rgb(0, 0, 204); text-decoration: none;"&gt;&lt;/a&gt;&lt;a href="http://livedocs.adobe.com/flex/3/langref/flash/geom/Matrix3D.html" style="color: rgb(0, 0, 204); text-decoration: none;"&gt;Matrix3D&lt;/a&gt;&lt;/div&gt;&lt;div class="summaryTableDescription" style="color: rgb(51, 51, 51);"&gt;Returns a Matrix3D object, which can transform the space of a specified display object in relation to the current display object's space.&lt;/div&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;然後再進行排序，以決定重新加入 Display List 的順序。&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;最後會提到以 BitmapData 進行 3D 貼圖的做法，也會用到 drawTriangles() 來完成。&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;這章節，提到不少小型 3D Engine 原理。&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;7. Using an Animation and Effect Library&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;使用以下兩組 library：&lt;/div&gt;&lt;div&gt;&lt;a href="http://code.google.com/p/aeon-animation/"&gt;http://code.google.com/p/aeon-animation/&lt;/a&gt;&lt;/div&gt;&lt;div&gt;&lt;a href="http://code.google.com/p/aether-effects/"&gt;http://code.google.com/p/aether-effects/&lt;/a&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;比較特別的是，他有支援複合式動畫、特效的機制，使用了 Composite 設計模式，可用來製作連續動畫，將多個動畫組合起來做 連續 或 同時 播放。&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;以下章節還沒閱讀到，不過相信也會很精彩&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;8. Elemental Animation Effects&lt;/div&gt;&lt;div&gt;9. Text Effects&lt;/div&gt;&lt;div&gt;10. Video Effects&lt;/div&gt;&lt;div&gt;11. Sound Visualization Effects&lt;/div&gt;&lt;div&gt;12. Interactive Effects&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;非常值得推薦給需要做影像處理、特效的開發者閱讀，或是一些網路活動要針對 webcam 拍照後做特效的機制，也都可以參考本書的範例程式。&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;最後，補充一點，以上我貼的語法說明，是從 adobe 官網貼來的，若你手邊的 Help 檔是 Flash CS3 的話，那是不夠的，因為只支援到 Flash Player 9，一定要找有支援到 Flash Player 10 的新版 Help 才行，譬如 Flex 3.3 的 Help：&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;a href="http://livedocs.adobe.com/flex/3/langref/"&gt;http://livedocs.adobe.com/flex/3/langref/&lt;/a&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4754237190569973724-584481283385808013?l=blog.ben.idv.tw' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.ben.idv.tw/feeds/584481283385808013/comments/default' title='張貼意見'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4754237190569973724&amp;postID=584481283385808013' title='8 個意見'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4754237190569973724/posts/default/584481283385808013'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4754237190569973724/posts/default/584481283385808013'/><link rel='alternate' type='text/html' href='http://blog.ben.idv.tw/2009/08/actionscript-30-image-effects.html' title='ActionScript 3.0 Image Effects'/><author><name>Ben Chang</name><uri>http://www.blogger.com/profile/01921640246111819069</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/_HsFEtLMw5zU/SnvhuYaaRFI/AAAAAAAALNg/iuC8dXCdiCc/s72-c/1430218711.jpg' height='72' width='72'/><thr:total>8</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4754237190569973724.post-6474460168853250540</id><published>2009-08-06T16:22:00.006+08:00</published><updated>2011-08-02T16:13:11.973+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='AS3'/><category scheme='http://www.blogger.com/atom/ns#' term='Flash'/><category scheme='http://www.blogger.com/atom/ns#' term='pureMVC'/><title type='text'>初探 pureMVC</title><content type='html'>最近突然感覺身邊的人都在談 pureMVC，這個 framework 的目的是為了讓我們的程式功能切分乾淨：&lt;br /&gt;&lt;br /&gt;Model 儲存資料&lt;br /&gt;View 視覺、畫面&lt;br /&gt;Controller 邏輯、流程控制&lt;br /&gt;&lt;br /&gt;配合這三個基本元素，有著以下三個負責 "做事情" 的傢伙：&lt;br /&gt;&lt;br /&gt;Proxy 負責存取 Model 的資料、取得外部資料...等&lt;br /&gt;Mediator 負責對 View 作改變，以及監聽 View 的事件&lt;br /&gt;Command 在 Controller 中的角色，是實作你商業邏輯的地方&lt;br /&gt;&lt;br /&gt;而要讓這三方能 "認識" 彼此，就靠唯一的 Facade；若想要 "通知" 彼此的話，就必須送出 Notification，會由有興趣的人 收到通知後 進行後續的工作。&lt;br /&gt;&lt;br /&gt;以上的概念，只要認識下面這張圖就可以了：&lt;br /&gt;&lt;br /&gt;&lt;a target="_blank" onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_HsFEtLMw5zU/SnqZGE1X65I/AAAAAAAALNY/vHJs5eR4Zdw/s1600-h/Clipboard01.jpg"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 400px; height: 352px;" src="http://4.bp.blogspot.com/_HsFEtLMw5zU/SnqZGE1X65I/AAAAAAAALNY/vHJs5eR4Zdw/s400/Clipboard01.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5366770235621239698" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;先對每個角色的 "位置" 有個瞭解，至於它們之間的那些 "箭頭" 表示著互通有無的關係，那就看不同的專案、每個人的經驗，來決定實務上的作法(誰可以與誰有互動)，當然最好是越單純越好，別因為大家都可以透過 Facade 取得彼此而亂來。&lt;br /&gt;&lt;br /&gt;以下，我作一個超陽春簡單的範例：&lt;br /&gt;&lt;br /&gt;pureMVC_Test1.as&lt;br /&gt;&lt;br /&gt;程式進入點，在這個程式中，我進行 UI 的建立，若是你的 UI 是 Flash(*.fla) 製作，或是 Flex Builder(*.mxml) 的話，就不用像我這樣寫一堆瑣碎的程式碼。&lt;br /&gt;&lt;br /&gt;取得 ApplicationFacade 後，透過 init() 開始進行一連串的工作。&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;package {&lt;br /&gt; import flash.display.SimpleButton;&lt;br /&gt; import flash.display.Sprite;&lt;br /&gt; import flash.text.TextField;&lt;br /&gt; import flash.text.TextFieldType;&lt;br /&gt; &lt;br /&gt; import idv.ben.test1.ApplicationFacade;&lt;br /&gt;&lt;br /&gt; public class pureMVC_Test1 extends Sprite&lt;br /&gt; {&lt;br /&gt;  public var txtSearch:TextField; //輸入搜尋字串的文字欄位&lt;br /&gt;  public var btnSearch:SimpleButton; //搜尋按鈕&lt;br /&gt;  public var txtResult:TextField; //顯示搜尋結果的文字欄位&lt;br /&gt;  &lt;br /&gt;  public function pureMVC_Test1()&lt;br /&gt;  {&lt;br /&gt;   //初始化 UI&lt;br /&gt;   initComponents();&lt;br /&gt;   &lt;br /&gt;   //開始叫 pureMVC 工作了&lt;br /&gt;   ApplicationFacade.getInstance().init(this);&lt;br /&gt;  }&lt;br /&gt;  &lt;br /&gt;  /**&lt;br /&gt;   * 本範例的 UI 完全由程式產生，所以以下會有比較瑣碎的 UI 建立&lt;br /&gt;   * &lt;br /&gt;   */  &lt;br /&gt;  private function initComponents():void{&lt;br /&gt;   txtSearch = new TextField();&lt;br /&gt;   txtSearch.type = TextFieldType.INPUT;&lt;br /&gt;   txtSearch.border = true;&lt;br /&gt;   txtSearch.x = 100;&lt;br /&gt;   txtSearch.y = 50;&lt;br /&gt;   txtSearch.width = 200;&lt;br /&gt;   txtSearch.height = 20;&lt;br /&gt;   this.addChild(txtSearch);&lt;br /&gt;   &lt;br /&gt;   var spriteBtn:Sprite = new Sprite();&lt;br /&gt;   spriteBtn.graphics.beginFill(0x999999);&lt;br /&gt;   spriteBtn.graphics.drawRect(0, 0, 100, 20);&lt;br /&gt;   spriteBtn.graphics.endFill();&lt;br /&gt;   var txtBtn:TextField = new TextField();&lt;br /&gt;   txtBtn.text = "SEARCH";&lt;br /&gt;   txtBtn.width = 100;&lt;br /&gt;   txtBtn.height = 20;&lt;br /&gt;   spriteBtn.addChild(txtBtn);&lt;br /&gt;   btnSearch = new SimpleButton(spriteBtn, spriteBtn, spriteBtn, spriteBtn);&lt;br /&gt;   btnSearch.x = 100;&lt;br /&gt;   btnSearch.y = 100;&lt;br /&gt;   this.addChild(btnSearch);&lt;br /&gt;   &lt;br /&gt;   txtResult = new TextField();&lt;br /&gt;   txtResult.type = TextFieldType.DYNAMIC;&lt;br /&gt;   txtResult.border = true;&lt;br /&gt;   txtResult.x = 100;&lt;br /&gt;   txtResult.y = 150;&lt;br /&gt;   txtResult.width = 200;&lt;br /&gt;   txtResult.height = 20;&lt;br /&gt;   this.addChild(txtResult);&lt;br /&gt;  }&lt;br /&gt; }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;ApplicationFacade.as&lt;br /&gt;&lt;br /&gt;定義了一堆 Notification 名稱。&lt;br /&gt;&lt;br /&gt;註冊第一個 Command，以及送出 Notification 以觸發該 Command 執行。(其實背後還包含了 Facade 去 View 中，用 Notification 找是否有對應的 Observer，才找到事先註冊的 Command)&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;package idv.ben.test1&lt;br /&gt;{&lt;br /&gt; import idv.ben.test1.controller.InitCommand;&lt;br /&gt; &lt;br /&gt; import org.puremvc.as3.interfaces.IFacade;&lt;br /&gt; import org.puremvc.as3.patterns.facade.Facade;&lt;br /&gt;&lt;br /&gt; public class ApplicationFacade extends Facade implements IFacade&lt;br /&gt; {&lt;br /&gt;  static public const NOTIFICATION_INIT:String = "NOTIFICATION_INIT";&lt;br /&gt;  static public const NOTIFICATION_INITED:String = "NOTIFICATION_INITED";&lt;br /&gt;  &lt;br /&gt;  static public const NOTIFICATION_SEARCH:String = "NOTIFICATION_SEARCH";&lt;br /&gt;  static public const NOTIFICATION_RESULT:String = "NOTIFICATION_RESULT";&lt;br /&gt;  &lt;br /&gt;  static public function getInstance():ApplicationFacade{&lt;br /&gt;   if(instance==null)&lt;br /&gt;    instance = new ApplicationFacade();&lt;br /&gt;   return ApplicationFacade(instance);&lt;br /&gt;  }&lt;br /&gt;  &lt;br /&gt;  /**&lt;br /&gt;   * 當建立 Facade 過程中，要取得 Controller 時，會有機會讓開發者可以定義一些有的沒的&lt;br /&gt;   * &lt;br /&gt;   */  &lt;br /&gt;  override protected function initializeController():void{&lt;br /&gt;   super.initializeController();&lt;br /&gt;   &lt;br /&gt;   //註冊 當 NOTIFICATION_INIT 發生時，由 InitCommand 類別來處理&lt;br /&gt;   this.registerCommand(NOTIFICATION_INIT, InitCommand);&lt;br /&gt;  }&lt;br /&gt;  &lt;br /&gt;  /**&lt;br /&gt;   * 開始工作&lt;br /&gt;   * @param app&lt;br /&gt;   * &lt;br /&gt;   */  &lt;br /&gt;  public function init(app:pureMVC_Test1):void{&lt;br /&gt;   //通知 發生 NOTIFICATION_INIT&lt;br /&gt;   this.sendNotification(NOTIFICATION_INIT, app);&lt;br /&gt;  }&lt;br /&gt; }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;InitCommand.as&lt;br /&gt;&lt;br /&gt;被通知而執行 execute() 後，可以作一些其他初始化的工作，像是設定哪些 View 要由哪些 Mediator 來管理，又有哪些 Notification 可能發生，發生時要由哪個 Command 處理...等等。&lt;br /&gt;&lt;br /&gt;作完後，再送一個 Notification 出來，這裡我用的是 NOTIFICATION_INITED。&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;package idv.ben.test1.controller&lt;br /&gt;{&lt;br /&gt; import idv.ben.test1.ApplicationFacade;&lt;br /&gt; import idv.ben.test1.model.DataProxy;&lt;br /&gt; import idv.ben.test1.view.MainMediator;&lt;br /&gt; &lt;br /&gt; import org.puremvc.as3.interfaces.ICommand;&lt;br /&gt; import org.puremvc.as3.interfaces.INotification;&lt;br /&gt; import org.puremvc.as3.patterns.command.SimpleCommand;&lt;br /&gt;&lt;br /&gt; public class InitCommand extends SimpleCommand implements ICommand&lt;br /&gt; {&lt;br /&gt;  public function InitCommand()&lt;br /&gt;  {&lt;br /&gt;   super();&lt;br /&gt;  }&lt;br /&gt;  &lt;br /&gt;  override public function execute(notification:INotification):void&lt;br /&gt;  {&lt;br /&gt;   //註冊 儲存資料的物件&lt;br /&gt;   this.facade.registerProxy(new DataProxy());&lt;br /&gt;   &lt;br /&gt;   //註冊 指定的UI 是由哪個 Mediator 負責管理&lt;br /&gt;   var app:pureMVC_Test1 = pureMVC_Test1(notification.getBody());&lt;br /&gt;   this.facade.registerMediator(new MainMediator(app));&lt;br /&gt;   &lt;br /&gt;   //註冊 當 NOTIFICATION_SEARCH 發生時，由 SearchCommand 類別來處理&lt;br /&gt;   this.facade.registerCommand(ApplicationFacade.NOTIFICATION_SEARCH, SearchCommand);&lt;br /&gt;   &lt;br /&gt;   //通知 發生 NOTIFICATION_INITED&lt;br /&gt;   this.facade.sendNotification(ApplicationFacade.NOTIFICATION_INITED);&lt;br /&gt;  }&lt;br /&gt;  &lt;br /&gt; }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;若是你這時候發現，在 InitCommand 中，沒有看到我註冊負責處理 NOTIFICATION_INITED 這個 Notification 的 Command，在 ApplicationFacade 中也沒，那是誰會做對應的動作？那就繼續來看看 MainMediator.as 吧！&lt;br /&gt;&lt;br /&gt;MainMediator.as&lt;br /&gt;&lt;br /&gt;會 override listNotificationInterests()，目的是當他被註冊時，會要告訴 View 自己關心哪些 Notification，這樣一來當 View 要分派 Notification 時就會通知道這個 Mediator 了。&lt;br /&gt;&lt;br /&gt;於是在 handleNotification() 中，就可以收到 NOTIFICATION_INITED 並進行一些作業。這裡我會進行畫面 UI 元素的事件監聽程式，當按下搜尋按鈕時要送出 NOTIFICATION_SEARCH 通知，將欲搜尋的關鍵字一同送出。&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;package idv.ben.test1.view&lt;br /&gt;{&lt;br /&gt; import flash.events.MouseEvent;&lt;br /&gt; &lt;br /&gt; import idv.ben.test1.ApplicationFacade;&lt;br /&gt; import idv.ben.test1.model.DataProxy;&lt;br /&gt; &lt;br /&gt; import org.puremvc.as3.interfaces.IMediator;&lt;br /&gt; import org.puremvc.as3.interfaces.INotification;&lt;br /&gt; import org.puremvc.as3.patterns.mediator.Mediator;&lt;br /&gt;&lt;br /&gt; public class MainMediator extends Mediator implements IMediator&lt;br /&gt; {&lt;br /&gt;  static private const MEDIATOR_NAME:String = "MainMediator";&lt;br /&gt;  &lt;br /&gt;  private var dataProxy:DataProxy;&lt;br /&gt;  &lt;br /&gt;  private function get app():pureMVC_Test1{&lt;br /&gt;   return pureMVC_Test1(this.viewComponent);&lt;br /&gt;  }&lt;br /&gt;  &lt;br /&gt;  public function MainMediator(viewComponent:Object=null)&lt;br /&gt;  {&lt;br /&gt;   super(MEDIATOR_NAME, viewComponent);&lt;br /&gt;   &lt;br /&gt;   //記住負責儲存資料的物件是誰&lt;br /&gt;   dataProxy = DataProxy(this.facade.retrieveProxy(DataProxy.PROXY_NAME));&lt;br /&gt;  }&lt;br /&gt;  &lt;br /&gt;  /**&lt;br /&gt;   * 此 Mediator 關心哪些 Notification&lt;br /&gt;   * @return &lt;br /&gt;   * &lt;br /&gt;   */  &lt;br /&gt;  override public function listNotificationInterests():Array{&lt;br /&gt;   return [ApplicationFacade.NOTIFICATION_INITED&lt;br /&gt;     , ApplicationFacade.NOTIFICATION_RESULT];&lt;br /&gt;  }&lt;br /&gt;  &lt;br /&gt;  /**&lt;br /&gt;   * 當此 Mediator 關心的 Notification 發生時，分別要做哪些工作&lt;br /&gt;   * @param notification&lt;br /&gt;   * &lt;br /&gt;   */  &lt;br /&gt;  override public function handleNotification(notification:INotification):void{&lt;br /&gt;   switch(notification.getName()){&lt;br /&gt;    case ApplicationFacade.NOTIFICATION_INITED:&lt;br /&gt;     onNotify_inited(notification);&lt;br /&gt;     break;&lt;br /&gt;    case ApplicationFacade.NOTIFICATION_RESULT:&lt;br /&gt;     onNotify_result(notification);&lt;br /&gt;     break;&lt;br /&gt;   }&lt;br /&gt;  }&lt;br /&gt;  &lt;br /&gt;  /**&lt;br /&gt;   * Facade 初始化完成時&lt;br /&gt;   * &lt;br /&gt;   */  &lt;br /&gt;  private function onNotify_inited(notification:INotification):void{&lt;br /&gt;   setListener(true);&lt;br /&gt;  }&lt;br /&gt;  &lt;br /&gt;  /**&lt;br /&gt;   * 搜尋得到結果時&lt;br /&gt;   * &lt;br /&gt;   */  &lt;br /&gt;  private function onNotify_result(notification:INotification):void{&lt;br /&gt;   //從 Notification 中取得搜尋結果&lt;br /&gt;   app.txtResult.text = notification.getBody()["result"];&lt;br /&gt;  }&lt;br /&gt;  &lt;br /&gt;  /**&lt;br /&gt;   * 設定UI的事件處理&lt;br /&gt;   * @param tf&lt;br /&gt;   * &lt;br /&gt;   */  &lt;br /&gt;  private function setListener(tf:Boolean):void{&lt;br /&gt;   if(tf){&lt;br /&gt;    app.btnSearch.addEventListener(MouseEvent.CLICK, onBtnSearchClick);&lt;br /&gt;   }else{&lt;br /&gt;    app.btnSearch.removeEventListener(MouseEvent.CLICK, onBtnSearchClick);&lt;br /&gt;   }&lt;br /&gt;  }&lt;br /&gt;  &lt;br /&gt;  /**&lt;br /&gt;   * 按下搜尋按鈕時&lt;br /&gt;   * @param e&lt;br /&gt;   * &lt;br /&gt;   */  &lt;br /&gt;  private function onBtnSearchClick(e:MouseEvent):void{&lt;br /&gt;   var body:Object = {};&lt;br /&gt;   body["keyword"] = app.txtSearch.text;&lt;br /&gt;   &lt;br /&gt;   //通知 發生 NOTIFICATION_SEARCH，並且將搜尋字串夾帶在 Notification 中&lt;br /&gt;   this.facade.sendNotification(ApplicationFacade.NOTIFICATION_SEARCH, body);&lt;br /&gt;  }&lt;br /&gt;  &lt;br /&gt; }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;回頭看看 InitCommand 中所設定的，當 NOTIFICATION_SEARCH 發生時，會由 SearchCommand 來負責處理。&lt;br /&gt;&lt;br /&gt;SearchCommand.as&lt;br /&gt;&lt;br /&gt;負責請 DataProxy 進行資料存取，不管該資料是來自內部或外部，反正 DataProxy 會負責搞定。&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;package idv.ben.test1.controller&lt;br /&gt;{&lt;br /&gt; import idv.ben.test1.model.DataProxy;&lt;br /&gt; &lt;br /&gt; import org.puremvc.as3.interfaces.ICommand;&lt;br /&gt; import org.puremvc.as3.interfaces.INotification;&lt;br /&gt; import org.puremvc.as3.patterns.command.SimpleCommand;&lt;br /&gt;&lt;br /&gt; public class SearchCommand extends SimpleCommand implements ICommand&lt;br /&gt; {&lt;br /&gt;  public function SearchCommand()&lt;br /&gt;  {&lt;br /&gt;   super();&lt;br /&gt;  }&lt;br /&gt;  &lt;br /&gt;  override public function execute(notification:INotification):void&lt;br /&gt;  {&lt;br /&gt;   //由 Notification 中可以取得搜尋字串&lt;br /&gt;   var searchString:String = notification.getBody()["keyword"];&lt;br /&gt;   &lt;br /&gt;   //開始搜尋&lt;br /&gt;   search(searchString);&lt;br /&gt;  }&lt;br /&gt;  &lt;br /&gt;  private function search(searchString:String):void{&lt;br /&gt;   &lt;br /&gt;   //透過 DataProxy 進行查詢&lt;br /&gt;   var dataProxy:DataProxy = DataProxy(this.facade.retrieveProxy(DataProxy.PROXY_NAME));&lt;br /&gt;   dataProxy.search(searchString);&lt;br /&gt;  }&lt;br /&gt; }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;DataProxy.as&lt;br /&gt;&lt;br /&gt;可針對寫在程式碼中的資料作一些存取，或是向外部資源要求資料。這裡我為了測試方便，直接模擬查詢結果是現在時刻的字串。&lt;br /&gt;&lt;br /&gt;通知 NOTIFICATION_RESULT 發生。&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;package idv.ben.test1.model&lt;br /&gt;{&lt;br /&gt; import idv.ben.test1.ApplicationFacade;&lt;br /&gt; &lt;br /&gt; import org.puremvc.as3.interfaces.IProxy;&lt;br /&gt; import org.puremvc.as3.patterns.proxy.Proxy;&lt;br /&gt;&lt;br /&gt; public class DataProxy extends Proxy implements IProxy&lt;br /&gt; {&lt;br /&gt;  static public const PROXY_NAME:String = "DataProxy";&lt;br /&gt;  &lt;br /&gt;  public function DataProxy()&lt;br /&gt;  {&lt;br /&gt;   super(PROXY_NAME, "");&lt;br /&gt;  }&lt;br /&gt;  &lt;br /&gt;  public function search(searchString:String):void{&lt;br /&gt;   //假設搜尋結果是此刻時間&lt;br /&gt;   var result:String = (new Date()).toString();&lt;br /&gt;   &lt;br /&gt;   //通知 發生 NOTIFICATION_RESULT&lt;br /&gt;   var body:Object = {};&lt;br /&gt;   body["result"] = result;&lt;br /&gt;   &lt;br /&gt;   this.facade.sendNotification(ApplicationFacade.NOTIFICATION_RESULT, body);&lt;br /&gt;  }&lt;br /&gt;  &lt;br /&gt;  &lt;br /&gt; }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;DataProxy 只負責資料存取，不用理會查到的資料要給誰用。&lt;br /&gt;&lt;br /&gt;這時候我們可以回到 MainMediator 看看 listNotificationInterests() 中，MainMediator  對 NOTIFICATION_RESULT 也有興趣，所以 View 就會通知 MainMediator 更新畫面。&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;以上，總之，每個角色只顧好自己的工作，然後通知 Facade 發生了哪些 Notification，之後自然會有事先註冊好的 Command 或 Mediator 會去執行作業。&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4754237190569973724-6474460168853250540?l=blog.ben.idv.tw' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.ben.idv.tw/feeds/6474460168853250540/comments/default' title='張貼意見'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4754237190569973724&amp;postID=6474460168853250540' title='5 個意見'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4754237190569973724/posts/default/6474460168853250540'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4754237190569973724/posts/default/6474460168853250540'/><link rel='alternate' type='text/html' href='http://blog.ben.idv.tw/2009/08/puremvc.html' title='初探 pureMVC'/><author><name>Ben Chang</name><uri>http://www.blogger.com/profile/01921640246111819069</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_HsFEtLMw5zU/SnqZGE1X65I/AAAAAAAALNY/vHJs5eR4Zdw/s72-c/Clipboard01.jpg' height='72' width='72'/><thr:total>5</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4754237190569973724.post-2769416998643776495</id><published>2009-06-22T16:31:00.003+08:00</published><updated>2009-06-22T16:48:07.407+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Flash Player'/><category scheme='http://www.blogger.com/atom/ns#' term='AS3'/><category scheme='http://www.blogger.com/atom/ns#' term='Flash'/><title type='text'>TypeError: Error #1007: 嘗試個體化非建構函式。</title><content type='html'>前兩天遇到一個非常詭異的錯誤訊息：&lt;br /&gt;&lt;br /&gt;"TypeError: Error #1007: 嘗試個體化非建構函式。"&lt;br /&gt;&lt;br /&gt;若用 google 去查的話，可以找到一堆與 Document Class 相關的議題，不過這次我遇到的可不是那樣的問題。事實上，我遇到的問題正如他的錯誤訊息一樣的清楚，只不過難以發覺。&lt;br /&gt;&lt;br /&gt;以下，我先準備一個我簡化過的問題案例：&lt;br /&gt;&lt;br /&gt;Test.fla 的 Document Class 為 Test.as&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;package{&lt;br /&gt; import flash.display.MovieClip;&lt;br /&gt;&lt;br /&gt; import a.Vector;&lt;br /&gt; &lt;br /&gt; public class Test extends MovieClip{&lt;br /&gt;  &lt;br /&gt;  var v:Vector = new Vector();&lt;br /&gt;  &lt;br /&gt;  public function Test(){&lt;br /&gt;   &lt;br /&gt;   trace(123, v);&lt;br /&gt;   &lt;br /&gt;   }&lt;br /&gt;  &lt;br /&gt;  }&lt;br /&gt; &lt;br /&gt; }&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;在這個 Test.as 中，有用到一個 package a 下的 Vector 類別：&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;package a{&lt;br /&gt; public class Vector{&lt;br /&gt;  public function Vector(){&lt;br /&gt;   trace("Vector!!");&lt;br /&gt;   }&lt;br /&gt;  }&lt;br /&gt; }&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;這個案例，若是發佈成 Flash Player 9 的話，一點問題也沒有，但若是發佈成 Flash Player 10 的話，就會出現錯誤訊息：&lt;br /&gt;&lt;br /&gt;TypeError: Error #1007: 嘗試個體化非建構函式。&lt;br /&gt; at Test()&lt;br /&gt;&lt;br /&gt;我查了許久後，才發現問題出在那個 a.Vector，因為在 Flash Player 10 還沒推出時，Flash Player 還沒有內建 Vector 類別，所以當我們寫 var v:Vector = new Vector(); 時，可以由 import a.Vector (或 import a.*) 中找到這個 Vector 類別。可是到了 Flash Player 10 之後，會先找到的是全域類別物件 Vector，就像 String、Number 一樣，而不是我們自訂的 a.Vector 類別。&lt;br /&gt;&lt;br /&gt;然而因為 Flash Player 10 新具備的 Vector 類別並不具有 "不帶參數的建構式"，所以就會出現 "嘗試個體化非建構函式" 的錯誤訊息啦！&lt;br /&gt;&lt;br /&gt;如果你們家的 Flash 程式，你或前人也有從不知道哪裡找來的 Vector 類別的話，或是任何改寫自其他程式語言 (Java) 的常用類別的話，未來都很有可能遇到這種同名的衝突問題。&lt;br /&gt;&lt;br /&gt;解決方法一，將 Test.as 改寫成：&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;package{&lt;br /&gt; import flash.display.MovieClip;&lt;br /&gt;&lt;br /&gt; import a.Vector;&lt;br /&gt; &lt;br /&gt; public class Test extends MovieClip{&lt;br /&gt;  &lt;br /&gt;  var v:a.Vector = new a.Vector();&lt;br /&gt;  &lt;br /&gt;  public function Test(){&lt;br /&gt;   &lt;br /&gt;   trace(123, v);&lt;br /&gt;   &lt;br /&gt;   }&lt;br /&gt;  &lt;br /&gt;  }&lt;br /&gt; &lt;br /&gt; }&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;使用自訂的 Vector 類別時，請明確指出完整路徑 var v:a.Vector = new a.Vector(); 即可。&lt;br /&gt;&lt;br /&gt;解決方法二，將自訂的 Vector 類別重構一下，改名ㄅㄟ，反正現在的開發工具都很方便，重構時會協助你將所有已經使用到的程式碼都一起更新，除非你是使用 "字串轉類別" 的作法。&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4754237190569973724-2769416998643776495?l=blog.ben.idv.tw' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.ben.idv.tw/feeds/2769416998643776495/comments/default' title='張貼意見'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4754237190569973724&amp;postID=2769416998643776495' title='2 個意見'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4754237190569973724/posts/default/2769416998643776495'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4754237190569973724/posts/default/2769416998643776495'/><link rel='alternate' type='text/html' href='http://blog.ben.idv.tw/2009/06/typeerror-error-1007.html' title='TypeError: Error #1007: 嘗試個體化非建構函式。'/><author><name>Ben Chang</name><uri>http://www.blogger.com/profile/01921640246111819069</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4754237190569973724.post-6793602724382744903</id><published>2009-06-18T21:52:00.007+08:00</published><updated>2011-08-02T16:23:28.527+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Security'/><category scheme='http://www.blogger.com/atom/ns#' term='BitmapData'/><category scheme='http://www.blogger.com/atom/ns#' term='AS3'/><category scheme='http://www.blogger.com/atom/ns#' term='Flash'/><title type='text'>將文字隱藏在圖片中</title><content type='html'>這兩天在研究如何將文字資訊隱藏在圖片中的技術，在 google 查了一些 "secure image sharing" 的資料，但是都沒有看到實作的方法(其實是沒有看到範例程式碼)，最後，我參考 Wiki 上關於 Steganography 的介紹：&lt;br /&gt;&lt;br /&gt;http://en.wikipedia.org/wiki/Steganography&lt;br /&gt;&lt;br /&gt;寫了以下的類別：&lt;br /&gt;&lt;br /&gt;Steganography.as&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;package idv.ben.steganography&lt;br /&gt;{&lt;br /&gt; import flash.display.BitmapData;&lt;br /&gt; import flash.geom.Point;&lt;br /&gt; &lt;br /&gt; public class Steganography&lt;br /&gt; {&lt;br /&gt;  static private var __instance:Steganography;&lt;br /&gt;  static public function getInstance():Steganography{&lt;br /&gt;   if(__instance==null)&lt;br /&gt;    __instance = new Steganography();&lt;br /&gt;   return __instance;&lt;br /&gt;  }&lt;br /&gt;  &lt;br /&gt;  private var __totalWidth:int;&lt;br /&gt;  private var __totalHeight:int;&lt;br /&gt;  private var __point:Point;&lt;br /&gt;  &lt;br /&gt;  public function Steganography()&lt;br /&gt;  {&lt;br /&gt;   if(__instance!=null)&lt;br /&gt;    throw new Error("plz use Steganography.getInstance()");&lt;br /&gt;  }&lt;br /&gt;  &lt;br /&gt;  public function encode(oBD:BitmapData, txt:String):BitmapData{&lt;br /&gt;   var txtLen:int = txt.length;&lt;br /&gt;   var txtLenLen:int = String(txtLen).length;&lt;br /&gt;   &lt;br /&gt;   if(oBD.width * oBD.height &amp;lt; txtLen + 10)&lt;br /&gt;    return null;&lt;br /&gt;   &lt;br /&gt;   var newBD:BitmapData = oBD.clone();&lt;br /&gt;   __totalWidth = newBD.width;&lt;br /&gt;   __totalHeight = newBD.height;&lt;br /&gt;   __point = null;&lt;br /&gt;   &lt;br /&gt;   var c:String;&lt;br /&gt;   var p:Point;&lt;br /&gt;   var newPixel:uint;&lt;br /&gt;   &lt;br /&gt;   //txtLenLen&lt;br /&gt;   c = String(txtLenLen);&lt;br /&gt;   p = getNextPoint();&lt;br /&gt;   newPixel = putCharIntoPixel(c, oBD.getPixel(p.x, p.y));&lt;br /&gt;   newBD.setPixel(p.x, p.y, newPixel);&lt;br /&gt;   &lt;br /&gt;   //txtLen&lt;br /&gt;   for(var i:int=0; i&amp;lt;txtLenLen; i++){&lt;br /&gt;    c = String(txtLen).substr(i, 1);&lt;br /&gt;    p = getNextPoint();&lt;br /&gt;    newPixel = putCharIntoPixel(c, oBD.getPixel(p.x, p.y));&lt;br /&gt;    newBD.setPixel(p.x, p.y, newPixel);&lt;br /&gt;   }&lt;br /&gt;   &lt;br /&gt;   //txt&lt;br /&gt;   for(var j:int=0; j&amp;lt;txtLen; j++){&lt;br /&gt;    c = txt.substr(j, 1);&lt;br /&gt;    p = getNextPoint();&lt;br /&gt;    newPixel = putCharIntoPixel(c, oBD.getPixel(p.x, p.y));&lt;br /&gt;    newBD.setPixel(p.x, p.y, newPixel);&lt;br /&gt;   }&lt;br /&gt;   &lt;br /&gt;   return newBD;&lt;br /&gt;  }&lt;br /&gt;  &lt;br /&gt;  public function decode(bd:BitmapData):String{&lt;br /&gt;   __totalWidth = bd.width;&lt;br /&gt;   __totalHeight = bd.height;&lt;br /&gt;   __point = null;&lt;br /&gt;   &lt;br /&gt;   var txtLenLen:int;&lt;br /&gt;   var txtLen:int&lt;br /&gt;   var txt:String = "";&lt;br /&gt;   &lt;br /&gt;   var p:Point;&lt;br /&gt;   var c:String;&lt;br /&gt;   &lt;br /&gt;   //txtLenLen&lt;br /&gt;   if(bd.width * bd.height &amp;lt;= 0)return "";&lt;br /&gt;   p = getNextPoint();&lt;br /&gt;   c = getCharFromPixel(bd.getPixel(p.x, p.y));&lt;br /&gt;   txtLenLen = int(c);&lt;br /&gt;   &lt;br /&gt;   //txtLen&lt;br /&gt;   if(bd.width * bd.height &amp;lt;= (1 + txtLenLen))return "";&lt;br /&gt;   var strTxtLen:String = "";&lt;br /&gt;   for(var i:int=0; i&amp;lt;txtLenLen; i++){&lt;br /&gt;    p = getNextPoint();&lt;br /&gt;    c = getCharFromPixel(bd.getPixel(p.x, p.y));&lt;br /&gt;    strTxtLen += c;&lt;br /&gt;   }&lt;br /&gt;   txtLen = int(strTxtLen);&lt;br /&gt;   &lt;br /&gt;   //txt&lt;br /&gt;   if(bd.width * bd.height &amp;lt;= (1 + txtLenLen + txtLen))return "";&lt;br /&gt;   for(var j:int=0; j&amp;lt;txtLen; j++){&lt;br /&gt;    p = getNextPoint();&lt;br /&gt;    c = getCharFromPixel(bd.getPixel(p.x, p.y));&lt;br /&gt;    txt += c;&lt;br /&gt;   }&lt;br /&gt;   &lt;br /&gt;   return txt;&lt;br /&gt;  }&lt;br /&gt;  &lt;br /&gt;  private function getNextPoint():Point{&lt;br /&gt;   if(__point==null){&lt;br /&gt;    __point = new Point(0, 0);&lt;br /&gt;   }else{&lt;br /&gt;    if(__point.x &amp;lt; __totalWidth-1){&lt;br /&gt;     __point.x++;&lt;br /&gt;    }else{&lt;br /&gt;     __point.x = 0;&lt;br /&gt;     __point.y++;&lt;br /&gt;    }&lt;br /&gt;   }&lt;br /&gt;   return __point;&lt;br /&gt;  }&lt;br /&gt;  &lt;br /&gt;  private function putCharIntoPixel(char:String, oPixel:uint):uint{&lt;br /&gt;   var r:uint = (oPixel &amp;gt;&amp;gt; 16) &amp; 255;&lt;br /&gt;   var g:uint = (oPixel &amp;gt;&amp;gt; 8) &amp; 255;&lt;br /&gt;   var b:uint = (oPixel &amp;gt;&amp;gt; 0) &amp; 255;&lt;br /&gt;   &lt;br /&gt;   var charCode:String = String(char.charCodeAt(0));&lt;br /&gt;   while(charCode.length&amp;lt;3)&lt;br /&gt;    charCode = "0" + charCode;&lt;br /&gt;    &lt;br /&gt;   var dr:uint = uint(charCode.substr(0, 1));&lt;br /&gt;   var dg:uint = uint(charCode.substr(1, 1));&lt;br /&gt;   var db:uint = uint(charCode.substr(2, 1));&lt;br /&gt;   &lt;br /&gt;   var r2:uint = ((r &amp;gt;&amp;gt; 4) &amp;lt;&amp;lt; 4) | dr;&lt;br /&gt;   var g2:uint = ((g &amp;gt;&amp;gt; 4) &amp;lt;&amp;lt; 4) | dg;&lt;br /&gt;   var b2:uint = ((b &amp;gt;&amp;gt; 4) &amp;lt;&amp;lt; 4) | db;&lt;br /&gt;   &lt;br /&gt;   return r2 &amp;lt;&amp;lt; 16 | g2 &amp;lt;&amp;lt; 8 | b2;&lt;br /&gt;  }&lt;br /&gt;  &lt;br /&gt;  private function getCharFromPixel(pixel:uint):String{&lt;br /&gt;   var dr:uint = (pixel &amp;gt;&amp;gt; 16) &amp; 15;&lt;br /&gt;   var dg:uint = (pixel &amp;gt;&amp;gt; 8) &amp; 15;&lt;br /&gt;   var db:uint = (pixel &amp;gt;&amp;gt; 0) &amp; 15;&lt;br /&gt;   &lt;br /&gt;   var charCode:String = String(dr) + String(dg) + String(db);&lt;br /&gt;   var char:String = String.fromCharCode(int(charCode));&lt;br /&gt;   return char;&lt;br /&gt;  }&lt;br /&gt; }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;使用範例如下，載入一張圖，並將 "Hello World!!" 的字串給隱藏進去，產生出第二張看似一樣的圖，最後再由第二張圖的 BitmapData 取出該字串。&lt;br /&gt;&lt;br /&gt;SteganographyAS3 .as&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;package {&lt;br /&gt; import flash.display.Bitmap;&lt;br /&gt; import flash.display.BitmapData;&lt;br /&gt; import flash.display.Sprite;&lt;br /&gt; &lt;br /&gt; import idv.ben.steganography.Steganography;&lt;br /&gt;&lt;br /&gt; public class SteganographyAS3 extends Sprite&lt;br /&gt; {&lt;br /&gt;  [Embed(source='../asset/IMG_3641.jpg', mimeType='image/jpeg')]&lt;br /&gt;  public var Img:Class;&lt;br /&gt;  &lt;br /&gt;  public function SteganographyAS3()&lt;br /&gt;  {&lt;br /&gt;   var bmp:Bitmap = new Img() as Bitmap;&lt;br /&gt;   bmp.scaleX = bmp.scaleY = 0.5;&lt;br /&gt;   this.addChild(bmp);&lt;br /&gt;&lt;br /&gt;   var msg:String = "hello world!!";   &lt;br /&gt;   var newBD:BitmapData = Steganography.getInstance().encode(bmp.bitmapData, msg);&lt;br /&gt;   var newBMP:Bitmap = new Bitmap(newBD);&lt;br /&gt;   newBMP.x = bmp.x + bmp.width;&lt;br /&gt;   newBMP.scaleX = newBMP.scaleY = 0.5;&lt;br /&gt;   this.addChild(newBMP);&lt;br /&gt;   &lt;br /&gt;   var msg2:String = Steganography.getInstance().decode(newBMP.bitmapData);&lt;br /&gt;   trace("decode=&amp;gt;", msg2);&lt;br /&gt;  }&lt;br /&gt; }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;執行結果，出現兩張圖，看起來沒甚麼不同，可能要將欲編入的文字資料放多一點，或許可以看到一些像素的不同吧：&lt;br /&gt;&lt;br /&gt;&lt;a target="_blank" href="http://2.bp.blogspot.com/_HsFEtLMw5zU/SjpIGwvWkGI/AAAAAAAAJ_4/a9s1i1TUGBI/s1600-h/Clipboard01.jpg"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 400px; height: 333px;" src="http://2.bp.blogspot.com/_HsFEtLMw5zU/SjpIGwvWkGI/AAAAAAAAJ_4/a9s1i1TUGBI/s400/Clipboard01.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5348666788455813218" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;將第二張圖(右邊)的 BitmapData 中隱藏的資料解出來後，trace 在 Flex Builder 的輸出視窗中：&lt;br /&gt;&lt;br /&gt;&lt;a target="_blank" href="http://3.bp.blogspot.com/_HsFEtLMw5zU/SjpIG1BHyII/AAAAAAAAJ_w/FVwxT0iJY4E/s1600-h/Clipboard02.jpg"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 400px; height: 72px;" src="http://3.bp.blogspot.com/_HsFEtLMw5zU/SjpIG1BHyII/AAAAAAAAJ_w/FVwxT0iJY4E/s400/Clipboard02.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5348666789604083842" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;==============================================================&lt;br /&gt;&lt;br /&gt;[2009-06-19-13-00]&lt;br /&gt;&lt;br /&gt;作了一個範例，完整程式碼：&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;package&lt;br /&gt;{&lt;br /&gt; import com.adobe.images.PNGEncoder;&lt;br /&gt; &lt;br /&gt; import fl.containers.ScrollPane;&lt;br /&gt; import fl.controls.Button;&lt;br /&gt; import fl.controls.TextArea;&lt;br /&gt; &lt;br /&gt; import flash.display.Bitmap;&lt;br /&gt; import flash.display.BitmapData;&lt;br /&gt; import flash.display.Loader;&lt;br /&gt; import flash.display.MovieClip;&lt;br /&gt; import flash.events.Event;&lt;br /&gt; import flash.events.MouseEvent;&lt;br /&gt; import flash.net.FileFilter;&lt;br /&gt; import flash.net.FileReference;&lt;br /&gt; import flash.utils.ByteArray;&lt;br /&gt; import flash.utils.setTimeout;&lt;br /&gt; &lt;br /&gt; import idv.ben.steganography.Steganography;&lt;br /&gt;&lt;br /&gt; public class Demo2 extends MovieClip&lt;br /&gt; {&lt;br /&gt;  public var btnBrowse:Button;&lt;br /&gt;  public var btnEncode:Button;&lt;br /&gt;  public var btnSave:Button;&lt;br /&gt;  public var btnLoad:Button;&lt;br /&gt;  public var btnDecode:Button;&lt;br /&gt;  &lt;br /&gt;  public var spImg:ScrollPane;&lt;br /&gt;  public var spImg2:ScrollPane;&lt;br /&gt;  &lt;br /&gt;  public var txtInput:TextArea;&lt;br /&gt;  public var txtOutput:TextArea;&lt;br /&gt;  &lt;br /&gt;  private var __fileReference:FileReference = new FileReference();&lt;br /&gt;  private var __fileReference2:FileReference = new FileReference();&lt;br /&gt;  &lt;br /&gt;  public function Demo2()&lt;br /&gt;  {&lt;br /&gt;   btnBrowse.addEventListener(MouseEvent.CLICK, onBtnBrowseClick);&lt;br /&gt;   btnEncode.addEventListener(MouseEvent.CLICK, onBtnEncodeClick);&lt;br /&gt;   btnSave.addEventListener(MouseEvent.CLICK, onBtnSaveClick);&lt;br /&gt;   btnLoad.addEventListener(MouseEvent.CLICK, onBtnLoadClick);&lt;br /&gt;   btnDecode.addEventListener(MouseEvent.CLICK, onBtnDecodeClick);&lt;br /&gt;   &lt;br /&gt;   __fileReference.addEventListener(Event.SELECT, onFileReferenceSelect);&lt;br /&gt;   __fileReference.addEventListener(Event.COMPLETE, onFileReferenceComplete);&lt;br /&gt;   &lt;br /&gt;   __fileReference2.addEventListener(Event.SELECT, onFileReference2Select);&lt;br /&gt;   __fileReference2.addEventListener(Event.COMPLETE, onFileReference2Complete);&lt;br /&gt;  }&lt;br /&gt;  &lt;br /&gt;  private function onBtnBrowseClick(e:MouseEvent):void{&lt;br /&gt;   trace("onBtnBrowseClick()");&lt;br /&gt;   &lt;br /&gt;   var typeFilter:Array = [new FileFilter("Images(*.jpg;*.gif;*.png)", "*.jpg;*.gif;*.png")];&lt;br /&gt;   __fileReference.browse(typeFilter);&lt;br /&gt;  }&lt;br /&gt;  &lt;br /&gt;  private function onBtnEncodeClick(e:MouseEvent):void{&lt;br /&gt;   trace("onBtnEncodeClick()");&lt;br /&gt;   &lt;br /&gt;   var bd:BitmapData = getEncodedBitmapData(spImg);&lt;br /&gt;   if(bd == null)&lt;br /&gt;    return;&lt;br /&gt;&lt;br /&gt;   var txt:String = txtInput.text;&lt;br /&gt;   &lt;br /&gt;   if(txt == "")&lt;br /&gt;    return;&lt;br /&gt;   &lt;br /&gt;   var newBD:BitmapData = Steganography.getInstance().encode(bd, txt);&lt;br /&gt;   var newBMP:Bitmap = new Bitmap(newBD);&lt;br /&gt;   spImg2.source = newBMP;&lt;br /&gt;   setTimeout(spImg2.update, 200);&lt;br /&gt;  }&lt;br /&gt;  &lt;br /&gt;  private function onBtnSaveClick(e:MouseEvent):void{&lt;br /&gt;   trace("onBtnSaveClick()");&lt;br /&gt;   &lt;br /&gt;   var bd:BitmapData = getEncodedBitmapData(spImg2);&lt;br /&gt;   if(bd == null)&lt;br /&gt;    return;&lt;br /&gt;   &lt;br /&gt;   var data:ByteArray = PNGEncoder.encode(bd);&lt;br /&gt;   var fr:FileReference = new FileReference();&lt;br /&gt;   fr.save(data, "EncodeImage.png");&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  private function onBtnLoadClick(e:MouseEvent):void{&lt;br /&gt;   trace("onBtnLoadClick()");&lt;br /&gt;   &lt;br /&gt;   var typeFilter:Array = [new FileFilter("Images(*.jpg;*.gif;*.png)", "*.jpg;*.gif;*.png")];&lt;br /&gt;   __fileReference2.browse(typeFilter);&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  private function onBtnDecodeClick(e:MouseEvent):void{&lt;br /&gt;   trace("onBtnDecodeClick()");&lt;br /&gt;   &lt;br /&gt;   var bd:BitmapData = getEncodedBitmapData(spImg2);&lt;br /&gt;   if(bd == null)&lt;br /&gt;    return;&lt;br /&gt;   &lt;br /&gt;   var txt:String = Steganography.getInstance().decode(bd);&lt;br /&gt;   txtOutput.text = txt;&lt;br /&gt;  }&lt;br /&gt;  &lt;br /&gt;  private function onFileReferenceSelect(e:Event):void{&lt;br /&gt;   trace("onFileReferenceSelect()");&lt;br /&gt;   &lt;br /&gt;   __fileReference.load();&lt;br /&gt;  }&lt;br /&gt;  &lt;br /&gt;  private function onFileReferenceComplete(e:Event):void{&lt;br /&gt;   trace("onFileReferenceComplete()");&lt;br /&gt;   &lt;br /&gt;   var data:ByteArray = __fileReference.data;&lt;br /&gt;   var loader:Loader = new Loader();&lt;br /&gt;   loader.loadBytes(data);&lt;br /&gt;   spImg.source = loader;&lt;br /&gt;   setTimeout(spImg.update, 200);&lt;br /&gt;  }&lt;br /&gt;  &lt;br /&gt;  private function onFileReference2Select(e:Event):void{&lt;br /&gt;   trace("onFileReference2Select()");&lt;br /&gt;   &lt;br /&gt;   __fileReference2.load();&lt;br /&gt;  }&lt;br /&gt;  &lt;br /&gt;  private function onFileReference2Complete(e:Event):void{&lt;br /&gt;   trace("onFileReference2Complete()");&lt;br /&gt;   &lt;br /&gt;   var data:ByteArray = __fileReference2.data;&lt;br /&gt;   var loader:Loader = new Loader();&lt;br /&gt;   loader.loadBytes(data);&lt;br /&gt;   spImg2.source = loader;&lt;br /&gt;   setTimeout(spImg2.update, 200);&lt;br /&gt;  }&lt;br /&gt;  &lt;br /&gt;  private function getEncodedBitmapData(sp:ScrollPane):BitmapData{&lt;br /&gt;   if(sp.content == null)&lt;br /&gt;    return null;&lt;br /&gt;   &lt;br /&gt;   var bmp:Bitmap;&lt;br /&gt;   &lt;br /&gt;   if(sp.content is Loader){&lt;br /&gt;    if(Loader(sp.content).content == null)&lt;br /&gt;     return null;&lt;br /&gt;    &lt;br /&gt;    bmp = Bitmap(Loader(sp.content).content);&lt;br /&gt;   }else if(sp.content is Bitmap){&lt;br /&gt;    bmp = Bitmap(sp.content);&lt;br /&gt;   }else{&lt;br /&gt;    return null;&lt;br /&gt;   }&lt;br /&gt;   &lt;br /&gt;   return bmp.bitmapData;&lt;br /&gt;  }&lt;br /&gt; }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;操作步驟：&lt;br /&gt;&lt;br /&gt;加密：&lt;br /&gt;1. 按下 Browse 按鈕，載入原始圖片到左上角的 ScrollPane 中。&lt;br /&gt;2. 在右上角的文字框中輸入欲藏入的文字 (此版 不接受雙位元文字)。&lt;br /&gt;3. 按下 Encode 按鈕，會將處理好後的圖片放到左下角的 ScrollPane 中。&lt;br /&gt;4. 可按下 Save 按鈕將圖片存檔。&lt;br /&gt;&lt;br /&gt;解密：&lt;br /&gt;5. 按下 Load 按鈕，將內含資訊的圖片載入到左下角的 ScrollPane 中。&lt;br /&gt;6. 按下 Decode 按鈕，將文字資訊從圖片中解出來到右下角的文字框中。&lt;br /&gt;&lt;br /&gt;程式試用：&lt;br /&gt;&lt;br /&gt; &lt;object classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=10,0,0,0" width="650" height="700" id="20090619_SteganographyAS3" align="middle"&gt;&lt;br /&gt; &lt;param name="allowScriptAccess" value="sameDomain" /&gt;&lt;br /&gt; &lt;param name="allowFullScreen" value="false" /&gt;&lt;br /&gt; &lt;param name="movie" value="http://ben.rb.chang.googlepages.com/20090619_SteganographyAS3.swf" /&gt;&lt;param name="quality" value="high" /&gt;&lt;param name="bgcolor" value="#ffffff" /&gt; &lt;embed src="http://ben.rb.chang.googlepages.com/20090619_SteganographyAS3.swf" quality="high" bgcolor="#ffffff" width="650" height="700" name="20090619_SteganographyAS3" align="middle" allowScriptAccess="sameDomain" allowFullScreen="false" type="application/x-shockwave-flash" pluginspage="http://www.adobe.com/go/getflashplayer_tw"&gt;&lt;/embed&gt;&lt;br /&gt; &lt;/object&gt;&lt;br /&gt;&lt;br /&gt;或到以下網址試用：&lt;br /&gt;&lt;br /&gt;&lt;a target="_blank" href="http://ben.rb.chang.googlepages.com/20090619_SteganographyAS3.html"&gt;http://ben.rb.chang.googlepages.com/20090619_SteganographyAS3.html&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4754237190569973724-6793602724382744903?l=blog.ben.idv.tw' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.ben.idv.tw/feeds/6793602724382744903/comments/default' title='張貼意見'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4754237190569973724&amp;postID=6793602724382744903' title='0 個意見'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4754237190569973724/posts/default/6793602724382744903'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4754237190569973724/posts/default/6793602724382744903'/><link rel='alternate' type='text/html' href='http://blog.ben.idv.tw/2009/06/blog-post.html' title='將文字隱藏在圖片中'/><author><name>Ben Chang</name><uri>http://www.blogger.com/profile/01921640246111819069</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/_HsFEtLMw5zU/SjpIGwvWkGI/AAAAAAAAJ_4/a9s1i1TUGBI/s72-c/Clipboard01.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4754237190569973724.post-9156261627526915504</id><published>2009-06-11T01:01:00.002+08:00</published><updated>2009-06-11T01:13:29.092+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Flex Builder'/><category scheme='http://www.blogger.com/atom/ns#' term='SWC'/><category scheme='http://www.blogger.com/atom/ns#' term='Flash'/><title type='text'>以 SWC 當作素材被載入</title><content type='html'>如果貴公司的 Flash 平台的開發方式也是：用 Flash IDE 製作畫面，但邏輯程式都用外部 AS Code Editor(筆記本、Flex Builder、Flash Develop...)來編輯 *.as 的話，你一定會遇到一些命名問題，在 *.as 想要使用的某些類別名稱 是來自於 *.fla 中 Library 定義(匯出)的類別，當然我們可以使用 getDefinitionByName() 或其他方式來將指定字串變成想要的類別 進而產生實體，不過只要一個不注意的話，就很容易出錯並 debug 到死～尤其若是有使用擾亂器(obfuscator，一種將 *.swf 內部的程式碼改變其命名、定義...等程式碼的工具，目的是讓反組譯出來的原始碼不易閱讀)的話，恐怕那更會是一個災難。&lt;br /&gt;&lt;br /&gt;這裡有一篇文章：http://www.airtightinteractive.com/news/?p=327&lt;br /&gt;&lt;br /&gt;他建議我們可以將 *.fla 的素材以匯出 *.swc 的方式，來提供給 flex builder 使用，這樣當 flex builder 的 AS Project 引用這些 *.swc 時，就可以正確的找到實際存在的類別名稱。&lt;br /&gt;&lt;br /&gt;不知道若是有使用擾亂器的話，是否仍可具有相同的優勢，不過對於一般開發的話，這種做法確實應該會比較保險一點，讓 *.fla 與 *.as 能更同步一些！&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4754237190569973724-9156261627526915504?l=blog.ben.idv.tw' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.ben.idv.tw/feeds/9156261627526915504/comments/default' title='張貼意見'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4754237190569973724&amp;postID=9156261627526915504' title='0 個意見'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4754237190569973724/posts/default/9156261627526915504'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4754237190569973724/posts/default/9156261627526915504'/><link rel='alternate' type='text/html' href='http://blog.ben.idv.tw/2009/06/swc.html' title='以 SWC 當作素材被載入'/><author><name>Ben Chang</name><uri>http://www.blogger.com/profile/01921640246111819069</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4754237190569973724.post-4185406749964579497</id><published>2009-04-07T18:04:00.008+08:00</published><updated>2009-04-09T10:22:55.020+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='JSFL'/><category scheme='http://www.blogger.com/atom/ns#' term='Flash'/><title type='text'>使用 JSFL 列出有 Linkage 的 Symbol 列表</title><content type='html'>今天被問到，如何得知 Flash IDE 中，Library 中有哪些 Symbol 有 link 到 Class。&lt;br /&gt;&lt;br /&gt;以下，我寫了一個 JSFL 來產生這份報表。首先，先任意準備一些 Symbol，並任意設定他們的 linkage 設定：&lt;br /&gt;&lt;br /&gt;&lt;a target="_blank" href="http://4.bp.blogspot.com/_HsFEtLMw5zU/SdslPKF6O2I/AAAAAAAAJWM/betq8LFOrj8/s1600-h/Clipboard01.jpg"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 306px; height: 400px;" src="http://4.bp.blogspot.com/_HsFEtLMw5zU/SdslPKF6O2I/AAAAAAAAJWM/betq8LFOrj8/s400/Clipboard01.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5321888327005780834" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;a target="_blank" href="http://2.bp.blogspot.com/_HsFEtLMw5zU/SdslO3vJbRI/AAAAAAAAJWE/kW-T6RvTPpk/s1600-h/Clipboard02.jpg"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 306px; height: 400px;" src="http://2.bp.blogspot.com/_HsFEtLMw5zU/SdslO3vJbRI/AAAAAAAAJWE/kW-T6RvTPpk/s400/Clipboard02.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5321888322078469394" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;a target="_blank" href="http://3.bp.blogspot.com/_HsFEtLMw5zU/SdslO6QKGmI/AAAAAAAAJV8/5PKTKdmixXY/s1600-h/Clipboard03.jpg"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 306px; height: 400px;" src="http://3.bp.blogspot.com/_HsFEtLMw5zU/SdslO6QKGmI/AAAAAAAAJV8/5PKTKdmixXY/s400/Clipboard03.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5321888322753796706" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;JSFL 程式碼：&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;var lib = fl.getDocumentDOM().library;&lt;br /&gt;var libItems = lib.items;&lt;br /&gt;&lt;br /&gt;fl.outputPanel.clear();&lt;br /&gt;fl.outputPanel.trace("symbol name\ttype\tclass\tbase class\texport in first frame");&lt;br /&gt;for(var i=0; i&amp;lt;libItems.length; i++){&lt;br /&gt; var item = libItems[i];&lt;br /&gt; if(item.linkageExportForAS){&lt;br /&gt;  fl.outputPanel.trace(item.name&lt;br /&gt;    + "\t" + item.itemType&lt;br /&gt;    + "\t" + item.linkageClassName&lt;br /&gt;    + "\t" + item.linkageBaseClass&lt;br /&gt;    + "\t" + item.linkageExportInFirstFrame);&lt;br /&gt; }&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;在 Flash IDE 執行指定的 *.jsfl 檔：&lt;br /&gt;&lt;br /&gt;&lt;a target="_blank" href="http://1.bp.blogspot.com/_HsFEtLMw5zU/SdslOjUJF2I/AAAAAAAAJV0/dJIcO2bmNYY/s1600-h/Clipboard05.jpg"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 400px; height: 258px;" src="http://1.bp.blogspot.com/_HsFEtLMw5zU/SdslOjUJF2I/AAAAAAAAJV0/dJIcO2bmNYY/s400/Clipboard05.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5321888316596492130" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;將我寫在 output 視窗的文字剪貼到 Excel 中看，比較清楚：&lt;br /&gt;&lt;br /&gt;&lt;a target="_blank" href="http://4.bp.blogspot.com/_HsFEtLMw5zU/SdslN8RXA3I/AAAAAAAAJVs/2IIcEDor5Ig/s1600-h/Clipboard06.jpg"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 400px; height: 272px;" src="http://4.bp.blogspot.com/_HsFEtLMw5zU/SdslN8RXA3I/AAAAAAAAJVs/2IIcEDor5Ig/s400/Clipboard06.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5321888306115838834" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;線上說明文件：http://livedocs.adobe.com/flash/9.0/main/wwhelp/wwhimpl/js/html/wwhelp.htm&lt;br /&gt;&lt;br /&gt;==================================================&lt;br /&gt;&lt;br /&gt;[2009-04-08-17-51]&lt;br /&gt;&lt;br /&gt;其實，寫這個工具的目的是，若是我們想要將一個舊的 Flash 的視覺全部重新設計，設計好後新的 FLA 希望能將一些與程式有關的設定資料都一一仿照舊 FLA 中的結構，像是 instance name 與 linkage class 等等，因此以下我又增加了對場景物件的列表：&lt;br /&gt;&lt;br /&gt;JSFL：&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;fl.outputPanel.clear();&lt;br /&gt;&lt;br /&gt;fl.trace("parent"&lt;br /&gt;   + "\t" + "timeline"&lt;br /&gt;   + "\t" + "layer"&lt;br /&gt;   + "\t" + "frame"&lt;br /&gt;   + "\t" + "instance type"&lt;br /&gt;   + "\t" + "instance name"&lt;br /&gt;   + "\t" + "pos"&lt;br /&gt;   + "\t" + "symbol type"&lt;br /&gt;   + "\t" + "symbol name"&lt;br /&gt;   + "\t" + "class"&lt;br /&gt;   + "\t" + "base class"&lt;br /&gt;   + "\t" + "export in first frame"&lt;br /&gt;   );&lt;br /&gt;&lt;br /&gt;var dom = fl.getDocumentDOM();&lt;br /&gt;&lt;br /&gt;traceContainer(null);&lt;br /&gt;&lt;br /&gt;fl.trace("------------------------------------------------------------------");&lt;br /&gt;fl.trace("symbol name"&lt;br /&gt;   + "\t" + "type"&lt;br /&gt;   + "\t" + "class"&lt;br /&gt;   + "\t" + "base class"&lt;br /&gt;   + "\t" + "export in first frame"&lt;br /&gt;   );&lt;br /&gt;traceLibrary();&lt;br /&gt;&lt;br /&gt;function traceContainer(container){&lt;br /&gt; if(container!=null){&lt;br /&gt;  fl.getDocumentDOM().selectNone();&lt;br /&gt;  container.selected = true;&lt;br /&gt;  fl.getDocumentDOM().enterEditMode("inPlace");&lt;br /&gt; }&lt;br /&gt; &lt;br /&gt; var timeline = dom.getTimeline();&lt;br /&gt; var layers, layer;&lt;br /&gt; var frames, frame;&lt;br /&gt; var elements, element;&lt;br /&gt; var libraryItem;&lt;br /&gt;&lt;br /&gt; var layer_locked, layer_visible;&lt;br /&gt; &lt;br /&gt; layers = timeline.layers;&lt;br /&gt;&lt;br /&gt; for(var idxLayer=0; idxLayer&amp;lt;layers.length; idxLayer++){&lt;br /&gt;  layer = layers[idxLayer];&lt;br /&gt;  frames = layer.frames;&lt;br /&gt;  &lt;br /&gt;  timeline.currentLayer = idxLayer;&lt;br /&gt;  &lt;br /&gt;  layer_locked = layer.locked;&lt;br /&gt;  layer_visible = layer.visible;&lt;br /&gt;  layer.locked = false;&lt;br /&gt;  layer.visible = true;&lt;br /&gt; &lt;br /&gt;  for(var idxFrame=0; idxFrame&amp;lt;frames.length; idxFrame++){&lt;br /&gt;   frame = frames[idxFrame];&lt;br /&gt;   elements = frame.elements;&lt;br /&gt;&lt;br /&gt;   timeline.currentFrame = idxFrame;&lt;br /&gt;&lt;br /&gt;   if(frame.startFrame == timeline.currentFrame){&lt;br /&gt;    for(var idxElement=0; idxElement&amp;lt;elements.length; idxElement++){&lt;br /&gt;     element = elements[idxElement];&lt;br /&gt;  &lt;br /&gt;     traceElement(container, timeline, layer, frame, element);&lt;br /&gt;    &lt;br /&gt;     if(element.elementType=="instance" &amp;&amp; element.name!=""){&lt;br /&gt;      traceContainer(element);&lt;br /&gt;     }&lt;br /&gt;    }&lt;br /&gt;   }&lt;br /&gt;  }&lt;br /&gt;  &lt;br /&gt;  layer.locked = layer_locked;&lt;br /&gt;  layer.visible = layer_visible;&lt;br /&gt; }&lt;br /&gt; &lt;br /&gt; if(container!=null){&lt;br /&gt;  fl.getDocumentDOM().exitEditMode();&lt;br /&gt;  container.selected = false;&lt;br /&gt; }&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;function traceElement(container, timeline, layer, frame, element){&lt;br /&gt; if(element.name=="")return;&lt;br /&gt; &lt;br /&gt; var str = "";&lt;br /&gt; switch(element.elementType){&lt;br /&gt;  case "shape":&lt;br /&gt;  case "shapeObj":&lt;br /&gt;   break;&lt;br /&gt;  case "text":&lt;br /&gt;  case "instance":&lt;br /&gt;   str += (container==null ? "root" : container.name);&lt;br /&gt;   str += '\t' + timeline.name;&lt;br /&gt;   str += '\t' + layer.name;&lt;br /&gt;   str += '\t' + timeline.currentFrame;&lt;br /&gt;   str += '\t' + element.elementType;&lt;br /&gt;   str += '\t' + element.name;&lt;br /&gt;   str += '\t' + '(' + element.x + ', ' + element.y + ')';&lt;br /&gt;   &lt;br /&gt;   if(element.elementType=="instance"){&lt;br /&gt;    libraryItem = element.libraryItem;&lt;br /&gt;    &lt;br /&gt;    str += '\t' + element.instanceType;&lt;br /&gt;    str += '\t' + libraryItem.name;&lt;br /&gt;    &lt;br /&gt;    if(libraryItem.linkageExportForAS){&lt;br /&gt;     str += '\t' + libraryItem.linkageClassName;&lt;br /&gt;     str += '\t' + libraryItem.linkageBaseClass;&lt;br /&gt;     str += '\t' + libraryItem.linkageExportInFirstFrame;&lt;br /&gt;    }else{&lt;br /&gt;     str += '\t\t\t';&lt;br /&gt;    }&lt;br /&gt;   }else{&lt;br /&gt;    str += '\t\t\t\t\t';&lt;br /&gt;   }&lt;br /&gt; }&lt;br /&gt; &lt;br /&gt; if(str!=""){&lt;br /&gt;  fl.trace(str); &lt;br /&gt; }&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;function traceLibrary(){&lt;br /&gt; var library = dom.library;&lt;br /&gt; var items = library.items;&lt;br /&gt; &lt;br /&gt; for(var i=0; i&amp;lt;items.length; i++){&lt;br /&gt;  var item = items[i];&lt;br /&gt;  if(item.linkageExportForAS){&lt;br /&gt;   fl.trace(item.name&lt;br /&gt;      + "\t" + item.itemType&lt;br /&gt;      + "\t" + item.linkageClassName&lt;br /&gt;      + "\t" + item.linkageBaseClass&lt;br /&gt;      + "\t" + item.linkageExportInFirstFrame);&lt;br /&gt;  }&lt;br /&gt; } &lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;將輸出結果放到 Excel 看：&lt;br /&gt;&lt;br /&gt;&lt;a target="_blank" href="http://3.bp.blogspot.com/_HsFEtLMw5zU/Sdx1ZzHNXBI/AAAAAAAAJWU/uyyVIFi8YvY/s1600-h/Clipboard01.jpg"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 400px; height: 399px;" src="http://3.bp.blogspot.com/_HsFEtLMw5zU/Sdx1ZzHNXBI/AAAAAAAAJWU/uyyVIFi8YvY/s400/Clipboard01.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5322257945722706962" /&gt;&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4754237190569973724-4185406749964579497?l=blog.ben.idv.tw' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.ben.idv.tw/feeds/4185406749964579497/comments/default' title='張貼意見'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4754237190569973724&amp;postID=4185406749964579497' title='7 個意見'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4754237190569973724/posts/default/4185406749964579497'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4754237190569973724/posts/default/4185406749964579497'/><link rel='alternate' type='text/html' href='http://blog.ben.idv.tw/2009/04/jsfl-linkage-symbol.html' title='使用 JSFL 列出有 Linkage 的 Symbol 列表'/><author><name>Ben Chang</name><uri>http://www.blogger.com/profile/01921640246111819069</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_HsFEtLMw5zU/SdslPKF6O2I/AAAAAAAAJWM/betq8LFOrj8/s72-c/Clipboard01.jpg' height='72' width='72'/><thr:total>7</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4754237190569973724.post-3797552261934069215</id><published>2009-03-27T09:24:00.004+08:00</published><updated>2009-03-27T13:52:12.259+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Decompiler'/><category scheme='http://www.blogger.com/atom/ns#' term='Security'/><category scheme='http://www.blogger.com/atom/ns#' term='swf format'/><category scheme='http://www.blogger.com/atom/ns#' term='Flash'/><title type='text'>HP 推出 SWFScan 協助分析 SWF 的安全問題(更容易 decompile?)</title><content type='html'>有鑑於 SWF 的安全性問題引發很多爭議，HP Web Security Research Group 推出免費的 SWFScan 軟體，可以協助你分析你們家的 Flash Application，並提出一些安全方面的建議。&lt;br /&gt;&lt;br /&gt;https://h30406.www3.hp.com/campaigns/2009/wwcampaign/1-5TUVE/index.php?key=swf&amp;jumpid=go/swfscan&lt;br /&gt;&lt;br /&gt;重要的是，他不僅僅是分析與提供報表而已，過程中理所當然的會進行 decompile，而且可以讓你看到所有 ActionScript Code，雖然不如其他 3rd party 的 decompiler 可以看到所有 symbol，但是有經驗的 AS Programmer 仍可藉此分析出許多商業邏輯。&lt;br /&gt;&lt;br /&gt;以下，我僅隨意拿一個行銷網站的簡單 SWF 試試：&lt;br /&gt;&lt;br /&gt;&lt;a target="_blank" onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_HsFEtLMw5zU/Scwq8IOM2XI/AAAAAAAAJUo/azlG6nXmpEU/s1600-h/Clipboard01.jpg"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 400px; height: 258px;" src="http://3.bp.blogspot.com/_HsFEtLMw5zU/Scwq8IOM2XI/AAAAAAAAJUo/azlG6nXmpEU/s400/Clipboard01.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5317672472505276786" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;a target="_blank" onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_HsFEtLMw5zU/Scwq8OyrGSI/AAAAAAAAJUg/zf3YfeaHur8/s1600-h/Clipboard02.jpg"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 400px; height: 258px;" src="http://2.bp.blogspot.com/_HsFEtLMw5zU/Scwq8OyrGSI/AAAAAAAAJUg/zf3YfeaHur8/s400/Clipboard02.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5317672474268866850" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;這個 SWF 的做法想必簡單，想必只運用了 Timeline 上的程式，想必是用 AS1/AS2。找時間再來測測用 AS3 製作的複雜 RIA、遊戲 試試看。&lt;br /&gt;&lt;br /&gt;==================================================&lt;br /&gt;&lt;br /&gt;[2009-03-27-13-46]&lt;br /&gt;&lt;br /&gt;針對比較複雜的 SWF 測試之後，發現他還會檢查一些 keyword，告訴你哪些文字可能透露出使用者帳戶的訊息，譬如 "LOGIN"：&lt;br /&gt;&lt;br /&gt;&lt;a target="_blank" onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_HsFEtLMw5zU/Scxo8at-ixI/AAAAAAAAJUw/a38qDx0-uF8/s1600-h/Clipboard01.jpg"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 400px; height: 290px;" src="http://2.bp.blogspot.com/_HsFEtLMw5zU/Scxo8at-ixI/AAAAAAAAJUw/a38qDx0-uF8/s400/Clipboard01.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5317740647191317266" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;或是有哪些文字可能透露出與資料加密有關的訊息。&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4754237190569973724-3797552261934069215?l=blog.ben.idv.tw' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.ben.idv.tw/feeds/3797552261934069215/comments/default' title='張貼意見'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4754237190569973724&amp;postID=3797552261934069215' title='2 個意見'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4754237190569973724/posts/default/3797552261934069215'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4754237190569973724/posts/default/3797552261934069215'/><link rel='alternate' type='text/html' href='http://blog.ben.idv.tw/2009/03/hp-swfscan-swf-decompile.html' title='HP 推出 SWFScan 協助分析 SWF 的安全問題(更容易 decompile?)'/><author><name>Ben Chang</name><uri>http://www.blogger.com/profile/01921640246111819069</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/_HsFEtLMw5zU/Scwq8IOM2XI/AAAAAAAAJUo/azlG6nXmpEU/s72-c/Clipboard01.jpg' height='72' width='72'/><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4754237190569973724.post-2616448529336431247</id><published>2009-03-17T18:15:00.004+08:00</published><updated>2009-03-24T16:01:17.024+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Local Connection'/><category scheme='http://www.blogger.com/atom/ns#' term='AS3'/><category scheme='http://www.blogger.com/atom/ns#' term='Flash'/><title type='text'>利用 LocalConnection 限制 Flash 應用程式同時間只能執行一個</title><content type='html'>若是基於一些原因，你不希望你的 flash 應用程式，在同一台電腦被同時執行兩個，那麼你可以透過 LocalConnection 連線到已使用的名稱時會送出錯誤訊息，來達到這個目的。&lt;br /&gt;&lt;br /&gt;以下，我準備一個 test.fla，其 Document Class 是 Main，而 Main.as 的程式碼如下：&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;package{&lt;br /&gt; import flash.display.MovieClip;&lt;br /&gt; import flash.net.LocalConnection;&lt;br /&gt; import flash.utils.getQualifiedClassName;&lt;br /&gt; &lt;br /&gt; public class Main extends MovieClip{&lt;br /&gt;  private var __lcChackSingleApp:LocalConnection;&lt;br /&gt;  public function Main(){&lt;br /&gt;   var lcName:String = getQualifiedClassName(this);&lt;br /&gt;   __lcChackSingleApp = new LocalConnection();&lt;br /&gt;   try{&lt;br /&gt;    __lcChackSingleApp.connect(lcName);&lt;br /&gt;   }catch(e:Error){&lt;br /&gt;    throw new Error("不允許同時執行兩個 flash");&lt;br /&gt;    return;&lt;br /&gt;   }&lt;br /&gt;   &lt;br /&gt;   init();&lt;br /&gt;  }&lt;br /&gt;  &lt;br /&gt;  private function init():void{&lt;br /&gt;   throw new Error("init()");&lt;br /&gt;  }&lt;br /&gt; }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;以下，我的測試畫面是直接在自己電腦用 standalone player 來開 *.swf 的效果，第一次開啟 test.swf 時，會跳出以下的 Error 訊息，表示有順利執行到 init()：&lt;br /&gt;&lt;br /&gt;&lt;a target="_blank" onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_HsFEtLMw5zU/Sb95TpYUDfI/AAAAAAAAJT8/8EpM6-mFDek/s1600-h/Clipboard01.jpg"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 400px; height: 209px;" src="http://4.bp.blogspot.com/_HsFEtLMw5zU/Sb95TpYUDfI/AAAAAAAAJT8/8EpM6-mFDek/s400/Clipboard01.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5314099463752781298" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;然後第一個視窗就開起完成了，然後再次按下 test.swf 嘗試開啟新的視窗，就會看到以下畫面告知錯誤訊息：&lt;br /&gt;&lt;br /&gt;&lt;a target="_blank" onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_HsFEtLMw5zU/Sb95Tq531bI/AAAAAAAAJT0/nKEp8reJ2-k/s1600-h/Clipboard02.jpg"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 400px; height: 187px;" src="http://3.bp.blogspot.com/_HsFEtLMw5zU/Sb95Tq531bI/AAAAAAAAJT0/nKEp8reJ2-k/s400/Clipboard02.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5314099464161973682" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;結束錯誤訊息後，也不會出現表示 init() 的訊息，證明後續的工作沒有被執行到：&lt;br /&gt;&lt;br /&gt;&lt;a target="_blank" onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_HsFEtLMw5zU/Sb95TIWLqkI/AAAAAAAAJTs/5vSm7fE6go8/s1600-h/Clipboard03.jpg"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 400px; height: 162px;" src="http://1.bp.blogspot.com/_HsFEtLMw5zU/Sb95TIWLqkI/AAAAAAAAJTs/5vSm7fE6go8/s400/Clipboard03.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5314099454885472834" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;實務上，當然你不會用 throw new Error() 的方式來處理，你可以使用自己想要的畫面，或是導向網頁。&lt;br /&gt;&lt;br /&gt;這個機制，不僅可以防堵相同種類的瀏覽器，對於不同種類的瀏覽器 IE 與 FF 也一樣有效。&lt;br /&gt;&lt;br /&gt;=====================================================&lt;br /&gt;&lt;br /&gt;[2009-03-24-15-48]&lt;br /&gt;&lt;br /&gt;實務上，遇到一些問題，有些人的電腦，IE 瀏覽器關閉時，雖然以為已經關閉了，但是 flash 卻好像仍未結束的樣子，通常發生在還有其他 IE 瀏覽器開啟的時候，但這種情況也不是每台電腦都可見，只有某些人的電腦會發生 IE 關不完全的情況。&lt;br /&gt;&lt;br /&gt;這種情況，就導致了 LocalConnection 還存在，以至於新開啟的 Flash 會檢查到 LC 重複，導致無法進入。&lt;br /&gt;&lt;br /&gt;另一種作法，當第二個 instance 開啟發現第一個 instance 的 LC 還存在的話，就用該名稱向 instance 1 溝通，要求 instance 1 進行釋放資源與結束的工作，讓 instance 2 可以進入。這種方式永遠讓後者取代前者。&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4754237190569973724-2616448529336431247?l=blog.ben.idv.tw' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.ben.idv.tw/feeds/2616448529336431247/comments/default' title='張貼意見'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4754237190569973724&amp;postID=2616448529336431247' title='3 個意見'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4754237190569973724/posts/default/2616448529336431247'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4754237190569973724/posts/default/2616448529336431247'/><link rel='alternate' type='text/html' href='http://blog.ben.idv.tw/2009/03/localconnection-flash.html' title='利用 LocalConnection 限制 Flash 應用程式同時間只能執行一個'/><author><name>Ben Chang</name><uri>http://www.blogger.com/profile/01921640246111819069</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_HsFEtLMw5zU/Sb95TpYUDfI/AAAAAAAAJT8/8EpM6-mFDek/s72-c/Clipboard01.jpg' height='72' width='72'/><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4754237190569973724.post-9056304671375872104</id><published>2009-03-09T14:06:00.002+08:00</published><updated>2009-03-09T14:15:05.675+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Flex Builder'/><category scheme='http://www.blogger.com/atom/ns#' term='Flex'/><category scheme='http://www.blogger.com/atom/ns#' term='Flash'/><title type='text'>免費的 Flex Builder</title><content type='html'>這對一些 Flex 的開發者來說或許是個好消息，Flex Builder 可以免費取得～&lt;br /&gt;&lt;br /&gt;http://www.eonflex.com/?p=139&lt;br /&gt;http://www.digitalartsonline.co.uk/news/index.cfm?NewsID=12218&lt;br /&gt;&lt;br /&gt;雖然這是來自英國 Adobe 的消息，但卻不限各地的 user 去索取它。&lt;br /&gt;&lt;br /&gt;你所要做的，就是去連絡 Shorten：&lt;br /&gt;email : shorten [at] adobe.com&lt;br /&gt;twitter：http://twitter.com/ashorten&lt;br /&gt;blog：http://www.ashorten.com/&lt;br /&gt;&lt;br /&gt;雖然大部分的人都已經有其他方法取得 Flex Builder 了，或是採用其他的開發工具如 Visual Studio 版的 Amethyst：http://www.sapphiresteel.com/Download-Amethyst-Adobe-Flex-IDE，不過有需要的人還是可以去詢問看看。&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4754237190569973724-9056304671375872104?l=blog.ben.idv.tw' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.ben.idv.tw/feeds/9056304671375872104/comments/default' title='張貼意見'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4754237190569973724&amp;postID=9056304671375872104' title='2 個意見'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4754237190569973724/posts/default/9056304671375872104'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4754237190569973724/posts/default/9056304671375872104'/><link rel='alternate' type='text/html' href='http://blog.ben.idv.tw/2009/03/flex-builder.html' title='免費的 Flex Builder'/><author><name>Ben Chang</name><uri>http://www.blogger.com/profile/01921640246111819069</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4754237190569973724.post-5421587255435757185</id><published>2009-03-07T14:22:00.005+08:00</published><updated>2011-08-02T16:20:29.691+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Security'/><category scheme='http://www.blogger.com/atom/ns#' term='.NET'/><category scheme='http://www.blogger.com/atom/ns#' term='AS3'/><category scheme='http://www.blogger.com/atom/ns#' term='Flex'/><title type='text'>AS3 作 3DES 編碼，與 .NET 互通資料</title><content type='html'>使用 AS3 想要進行資料加密的工作時，可以參考 as3crypto：&lt;br /&gt;&lt;br /&gt;http://code.google.com/p/as3crypto/&lt;br /&gt;&lt;br /&gt;以及其範例：&lt;br /&gt;&lt;br /&gt;http://crypto.hurlant.com/demo/&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;假設，我們要在 .NET 中將一段明碼編碼：&lt;br /&gt;&lt;br /&gt;&lt;a target="_blank" onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_HsFEtLMw5zU/SbITbrPNSAI/AAAAAAAAJSY/jbM_le4eKh4/s1600-h/Clipboard01.jpg"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 400px; height: 236px;" src="http://4.bp.blogspot.com/_HsFEtLMw5zU/SbITbrPNSAI/AAAAAAAAJSY/jbM_le4eKh4/s400/Clipboard01.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5310328276807141378" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;會得到：&lt;br /&gt;&lt;br /&gt;Key(Base64): Lns8zSrn2h4VGb5y1NBBHPcNDGjTHjna&lt;br /&gt;IV(Hex): 41b362c1231999fc&lt;br /&gt;編碼結果：GAUNI2sJCx32yFiF1J0AC5YPbbXcizYl&lt;br /&gt;&lt;br /&gt;然後將這些資料貼進 Demo 的網頁後：&lt;br /&gt;&lt;br /&gt;&lt;a target="_blank" onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_HsFEtLMw5zU/SbITb_J6WPI/AAAAAAAAJSg/XcV8mGG6yJ0/s1600-h/Clipboard02.jpg"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 400px; height: 364px;" src="http://2.bp.blogspot.com/_HsFEtLMw5zU/SbITb_J6WPI/AAAAAAAAJSg/XcV8mGG6yJ0/s400/Clipboard02.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5310328282153638130" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;按下 Decrypt，就可以解出原來的明碼 (我就不重複貼圖了)&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;另外一個情況是，反過來，當 Flash 透過 3DES 進行編碼後，要提供資料給 .NET 的話：&lt;br /&gt;&lt;br /&gt;&lt;a target="_blank" onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_HsFEtLMw5zU/SbIVWacThuI/AAAAAAAAJSw/lNiB_LeTlJ0/s1600-h/Clipboard03.jpg"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 400px; height: 329px;" src="http://1.bp.blogspot.com/_HsFEtLMw5zU/SbIVWacThuI/AAAAAAAAJSw/lNiB_LeTlJ0/s400/Clipboard03.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5310330385422583522" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;則會提供：&lt;br /&gt;&lt;br /&gt;Key(Base64): Lns8zSrn2h4VGb5y1NBBHPcNDGjTHjna&lt;br /&gt;IV(Base64): 0sqxgBNq7iA=&lt;br /&gt;編碼結果：XcMt/RnEoozLmBLUpLNRTPVMjRykzDxR9wvrKV9Zwwo=&lt;br /&gt;&lt;br /&gt;範例程式的 Key Format 下拉選單好像有點問題，無法將 Hex 資料轉成 Base64，懶得解 bug，所以這裡的 Key(Base64) 可以直接用剛剛由 .NET 產生的繼續使用即可。&lt;br /&gt;&lt;br /&gt;IV(Base64) 的部分，因為原範例程式只有顯示 IV(Hex)，所以這部分我有修改原範例程式，多顯示一種格式的資料，便於提供給 .NET 使用。&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;將資料貼進 .NET 之後，按下 Decrypt 就順利解出來囉：&lt;br /&gt;&lt;br /&gt;&lt;a target="_blank" onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_HsFEtLMw5zU/SbIVWKYaE6I/AAAAAAAAJSo/AQivkwKkQY4/s1600-h/Clipboard04.jpg"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 400px; height: 236px;" src="http://3.bp.blogspot.com/_HsFEtLMw5zU/SbIVWKYaE6I/AAAAAAAAJSo/AQivkwKkQY4/s400/Clipboard04.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5310330381111268258" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;.NET 的原始碼，主架構可以由 MSDN 的範例找到，&lt;br /&gt;http://msdn.microsoft.com/zh-tw/library/system.security.cryptography.tripledescryptoserviceprovider(VS.80).aspx&lt;br /&gt;&lt;br /&gt;為了能編中文，所以我將原本的 ASCIIEncoding() 改為 System.Text.Encoding.UTF8。&lt;br /&gt;&lt;br /&gt;並且設定了 填補模式 為 PKCS7(在 AS3 中用的是 PKCS#5，放心，有通！)：&lt;br /&gt;TripleDESCryptoServiceProvider tDESalg = new TripleDESCryptoServiceProvider();&lt;br /&gt;tDESalg.Padding = PaddingMode.PKCS7;&lt;br /&gt;&lt;br /&gt;完整程式碼如下：&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;using System;&lt;br /&gt;using System.Collections.Generic;&lt;br /&gt;using System.ComponentModel;&lt;br /&gt;using System.Data;&lt;br /&gt;using System.Drawing;&lt;br /&gt;using System.Text;&lt;br /&gt;using System.Windows.Forms;&lt;br /&gt;&lt;br /&gt;using System.Security.Cryptography;&lt;br /&gt;using System.IO;&lt;br /&gt;&lt;br /&gt;namespace TripleDES&lt;br /&gt;{&lt;br /&gt;    public partial class Form1 : Form&lt;br /&gt;    {&lt;br /&gt;        public Form1()&lt;br /&gt;        {&lt;br /&gt;            InitializeComponent();&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        private void btnEncrypt_Click(object sender, EventArgs e)&lt;br /&gt;        {&lt;br /&gt;            try&lt;br /&gt;            {&lt;br /&gt;                // Create a new TripleDESCryptoServiceProvider object&lt;br /&gt;                // to generate a key and initialization vector (IV).&lt;br /&gt;                TripleDESCryptoServiceProvider tDESalg = new TripleDESCryptoServiceProvider();&lt;br /&gt;&lt;br /&gt;                // Create a string to encrypt.&lt;br /&gt;                string sData = txtSource.Text;&lt;br /&gt;&lt;br /&gt;                if (txtKey.Text == "")&lt;br /&gt;                {&lt;br /&gt;                    txtKey.Text = Convert.ToBase64String(tDESalg.Key);&lt;br /&gt;                }&lt;br /&gt;                else&lt;br /&gt;                {&lt;br /&gt;                    tDESalg.Key = Convert.FromBase64String(txtKey.Text);&lt;br /&gt;                }&lt;br /&gt;&lt;br /&gt;                if (txtIV.Text == "")&lt;br /&gt;                {&lt;br /&gt;                    txtIV.Text = Convert.ToBase64String(tDESalg.IV);&lt;br /&gt;                }&lt;br /&gt;                else&lt;br /&gt;                {&lt;br /&gt;                    tDESalg.IV = Convert.FromBase64String(txtIV.Text);&lt;br /&gt;                }&lt;br /&gt;&lt;br /&gt;                String hexIV = "";&lt;br /&gt;                for (int i = 0; i &amp;lt; tDESalg.IV.Length; i++)&lt;br /&gt;                {&lt;br /&gt;                    hexIV += Convert.ToString(tDESalg.IV[i], 16);&lt;br /&gt;                }&lt;br /&gt;                txtIV2.Text = hexIV;&lt;br /&gt;&lt;br /&gt;                // Encrypt the string to an in-memory buffer.&lt;br /&gt;                byte[] Data = EncryptTextToMemory(sData, tDESalg.Key, tDESalg.IV);&lt;br /&gt;                &lt;br /&gt;                txtResult.Text = Convert.ToBase64String(Data);&lt;br /&gt;            }&lt;br /&gt;            catch (Exception exp)&lt;br /&gt;            {&lt;br /&gt;                Console.WriteLine(exp.Message);&lt;br /&gt;            }&lt;br /&gt;&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        private void btnDecrypt_Click(object sender, EventArgs e)&lt;br /&gt;        {&lt;br /&gt;            try&lt;br /&gt;            {&lt;br /&gt;                &lt;br /&gt;                String hexIV = txtIV2.Text;&lt;br /&gt;                hexIV = System.Text.RegularExpressions.Regex.Replace(hexIV, "/\\s|:/gm", "");&lt;br /&gt;                if ((hexIV.Length &amp; 1) == 1) hexIV = "0" + hexIV;&lt;br /&gt;                byte[] iv = new byte[hexIV.Length/2];&lt;br /&gt;                for (int i = 0; i &amp;lt; iv.Length; i++) {&lt;br /&gt;                    iv[i] = Convert.ToByte(hexIV.Substring(i * 2, 2), 16);&lt;br /&gt;                }&lt;br /&gt;                &lt;br /&gt;&lt;br /&gt;                txtResult2.Text = DecryptTextFromMemory(Convert.FromBase64String(txtResult.Text)&lt;br /&gt;                                                    , Convert.FromBase64String(txtKey.Text)&lt;br /&gt;                                                    , Convert.FromBase64String(txtIV.Text));&lt;br /&gt;            }&lt;br /&gt;            catch (Exception exp)&lt;br /&gt;            {&lt;br /&gt;                Console.WriteLine(exp.Message);&lt;br /&gt;            }&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        public static byte[] EncryptTextToMemory(string Data, byte[] Key, byte[] IV)&lt;br /&gt;        {&lt;br /&gt;            try&lt;br /&gt;            {&lt;br /&gt;                TripleDESCryptoServiceProvider tDESalg = new TripleDESCryptoServiceProvider();&lt;br /&gt;                tDESalg.Padding = PaddingMode.PKCS7;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;                // Create a MemoryStream.&lt;br /&gt;                MemoryStream mStream = new MemoryStream();&lt;br /&gt;&lt;br /&gt;                // Create a CryptoStream using the MemoryStream &lt;br /&gt;                // and the passed key and initialization vector (IV).&lt;br /&gt;                CryptoStream cStream = new CryptoStream(mStream,&lt;br /&gt;                    tDESalg.CreateEncryptor(Key, IV),&lt;br /&gt;                    CryptoStreamMode.Write);&lt;br /&gt;&lt;br /&gt;                // Convert the passed string to a byte array.&lt;br /&gt;                //byte[] toEncrypt = new ASCIIEncoding().GetBytes(Data);&lt;br /&gt;                byte[] toEncrypt = System.Text.Encoding.UTF8.GetBytes(Data);&lt;br /&gt;&lt;br /&gt;                // Write the byte array to the crypto stream and flush it.&lt;br /&gt;                cStream.Write(toEncrypt, 0, toEncrypt.Length);&lt;br /&gt;                cStream.FlushFinalBlock();&lt;br /&gt;&lt;br /&gt;                // Get an array of bytes from the &lt;br /&gt;                // MemoryStream that holds the &lt;br /&gt;                // encrypted data.&lt;br /&gt;                byte[] ret = mStream.ToArray();&lt;br /&gt;&lt;br /&gt;                // Close the streams.&lt;br /&gt;                cStream.Close();&lt;br /&gt;                mStream.Close();&lt;br /&gt;&lt;br /&gt;                // Return the encrypted buffer.&lt;br /&gt;                return ret;&lt;br /&gt;            }&lt;br /&gt;            catch (CryptographicException e)&lt;br /&gt;            {&lt;br /&gt;                Console.WriteLine("A Cryptographic error occurred: {0}", e.Message);&lt;br /&gt;                return null;&lt;br /&gt;            }&lt;br /&gt;&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        public static string DecryptTextFromMemory(byte[] Data, byte[] Key, byte[] IV)&lt;br /&gt;        {&lt;br /&gt;            try&lt;br /&gt;            {&lt;br /&gt;                TripleDESCryptoServiceProvider tDESalg = new TripleDESCryptoServiceProvider();&lt;br /&gt;                tDESalg.Padding = PaddingMode.PKCS7;&lt;br /&gt;&lt;br /&gt;                // Create a new MemoryStream using the passed &lt;br /&gt;                // array of encrypted data.&lt;br /&gt;                MemoryStream msDecrypt = new MemoryStream(Data);&lt;br /&gt;&lt;br /&gt;                // Create a CryptoStream using the MemoryStream &lt;br /&gt;                // and the passed key and initialization vector (IV).&lt;br /&gt;                CryptoStream csDecrypt = new CryptoStream(msDecrypt,&lt;br /&gt;                    tDESalg.CreateDecryptor(Key, IV),&lt;br /&gt;                    CryptoStreamMode.Read);&lt;br /&gt;&lt;br /&gt;                // Create buffer to hold the decrypted data.&lt;br /&gt;                byte[] fromEncrypt = new byte[Data.Length];&lt;br /&gt;&lt;br /&gt;                // Read the decrypted data out of the crypto stream&lt;br /&gt;                // and place it into the temporary buffer.&lt;br /&gt;                csDecrypt.Read(fromEncrypt, 0, fromEncrypt.Length);&lt;br /&gt;&lt;br /&gt;                //Convert the buffer into a string and return it.&lt;br /&gt;                return System.Text.Encoding.UTF8.GetString(fromEncrypt);&lt;br /&gt;            }&lt;br /&gt;            catch (CryptographicException e)&lt;br /&gt;            {&lt;br /&gt;                Console.WriteLine("A Cryptographic error occurred: {0}", e.Message);&lt;br /&gt;                return null;&lt;br /&gt;            }&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        &lt;br /&gt;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;至於我自己改寫的 Flex 範例，原則上只是因為在原範例中，IV 是編碼後所自動產生的，並可用於解碼，我將範例改成可以使用我們所填入文字欄位提供的 IV 值作編碼；以及上面我提過的有多顯示 IV(Base64) 的欄位。我就不再轉貼落落長的原始碼了。&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4754237190569973724-5421587255435757185?l=blog.ben.idv.tw' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.ben.idv.tw/feeds/5421587255435757185/comments/default' title='張貼意見'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4754237190569973724&amp;postID=5421587255435757185' title='3 個意見'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4754237190569973724/posts/default/5421587255435757185'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4754237190569973724/posts/default/5421587255435757185'/><link rel='alternate' type='text/html' href='http://blog.ben.idv.tw/2009/03/as3-3des-net.html' title='AS3 作 3DES 編碼，與 .NET 互通資料'/><author><name>Ben Chang</name><uri>http://www.blogger.com/profile/01921640246111819069</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_HsFEtLMw5zU/SbITbrPNSAI/AAAAAAAAJSY/jbM_le4eKh4/s72-c/Clipboard01.jpg' height='72' width='72'/><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4754237190569973724.post-4342525707052715813</id><published>2009-03-02T17:19:00.003+08:00</published><updated>2009-03-02T17:26:34.122+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Class Loader'/><category scheme='http://www.blogger.com/atom/ns#' term='AS3'/><category scheme='http://www.blogger.com/atom/ns#' term='Flash'/><title type='text'>將 ClassLoader 用於音效管理</title><content type='html'>有了 &lt;a href="http://blog.ben.idv.tw/2009/03/classloader-swf-class.html" target="_blank"&gt;ClassLoader&lt;/a&gt; 之後，可以將它用在音效的管理。&lt;br /&gt;&lt;br /&gt;我寫了一個 SoundManager.as，裡面會用到 ClassLoader 將外部的 *.swf 載入進來，要使用的時候只要指定 音效的類別名稱 就可以播放了。&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;package&lt;br /&gt;{ &lt;br /&gt; import flash.events.Event;&lt;br /&gt; import flash.events.EventDispatcher;&lt;br /&gt; import flash.media.*;&lt;br /&gt; import flash.utils.getQualifiedClassName;&lt;br /&gt; &lt;br /&gt; public class SoundManager extends EventDispatcher&lt;br /&gt; {&lt;br /&gt;  static public var SOUND_LOADED:String = "SOUND_LOADED";&lt;br /&gt;  &lt;br /&gt;  private var __sounds:Object = new Object();&lt;br /&gt;  private var __soundClassLoaderList:Array = new Array();&lt;br /&gt;  &lt;br /&gt;  static private var __instance:SoundManager;&lt;br /&gt;  static public function getInstance():SoundManager{&lt;br /&gt;   if(__instance==null)&lt;br /&gt;    __instance = new SoundManager();&lt;br /&gt;   return __instance;&lt;br /&gt;  } &lt;br /&gt;  public function SoundManager()&lt;br /&gt;  {&lt;br /&gt;   if(__instance!=null)throw new Error("please use SoundManager.getInstance()!!");&lt;br /&gt;  }&lt;br /&gt;  &lt;br /&gt;  /**&lt;br /&gt;   * 同一個存放 Sound 類別的 *.swf 只會載入一次 &lt;br /&gt;   * @param soundClassLibUrl&lt;br /&gt;   * &lt;br /&gt;   */  &lt;br /&gt;  public function load(soundClassLibUrl:String):void{&lt;br /&gt;   if(soundClassLibUrl!=null &amp;&amp; soundClassLibUrl.length&amp;gt;0){&lt;br /&gt;    for(var i:uint=0; i&amp;lt;__soundClassLoaderList.length; i++){&lt;br /&gt;     if(__soundClassLoaderList[i]["url"]==soundClassLibUrl){&lt;br /&gt;      dispatchEvent(new Event(SOUND_LOADED));&lt;br /&gt;      return;&lt;br /&gt;     }&lt;br /&gt;    }&lt;br /&gt;    &lt;br /&gt;    var soundClassLoader:ClassLoader = new ClassLoader(soundClassLibUrl);&lt;br /&gt;    soundClassLoader.addEventListener(ClassLoader.CLASS_LOADED, onClassLoaded);&lt;br /&gt;    soundClassLoader.addEventListener(ClassLoader.LOAD_ERROR, onClassLoadError);&lt;br /&gt;    soundClassLoader.load();&lt;br /&gt;    &lt;br /&gt;    __soundClassLoaderList.push({url: soundClassLibUrl, clsLoader: soundClassLoader});&lt;br /&gt;    &lt;br /&gt;   }else{&lt;br /&gt;    dispatchEvent(new Event(SOUND_LOADED));&lt;br /&gt;   }&lt;br /&gt;  }&lt;br /&gt;  &lt;br /&gt;  /**&lt;br /&gt;   * 載入 *.swf 完成 &lt;br /&gt;   * @param e&lt;br /&gt;   * &lt;br /&gt;   */  &lt;br /&gt;  private function onClassLoaded(e:Event):void{&lt;br /&gt;   dispatchEvent(new Event(SOUND_LOADED));&lt;br /&gt;  } &lt;br /&gt;  &lt;br /&gt;  /**&lt;br /&gt;   * 載入 *.swf 失敗 &lt;br /&gt;   * @param e&lt;br /&gt;   * &lt;br /&gt;   */  &lt;br /&gt;  private function onClassLoadError(e:Event):void{&lt;br /&gt;   trace(flash.utils.getQualifiedClassName(this), "onClassLoadError()", e.toString());&lt;br /&gt;  }&lt;br /&gt;  &lt;br /&gt;  /**&lt;br /&gt;   * 去各個 Class Loader 找一遍，找出指定的 Sound Class&lt;br /&gt;   * @param id&lt;br /&gt;   * @return &lt;br /&gt;   * &lt;br /&gt;   */  &lt;br /&gt;  private function getSound(id:String):Sound{&lt;br /&gt;   var clsLoader:ClassLoader;&lt;br /&gt;   var runtimeClassRef:Class;&lt;br /&gt;    &lt;br /&gt;   for(var i:uint=0; i&amp;lt;__soundClassLoaderList.length; i++){&lt;br /&gt;     clsLoader = __soundClassLoaderList[i]["clsLoader"] as ClassLoader;&lt;br /&gt;     runtimeClassRef = clsLoader.getClass(id);&lt;br /&gt;     &lt;br /&gt;     if(runtimeClassRef!=null){&lt;br /&gt;      return new runtimeClassRef() as Sound;&lt;br /&gt;     }&lt;br /&gt;   }&lt;br /&gt;   &lt;br /&gt;   return null;&lt;br /&gt;  }&lt;br /&gt;  &lt;br /&gt;  /**&lt;br /&gt;   * 取得指定的 Sound Class 的物件，並存在 cache 中 &lt;br /&gt;   * @param id&lt;br /&gt;   * @return &lt;br /&gt;   * &lt;br /&gt;   */  &lt;br /&gt;  private function getSoundObj(id:String):Object{&lt;br /&gt;   if(__sounds[id]!=null){&lt;br /&gt;    return __sounds[id];&lt;br /&gt;   }else{&lt;br /&gt;    var snd:Sound = getSound(id);&lt;br /&gt;    if(snd!=null){&lt;br /&gt;     var obj:Object = {};&lt;br /&gt;     obj["sound"] = snd;&lt;br /&gt;     obj["channel"] = null;&lt;br /&gt;     obj["transform"] = new SoundTransform();&lt;br /&gt;     obj["position"] = 0;&lt;br /&gt;      &lt;br /&gt;     __sounds[id] = obj;&lt;br /&gt;     return __sounds[id];&lt;br /&gt;    }&lt;br /&gt;    &lt;br /&gt;    return null;&lt;br /&gt;   }&lt;br /&gt;  }&lt;br /&gt;  &lt;br /&gt;  /**&lt;br /&gt;   * 播放指定 Sound Class 的音效 &lt;br /&gt;   * @param id&lt;br /&gt;   * @param isLoop&lt;br /&gt;   * &lt;br /&gt;   */  &lt;br /&gt;  public function play(id:String, isLoop:Boolean=false):void{&lt;br /&gt;   //log.debug("play sound", id);&lt;br /&gt;   var objSound:Object = getSoundObj(id);&lt;br /&gt;   if(objSound!=null){&lt;br /&gt;    var loops:int = isLoop ? int.MAX_VALUE : 0;&lt;br /&gt;    try{&lt;br /&gt;     objSound["channel"] = (objSound["sound"] as Sound).play(objSound["position"], loops, objSound["transform"]);&lt;br /&gt;     (objSound["channel"] as SoundChannel).addEventListener(Event.SOUND_COMPLETE, soundComplete);&lt;br /&gt;    }catch(ae:ArgumentError){&lt;br /&gt;     trace(flash.utils.getQualifiedClassName(this), "play()", id, isLoop, ae.toString());&lt;br /&gt;    }&lt;br /&gt;   }&lt;br /&gt;  }&lt;br /&gt;  &lt;br /&gt;  private function soundComplete(e:Event):void{&lt;br /&gt;   dispatchEvent(e);&lt;br /&gt;  }&lt;br /&gt;  &lt;br /&gt;  /**&lt;br /&gt;   * 停止指定 Sound Class 的音效 &lt;br /&gt;   * @param id&lt;br /&gt;   * @param isPause&lt;br /&gt;   * &lt;br /&gt;   */  &lt;br /&gt;  public function stop(id:String, isPause:Boolean=false):void{&lt;br /&gt;   //log.debug("stop sound", id);&lt;br /&gt;   var objSound:Object = getSoundObj(id);&lt;br /&gt;   if(objSound!=null){&lt;br /&gt;    if(objSound["channel"]!=null){&lt;br /&gt;     var channel:SoundChannel = objSound["channel"] as SoundChannel;&lt;br /&gt;     objSound["position"] = isPause ? channel.position : 0; //紀錄停止的地方&lt;br /&gt;     channel.stop();&lt;br /&gt;    }&lt;br /&gt;   }&lt;br /&gt;  }&lt;br /&gt;  &lt;br /&gt;  //===================================================================================&lt;br /&gt;  &lt;br /&gt;  private var __soundLists:Array = new Array();&lt;br /&gt;  &lt;br /&gt;  /**&lt;br /&gt;   * 將多個 Sound Class 組成為一個串列音效，可以一個接一個播放 &lt;br /&gt;   * @param ids&lt;br /&gt;   * &lt;br /&gt;   */  &lt;br /&gt;  public function playList(...ids):void{&lt;br /&gt;   var sndAry:Array = new Array();&lt;br /&gt;   var snd:Sound;&lt;br /&gt;   &lt;br /&gt;   for(var i=0; i&amp;lt;ids.length; i++){&lt;br /&gt;    snd = getSound(ids[i]);&lt;br /&gt;    if(snd!=null){&lt;br /&gt;     sndAry.push(snd);&lt;br /&gt;    }&lt;br /&gt;   }&lt;br /&gt;   &lt;br /&gt;   //存放一個 sound channel 與多個 Sound 組成的陣列&lt;br /&gt;   var soundList:Object = {channel: null, list: sndAry};&lt;br /&gt;   __soundLists.push(soundList);&lt;br /&gt;   playListObject(soundList);&lt;br /&gt;  }&lt;br /&gt;  &lt;br /&gt;  /**&lt;br /&gt;   * 播放指定的串列音效 &lt;br /&gt;   * @param soundList&lt;br /&gt;   * &lt;br /&gt;   */  &lt;br /&gt;  private function playListObject(soundList:Object):void{&lt;br /&gt;   var sndAry:Array = soundList["list"];&lt;br /&gt;   if(sndAry.length&amp;gt;0){&lt;br /&gt;    //播放串列中的下一個音效&lt;br /&gt;    var snd:Sound = sndAry.splice(0, 1)[0];&lt;br /&gt;    soundList["channel"] = snd.play();&lt;br /&gt;    (soundList["channel"] as SoundChannel).addEventListener(Event.SOUND_COMPLETE, onPlayListSoundComplete);&lt;br /&gt;   }else{&lt;br /&gt;    //這個串列的音效都播完了&lt;br /&gt;    for(var i:uint=0; i&amp;lt;__soundLists.length; i++){&lt;br /&gt;     if(__soundLists[i]==soundList){&lt;br /&gt;      __soundLists.splice(i, 1);&lt;br /&gt;      dispatchEvent(new Event(Event.SOUND_COMPLETE)); //串列音效播放完畢&lt;br /&gt;      return;&lt;br /&gt;     }&lt;br /&gt;    }&lt;br /&gt;   }&lt;br /&gt;  }&lt;br /&gt;  &lt;br /&gt;  /**&lt;br /&gt;   * 串列音效中的某一個音效播完時，準備播下一個 &lt;br /&gt;   * @param e&lt;br /&gt;   * &lt;br /&gt;   */  &lt;br /&gt;  private function onPlayListSoundComplete(e:Event):void{&lt;br /&gt;   for(var i:uint=0; i&amp;lt;__soundLists.length; i++){&lt;br /&gt;    if(__soundLists[i]["channel"]==(e.currentTarget as SoundChannel)){&lt;br /&gt;     playListObject(__soundLists[i]); //播放串列中的下一個&lt;br /&gt;     return;&lt;br /&gt;    }&lt;br /&gt;   }&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt; }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;測試方法，首先先準備一個 sound.swf，裡面在 Library 中準備兩個 *.mp3，並且匯出在第一影格，類別名稱取名 "S1" 與 "S2"。在場景畫面上不用放置任何內容。&lt;br /&gt;&lt;br /&gt;再來，在 main.swf 的 frame 1 上寫：&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;var soundMgr:SoundManager = SoundManager.getInstance();   &lt;br /&gt;soundMgr.addEventListener(SoundManager.SOUND_LOADED, onSoundLoaded);&lt;br /&gt;soundMgr.load("sound.swf");&lt;br /&gt;  &lt;br /&gt;function onSoundLoaded(e:Event):void{&lt;br /&gt; soundMgr.play("S2");&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;開始測試時，就會聽到 main.swf 播放在 sound.swf 中的 "S2" 類別的音效。&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;若是 main.swf 的 frame 1 改寫成：&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;var soundMgr:SoundManager = SoundManager.getInstance();   &lt;br /&gt;soundMgr.addEventListener(SoundManager.SOUND_LOADED, onSoundLoaded);&lt;br /&gt;soundMgr.load("sound.swf");&lt;br /&gt;  &lt;br /&gt;function onSoundLoaded(e:Event):void{&lt;br /&gt; soundMgr.playList("S2", "S1");&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;則測試時，就會先播放 "S2" 類別的音效後，再接著播放 "S1" 類別的音效。&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4754237190569973724-4342525707052715813?l=blog.ben.idv.tw' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.ben.idv.tw/feeds/4342525707052715813/comments/default' title='張貼意見'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4754237190569973724&amp;postID=4342525707052715813' title='0 個意見'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4754237190569973724/posts/default/4342525707052715813'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4754237190569973724/posts/default/4342525707052715813'/><link rel='alternate' type='text/html' href='http://blog.ben.idv.tw/2009/03/classloader.html' title='將 ClassLoader 用於音效管理'/><author><name>Ben Chang</name><uri>http://www.blogger.com/profile/01921640246111819069</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4754237190569973724.post-3858154248824384556</id><published>2009-03-02T16:24:00.003+08:00</published><updated>2009-03-02T17:26:47.935+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Class Loader'/><category scheme='http://www.blogger.com/atom/ns#' term='AS3'/><category scheme='http://www.blogger.com/atom/ns#' term='Flash'/><category scheme='http://www.blogger.com/atom/ns#' term='ApplicationDomain'/><title type='text'>使用 ClassLoader 載入外部 swf 中的 class</title><content type='html'>官方 HELP 中有段範例：&lt;br /&gt;&lt;br /&gt;http://livedocs.adobe.com/flash/9.0/ActionScriptLangRefV3/flash/system/ApplicationDomain.html#includeExamplesSummary&lt;br /&gt;&lt;br /&gt;是談到當 main.swf 載入外部的 asset.swf 後，要使用 asset.swf 中的 Class 來動態產生物件時，要注意 ApplicationDomain 的設定。&lt;br /&gt;&lt;br /&gt;在這個範例中最有意義的是 ClassLoader，透過這個好用的類別，你可以任意載入 *.swf，然後使用 function getClass(className:String):Class 取得在 asset.swf 中的類別，並產生物件。&lt;br /&gt;&lt;br /&gt;我將這個 ClassLoader 類別作了一點點修改，當第一次載入完成後便會將 ByteArray 存在 cache 中，若是有不小心載入到同一個 *.swf 的話，就不會再從 server 作 request，而是從 cache 中找出之前載入過的 ByteArray 即可。&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;package&lt;br /&gt;{&lt;br /&gt; import flash.display.Loader;&lt;br /&gt; import flash.errors.IllegalOperationError;&lt;br /&gt; import flash.events.Event;&lt;br /&gt; import flash.events.EventDispatcher;&lt;br /&gt; import flash.events.IOErrorEvent;&lt;br /&gt; import flash.events.SecurityErrorEvent;&lt;br /&gt; import flash.net.URLLoader;&lt;br /&gt; import flash.net.URLLoaderDataFormat;&lt;br /&gt; import flash.net.URLRequest;&lt;br /&gt; import flash.system.ApplicationDomain;&lt;br /&gt; import flash.system.LoaderContext;&lt;br /&gt; import flash.utils.ByteArray;&lt;br /&gt;&lt;br /&gt; public class ClassLoader extends EventDispatcher&lt;br /&gt; {&lt;br /&gt;  public static var CLASS_LOADED:String = "classLoaded";&lt;br /&gt;     public static var LOAD_ERROR:String = "loadError";&lt;br /&gt;     private var loader:Loader;&lt;br /&gt;     private var swfLib:String;&lt;br /&gt;     private var request:URLRequest;&lt;br /&gt;     private var loadedClass:Class;&lt;br /&gt;     &lt;br /&gt;     static private var cache:Object = new Object();&lt;br /&gt;   private var lib:String;   &lt;br /&gt;    &lt;br /&gt;  public function ClassLoader(lib:String)&lt;br /&gt;  {&lt;br /&gt;   this.lib = lib;&lt;br /&gt;   &lt;br /&gt;   loader = new Loader();&lt;br /&gt;         loader.contentLoaderInfo.addEventListener(Event.COMPLETE,completeHandler);&lt;br /&gt;         loader.contentLoaderInfo.addEventListener(IOErrorEvent.IO_ERROR,ioErrorHandler);&lt;br /&gt;         loader.contentLoaderInfo.addEventListener(SecurityErrorEvent.SECURITY_ERROR,securityErrorHandler);&lt;br /&gt;  }&lt;br /&gt;  &lt;br /&gt;  public function load():void {&lt;br /&gt;   if(cache[lib]!=null){&lt;br /&gt;    loadFromCache();&lt;br /&gt;   }else{&lt;br /&gt;    var urlLoader:URLLoader = new URLLoader();&lt;br /&gt;    urlLoader.dataFormat = URLLoaderDataFormat.BINARY;&lt;br /&gt;    urlLoader.addEventListener(Event.COMPLETE, urlLoaderComplete);&lt;br /&gt;    urlLoader.load(new URLRequest(lib));&lt;br /&gt;   }&lt;br /&gt;     }&lt;br /&gt;     &lt;br /&gt;     private function urlLoaderComplete(e:Event):void{&lt;br /&gt;   cache[lib] = (e.currentTarget as URLLoader).data;&lt;br /&gt;   loadFromCache();&lt;br /&gt;  }&lt;br /&gt;  &lt;br /&gt;  private function loadFromCache(){&lt;br /&gt;   var ba:ByteArray = cache[lib] as ByteArray;&lt;br /&gt;   &lt;br /&gt;         var context:LoaderContext = new LoaderContext();&lt;br /&gt;         context.applicationDomain=ApplicationDomain.currentDomain;&lt;br /&gt;         &lt;br /&gt;         loader.loadBytes(ba, context);&lt;br /&gt;  }&lt;br /&gt; &lt;br /&gt;     public function getClass(className:String):Class {&lt;br /&gt;         try {&lt;br /&gt;             return loader.contentLoaderInfo.applicationDomain.getDefinition(className)  as  Class;&lt;br /&gt;         } catch (e:Error) {&lt;br /&gt;             throw new IllegalOperationError(className + " definition not found in " + swfLib);&lt;br /&gt;         }&lt;br /&gt;         return null;&lt;br /&gt;     }&lt;br /&gt; &lt;br /&gt;     private function completeHandler(e:Event):void {&lt;br /&gt;         dispatchEvent(new Event(ClassLoader.CLASS_LOADED));&lt;br /&gt;     }&lt;br /&gt; &lt;br /&gt;     private function ioErrorHandler(e:Event):void {&lt;br /&gt;         dispatchEvent(new Event(ClassLoader.LOAD_ERROR));&lt;br /&gt;     }&lt;br /&gt; &lt;br /&gt;     private function securityErrorHandler(e:Event):void {&lt;br /&gt;         dispatchEvent(new Event(ClassLoader.LOAD_ERROR));&lt;br /&gt;     }&lt;br /&gt;  &lt;br /&gt; }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;要測試的話，可以先建立一個 asset.swf，裡面準備一個 MovieClip，放在 Library 中，設定其類別為 "MC1"，並且是 "匯出在第 1 個影格"，而場景或畫面上不用放置任何東西，基本上這個 asset.swf 的解析度或其他設定要設多少也都沒關係，因為我們真正會用到的就是那 第一影格會匯出 的類別們。&lt;br /&gt;&lt;br /&gt;第二步，建一個 main.swf，在 frame 1 寫：&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;var clsLoader:ClassLoader = new ClassLoader("asset.swf");&lt;br /&gt;clsLoader.addEventListener(ClassLoader.CLASS_LOADED, onLoaded);&lt;br /&gt;clsLoader.load();&lt;br /&gt;&lt;br /&gt;function onLoaded(e:Event):void{&lt;br /&gt; var runtimeClassRef:Class = clsLoader.getClass("MC1");&lt;br /&gt; var mc1:MovieClip = new runtimeClassRef() as MovieClip;&lt;br /&gt; addChild(mc1);&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;測試後，應該可以發現 main 有將 asset 中的 MC1 類別產生出實體，並放在場景上。&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4754237190569973724-3858154248824384556?l=blog.ben.idv.tw' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.ben.idv.tw/feeds/3858154248824384556/comments/default' title='張貼意見'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4754237190569973724&amp;postID=3858154248824384556' title='2 個意見'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4754237190569973724/posts/default/3858154248824384556'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4754237190569973724/posts/default/3858154248824384556'/><link rel='alternate' type='text/html' href='http://blog.ben.idv.tw/2009/03/classloader-swf-class.html' title='使用 ClassLoader 載入外部 swf 中的 class'/><author><name>Ben Chang</name><uri>http://www.blogger.com/profile/01921640246111819069</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4754237190569973724.post-3964144249682115907</id><published>2009-02-21T16:58:00.003+08:00</published><updated>2009-02-21T17:11:56.265+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ByteArray'/><category scheme='http://www.blogger.com/atom/ns#' term='AS3'/><category scheme='http://www.blogger.com/atom/ns#' term='Flash'/><title type='text'>利用 ByteArray 將 SWF 重新編碼加密</title><content type='html'>一篇舊文章，教如何透過 ByteArray 將 *.swf 進行自訂的編碼，使得一般人無法透過 decompiler 將該 *.swf 解出來。&lt;br /&gt;&lt;br /&gt;文章已不存在，google cache：http://209.85.175.132/search?q=cache:JFsWjtfvv0QJ:lab.lzyy.name/blog/archives/32+swf+bytearray&amp;hl=zh-TW&amp;ct=clnk&amp;cd=1&amp;gl=tw&amp;client=firefox-a&lt;br /&gt;&lt;br /&gt;步驟一，隨便建立一個 swf 當作要被加密的內容檔案，怎麼做不管，假設檔名 asset.swf。&lt;br /&gt;&lt;br /&gt;步驟二，做一個用來進行加密工作的 flash：&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;var ul:URLLoader = new URLLoader();&lt;br /&gt;ul.dataFormat = URLLoaderDataFormat.BINARY;&lt;br /&gt;ul.addEventListener(Event.COMPLETE, onComplete);&lt;br /&gt;ul.load(new URLRequest("asset.swf"));&lt;br /&gt;&lt;br /&gt;function onComplete(e:Event):void{&lt;br /&gt; var ba:ByteArray = (e.target as URLLoader).data;&lt;br /&gt; &lt;br /&gt; ba.compress(); //這裡要代換成一個複雜的加工作業&lt;br /&gt; &lt;br /&gt; var fr:FileReference = new FileReference();&lt;br /&gt; fr.save(ba, "asset_c.swf");&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;簡單來說，就是將 swf 以 binary 的方式讀入，並對 ByteArray 做些改變，再重新存成 swf 檔。這個作業當然也可能應該是由 Server 進行，至於要對 ByteArray 做甚麼樣的資料改變，都可以。&lt;br /&gt;&lt;br /&gt;步驟三，可以用 decompiler 軟體對剛存好的 asset_c.swf 作業看看，就可以發現沒有效果，因為本質上他已經不是 swf format 了。&lt;br /&gt;&lt;br /&gt;步驟四，另外開發一個讀取用的 flash，也就是未來真正要將 asset_c.swf 動態載入進來播放的 main.swf：&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;var ul:URLLoader = new URLLoader();&lt;br /&gt;ul.dataFormat = URLLoaderDataFormat.BINARY;&lt;br /&gt;ul.addEventListener(Event.COMPLETE, onComplete);&lt;br /&gt;ul.load(new URLRequest("asset_c.swf"));&lt;br /&gt;&lt;br /&gt;var loader:Loader = new Loader();&lt;br /&gt;addChild(loader);&lt;br /&gt;&lt;br /&gt;function onComplete(e:Event):void{&lt;br /&gt; var ba:ByteArray = (e.target as URLLoader).data;&lt;br /&gt; &lt;br /&gt; ba.uncompress(); //這裡要代換成一個複雜的加工作業&lt;br /&gt; &lt;br /&gt; loader.loadBytes(ba);&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;解密的部分，要參考加密的過程，反向進行。&lt;br /&gt;&lt;br /&gt;不過，我想聰明如你也會知道，這個 main.swf 仍是明碼，仍能被 decompiler 給破解出來，以上這作法也就只是為了更加強破解的難度罷了，只好儘量將解密的程式隱藏的複雜一點囉，騙騙君子！&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4754237190569973724-3964144249682115907?l=blog.ben.idv.tw' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.ben.idv.tw/feeds/3964144249682115907/comments/default' title='張貼意見'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4754237190569973724&amp;postID=3964144249682115907' title='0 個意見'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4754237190569973724/posts/default/3964144249682115907'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4754237190569973724/posts/default/3964144249682115907'/><link rel='alternate' type='text/html' href='http://blog.ben.idv.tw/2009/02/bytearray-swf.html' title='利用 ByteArray 將 SWF 重新編碼加密'/><author><name>Ben Chang</name><uri>http://www.blogger.com/profile/01921640246111819069</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4754237190569973724.post-8333751521170710712</id><published>2009-02-21T15:31:00.003+08:00</published><updated>2009-02-21T15:37:14.649+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ByteArray'/><category scheme='http://www.blogger.com/atom/ns#' term='Flash Player'/><category scheme='http://www.blogger.com/atom/ns#' term='swf format'/><title type='text'>SWF Parser</title><content type='html'>有一篇舊文章，連原始文章都不在了，只能靠 google cache 看到：&lt;br /&gt;&lt;br /&gt;http://72.14.235.132/search?q=cache:OUVn3qZqmC4J:flashpanoramas.com/blog/2007/07/02/swf-parser-air-application/+swf+bytearray&amp;hl=zh-TW&amp;ct=clnk&amp;cd=6&amp;gl=tw&amp;client=firefox-a&lt;br /&gt;&lt;br /&gt;提到因為 ByteArray 的關係，所以其實我們在 Flash 中就可以讀取另一個 swf 的資訊，程式碼如下：&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;/*&lt;br /&gt;Simple SWF parser&lt;br /&gt;Written by Denis V. Chumakov &lt;br /&gt;http://flashpanoramas.com/blog/&lt;br /&gt;Use this code without any restrictions.&lt;br /&gt;*/&lt;br /&gt;&lt;br /&gt;// log string&lt;br /&gt;var parseLog:String;&lt;br /&gt;&lt;br /&gt;// handlers for SWF tags&lt;br /&gt;// for example: &lt;br /&gt;// handlers[6] = parseJPEG; &lt;br /&gt;// to set your handler for DefineBitsJPEG tag.&lt;br /&gt;// you can find SWF file specifications in Google.&lt;br /&gt;var handlers:Array = [];&lt;br /&gt;&lt;br /&gt;// parse SWF file&lt;br /&gt;function parseSWF(data:ByteArray) {&lt;br /&gt; parseLog = "";&lt;br /&gt; data.endian = Endian.LITTLE_ENDIAN;&lt;br /&gt; var format:String = data.readUTFBytes(3);&lt;br /&gt; var compressed:Boolean = format=="CWS";&lt;br /&gt; if (format=="FWS" || format=="CWS") {&lt;br /&gt;  parseLog += "SWF version "+data.readByte();&lt;br /&gt;  parseLog += ", size: "+data.readUnsignedInt();&lt;br /&gt; } else {&lt;br /&gt;  parseLog += "Not a Flash file.";&lt;br /&gt;  return;&lt;br /&gt; }&lt;br /&gt; data.readBytes(data);&lt;br /&gt; data.length -= 8;&lt;br /&gt; if (compressed) {&lt;br /&gt;  data.uncompress();&lt;br /&gt; }&lt;br /&gt; data.position = 0;&lt;br /&gt; var frame:Array = readBox(data);&lt;br /&gt; parseLog += "\n";&lt;br /&gt; parseLog += "Width: "+Math.round((frame[1]-frame[0])/20);&lt;br /&gt; parseLog += ", height: "+Math.round((frame[3]-frame[2])/20);&lt;br /&gt; var fps_f:uint = data.readUnsignedByte();&lt;br /&gt; var fps_i:uint = data.readUnsignedByte();&lt;br /&gt; parseLog += "\n";&lt;br /&gt; parseLog += "FPS: "+(fps_i+fps_f/256);&lt;br /&gt; var count:uint = data.readUnsignedShort();&lt;br /&gt; parseLog += "\n";&lt;br /&gt; parseLog += "Total frames: "+count;&lt;br /&gt; parseLog += "\n";&lt;br /&gt; while (data.bytesAvailable) {&lt;br /&gt;  readSWFTag(data);&lt;br /&gt; }&lt;br /&gt; trace(parseLog);&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;// read SWF tag and call handler if present&lt;br /&gt;function readSWFTag(data:ByteArray) {&lt;br /&gt; var tag:uint = data.readUnsignedShort();&lt;br /&gt; var id:int = tag&amp;gt;&amp;gt;6;&lt;br /&gt; var size:int = tag&amp;0x3F;&lt;br /&gt; if (size == 0x3F) {&lt;br /&gt;  size = data.readUnsignedInt();&lt;br /&gt; }&lt;br /&gt; parseLog += "\n";&lt;br /&gt; parseLog += "Tag "+id;&lt;br /&gt; if (handlers[id]!=null) {&lt;br /&gt;  var dump:ByteArray = new ByteArray();&lt;br /&gt;  if (size!=0) {&lt;br /&gt;   data.readBytes(dump,0,size);&lt;br /&gt;  }&lt;br /&gt;  handlers[id](tag, id, size, dump);&lt;br /&gt; } else {&lt;br /&gt;  data.position += size;&lt;br /&gt; }&lt;br /&gt; parseLog += "\tsize: "+size;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;// read compressed box format&lt;br /&gt;function readBox(data:ByteArray):Array {&lt;br /&gt; var c:Array = [];&lt;br /&gt; var current:uint = data.readUnsignedByte();&lt;br /&gt; var size:uint = current&amp;gt;&amp;gt;3;&lt;br /&gt; var off:int = 3;&lt;br /&gt; for (var i:int=0; i&amp;lt;4; i+=1) {&lt;br /&gt;  c[i] = current&amp;lt;&amp;lt;(32-off)&amp;gt;&amp;gt;(32-size);&lt;br /&gt;  off -= size;&lt;br /&gt;  while (off&amp;lt;0) {&lt;br /&gt;   current = data.readUnsignedByte();&lt;br /&gt;   c[i] |= off&amp;lt;-8?current&amp;lt;&amp;lt;(-off-8):current&amp;gt;&amp;gt;(-off-8);&lt;br /&gt;   off += 8;&lt;br /&gt;  }&lt;br /&gt; }&lt;br /&gt; return c;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;var loader:URLLoader = new URLLoader();&lt;br /&gt;loader.dataFormat = URLLoaderDataFormat.BINARY;&lt;br /&gt;loader.addEventListener(Event.COMPLETE, loadComplete);&lt;br /&gt;// load complete handler&lt;br /&gt;function loadComplete(event:Event) {&lt;br /&gt; parseSWF(loader.data);&lt;br /&gt;}&lt;br /&gt;loader.load(new URLRequest("asset.swf"));&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;最後一句的 swf 檔名你自己換～&lt;br /&gt;&lt;br /&gt;輸出結果：&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;SWF version 10, size: 1404&lt;br /&gt;Width: 50, height: 50&lt;br /&gt;FPS: 24&lt;br /&gt;Total frames: 1&lt;br /&gt;&lt;br /&gt;Tag 69 size: 4&lt;br /&gt;Tag 77 size: 1284&lt;br /&gt;Tag 9 size: 3&lt;br /&gt;Tag 86 size: 12&lt;br /&gt;Tag 83 size: 48&lt;br /&gt;Tag 26 size: 6&lt;br /&gt;Tag 1 size: 0&lt;br /&gt;Tag 0 size: 0&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;其實 swf format 早已是公開的文件，有興趣的話可以自己寫一個 swf generator 或是 flash player。&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4754237190569973724-8333751521170710712?l=blog.ben.idv.tw' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.ben.idv.tw/feeds/8333751521170710712/comments/default' title='張貼意見'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4754237190569973724&amp;postID=8333751521170710712' title='0 個意見'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4754237190569973724/posts/default/8333751521170710712'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4754237190569973724/posts/default/8333751521170710712'/><link rel='alternate' type='text/html' href='http://blog.ben.idv.tw/2009/02/swf-parser.html' title='SWF Parser'/><author><name>Ben Chang</name><uri>http://www.blogger.com/profile/01921640246111819069</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4754237190569973724.post-4212443643135205588</id><published>2009-02-21T12:01:00.003+08:00</published><updated>2009-02-21T12:26:58.890+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Flash Player'/><category scheme='http://www.blogger.com/atom/ns#' term='AS3'/><category scheme='http://www.blogger.com/atom/ns#' term='Flash'/><title type='text'>時間軸預置物件的參考物件的特性</title><content type='html'>遇到一個現象。&lt;br /&gt;&lt;br /&gt;在 flash 中請像以下畫面這樣設計，在場景上放置一個叫作 m1 的 MovieClip，出現在 frame 1~10 與 frame 21~30 (第二次出現時要改變座標)：&lt;br /&gt;&lt;br /&gt;&lt;a target="_blank" onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_HsFEtLMw5zU/SZ98lmHxZMI/AAAAAAAAJRc/cl_neKk-TCY/s1600-h/Clipboard01.jpg"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 377px; height: 400px;" src="http://1.bp.blogspot.com/_HsFEtLMw5zU/SZ98lmHxZMI/AAAAAAAAJRc/cl_neKk-TCY/s400/Clipboard01.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5305095871395882178" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;然後 frame 1 的程式：&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;var n1:MovieClip = m1;&lt;br /&gt;&lt;br /&gt;function on_EnterFrame(e:Event):void{&lt;br /&gt; trace(currentFrame, m1, n1, n1.parent, n1.x + ", " + n1.y, m1==n1);&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;addEventListener(Event.ENTER_FRAME, on_EnterFrame);&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;輸出時，訊息為：&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;2 [object MovieClip] [object MovieClip] [object MainTimeline] 58, 139 true&lt;br /&gt;3 [object MovieClip] [object MovieClip] [object MainTimeline] 58, 139 true&lt;br /&gt;...&lt;br /&gt;...&lt;br /&gt;9 [object MovieClip] [object MovieClip] [object MainTimeline] 58, 139 true&lt;br /&gt;10 [object MovieClip] [object MovieClip] [object MainTimeline] 58, 139 true&lt;br /&gt;11 null [object MovieClip] [object MainTimeline] 58, 139 false&lt;br /&gt;12 null [object MovieClip] [object MainTimeline] 58, 139 false&lt;br /&gt;...&lt;br /&gt;...&lt;br /&gt;19 null [object MovieClip] [object MainTimeline] 58, 139 false&lt;br /&gt;20 null [object MovieClip] [object MainTimeline] 58, 139 false&lt;br /&gt;21 null [object MovieClip] [object MainTimeline] 58, 139 false&lt;br /&gt;22 [object MovieClip] [object MovieClip] [object MainTimeline] 58, 139 false&lt;br /&gt;23 [object MovieClip] [object MovieClip] [object MainTimeline] 58, 139 false&lt;br /&gt;...&lt;br /&gt;...&lt;br /&gt;29 [object MovieClip] [object MovieClip] [object MainTimeline] 58, 139 false&lt;br /&gt;30 [object MovieClip] [object MovieClip] [object MainTimeline] 58, 139 false&lt;br /&gt;31 null [object MovieClip] [object MainTimeline] 58, 139 false&lt;br /&gt;32 null [object MovieClip] [object MainTimeline] 58, 139 false&lt;br /&gt;...&lt;br /&gt;...&lt;br /&gt;39 null [object MovieClip] [object MainTimeline] 58, 139 false&lt;br /&gt;40 null [object MovieClip] [object MainTimeline] 58, 139 false&lt;br /&gt;1 null [object MovieClip] [object MainTimeline] 58, 139 false&lt;br /&gt;...&lt;br /&gt;...&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;我要說明的現象是：&lt;br /&gt;&lt;br /&gt;1. 若是我們建立一個物件 n1 參考到時間軸上的預置物件 m1，當 m1 因空白影格而移除後，參考物件 n1 仍能參考到 MovieClip。&lt;br /&gt;&lt;br /&gt;2. 參考物件 n1 的 parent 仍是參考到 Timeline。&lt;br /&gt;&lt;br /&gt;3. 當 m1 於 frame 21 再次出現時，n1 參考到的物件仍是在 frame 1 所出現的 m1，這點可由 n1 的 x, y 座標仍維持不變得知。而且 frame 22 時的 m1==n1 也是 false。&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;更有意思的是，以上的測試環境是 Flash CS4 發佈成 Flash Player 9 的情況，若是發佈成 Flash Player 10 的話：&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;2 [object MovieClip] [object MovieClip] [object MainTimeline] 58, 139 true&lt;br /&gt;3 [object MovieClip] [object MovieClip] [object MainTimeline] 58, 139 true&lt;br /&gt;...&lt;br /&gt;...&lt;br /&gt;9 [object MovieClip] [object MovieClip] [object MainTimeline] 58, 139 true&lt;br /&gt;10 [object MovieClip] [object MovieClip] [object MainTimeline] 58, 139 true&lt;br /&gt;11 null [object MovieClip] null 58, 139 false&lt;br /&gt;12 null [object MovieClip] null 58, 139 false&lt;br /&gt;...&lt;br /&gt;...&lt;br /&gt;20 null [object MovieClip] null 58, 139 false&lt;br /&gt;21 null [object MovieClip] null 58, 139 false&lt;br /&gt;22 [object MovieClip] [object MovieClip] null 58, 139 false&lt;br /&gt;23 [object MovieClip] [object MovieClip] null 58, 139 false&lt;br /&gt;...&lt;br /&gt;...&lt;br /&gt;29 [object MovieClip] [object MovieClip] null 58, 139 false&lt;br /&gt;30 [object MovieClip] [object MovieClip] null 58, 139 false&lt;br /&gt;31 null [object MovieClip] null 58, 139 false&lt;br /&gt;32 null [object MovieClip] null 58, 139 false&lt;br /&gt;...&lt;br /&gt;...&lt;br /&gt;39 null [object MovieClip] null 58, 139 false&lt;br /&gt;40 null [object MovieClip] null 58, 139 false&lt;br /&gt;1 null [object MovieClip] null 58, 139 false&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;觀察到的是，當 m1 被移除時，參考物件 n1 的 parent 也同時被設為 null 了。&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;不論測試環境是 FP9 或 FP10，n1 都是參考到 frame 1 上的 m1，不同的是在 FP10 時，當 m1 被移除時，m1 的 parent 也會被移除，所以參考到 m1 的 n1 的 parent 就變成 null 了。&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4754237190569973724-4212443643135205588?l=blog.ben.idv.tw' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.ben.idv.tw/feeds/4212443643135205588/comments/default' title='張貼意見'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4754237190569973724&amp;postID=4212443643135205588' title='1 個意見'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4754237190569973724/posts/default/4212443643135205588'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4754237190569973724/posts/default/4212443643135205588'/><link rel='alternate' type='text/html' href='http://blog.ben.idv.tw/2009/02/blog-post.html' title='時間軸預置物件的參考物件的特性'/><author><name>Ben Chang</name><uri>http://www.blogger.com/profile/01921640246111819069</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/_HsFEtLMw5zU/SZ98lmHxZMI/AAAAAAAAJRc/cl_neKk-TCY/s72-c/Clipboard01.jpg' height='72' width='72'/><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4754237190569973724.post-6691164397754315194</id><published>2009-02-07T10:34:00.002+08:00</published><updated>2009-02-07T10:50:42.911+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='AS3'/><category scheme='http://www.blogger.com/atom/ns#' term='Flash'/><title type='text'>Main Document 如何在 Flash 移至指定 Frame 後做事情</title><content type='html'>寫 AS3，或是說寫 Flex，或是說早先 Flash 有支援的 幻燈片、簡報式、表單式 的開發模式，越來越不會考量到 Timeline 的問題，都是假設 Flash 中只有一個 Frame，但是當 Flash 還是由美術設計所提供時，Timeline 對於開發人員來說就很麻煩了。&lt;br /&gt;&lt;br /&gt;在 Main Document 類別中，若是我們寫了 gotoAndPlay("frame name") 後，想要當移至該 Frame 時就進行某些工作，譬如設定場景上的元素的初始值，這時我們只有 Event.ENTER_FRAME 事件可以協助，但是 Event.ENTER_FRAME 看來又發生得比 場景上的元素載入完成 來得早。&lt;br /&gt;&lt;br /&gt;於是，我寫了以下這個程式，為了當移至指定的 Frame 後，Event.ENTER_FRAME 發生第二次時，可以呼叫我們的程式：&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;package aa.bb.cc.dd.utils&lt;br /&gt;{&lt;br /&gt; import flash.display.MovieClip;&lt;br /&gt; import flash.events.Event;&lt;br /&gt; &lt;br /&gt; public class FrameController&lt;br /&gt; {&lt;br /&gt;  private var mc:MovieClip;&lt;br /&gt;  private var callback:Function;&lt;br /&gt;  private var enterFrameCnt:uint;&lt;br /&gt;  &lt;br /&gt;  public function FrameController(mc:MovieClip){&lt;br /&gt;   this.mc = mc;&lt;br /&gt;   &lt;br /&gt;   enterFrameCnt = 0;&lt;br /&gt;  }&lt;br /&gt;  &lt;br /&gt;  public function gotoAndPlay(frame:Object, callback:Function):void{&lt;br /&gt;   this.callback = callback;&lt;br /&gt;   &lt;br /&gt;   mc.addEventListener(Event.ENTER_FRAME, onEnterFrame);&lt;br /&gt;   mc.gotoAndPlay(frame);&lt;br /&gt;  }&lt;br /&gt;  &lt;br /&gt;  public function gotoAndStop(frame:Object, callback:Function):void{&lt;br /&gt;   this.callback = callback;&lt;br /&gt;   &lt;br /&gt;   mc.addEventListener(Event.ENTER_FRAME, onEnterFrame);&lt;br /&gt;   mc.gotoAndStop(frame);&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  private function onEnterFrame(e:Event):void{&lt;br /&gt;   enterFrameCnt++;&lt;br /&gt;   &lt;br /&gt;   if(enterFrameCnt==2){&lt;br /&gt;    callback();&lt;br /&gt;    mc.removeEventListener(Event.ENTER_FRAME, onEnterFrame);&lt;br /&gt;    destroy();&lt;br /&gt;   }&lt;br /&gt;  }&lt;br /&gt;  &lt;br /&gt;  private function destroy():void{&lt;br /&gt;   mc = null;&lt;br /&gt;   callback = null;&lt;br /&gt;   delete this;&lt;br /&gt;  }&lt;br /&gt; }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;在 Main Document 想要使用的時候：&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;  &lt;br /&gt;  private function gotoFrameAAA():void{&lt;br /&gt;   var fc:FrameController = new FrameController(this);&lt;br /&gt;   fc.gotoAndStop("frame aaa", onGotoFrameAAA);&lt;br /&gt;  }&lt;br /&gt;  private function onGotoFrameAAA():void{&lt;br /&gt;   ......&lt;br /&gt;  }&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;尚未進行太複雜的測試，基本上，我想，別同時對同一個 MovieClip 都進行這項工作，應該無大礙，不然有可能會有某個 FrameController 會在 Event.ENTER_FRAME 發生第二次時，回呼其實你已經不想要執行的函式，因為實際上你可能已經透過第二個 FrameController 跳到別的 Frame 去了。&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4754237190569973724-6691164397754315194?l=blog.ben.idv.tw' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.ben.idv.tw/feeds/6691164397754315194/comments/default' title='張貼意見'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4754237190569973724&amp;postID=6691164397754315194' title='8 個意見'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4754237190569973724/posts/default/6691164397754315194'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4754237190569973724/posts/default/6691164397754315194'/><link rel='alternate' type='text/html' href='http://blog.ben.idv.tw/2009/02/main-document-flash-frame.html' title='Main Document 如何在 Flash 移至指定 Frame 後做事情'/><author><name>Ben Chang</name><uri>http://www.blogger.com/profile/01921640246111819069</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>8</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4754237190569973724.post-3416869201660673471</id><published>2009-02-07T09:40:00.005+08:00</published><updated>2009-02-07T10:32:53.384+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='AS3'/><category scheme='http://www.blogger.com/atom/ns#' term='Flash'/><title type='text'>Flash 不同 Frame 加入的元素，Main Document 中如何得知</title><content type='html'>使用 Flash IDE，程式碼卻都寫成 *.as，並且用其他開發工具(Flex Builder 或 FlashDevelop) 來開發。這種模式在美術程式切得很開的公司會遇到，因為程式開發人員不喜歡 Flash。&lt;br /&gt;&lt;br /&gt;這時，就遇到一些問題，譬如 Main Document 的類別，如何拿到場景上的 TextField 與 Button 呢？尤其是美術設計所設計出來的 Flash 不是只有一個 Frame 的時候。當 Main Document 載入其類別時，若類別中有指定 TextField 的話，是抓不到 Frame 2 場景上的物件的。&lt;br /&gt;&lt;br /&gt;為處理這樣的問題，我做了一個 UIManager，負責用來記錄這些 場景上的元件 的參考：&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;package aa.bb.cc.dd.ui&lt;br /&gt;{&lt;br /&gt; import aa.bb.cc.dd.event.XxxBtnClickEvent;&lt;br /&gt; &lt;br /&gt; import flash.events.*;&lt;br /&gt; import flash.text.TextField;&lt;br /&gt; &lt;br /&gt; public class UIManager extends EventDispatcher&lt;br /&gt; {&lt;br /&gt;  public var txtAAA:TextField;&lt;br /&gt;  public var txtBBB:TextField;&lt;br /&gt;  &lt;br /&gt;  public var btnCCC:XxxBtn;&lt;br /&gt;  public var btnDDD:XxxBtn;&lt;br /&gt;  &lt;br /&gt;  static private var __instance:UIManager;&lt;br /&gt;  static public function getInstance():UIManager{&lt;br /&gt;   if(__instance==null){&lt;br /&gt;    __instance = new UIManager();&lt;br /&gt;   }&lt;br /&gt;   return __instance;&lt;br /&gt;  }&lt;br /&gt;  &lt;br /&gt;  public function registerTextSprite(obj:TextSprite):void{&lt;br /&gt;   obj.addEventListener(Event.ADDED_TO_STAGE, onAddedToStage);&lt;br /&gt;   obj.addEventListener(Event.REMOVED_FROM_STAGE, onRemoveFromStage);&lt;br /&gt;  }&lt;br /&gt;  &lt;br /&gt;  public function registerXxxBtn(obj:XxxBtn):void{&lt;br /&gt;   obj.addEventListener(Event.ADDED_TO_STAGE, onAddedToStage);&lt;br /&gt;   obj.addEventListener(Event.REMOVED_FROM_STAGE, onRemoveFromStage);&lt;br /&gt;  }&lt;br /&gt;  &lt;br /&gt;  private function onAddedToStage(e:Event):void{&lt;br /&gt;   if(e.target is TextSprite){&lt;br /&gt;    UIManager.getInstance()[e.target.id] = e.target.txt;&lt;br /&gt;   }else if(e.target is XxxBtn){&lt;br /&gt;    var btn:XxxBtn = e.target as XxxBtn;&lt;br /&gt;    btn.addEventListener(MouseEvent.CLICK, onXxxBtnClick);&lt;br /&gt;    &lt;br /&gt;    UIManager.getInstance()[e.target.id] = btn;&lt;br /&gt;   }&lt;br /&gt;  }&lt;br /&gt;  &lt;br /&gt;  private function onRemoveFromStage(e:Event):void{&lt;br /&gt;   if(e.target is TextSprite){&lt;br /&gt;    UIManager.getInstance()[e.target.id] = null;&lt;br /&gt;   }else if(e.target is GameBtn){&lt;br /&gt;    var btn:XxxBtn = e.target as XxxBtn;&lt;br /&gt;    btn.removeEventListener(MouseEvent.CLICK, onXxxBtnClick);&lt;br /&gt;    &lt;br /&gt;    UIManager.getInstance()[e.target.id] = null;&lt;br /&gt;   }&lt;br /&gt;  }&lt;br /&gt;  &lt;br /&gt;  private function onXxxBtnClick(e:MouseEvent):void{&lt;br /&gt;   this.dispatchEvent(new XxxBtnClickEvent(e.currentTarget as XxxBtn));&lt;br /&gt;  }&lt;br /&gt; }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;這個 UIManager 現在我用來協助記錄兩種類型的物件，一種是 TextField，另一種是 XxxBtn。在說明如何使用 UIManager 之前，先概述一下我的想法，我希望在 Flash 中每個想要被控制的 TextField 與 Button(實際上是 SimpleButton) 都能在當自己被加入或移出 Stage 時，對 UIManager 通知並進行相對的處理。&lt;br /&gt;&lt;br /&gt;因為在 Flash 中，Library 中可以放的 Symbol 種類 "傳統上" 只有三種：Graphic、Button、MovieClip，不能放 TextField，所以無法為一個 TextField 指定其所連結的類別。因此在我的設計中，TextField 的做法是一個放在 MovieClip 中的 TextField(instance name 固定為 "txt")，然後再設定此 MovieClip 的連結類別即可。&lt;br /&gt;&lt;br /&gt;所以，我設計了一個 TextSprite 的類別：&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;package aa.bb.cc.dd.ui&lt;br /&gt;{&lt;br /&gt; import flash.display.Sprite;&lt;br /&gt; import flash.text.TextField;&lt;br /&gt;&lt;br /&gt; public class TextSprite extends Sprite&lt;br /&gt; {&lt;br /&gt;  public var id:String;&lt;br /&gt;  public var txt:TextField;&lt;br /&gt;  &lt;br /&gt;  public function TextSprite(id:String)&lt;br /&gt;  {&lt;br /&gt;   super();&lt;br /&gt;   &lt;br /&gt;   this.id = id;&lt;br /&gt;   UIManager.getInstance().registerTextSprite(this);&lt;br /&gt;  }&lt;br /&gt; }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;接著，每個想要放在場景上的 TextField(被包在一個 MovieClip) 都需要撰寫各自的類別，繼承自 TextSprite，譬如 TextSpriteAAA：&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;package aa.bb.cc.dd.ui&lt;br /&gt;{&lt;br /&gt; import flash.text.TextField;&lt;br /&gt;&lt;br /&gt; public class TextSpriteAAA extends TextSprite&lt;br /&gt; {&lt;br /&gt;  public function TextSpriteAAA ()&lt;br /&gt;  {&lt;br /&gt;   super("txtAAA");&lt;br /&gt;  }  &lt;br /&gt; }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;目的是在建構函式中，設定這個 TextSprite 的 id，然後就會在 UIManager 中註冊這個 TextSprite 了，也就是將自己的參考提供給 UIManager 記住。&lt;br /&gt;&lt;br /&gt;最後，在 Flash 的 Library 中的 MovieClip(帶有 instance name = "txt" 的 TextField) 的連結類別，指定為 aa.bb.cc.dd.ui.TextSpriteAAA 即可。這樣一來不管美術設計想要將這個文字欄位在哪個 Frame 放到場景上 或 移出場景，UIManager 都會知道了。&lt;br /&gt;&lt;br /&gt;在 Main Document 的類別中，要使用該文字欄位時，只要判斷 UIManager 的 txtAAA 是否為 null 就可以使用了。&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;另外一種物件 SimpleButton，我用一個 XxxBtn 來繼承之，主要也是為了用 id 來區別是哪個按鈕，然後在 UIManager 中記錄：&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;package aa.bb.cc.dd.ui&lt;br /&gt;{&lt;br /&gt; import flash.display.SimpleButton;&lt;br /&gt;&lt;br /&gt; public class XxxBtn extends SimpleButton&lt;br /&gt; {&lt;br /&gt;  public var id:String;&lt;br /&gt;  &lt;br /&gt;  public function XxxBtn(id:String)&lt;br /&gt;  {&lt;br /&gt;   super();&lt;br /&gt;   &lt;br /&gt;   this.id = id;&lt;br /&gt;   UIManager.getInstance().registerXxxBtn(this);&lt;br /&gt;  }&lt;br /&gt; }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;同樣的，場景上每個希望被控制的 Button 都要各自開發一個繼承自 XxxBtn 的類別，譬如&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;package aa.bb.cc.dd.ui&lt;br /&gt;{&lt;br /&gt; public class XxxBtnCCC extends XxxBtn&lt;br /&gt; {&lt;br /&gt;  public function XxxBtnCCC()&lt;br /&gt;  {&lt;br /&gt;   super("btnCCC");&lt;br /&gt;  }&lt;br /&gt;  &lt;br /&gt; }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;然後 Flash 的 Library 中的 Button 指定連結為 aa.bb.cc.dd.ui.XxxBtnCCC 即可。&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;若是你再回頭看看 UIManager 中的程式，在 Add to Stage 時，若是物件為 XxxBtn 的話，UIManager 會監聽其 MouseEvent.CLICK 事件：&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;private function onAddedToStage(e:Event):void{&lt;br /&gt;   if(e.target is TextSprite){&lt;br /&gt;    UIManager.getInstance()[e.target.id] = e.target.txt;&lt;br /&gt;   }else if(e.target is XxxBtn){&lt;br /&gt;    var btn:XxxBtn = e.target as XxxBtn;&lt;br /&gt;    btn.addEventListener(MouseEvent.CLICK, onXxxBtnClick);&lt;br /&gt;    &lt;br /&gt;    UIManager.getInstance()[e.target.id] = btn;&lt;br /&gt;   }&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;......&lt;br /&gt;......&lt;br /&gt;&lt;br /&gt;private function onXxxBtnClick(e:MouseEvent):void{&lt;br /&gt;   this.dispatchEvent(new XxxBtnClickEvent(e.currentTarget as XxxBtn));&lt;br /&gt;  }&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;然後將這個按鈕事件再以 XxxBtnClickEvent 事件送出，並將按鈕資訊(是哪個 XxxBtn 類別的 instance) 存放在 XxxBtnClickEvent 事件中，讓之後的 Main Document 類別可以接收到：&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;package aa.bb.cc.dd.event&lt;br /&gt;{&lt;br /&gt; import aa.bb.cc.dd.ui.XxxBtn;&lt;br /&gt; &lt;br /&gt; import flash.events.Event;&lt;br /&gt;&lt;br /&gt; public class XxxBtnClickEvent extends Event&lt;br /&gt; {&lt;br /&gt;  static public var ON_EVENT:String = "xxx btn click event";&lt;br /&gt;  &lt;br /&gt;  public var xxxBtn:XxxBtn;&lt;br /&gt;  &lt;br /&gt;  public function XxxBtnClickEvent(xxxBtn:XxxBtn)&lt;br /&gt;  {&lt;br /&gt;   super(XxxBtnClickEvent.ON_EVENT);&lt;br /&gt;   &lt;br /&gt;   this.xxxBtn= xxxBtn;&lt;br /&gt;  }  &lt;br /&gt; }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;這樣一來，在 Main Document 類別中，就可以收到這些按鈕被按下的事件，而不用理會這些按鈕是何時被加入或移除場景中了：&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;package {&lt;br /&gt; import aa.bb.cc.dd.event.*;&lt;br /&gt; import aa.bb.cc.dd.ui.*;&lt;br /&gt; &lt;br /&gt; import flash.display.MovieClip;&lt;br /&gt; import flash.events.*;&lt;br /&gt; &lt;br /&gt; public class Main extends MovieClip&lt;br /&gt; {&lt;br /&gt;&lt;br /&gt;......&lt;br /&gt;......&lt;br /&gt;  &lt;br /&gt;  private var uiMgr:UIManager;&lt;br /&gt;  &lt;br /&gt;  private function initComponents():void{&lt;br /&gt;   uiMgr = UIManager.getInstance();&lt;br /&gt;   &lt;br /&gt;   uiMgr.addEventListener(XxxBtnClickEvent.ON_EVENT, onXxxBtnClick);&lt;br /&gt;  }&lt;br /&gt;  &lt;br /&gt;  private function onXxxBtnClick(e:XxxBtnClickEvent):void{&lt;br /&gt;   switch(e.xxxBtn.id){&lt;br /&gt;    case "btnCCC":&lt;br /&gt;     btnCCC_click();&lt;br /&gt;     break;&lt;br /&gt;    case "btnDDD":&lt;br /&gt;     btnDDD_click();&lt;br /&gt;     break;&lt;br /&gt;    default:&lt;br /&gt;     throw new Error("not handle xxx btn event: " + e.xxxBtn.id);&lt;br /&gt;   }&lt;br /&gt;  }&lt;br /&gt;  &lt;br /&gt;  &lt;br /&gt; }&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;以上，堪用，若需再加強，歡迎大家提點！&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4754237190569973724-3416869201660673471?l=blog.ben.idv.tw' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.ben.idv.tw/feeds/3416869201660673471/comments/default' title='張貼意見'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4754237190569973724&amp;postID=3416869201660673471' title='2 個意見'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4754237190569973724/posts/default/3416869201660673471'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4754237190569973724/posts/default/3416869201660673471'/><link rel='alternate' type='text/html' href='http://blog.ben.idv.tw/2009/02/flash-frame-main-document.html' title='Flash 不同 Frame 加入的元素，Main Document 中如何得知'/><author><name>Ben Chang</name><uri>http://www.blogger.com/profile/01921640246111819069</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4754237190569973724.post-2186630045670563578</id><published>2009-02-05T13:59:00.003+08:00</published><updated>2009-02-05T14:11:23.969+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Flash Player'/><category scheme='http://www.blogger.com/atom/ns#' term='Flash'/><category scheme='http://www.blogger.com/atom/ns#' term='Browser'/><title type='text'>IE 在同一頁處理過多 Flash 時</title><content type='html'>這兩天遇到一個詭異的問題，發現 IE 的 Flash Player 外掛的 bug。&lt;br /&gt;&lt;br /&gt;需求是這樣的，若是我們希望用 Flash 作一些簡單資料的呈現，譬如 Image Viewer 或其他數字的顯示，而資料是由 HTML 在一開始建立 Flash 標籤時就帶入的。當在一頁 HTML 中，若要顯示這同樣的 swf 達到 100 個的時候，在 Firefox 可以正常顯示，但是 IE 就會發生錯誤而當掉。&lt;br /&gt;&lt;br /&gt;假設，準備一個 demo.fla(AS3)，裡面只放一個 t1 的文字欄位，在 frame 1 的程式碼為：&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;var paramObj:Object = LoaderInfo(this.root.loaderInfo).parameters;&lt;br /&gt;t1.text = paramObj["v1"];&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;用來接收來自預設參數 v1 並顯示在 t1 文字欄位中。&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;接下來，將輸出的 demo.htm 修改一點程式碼，讓他跑迴圈產生 100 筆：&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&amp;lt;html xmlns="http://www.w3.org/1999/xhtml" xml:lang="zh_tw" lang="zh_tw"&amp;gt;&lt;br /&gt;&amp;lt;head&amp;gt;&lt;br /&gt;&amp;lt;meta http-equiv="Content-Type" content="text/html; charset=big5" /&amp;gt;&lt;br /&gt;&amp;lt;title&amp;gt;demo&amp;lt;/title&amp;gt;&lt;br /&gt;&amp;lt;script language="javascript"&amp;gt;AC_FL_RunContent = 0;&amp;lt;/script&amp;gt;&lt;br /&gt;&amp;lt;script src="AC_RunActiveContent.js" language="javascript"&amp;gt;&amp;lt;/script&amp;gt;&lt;br /&gt;&amp;lt;/head&amp;gt;&lt;br /&gt;&amp;lt;body bgcolor="#ffffff"&amp;gt;&lt;br /&gt;&amp;lt;!-- saved from url=(0013)about:internet --&amp;gt;&lt;br /&gt;&amp;lt;script language="javascript"&amp;gt;&lt;br /&gt; if (AC_FL_RunContent == 0) {&lt;br /&gt;  alert("這個頁面必須具備 AC_RunActiveContent.js。");&lt;br /&gt; } else {&lt;br /&gt;  for(var i=0; i&amp;lt;100; i++)&lt;br /&gt;  AC_FL_RunContent(&lt;br /&gt;   'codebase', 'http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=9,0,0,0',&lt;br /&gt;   'width', '100',&lt;br /&gt;   'height', '50',&lt;br /&gt;   'src', 'demo',&lt;br /&gt;   'quality', 'high',&lt;br /&gt;   'pluginspage', 'http://www.macromedia.com/go/getflashplayer',&lt;br /&gt;   'align', 'middle',&lt;br /&gt;   'play', 'true',&lt;br /&gt;   'loop', 'true',&lt;br /&gt;   'scale', 'showall',&lt;br /&gt;   'wmode', 'window',&lt;br /&gt;   'devicefont', 'false',&lt;br /&gt;   'id', 'demo',&lt;br /&gt;   'bgcolor', '#ffffff',&lt;br /&gt;   'name', 'demo',&lt;br /&gt;   'menu', 'true',&lt;br /&gt;   'allowFullScreen', 'false',&lt;br /&gt;   'allowScriptAccess','sameDomain',&lt;br /&gt;   'movie', 'demo',&lt;br /&gt;   'salign', '',&lt;br /&gt;   'FlashVars', 'v1='+i&lt;br /&gt;   ); //end AC code&lt;br /&gt; }&lt;br /&gt;&amp;lt;/script&amp;gt;&lt;br /&gt;&amp;lt;/body&amp;gt;&lt;br /&gt;&amp;lt;/html&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;在 FF 可以活著跑完，IE 則會在 80 以上的次數就可能會死掉了。&lt;br /&gt;&lt;br /&gt;於是，我想，會不會跟同一時間就要產生那麼多 Flash 有關，所以我調整了一下程式碼，另外產生 tag 的部分改用 swfobject 來做：&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&amp;lt;html xmlns="http://www.w3.org/1999/xhtml" xml:lang="zh_tw" lang="zh_tw"&amp;gt;&lt;br /&gt;&amp;lt;head&amp;gt;&lt;br /&gt;&amp;lt;meta http-equiv="Content-Type" content="text/html; charset=big5" /&amp;gt;&lt;br /&gt;&amp;lt;title&amp;gt;demo&amp;lt;/title&amp;gt;&lt;br /&gt;&amp;lt;script type="text/javascript" src="swfobject.js"&amp;gt;&amp;lt;/script&amp;gt;&lt;br /&gt;&amp;lt;/head&amp;gt;&lt;br /&gt;&amp;lt;body bgcolor="#ffffff"&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;!-- saved from url=(0013)about:internet --&amp;gt;&lt;br /&gt;&amp;lt;script language="javascript"&amp;gt;&lt;br /&gt; var i=0;&lt;br /&gt; var cnt = 100;&lt;br /&gt;&lt;br /&gt; function createFlashTag(){&lt;br /&gt;  var flashvars = {v1:i};&lt;br /&gt;  var params = {};&lt;br /&gt;  var attributes = {};&lt;br /&gt;  swfobject.embedSWF("demo.swf", "div" + i, "100", "50", "9.0.0", false, flashvars, params, attributes);&lt;br /&gt;&lt;br /&gt;  i++;&lt;br /&gt;  if(i&amp;lt;cnt)&lt;br /&gt;   setTimeout(createFlashTag, 50);&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; for(var j=0; j&amp;lt;cnt; j++)&lt;br /&gt;  document.write("&amp;lt;div id='div" + j + "'&amp;gt;&amp;lt;/div&amp;gt;");&lt;br /&gt;&lt;br /&gt; createFlashTag();&lt;br /&gt;&lt;br /&gt;&amp;lt;/script&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;/body&amp;gt;&lt;br /&gt;&amp;lt;/html&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;結果還是一樣，IE 跑到 95 筆左右時，就跳錯誤訊息死當了。&lt;br /&gt;&lt;br /&gt;在還沒研究出問題原因之前，我只能先歸咎是 IE 的問題，設計時儘量避免在同一頁面用那麼多 Flash 來表現。&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4754237190569973724-2186630045670563578?l=blog.ben.idv.tw' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.ben.idv.tw/feeds/2186630045670563578/comments/default' title='張貼意見'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4754237190569973724&amp;postID=2186630045670563578' title='0 個意見'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4754237190569973724/posts/default/2186630045670563578'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4754237190569973724/posts/default/2186630045670563578'/><link rel='alternate' type='text/html' href='http://blog.ben.idv.tw/2009/02/ie-flash.html' title='IE 在同一頁處理過多 Flash 時'/><author><name>Ben Chang</name><uri>http://www.blogger.com/profile/01921640246111819069</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4754237190569973724.post-3670695818464936220</id><published>2009-01-13T11:00:00.002+08:00</published><updated>2011-08-02T16:05:59.961+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='.NET'/><category scheme='http://www.blogger.com/atom/ns#' term='Google API'/><title type='text'>Google Weather API</title><content type='html'>原來 google 也有出 weather api 可以查天氣資訊。&lt;br /&gt;&lt;br /&gt;這裡有篇文章：&lt;br /&gt;http://animaonline.blogspot.com/2007/07/google-weather-api.html&lt;br /&gt;&lt;br /&gt;提供了 C# 範例：&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;static void Main(string[] args)&lt;br /&gt;{&lt;br /&gt;    int i = 0;&lt;br /&gt;    XmlNodeList GWP_NodeList = GoogleWeatherAPI_Parser(@"http://www.google.co.uk/ig/api?weather=Drammen").SelectNodes("xml_api_reply/weather/current_conditions");&lt;br /&gt;    Console.WriteLine("Current weather in Drammen: " + GWP_NodeList.Item(i).SelectSingleNode("temp_c").Attributes["data"].InnerText);&lt;br /&gt;    Console.ReadLine();&lt;br /&gt;}&lt;br /&gt;private static XmlDocument GoogleWeatherAPI_Parser(string baseUrl)&lt;br /&gt;{&lt;br /&gt;    HttpWebRequest GWP_Request;&lt;br /&gt;    HttpWebResponse GWP_Response = null;&lt;br /&gt;    XmlDocument GWP_XMLdoc = null;&lt;br /&gt;    try&lt;br /&gt;    {&lt;br /&gt;        GWP_Request = (HttpWebRequest)WebRequest.Create(string.Format(baseUrl));&lt;br /&gt;        GWP_Request.UserAgent = @"Mozilla/5.0 (Windows; U; Windows NT 6.0; en-US; rv:1.8.1.4) Gecko/20070515 Firefox/2.0.0.4";&lt;br /&gt;        GWP_Response = (HttpWebResponse)GWP_Request.GetResponse();&lt;br /&gt;        GWP_XMLdoc = new XmlDocument();&lt;br /&gt;        GWP_XMLdoc.Load(GWP_Response.GetResponseStream());&lt;br /&gt;    }&lt;br /&gt;    catch (Exception ex)&lt;br /&gt;    {&lt;br /&gt;        Console.WriteLine(ex.Message);&lt;br /&gt;    }&lt;br /&gt;    GWP_Response.Close();&lt;br /&gt;    return GWP_XMLdoc;&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;不過，問題在於，google weather api 的位置在哪裡？範例中使用 http://www.google.co.uk/ig/api?weather=Drammen，不過若是我們想要查找的地點不知道城市名稱的話呢？&lt;br /&gt;&lt;br /&gt;這裡有另外一篇文章：&lt;br /&gt;http://space.itpub.net/14780828/viewspace-497880&lt;br /&gt;&lt;br /&gt;提到可以使用經緯度查資料&lt;br /&gt;var strURL="http://www.google.com/ig/api?hl=zh-cn&amp;weather=,,,"+point.y*1000000+","+point.x*1000000;&lt;br /&gt;&lt;br /&gt;所以，這樣就組合起來啦～譬如若是我知道 台北縣政府 的經緯度的話：&lt;br /&gt;http://www.google.com/ig/api?hl=zh-tw&amp;weather=,,,25012085,121465701&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4754237190569973724-3670695818464936220?l=blog.ben.idv.tw' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.ben.idv.tw/feeds/3670695818464936220/comments/default' title='張貼意見'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4754237190569973724&amp;postID=3670695818464936220' title='0 個意見'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4754237190569973724/posts/default/3670695818464936220'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4754237190569973724/posts/default/3670695818464936220'/><link rel='alternate' type='text/html' href='http://blog.ben.idv.tw/2009/01/google-weather-api.html' title='Google Weather API'/><author><name>Ben Chang</name><uri>http://www.blogger.com/profile/01921640246111819069</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4754237190569973724.post-4165132732035296042</id><published>2008-12-28T04:43:00.005+08:00</published><updated>2011-08-02T16:05:59.966+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='.NET'/><title type='text'>ASP.NET 的 Url Rewrite</title><content type='html'>若希望當網友點下 http://www.xyz.com/123456789 可以自動連到 http://www.xyz.com/page.aspx?id=123456789 的話，就需要用到 Url Rewrite。&lt;br /&gt;&lt;br /&gt;導到別頁的語法是：HttpContext 的 RewritePath() 或 Response 的 Redirect()，差別是後者是告知 client 端進行，前者是 server 端直接進行。&lt;br /&gt;&lt;br /&gt;問題是 "時機"，在哪裡可以寫程式來判斷現在的 url 的組成？&lt;br /&gt;&lt;br /&gt;有時間的話，請看一下 MSDN 這篇 ASP.NET Application Life Cycle Overview for IIS 5.0 and 6.0：&lt;br /&gt;http://msdn.microsoft.com/en-us/library/ms178473.aspx&lt;br /&gt;HttpApplication 中依照不同程序會發生一堆事件。&lt;br /&gt;&lt;br /&gt;我們可以在 Global.asax 中，當這些事件發生時，做 Url Rewrite 的工作。&lt;br /&gt;&lt;br /&gt;另外一種做法，是寫一個實作 IHttpModule 的 HttpModule 類別，然後掛在 web.config 中，這樣每個 request 都會經過這個我們開發的 HttpModule，就可以進行 Url Rewrite 了。&lt;br /&gt;&lt;br /&gt;首先，先開發這個 HttpModule，&lt;br /&gt;&lt;br /&gt;UrlRewrite.cs：&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;using System;&lt;br /&gt;using System.Data;&lt;br /&gt;using System.Configuration;&lt;br /&gt;using System.Web;&lt;br /&gt;using System.Web.Security;&lt;br /&gt;using System.Web.UI;&lt;br /&gt;using System.Web.UI.WebControls;&lt;br /&gt;using System.Web.UI.WebControls.WebParts;&lt;br /&gt;using System.Web.UI.HtmlControls;&lt;br /&gt;&lt;br /&gt;namespace idv.ben.httpmodule&lt;br /&gt;{&lt;br /&gt;    public class UrlRewrite : IHttpModule&lt;br /&gt;    {&lt;br /&gt;        public UrlRewrite() { }&lt;br /&gt;&lt;br /&gt;        #region IHttpModule 成員&lt;br /&gt;&lt;br /&gt;        public void Dispose()&lt;br /&gt;        {&lt;br /&gt;            //throw new Exception("The method or operation is not implemented.");&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        public void Init(HttpApplication application)&lt;br /&gt;        {&lt;br /&gt;            application.BeginRequest += new EventHandler(context_BeginRequest);&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        void context_BeginRequest(object sender, EventArgs e)&lt;br /&gt;        {&lt;br /&gt;            HttpApplication application = (HttpApplication)sender;&lt;br /&gt;            HttpContext context = application.Context;&lt;br /&gt;&lt;br /&gt;            string queryString = context.Request.ServerVariables["QUERY_STRING"];&lt;br /&gt;            string currentURL = context.Request.Path.ToLower();&lt;br /&gt;            string pageParam = "";&lt;br /&gt;&lt;br /&gt;            System.Diagnostics.EventLog log = new System.Diagnostics.EventLog();&lt;br /&gt;            log.Source = "Application";&lt;br /&gt;            log.WriteEntry(string.Format("queryString={0}, currentURL={1}"&lt;br /&gt;                , queryString&lt;br /&gt;                , currentURL&lt;br /&gt;                ));&lt;br /&gt;&lt;br /&gt;            if (currentURL.EndsWith(".aspx"))&lt;br /&gt;            {&lt;br /&gt;                int idx = currentURL.LastIndexOf("/");&lt;br /&gt;                string page = currentURL.Substring(idx + 1);&lt;br /&gt;                currentURL = currentURL.Substring(0, idx);&lt;br /&gt;&lt;br /&gt;                bool fileExists = false;&lt;br /&gt;                while (idx != -1)&lt;br /&gt;                {&lt;br /&gt;                    string paramName = "";&lt;br /&gt;                    string paramValue = "";&lt;br /&gt;&lt;br /&gt;                    idx = currentURL.LastIndexOf("/");&lt;br /&gt;                    if (idx != -1)&lt;br /&gt;                    {&lt;br /&gt;                        paramValue = currentURL.Substring(idx + 1);&lt;br /&gt;                        currentURL = currentURL.Substring(0, idx);&lt;br /&gt;                    }&lt;br /&gt;&lt;br /&gt;                    idx = currentURL.LastIndexOf("/");&lt;br /&gt;                    if (idx != -1)&lt;br /&gt;                    {&lt;br /&gt;                        paramName = currentURL.Substring(idx + 1);&lt;br /&gt;                        currentURL = currentURL.Substring(0, idx);&lt;br /&gt;                    }&lt;br /&gt;&lt;br /&gt;                    if (!paramName.Equals("") &amp;&amp; !paramValue.Equals(""))&lt;br /&gt;                    {&lt;br /&gt;                        if (!pageParam.Equals(""))&lt;br /&gt;                            pageParam += "&amp;";&lt;br /&gt;                        pageParam += string.Format("{0}={1}", paramName, paramValue);&lt;br /&gt;                    }&lt;br /&gt;&lt;br /&gt;                    try&lt;br /&gt;                    {&lt;br /&gt;                        if (System.IO.File.Exists(context.Server.MapPath(currentURL + "/" + page)))&lt;br /&gt;                        {&lt;br /&gt;                            fileExists = true;&lt;br /&gt;                            break;&lt;br /&gt;                        }&lt;br /&gt;                    }&lt;br /&gt;                    catch { break; }&lt;br /&gt;                }&lt;br /&gt;&lt;br /&gt;                if (fileExists)&lt;br /&gt;                {&lt;br /&gt;                    if (queryString != string.Empty)&lt;br /&gt;                        context.RewritePath(currentURL + "/" + page + "?" + pageParam + "&amp;" + queryString, false);&lt;br /&gt;                    else&lt;br /&gt;                        context.RewritePath(currentURL + "/" + page + "?" + pageParam, false);&lt;br /&gt;                }&lt;br /&gt;                else&lt;br /&gt;                {&lt;br /&gt;                    context.Response.Write("page not found!!");&lt;br /&gt;                    context.Response.End();&lt;br /&gt;                }&lt;br /&gt;            }&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        #endregion&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;只要注意在 init() 時，我們設定 HttpApplication 的 BeginRequest 事件發生時，要處理的動作。&lt;br /&gt;&lt;br /&gt;至於在 context_BeginRequest()，該如何將 網友瀏覽的 Url 轉成你期望的 Url，這就視需求而訂。我這裡的用途是：&lt;br /&gt;&lt;br /&gt;* url 的最後一定要是一個 *.aspx&lt;br /&gt;* 去除 page (*.aspx) 之外，將 url 由後往前組合 變數值對(name=value)，每找到一組可成為 變數值對 後，原本的 url 就縮減去除那組 變數值對。&lt;br /&gt;* 判斷 url(某層資料夾) 下是否存在有 page (*.aspx)。如果找到 page 所在的 url 層級，就可以進行 Url Rewrite 了。&lt;br /&gt;* 所有找出來的 變數值對 與 原始url 的 query string，都會成為新的 query string。&lt;br /&gt;&lt;br /&gt;以上，是我的範例的做法，你們可以寫自己的一套。&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;接下來，就可以將這個 HttpModule 掛到 web.config 開始服務了，請於 web.config 中加入以下這段：&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt; &amp;lt;system.web&amp;gt;&lt;br /&gt;  &amp;lt;httpModules&amp;gt;&lt;br /&gt;   &amp;lt;add name="UrlRewrite" type="idv.ben.httpmodule.UrlRewrite"/&amp;gt;&lt;br /&gt;  &amp;lt;/httpModules&amp;gt;&lt;br /&gt; &amp;lt;/system.web&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;最後，準備一個 view.aspx 做測試`:&lt;br /&gt;&lt;pre&gt;&amp;lt;%@ Page Language="C#" AutoEventWireup="true" %&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;script runat="server"&amp;gt;&lt;br /&gt;    &lt;br /&gt;    void Page_Load(object sender, EventArgs e)&lt;br /&gt;    {&lt;br /&gt;        Response.Write("qs = " + Request.ServerVariables["QUERY_STRING"]);&lt;br /&gt;    }    &lt;br /&gt;    &lt;br /&gt;&amp;lt;/script&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"&amp;gt;&lt;br /&gt;&amp;lt;html xmlns="http://www.w3.org/1999/xhtml"&amp;gt;&lt;br /&gt;&amp;lt;head runat="server"&amp;gt;&lt;br /&gt;    &amp;lt;title&amp;gt;aa&amp;lt;/title&amp;gt;&lt;br /&gt;&amp;lt;/head&amp;gt;&lt;br /&gt;&amp;lt;body&amp;gt;&lt;br /&gt;    &amp;lt;form id="form1" runat="server"&amp;gt;&lt;br /&gt;        &amp;lt;div&amp;gt;&lt;br /&gt;        &amp;lt;/div&amp;gt;&lt;br /&gt;    &amp;lt;/form&amp;gt;&lt;br /&gt;&amp;lt;/body&amp;gt;&lt;br /&gt;&amp;lt;/html&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;瀏覽效果如下：&lt;br /&gt;&lt;br /&gt;一般：http://localhost:13833/WebSite1/var1/123/var2/456/view.aspx&lt;br /&gt;&lt;br /&gt;&lt;a target="_blank" onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_HsFEtLMw5zU/SVaaQnt_5tI/AAAAAAAAJLE/E-4EHWo3IvQ/s1600-h/Clipboard02.jpg"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 400px; height: 97px;" src="http://2.bp.blogspot.com/_HsFEtLMw5zU/SVaaQnt_5tI/AAAAAAAAJLE/E-4EHWo3IvQ/s400/Clipboard02.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5284580823096354514" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;加額外的參數：http://localhost:13833/WebSite1/var1/123/var2/456/view.aspx?var3=789&amp;var4=999&lt;br /&gt;&lt;br /&gt;&lt;a target="_blank" onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_HsFEtLMw5zU/SVaaQFIH0-I/AAAAAAAAJK8/AmKX1ycpdVg/s1600-h/Clipboard03.jpg"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 400px; height: 93px;" src="http://4.bp.blogspot.com/_HsFEtLMw5zU/SVaaQFIH0-I/AAAAAAAAJK8/AmKX1ycpdVg/s400/Clipboard03.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5284580813810684898" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;變數值對有誤、找不到網頁：http://localhost:13833/WebSite1/xxx/var1/123/var2/456/view.aspx?var3=789&amp;var4=999&lt;br /&gt;&lt;br /&gt;&lt;a target="_blank" onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_HsFEtLMw5zU/SVaaP6Ms4SI/AAAAAAAAJK0/5bCS7PmcoGU/s1600-h/Clipboard04.jpg"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 400px; height: 102px;" src="http://4.bp.blogspot.com/_HsFEtLMw5zU/SVaaP6Ms4SI/AAAAAAAAJK0/5bCS7PmcoGU/s400/Clipboard04.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5284580810877100322" /&gt;&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4754237190569973724-4165132732035296042?l=blog.ben.idv.tw' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.ben.idv.tw/feeds/4165132732035296042/comments/default' title='張貼意見'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4754237190569973724&amp;postID=4165132732035296042' title='2 個意見'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4754237190569973724/posts/default/4165132732035296042'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4754237190569973724/posts/default/4165132732035296042'/><link rel='alternate' type='text/html' href='http://blog.ben.idv.tw/2008/12/aspnet-url-rewrite.html' title='ASP.NET 的 Url Rewrite'/><author><name>Ben Chang</name><uri>http://www.blogger.com/profile/01921640246111819069</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/_HsFEtLMw5zU/SVaaQnt_5tI/AAAAAAAAJLE/E-4EHWo3IvQ/s72-c/Clipboard02.jpg' height='72' width='72'/><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4754237190569973724.post-1336213234351124685</id><published>2008-12-25T04:53:00.003+08:00</published><updated>2011-08-02T16:05:59.973+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='.NET'/><title type='text'>ASP.NET 動態產生縮圖</title><content type='html'>動態產生縮圖的程式，每次都要找，就連自己以前寫過的都找不到了，所以再寫一遍。&lt;br /&gt;&lt;br /&gt;thumbnail.ashx：&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&lt;%@ WebHandler Language="C#" Class="thumbnail" %&gt;&lt;br /&gt;&lt;br /&gt;using System;&lt;br /&gt;using System.Web;&lt;br /&gt;&lt;br /&gt;using System.Drawing;&lt;br /&gt;using System.Drawing.Imaging;&lt;br /&gt;&lt;br /&gt;public class thumbnail : IHttpHandler&lt;br /&gt;{&lt;br /&gt;&lt;br /&gt;    public void ProcessRequest(HttpContext context)&lt;br /&gt;    {&lt;br /&gt;        /*&lt;br /&gt;        context.Response.ContentType = "text/plain";&lt;br /&gt;        context.Response.Write("Hello World");&lt;br /&gt;        */&lt;br /&gt;        &lt;br /&gt;        string file = context.Request["file"];&lt;br /&gt;        int max = Convert.ToInt32(context.Request["max"]);&lt;br /&gt;&lt;br /&gt;        Image img = Image.FromFile(context.Server.MapPath(file));&lt;br /&gt;&lt;br /&gt;        double w, h;&lt;br /&gt;        if (img.Width &amp;gt; img.Height)&lt;br /&gt;        {&lt;br /&gt;            w = max;&lt;br /&gt;            h = img.Height * (w / img.Width);&lt;br /&gt;        }&lt;br /&gt;        else&lt;br /&gt;        {&lt;br /&gt;            h = max;&lt;br /&gt;            w = img.Width * (h / img.Height);&lt;br /&gt;        }&lt;br /&gt;        &lt;br /&gt;        /*&lt;br /&gt;        Image.GetThumbnailImageAbort myCallback = new Image.GetThumbnailImageAbort(ThumbnailCallback);&lt;br /&gt;        Image thumb = img.GetThumbnailImage(Convert.ToInt32(w), Convert.ToInt32(h), myCallback, IntPtr.Zero);&lt;br /&gt;         * */&lt;br /&gt;        Image thumb = new Bitmap(img, Convert.ToInt32(w), Convert.ToInt32(h));&lt;br /&gt;&lt;br /&gt;        thumb.Save(context.Response.OutputStream, img.RawFormat);&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    public bool IsReusable&lt;br /&gt;    {&lt;br /&gt;        get&lt;br /&gt;        {&lt;br /&gt;            return false;&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    /*&lt;br /&gt;    public bool ThumbnailCallback()&lt;br /&gt;    {&lt;br /&gt;        return false;&lt;br /&gt;    }&lt;br /&gt;     * */&lt;br /&gt;&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;thumbnail.htm：&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"&amp;gt;&lt;br /&gt;&amp;lt;html xmlns="http://www.w3.org/1999/xhtml"&amp;gt;&lt;br /&gt;&amp;lt;head&amp;gt;&lt;br /&gt;    &amp;lt;title&amp;gt;thumbnail demo&amp;lt;/title&amp;gt;&lt;br /&gt;&amp;lt;/head&amp;gt;&lt;br /&gt;&amp;lt;body&amp;gt;&lt;br /&gt;    &amp;lt;table&amp;gt;&lt;br /&gt;        &amp;lt;tr&amp;gt;&lt;br /&gt;            &amp;lt;td&amp;gt;&lt;br /&gt;                100&amp;lt;/td&amp;gt;&lt;br /&gt;            &amp;lt;td&amp;gt;&lt;br /&gt;                &amp;lt;img src="thumbnail.ashx?max=100&amp;file=imgs/IMG_3492.JPG" /&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;        &amp;lt;/tr&amp;gt;&lt;br /&gt;        &amp;lt;tr&amp;gt;&lt;br /&gt;            &amp;lt;td&amp;gt;&lt;br /&gt;                200&amp;lt;/td&amp;gt;&lt;br /&gt;            &amp;lt;td&amp;gt;&lt;br /&gt;                &amp;lt;img src="thumbnail.ashx?max=200&amp;file=imgs/IMG_3492.JPG" /&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;        &amp;lt;/tr&amp;gt;&lt;br /&gt;        &amp;lt;tr&amp;gt;&lt;br /&gt;            &amp;lt;td&amp;gt;&lt;br /&gt;                300&amp;lt;/td&amp;gt;&lt;br /&gt;            &amp;lt;td&amp;gt;&lt;br /&gt;                &amp;lt;img src="thumbnail.ashx?max=300&amp;file=imgs/IMG_3492.JPG" /&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;        &amp;lt;/tr&amp;gt;&lt;br /&gt;        &amp;lt;tr&amp;gt;&lt;br /&gt;            &amp;lt;td&amp;gt;&lt;br /&gt;                400&amp;lt;/td&amp;gt;&lt;br /&gt;            &amp;lt;td&amp;gt;&lt;br /&gt;                &amp;lt;img src="thumbnail.ashx?max=400&amp;file=imgs/IMG_3492.JPG" /&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;        &amp;lt;/tr&amp;gt;&lt;br /&gt;    &amp;lt;/table&amp;gt;&lt;br /&gt;&amp;lt;/body&amp;gt;&lt;br /&gt;&amp;lt;/html&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;瀏覽：&lt;br /&gt;&lt;br /&gt;&lt;a target="_blank" onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_HsFEtLMw5zU/SVKiFBa5RGI/AAAAAAAAJKU/RHVXZp370_g/s1600-h/Clipboard01.jpg"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 400px; height: 304px;" src="http://2.bp.blogspot.com/_HsFEtLMw5zU/SVKiFBa5RGI/AAAAAAAAJKU/RHVXZp370_g/s400/Clipboard01.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5283463520023299170" /&gt;&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4754237190569973724-1336213234351124685?l=blog.ben.idv.tw' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.ben.idv.tw/feeds/1336213234351124685/comments/default' title='張貼意見'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4754237190569973724&amp;postID=1336213234351124685' title='6 個意見'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4754237190569973724/posts/default/1336213234351124685'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4754237190569973724/posts/default/1336213234351124685'/><link rel='alternate' type='text/html' href='http://blog.ben.idv.tw/2008/12/aspnet.html' title='ASP.NET 動態產生縮圖'/><author><name>Ben Chang</name><uri>http://www.blogger.com/profile/01921640246111819069</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/_HsFEtLMw5zU/SVKiFBa5RGI/AAAAAAAAJKU/RHVXZp370_g/s72-c/Clipboard01.jpg' height='72' width='72'/><thr:total>6</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4754237190569973724.post-7858219814551833521</id><published>2008-12-18T15:38:00.004+08:00</published><updated>2011-08-02T16:05:59.978+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='.NET'/><title type='text'>用 ASP.NET 的 Cache 做週期執行的程式</title><content type='html'>要寫一個週期執行的工作，如果不能寫 windows service，也不能在 server 上安裝程式的話，可以寫一個 aspx 頁面並且定期去執行它，只不過要誰來執行這個 aspx？一個人做在電腦前不斷 reload？寫個程式放在不關機的電腦不斷向 web server 送出 request？&lt;br /&gt;&lt;br /&gt;透過前輩提點使用 Cache，先去找幾篇基本用法：&lt;br /&gt;&lt;br /&gt;http://blog.darkthread.net/blogs/darkthreadtw/archive/2007/08/30/tips-asp-net-cache-mini-guide.aspx&lt;br /&gt;&lt;br /&gt;http://www.dotblogs.com.tw/jeff377/archive/2008/08/28/5236.aspx&lt;br /&gt;&lt;br /&gt;http://msdn.microsoft.com/zh-tw/library/system.web.caching.cacheitemremovedcallback(VS.80).aspx&lt;br /&gt;&lt;br /&gt;然後我寫了一個 aspx 網頁，其 *.cs 如下：&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;using System;&lt;br /&gt;using System.Data;&lt;br /&gt;using System.Configuration;&lt;br /&gt;using System.Collections;&lt;br /&gt;using System.Web;&lt;br /&gt;using System.Web.Security;&lt;br /&gt;using System.Web.UI;&lt;br /&gt;using System.Web.UI.WebControls;&lt;br /&gt;using System.Web.UI.WebControls.WebParts;&lt;br /&gt;using System.Web.UI.HtmlControls;&lt;br /&gt;&lt;br /&gt;using System.Web.Caching;&lt;br /&gt;using System.IO;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;public partial class cacheTest : System.Web.UI.Page&lt;br /&gt;{&lt;br /&gt;    static public string status = "";&lt;br /&gt;&lt;br /&gt;    protected void RemovedCallback(String k, Object v, CacheItemRemovedReason r)&lt;br /&gt;    {&lt;br /&gt;        if (status.Equals("PLAY"))&lt;br /&gt;        {&lt;br /&gt;            addCache();&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        log(string.Format("CacheItemRemovedReason={0}", r.ToString()));&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    protected void log(string str)&lt;br /&gt;    {&lt;br /&gt;        StreamWriter sr;&lt;br /&gt;&lt;br /&gt;        FileInfo fi = new FileInfo(Server.MapPath("cacheTest7.txt"));&lt;br /&gt;        sr = new StreamWriter(fi.Open(FileMode.OpenOrCreate | FileMode.Append, FileAccess.Write));&lt;br /&gt;        sr.WriteLine(string.Format("{0}, {1}, {2}"&lt;br /&gt;            , DateTime.Now.ToString("yyyyMMdd HHmmss")&lt;br /&gt;            , str&lt;br /&gt;            , Cache.Count&lt;br /&gt;            ));&lt;br /&gt;        sr.Flush();&lt;br /&gt;        sr.Close();&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    protected void addCache()&lt;br /&gt;    {&lt;br /&gt;        log("[addCache start]");&lt;br /&gt;&lt;br /&gt;        if (Cache["AutoTask"] == null)&lt;br /&gt;        {&lt;br /&gt;            Cache.Add("AutoTask", "xxx", null&lt;br /&gt;                , DateTime.Now.AddSeconds(10), TimeSpan.Zero&lt;br /&gt;                , CacheItemPriority.High, new CacheItemRemovedCallback(this.RemovedCallback));&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        log("[addCache end]");&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    protected void remove()&lt;br /&gt;    {&lt;br /&gt;        if (Cache["AutoTask"] != null)&lt;br /&gt;        {&lt;br /&gt;            Cache.Remove("AutoTask");&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    protected void Page_Load(object sender, EventArgs e)&lt;br /&gt;    {&lt;br /&gt;        if (Request["stop"] != null)&lt;br /&gt;        {&lt;br /&gt;            status = "STOP";&lt;br /&gt;            remove();&lt;br /&gt;        }&lt;br /&gt;        else&lt;br /&gt;        {&lt;br /&gt;            status = "PLAY";&lt;br /&gt;            addCache();&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;第一次進入，會執行  addCache()，並會設定 10 秒後到期，以及到期時要執行的 RemovedCallback()，然後再次重複執行  addCache()。&lt;br /&gt;&lt;br /&gt;寫入紀錄檔的內容：&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;//用ff開網頁&lt;br /&gt;20081218 153238, [addCache start], 0&lt;br /&gt;20081218 153238, [addCache end], 1&lt;br /&gt;&lt;br /&gt;20081218 153300, [addCache start], 1&lt;br /&gt;20081218 153300, [addCache end], 2&lt;br /&gt;20081218 153300, CacheItemRemovedReason=Expired, 2&lt;br /&gt;&lt;br /&gt;20081218 153320, [addCache start], 1&lt;br /&gt;20081218 153320, [addCache end], 2&lt;br /&gt;20081218 153320, CacheItemRemovedReason=Expired, 2&lt;br /&gt;&lt;br /&gt;20081218 153340, [addCache start], 1&lt;br /&gt;20081218 153340, [addCache end], 2&lt;br /&gt;20081218 153340, CacheItemRemovedReason=Expired, 2&lt;br /&gt;&lt;br /&gt;//用ie開相同網頁&lt;br /&gt;20081218 153356, [addCache start], 1&lt;br /&gt;20081218 153356, [addCache start], 1&lt;br /&gt;20081218 153356, [addCache end], 2&lt;br /&gt;20081218 153356, CacheItemRemovedReason=Expired, 2&lt;br /&gt;20081218 153356, [addCache end], 1&lt;br /&gt;&lt;br /&gt;20081218 153420, [addCache start], 1&lt;br /&gt;20081218 153420, [addCache end], 2&lt;br /&gt;20081218 153420, CacheItemRemovedReason=Expired, 2&lt;br /&gt;&lt;br /&gt;20081218 153440, [addCache start], 1&lt;br /&gt;20081218 153440, [addCache end], 2&lt;br /&gt;20081218 153440, CacheItemRemovedReason=Expired, 2&lt;br /&gt;&lt;br /&gt;20081218 153500, [addCache start], 1&lt;br /&gt;20081218 153500, [addCache end], 2&lt;br /&gt;20081218 153500, CacheItemRemovedReason=Expired, 2&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;* 即使瀏覽器被關掉了，這個執行緒仍會不斷跑。&lt;br /&gt;* 開不同的瀏覽器、另一個人瀏覽此網頁，可造成上次的 cache 立即到期，然後建立新的 cache。&lt;br /&gt;* web server 重開好像不會造成中斷，www 服務重開才會造成中斷。&lt;br /&gt;&lt;br /&gt;這樣就可以寫週期執行、排程程式了。&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4754237190569973724-7858219814551833521?l=blog.ben.idv.tw' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.ben.idv.tw/feeds/7858219814551833521/comments/default' title='張貼意見'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4754237190569973724&amp;postID=7858219814551833521' title='7 個意見'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4754237190569973724/posts/default/7858219814551833521'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4754237190569973724/posts/default/7858219814551833521'/><link rel='alternate' type='text/html' href='http://blog.ben.idv.tw/2008/12/aspnet-cache.html' title='用 ASP.NET 的 Cache 做週期執行的程式'/><author><name>Ben Chang</name><uri>http://www.blogger.com/profile/01921640246111819069</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>7</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4754237190569973724.post-225079046120624703</id><published>2008-12-15T00:14:00.003+08:00</published><updated>2008-12-15T00:48:33.200+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Books'/><category scheme='http://www.blogger.com/atom/ns#' term='AS3'/><category scheme='http://www.blogger.com/atom/ns#' term='Adobe AIR'/><category scheme='http://www.blogger.com/atom/ns#' term='Flex'/><title type='text'>精通 Flex 與 Flex 3 徹底研究 兩本書</title><content type='html'>前幾天收到最近新出的 Flex 中文書：&lt;br /&gt;&lt;br /&gt;1.&lt;br /&gt;精通 Flex－基於 ActionScript 實現  &lt;br /&gt;&lt;br /&gt;http://tlsj.tenlong.com.tw/WebModule/BookSearch/bookSearchViewAction.do?isbn=9789862043226&amp;amp;sid=47795&lt;br /&gt;&lt;br /&gt;&lt;a target="_blank" onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_HsFEtLMw5zU/SUUxL8lWGjI/AAAAAAAAI7E/zBdbvss54zI/s1600-h/9789862043226.jpg"&gt;&lt;img style="cursor: pointer; width: 110px; height: 149px;" src="http://1.bp.blogspot.com/_HsFEtLMw5zU/SUUxL8lWGjI/AAAAAAAAI7E/zBdbvss54zI/s400/9789862043226.jpg" alt="" id="BLOGGER_PHOTO_ID_5279680219472861746" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;2.&lt;br /&gt;Flex 3 徹底研究 (Adobe Flex 3: Training from the Source)  &lt;br /&gt;&lt;br /&gt;http://tlsj.tenlong.com.tw/WebModule/BookSearch/bookSearchViewAction.do?isbn=9789866587252&amp;amp;sid=47356&lt;br /&gt;&lt;br /&gt;&lt;a target="_blank" onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_HsFEtLMw5zU/SUUxMFbLrPI/AAAAAAAAI7M/J4hT7So0Q9w/s1600-h/9789866587252.jpg"&gt;&lt;img style="cursor: pointer; width: 126px; height: 170px;" src="http://3.bp.blogspot.com/_HsFEtLMw5zU/SUUxMFbLrPI/AAAAAAAAI7M/J4hT7So0Q9w/s400/9789866587252.jpg" alt="" id="BLOGGER_PHOTO_ID_5279680221846154482" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;隨性買了這兩本新出的 Flex 3 的書，因為 1. 看中文書畢竟比原文書快，2. 兩本中文書加起來才 1000 左右，比起一本原文書還便宜。&lt;br /&gt;&lt;br /&gt;這幾天正在看 人民郵電出版社 的 精通 Flex，我自己的感覺是，這本書挺糟的。我大約已經快速的翻了 3/4 了。&lt;br /&gt;&lt;br /&gt;1 ~ 4 章是基礎，認識 Flex 觀念 或 學過 ActionScript 的人，都可以在第一個小時就很快速的翻過。&lt;br /&gt;&lt;br /&gt;5 ~ 10 章是 Flex 的一些基本組件，排版方面的一些表格列表，可以讓讀者很快的有個初淺的認識，不過在這一階段中，我就已經感到內容的排版描述方式不是很討喜：貼了一大串的完整程式碼，然後用一段的文字敘述作簡述，有一些物件定義或命名還需要讀者回到原始檔自己好好找，原始碼中並沒有用粗體標示出一些關鍵程式碼，有經驗的 Flex 開發者可能才有辦法很快的找到對應的 MXML 標籤或 AS 程式碼。&lt;br /&gt;&lt;br /&gt;總之，有概念的讀者，可以利用這本書，有個整體、概述的閱讀方式，不過若真是初學者，我擔心光看書中的敘述，也提供了完整原始碼，會仍不知道原始碼中彼此的關係。&lt;br /&gt;&lt;br /&gt;11~16 章，是 Flex 與後台資料傳遞的部分，也是我正在閱讀，也是我之前比較沒有花時間研究，也是我很想好好學習的部分。不過，一些資料傳輸組件的教學，都非常簡述，如同我上面說的 5~10 章的部分，雖然我以速讀的方式大多可以理解，不過我覺得實作的話，或是由讀者要自己應用的話，恐怕會遇到一些書中沒提到的問題與觀念吧。&lt;br /&gt;&lt;br /&gt;另外，第 13 章，談到 Flex 與後台不同技術的資料整合方式，包括 ASP.NET、Java、PHP，這裡雖然提到三種，不過寫作方式等於只有一種，因為，全都是講述如何用 Flex 的精靈來產生，然後再次將所有 Flex 產生的程式碼完整貼出，然後只寫了簡單的註解，加上一點點自己的意見，況且，對於 Server 技術的部分也因為超出本書範圍之緣故而減少說明，我的感覺這本書有點充數～&lt;br /&gt;&lt;br /&gt;還沒完全閱讀完，我並不能完全說這本書不好，對於我這種背景 (有寫過 Flash 與 Server 溝通，初淺認識 Flex 或是其他 ASP.NET 的視覺化組件，有其他程式語言的經驗，看過 Flex 官方 PDF 文件) 來說，閱讀它 是可以 以速讀的方式幫自己複習一下 Flex 的功能，而且至少可以對 LCDS 的一些概觀能有瞭解。不過若是對於初學者來說，對於連非同步資料傳輸與 callback 都不知道的人來說，恐怕這本書會讓你看得很辛苦。&lt;br /&gt;&lt;br /&gt;我會很快的翻完 "精通 Flex" 這本書，並期待 "Flex 3 徹底研究" 能讓我懂更多我遺漏的小細節，雖然之前已經簡單翻過幾頁 "Flex 3 徹底研究"，發現翻譯有些白字 或 遺漏，不過我想對於我閱讀上來說，應該不會有太大的理解方面的問題。&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4754237190569973724-225079046120624703?l=blog.ben.idv.tw' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.ben.idv.tw/feeds/225079046120624703/comments/default' title='張貼意見'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4754237190569973724&amp;postID=225079046120624703' title='9 個意見'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4754237190569973724/posts/default/225079046120624703'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4754237190569973724/posts/default/225079046120624703'/><link rel='alternate' type='text/html' href='http://blog.ben.idv.tw/2008/12/flex-flex-3.html' title='精通 Flex 與 Flex 3 徹底研究 兩本書'/><author><name>Ben Chang</name><uri>http://www.blogger.com/profile/01921640246111819069</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/_HsFEtLMw5zU/SUUxL8lWGjI/AAAAAAAAI7E/zBdbvss54zI/s72-c/9789862043226.jpg' height='72' width='72'/><thr:total>9</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4754237190569973724.post-7394749808418406924</id><published>2008-11-18T09:00:00.002+08:00</published><updated>2008-11-18T09:05:44.961+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Adobe AIR'/><title type='text'>AIR 1.5</title><content type='html'>Adobe AIR 推出 1.5 版，他的新功能介紹請參考這篇文章：&lt;br /&gt;&lt;br /&gt;&lt;a target="_blank" href="http://www.adobe.com/devnet/logged_in/rchristensen_lpolanco_air_1.5.html"&gt;http://www.adobe.com/devnet/logged_in/rchristensen_lpolanco_air_1.5.html&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;因為 AIR 1.5 包含了 Flash Player 10，所以也已經可以使用 Pixel Bender 的特效了：&lt;br /&gt;&lt;br /&gt;&lt;a target="_blank" href="http://www.adobe.com/devnet/air/ajax/articles/blackbooksafe_anatomy.html"&gt;http://www.adobe.com/devnet/air/ajax/articles/blackbooksafe_anatomy.html&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;這篇文章也提到在先前 AIR 的版本與 1.5 版間，分別要如何作資料的編碼：&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;In previous versions of the AIR runtime, if you wanted to             store sensitive data in your AIR application, you had to use the encrypted             local store. Although this is helpful in a pinch, the encrypted local store is             not a relational database; it uses only key/value pairs. With AIR 1.5, you can             use either the encrypted local store or the encrypted (SQLite) database which             is included in AIR.&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4754237190569973724-7394749808418406924?l=blog.ben.idv.tw' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.ben.idv.tw/feeds/7394749808418406924/comments/default' title='張貼意見'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4754237190569973724&amp;postID=7394749808418406924' title='0 個意見'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4754237190569973724/posts/default/7394749808418406924'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4754237190569973724/posts/default/7394749808418406924'/><link rel='alternate' type='text/html' href='http://blog.ben.idv.tw/2008/11/air-15.html' title='AIR 1.5'/><author><name>Ben Chang</name><uri>http://www.blogger.com/profile/01921640246111819069</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4754237190569973724.post-5027956150209351417</id><published>2008-11-12T22:51:00.000+08:00</published><updated>2010-01-13T08:41:17.636+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Pixel Bender'/><category scheme='http://www.blogger.com/atom/ns#' term='Flash CS4'/><title type='text'>Pixel Bender</title><content type='html'>Flash CS4 新增 Pixel Bender 的功能，可以自己寫濾鏡，你也可以去下載別人開發好的 Pixel Bender 來用，譬如 Adobe Exchange 也提供了 Pixel Bender 區：&lt;br /&gt;&lt;br /&gt;&lt;a target="_blank" href="http://www.adobe.com/cfusion/exchange/index.cfm?event=productHome&amp;exc=26&amp;loc=en_us"&gt;http://www.adobe.com/cfusion/exchange/index.cfm?event=productHome&amp;exc=26&amp;loc=en_us&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;a target="_blank" onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_HsFEtLMw5zU/SRrvR3vhvCI/AAAAAAAAIfo/ae-jaN5jOcA/s1600-h/Clipboard01.jpg"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 400px; height: 318px;" src="http://1.bp.blogspot.com/_HsFEtLMw5zU/SRrvR3vhvCI/AAAAAAAAIfo/ae-jaN5jOcA/s400/Clipboard01.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5267785804463324194" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;我下載 RippleBlocks 這個來作展示，將下載的檔案解壓縮後是一個 RippleBlocks.pbk 文字檔，可以透過 Adobe CS4 包含的 Adobe Pixel Bender Toolkit 來開啟，並且 Run 執行效果，系統會提醒你載入一個圖檔來套用這個特效：&lt;br /&gt;&lt;br /&gt;&lt;a target="_blank" onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_HsFEtLMw5zU/SRrvSBGpWQI/AAAAAAAAIfw/JaEr6Pazmow/s1600-h/Clipboard02.jpg"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 400px; height: 307px;" src="http://2.bp.blogspot.com/_HsFEtLMw5zU/SRrvSBGpWQI/AAAAAAAAIfw/JaEr6Pazmow/s400/Clipboard02.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5267785806976211202" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;接下來，要將它輸出給 Flash Player 可以用的濾鏡 RippleBlocks.pbj：&lt;br /&gt;&lt;br /&gt;&lt;a target="_blank" onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_HsFEtLMw5zU/SRrvoyUp9BI/AAAAAAAAIf4/Ylx4ue5GjXc/s1600-h/Clipboard03.jpg"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 321px; height: 400px;" src="http://1.bp.blogspot.com/_HsFEtLMw5zU/SRrvoyUp9BI/AAAAAAAAIf4/Ylx4ue5GjXc/s400/Clipboard03.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5267786198145430546" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;接下來，在 Flash CS4 中，我在 frame 1 寫下以下的程式碼：&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;var fr:flash.net.FileReference;&lt;br /&gt;var shader:flash.display.Shader;&lt;br /&gt;var shaderFilter:flash.filters.ShaderFilter;&lt;br /&gt;var loader:flash.display.Loader;&lt;br /&gt;&lt;br /&gt;fr = new FileReference();&lt;br /&gt;fr.addEventListener(Event.SELECT, onSelect);&lt;br /&gt;fr.addEventListener(Event.COMPLETE, onComplete);&lt;br /&gt;loader = new Loader();&lt;br /&gt;loader.load(new flash.net.URLRequest("C:/Users/ben/Pictures/20081019_日本九州_Ben/PA190002.JPG"));&lt;br /&gt;loader.contentLoaderInfo.addEventListener(Event.COMPLETE, loaderComplete);&lt;br /&gt;addChild(loader);&lt;br /&gt;loader.addEventListener(MouseEvent.CLICK, loaderClick);&lt;br /&gt;&lt;br /&gt;function loaderComplete(e:Event):void {&lt;br /&gt; var loader:Loader = (LoaderInfo(e.target).loader);&lt;br /&gt; loader.width = 550;&lt;br /&gt; loader.height = 400;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;function loaderClick(e:Event):void {&lt;br /&gt; fr.browse();&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;function onSelect(e:Event):void {&lt;br /&gt; fr.load();&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;function onComplete(e:Event):void {&lt;br /&gt; shader = new Shader(fr.data as flash.utils.ByteArray);&lt;br /&gt; shaderFilter = new ShaderFilter(shader);&lt;br /&gt; loader.filters = [shaderFilter];&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;程式一執行，先載入照片，點選照片後，可以讓 user 透過 FileReference 載入外部 *.pbj 檔，並且可以於載入完成時透過 FileReference.data 得到檔案的 ByteArray 資料 (這也是新功能)，然後就可以產生 Shader 與 ShaderFilter，用在 loader 上當作濾鏡。&lt;br /&gt;&lt;br /&gt;執行畫面：&lt;br /&gt;&lt;br /&gt;&lt;a target="_blank" onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_HsFEtLMw5zU/SRryR1ohsjI/AAAAAAAAIgQ/HONjzogeRzE/s1600-h/Clipboard04.jpg"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 400px; height: 320px;" src="http://1.bp.blogspot.com/_HsFEtLMw5zU/SRryR1ohsjI/AAAAAAAAIgQ/HONjzogeRzE/s400/Clipboard04.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5267789102431973938" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;a target="_blank" onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_HsFEtLMw5zU/SRryR54r1QI/AAAAAAAAIgI/3OCIDLGmqQk/s1600-h/Clipboard05.jpg"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 400px; height: 277px;" src="http://3.bp.blogspot.com/_HsFEtLMw5zU/SRryR54r1QI/AAAAAAAAIgI/3OCIDLGmqQk/s400/Clipboard05.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5267789103573488898" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;a target="_blank" onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_HsFEtLMw5zU/SRryRvV4slI/AAAAAAAAIgA/o9N67A5QIl4/s1600-h/Clipboard06.jpg"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 400px; height: 320px;" src="http://3.bp.blogspot.com/_HsFEtLMw5zU/SRryRvV4slI/AAAAAAAAIgA/o9N67A5QIl4/s400/Clipboard06.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5267789100743176786" /&gt;&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4754237190569973724-5027956150209351417?l=blog.ben.idv.tw' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.ben.idv.tw/feeds/5027956150209351417/comments/default' title='張貼意見'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4754237190569973724&amp;postID=5027956150209351417' title='0 個意見'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4754237190569973724/posts/default/5027956150209351417'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4754237190569973724/posts/default/5027956150209351417'/><link rel='alternate' type='text/html' href='http://blog.ben.idv.tw/2008/11/pixel-bender.html' title='Pixel Bender'/><author><name>Ben Chang</name><uri>http://www.blogger.com/profile/01921640246111819069</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/_HsFEtLMw5zU/SRrvR3vhvCI/AAAAAAAAIfo/ae-jaN5jOcA/s72-c/Clipboard01.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4754237190569973724.post-8343595043014070718</id><published>2008-08-29T01:06:00.003+08:00</published><updated>2008-08-29T01:15:38.261+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Office'/><title type='text'>Excel 為欄位設定下拉選單的驗證方式</title><content type='html'>也不是什麼太特別的東西，也跟程式沒什麼關係，只不過是老婆問到，若要提供一個 Excel 請客戶填資料用來匯入資料庫，又希望部分欄位可以用下拉選單的方式，以免填錯，該如何在 Excel 中做這項設定呢？我想 Excel 的書中應該都會教吧，就算沒教，把功能表選單全部摸一遍，大概也可以找出做法(這時好像該稱讚一下微軟設計的好？)&lt;br /&gt;&lt;br /&gt;首先，在想要具有下拉選單的填空格中，進行 [資料] 的 [驗證] 設定：&lt;br /&gt;&lt;a target="_blank" href="http://2.bp.blogspot.com/_HsFEtLMw5zU/SLbbnY1ImGI/AAAAAAAAGOs/SD6yUm0qNqc/s1600-h/Clipboard01.jpg"&gt;&lt;img style="cursor:pointer; cursor:hand;" src="http://2.bp.blogspot.com/_HsFEtLMw5zU/SLbbnY1ImGI/AAAAAAAAGOs/SD6yUm0qNqc/s400/Clipboard01.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5239616686218844258" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;將儲存格允許的值，由原本的 "任意值" 改為 "清單"：&lt;br /&gt;&lt;a target="_blank" href="http://3.bp.blogspot.com/_HsFEtLMw5zU/SLbbnj1QLjI/AAAAAAAAGO0/vXtqUcBELpQ/s1600-h/Clipboard02.jpg"&gt;&lt;img style="cursor:pointer; cursor:hand;" src="http://3.bp.blogspot.com/_HsFEtLMw5zU/SLbbnj1QLjI/AAAAAAAAGO0/vXtqUcBELpQ/s400/Clipboard02.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5239616689172131378" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;然後 "清單來源" 就去選擇 "清單來源" 囉～很白話阿～：&lt;br /&gt;&lt;a target="_blank" href="http://4.bp.blogspot.com/_HsFEtLMw5zU/SLbboNXTZhI/AAAAAAAAGO8/49yCgJt3Y1Q/s1600-h/Clipboard03.jpg"&gt;&lt;img style="cursor:pointer; cursor:hand;" src="http://4.bp.blogspot.com/_HsFEtLMw5zU/SLbboNXTZhI/AAAAAAAAGO8/49yCgJt3Y1Q/s400/Clipboard03.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5239616700320802322" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;這樣該欄位就具備下拉功能了，只要將該欄位的格式複製到整欄即可：&lt;br /&gt;&lt;a target="_blank" href="http://4.bp.blogspot.com/_HsFEtLMw5zU/SLbbofgiCQI/AAAAAAAAGPE/lOyo6DHgQyQ/s1600-h/Clipboard04.jpg"&gt;&lt;img style="cursor:pointer; cursor:hand;" src="http://4.bp.blogspot.com/_HsFEtLMw5zU/SLbbofgiCQI/AAAAAAAAGPE/lOyo6DHgQyQ/s400/Clipboard04.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5239616705191348482" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;其他欄位也可以一樣畫葫蘆：&lt;br /&gt;&lt;a target="_blank" href="http://3.bp.blogspot.com/_HsFEtLMw5zU/SLbbonXI3yI/AAAAAAAAGPM/NXUlK0Ysvf0/s1600-h/Clipboard05.jpg"&gt;&lt;img style="cursor:pointer; cursor:hand;" src="http://3.bp.blogspot.com/_HsFEtLMw5zU/SLbbonXI3yI/AAAAAAAAGPM/NXUlK0Ysvf0/s400/Clipboard05.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5239616707299434274" /&gt;&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4754237190569973724-8343595043014070718?l=blog.ben.idv.tw' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.ben.idv.tw/feeds/8343595043014070718/comments/default' title='張貼意見'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4754237190569973724&amp;postID=8343595043014070718' title='2 個意見'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4754237190569973724/posts/default/8343595043014070718'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4754237190569973724/posts/default/8343595043014070718'/><link rel='alternate' type='text/html' href='http://blog.ben.idv.tw/2008/08/excel.html' title='Excel 為欄位設定下拉選單的驗證方式'/><author><name>Ben Chang</name><uri>http://www.blogger.com/profile/01921640246111819069</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/_HsFEtLMw5zU/SLbbnY1ImGI/AAAAAAAAGOs/SD6yUm0qNqc/s72-c/Clipboard01.jpg' height='72' width='72'/><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4754237190569973724.post-4984717418213531943</id><published>2008-08-28T15:59:00.004+08:00</published><updated>2011-08-02T16:19:08.931+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Webcam'/><category scheme='http://www.blogger.com/atom/ns#' term='BitmapData'/><category scheme='http://www.blogger.com/atom/ns#' term='AS3'/><category scheme='http://www.blogger.com/atom/ns#' term='Flash'/><title type='text'>Webcam 偵測畫面改變</title><content type='html'>之前做過畫面偵測：&lt;a target="_blank" href="http://blog.ben.idv.tw/2007/08/webcam.html"&gt;http://blog.ben.idv.tw/2007/08/webcam.html&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;這次來試試看如何可以抓到變化區域最大的地方。&lt;br /&gt;&lt;br /&gt;執行畫面如下，畫面中第一直行是原 camera，第二直行是取得與上次 BitmapData 的變化，第三直行是根據原始變化以不同大小的格子來區分，第四直行是依照格子變化將有連在一起的格子用相同顏色作群組。&lt;br /&gt;&lt;br /&gt;&lt;a target="_blank" onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_HsFEtLMw5zU/SLZbm81hJ4I/AAAAAAAAGNo/YFemZyBpGek/s1600-h/screen1.jpg"&gt;&lt;img style="cursor:pointer; cursor:hand;" src="http://1.bp.blogspot.com/_HsFEtLMw5zU/SLZbm81hJ4I/AAAAAAAAGNo/YFemZyBpGek/s400/screen1.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5239475941215905666" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;a target="_blank" onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_HsFEtLMw5zU/SLZbnCplCzI/AAAAAAAAGNw/3cu0VgXgrFw/s1600-h/screen2.jpg"&gt;&lt;img style="cursor:pointer; cursor:hand;" src="http://2.bp.blogspot.com/_HsFEtLMw5zU/SLZbnCplCzI/AAAAAAAAGNw/3cu0VgXgrFw/s400/screen2.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5239475942776441650" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;a target="_blank" onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_HsFEtLMw5zU/SLZbnB4P4uI/AAAAAAAAGN8/WncfDiZPakw/s1600-h/screen3.jpg"&gt;&lt;img style="cursor:pointer; cursor:hand;" src="http://4.bp.blogspot.com/_HsFEtLMw5zU/SLZbnB4P4uI/AAAAAAAAGN8/WncfDiZPakw/s400/screen3.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5239475942569534178" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;若是整個環境沒有太多雜訊，若是人物離 camera 遠一點(使人物對畫面的影響減少)，然後用拳頭取代手指(因為人坐遠了，所以要大一點的指標)，然後為了避免手臂會被誤判，所以要將手臂抬起來呈現直指 camera 的姿勢，這樣的話就可以讓變化區比較集中一些了。&lt;br /&gt;&lt;br /&gt;不過，上述的範例，放在瀏覽器的 flash player 播放時，會停住，想必可能是因為我中間作了太多不必要的 BitmapData 的關係吧：&lt;br /&gt;&lt;br /&gt;&lt;a target="_blank" onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_HsFEtLMw5zU/SLZbnY7AEvI/AAAAAAAAGOI/Kzy5rEZpzs0/s1600-h/screen4.jpg"&gt;&lt;img style="cursor:pointer; cursor:hand;" src="http://2.bp.blogspot.com/_HsFEtLMw5zU/SLZbnY7AEvI/AAAAAAAAGOI/Kzy5rEZpzs0/s400/screen4.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5239475948755096306" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;原始檔：&lt;a target="_blank" href="http://ben.rb.chang.googlepages.com/20080828_Webcam_Detect.fla"&gt;http://ben.rb.chang.googlepages.com/20080828_Webcam_Detect.fla&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;=====================================================&lt;br /&gt;&lt;br /&gt;[2008-08-28-16-34]&lt;br /&gt;&lt;br /&gt;若是將最後取得的最大 Rect，用其中心點來控制小球的話，畫面如下：&lt;br /&gt;&lt;br /&gt;&lt;a target="_blank" onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_HsFEtLMw5zU/SLZi-GOZ4tI/AAAAAAAAGOU/zrxy2Zbjwf0/s1600-h/screen5.jpg"&gt;&lt;img style="cursor:pointer; cursor:hand;" src="http://2.bp.blogspot.com/_HsFEtLMw5zU/SLZi-GOZ4tI/AAAAAAAAGOU/zrxy2Zbjwf0/s400/screen5.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5239484035454591698" /&gt;&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4754237190569973724-4984717418213531943?l=blog.ben.idv.tw' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.ben.idv.tw/feeds/4984717418213531943/comments/default' title='張貼意見'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4754237190569973724&amp;postID=4984717418213531943' title='4 個意見'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4754237190569973724/posts/default/4984717418213531943'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4754237190569973724/posts/default/4984717418213531943'/><link rel='alternate' type='text/html' href='http://blog.ben.idv.tw/2008/08/webcam.html' title='Webcam 偵測畫面改變'/><author><name>Ben Chang</name><uri>http://www.blogger.com/profile/01921640246111819069</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/_HsFEtLMw5zU/SLZbm81hJ4I/AAAAAAAAGNo/YFemZyBpGek/s72-c/screen1.jpg' height='72' width='72'/><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4754237190569973724.post-6768222836472655414</id><published>2008-08-28T10:57:00.004+08:00</published><updated>2008-08-28T17:04:48.309+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Google API'/><title type='text'>Google Map 做店家地圖</title><content type='html'>若是想要用 Google Map API(JavaScript版) 製作店家地圖的話，我寫了以下的範例。&lt;br /&gt;&lt;br /&gt;從技術的角度來說，要參考的資源有：&lt;br /&gt;&lt;br /&gt;* 官網範例：http://code.google.com/apis/maps/documentation/examples/index.html&lt;br /&gt;* 官網API文件：http://code.google.com/apis/maps/documentation/reference.html&lt;br /&gt;&lt;br /&gt;做出來的畫面，第一次使用時，可用設定介面來批次搜尋大量的店家地址，以找出每家店的經緯度，然後存成 xml：&lt;br /&gt;&lt;br /&gt;&lt;a target="_blank" onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_HsFEtLMw5zU/SLYUp356p3I/AAAAAAAAGNY/CufrEU2YOr0/s1600-h/screen1.jpg"&gt;&lt;img style="cursor:pointer; cursor:hand;" src="http://2.bp.blogspot.com/_HsFEtLMw5zU/SLYUp356p3I/AAAAAAAAGNY/CufrEU2YOr0/s400/screen1.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5239397926106212210" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;之後，正式放在網站上時，只要使用以下的部份，將事先查好的 xml 載入進來呈現即可：&lt;br /&gt;&lt;br /&gt;&lt;a target="_blank" onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_HsFEtLMw5zU/SLYUqeJekDI/AAAAAAAAGNg/BKqQZrXZnzc/s1600-h/screen2.jpg"&gt;&lt;img style="cursor:pointer; cursor:hand;" src="http://4.bp.blogspot.com/_HsFEtLMw5zU/SLYUqeJekDI/AAAAAAAAGNg/BKqQZrXZnzc/s400/screen2.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5239397936372027442" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;線上瀏覽：&lt;br /&gt;&lt;a target="_blank" href="http://ben.rb.chang.googlepages.com/20080828_GoogleMap.html"&gt;http://ben.rb.chang.googlepages.com/20080828_GoogleMap.html&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;以上範例的店家資料，我是以 &lt;a target="_blank" href="http://www.misterdonut.com.tw/shop/shop-T.htm"&gt;misterdonut&lt;/a&gt; 為例。&lt;br /&gt;&lt;br /&gt;======================================================&lt;br /&gt;&lt;br /&gt;[2008-08-28-17-01]&lt;br /&gt;&lt;br /&gt;正巧今天要找彰化銀行的位置，官網提供的據點：&lt;br /&gt;&lt;br /&gt;https://www.chb.com.tw/chbib/faces/po/po01201/PO01201_2.jsp?city=%E8%87%BA%E5%8C%97%E5%B8%82&lt;br /&gt;&lt;br /&gt;自己想辦法用 Excel 將資料切成想要的格式：&lt;br /&gt;&lt;br /&gt;臺北市中正區衡陽路68號3樓 |02-23619654&lt;br /&gt;臺北市中正區衡陽路68號 |02-23113791&lt;br /&gt;臺北市中正區重慶南路一段27號 |02-23617211&lt;br /&gt;臺北市中正區金山南路一段47號 |02-23560000&lt;br /&gt;臺北市大同區延平北路一段18號 |02-25586271&lt;br /&gt;臺北市大同區迪化街一段120號 |02-25585151&lt;br /&gt;臺北市大同區南京西路123號 |02-25555121&lt;br /&gt;臺北市大同區重慶北路三段199號 |02-25919113&lt;br /&gt;臺北市中山區中山北路二段57號12樓 |02-25362951&lt;br /&gt;臺北市中山區中山北路二段57號6樓 |02-&lt;br /&gt;臺北市中山區中山北路二段57號5樓 |02-25362951&lt;br /&gt;臺北市中山區中山北路二段57號1樓 |02-25514256&lt;br /&gt;臺北市中山區長安東路一段23號之1 |02-25230739&lt;br /&gt;臺北市中山區中山北路二段111號 |02-25711241&lt;br /&gt;臺北市中山區南京東路二段98號 |02-25626151&lt;br /&gt;臺北市中山區林森北路609號 |02-25950551&lt;br /&gt;臺北市中山區北安路589號 |02-25337861&lt;br /&gt;臺北市中山區松江路261號 |02-25024923&lt;br /&gt;臺北市中山區南京東路三段225號 |02-27153535&lt;br /&gt;臺北市中山區八德路2段201號 |02-27312211&lt;br /&gt;臺北市松山區復興北路367號 |02-27173222&lt;br /&gt;臺北市松山區南京東路五段213號 |02-27639611&lt;br /&gt;臺北市松山區民生東路四段54之1號 |02-27121311&lt;br /&gt;臺北市松山區南京東路四段126號 |02-25704567&lt;br /&gt;臺北市大安區金山南路二段33號 |02-23921241&lt;br /&gt;臺北市大安區羅斯福路二段25號 |02-23517211&lt;br /&gt;臺北市大安區和平東路一段177號 |02-23213214&lt;br /&gt;臺北市大安區仁愛路三段136號 |02-27033737&lt;br /&gt;臺北市大安區信義路四段155號 |02-27039081&lt;br /&gt;臺北市大安區敦化南路二段71號 |02-27849821&lt;br /&gt;臺北市大安區仁愛路四段31號 |02-27514066&lt;br /&gt;臺北市大安區忠孝東路四段164號 |02-27713151&lt;br /&gt;臺北市萬華區西寧南路169之2號 |02-23719271&lt;br /&gt;臺北市萬華區康定路304號 |02-23060201&lt;br /&gt;臺北市萬華區莒光路312號 |02-23042141&lt;br /&gt;臺北市信義區基隆路一段333號3樓 |02-27203101&lt;br /&gt;臺北市松山區永吉路165號 |02-27625242&lt;br /&gt;臺北市信義區忠孝東路五段1之2號 |02-27682322&lt;br /&gt;臺北市士林區中山北路六段88號 |02-28333232&lt;br /&gt;臺北市士林區福德路21號 |02-28822354&lt;br /&gt;臺北市北投區大業路452巷6號1樓 |02-28968585&lt;br /&gt;臺北市內湖區文德路100號 |02-26590766&lt;br /&gt;臺北市內湖區民權東路六段109號 |02-27904567&lt;br /&gt;臺北市內湖區瑞光路513巷26號 |02-27978966&lt;br /&gt;臺北市南港區南港路三段48號 |02-27833456&lt;br /&gt;臺北市內湖區新湖二路180號 |02-27931616&lt;br /&gt;臺北市南港區園區街3號2樓之3 |02-26558169&lt;br /&gt;臺北市文山區木新路三段48號 |02-86617377&lt;br /&gt;&lt;br /&gt;貼進批次查詢介面中，就可以找到囉：&lt;br /&gt;&lt;br /&gt;&lt;a target="_blank" onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_HsFEtLMw5zU/SLZqHHTVlBI/AAAAAAAAGOc/eE-qUwy5-do/s1600-h/Clipboard01.jpg"&gt;&lt;img style="cursor:pointer; cursor:hand;" src="http://2.bp.blogspot.com/_HsFEtLMw5zU/SLZqHHTVlBI/AAAAAAAAGOc/eE-qUwy5-do/s400/Clipboard01.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5239491886943933458" /&gt;&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4754237190569973724-6768222836472655414?l=blog.ben.idv.tw' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.ben.idv.tw/feeds/6768222836472655414/comments/default' title='張貼意見'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4754237190569973724&amp;postID=6768222836472655414' title='3 個意見'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4754237190569973724/posts/default/6768222836472655414'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4754237190569973724/posts/default/6768222836472655414'/><link rel='alternate' type='text/html' href='http://blog.ben.idv.tw/2008/08/google-map.html' title='Google Map 做店家地圖'/><author><name>Ben Chang</name><uri>http://www.blogger.com/profile/01921640246111819069</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/_HsFEtLMw5zU/SLYUp356p3I/AAAAAAAAGNY/CufrEU2YOr0/s72-c/screen1.jpg' height='72' width='72'/><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4754237190569973724.post-6717586566527609550</id><published>2008-08-19T14:47:00.003+08:00</published><updated>2008-08-19T14:58:36.195+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='AS3'/><category scheme='http://www.blogger.com/atom/ns#' term='Flash'/><title type='text'>不規則移動動畫的移動控制</title><content type='html'>若有一物體，依照動畫路徑移動，同時會依照動畫路徑改變角度，若我們希望能控制該物體延著物體 y 軸做垂直上下移動時，我們需要計算當時的物體角度，來算出新的座標。不過，當然，簡單的作法，就是好好利用 Flash 的特性囉。&lt;br /&gt;&lt;br /&gt;線上瀏覽：&lt;br /&gt;&lt;a target="_blank" href="http://ben.rb.chang.googlepages.com/20080819_timeline_dir.html"&gt;http://ben.rb.chang.googlepages.com/20080819_timeline_dir.html&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;截圖：&lt;br /&gt;&lt;a target="_blank" onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_HsFEtLMw5zU/SKptjKqUqFI/AAAAAAAAGM4/jCU5FDLz1w8/s1600-h/Clipboard01.jpg"&gt;&lt;img style="cursor:pointer; cursor:hand;" src="http://1.bp.blogspot.com/_HsFEtLMw5zU/SKptjKqUqFI/AAAAAAAAGM4/jCU5FDLz1w8/s400/Clipboard01.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5236117967696341074" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;直接看 fla 原始檔吧，注意車子多包一層 MovieClip 的用途：&lt;br /&gt;&lt;a target="_blank" href="http://ben.rb.chang.googlepages.com/20080819_timeline_dir.fla"&gt;http://ben.rb.chang.googlepages.com/20080819_timeline_dir.fla&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;frame 1 程式碼：&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;function btnLeft_onClick(evt:MouseEvent):void{&lt;br /&gt; ani_mc.carAni_mc.car_mc.y -= 5;&lt;br /&gt;}&lt;br /&gt;btnLeft.addEventListener(MouseEvent.CLICK, btnLeft_onClick);&lt;br /&gt;&lt;br /&gt;function btnRight_onClick(evt:MouseEvent):void{&lt;br /&gt; ani_mc.carAni_mc.car_mc.y += 5;&lt;br /&gt;}&lt;br /&gt;btnRight.addEventListener(MouseEvent.CLICK, btnRight_onClick);&lt;br /&gt;&lt;br /&gt;function stage_onEnterFrame(evt:Event):void{&lt;br /&gt; var p:Point = new Point(ani_mc.carAni_mc.car_mc.x, ani_mc.carAni_mc.car_mc.y);&lt;br /&gt; p = ani_mc.carAni_mc.localToGlobal(p);&lt;br /&gt; &lt;br /&gt; msg_txt.text = ani_mc.road_mc.hitTestPoint(p.x, p.y, true);&lt;br /&gt;}&lt;br /&gt;stage.addEventListener(Event.ENTER_FRAME, stage_onEnterFrame);&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;判斷車子是否離開路面，也只要轉換一下座標，與路面灰色區域 進行 hitTestPoint() 測試即可。特別要注意的是我是以兩個輪胎中心點當作碰撞偵測的基準。&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4754237190569973724-6717586566527609550?l=blog.ben.idv.tw' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.ben.idv.tw/feeds/6717586566527609550/comments/default' title='張貼意見'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4754237190569973724&amp;postID=6717586566527609550' title='0 個意見'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4754237190569973724/posts/default/6717586566527609550'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4754237190569973724/posts/default/6717586566527609550'/><link rel='alternate' type='text/html' href='http://blog.ben.idv.tw/2008/08/blog-post_8440.html' title='不規則移動動畫的移動控制'/><author><name>Ben Chang</name><uri>http://www.blogger.com/profile/01921640246111819069</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/_HsFEtLMw5zU/SKptjKqUqFI/AAAAAAAAGM4/jCU5FDLz1w8/s72-c/Clipboard01.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4754237190569973724.post-8807874040678165641</id><published>2008-08-19T11:05:00.004+08:00</published><updated>2008-08-19T11:15:50.684+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='AS3'/><category scheme='http://www.blogger.com/atom/ns#' term='Flash'/><title type='text'>不規則移動動畫的速度控制</title><content type='html'>若是有一段物體移動動畫，是不規則的路線，用一堆座標陣列也不是不可以，不過若希望用更簡單的方式的話，可以直接配合時間軸動畫來做。&lt;br /&gt;&lt;br /&gt;線上瀏覽：&lt;br /&gt;&lt;a target="_blank" href="http://ben.rb.chang.googlepages.com/20080819_timeline_speed.html"&gt;http://ben.rb.chang.googlepages.com/20080819_timeline_speed.html&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;截圖：&lt;br /&gt;&lt;a target="_blank" onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_HsFEtLMw5zU/SKo5TogQdiI/AAAAAAAAGMY/tJrgTzM0V2M/s1600-h/Clipboard01.jpg"&gt;&lt;img style="cursor:pointer; cursor:hand;" src="http://3.bp.blogspot.com/_HsFEtLMw5zU/SKo5TogQdiI/AAAAAAAAGMY/tJrgTzM0V2M/s400/Clipboard01.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5236060526224635426" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;原始檔：&lt;br /&gt;&lt;a target="_blank" href="http://ben.rb.chang.googlepages.com/20080819_timeline_speed.fla"&gt;http://ben.rb.chang.googlepages.com/20080819_timeline_speed.fla&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;frame 1 的程式碼：&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;function m1_mc_onEnterFrame(evt:Event):void{&lt;br /&gt; var mc:MovieClip = evt.target as MovieClip;&lt;br /&gt; frame_txt.text = mc.currentFrame.toString();&lt;br /&gt; speed_txt.text = speed.toString();&lt;br /&gt;}&lt;br /&gt;m1_mc.addEventListener(Event.ENTER_FRAME, m1_mc_onEnterFrame);&lt;br /&gt;m1_mc.stop();&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;//時速轉微秒&lt;br /&gt;function speed2ms(speed:int):Number{&lt;br /&gt; return ((speed - SPEED_MIN) / (SPEED_MAX-SPEED_MIN)) * (SPEED_MS_MAX-SPEED_MS_MIN) + SPEED_MS_MIN;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;var SPEED_MAX:int = 100; //最高時速&lt;br /&gt;var SPEED_MIN:int = 0; //最低時速&lt;br /&gt;var SPEED_DIFF:int = 20; //每階段時速變化&lt;br /&gt;var speed:int = SPEED_MIN;&lt;br /&gt;&lt;br /&gt;var SPEED_MS_MAX:int = 20; //最快多少微秒更新一次&lt;br /&gt;var SPEED_MS_MIN:int = 200; //最慢多少微秒更新一次&lt;br /&gt;var speed_ms:Number = speed2ms(speed);&lt;br /&gt;&lt;br /&gt;var timer:Timer = new Timer(speed_ms);&lt;br /&gt;function timer_onTimer(evt:TimerEvent):void{&lt;br /&gt; m1_mc.nextFrame();&lt;br /&gt; if(m1_mc.currentFrame==m1_mc.totalFrames){&lt;br /&gt;  m1_mc.gotoAndStop(1);&lt;br /&gt; }&lt;br /&gt;}&lt;br /&gt;timer.addEventListener(TimerEvent.TIMER, timer_onTimer);&lt;br /&gt;&lt;br /&gt;function btnUp_onClick(evt:MouseEvent):void{&lt;br /&gt; speed = Math.min(SPEED_MAX, speed+SPEED_DIFF);&lt;br /&gt; speed_ms = speed2ms(speed);&lt;br /&gt; timer.delay = speed_ms;&lt;br /&gt; trace("speed=" + speed + ", speed_ms=" + speed_ms);&lt;br /&gt; if(!timer.running){&lt;br /&gt;  timer.start();&lt;br /&gt; }&lt;br /&gt;}&lt;br /&gt;btnUp.addEventListener(MouseEvent.CLICK, btnUp_onClick);&lt;br /&gt;&lt;br /&gt;function btnDown_onClick(evt:MouseEvent):void{&lt;br /&gt; speed = Math.max(SPEED_MIN, speed-SPEED_DIFF);&lt;br /&gt; speed_ms = speed2ms(speed);&lt;br /&gt; timer.delay = speed_ms;&lt;br /&gt; trace("speed=" + speed + ", speed_ms=" + speed_ms);&lt;br /&gt; if(timer.delay==SPEED_MS_MIN){&lt;br /&gt;  timer.stop();&lt;br /&gt; }&lt;br /&gt;}&lt;br /&gt;btnDown.addEventListener(MouseEvent.CLICK, btnDown_onClick);&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;基本觀念就是，自己決定要間隔多少微秒，呼叫 nextFrame() 一次。&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4754237190569973724-8807874040678165641?l=blog.ben.idv.tw' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.ben.idv.tw/feeds/8807874040678165641/comments/default' title='張貼意見'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4754237190569973724&amp;postID=8807874040678165641' title='0 個意見'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4754237190569973724/posts/default/8807874040678165641'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4754237190569973724/posts/default/8807874040678165641'/><link rel='alternate' type='text/html' href='http://blog.ben.idv.tw/2008/08/blog-post_19.html' title='不規則移動動畫的速度控制'/><author><name>Ben Chang</name><uri>http://www.blogger.com/profile/01921640246111819069</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/_HsFEtLMw5zU/SKo5TogQdiI/AAAAAAAAGMY/tJrgTzM0V2M/s72-c/Clipboard01.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4754237190569973724.post-5800707137108260377</id><published>2008-08-08T14:39:00.003+08:00</published><updated>2008-08-08T15:07:03.797+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='AS3'/><title type='text'>Stage RESIZE 時的物件座標</title><content type='html'>最近遇到需要製作 Flash 全畫面的機制，所有物件都需要用程式來控制座標，以求當 player / browser 改變大小時，各物件可以隨著邊緣的相對距離 / 比例做改變。&lt;br /&gt;&lt;br /&gt;首先，我準備了幾個 MC 放在場景上，等下將會將每個 MC 給予不同的設定：&lt;br /&gt;&lt;br /&gt;&lt;a target="_blank" onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_HsFEtLMw5zU/SJvrfDgLWLI/AAAAAAAAGJI/bXrEnqnEKq8/s1600-h/Clipboard01.jpg"&gt;&lt;img style="cursor:pointer; cursor:hand;" src="http://1.bp.blogspot.com/_HsFEtLMw5zU/SJvrfDgLWLI/AAAAAAAAGJI/bXrEnqnEKq8/s400/Clipboard01.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5232034310869702834" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;fla 的 frame 1 上的原始碼為：&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;var layoutMgr:PositionManager = PositionManager.getInstance(550, 400, stage, StageAlign.BOTTOM);&lt;br /&gt;if(false){&lt;br /&gt; layoutMgr.add(m1, PositionManager.BASE_POINT, PositionManager.ALIGN_TOP_LEFT);&lt;br /&gt; layoutMgr.add(m2, PositionManager.BASE_POINT, PositionManager.ALIGN_TOP);&lt;br /&gt; layoutMgr.add(m3, PositionManager.BASE_POINT, PositionManager.ALIGN_TOP_RIGHT);&lt;br /&gt; layoutMgr.add(m4, PositionManager.BASE_POINT, PositionManager.ALIGN_LEFT);&lt;br /&gt; layoutMgr.add(m5, PositionManager.BASE_POINT);&lt;br /&gt; layoutMgr.add(m6, PositionManager.BASE_POINT, PositionManager.ALIGN_RIGHT);&lt;br /&gt; layoutMgr.add(m7, PositionManager.BASE_POINT, PositionManager.ALIGN_BOTTOM_LEFT);&lt;br /&gt; layoutMgr.add(m8, PositionManager.BASE_POINT, PositionManager.ALIGN_BOTTOM);&lt;br /&gt; layoutMgr.add(m9, PositionManager.BASE_POINT, PositionManager.ALIGN_BOTTOM_RIGHT);&lt;br /&gt; &lt;br /&gt; layoutMgr.add(p1, PositionManager.BASE_POINT, PositionManager.ALIGN_RATIO, .25, .25);&lt;br /&gt; layoutMgr.add(p2, PositionManager.BASE_POINT, PositionManager.ALIGN_RATIO, .75, .25);&lt;br /&gt; layoutMgr.add(p3, PositionManager.BASE_POINT, PositionManager.ALIGN_RATIO, .25, .75);&lt;br /&gt; layoutMgr.add(p4, PositionManager.BASE_POINT, PositionManager.ALIGN_RATIO, .75, .75);&lt;br /&gt;}else{&lt;br /&gt; layoutMgr.add(m1, PositionManager.BASE_BOARDER, PositionManager.ALIGN_TOP_LEFT);&lt;br /&gt; layoutMgr.add(m2, PositionManager.BASE_BOARDER, PositionManager.ALIGN_TOP);&lt;br /&gt; layoutMgr.add(m3, PositionManager.BASE_BOARDER, PositionManager.ALIGN_TOP_RIGHT);&lt;br /&gt; layoutMgr.add(m4, PositionManager.BASE_BOARDER, PositionManager.ALIGN_LEFT);&lt;br /&gt; layoutMgr.add(m5, PositionManager.BASE_BOARDER);&lt;br /&gt; layoutMgr.add(m6, PositionManager.BASE_BOARDER, PositionManager.ALIGN_RIGHT);&lt;br /&gt; layoutMgr.add(m7, PositionManager.BASE_BOARDER, PositionManager.ALIGN_BOTTOM_LEFT);&lt;br /&gt; layoutMgr.add(m8, PositionManager.BASE_BOARDER, PositionManager.ALIGN_BOTTOM);&lt;br /&gt; layoutMgr.add(m9, PositionManager.BASE_BOARDER, PositionManager.ALIGN_BOTTOM_RIGHT);&lt;br /&gt; &lt;br /&gt; layoutMgr.add(p1, PositionManager.BASE_BOARDER, PositionManager.ALIGN_RATIO, .25, .25);&lt;br /&gt; layoutMgr.add(p2, PositionManager.BASE_BOARDER, PositionManager.ALIGN_RATIO, .75, .25);&lt;br /&gt; layoutMgr.add(p3, PositionManager.BASE_BOARDER, PositionManager.ALIGN_RATIO, .25, .75);&lt;br /&gt; layoutMgr.add(p4, PositionManager.BASE_BOARDER, PositionManager.ALIGN_RATIO, .75, .75);&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;var stageWH_txt:TextField = new TextField();&lt;br /&gt;addChild(stageWH_txt);&lt;br /&gt;stageWH_txt.border = true;&lt;br /&gt;stageWH_txt.autoSize = TextFieldAutoSize.LEFT;&lt;br /&gt;stageWH_txt.text = "stage = " + stage.stageWidth + " x " + stage.stageHeight;&lt;br /&gt;layoutMgr.add(stageWH_txt, PositionManager.BASE_POINT, PositionManager.ALIGN_OFFSET_BR, stageWH_txt.width + 10, 100);&lt;br /&gt;&lt;br /&gt;layoutMgr.startAutoLayout();&lt;br /&gt;&lt;br /&gt;stage.addEventListener(Event.RESIZE&lt;br /&gt;        , function(evt:Event):void{&lt;br /&gt;         stageWH_txt.text = "stage = " + stage.stageWidth + " x " + stage.stageHeight;&lt;br /&gt;      });&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;我自訂了一個 PositionManager 類別，只要將各種設定利用 add() 加到 PositionManager 物件中，然後就可以用 startAutoLayout() 來啟動了。&lt;br /&gt;&lt;br /&gt;新增設定時，第二個參數要填 PositionManager.BASE_POINT 或 PositionManager.BASE_BOARDER，表示是以物件的座標做基準，還是以物件的外邊界做基準，等下看截圖會比較懂～&lt;br /&gt;&lt;br /&gt;第三個參數則有 PositionManager.ALIGN_TOP_LEFT 等八種代表要將物件貼到八方向的邊緣上，若是不想完全貼緊 Stage 的邊緣的話，也可以用 PositionManager.ALIGN_RATIO 然後指定第四、第五參數，來指定物件距離左上角百分比，若是 1 表示最右邊或最下面。&lt;br /&gt;&lt;br /&gt;第三個參數除了貼邊緣，與自訂百分比之外，也可以設定要距離四個角多少像素，有 PositionManager.ALIGN_OFFSET_TL 等四種代表 Stage 的四個頂角，若是設定 PositionManager.ALIGN_OFFSET_BR，然後第四、第五 參數設定為 100 的話，表示物件要放在距離右下角各 100 的位置。&lt;br /&gt;&lt;br /&gt;PositionManager.as 原始檔如下：&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;package{&lt;br /&gt; import flash.display.*;&lt;br /&gt; import flash.events.*;&lt;br /&gt; import flash.geom.*;&lt;br /&gt; &lt;br /&gt; public class PositionManager{&lt;br /&gt;  private static var __instance:PositionManager;&lt;br /&gt;  &lt;br /&gt;  public static var BASE_BOARDER:int = 1;&lt;br /&gt;  public static var BASE_POINT:int = 2;&lt;br /&gt;  &lt;br /&gt;  public static var ALIGN_TOP_LEFT:int = 1;&lt;br /&gt;  public static var ALIGN_TOP:int = 2;&lt;br /&gt;  public static var ALIGN_TOP_RIGHT:int = 3;&lt;br /&gt;  public static var ALIGN_LEFT:int = 4;&lt;br /&gt;  public static var ALIGN_RIGHT:int = 5;&lt;br /&gt;  public static var ALIGN_BOTTOM_LEFT:int = 6;&lt;br /&gt;  public static var ALIGN_BOTTOM:int = 7;&lt;br /&gt;  public static var ALIGN_BOTTOM_RIGHT:int = 8;&lt;br /&gt;  &lt;br /&gt;  public static var ALIGN_RATIO:int = 9;&lt;br /&gt;  &lt;br /&gt;  public static var ALIGN_OFFSET_TL:int = 10;&lt;br /&gt;  public static var ALIGN_OFFSET_TR:int = 11;&lt;br /&gt;  public static var ALIGN_OFFSET_BL:int = 12;&lt;br /&gt;  public static var ALIGN_OFFSET_BR:int = 13;&lt;br /&gt;  &lt;br /&gt;  public static function getInstance(movieWidth:Number, movieHeight:Number, stage:Stage=null, align:String=""):PositionManager{&lt;br /&gt;   if(__instance==null){&lt;br /&gt;    if(stage!=null){&lt;br /&gt;     __instance = new PositionManager(movieWidth, movieHeight, stage, align);&lt;br /&gt;    }else{&lt;br /&gt;     throw new Error("初始化須提供Stage類別物件");&lt;br /&gt;    }&lt;br /&gt;   }&lt;br /&gt;   return __instance;&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  private var __movieWidth:Number;&lt;br /&gt;  private var __movieHeight:Number;&lt;br /&gt;&lt;br /&gt;  private var __stage:Stage;&lt;br /&gt;  private var __align:String;&lt;br /&gt;&lt;br /&gt;  private var __ary:Array;&lt;br /&gt;  &lt;br /&gt;  function PositionManager(movieWidth:Number, movieHeight:Number, stage:Stage, align:String){&lt;br /&gt;   trace("[PositionManager]");&lt;br /&gt;   __movieWidth = movieWidth;&lt;br /&gt;   __movieHeight = movieHeight;&lt;br /&gt;   __stage = stage;&lt;br /&gt;   __align = align;&lt;br /&gt;   &lt;br /&gt;   __ary = new Array();&lt;br /&gt;  }&lt;br /&gt;  &lt;br /&gt;  public function add(obj:DisplayObject, base:int, align:int=0, cust_x:Number=0, cust_y:Number=0):void{&lt;br /&gt;   __ary.push({obj:obj, base:base, align:align, cust_x:cust_x, cust_y:cust_y});&lt;br /&gt;  }&lt;br /&gt;  &lt;br /&gt;  public function startAutoLayout():void{&lt;br /&gt;   __stage.scaleMode = StageScaleMode.NO_SCALE;&lt;br /&gt;   __stage.align = __align;&lt;br /&gt;   __stage.addEventListener(Event.RESIZE, onResizeHandler);&lt;br /&gt;   &lt;br /&gt;   arrange();&lt;br /&gt;  }&lt;br /&gt;  &lt;br /&gt;  public function stopAutoLayout():void{&lt;br /&gt;   __stage.removeEventListener(Event.RESIZE, onResizeHandler);&lt;br /&gt;  }&lt;br /&gt;  &lt;br /&gt;  private function onResizeHandler(evt:Event):void{&lt;br /&gt;   trace("[PositionManager.onResizeHandler]stage.x=" + __stage.x + ", stage.y=" + __stage.y);&lt;br /&gt;   arrange();&lt;br /&gt;  }&lt;br /&gt;  &lt;br /&gt;  private function arrange():void{&lt;br /&gt;   trace("[PositionManager.arrange]");&lt;br /&gt;   &lt;br /&gt;   var sw:Number = __stage.stageWidth;&lt;br /&gt;   var sh:Number = __stage.stageHeight;&lt;br /&gt;   &lt;br /&gt;   var movieX:Number;&lt;br /&gt;   var movieY:Number;&lt;br /&gt;   &lt;br /&gt;   var ratioX:Number;&lt;br /&gt;   var ratioY:Number;&lt;br /&gt;   &lt;br /&gt;   switch(__align){&lt;br /&gt;    case StageAlign.TOP_LEFT:&lt;br /&gt;     ratioX = 0;&lt;br /&gt;     ratioY = 0;&lt;br /&gt;     break;&lt;br /&gt;    case StageAlign.TOP:&lt;br /&gt;     ratioX = .5;&lt;br /&gt;     ratioY = 0;&lt;br /&gt;     break;&lt;br /&gt;    case StageAlign.TOP_RIGHT:&lt;br /&gt;     ratioX = 1;&lt;br /&gt;     ratioY = 0;&lt;br /&gt;     break;&lt;br /&gt;    case StageAlign.LEFT:&lt;br /&gt;     ratioX = 0;&lt;br /&gt;     ratioY = .5;&lt;br /&gt;     break;&lt;br /&gt;    case StageAlign.RIGHT:&lt;br /&gt;     ratioX = 1;&lt;br /&gt;     ratioY = .5;&lt;br /&gt;     break;&lt;br /&gt;    case StageAlign.BOTTOM_LEFT:&lt;br /&gt;     ratioX = 0;&lt;br /&gt;     ratioY = 1;&lt;br /&gt;     break;&lt;br /&gt;    case StageAlign.BOTTOM:&lt;br /&gt;     ratioX = .5;&lt;br /&gt;     ratioY = 1;&lt;br /&gt;     break;&lt;br /&gt;    case StageAlign.BOTTOM_RIGHT:&lt;br /&gt;     ratioX = 1;&lt;br /&gt;     ratioY = 1;&lt;br /&gt;     break;&lt;br /&gt;    default:&lt;br /&gt;     ratioX = .5;&lt;br /&gt;     ratioY = .5;&lt;br /&gt;   }&lt;br /&gt;   movieX = (sw - __movieWidth) * ratioX;&lt;br /&gt;   movieY = (sh - __movieHeight) * ratioY;&lt;br /&gt;&lt;br /&gt;   trace("movieX=" + movieX + ", movieY=" + movieY);&lt;br /&gt;   &lt;br /&gt;   for(var i:int=0; i&amp;lt;__ary.length; i++){&lt;br /&gt;    var obj:Object = __ary[i];&lt;br /&gt;    var displayObj:DisplayObject = obj["obj"] as DisplayObject;&lt;br /&gt;    &lt;br /&gt;    switch(obj["align"]){&lt;br /&gt;     case ALIGN_TOP_LEFT:&lt;br /&gt;      ratioX = 0;&lt;br /&gt;      ratioY = 0;&lt;br /&gt;      break;&lt;br /&gt;     case ALIGN_TOP:&lt;br /&gt;      ratioX = .5;&lt;br /&gt;      ratioY = 0;&lt;br /&gt;      break;&lt;br /&gt;     case ALIGN_TOP_RIGHT:&lt;br /&gt;      ratioX = 1;&lt;br /&gt;      ratioY = 0;&lt;br /&gt;      break;&lt;br /&gt;     case ALIGN_LEFT:&lt;br /&gt;      ratioX = 0;&lt;br /&gt;      ratioY = .5;&lt;br /&gt;      break;&lt;br /&gt;     case ALIGN_RIGHT:&lt;br /&gt;      ratioX = 1;&lt;br /&gt;      ratioY = .5;&lt;br /&gt;      break;&lt;br /&gt;     case ALIGN_BOTTOM_LEFT:&lt;br /&gt;      ratioX = 0;&lt;br /&gt;      ratioY = 1;&lt;br /&gt;      break;&lt;br /&gt;     case ALIGN_BOTTOM:&lt;br /&gt;      ratioX = .5;&lt;br /&gt;      ratioY = 1;&lt;br /&gt;      break;&lt;br /&gt;     case ALIGN_BOTTOM_RIGHT:&lt;br /&gt;      ratioX = 1;&lt;br /&gt;      ratioY = 1;&lt;br /&gt;      break;&lt;br /&gt;     case ALIGN_RATIO:&lt;br /&gt;      ratioX = obj["cust_x"];&lt;br /&gt;      ratioY = obj["cust_y"];&lt;br /&gt;      break;&lt;br /&gt;     case ALIGN_OFFSET_TL:&lt;br /&gt;      ratioX = obj["cust_x"] / sw;&lt;br /&gt;      ratioY = obj["cust_y"] / sh;&lt;br /&gt;      break;&lt;br /&gt;     case ALIGN_OFFSET_TR:&lt;br /&gt;      ratioX = (sw - obj["cust_x"]) / sw;&lt;br /&gt;      ratioY = obj["cust_y"] / sh;&lt;br /&gt;      break;&lt;br /&gt;     case ALIGN_OFFSET_BL:&lt;br /&gt;      ratioX = obj["cust_x"] / sw;&lt;br /&gt;      ratioY = (sh - obj["cust_y"]) / sh;&lt;br /&gt;      break;&lt;br /&gt;     case ALIGN_OFFSET_BR:&lt;br /&gt;      ratioX = (sw - obj["cust_x"]) / sw;&lt;br /&gt;      ratioY = (sh - obj["cust_y"]) / sh;&lt;br /&gt;      break;&lt;br /&gt;     case 0:&lt;br /&gt;     default:&lt;br /&gt;      ratioX = .5;&lt;br /&gt;      ratioY = .5;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    if(obj["base"] == BASE_POINT){&lt;br /&gt;     displayObj.x = sw * ratioX;&lt;br /&gt;     displayObj.y = sh * ratioY;&lt;br /&gt;    }else if(obj["base"] == BASE_BOARDER){&lt;br /&gt;     var topRect:Rectangle = displayObj.getBounds(__stage);&lt;br /&gt;     var parentRect:Rectangle = displayObj.getBounds(displayObj.parent);&lt;br /&gt;     //trace("topRect=" + topRect + ", parentRect=" + parentRect);&lt;br /&gt;    &lt;br /&gt;     var cx:Number = displayObj.x - parentRect.x;&lt;br /&gt;     var cy:Number = displayObj.y - parentRect.y;&lt;br /&gt;     //trace(displayObj.name + ", cx=" + cx + ", cy=" + cy);&lt;br /&gt;     &lt;br /&gt;     displayObj.x = (-parentRect.width * ratioX) + cx + (sw * ratioX);&lt;br /&gt;     displayObj.y = (-parentRect.height * ratioY) + cy + (sh * ratioY);&lt;br /&gt;    }&lt;br /&gt;    displayObj.x -= movieX;&lt;br /&gt;    displayObj.y -= movieY;&lt;br /&gt;   }&lt;br /&gt;  }&lt;br /&gt; }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;若是將一開始的 StageAlign 設定為 StageAlign.TOP，將會看到只有 550x400 的有色背景會向中上對齊，然後物件對齊的基準若是以物件座標 PositionManager.BASE_POINT，則測試畫面如下：&lt;br /&gt;&lt;br /&gt;&lt;a target="_blank" onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_HsFEtLMw5zU/SJvrfVlrGOI/AAAAAAAAGJQ/B4mj4AQH_1g/s1600-h/Clipboard02.jpg"&gt;&lt;img style="cursor:pointer; cursor:hand;" src="http://2.bp.blogspot.com/_HsFEtLMw5zU/SJvrfVlrGOI/AAAAAAAAGJQ/B4mj4AQH_1g/s400/Clipboard02.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5232034315724593378" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;若是將一開始的 StageAlign 設定為 StageAlign.BOTTOM，將會看到只有 550x400 的有色背景會向中下對齊，然後物件對齊的基準若是以物件外框 PositionManager.BASE_BOARDER，則測試畫面如下：&lt;br /&gt;&lt;br /&gt;&lt;a target="_blank" onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_HsFEtLMw5zU/SJvrfRa6YpI/AAAAAAAAGJY/9wE770RDFZ0/s1600-h/Clipboard03.jpg"&gt;&lt;img style="cursor:pointer; cursor:hand;" src="http://1.bp.blogspot.com/_HsFEtLMw5zU/SJvrfRa6YpI/AAAAAAAAGJY/9wE770RDFZ0/s400/Clipboard03.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5232034314605716114" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;另外可以注意到，右下角的文字框，則是以固定距離的方式來對齊右下角頂點，不會因為 Stage 的大小改變，而有不同的距離比例變化，也就是 "實際距離" 與 "相對(於總寬度的)距離" 的不同啦～&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4754237190569973724-5800707137108260377?l=blog.ben.idv.tw' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.ben.idv.tw/feeds/5800707137108260377/comments/default' title='張貼意見'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4754237190569973724&amp;postID=5800707137108260377' title='9 個意見'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4754237190569973724/posts/default/5800707137108260377'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4754237190569973724/posts/default/5800707137108260377'/><link rel='alternate' type='text/html' href='http://blog.ben.idv.tw/2008/08/stage-resize.html' title='Stage RESIZE 時的物件座標'/><author><name>Ben Chang</name><uri>http://www.blogger.com/profile/01921640246111819069</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/_HsFEtLMw5zU/SJvrfDgLWLI/AAAAAAAAGJI/bXrEnqnEKq8/s72-c/Clipboard01.jpg' height='72' width='72'/><thr:total>9</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4754237190569973724.post-6881840025056035748</id><published>2008-07-30T16:12:00.000+08:00</published><updated>2011-08-02T16:16:45.500+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='flash.text.engine'/><category scheme='http://www.blogger.com/atom/ns#' term='Flash CS4'/><title type='text'>flash.text.engine 可載入 local 端的字型</title><content type='html'>Flash Player 10 允許我們動態載入 client 端的字型來顯示，就連中文字也可以作旋轉效果了！&lt;br /&gt;&lt;br /&gt;執行效果如下：&lt;br /&gt;&lt;br /&gt;&lt;a target="_blank" onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_HsFEtLMw5zU/SJAimQu4RyI/AAAAAAAAGH4/gCe87ZAOrgI/s1600-h/Clipboard01.jpg"&gt;&lt;img style="cursor:pointer; cursor:hand;" src="http://4.bp.blogspot.com/_HsFEtLMw5zU/SJAimQu4RyI/AAAAAAAAGH4/gCe87ZAOrgI/s400/Clipboard01.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5228717208099112738" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;a target="_blank" onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_HsFEtLMw5zU/SJAimS1Y4tI/AAAAAAAAGIA/GsfSxk3Rdd4/s1600-h/Clipboard02.jpg"&gt;&lt;img style="cursor:pointer; cursor:hand;" src="http://4.bp.blogspot.com/_HsFEtLMw5zU/SJAimS1Y4tI/AAAAAAAAGIA/GsfSxk3Rdd4/s400/Clipboard02.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5228717208663286482" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;a target="_blank" onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_HsFEtLMw5zU/SJAimlARmBI/AAAAAAAAGII/M2Oj5On6fPs/s1600-h/Clipboard03.jpg"&gt;&lt;img style="cursor:pointer; cursor:hand;" src="http://2.bp.blogspot.com/_HsFEtLMw5zU/SJAimlARmBI/AAAAAAAAGII/M2Oj5On6fPs/s400/Clipboard03.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5228717213540784146" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;a target="_blank" onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_HsFEtLMw5zU/SJAim1oznnI/AAAAAAAAGIQ/FPqaaKmXeO8/s1600-h/Clipboard04.jpg"&gt;&lt;img style="cursor:pointer; cursor:hand;" src="http://1.bp.blogspot.com/_HsFEtLMw5zU/SJAim1oznnI/AAAAAAAAGIQ/FPqaaKmXeO8/s400/Clipboard04.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5228717218005753458" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;輸出的 swf 檔案大小約 37.2 KB 左右，而下拉選單中的字型列表，是根據 client 端擁有的字型而定，沒有使用 embeded font：&lt;br /&gt;&lt;br /&gt;&lt;a target="_blank" onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_HsFEtLMw5zU/SJAinG8ADrI/AAAAAAAAGIY/qn1e8sJF_Qw/s1600-h/Clipboard05.jpg"&gt;&lt;img style="cursor:pointer; cursor:hand;" src="http://3.bp.blogspot.com/_HsFEtLMw5zU/SJAinG8ADrI/AAAAAAAAGIY/qn1e8sJF_Qw/s400/Clipboard05.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5228717222649663154" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;關於新的 flash.text.engine 的文件，可於官方查得：&lt;br /&gt;&lt;br /&gt;&lt;a target="_blank" href="http://livedocs.adobe.com/flex/gumbo/langref/flash/text/engine/package-detail.html"&gt;http://livedocs.adobe.com/flex/gumbo/langref/flash/text/engine/package-detail.html&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;我寫在 frame 1 的完整程式碼如下：&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;import fl.controls.Button;&lt;br /&gt;import fl.controls.ComboBox;&lt;br /&gt;import flash.text.engine.*;&lt;br /&gt;&lt;br /&gt;var rotate_btn:Button;&lt;br /&gt;var font_cb:ComboBox;&lt;br /&gt;var msg:String;&lt;br /&gt;var textContainer:Sprite;&lt;br /&gt;&lt;br /&gt;function init():void{&lt;br /&gt; font_cb = new ComboBox();&lt;br /&gt; var fonts:Array = Font.enumerateFonts(true);&lt;br /&gt; for(var i:int=0; i&amp;lt;fonts.length; i++){&lt;br /&gt;  font_cb.addItem({label:fonts[i].fontName});&lt;br /&gt; }&lt;br /&gt; font_cb.width = 200;&lt;br /&gt; font_cb.addEventListener(Event.CHANGE, fontChange);&lt;br /&gt; addChild(font_cb);&lt;br /&gt; &lt;br /&gt; rotate_btn = new Button();&lt;br /&gt; rotate_btn.label = "旋轉 / 停止";&lt;br /&gt; rotate_btn.width = 100;&lt;br /&gt; rotate_btn.x = font_cb.x + font_cb.width + 20;&lt;br /&gt; rotate_btn.addEventListener(MouseEvent.CLICK&lt;br /&gt;        , function(evt:MouseEvent):void{&lt;br /&gt;         if(hasEventListener(Event.ENTER_FRAME)){&lt;br /&gt;          removeEventListener(Event.ENTER_FRAME, onEnterFrameHandler);&lt;br /&gt;         }else{&lt;br /&gt;          addEventListener(Event.ENTER_FRAME, onEnterFrameHandler);&lt;br /&gt;         }&lt;br /&gt;         });&lt;br /&gt; addChild(rotate_btn);&lt;br /&gt; &lt;br /&gt; msg = "";&lt;br /&gt; for(var j:int=0; j&amp;lt;20; j++){&lt;br /&gt;  msg += "中文世界, ";&lt;br /&gt; }&lt;br /&gt; &lt;br /&gt; displayText(msg);&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;function fontChange(evt:Event):void{&lt;br /&gt; displayText(msg, font_cb.selectedItem.label);&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;function displayText(str:String = ""&lt;br /&gt;      , fontName:String = "_serif"&lt;br /&gt;      , fontSize:Number = 12.0&lt;br /&gt;      , fontColor:uint = 0x000000):void{&lt;br /&gt; if(textContainer!=null){&lt;br /&gt;  removeChild(textContainer);&lt;br /&gt; }&lt;br /&gt; textContainer = new Sprite();&lt;br /&gt;&lt;br /&gt; var fd:FontDescription = new FontDescription(fontName);&lt;br /&gt; var ef:ElementFormat = new ElementFormat(fd, fontSize, fontColor);&lt;br /&gt;&lt;br /&gt; var te:TextElement = new TextElement(str, ef);&lt;br /&gt; var tb:TextBlock = new TextBlock();&lt;br /&gt; tb.content = te;&lt;br /&gt;&lt;br /&gt; var lineWidth:Number = 250;&lt;br /&gt; var xPos:Number = 0;&lt;br /&gt; var yPos:Number = 0;&lt;br /&gt; &lt;br /&gt; var yMax:Number = 0;&lt;br /&gt; &lt;br /&gt; var line:TextLine = tb.createTextLine (null, lineWidth);&lt;br /&gt; while(line){&lt;br /&gt;  line.x = xPos;&lt;br /&gt;  line.y = yPos + line.textHeight;&lt;br /&gt;  &lt;br /&gt;  yPos += line.height + 5;&lt;br /&gt;  textContainer.addChild(line);&lt;br /&gt;&lt;br /&gt;  yMax = line.getBounds(textContainer).bottom;&lt;br /&gt;  &lt;br /&gt;  line = tb.createTextLine(line, lineWidth);&lt;br /&gt; }&lt;br /&gt; &lt;br /&gt; textContainer.graphics.lineStyle(0);&lt;br /&gt; textContainer.graphics.drawRect(0, 0, textContainer.width, yMax);&lt;br /&gt; &lt;br /&gt; textContainer.x = stage.stageWidth / 2;&lt;br /&gt; textContainer.y = stage.stageHeight / 2;&lt;br /&gt; &lt;br /&gt; addChild(textContainer);&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;function onEnterFrameHandler(evt:Event):void{&lt;br /&gt; if(textContainer!=null){&lt;br /&gt;  textContainer.rotation++;&lt;br /&gt;  //trace("rotation = " + textContainer.rotation);&lt;br /&gt; }&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;init();&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;至於輸出時，好像選擇 Flash Player 10 或 Flash Player 10 (flash.text.engine API) 都可以：&lt;br /&gt;&lt;br /&gt;&lt;a target="_blank" onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_HsFEtLMw5zU/SJAj7HnE8aI/AAAAAAAAGIg/_MNIAiYCfb8/s1600-h/Clipboard06.jpg"&gt;&lt;img style="cursor:pointer; cursor:hand;" src="http://3.bp.blogspot.com/_HsFEtLMw5zU/SJAj7HnE8aI/AAAAAAAAGIg/_MNIAiYCfb8/s400/Clipboard06.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5228718665939349922" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;瀏覽效果(記得先安裝 Flash Player 10)：&lt;br /&gt;&lt;a target="_blank" href="http://ben.rb.chang.googlepages.com/20080730_flash_player10_local_font.html"&gt;http://ben.rb.chang.googlepages.com/20080730_flash_player10_local_font.html&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4754237190569973724-6881840025056035748?l=blog.ben.idv.tw' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.ben.idv.tw/feeds/6881840025056035748/comments/default' title='張貼意見'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4754237190569973724&amp;postID=6881840025056035748' title='2 個意見'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4754237190569973724/posts/default/6881840025056035748'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4754237190569973724/posts/default/6881840025056035748'/><link rel='alternate' type='text/html' href='http://blog.ben.idv.tw/2008/07/flashtextengine-local.html' title='flash.text.engine 可載入 local 端的字型'/><author><name>Ben Chang</name><uri>http://www.blogger.com/profile/01921640246111819069</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_HsFEtLMw5zU/SJAimQu4RyI/AAAAAAAAGH4/gCe87ZAOrgI/s72-c/Clipboard01.jpg' height='72' width='72'/><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4754237190569973724.post-172076084114409380</id><published>2008-07-21T08:49:00.001+08:00</published><updated>2008-11-13T12:34:51.511+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Flex'/><title type='text'>Hands-On With the Voodoo Envy's Instant-On OS</title><content type='html'>Ticore，這是你們家的產品嗎：&lt;br /&gt;&lt;br /&gt;&lt;a target="_blank" href="http://blog.laptopmag.com/first-impressions-of-the-voodoo-envys-ios"&gt;http://blog.laptopmag.com/first-impressions-of-the-voodoo-envys-ios&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;我看到 Flex 了：&lt;br /&gt;&lt;br /&gt;&lt;a target="_blank" onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_HsFEtLMw5zU/SIPdSjFAoiI/AAAAAAAAGHw/oceYdb8yRnU/s1600-h/Clipboard01.jpg"&gt;&lt;img style="cursor:pointer; cursor:hand;" src="http://4.bp.blogspot.com/_HsFEtLMw5zU/SIPdSjFAoiI/AAAAAAAAGHw/oceYdb8yRnU/s400/Clipboard01.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5225263303403545122" /&gt;&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4754237190569973724-172076084114409380?l=blog.ben.idv.tw' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.ben.idv.tw/feeds/172076084114409380/comments/default' title='張貼意見'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4754237190569973724&amp;postID=172076084114409380' title='0 個意見'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4754237190569973724/posts/default/172076084114409380'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4754237190569973724/posts/default/172076084114409380'/><link rel='alternate' type='text/html' href='http://blog.ben.idv.tw/2008/07/hands-on-with-voodoo-envys-instant-on.html' title='Hands-On With the Voodoo Envy&apos;s Instant-On OS'/><author><name>Ben Chang</name><uri>http://www.blogger.com/profile/01921640246111819069</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_HsFEtLMw5zU/SIPdSjFAoiI/AAAAAAAAGHw/oceYdb8yRnU/s72-c/Clipboard01.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4754237190569973724.post-1586547248757955462</id><published>2008-07-16T10:59:00.001+08:00</published><updated>2008-07-16T11:03:00.755+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='AS3'/><title type='text'>unloadAndStop()</title><content type='html'>moock 貼了一篇文章，說明當我們要卸載一個 MC 時，要注意釋放哪些資源，或是停下哪些正在進行的作業：&lt;br /&gt;&lt;br /&gt;&lt;a target="_blank" href="http://www.moock.org/blog/archives/000279.html"&gt;http://www.moock.org/blog/archives/000279.html&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;包含了：&lt;br /&gt;&lt;br /&gt;Tell any loaded .swf child assets to disable themselves. &lt;br /&gt;Stop any sounds from playing. &lt;br /&gt;Stop the main timeline, if it is currently playing. &lt;br /&gt;Stop any movie clips that are currently playing. &lt;br /&gt;Close any connected network objects, such as instances of Loader, URLLoader, Socket, XMLSocket, LocalConnection, NetConnections, and NetStream. &lt;br /&gt;Release all references to cameras and microphones. &lt;br /&gt;Unregister all event listeners in the .swf (particularly Event.ENTER_FRAME, and mouse and keyboard listeners) &lt;br /&gt;Stop any currently running intervals (via clearInterval()). &lt;br /&gt;Stop any Timer objects (via the Timer class’s instance method stop()). &lt;br /&gt;&lt;br /&gt;未來，將會有 Loader.unloadAndStop() 可以幫我們做掉以上的事情：&lt;br /&gt;&lt;br /&gt;&lt;a target="_blank" href="http://www.gskinner.com/blog/archives/2008/07/additional_info.html"&gt;http://www.gskinner.com/blog/archives/2008/07/additional_info.html&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4754237190569973724-1586547248757955462?l=blog.ben.idv.tw' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.ben.idv.tw/feeds/1586547248757955462/comments/default' title='張貼意見'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4754237190569973724&amp;postID=1586547248757955462' title='0 個意見'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4754237190569973724/posts/default/1586547248757955462'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4754237190569973724/posts/default/1586547248757955462'/><link rel='alternate' type='text/html' href='http://blog.ben.idv.tw/2008/07/unloadandstop.html' title='unloadAndStop()'/><author><name>Ben Chang</name><uri>http://www.blogger.com/profile/01921640246111819069</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4754237190569973724.post-8226193252579384723</id><published>2008-07-16T10:42:00.006+08:00</published><updated>2008-07-16T10:56:32.651+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='AS3'/><title type='text'>The Charges Against ActionScript 3.0</title><content type='html'>Colin Moock 寫了一篇文章：&lt;br /&gt;&lt;a target="_blank" href="http://www.insideria.com/2008/07/the-charges-against-actionscri.html"&gt;http://www.insideria.com/2008/07/the-charges-against-actionscri.html&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;針對一些升級到 Flash CS3 時，一些小小的不便 (多個"小小的不便"，加起來就成為"大大的不便")，在 Flash CS3 時要如何對應，但又建議 Adobe 應該在下一版時可以如何改進，或是建議如何針對各位 Flasher 的習慣來設計開發工具的介面。也建議 Flasher 們，可以上官方的 wish list 去張貼自己對下一版的期待。&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4754237190569973724-8226193252579384723?l=blog.ben.idv.tw' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.ben.idv.tw/feeds/8226193252579384723/comments/default' title='張貼意見'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4754237190569973724&amp;postID=8226193252579384723' title='0 個意見'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4754237190569973724/posts/default/8226193252579384723'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4754237190569973724/posts/default/8226193252579384723'/><link rel='alternate' type='text/html' href='http://blog.ben.idv.tw/2008/07/charges-against-actionscript-30.html' title='The Charges Against ActionScript 3.0'/><author><name>Ben Chang</name><uri>http://www.blogger.com/profile/01921640246111819069</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4754237190569973724.post-6979545691618674170</id><published>2008-07-15T11:50:00.003+08:00</published><updated>2008-11-13T12:34:51.635+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Game'/><title type='text'>圍棋題庫</title><content type='html'>基於網友提出的疑問：&lt;br /&gt;&lt;br /&gt;&lt;a target="_blank" href="http://blog.ben.idv.tw/2007/06/papervision3d-part-72.html?showComment=1216084860000#c3959481488832795458"&gt;http://blog.ben.idv.tw/2007/06/papervision3d-part-72.html?showComment=1216084860000#c3959481488832795458&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;若是要製作一個圍棋的題庫的話，這支 flash 的基本架構與程式大致如下：&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;首先，準備一個主程式 main.fla，其中 frame 1 的 actionscript 如下：&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;var loader:URLLoader = new URLLoader();&lt;br /&gt;loader.addEventListener(Event.COMPLETE, function(evt:Event):void{&lt;br /&gt; var target:URLLoader = evt.target as URLLoader;&lt;br /&gt; var xml:XML = new XML(target.data);&lt;br /&gt; paint(xml);&lt;br /&gt;})&lt;br /&gt;loader.load(new URLRequest("chess.xml"));&lt;br /&gt;&lt;br /&gt;function paint(chessXML:XML):void{&lt;br /&gt; var sprite:Sprite = new Sprite();&lt;br /&gt;&lt;br /&gt; var g:Graphics = sprite.graphics;&lt;br /&gt; g.lineStyle(0);&lt;br /&gt; &lt;br /&gt; var ary:Array = chessXML.text().split("\r").join("").split("\n")&lt;br /&gt; for(var i:int=0; i&amp;lt;ary.length; i++){&lt;br /&gt;  //橫線&lt;br /&gt;  g.moveTo(0, 20 * i);&lt;br /&gt;  g.lineTo(20 * (ary.length-1), 20 * i);&lt;br /&gt;  &lt;br /&gt;  //直線&lt;br /&gt;  g.moveTo(20 * i, 0);&lt;br /&gt;  g.lineTo(20 * i, 20 * (ary.length-1));&lt;br /&gt; }&lt;br /&gt; &lt;br /&gt; for(var i:int=0; i&amp;lt;ary.length; i++){&lt;br /&gt;  var line:String = ary[i];&lt;br /&gt;  for(var j:int=0; j&amp;lt;line.length; j++){&lt;br /&gt;   var chess:String = line.charAt(j);&lt;br /&gt;   if(chess=="0" || chess=="y"){&lt;br /&gt;    var chessSprite:ChessSprite = new ChessSprite(chess);&lt;br /&gt;    chessSprite.graphics.beginFill(0xffffff, 0.2);&lt;br /&gt;    chessSprite.graphics.drawCircle(0, 0, 5);&lt;br /&gt;    chessSprite.graphics.endFill();&lt;br /&gt;    chessSprite.x = 20 * j;&lt;br /&gt;    chessSprite.y = 20 * i;&lt;br /&gt;    chessSprite.addEventListener(MouseEvent.CLICK, function(evt:MouseEvent):void{&lt;br /&gt;                 if((evt.target as ChessSprite).value=="y"){&lt;br /&gt;                  trace("正確");&lt;br /&gt;                 }else{&lt;br /&gt;                  trace("錯誤");&lt;br /&gt;                 }&lt;br /&gt;                });&lt;br /&gt;    sprite.addChild(chessSprite);&lt;br /&gt;   }&lt;br /&gt;   if(chess=="1"){&lt;br /&gt;    g.beginFill(0x000000);&lt;br /&gt;    g.drawCircle(20 * j, 20 * i, 5);&lt;br /&gt;    g.endFill();&lt;br /&gt;   }&lt;br /&gt;   if(chess=="2"){&lt;br /&gt;    g.beginFill(0xffffff);&lt;br /&gt;    g.drawCircle(20 * j, 20 * i, 5);&lt;br /&gt;    g.endFill();&lt;br /&gt;   }&lt;br /&gt;  }&lt;br /&gt; }&lt;br /&gt; &lt;br /&gt; addChild(sprite);&lt;br /&gt; sprite.x = (stage.stageWidth - sprite.width)/2;&lt;br /&gt; sprite.y = (stage.stageHeight - sprite.height)/2;&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;這個 fla 會載入外部 chess.xml，取得棋子的擺放方法，若是 0 表示一般錯誤(較差)的位置，1 與 2 表示已下的棋子，y 表示正確的下一步，程式會為 0 與 y 放上可點選的透明棋子，若是點下去發現是 y，則表示正確，反之則錯誤。&lt;br /&gt;&lt;br /&gt;chess.xml：&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&amp;lt;c&amp;gt;&lt;br /&gt;0000200000000000000&lt;br /&gt;00021y0000000000000&lt;br /&gt;0002120000000000000&lt;br /&gt;0000200000000000000&lt;br /&gt;0000000000000000000&lt;br /&gt;0000000000000000000&lt;br /&gt;0000000000000000000&lt;br /&gt;0000000000000000000&lt;br /&gt;0000000000000000000&lt;br /&gt;0000000000000000000&lt;br /&gt;0000000000000000000&lt;br /&gt;0000000000000000000&lt;br /&gt;0000000000000000000&lt;br /&gt;0000000000000000000&lt;br /&gt;0000000000000000000&lt;br /&gt;0000000000000000000&lt;br /&gt;0000000000000000000&lt;br /&gt;0000000000000000000&lt;br /&gt;0000000000000000000&lt;br /&gt;&amp;lt;/c&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;為了要在 Sprite 中，儲存一些額外的資訊 ("0" 或 "y")，所以我另外新建一個繼承自 Sprite 的 ChessSprite 類別，可夾帶自訂變數，這個 ChessSprite.as 就放在與 fla 相同目錄下即可：&lt;br /&gt; &lt;br /&gt;&lt;pre&gt;&lt;br /&gt;package{&lt;br /&gt; import flash.display.Sprite;&lt;br /&gt; public class ChessSprite extends Sprite{&lt;br /&gt;  private var __value:String;&lt;br /&gt;  function ChessSprite(v:String){&lt;br /&gt;   this.__value = v;&lt;br /&gt;  }&lt;br /&gt;  public function get value():String{&lt;br /&gt;   return __value;&lt;br /&gt;  }&lt;br /&gt; }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;執行畫面如下，點選正確與否，會 trace 在 output 視窗中：&lt;br /&gt;&lt;br /&gt;&lt;a target="_blank" onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_HsFEtLMw5zU/SHwyFRzY5EI/AAAAAAAAGGo/xlqZV9Mm2qM/s1600-h/Clipboard01.jpg"&gt;&lt;img style="cursor:pointer; cursor:hand;" src="http://4.bp.blogspot.com/_HsFEtLMw5zU/SHwyFRzY5EI/AAAAAAAAGGo/xlqZV9Mm2qM/s400/Clipboard01.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5223104734102611010" /&gt;&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4754237190569973724-6979545691618674170?l=blog.ben.idv.tw' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.ben.idv.tw/feeds/6979545691618674170/comments/default' title='張貼意見'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4754237190569973724&amp;postID=6979545691618674170' title='0 個意見'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4754237190569973724/posts/default/6979545691618674170'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4754237190569973724/posts/default/6979545691618674170'/><link rel='alternate' type='text/html' href='http://blog.ben.idv.tw/2008/07/blog-post_15.html' title='圍棋題庫'/><author><name>Ben Chang</name><uri>http://www.blogger.com/profile/01921640246111819069</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_HsFEtLMw5zU/SHwyFRzY5EI/AAAAAAAAGGo/xlqZV9Mm2qM/s72-c/Clipboard01.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4754237190569973724.post-5544359948380809673</id><published>2008-07-07T15:40:00.005+08:00</published><updated>2011-08-02T16:11:46.105+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='PV3D'/><title type='text'>黑白棋，加入電腦玩家</title><content type='html'>之前寫過 黑白棋 的遊戲：&lt;br /&gt;&lt;a target="_blank" href="http://blog.ben.idv.tw/2007/06/papervision3d-part-72.html"&gt;http://blog.ben.idv.tw/2007/06/papervision3d-part-72.html&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;不過之前沒有將 電腦玩家 寫進去，這次我將之前寫給 flex 的 *.as 檔拿來改一改，給 flash cs3 當作 document class 使用。&lt;br /&gt;&lt;br /&gt;Reversi.as 原始檔如下：&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;package  {&lt;br /&gt; import flash.display.*;&lt;br /&gt; import flash.events.*;&lt;br /&gt; import flash.ui.*;&lt;br /&gt; import flash.utils.*;&lt;br /&gt; &lt;br /&gt; import org.papervision3d.cameras.*;&lt;br /&gt; import org.papervision3d.scenes.*;&lt;br /&gt; import org.papervision3d.objects.*;&lt;br /&gt; import org.papervision3d.materials.*;&lt;br /&gt; &lt;br /&gt; public class Reversi extends MovieClip {&lt;br /&gt;  &lt;br /&gt;  // Constants:&lt;br /&gt;  private static var TH:Number = Math.PI / 180;&lt;br /&gt;  &lt;br /&gt;  // Public Properties:&lt;br /&gt;  // Private Properties:&lt;br /&gt;  private var container:Sprite;&lt;br /&gt;  private var scene:Scene3D;&lt;br /&gt;  private var camera:Camera3D;&lt;br /&gt;  &lt;br /&gt;  //camera 繞著y軸線旋轉的角度&lt;br /&gt;  private var du:Number = -90;&lt;br /&gt;  &lt;br /&gt;  //camera 距離y軸線的半徑&lt;br /&gt;  private var movingRadius:int = 1000;&lt;br /&gt;  &lt;br /&gt;  //camera 的高度&lt;br /&gt;  private var movingHeight:int = 3000;&lt;br /&gt;  &lt;br /&gt;  //棋子材質寬高&lt;br /&gt;  private var chess_material_width:int = 40;&lt;br /&gt;  private var chess_material_height:int = 40;&lt;br /&gt;  &lt;br /&gt;  //棋子間距&lt;br /&gt;  private var chess_offset_h:int = 5;&lt;br /&gt;  private var chess_offset_v:int = 5;&lt;br /&gt;  &lt;br /&gt;  //棋子離地高度&lt;br /&gt;  private var chess_pos_y:int = 5;&lt;br /&gt;  &lt;br /&gt;  //地板資訊&lt;br /&gt;  private var groundSpriteData:Object = {};&lt;br /&gt;&lt;br /&gt;  //棋位&lt;br /&gt;  private var gameData:Array = [&lt;br /&gt;   [-1, -1, -1, -1, -1, -1, -1, -1],&lt;br /&gt;   [-1, -1, -1, -1, -1, -1, -1, -1],&lt;br /&gt;   [-1, -1, -1, -1, -1, -1, -1, -1],&lt;br /&gt;   [-1, -1, -1,  1,  0, -1, -1, -1],&lt;br /&gt;   [-1, -1, -1,  0,  1, -1, -1, -1],&lt;br /&gt;   [-1, -1, -1, -1, -1, -1, -1, -1],&lt;br /&gt;   [-1, -1, -1, -1, -1, -1, -1, -1],&lt;br /&gt;   [-1, -1, -1, -1, -1, -1, -1, -1]&lt;br /&gt;  ];&lt;br /&gt;  &lt;br /&gt;  //兩家雙方可點的位置&lt;br /&gt;  private var allowClickData:Array = [&lt;br /&gt;   [&lt;br /&gt;   [0, 0, 0, 0, 0, 0, 0, 0],&lt;br /&gt;   [0, 0, 0, 0, 0, 0, 0, 0],&lt;br /&gt;   [0, 0, 0, 0, 0, 0, 0, 0],&lt;br /&gt;   [0, 0, 0, 0, 0, 0, 0, 0],&lt;br /&gt;   [0, 0, 0, 0, 0, 0, 0, 0],&lt;br /&gt;   [0, 0, 0, 0, 0, 0, 0, 0],&lt;br /&gt;   [0, 0, 0, 0, 0, 0, 0, 0],&lt;br /&gt;   [0, 0, 0, 0, 0, 0, 0, 0]&lt;br /&gt;   ],&lt;br /&gt;   [&lt;br /&gt;   [0, 0, 0, 0, 0, 0, 0, 0],&lt;br /&gt;   [0, 0, 0, 0, 0, 0, 0, 0],&lt;br /&gt;   [0, 0, 0, 0, 0, 0, 0, 0],&lt;br /&gt;   [0, 0, 0, 0, 0, 0, 0, 0],&lt;br /&gt;   [0, 0, 0, 0, 0, 0, 0, 0],&lt;br /&gt;   [0, 0, 0, 0, 0, 0, 0, 0],&lt;br /&gt;   [0, 0, 0, 0, 0, 0, 0, 0],&lt;br /&gt;   [0, 0, 0, 0, 0, 0, 0, 0]&lt;br /&gt;   ]&lt;br /&gt;  ];&lt;br /&gt;  &lt;br /&gt;  //換誰&lt;br /&gt;  private var whoTurn:int = 0; //0=黑：玩家先攻, 1=白：電腦後攻&lt;br /&gt;  &lt;br /&gt;  //使用金牌&lt;br /&gt;  private var isUsingGoldCard:Boolean = false;&lt;br /&gt; &lt;br /&gt;  // Initialization:&lt;br /&gt;  public function Reversi(chess_material_width:int = 49&lt;br /&gt;        , chess_material_height:int = 42&lt;br /&gt;        , chess_offset_h:int = 5&lt;br /&gt;        , chess_offset_v:int = 5&lt;br /&gt;        , chess_pos_y: int = 5) {&lt;br /&gt;   this.chess_material_width = chess_material_width;&lt;br /&gt;   this.chess_material_height = chess_material_height;&lt;br /&gt;   &lt;br /&gt;   this.chess_offset_h = chess_offset_h;&lt;br /&gt;   this.chess_offset_v = chess_offset_v;&lt;br /&gt;   &lt;br /&gt;   this.chess_pos_y = chess_pos_y;&lt;br /&gt;   &lt;br /&gt;   this.addEventListener(Event.ADDED_TO_STAGE, addToStageHandler);&lt;br /&gt;  }&lt;br /&gt;  &lt;br /&gt;  private function addToStageHandler(evt:Event):void{&lt;br /&gt;   init3D();&lt;br /&gt;   this.addEventListener(Event.ENTER_FRAME, loop3D);&lt;br /&gt;&lt;br /&gt;   //stage.addEventListener(KeyboardEvent.KEY_UP, keyUpHandler);&lt;br /&gt;   stage.addEventListener(KeyboardEvent.KEY_DOWN, keyDownHandler);&lt;br /&gt;  }&lt;br /&gt;  &lt;br /&gt;  // Public Methods:&lt;br /&gt;  // Protected Methods:&lt;br /&gt;  private function init3D():void{&lt;br /&gt;   container = new Sprite();&lt;br /&gt;   this.addChild(container);&lt;br /&gt;   container.x = stage.stageWidth/2;&lt;br /&gt;   container.y = stage.stageHeight/2;&lt;br /&gt;   &lt;br /&gt;   scene = new MovieScene3D(container);&lt;br /&gt;   &lt;br /&gt;   camera = new Camera3D();&lt;br /&gt;   camera.zoom = 30;&lt;br /&gt;   camera.focus = 100;&lt;br /&gt;   camera.x = movingRadius * Math.cos(du*TH);&lt;br /&gt;   camera.y = movingHeight;&lt;br /&gt;   camera.z = movingRadius * Math.sin(du*TH);&lt;br /&gt;   &lt;br /&gt;   //地板&amp;棋子&lt;br /&gt;   var material:ColorMaterial = new ColorMaterial(0x999999);&lt;br /&gt;   for(var i:int=0; i&amp;lt;gameData.length; i++){&lt;br /&gt;    for(var j:int=0; j&amp;lt;gameData[i].length; j++){&lt;br /&gt;     //去除預先擺上的棋子外，建立其他地板&lt;br /&gt;     if(gameData[i][j]==-1){&lt;br /&gt;      var ground:DisplayObject3D = scene.addChild(new Plane(material, chess_material_width, chess_material_height, 1, 1), "ground"+i+j);&lt;br /&gt;      ground.x = (j-3.5) * (chess_material_width+chess_offset_h);&lt;br /&gt;      ground.z = (3.5-i) * (chess_material_height+chess_offset_v);&lt;br /&gt;      ground.y = 1;&lt;br /&gt;      ground.rotationX = -90;&lt;br /&gt;     }else{&lt;br /&gt;      //棋子&lt;br /&gt;      addChess(i, j, gameData[i][j]);&lt;br /&gt;     }&lt;br /&gt;    }&lt;br /&gt;   }&lt;br /&gt;   &lt;br /&gt;   //先繪製出來，才能決定container的sprite，才能addEventListener&lt;br /&gt;   scene.renderCamera(camera);&lt;br /&gt;   &lt;br /&gt;   //地板，設定滑鼠事件&lt;br /&gt;   for(var i:int=0; i&amp;lt;gameData.length; i++){&lt;br /&gt;    for(var j:int=0; j&amp;lt;gameData[i].length; j++){&lt;br /&gt;     var ground:DisplayObject3D = scene.getChildByName("ground"+i+j);&lt;br /&gt;     if(ground!=null){&lt;br /&gt;      ground.container.name = "ground"+i+j;&lt;br /&gt;      ground.container.visible = false; //一開始全部不顯示&lt;br /&gt;      ground.container.alpha = 0.6;&lt;br /&gt;      ground.container.buttonMode = true;&lt;br /&gt;      ground.container.addEventListener(MouseEvent.CLICK, ground_onClick);&lt;br /&gt;      &lt;br /&gt;      groundSpriteData[ground.container.name] = {i:i, j:j};&lt;br /&gt;     }&lt;br /&gt;    }&lt;br /&gt;   }&lt;br /&gt;   &lt;br /&gt;   //計算可以點選的地板&lt;br /&gt;   countAllowClicks();&lt;br /&gt;   &lt;br /&gt;   //顯示可以點選的地板&lt;br /&gt;   displayAllowClicks();&lt;br /&gt;  }&lt;br /&gt;  &lt;br /&gt;  private function loop3D(evt:Event):void{&lt;br /&gt;   scene.renderCamera(camera);&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  private function countAllowClicks():void{&lt;br /&gt;   countAllowClick(0);&lt;br /&gt;   countAllowClick(1);&lt;br /&gt;   &lt;br /&gt;   //將現在輪到的玩家的權數表印出來參考&lt;br /&gt;   //dumpArray(allowClickData[whoTurn]);&lt;br /&gt;  }&lt;br /&gt;  &lt;br /&gt;  private function displayAllowClicks():void{&lt;br /&gt;   for(var i:int=0; i&amp;lt;gameData.length; i++){&lt;br /&gt;    for(var j:int=0; j&amp;lt;gameData[i].length; j++){&lt;br /&gt;     var ground:DisplayObject3D = scene.getChildByName("ground"+i+j);&lt;br /&gt;     if(ground){&lt;br /&gt;      if(whoTurn==0){&lt;br /&gt;       //玩家&lt;br /&gt;       if(isUsingGoldCard){&lt;br /&gt;        ground.container.visible = false;&lt;br /&gt;       }else{&lt;br /&gt;        if(allowClickData[whoTurn][i][j]&amp;gt;0){&lt;br /&gt;         ground.container.visible = true;&lt;br /&gt;        }else{&lt;br /&gt;         ground.container.visible = false;&lt;br /&gt;        }&lt;br /&gt;       }&lt;br /&gt;      }else{&lt;br /&gt;       //電腦，不顯示地板&lt;br /&gt;       ground.container.visible = false;&lt;br /&gt;      }&lt;br /&gt;     }&lt;br /&gt;     &lt;br /&gt;     //使用金牌，找出電腦下過的地方，可以被點&lt;br /&gt;     if(isUsingGoldCard &amp;&amp; gameData[i][j]==1){&lt;br /&gt;      var chess:DisplayObject3D = scene.getChildByName("chess"+i+j);&lt;br /&gt;      chess.container.name = "ground"+i+j;&lt;br /&gt;      chess.container.buttonMode = true;&lt;br /&gt;      chess.container.addEventListener(MouseEvent.CLICK, chess_onClick);&lt;br /&gt;     }&lt;br /&gt;    }&lt;br /&gt;   }&lt;br /&gt;  }&lt;br /&gt;  &lt;br /&gt;  private function countAllowClick(whoTurn:int):void{&lt;br /&gt;   var another:int = whoTurn==0?1:0;//對手&lt;br /&gt;   &lt;br /&gt;   for(var i:int=0; i&amp;lt;gameData.length; i++){&lt;br /&gt;    for(var j:int=0; j&amp;lt;gameData[i].length; j++){&lt;br /&gt;     if(gameData[i][j]==-1){&lt;br /&gt;      var canKillChess:Array = getKillChess(whoTurn, i, j);&lt;br /&gt;      if(canKillChess.length!=0){&lt;br /&gt;       //自訂該位置的點選權數&lt;br /&gt;       &lt;br /&gt;       //以可以殺多少對手，當作權數&lt;br /&gt;       allowClickData[whoTurn][i][j] = canKillChess.length;&lt;br /&gt;       &lt;br /&gt;       if((i==0&amp;&amp;j==0)&lt;br /&gt;          ||(i==0&amp;&amp;j==7)&lt;br /&gt;          ||(i==7&amp;&amp;j==0)&lt;br /&gt;          ||(i==7&amp;&amp;j==7)){&lt;br /&gt;        //若是該點是四個角，則權數+24&lt;br /&gt;        allowClickData[whoTurn][i][j] += 24;&lt;br /&gt;       }else if(i==0 || i==7 || j==0 || j==7){&lt;br /&gt;        //若是該點是四邊，則權數+12&lt;br /&gt;        allowClickData[whoTurn][i][j] += 12;&lt;br /&gt;       }&lt;br /&gt;       &lt;br /&gt;       //若是該點正巧也是對手可以點的，則權數 + "對手殺我方的個數"&lt;br /&gt;       //意味著，會使我方損傷越多的，越要先擋&lt;br /&gt;       if(allowClickData[another][i][j]&amp;gt;0){&lt;br /&gt;        allowClickData[whoTurn][i][j] += allowClickData[another][i][j]&lt;br /&gt;       }&lt;br /&gt;      }else{&lt;br /&gt;       allowClickData[whoTurn][i][j] = 0; //沒對手可殺，不能點&lt;br /&gt;      }&lt;br /&gt;     }else{&lt;br /&gt;      allowClickData[whoTurn][i][j] = -1; //有棋子，不能點&lt;br /&gt;     }&lt;br /&gt;    }&lt;br /&gt;   }&lt;br /&gt;   //dumpArray(allowClickData[whoTurn]);&lt;br /&gt;  }&lt;br /&gt;  &lt;br /&gt;  private function ground_onClick(event:MouseEvent):void{&lt;br /&gt;   var ci:int = groundSpriteData[event.target.name].i;&lt;br /&gt;   var cj:int = groundSpriteData[event.target.name].j;&lt;br /&gt;   &lt;br /&gt;   select(ci, cj);&lt;br /&gt;  }&lt;br /&gt;  &lt;br /&gt;  private function chess_onClick(event:MouseEvent):void{&lt;br /&gt;   var ci:int = groundSpriteData[event.target.name].i;&lt;br /&gt;   var cj:int = groundSpriteData[event.target.name].j;&lt;br /&gt;&lt;br /&gt;   //將每個電腦下過的位置，解除按鈕事件&lt;br /&gt;   for(var i:int=0; i&amp;lt;gameData.length; i++){&lt;br /&gt;    for(var j:int=0; j&amp;lt;gameData[i].length; j++){&lt;br /&gt;     if(gameData[i][j]==1){&lt;br /&gt;      var chess:DisplayObject3D = scene.getChildByName("chess"+i+j);&lt;br /&gt;      chess.container.name = "";&lt;br /&gt;      chess.container.buttonMode = false;&lt;br /&gt;      chess.container.removeEventListener(MouseEvent.CLICK, chess_onClick);&lt;br /&gt;     }&lt;br /&gt;    }&lt;br /&gt;   }&lt;br /&gt;   &lt;br /&gt;   select(ci, cj);&lt;br /&gt;   &lt;br /&gt;   isUsingGoldCard = false;&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  private function chessAnimation(ci:int, cj:int, whoTurn:int):void{&lt;br /&gt;   var timer:Timer = new Timer(0, 200);&lt;br /&gt;   timer.addEventListener(TimerEvent.TIMER, function(evt:TimerEvent):void{&lt;br /&gt;              var timer:Timer = evt.target as Timer;&lt;br /&gt;              var chess:DisplayObject3D = scene.getChildByName("chess"+ci+cj);&lt;br /&gt;              //轉棋面效果&lt;br /&gt;              if(whoTurn==0){&lt;br /&gt;               //黑&lt;br /&gt;               chess.rotationZ -= 20;&lt;br /&gt;               if(chess.rotationZ&amp;lt;=0){&lt;br /&gt;                chess.rotationZ = 0;&lt;br /&gt;                timer.stop();&lt;br /&gt;                timer = null;&lt;br /&gt;               }&lt;br /&gt;              }else if(whoTurn==1){&lt;br /&gt;               //白&lt;br /&gt;               chess.rotationZ += 20;&lt;br /&gt;               if(chess.rotationZ&amp;gt;=180){&lt;br /&gt;                chess.rotationZ = 180;&lt;br /&gt;                timer.stop();&lt;br /&gt;                timer = null;&lt;br /&gt;               }&lt;br /&gt;              }&lt;br /&gt;             });&lt;br /&gt;   timer.start();&lt;br /&gt;  }&lt;br /&gt;  &lt;br /&gt;  private function addChess(ci:int, cj:int, whoTurn:int):DisplayObject3D{&lt;br /&gt;   var material0:BitmapAssetMaterial = new BitmapAssetMaterial("PlayerImg0");&lt;br /&gt;   var material1:BitmapAssetMaterial = new BitmapAssetMaterial("PlayerImg1");&lt;br /&gt;    &lt;br /&gt;   var chess:DisplayObject3D = scene.addChild(new DisplayObject3D(), "chess"+ci+cj);&lt;br /&gt;   chess.addChild(new Plane(material0, chess_material_width, chess_material_height, 8, 8, {y:2, rotationX:-90}));&lt;br /&gt;   chess.addChild(new Plane(material1, chess_material_width, chess_material_height, 8, 8, {y:1, rotationX:-90, rotationZ:180}));&lt;br /&gt;   chess.x = (cj-3.5) * (chess_material_width+chess_offset_h);&lt;br /&gt;   chess.z = (3.5-ci) * (chess_material_height+chess_offset_v);&lt;br /&gt;   chess.y = chess_pos_y;&lt;br /&gt;    &lt;br /&gt;   //轉棋面效果&lt;br /&gt;   if(whoTurn==0){&lt;br /&gt;    //黑&lt;br /&gt;    chess.rotationZ = 0;&lt;br /&gt;   }else if(whoTurn==1){&lt;br /&gt;    //白&lt;br /&gt;    chess.rotationZ = 180;&lt;br /&gt;   }&lt;br /&gt;   &lt;br /&gt;   return chess;&lt;br /&gt;  }&lt;br /&gt;  &lt;br /&gt;  private function select(ci:int, cj:int):void{&lt;br /&gt;   //改變此座標&lt;br /&gt;   gameData[ci][cj] = whoTurn;&lt;br /&gt;   &lt;br /&gt;   //若是地板還沒刪除&lt;br /&gt;   var ground:DisplayObject3D = scene.getChildByName("ground"+ci+cj);&lt;br /&gt;   if(ground!=null){&lt;br /&gt;    scene.removeChild(ground);&lt;br /&gt;   }&lt;br /&gt;   &lt;br /&gt;   //若是棋子還沒生出來&lt;br /&gt;   var chess:DisplayObject3D = scene.getChildByName("chess"+ci+cj);&lt;br /&gt;   if(chess==null){&lt;br /&gt;    chess = addChess(ci, cj, whoTurn);&lt;br /&gt;   }else{&lt;br /&gt;    //動畫&lt;br /&gt;    chessAnimation(ci, cj, whoTurn);&lt;br /&gt;   }&lt;br /&gt;   &lt;br /&gt;   //改變所有會被換掉的座標&lt;br /&gt;   var ary:Array = getKillChess(whoTurn, ci, cj);&lt;br /&gt;   &lt;br /&gt;   var timer:Timer = new Timer(150);&lt;br /&gt;   timer.addEventListener(TimerEvent.TIMER&lt;br /&gt;           , function(evt:TimerEvent):void{&lt;br /&gt;          if(ary.length&amp;gt;0){&lt;br /&gt;           var k:Array = ary.splice(0, 1);&lt;br /&gt;               &lt;br /&gt;           //改變座標&lt;br /&gt;           gameData[k[0].i][k[0].j] = whoTurn;&lt;br /&gt;               &lt;br /&gt;           //動畫&lt;br /&gt;           chessAnimation(k[0].i, k[0].j, whoTurn);&lt;br /&gt;          }else{&lt;br /&gt;           (evt.target as Timer).stop();&lt;br /&gt;               &lt;br /&gt;           //換手&lt;br /&gt;           whoTurn = whoTurn==0?1:0;&lt;br /&gt;               &lt;br /&gt;           //計算可以點選的地板&lt;br /&gt;           countAllowClicks();&lt;br /&gt;   &lt;br /&gt;           //顯示可以點選的地板&lt;br /&gt;           displayAllowClicks();&lt;br /&gt;               &lt;br /&gt;           //為接下來的玩家找出最適合的攻擊點&lt;br /&gt;           var nextBestPoint:Object = choiseBestAttPoint();&lt;br /&gt;           if(nextBestPoint==null){&lt;br /&gt;            //沒路可走，換另一方&lt;br /&gt;            &lt;br /&gt;            //換手&lt;br /&gt;            whoTurn = whoTurn==0?1:0;&lt;br /&gt;               &lt;br /&gt;            //計算可以點選的地板&lt;br /&gt;            countAllowClicks();&lt;br /&gt;   &lt;br /&gt;            //顯示可以點選的地板&lt;br /&gt;            displayAllowClicks();&lt;br /&gt;            &lt;br /&gt;            //為接下來的玩家找出最適合的攻擊點&lt;br /&gt;            var nextBestPoint:Object = choiseBestAttPoint();&lt;br /&gt;            if(nextBestPoint==null){&lt;br /&gt;             //表示沒有可以攻擊的位置，遊戲結束&lt;br /&gt;             gameover();&lt;br /&gt;            }else{&lt;br /&gt;             if(whoTurn==1){&lt;br /&gt;              //電腦自動選最佳攻擊點&lt;br /&gt;              var timer:Timer = new Timer(1000, -1);&lt;br /&gt;              timer.addEventListener(TimerEvent.TIMER_COMPLETE, function(evt:TimerEvent):void{&lt;br /&gt;               select(nextBestPoint.i, nextBestPoint.j);&lt;br /&gt;              });&lt;br /&gt;              timer.start();&lt;br /&gt;             }&lt;br /&gt;            }&lt;br /&gt;           }else{&lt;br /&gt;            if(whoTurn==1){&lt;br /&gt;             //電腦自動選最佳攻擊點&lt;br /&gt;             var timer:Timer = new Timer(1000, -1);&lt;br /&gt;             timer.addEventListener(TimerEvent.TIMER_COMPLETE, function(evt:TimerEvent):void{&lt;br /&gt;              select(nextBestPoint.i, nextBestPoint.j);&lt;br /&gt;             });&lt;br /&gt;             timer.start();&lt;br /&gt;            }&lt;br /&gt;           }&lt;br /&gt;          }&lt;br /&gt;         });&lt;br /&gt;   timer.start();&lt;br /&gt;   dumpArray(gameData);&lt;br /&gt;  }&lt;br /&gt;  &lt;br /&gt;  private function choiseBestAttPoint():Object{&lt;br /&gt;   //為接下來的玩家找出最適合的攻擊點&lt;br /&gt;   var maxValue:int = 0;&lt;br /&gt;   var max_i:int;&lt;br /&gt;   var max_j:int;&lt;br /&gt;   for(var i:int=0; i&amp;lt;allowClickData[whoTurn].length; i++){&lt;br /&gt;    for(var j:int=0; j&amp;lt;allowClickData[whoTurn][i].length; j++){&lt;br /&gt;     if(allowClickData[whoTurn][i][j]&amp;gt;0){&lt;br /&gt;      if(allowClickData[whoTurn][i][j] &amp;gt; maxValue){&lt;br /&gt;       maxValue = allowClickData[whoTurn][i][j];&lt;br /&gt;       max_i = i;&lt;br /&gt;       max_j = j;&lt;br /&gt;      }&lt;br /&gt;     }&lt;br /&gt;    }&lt;br /&gt;   }&lt;br /&gt;   if(maxValue==0){&lt;br /&gt;    return null;&lt;br /&gt;   }else{&lt;br /&gt;    return {i:max_i, j:max_j};&lt;br /&gt;   }&lt;br /&gt;  }&lt;br /&gt;  &lt;br /&gt;  private function gameover():void{&lt;br /&gt;   trace("遊戲結束");&lt;br /&gt;   &lt;br /&gt;   var score0:int = 0;&lt;br /&gt;   var score1:int = 0;&lt;br /&gt;   &lt;br /&gt;   for(var i:int=0; i&amp;lt;gameData.length; i++){&lt;br /&gt;    for(var j:int=0; j&amp;lt;gameData[i].length; j++){&lt;br /&gt;     if(gameData[i][j]==0){&lt;br /&gt;      score0++;&lt;br /&gt;     }else if(gameData[i][j]==1){&lt;br /&gt;      score1++;&lt;br /&gt;     }&lt;br /&gt;    }&lt;br /&gt;   }&lt;br /&gt;   &lt;br /&gt;   trace("玩家=" + score0 + ", 電腦=" + score1);&lt;br /&gt;   this.dispatchEvent(new GameOverEvent(score0, score1));&lt;br /&gt;  }&lt;br /&gt;  &lt;br /&gt;  private function dumpArray(ary:Array):void{&lt;br /&gt;   for(var i:int=0; i&amp;lt;ary.length; i++){&lt;br /&gt;    trace(ary[i]);&lt;br /&gt;   }&lt;br /&gt;  }&lt;br /&gt;  &lt;br /&gt;  private function getKillChess(whoTurn:int, ci:int, cj:int):Array{&lt;br /&gt;   //判斷某個棋子座標的八方向是否可以掃射哪些棋子座標&lt;br /&gt;   //trace("[getKillChess]i=" + ci + ", j=" + cj);&lt;br /&gt;   var ary:Array = new Array();&lt;br /&gt;   &lt;br /&gt;   ary = ary.concat(killChess(whoTurn, ci, cj, -1, 0, 0, cj));//往上, i&lt;br /&gt;   ary = ary.concat(killChess(whoTurn, ci, cj, 1, 0, 7, cj));//往下, i&lt;br /&gt;   ary = ary.concat(killChess(whoTurn, ci, cj, 0, -1, ci, 0));//往左, j&lt;br /&gt;   ary = ary.concat(killChess(whoTurn, ci, cj, 0, 1, ci, 7));//往右, j&lt;br /&gt;   &lt;br /&gt;   ary = ary.concat(killChess(whoTurn, ci, cj, -1, -1, 0, 0));//往左上&lt;br /&gt;   ary = ary.concat(killChess(whoTurn, ci, cj, 1, -1, 7, 0));//往左下&lt;br /&gt;   ary = ary.concat(killChess(whoTurn, ci, cj, -1, 1, 0, 7));//往右上&lt;br /&gt;   ary = ary.concat(killChess(whoTurn, ci, cj, 1, 1, 7, 7));//往右下&lt;br /&gt;   &lt;br /&gt;   return ary;&lt;br /&gt;  }&lt;br /&gt;  &lt;br /&gt;  private function killChess(whoTurn:int, i_s:int, j_s:int&lt;br /&gt;         , i_inc:int, j_inc:int&lt;br /&gt;         , i_e:int, j_e:int):Array{&lt;br /&gt;   //trace("[killChess]i=" + i_s + ", j=" + j_s);&lt;br /&gt;   &lt;br /&gt;   //若兩個變化量都為0&lt;br /&gt;   if(i_inc==0 &amp;&amp; j_inc==0)return new Array();&lt;br /&gt;   &lt;br /&gt;   //若是變化量不為0，但是起點卻等於終點&lt;br /&gt;   if((i_inc!=0 &amp;&amp; i_s==i_e)&lt;br /&gt;    || (j_inc!=0 &amp;&amp; j_s==j_e))return new Array();&lt;br /&gt;&lt;br /&gt;   var i:int = i_s;&lt;br /&gt;   var j:int = j_s;&lt;br /&gt;   var ary2:Array = new Array();&lt;br /&gt;   &lt;br /&gt;   do{&lt;br /&gt;    //檢查下一個&lt;br /&gt;    if(i!=i_e)i += i_inc;&lt;br /&gt;    if(j!=j_e)j += j_inc;&lt;br /&gt;    //trace("check i=" + i + ", j=" + j)&lt;br /&gt;    &lt;br /&gt;    if(gameData[i][j]!=-1){&lt;br /&gt;     if(gameData[i][j]==whoTurn){&lt;br /&gt;      //開始清算要被殺掉的棋子&lt;br /&gt;      return ary2;&lt;br /&gt;     }else{&lt;br /&gt;      //被掃到的對手棋&lt;br /&gt;      ary2.push({i:i, j:j});&lt;br /&gt;     }&lt;br /&gt;    }else{&lt;br /&gt;     return new Array();&lt;br /&gt;    }&lt;br /&gt;   }while((i_inc==0 || (i_inc!=0 &amp;&amp; i!=i_e))&lt;br /&gt;     &amp;&amp; (j_inc==0 || (j_inc!=0 &amp;&amp; j!=j_e)))&lt;br /&gt;   //變化量不為0，尚未抵達終點&lt;br /&gt;   &lt;br /&gt;   return new Array();&lt;br /&gt;  }&lt;br /&gt;  &lt;br /&gt;  public function useGoldCard():Boolean{&lt;br /&gt;   //該使用者時，可以使用金牌&lt;br /&gt;   if(whoTurn==0 &amp;&amp; !isUsingGoldCard){&lt;br /&gt;    isUsingGoldCard = true;&lt;br /&gt;    &lt;br /&gt;    //顯示可以點選的地板&lt;br /&gt;    displayAllowClicks();&lt;br /&gt;&lt;br /&gt;    return true;&lt;br /&gt;   }&lt;br /&gt;   return false;&lt;br /&gt;  }&lt;br /&gt;  &lt;br /&gt;  public function chessboard_zoomin():void{&lt;br /&gt;   if(movingHeight&amp;gt;2000){&lt;br /&gt;    movingHeight -= 100;&lt;br /&gt;    movingRadius += 100;&lt;br /&gt;   }&lt;br /&gt;  }&lt;br /&gt;  &lt;br /&gt;  public function chessboard_zoomout():void{&lt;br /&gt;   if(movingHeight&amp;lt;3000){&lt;br /&gt;    movingHeight += 100;&lt;br /&gt;    movingRadius -= 100;&lt;br /&gt;   }&lt;br /&gt;  }&lt;br /&gt;  &lt;br /&gt;  public function chessboard_rotateleft():void{&lt;br /&gt;   du += 5;&lt;br /&gt;   du = (du + 360) % 360;&lt;br /&gt;  }&lt;br /&gt;  &lt;br /&gt;  public function chessboard_rotateright():void{&lt;br /&gt;   du -= 5;&lt;br /&gt;   du = (du + 360) % 360;&lt;br /&gt;  }&lt;br /&gt;  &lt;br /&gt;  &lt;br /&gt;  &lt;br /&gt;  //鍵盤事件&lt;br /&gt;  private function keyUpHandler(evt:KeyboardEvent):void{&lt;br /&gt;   switch(evt.keyCode){&lt;br /&gt;    case Keyboard.SPACE:&lt;br /&gt;     useGoldCard();&lt;br /&gt;     break;&lt;br /&gt;   }&lt;br /&gt;  }&lt;br /&gt;  private function keyDownHandler(evt:KeyboardEvent):void{&lt;br /&gt;   switch(evt.keyCode){&lt;br /&gt;    case Keyboard.UP:&lt;br /&gt;     chessboard_zoomin();&lt;br /&gt;     break;&lt;br /&gt;    case Keyboard.DOWN:&lt;br /&gt;     chessboard_zoomout();&lt;br /&gt;     break;&lt;br /&gt;    case Keyboard.LEFT:&lt;br /&gt;     chessboard_rotateleft();&lt;br /&gt;     break;&lt;br /&gt;    case Keyboard.RIGHT:&lt;br /&gt;     chessboard_rotateright();&lt;br /&gt;     break;&lt;br /&gt;   }&lt;br /&gt;   trace("du=" + du + ", movingHeight=" + movingHeight);&lt;br /&gt;   camera.x = movingRadius * Math.cos(du*TH);&lt;br /&gt;   camera.y = movingHeight;&lt;br /&gt;   camera.z = movingRadius * Math.sin(du*TH);&lt;br /&gt;  }&lt;br /&gt;  &lt;br /&gt; }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;在 Reversi.fla 中，則在 library 中準備兩個 symbol 當做兩種棋子的貼圖，instance name 分別為 PlayerImg0 與 PlayerImg1。&lt;br /&gt;&lt;br /&gt;玩的過程中最開心的是，玩出一套增加勝算的玩法，小時候玩的時候好像還沒想通這點，那就是要盡量攻擊同一個區塊，不只是要攻下 四角 與 四邊，還要盡量讓自己的棋子集中在同一區域(已搶下邊與角的區域)，這樣一來，電腦就無法在我們的背後見縫插針了，最後，就會形成只有我們能攻擊的狀態。&lt;br /&gt;&lt;br /&gt;&lt;a target="_blank" onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_HsFEtLMw5zU/SHHKIKjSlFI/AAAAAAAAGEI/ZRqsVMOZf6w/s1600-h/Clipboard01.jpg"&gt;&lt;img style="cursor:pointer; cursor:hand;" src="http://2.bp.blogspot.com/_HsFEtLMw5zU/SHHKIKjSlFI/AAAAAAAAGEI/ZRqsVMOZf6w/s400/Clipboard01.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5220175684719252562" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;a target="_blank" onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_HsFEtLMw5zU/SHHKIdqOe7I/AAAAAAAAGEQ/Vycl7J00dys/s1600-h/Clipboard02.jpg"&gt;&lt;img style="cursor:pointer; cursor:hand;" src="http://3.bp.blogspot.com/_HsFEtLMw5zU/SHHKIdqOe7I/AAAAAAAAGEQ/Vycl7J00dys/s400/Clipboard02.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5220175689848617906" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;a target="_blank" onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_HsFEtLMw5zU/SHHKIdOTRlI/AAAAAAAAGEY/YTaM2yrd38Q/s1600-h/Clipboard03.jpg"&gt;&lt;img style="cursor:pointer; cursor:hand;" src="http://4.bp.blogspot.com/_HsFEtLMw5zU/SHHKIdOTRlI/AAAAAAAAGEY/YTaM2yrd38Q/s400/Clipboard03.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5220175689731491410" /&gt;&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4754237190569973724-5544359948380809673?l=blog.ben.idv.tw' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.ben.idv.tw/feeds/5544359948380809673/comments/default' title='張貼意見'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4754237190569973724&amp;postID=5544359948380809673' title='15 個意見'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4754237190569973724/posts/default/5544359948380809673'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4754237190569973724/posts/default/5544359948380809673'/><link rel='alternate' type='text/html' href='http://blog.ben.idv.tw/2008/07/blog-post.html' title='黑白棋，加入電腦玩家'/><author><name>Ben Chang</name><uri>http://www.blogger.com/profile/01921640246111819069</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/_HsFEtLMw5zU/SHHKIKjSlFI/AAAAAAAAGEI/ZRqsVMOZf6w/s72-c/Clipboard01.jpg' height='72' width='72'/><thr:total>15</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4754237190569973724.post-3224262671819704303</id><published>2008-07-02T16:07:00.000+08:00</published><updated>2011-08-02T16:17:38.709+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Flash CS4'/><category scheme='http://www.blogger.com/atom/ns#' term='Flash Remoting'/><title type='text'>使用 AMFPHP</title><content type='html'>其實這跟 Flash CS4 的新功能沒啥關係，只不過當初我在看 AMFPHP 時，沒有找到 Flash CS3 的作法，我還以為那是因為沒有 Flash CS3 的 Flash Remoting Component 的緣故，剛再重新看 AMFPHP 的資料時，發現有人寫過 Flash CS3 的用法。&lt;br /&gt;&lt;br /&gt;以下我只是將 Flash CS3 的用法，用在 Flash CS4 看看，測試結果沒啥大問題。&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;1.&lt;br /&gt;可以根據官網的安裝流程：&lt;br /&gt;&lt;a target="_blank" href="http://www.amfphp.org/docs/installingamfphp.html"&gt;http://www.amfphp.org/docs/installingamfphp.html&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;在 SourceForge 下載到 amfphp 1.9 版：&lt;br /&gt;&lt;a target="_blank" href="http://sourceforge.net/project/showfiles.php?group_id=72483#files"&gt;http://sourceforge.net/project/showfiles.php?group_id=72483#files&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;將下載的檔案解壓縮到 apache 的 htdocs 網站目錄下，你可以直接放在這個目錄下(我放這)，那就等於是網站根目錄，也可以依據官方的建議，多放一層 flashservices 的資料夾下。&lt;br /&gt;&lt;br /&gt;2.&lt;br /&gt;準備一個 php 的服務&lt;br /&gt;{apache安裝目錄}\htdocs\services\idv\ben\remotingObject\Hello.php&lt;br /&gt;原始檔如下：&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&amp;lt;?php&lt;br /&gt;class Hello{&lt;br /&gt;public function getData(){&lt;br /&gt; return array(&lt;br /&gt;  array("name" =&amp;gt; "name1",&lt;br /&gt;   "phone" =&amp;gt; "phone1",&lt;br /&gt;   "email" =&amp;gt; "email1"),&lt;br /&gt;  array("name" =&amp;gt; "name2",&lt;br /&gt;   "phone" =&amp;gt; "phone2",&lt;br /&gt;   "email" =&amp;gt; "email2")&lt;br /&gt; );&lt;br /&gt;}&lt;br /&gt;}&lt;br /&gt;?&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;3.&lt;br /&gt;在 Flash CS4 中，新建一個 main.fla，其 Class 為 Main.as，原始檔如下：&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;package{&lt;br /&gt; import flash.display.MovieClip;&lt;br /&gt; import flash.net.NetConnection;&lt;br /&gt; import flash.net.Responder;&lt;br /&gt; &lt;br /&gt; public class Main extends MovieClip{&lt;br /&gt;  private var gateway:String = "http://localhost:8080/gateway.php";&lt;br /&gt;  private var connection:NetConnection;&lt;br /&gt;  private var responder:Responder;&lt;br /&gt;  &lt;br /&gt;  public function Main(){&lt;br /&gt;   connection = new NetConnection();&lt;br /&gt;   connection.connect(gateway);&lt;br /&gt;   &lt;br /&gt;   responder = new Responder(roResult, roStatus);&lt;br /&gt;   connection.call("idv.ben.remotingObject.Hello.getData", responder);&lt;br /&gt;  }&lt;br /&gt;  &lt;br /&gt;  private function roResult(result:Object):void{&lt;br /&gt;   trace("[roResult]");&lt;br /&gt;   dumpObject(result);&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  private function roStatus(result:Object):void{&lt;br /&gt;   trace("[roStatus]");&lt;br /&gt;   dumpObject(result);&lt;br /&gt;  }&lt;br /&gt;  &lt;br /&gt;  private function dumpObject(obj:Object, level:Number=0):void{&lt;br /&gt;   var levelIndicate:String = "";&lt;br /&gt;   for(var i:int=0; i&amp;lt;level; i++){&lt;br /&gt;    levelIndicate += "-";&lt;br /&gt;   }&lt;br /&gt;   if(levelIndicate!="")levelIndicate += " ";&lt;br /&gt;   &lt;br /&gt;   for(var j:String in obj){&lt;br /&gt;    &lt;br /&gt;    trace(levelIndicate + j + " = " + obj[j]);&lt;br /&gt;    if(obj[j] is Object){&lt;br /&gt;     dumpObject(obj[j], level+1);&lt;br /&gt;    }&lt;br /&gt;   }&lt;br /&gt;  }&lt;br /&gt; } &lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;4.&lt;br /&gt;測試，輸出畫面：&lt;br /&gt;&lt;br /&gt;&lt;a target="_blank" onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_HsFEtLMw5zU/SGs6e5QAMKI/AAAAAAAAGD0/ED5DQ2BUOe0/s1600-h/Clipboard01.jpg"&gt;&lt;img style="cursor: pointer;" src="http://1.bp.blogspot.com/_HsFEtLMw5zU/SGs6e5QAMKI/AAAAAAAAGD0/ED5DQ2BUOe0/s400/Clipboard01.jpg" alt="" id="BLOGGER_PHOTO_ID_5218328895677280418" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;完成！&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4754237190569973724-3224262671819704303?l=blog.ben.idv.tw' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.ben.idv.tw/feeds/3224262671819704303/comments/default' title='張貼意見'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4754237190569973724&amp;postID=3224262671819704303' title='0 個意見'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4754237190569973724/posts/default/3224262671819704303'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4754237190569973724/posts/default/3224262671819704303'/><link rel='alternate' type='text/html' href='http://blog.ben.idv.tw/2008/07/amfphp.html' title='使用 AMFPHP'/><author><name>Ben Chang</name><uri>http://www.blogger.com/profile/01921640246111819069</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/_HsFEtLMw5zU/SGs6e5QAMKI/AAAAAAAAGD0/ED5DQ2BUOe0/s72-c/Clipboard01.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4754237190569973724.post-585490638731089766</id><published>2008-06-26T14:44:00.005+08:00</published><updated>2011-08-02T16:21:33.141+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='EveryDNS'/><title type='text'>Google 服務結合自己的 Domain</title><content type='html'>透過 http://www.everydns.net/ 的免費 DNS 代管，我們可以在沒有自己的主機的條件下，利用許多 Google 提供的服務，來建置一個中小企業的資訊系統。&lt;br /&gt;&lt;br /&gt;Google 提供的 blogspot 平台，可以讓你的 blog 使用自己申請的 domain，像是我的 blog 現在已經是 http://blog.ben.idv.tw 了。&lt;br /&gt;&lt;br /&gt;其他像是 Google App Engine 平台，也可以讓你使用自己的 domain，不僅可以放靜態 html 網頁，若是你會寫 python 的話，也可以開發 server 端程式呢！&lt;br /&gt;&lt;br /&gt;使用 Google 服務加自己的 domain 設定，通常都是在 DNS 上，加一筆 CNAME 資料，指到 google 的 ghs.google.com 即可，這樣當有人要瀏覽 blog.ben.idv.tw 時，就會先找到我在 everydns.net 上設定的 DNS 紀錄，然後導到 ghs.google.com 去找這個 blog.ben.idv.tw 的網址，接下來就是 google 的服務囉！&lt;br /&gt;&lt;br /&gt;感覺怎麼解釋都好像解釋得不是很好，誰叫我不是系統工程師出身的呢！以下畫面是我在 everydns.net 上設定的資料，可以看到我有不少的紀錄如 blog, js, lua 都是導到 google 採用 blogspot 平台，而 gae 則是使用 Google App Engine 平台：&lt;br /&gt;&lt;br /&gt;&lt;a target="_blank" onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_HsFEtLMw5zU/SGM7Zm5ANsI/AAAAAAAAF78/8HYFWqWpoeQ/s1600-h/Clipboard01.jpg"&gt;&lt;img style="cursor:pointer; cursor:hand;" src="http://4.bp.blogspot.com/_HsFEtLMw5zU/SGM7Zm5ANsI/AAAAAAAAF78/8HYFWqWpoeQ/s320/Clipboard01.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5216078104547571394" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;以上，是對於一般部落客可以運用的部份。&lt;br /&gt;&lt;br /&gt;接下來，是一個小型組織，甚至是公司可以考慮採用的應用，Google 提供了另一個平台：Google 應用服務！&lt;br /&gt;&lt;br /&gt;&lt;a target="_blank" href="https://www.google.com/a/"&gt;https://www.google.com/a/&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;先講講跟前述類似的部份，就是這個平台也可以使用你自訂的 domain 來提供一些服務，所以你若是打 http://www.ben.idv.tw/ 的話，就會導到我在 Google Apps 上所設定的 Start Page，基本上，這個 Start Page 應該是類似 iGoogle 的東西吧！我完全沒玩過 iGoogle，不過我想應該是一樣的，因為，他也可以讓你自訂你想要放的 widget 與排版位置：&lt;br /&gt;&lt;br /&gt;&lt;a target="_blank" onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_HsFEtLMw5zU/SGM7aNWOgTI/AAAAAAAAF8E/lnrnav_hiEs/s1600-h/Clipboard02.jpg"&gt;&lt;img style="cursor:pointer; cursor:hand;" src="http://4.bp.blogspot.com/_HsFEtLMw5zU/SGM7aNWOgTI/AAAAAAAAF8E/lnrnav_hiEs/s320/Clipboard02.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5216078114870690098" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;為何我說 Google Apps 適用於 "組織" 應用呢？因為你可以想像這裡是 ben.idv.tw 這家公司/組織的內部網站，若是要 login 的話，就必須輸入管理者事先已經定義好的帳號資料才行，你可以看到以下的 login 畫面中，他會提示你是要輸入 xxxxxx@ben.idv.tw 的帳號：&lt;br /&gt;&lt;br /&gt;&lt;a target="_blank" onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_HsFEtLMw5zU/SGM7alDaGhI/AAAAAAAAF8M/sbv_-jcYzzo/s1600-h/Clipboard03.jpg"&gt;&lt;img style="cursor:pointer; cursor:hand;" src="http://2.bp.blogspot.com/_HsFEtLMw5zU/SGM7alDaGhI/AAAAAAAAF8M/sbv_-jcYzzo/s320/Clipboard03.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5216078121234209298" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;登入成功後，回到這個 ben.idv.tw 的組織的 Start Page 時，就會看到此登入帳號自己的 Start Page 設定，譬如以下畫面中，我在右下角就放置了一個新的 widget：&lt;br /&gt;&lt;br /&gt;&lt;a target="_blank" onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_HsFEtLMw5zU/SGM7bViH_xI/AAAAAAAAF8U/7af6ZnKP0kI/s1600-h/Clipboard04.jpg"&gt;&lt;img style="cursor:pointer; cursor:hand;" src="http://2.bp.blogspot.com/_HsFEtLMw5zU/SGM7bViH_xI/AAAAAAAAF8U/7af6ZnKP0kI/s320/Clipboard04.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5216078134247948050" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;再來證明一下這個平台到底跟 "組織" 有什麼關係，登入者接著可以到信箱中看看，可以看到以下畫面的右上角，現在正在瀏覽的信箱是 webmaster@ben.idv.tw 的信箱，這就表示你可以為你的組織成員開信箱，而不用真的自己建置 mail server 環境了：&lt;br /&gt;&lt;br /&gt;&lt;a target="_blank" onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_HsFEtLMw5zU/SGM7bwjAmXI/AAAAAAAAF8c/06rAYk2-ig0/s1600-h/Clipboard05.jpg"&gt;&lt;img style="cursor:pointer; cursor:hand;" src="http://1.bp.blogspot.com/_HsFEtLMw5zU/SGM7bwjAmXI/AAAAAAAAF8c/06rAYk2-ig0/s320/Clipboard05.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5216078141499414898" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;所以啦！中小企業可以好好考慮這套服務，若是你公司只用 blog 來公告公司訊息的話，那就用 blogspot 結合自己的 domain 即可，若是想要做比較複雜的網頁服務，也可以考慮學學 python 然後使用 Google App Engine 來建置你家的企業網站，總之，在某種流量與空間的限制之下，這一切都是免費的囉，只有申請 domain name 是要花錢ㄉㄟ！&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4754237190569973724-585490638731089766?l=blog.ben.idv.tw' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.ben.idv.tw/feeds/585490638731089766/comments/default' title='張貼意見'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4754237190569973724&amp;postID=585490638731089766' title='3 個意見'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4754237190569973724/posts/default/585490638731089766'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4754237190569973724/posts/default/585490638731089766'/><link rel='alternate' type='text/html' href='http://blog.ben.idv.tw/2008/06/google-domain.html' title='Google 服務結合自己的 Domain'/><author><name>Ben Chang</name><uri>http://www.blogger.com/profile/01921640246111819069</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_HsFEtLMw5zU/SGM7Zm5ANsI/AAAAAAAAF78/8HYFWqWpoeQ/s72-c/Clipboard01.jpg' height='72' width='72'/><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4754237190569973724.post-151506358023180242</id><published>2008-06-26T08:37:00.005+08:00</published><updated>2008-06-26T10:40:35.828+08:00</updated><title type='text'>ben.idv.tw</title><content type='html'>經朋友介紹，使用了免費的 DNS 服務：http://www.everydns.net/&lt;br /&gt;&lt;br /&gt;所以現在我的 blog 可以使用自己的 domain 了！&lt;br /&gt;&lt;br /&gt;&lt;a target="_blank" href="http://blog.ben.idv.tw"&gt;http://blog.ben.idv.tw&lt;/a&gt; --&gt; 邦邦的部落格&lt;br /&gt;&lt;br /&gt;&lt;a target="_blank" href="http://lua.ben.idv.tw"&gt;http://lua.ben.idv.tw&lt;/a&gt; --&gt; 邦邦學 Lua in uiOne (學Lua時的心得)&lt;br /&gt;&lt;br /&gt;&lt;a target="_blank" href="http://js.ben.idv.tw"&gt;http://js.ben.idv.tw&lt;/a&gt; --&gt; 邦邦的JavaScript教學 (只寫了幾篇的JS教學)&lt;br /&gt;&lt;br /&gt;&lt;a target="_blank" href="http://gae.ben.idv.tw/WebcamCapture/"&gt;http://gae.ben.idv.tw/WebcamCapture/&lt;/a&gt; --&gt; 放在 Google App Engine 的 webcam 程式&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4754237190569973724-151506358023180242?l=blog.ben.idv.tw' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.ben.idv.tw/feeds/151506358023180242/comments/default' title='張貼意見'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4754237190569973724&amp;postID=151506358023180242' title='0 個意見'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4754237190569973724/posts/default/151506358023180242'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4754237190569973724/posts/default/151506358023180242'/><link rel='alternate' type='text/html' href='http://blog.ben.idv.tw/2008/06/benidvtw.html' title='ben.idv.tw'/><author><name>Ben Chang</name><uri>http://www.blogger.com/profile/01921640246111819069</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4754237190569973724.post-4364490171454823888</id><published>2008-06-25T15:57:00.004+08:00</published><updated>2008-06-25T16:30:33.276+08:00</updated><title type='text'>關於 MMUG 暫停服務</title><content type='html'>&lt;a target="_blank" href="http://mmug.com.tw/"&gt;http://mmug.com.tw/&lt;/a&gt; 因為一些說來話長的原因，暫停服務一陣子！&lt;br /&gt;&lt;br /&gt;若是您在這段期間有什麼 Flash 的問題 "急著" 想要找人請教與討論的話，歡迎到 Google Group 平台的 AUG.tw 繼續發問：&lt;br /&gt;&lt;br /&gt;&lt;a target="_blank" href="http://groups.google.com/group/augtw"&gt;http://groups.google.com/group/augtw&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4754237190569973724-4364490171454823888?l=blog.ben.idv.tw' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.ben.idv.tw/feeds/4364490171454823888/comments/default' title='張貼意見'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4754237190569973724&amp;postID=4364490171454823888' title='0 個意見'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4754237190569973724/posts/default/4364490171454823888'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4754237190569973724/posts/default/4364490171454823888'/><link rel='alternate' type='text/html' href='http://blog.ben.idv.tw/2008/06/mmug.html' title='關於 MMUG 暫停服務'/><author><name>Ben Chang</name><uri>http://www.blogger.com/profile/01921640246111819069</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4754237190569973724.post-3418017479883688293</id><published>2008-06-19T14:57:00.004+08:00</published><updated>2011-08-02T16:12:23.190+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='PV3D'/><category scheme='http://www.blogger.com/atom/ns#' term='Flash'/><title type='text'>PV3D 做翻頁</title><content type='html'>執行畫面：&lt;br /&gt;&lt;br /&gt;&lt;a target="_blank" onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_HsFEtLMw5zU/SFoDeBjbGtI/AAAAAAAAF5E/yIvWehGhaeE/s1600-h/Clipboard02.jpg"&gt;&lt;img style="cursor:pointer; cursor:hand;" src="http://4.bp.blogspot.com/_HsFEtLMw5zU/SFoDeBjbGtI/AAAAAAAAF5E/yIvWehGhaeE/s320/Clipboard02.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5213483332982741714" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;瀏覽效果；點選 flash 使之取得 focus，可用左右鍵進行翻頁；移動滑鼠與滾輪可用來切換視角：&lt;br /&gt;&lt;br /&gt;&lt;a target="_blank" href="http://ben.rb.chang.googlepages.com/20080619_PV3D_2_bookflip.html"&gt;http://ben.rb.chang.googlepages.com/20080619_PV3D_2_bookflip.html&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;完整程式碼：&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;package {&lt;br /&gt; import caurina.transitions.Tweener;&lt;br /&gt; &lt;br /&gt; import flash.display.Sprite;&lt;br /&gt; import flash.events.Event;&lt;br /&gt; import flash.events.KeyboardEvent;&lt;br /&gt; import flash.events.MouseEvent;&lt;br /&gt; import flash.ui.Keyboard;&lt;br /&gt; &lt;br /&gt; import org.papervision3d.cameras.Camera3D;&lt;br /&gt; import org.papervision3d.core.geom.renderables.Vertex3D;&lt;br /&gt; import org.papervision3d.materials.ColorMaterial;&lt;br /&gt; import org.papervision3d.materials.utils.MaterialsList;&lt;br /&gt; import org.papervision3d.objects.DisplayObject3D;&lt;br /&gt; import org.papervision3d.objects.primitives.Plane;&lt;br /&gt; import org.papervision3d.render.BasicRenderEngine;&lt;br /&gt; import org.papervision3d.scenes.Scene3D;&lt;br /&gt; import org.papervision3d.view.Viewport3D;&lt;br /&gt;&lt;br /&gt; [SWF(backgroundColor="#000000", frameRate="12", width="400", height="400")]&lt;br /&gt; public class PV3D_2_bookflip extends Sprite&lt;br /&gt; {&lt;br /&gt;  private var viewport:Viewport3D;&lt;br /&gt;  private var scene:Scene3D;&lt;br /&gt;  private var camera:Camera3D;&lt;br /&gt;  private var renderer:BasicRenderEngine;&lt;br /&gt;  &lt;br /&gt;  private var camera_angle:Number = 0; //盤旋的圓圈角度&lt;br /&gt;  private var camera_height:Number = 500; //高度&lt;br /&gt;  private var camera_r:Number = 500; //半徑，距離 y 軸線的距離&lt;br /&gt;  &lt;br /&gt;  private var page_count:int = 8;&lt;br /&gt;  private var page_thickness:int = 10;&lt;br /&gt;  private var page_left_idx:int = -1;&lt;br /&gt;  &lt;br /&gt;  public function PV3D_2_bookflip()&lt;br /&gt;  {&lt;br /&gt;   init();&lt;br /&gt;  }&lt;br /&gt;  &lt;br /&gt;  private function init():void&lt;br /&gt;  {   &lt;br /&gt;   initPV3D();&lt;br /&gt;   &lt;br /&gt;   this.addEventListener(Event.ENTER_FRAME, loopPV3D);&lt;br /&gt;   &lt;br /&gt;   this.stage.addEventListener(MouseEvent.MOUSE_MOVE, onMouseMove);&lt;br /&gt;   this.stage.addEventListener(MouseEvent.MOUSE_WHEEL, onMouseWheel);&lt;br /&gt;   this.stage.addEventListener(KeyboardEvent.KEY_UP, onKeyUp);&lt;br /&gt;  }&lt;br /&gt;  &lt;br /&gt;  private function initPV3D():void&lt;br /&gt;  {&lt;br /&gt;   viewport = new Viewport3D(stage.stageWidth, stage.stageHeight);&lt;br /&gt;   this.addChild(viewport);&lt;br /&gt;   &lt;br /&gt;   scene = new Scene3D();&lt;br /&gt;   camera = new Camera3D();&lt;br /&gt;   renderer = new BasicRenderEngine();&lt;br /&gt;   &lt;br /&gt;&lt;br /&gt;   for(var i:int=0; i&amp;lt;page_count; i++)&lt;br /&gt;   {&lt;br /&gt;    var materialList:MaterialsList = new MaterialsList({&lt;br /&gt;     front: new ColorMaterial(0xffffff * Math.random())&lt;br /&gt;     , back: new ColorMaterial(0xffffff * Math.random())&lt;br /&gt;     });&lt;br /&gt;    var page:DisplayObject3D = createNewPage(materialList, 750, 1000);&lt;br /&gt;    moveCenter(page, -750/2) //移動中心點&lt;br /&gt;    page.rotationX = -90; //倒下去&lt;br /&gt;    page.y = (page_count - i) * page_thickness; //每頁要有點層級、厚度&lt;br /&gt;    &lt;br /&gt;    scene.addChild(page, "page" + i);&lt;br /&gt;   }&lt;br /&gt;  }&lt;br /&gt;  &lt;br /&gt;  private function createNewPage(materials:MaterialsList, width:Number=500, height:Number=500, segmentsW:Number=0, segmentsH:Number=0, initObject:Object=null):DisplayObject3D&lt;br /&gt;  {&lt;br /&gt;   var page:DisplayObject3D = new DisplayObject3D();&lt;br /&gt;   &lt;br /&gt;   var frontPlane:Plane = new Plane(materials.getMaterialByName("front"), width, height, segmentsW, segmentsH, initObject);&lt;br /&gt;   var backPlane:Plane = new Plane(materials.getMaterialByName("back"), width, height, segmentsW, segmentsH, initObject);&lt;br /&gt;   &lt;br /&gt;   backPlane.rotationY = 180;&lt;br /&gt;   &lt;br /&gt;   page.addChild(frontPlane, "front");&lt;br /&gt;   page.addChild(backPlane, "back");&lt;br /&gt;   &lt;br /&gt;   return page;&lt;br /&gt;  }&lt;br /&gt;  &lt;br /&gt;  private function moveCenter(obj3d:DisplayObject3D, dx:Number=0, dy:Number=0, dz:Number=0):void&lt;br /&gt;  {&lt;br /&gt;   if(obj3d.geometry!=null)&lt;br /&gt;   {&lt;br /&gt;    var vs:Array = obj3d.geometry.vertices;&lt;br /&gt;    var vc:int = vs.length;&lt;br /&gt;    for(var i:int=0; i&amp;lt;vc; i++)&lt;br /&gt;    {&lt;br /&gt;     var vt:Vertex3D = vs[i] as Vertex3D;&lt;br /&gt;     vt.x -= dx;&lt;br /&gt;     vt.y -= dy;&lt;br /&gt;     vt.z -= dz;&lt;br /&gt;    }&lt;br /&gt;   }&lt;br /&gt;   &lt;br /&gt;   for each(var child:DisplayObject3D in obj3d.children)&lt;br /&gt;   {&lt;br /&gt;    child.x -= dx;&lt;br /&gt;    child.y -= dy;&lt;br /&gt;    child.z -= dz;&lt;br /&gt;   }&lt;br /&gt;   &lt;br /&gt;   /*&lt;br /&gt;   obj3d.x += dx;&lt;br /&gt;   obj3d.y += dy;&lt;br /&gt;   obj3d.z += dz;&lt;br /&gt;   */&lt;br /&gt;  }&lt;br /&gt;  &lt;br /&gt;  private function loopPV3D(evt:Event):void&lt;br /&gt;  {&lt;br /&gt;   countCameraPostion();&lt;br /&gt;   &lt;br /&gt;   renderer.renderScene(scene, camera, viewport);&lt;br /&gt;  }&lt;br /&gt;  &lt;br /&gt;  private function countCameraPostion():void&lt;br /&gt;  {&lt;br /&gt;   camera.x = camera_r * Math.cos(camera_angle);&lt;br /&gt;   camera.y = camera_height;&lt;br /&gt;   camera.z = camera_r * Math.sin(camera_angle);&lt;br /&gt;  }  &lt;br /&gt;  &lt;br /&gt;  private function onMouseMove(evt:MouseEvent):void&lt;br /&gt;  {&lt;br /&gt;   camera_angle = Math.PI * (.25 * (evt.stageX - this.stage.stageWidth/2) / (this.stage.stageWidth/2) - 0.5);&lt;br /&gt;   camera_height = 500 + 500 * (1 - evt.stageY / this.stage.stageHeight);&lt;br /&gt;  }&lt;br /&gt;  &lt;br /&gt;  private function onMouseWheel(evt:MouseEvent):void&lt;br /&gt;  {&lt;br /&gt;   if(evt.delta&amp;gt;0)&lt;br /&gt;   {&lt;br /&gt;    //拉近&lt;br /&gt;    camera_r -= 25;&lt;br /&gt;    camera_r = Math.max(camera_r, 200);&lt;br /&gt;   }&lt;br /&gt;   else&lt;br /&gt;   {&lt;br /&gt;    //拉遠&lt;br /&gt;    camera_r += 25;&lt;br /&gt;    camera_r = Math.min(camera_r, 2000);&lt;br /&gt;   }&lt;br /&gt;  }&lt;br /&gt;  &lt;br /&gt;  private function onKeyUp(evt:KeyboardEvent):void&lt;br /&gt;  {&lt;br /&gt;   if(evt.keyCode == flash.ui.Keyboard.RIGHT)&lt;br /&gt;   {&lt;br /&gt;    nextPage();&lt;br /&gt;   }&lt;br /&gt;   else if(evt.keyCode == flash.ui.Keyboard.LEFT)&lt;br /&gt;   {&lt;br /&gt;    prevPage();&lt;br /&gt;   }&lt;br /&gt;  }&lt;br /&gt;  &lt;br /&gt;  private function nextPage():void&lt;br /&gt;  {&lt;br /&gt;   //頁面翻到左邊&lt;br /&gt;   if(page_left_idx &amp;lt; page_count-1)&lt;br /&gt;   {&lt;br /&gt;    var page:DisplayObject3D = scene.getChildByName("page" + (page_left_idx+1));&lt;br /&gt;    if(page)&lt;br /&gt;    {&lt;br /&gt;     var newPageDepth:int = (page_left_idx+1) * page_thickness; //每頁要有點層級、厚度&lt;br /&gt;     Tweener.addTween(page, {rotationZ:180, time:3, onUpdate:function():void{&lt;br /&gt;                  if(this.rotationZ&amp;gt;90)&lt;br /&gt;                  {&lt;br /&gt;                   page.y = newPageDepth;&lt;br /&gt;                  }&lt;br /&gt;                 }});&lt;br /&gt;     page_left_idx++;&lt;br /&gt;    }&lt;br /&gt;   }&lt;br /&gt;  }&lt;br /&gt;  &lt;br /&gt;  private function prevPage():void&lt;br /&gt;  {&lt;br /&gt;   //頁面翻到右邊&lt;br /&gt;   if(page_left_idx &amp;gt; -1)&lt;br /&gt;   {&lt;br /&gt;    var page:DisplayObject3D = scene.getChildByName("page" + page_left_idx);&lt;br /&gt;    if(page)&lt;br /&gt;    {&lt;br /&gt;     var newPageDepth:int = (page_count - page_left_idx) * page_thickness; //每頁要有點層級、厚度&lt;br /&gt;     Tweener.addTween(page, {rotationZ:0, time:3, onUpdate:function():void{&lt;br /&gt;                  if(this.rotationZ&amp;lt;90)&lt;br /&gt;                  {&lt;br /&gt;                   page.y = newPageDepth;&lt;br /&gt;                  }&lt;br /&gt;                 }});&lt;br /&gt;     &lt;br /&gt;     page_left_idx--;&lt;br /&gt;    }&lt;br /&gt;   }&lt;br /&gt;  }&lt;br /&gt; }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4754237190569973724-3418017479883688293?l=blog.ben.idv.tw' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.ben.idv.tw/feeds/3418017479883688293/comments/default' title='張貼意見'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4754237190569973724&amp;postID=3418017479883688293' title='6 個意見'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4754237190569973724/posts/default/3418017479883688293'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4754237190569973724/posts/default/3418017479883688293'/><link rel='alternate' type='text/html' href='http://blog.ben.idv.tw/2008/06/pv3d_19.html' title='PV3D 做翻頁'/><author><name>Ben Chang</name><uri>http://www.blogger.com/profile/01921640246111819069</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_HsFEtLMw5zU/SFoDeBjbGtI/AAAAAAAAF5E/yIvWehGhaeE/s72-c/Clipboard02.jpg' height='72' width='72'/><thr:total>6</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4754237190569973724.post-5769763677572962700</id><published>2008-06-17T16:58:00.012+08:00</published><updated>2008-11-13T12:34:56.797+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Webcam'/><category scheme='http://www.blogger.com/atom/ns#' term='Google App Engine'/><category scheme='http://www.blogger.com/atom/ns#' term='BitmapData'/><category scheme='http://www.blogger.com/atom/ns#' term='AS3'/><category scheme='http://www.blogger.com/atom/ns#' term='Flex'/><category scheme='http://www.blogger.com/atom/ns#' term='Python'/><title type='text'>我的 Google App Engine 第一個範例：Webcam 監控程式</title><content type='html'>今天使用 Google App Engine 平台，開發了一個用 Webcam 監控，定期拍照上傳圖檔的程式。&lt;br /&gt;&lt;br /&gt;監控程式位置：&lt;br /&gt;&lt;a target="_blank" href="http://ben-rb-chang.appspot.com/WebcamCapture/"&gt;http://ben-rb-chang.appspot.com/WebcamCapture/&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;可以調整每隔 5 ~ 30 秒拍照一張，按下 Start 後就會開始擷取了：&lt;br /&gt;&lt;br /&gt;&lt;a target="_blank" onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_HsFEtLMw5zU/SFd8zQhI7TI/AAAAAAAAF40/lEIGfyBdxl0/s1600-h/Clipboard01.jpg"&gt;&lt;img style="cursor: pointer;" src="http://3.bp.blogspot.com/_HsFEtLMw5zU/SFd8zQhI7TI/AAAAAAAAF40/lEIGfyBdxl0/s320/Clipboard01.jpg" alt="" id="BLOGGER_PHOTO_ID_5212772313753775410" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;儲存在 Server 上的圖檔 (存在 DataStore 中)，可由此觀看：&lt;br /&gt;&lt;a target="_blank" href="http://ben-rb-chang.appspot.com/WebcamCapture/uploadPic"&gt;http://ben-rb-chang.appspot.com/WebcamCapture/uploadPic&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;a target="_blank" onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_HsFEtLMw5zU/SFd8z3eHxiI/AAAAAAAAF48/waGt18e7uxk/s1600-h/Clipboard02.jpg"&gt;&lt;img style="cursor: pointer;" src="http://4.bp.blogspot.com/_HsFEtLMw5zU/SFd8z3eHxiI/AAAAAAAAF48/waGt18e7uxk/s320/Clipboard02.jpg" alt="" id="BLOGGER_PHOTO_ID_5212772324210099746" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;原始檔放在 Google Code：&lt;br /&gt;&lt;a target="_blank" href="http://code.google.com/p/gae-ben-rb-chang/source/browse/trunk/WebcamCapture"&gt;http://code.google.com/p/gae-ben-rb-chang/source/browse/trunk/WebcamCapture&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;這個程式可以用來監看家裡的老人、寵物、或是任何想要開放給網路任何人看到的東西或景觀。&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Flex 儲存圖檔的程式，可以參考我之前的文章：&lt;br /&gt;&lt;br /&gt;Flash WebCam 拍照存檔&lt;br /&gt;&lt;a target="_blank" href="http://benbenstudio.blogspot.com/2007/08/flash-webcam.html"&gt;http://benbenstudio.blogspot.com/2007/08/flash-webcam.html&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;將影片轉成連續圖檔&lt;br /&gt;&lt;a target="_blank" href="http://benbenstudio.blogspot.com/2007/09/blog-post_05.html"&gt;http://benbenstudio.blogspot.com/2007/09/blog-post_05.html&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;===========================================================&lt;br /&gt;&lt;br /&gt;[2008-06-20-11-16]&lt;br /&gt;&lt;br /&gt;我將 Google Map for Flash 結合進來，user 可以自己定出自己的 webcam 的所在位置。&lt;br /&gt;&lt;br /&gt;&lt;a target="_blank" onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_HsFEtLMw5zU/SFshKvAE30I/AAAAAAAAF5k/5_GNiz0sRMs/s1600-h/Clipboard03.jpg"&gt;&lt;img style="cursor:pointer; cursor:hand;" src="http://4.bp.blogspot.com/_HsFEtLMw5zU/SFshKvAE30I/AAAAAAAAF5k/5_GNiz0sRMs/s320/Clipboard03.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5213797461910675266" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;a target="_blank" onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_HsFEtLMw5zU/SFshKmid_1I/AAAAAAAAF5s/_R2eAmqKdqo/s1600-h/Clipboard04.jpg"&gt;&lt;img style="cursor:pointer; cursor:hand;" src="http://1.bp.blogspot.com/_HsFEtLMw5zU/SFshKmid_1I/AAAAAAAAF5s/_R2eAmqKdqo/s320/Clipboard04.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5213797459639009106" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;接下來，就可以利用這些經緯度資料，以及拍照時間資料，看看如何美化看圖介面了。&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;我第一次使用 Google Map for Flash 時的文章如下：&lt;br /&gt;&lt;br /&gt;地址轉經緯度後，於PV3D地球上定位&lt;br /&gt;&lt;a target="_blank" href="http://benbenstudio.blogspot.com/2008/06/pv3d.html"&gt;http://benbenstudio.blogspot.com/2008/06/pv3d.html&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;===========================================================&lt;br /&gt;&lt;br /&gt;[2008-06-20-15-33]&lt;br /&gt;&lt;br /&gt;現在，可以在介面上，看到最近活動的 30 個 webcam 畫面(雖然只有我在玩)。&lt;br /&gt;&lt;br /&gt;&lt;a target="_blank" onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_HsFEtLMw5zU/SFtdUEDC4VI/AAAAAAAAF50/xN64xQUjC1w/s1600-h/Clipboard01.jpg"&gt;&lt;img style="cursor:pointer; cursor:hand;" src="http://4.bp.blogspot.com/_HsFEtLMw5zU/SFtdUEDC4VI/AAAAAAAAF50/xN64xQUjC1w/s320/Clipboard01.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5213863592876761426" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;地圖當然就是要可以放大的囉！&lt;br /&gt;&lt;br /&gt;&lt;a target="_blank" onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_HsFEtLMw5zU/SFtd9AtA00I/AAAAAAAAF6E/zDBAGLPRsRg/s1600-h/Clipboard03.jpg"&gt;&lt;img style="cursor:pointer; cursor:hand;" src="http://2.bp.blogspot.com/_HsFEtLMw5zU/SFtd9AtA00I/AAAAAAAAF6E/zDBAGLPRsRg/s320/Clipboard03.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5213864296353682242" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;===========================================================&lt;br /&gt;&lt;br /&gt;[2008-06-23-13-21]&lt;br /&gt;&lt;br /&gt;flex 向 server 端的 python 取得圖檔的時候，可以指定寬高，python 會將圖檔縮放成指定寬高後再傳回，雖增加了 server 的 CPU 運算，但可減少頻寬的使用。&lt;br /&gt;&lt;br /&gt;另外，增加了 what are you doing? 的欄位。&lt;br /&gt;&lt;br /&gt;&lt;a target="_blank" href="http://1.bp.blogspot.com/_HsFEtLMw5zU/SF8y-Frf7wI/AAAAAAAAF6k/evU_B37dl8g/s1600-h/Clipboard01.jpg"&gt;&lt;img style="cursor:pointer; cursor:hand;" src="http://1.bp.blogspot.com/_HsFEtLMw5zU/SF8y-Frf7wI/AAAAAAAAF6k/evU_B37dl8g/s320/Clipboard01.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5214942935776227074" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;a target="_blank" href="http://3.bp.blogspot.com/_HsFEtLMw5zU/SF8y-UzgcHI/AAAAAAAAF6s/vQghGOjzSCg/s1600-h/Clipboard02.jpg"&gt;&lt;img style="cursor:pointer; cursor:hand;" src="http://3.bp.blogspot.com/_HsFEtLMw5zU/SF8y-UzgcHI/AAAAAAAAF6s/vQghGOjzSCg/s320/Clipboard02.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5214942939836346482" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;說起來，這只還是多種技術的亂結合而已！&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4754237190569973724-5769763677572962700?l=blog.ben.idv.tw' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.ben.idv.tw/feeds/5769763677572962700/comments/default' title='張貼意見'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4754237190569973724&amp;postID=5769763677572962700' title='17 個意見'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4754237190569973724/posts/default/5769763677572962700'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4754237190569973724/posts/default/5769763677572962700'/><link rel='alternate' type='text/html' href='http://blog.ben.idv.tw/2008/06/google-app-engine-webcam.html' title='我的 Google App Engine 第一個範例：Webcam 監控程式'/><author><name>Ben Chang</name><uri>http://www.blogger.com/profile/01921640246111819069</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/_HsFEtLMw5zU/SFd8zQhI7TI/AAAAAAAAF40/lEIGfyBdxl0/s72-c/Clipboard01.jpg' height='72' width='72'/><thr:total>17</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4754237190569973724.post-4026948720158439770</id><published>2008-06-13T11:24:00.002+08:00</published><updated>2008-11-13T12:34:57.234+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Books'/><title type='text'>World or Warcraft Programming</title><content type='html'>之前買的 魔獸世界程式開發手冊 今天到貨了&lt;br /&gt;&lt;br /&gt;&lt;a target="_blank" href="http://4.bp.blogspot.com/_HsFEtLMw5zU/SFHoehR-KjI/AAAAAAAAF4k/wxCliVkc_c4/s1600-h/image0.jpg"&gt;&lt;img style="cursor:pointer; cursor:hand;" src="http://4.bp.blogspot.com/_HsFEtLMw5zU/SFHoehR-KjI/AAAAAAAAF4k/wxCliVkc_c4/s320/image0.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5211201854871841330" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;買的時候沒有注意到，它竟然有 1022 頁，比 Essential ActionScript 3 還厚，沒關係，只是好玩隨意看看而已，真是敗家ㄚ！&lt;br /&gt;&lt;br /&gt;&lt;a target="_blank" href="http://1.bp.blogspot.com/_HsFEtLMw5zU/SFHoe5SWPCI/AAAAAAAAF4s/1FxhLk5UidM/s1600-h/image1.jpg"&gt;&lt;img style="cursor:pointer; cursor:hand;" src="http://1.bp.blogspot.com/_HsFEtLMw5zU/SFHoe5SWPCI/AAAAAAAAF4s/1FxhLk5UidM/s320/image1.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5211201861315869730" /&gt;&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4754237190569973724-4026948720158439770?l=blog.ben.idv.tw' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.ben.idv.tw/feeds/4026948720158439770/comments/default' title='張貼意見'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4754237190569973724&amp;postID=4026948720158439770' title='0 個意見'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4754237190569973724/posts/default/4026948720158439770'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4754237190569973724/posts/default/4026948720158439770'/><link rel='alternate' type='text/html' href='http://blog.ben.idv.tw/2008/06/world-or-warcraft-programming.html' title='World or Warcraft Programming'/><author><name>Ben Chang</name><uri>http://www.blogger.com/profile/01921640246111819069</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_HsFEtLMw5zU/SFHoehR-KjI/AAAAAAAAF4k/wxCliVkc_c4/s72-c/image0.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4754237190569973724.post-1392570189688483691</id><published>2008-06-13T10:28:00.004+08:00</published><updated>2011-08-02T16:12:23.197+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='PV3D'/><title type='text'>升級 PV3D 2.0</title><content type='html'>稍微去看了一下 PV3D 2.0 的進展，在以下這裡有些教學：&lt;br /&gt;&lt;a target="_blank" href="http://pv3d.org/pv3d-20-tutorial-list/"&gt;http://pv3d.org/pv3d-20-tutorial-list/&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;其中，有些初學者的教學可以先看看：&lt;br /&gt;Preparing for your first Papervision3D (pv3d) Project&lt;br /&gt;&lt;a target="_blank" href="http://pv3d.org/2007/12/11/0-flash-develop-flex-2-sdk/"&gt;0. Flash Develop + Flex 2 SDK&lt;/a&gt;&lt;br /&gt;&lt;a target="_blank" href="http://pv3d.org/2007/12/12/1-downloading-papervision3d-20-alpha-great-white/"&gt;1. Downloading Papervision3D 2.0 Alpha - Great White&lt;/a&gt;&lt;br /&gt;&lt;a target="_blank" href="http://pv3d.org/2007/12/13/02-preparing-a-papervision3d-project/"&gt;2. Preparing a Papervision3D Project&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Introduction to pv3d Workflow&lt;br /&gt;&lt;a target="_blank" href="http://pv3d.org/2007/12/14/3-creating-a-pv3d-20-skeleton-class/"&gt;3. Creating a pv3d 2.0 Skeleton Class&lt;/a&gt;&lt;br /&gt;&lt;a target="_blank" href="http://pv3d.org/2007/12/14/4-creating-your-first-pv3d-3d-object-aka-displayobject3d/"&gt;4. Creating Your First pv3d 3D Object&lt;/a&gt;&lt;br /&gt;&lt;a target="_blank" href="http://pv3d.org/2007/12/18/5-applying-materials-to-a-pv3d-3d-object-skinningtexturing/"&gt;5. Applying Materials to a pv3d 3D Object (Skinning/Texturing)&lt;/a&gt;&lt;br /&gt;&lt;a target="_blank" href="http://pv3d.org/2008/01/01/6-basic-movement-in-3d/"&gt;6. Basic Movement in 3d&lt;/a&gt;&lt;br /&gt;&lt;a target="_blank" href="http://pv3d.org/2008/01/06/7-basic-interactivity/"&gt;7. Basic Interactivity&lt;/a&gt;&lt;br /&gt;&lt;a target="_blank" href="http://pv3d.org/2008/01/12/template-basic-template-and-function-modifier-explanations/"&gt;8. Basic Template and Function Modifier Explanations&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;前三篇，工作環境的介紹，有經驗的人只要知道 SVN 位置就好了：&lt;br /&gt;&lt;a target="_blank" href="http://papervision3d.googlecode.com/svn/trunk/branches/GreatWhite/src/"&gt;http://papervision3d.googlecode.com/svn/trunk/branches/GreatWhite/src/&lt;/a&gt;&lt;br /&gt;此刻的版本是 Revision 590。&lt;br /&gt;&lt;br /&gt;接下來，可以看看 3 與 7 的文章，了解與 1.x 版不同的新東西，像是 org.papervision3d.view.Viewport3D 與 org.papervision3d.render.BasicRenderEngine，然後看看如何製作可以接收互動事件的貼圖材質與相關事件處理方式。&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4754237190569973724-1392570189688483691?l=blog.ben.idv.tw' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.ben.idv.tw/feeds/1392570189688483691/comments/default' title='張貼意見'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4754237190569973724&amp;postID=1392570189688483691' title='2 個意見'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4754237190569973724/posts/default/1392570189688483691'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4754237190569973724/posts/default/1392570189688483691'/><link rel='alternate' type='text/html' href='http://blog.ben.idv.tw/2008/06/pv3d-20.html' title='升級 PV3D 2.0'/><author><name>Ben Chang</name><uri>http://www.blogger.com/profile/01921640246111819069</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4754237190569973724.post-638239394285769182</id><published>2008-06-11T11:18:00.005+08:00</published><updated>2008-11-13T12:34:57.701+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Google App Engine'/><category scheme='http://www.blogger.com/atom/ns#' term='Python'/><title type='text'>Datastore 的 DateTimeProperty 採用 UTC 儲存資料</title><content type='html'>Google AppEngine 的 DataStore 有個 DateTimeProperty 的資料型態，不過，它是以 UTC 做儲存的，不管我們寫入時是否有指定 tzinfo，取出時 tzinfo 都已經被拿掉了。相關說明官網有提到：&lt;br /&gt;&lt;br /&gt;&lt;a target="_blank" href="http://code.google.com/appengine/docs/datastore/typesandpropertyclasses.html#DateTimeProperty"&gt;http://code.google.com/appengine/docs/datastore/typesandpropertyclasses.html#DateTimeProperty&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;官網也提到如何將 UTC 的 datetime 轉換成自己想要的 tzinfo 的時間：&lt;br /&gt;&lt;br /&gt;&lt;a target="_blank" href="http://code.google.com/appengine/docs/datastore/typesandpropertyclasses.html#datetime"&gt;http://code.google.com/appengine/docs/datastore/typesandpropertyclasses.html#datetime&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;除了自己寫一個繼承自 tzinfo 的類別之外，也可以考慮使用 pytz：&lt;br /&gt;&lt;br /&gt;&lt;a target="_blank" href="http://pytz.sourceforge.net/"&gt;http://pytz.sourceforge.net/&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;我嘗試採用 pytz 來產生我要的 timezone，在寫入資料庫前，確認寫入的 datetime 真的具有 tzinfo，不過輸出時，tzinfo 也確實被拿掉了。&lt;br /&gt;&lt;br /&gt;以下是我寫入資料庫前的程式碼，之前的版本是採用資料庫預設產生的，而現在改為由我們自己用 datetime.now(taipei_tz) 指定：&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;class GuestBook(webapp.RequestHandler):&lt;br /&gt;    def post(self):&lt;br /&gt;        greeting = Greeting()&lt;br /&gt;        if users.get_current_user():&lt;br /&gt;            greeting.author = users.get_current_user()&lt;br /&gt;        greeting.content = self.request.get("content")&lt;br /&gt;        greeting.date = datetime.now(taipei_tz)&lt;br /&gt;        &lt;br /&gt;        greeting.put()&lt;br /&gt;&lt;br /&gt;        self.response.out.write("存入的日期時間為：" + greeting.date.strftime("%Y-%m-%d %H:%M:%S %Z%z") + "&amp;lt;p&amp;gt;")&lt;br /&gt;        self.response.out.write("&amp;lt;a href=\"/\"&amp;gt;Home&amp;lt;/a&amp;gt;")&lt;br /&gt;        #self.redirect("/")&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;這裡看到的 taipei_tz 是 global 建好的 timezone：&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;import pytz&lt;br /&gt;from pytz import timezone&lt;br /&gt;&lt;br /&gt;taipei_tz = timezone('Asia/Taipei')&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;執行時，送出留言後的畫面如下，可以看出我們用 strftime() 指定字串格式中的 %Z%z 所代表的 tzinfo 資訊，可以正確的呈現出來：&lt;br /&gt;&lt;br /&gt;&lt;a target="_blank" href="http://1.bp.blogspot.com/_HsFEtLMw5zU/SE9Jy6JUMYI/AAAAAAAAF4E/TrTOPR52G3o/s1600-h/Clipboard01.jpg"&gt;&lt;img style="cursor:pointer; cursor:hand;" src="http://1.bp.blogspot.com/_HsFEtLMw5zU/SE9Jy6JUMYI/AAAAAAAAF4E/TrTOPR52G3o/s320/Clipboard01.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5210464432841568642" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;可是當回到列表頁面時，若是我採用 replace(tzinfo=tz) 的話，出來的結果根本就沒有變化：&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;        greetings = Greeting.gql("order by date desc limit 10")&lt;br /&gt;        ......&lt;br /&gt;        ......&lt;br /&gt;        for greeting in greetings:&lt;br /&gt;            ......&lt;br /&gt;            ......&lt;br /&gt;            greeting.date.replace(tzinfo=taipei_tz)&lt;br /&gt;            self.response.out.write("&amp;lt;td&amp;gt;")&lt;br /&gt;            self.response.out.write(greeting.date.tzname())&lt;br /&gt;            self.response.out.write("&amp;lt;/td&amp;gt;")&lt;br /&gt;            ......&lt;br /&gt;            ......&lt;br /&gt;        ......&lt;br /&gt;        ......&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;而，若是採用 astimezone(tz) 的話，則會出現錯誤訊息：&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;        greetings = Greeting.gql("order by date desc limit 10")&lt;br /&gt;        ......&lt;br /&gt;        ......&lt;br /&gt;        for greeting in greetings:&lt;br /&gt;            ......&lt;br /&gt;            ......&lt;br /&gt;            greeting.date.astimezone(taipei_tz)&lt;br /&gt;            self.response.out.write("&amp;lt;td&amp;gt;")&lt;br /&gt;            self.response.out.write(greeting.date.tzname())&lt;br /&gt;            self.response.out.write("&amp;lt;/td&amp;gt;")&lt;br /&gt;            ......&lt;br /&gt;            ......&lt;br /&gt;        ......&lt;br /&gt;        ......&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;錯誤訊息如下：&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;Traceback (most recent call last):&lt;br /&gt;  File "C:\Program Files\Google\google_appengine\google\appengine\ext\webapp\__init__.py", line 499, in __call__&lt;br /&gt;    handler.get(*groups)&lt;br /&gt;  File "C:\GoogleAppEngineWorkspace\helloworld\05_helloworld_db.py", line 51, in get&lt;br /&gt;    greeting.date.astimezone(taipei_tz)&lt;br /&gt;ValueError: astimezone() cannot be applied to a naive datetime&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;所以，最後我還是暫時只能用我上一篇的作法，自己加 timedelta(hours=+8) 了，做出來的執行畫面如下：&lt;br /&gt;&lt;br /&gt;&lt;a href="http://2.bp.blogspot.com/_HsFEtLMw5zU/SE9Lj-_NMVI/AAAAAAAAF4M/n9AWHnScAAE/s1600-h/Clipboard02.jpg"&gt;&lt;img style="cursor:pointer; cursor:hand;" src="http://2.bp.blogspot.com/_HsFEtLMw5zU/SE9Lj-_NMVI/AAAAAAAAF4M/n9AWHnScAAE/s320/Clipboard02.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5210466375466561874" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;不知道是否是 Google AppEngine 的問題，輸出的 datetime 應該不要用 naive，而要用 aware 包含 tzinfo，還是說這是 dev_appserver.py 的限制(應該不可能)，還是說還有其他轉換的作法，還是說這版的 astimezone() 實作有問題(應該不可能)，總之，再研究看看吧！&lt;br /&gt;&lt;br /&gt;這次的完整程式碼如下：&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;# -*- coding: utf8 -*-&lt;br /&gt;import cgi&lt;br /&gt;import wsgiref.handlers&lt;br /&gt;from datetime import datetime, timedelta&lt;br /&gt;from google.appengine.api import users&lt;br /&gt;from google.appengine.ext import webapp&lt;br /&gt;from google.appengine.ext import db&lt;br /&gt;&lt;br /&gt;import pytz&lt;br /&gt;from pytz import timezone&lt;br /&gt;&lt;br /&gt;taipei_tz = timezone('Asia/Taipei')&lt;br /&gt;&lt;br /&gt;class MainPage(webapp.RequestHandler):&lt;br /&gt;    def get(self):&lt;br /&gt;&lt;br /&gt;        #self.response.out.write(datetime.now(taipei_tz).strftime("%Y-%m-%d %H:%M:%S %Z%z") + "&amp;lt;p&amp;gt;")&lt;br /&gt;        &lt;br /&gt;        self.response.out.write("&amp;lt;html&amp;gt;&amp;lt;body&amp;gt;")&lt;br /&gt;&lt;br /&gt;        user = users.get_current_user()&lt;br /&gt;        if user:&lt;br /&gt;            self.response.out.write("welcome, " + user.nickname())&lt;br /&gt;            self.response.out.write("[&amp;lt;a href='" + users.create_logout_url(self.request.uri) + "'&amp;gt;logout&amp;lt;/a&amp;gt;]&amp;lt;p&amp;gt;")&lt;br /&gt;        else:&lt;br /&gt;            self.response.out.write("[&amp;lt;a href='" + users.create_login_url(self.request.uri) + "'&amp;gt;login&amp;lt;/a&amp;gt;]&amp;lt;p&amp;gt;")&lt;br /&gt;&lt;br /&gt;        self.response.out.write("""&lt;br /&gt;                    &amp;lt;form action="/sign" method="post"&amp;gt;&lt;br /&gt;                    &amp;lt;div&amp;gt;&amp;lt;textarea name="content"&amp;gt;&amp;lt;/textarea&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;                    &amp;lt;div&amp;gt;&amp;lt;input type="submit"&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;                    &amp;lt;/form&amp;gt;""")&lt;br /&gt;&lt;br /&gt;        #greetings = db.GqlQuery("select * from Greeting order by date desc limit 10")&lt;br /&gt;        greetings = Greeting.gql("order by date desc limit 10")&lt;br /&gt;        self.response.out.write("""&lt;br /&gt;                &amp;lt;table border="1"&amp;gt;&lt;br /&gt;                &amp;lt;tr&amp;gt;&lt;br /&gt;                &amp;lt;th&amp;gt;UTC&amp;lt;/th&amp;gt;&lt;br /&gt;                &amp;lt;th&amp;gt;+08:00&amp;lt;/th&amp;gt;&lt;br /&gt;                &amp;lt;th&amp;gt;tzinfo&amp;lt;/th&amp;gt;&lt;br /&gt;                &amp;lt;th&amp;gt;user&amp;lt;/th&amp;gt;&lt;br /&gt;                &amp;lt;th&amp;gt;content&amp;lt;/th&amp;gt;&lt;br /&gt;                &amp;lt;/tr&amp;gt;""")&lt;br /&gt;        for greeting in greetings:&lt;br /&gt;            self.response.out.write("&amp;lt;tr&amp;gt;")&lt;br /&gt;            self.response.out.write("&amp;lt;td&amp;gt;" + greeting.date.strftime("%Y-%m-%d %H:%M:%S %Z%z") + "&amp;lt;/td&amp;gt;")&lt;br /&gt;            self.response.out.write("&amp;lt;td&amp;gt;" + (greeting.date + timedelta(hours=+8)).strftime("%Y-%m-%d %H:%M:%S %Z%z") + "&amp;lt;/td&amp;gt;")&lt;br /&gt;&lt;br /&gt;            greeting.date.replace(tzinfo=taipei_tz)&lt;br /&gt;            #greeting.date.astimezone(taipei_tz)&lt;br /&gt;            self.response.out.write("&amp;lt;td&amp;gt;")&lt;br /&gt;            self.response.out.write(greeting.date.tzname())&lt;br /&gt;            self.response.out.write("&amp;lt;/td&amp;gt;")&lt;br /&gt;&lt;br /&gt;            self.response.out.write("&amp;lt;td&amp;gt;")&lt;br /&gt;            if greeting.author:&lt;br /&gt;                self.response.out.write("&amp;lt;b&amp;gt;%s&amp;lt;/b&amp;gt; wrote:" % greeting.author.nickname())&lt;br /&gt;            else:&lt;br /&gt;                self.response.out.write("an anonymous person wrote:")&lt;br /&gt;            self.response.out.write("&amp;lt;/td&amp;gt;")&lt;br /&gt;            self.response.out.write("&amp;lt;td&amp;gt;&amp;lt;pre&amp;gt;%s&amp;lt;/pre&amp;gt;&amp;lt;/td&amp;gt;" % cgi.escape(greeting.content))&lt;br /&gt;            self.response.out.write("&amp;lt;/tr&amp;gt;")&lt;br /&gt;        self.response.out.write("&amp;lt;/table&amp;gt;")&lt;br /&gt;&lt;br /&gt;        self.response.out.write("&amp;lt;/body&amp;gt;&amp;lt;/html&amp;gt;")        &lt;br /&gt;                &lt;br /&gt;class GuestBook(webapp.RequestHandler):&lt;br /&gt;    def post(self):&lt;br /&gt;        greeting = Greeting()&lt;br /&gt;        if users.get_current_user():&lt;br /&gt;            greeting.author = users.get_current_user()&lt;br /&gt;        greeting.content = self.request.get("content")&lt;br /&gt;        greeting.date = datetime.now(taipei_tz)&lt;br /&gt;        &lt;br /&gt;        greeting.put()&lt;br /&gt;&lt;br /&gt;        self.response.out.write("存入的日期時間為：" + greeting.date.strftime("%Y-%m-%d %H:%M:%S %Z%z") + "&amp;lt;p&amp;gt;")&lt;br /&gt;        self.response.out.write("&amp;lt;a href=\"/\"&amp;gt;Home&amp;lt;/a&amp;gt;")&lt;br /&gt;        #self.redirect("/")&lt;br /&gt;&lt;br /&gt;class Greeting(db.Model):&lt;br /&gt;    author = db.UserProperty()&lt;br /&gt;    content = db.StringProperty(multiline=True)&lt;br /&gt;    date = db.DateTimeProperty(auto_now_add=True)&lt;br /&gt;    &lt;br /&gt;def main():&lt;br /&gt;    application = webapp.WSGIApplication(&lt;br /&gt;        [('/', MainPage)&lt;br /&gt;         , ('/sign', GuestBook)],&lt;br /&gt;        debug=True)&lt;br /&gt;    wsgiref.handlers.CGIHandler().run(application)&lt;br /&gt;&lt;br /&gt;if __name__ == "__main__":&lt;br /&gt;    main()&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4754237190569973724-638239394285769182?l=blog.ben.idv.tw' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.ben.idv.tw/feeds/638239394285769182/comments/default' title='張貼意見'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4754237190569973724&amp;postID=638239394285769182' title='0 個意見'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4754237190569973724/posts/default/638239394285769182'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4754237190569973724/posts/default/638239394285769182'/><link rel='alternate' type='text/html' href='http://blog.ben.idv.tw/2008/06/datastore-datetimeproperty-utc.html' title='Datastore 的 DateTimeProperty 採用 UTC 儲存資料'/><author><name>Ben Chang</name><uri>http://www.blogger.com/profile/01921640246111819069</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/_HsFEtLMw5zU/SE9Jy6JUMYI/AAAAAAAAF4E/TrTOPR52G3o/s72-c/Clipboard01.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4754237190569973724.post-492970928114844810</id><published>2008-06-10T14:07:00.004+08:00</published><updated>2008-11-13T12:34:57.857+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Google App Engine'/><category scheme='http://www.blogger.com/atom/ns#' term='Python'/><title type='text'>Python 的 datetime 轉時區</title><content type='html'>為了週末要參加 Google Developer Day，所以被官方寄信告知要先自己玩過 Google App Engine 的範例教學，以確保當天課程的順利進行。&lt;br /&gt;&lt;br /&gt;在玩 datastore 的範例時：&lt;br /&gt;&lt;a target="_blank" href="http://code.google.com/appengine/docs/gettingstarted/usingdatastore.html"&gt;http://code.google.com/appengine/docs/gettingstarted/usingdatastore.html&lt;/a&gt;&lt;br /&gt;Greeting 的 date 欄位預設自動填入日期值，而輸出時，範例並沒有示範如何顯示這個日期資料。&lt;br /&gt;&lt;br /&gt;第一個問題是，若是從 Greeting 取得 datetime 類別的 date 物件時，要用何種方法可以將它變成我們想要的字串格式，當然各別將年月日取出來自己接字串也是可以，不過大部分的程式語言都具備有 format 的功能才對。&lt;br /&gt;&lt;br /&gt;這題算是比較簡單，只要會使用 strftime() 即可：&lt;br /&gt;&lt;a target="_blank" href="http://docs.python.org/lib/strftime-behavior.html"&gt;http://docs.python.org/lib/strftime-behavior.html&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;有支援的符號，可以由此查得：&lt;br /&gt;&lt;a target="_blank" href="http://docs.python.org/lib/module-time.html"&gt;http://docs.python.org/lib/module-time.html&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;Directive Meaning&lt;br /&gt;%a Locale's abbreviated weekday name. &lt;br /&gt;%A Locale's full weekday name. &lt;br /&gt;%b Locale's abbreviated month name. &lt;br /&gt;%B Locale's full month name. &lt;br /&gt;%c Locale's appropriate date and time representation. &lt;br /&gt;%d Day of the month as a decimal number [01,31]. &lt;br /&gt;%H Hour (24-hour clock) as a decimal number [00,23]. &lt;br /&gt;%I Hour (12-hour clock) as a decimal number [01,12]. &lt;br /&gt;%j Day of the year as a decimal number [001,366]. &lt;br /&gt;%m Month as a decimal number [01,12]. &lt;br /&gt;%M Minute as a decimal number [00,59]. &lt;br /&gt;%p Locale's equivalent of either AM or PM.&lt;br /&gt;%S Second as a decimal number [00,61].&lt;br /&gt;%U Week number of the year (Sunday as the first day of the week) as a decimal number [00,53]. All days in a new year preceding the first Sunday are considered to be in week 0.&lt;br /&gt;%w Weekday as a decimal number [0(Sunday),6]. &lt;br /&gt;%W Week number of the year (Monday as the first day of the week) as a decimal number [00,53]. All days in a new year preceding the first Monday are considered to be in week 0.&lt;br /&gt;%x Locale's appropriate date representation. &lt;br /&gt;%X Locale's appropriate time representation. &lt;br /&gt;%y Year without century as a decimal number [00,99]. &lt;br /&gt;%Y Year with century as a decimal number. &lt;br /&gt;%Z Time zone name (no characters if no time zone exists). &lt;br /&gt;%% A literal "%" character.&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;接下來，我第二個遇到的問題是，從 datastore 取得的 datetime 資料型態，都是以 UTC 的 timezone 呈現，這對我來說就麻煩了，即使我在學 Java 的時候，也沒怎麼學過如何處理國際化或是時區的相關議題，只好硬著頭皮查查以下的資料：&lt;br /&gt;&lt;br /&gt;1.&lt;br /&gt;&lt;a target="_blank" href="http://docs.python.org/lib/datetime-datetime.html"&gt;http://docs.python.org/lib/datetime-datetime.html&lt;/a&gt;datetime 具有 tzinfo 屬性，以及 astimezone(tz) 方法 與 replace(tzinfo=tz) 方法，看來可以用來設定 timezone。&lt;br /&gt;&lt;br /&gt;2.&lt;br /&gt;&lt;a target="_blank" href="http://docs.python.org/lib/datetime-tzinfo.html"&gt;http://docs.python.org/lib/datetime-tzinfo.html&lt;/a&gt;&lt;br /&gt;不過，tzinfo 是個 abstract class，我們必須自己繼承它，並實做一些 method 才行，文件中有提供範例程式，可以透過 USTimeZone() 取得 tzinfo 物件，但是台灣要用何種時區設定，就還要再查一查，我只知道我們是 +08:00。&lt;br /&gt;&lt;br /&gt;3.&lt;br /&gt;若是你在 google 查 "python timezone" 的話，可以找到一個有名的專門用來處理 timezone 的 python lib：&lt;br /&gt;&lt;a target="_blank" href="http://pytz.sourceforge.net/"&gt;http://pytz.sourceforge.net/&lt;/a&gt;&lt;br /&gt;我還沒研究要如何使用它。&lt;br /&gt;&lt;br /&gt;4.&lt;br /&gt;繼續步驟 2.，雖然我還不知道台灣的設定該如何設，不過我還是先亂玩一下，用 USTimeZone 任意建立一個 tz 後，餵給 greeting.date.astimezone(tz)：&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;......&lt;br /&gt;from tzinfo import USTimeZone&lt;br /&gt;tz  = USTimeZone(-5, "Eastern",  "EST", "EDT")&lt;br /&gt;......&lt;br /&gt;greeting.date.astimezone(tz)&lt;br /&gt;......&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;結果，出現錯誤訊息：ValueError: astimezone() cannot be applied to a naive datetime&lt;br /&gt;&lt;br /&gt;5.&lt;br /&gt;重新回到 datetime 的文件：&lt;br /&gt;&lt;a target="_blank" href="http://docs.python.org/lib/module-datetime.html"&gt;http://docs.python.org/lib/module-datetime.html&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;有這麼一段：&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;There are two kinds of date and time objects: ``naive'' and ``aware''. This distinction refers to whether the object has any notion of time zone, daylight saving time, or other kind of algorithmic or political time adjustment. Whether a naive datetime object represents Coordinated Universal Time (UTC), local time, or time in some other timezone is purely up to the program, just like it's up to the program whether a particular number represents metres, miles, or mass. Naive datetime objects are easy to understand and to work with, at the cost of ignoring some aspects of reality. &lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;總之就是，我從 datastore 取出的 datetime 屬性的 date 欄位，因為是 naive 的，所以不具有 timezone 的資訊，所以，我乾脆利用 timedelta 自己來為它加 8 小時吧：&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;(greeting.date + timedelta(hours=+8)).strftime("%Y-%m-%d %H:%M:%S %Z%z")&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;關於 timedelta 的用法：&lt;br /&gt;&lt;a target="_blank" href="http://docs.python.org/lib/datetime-timedelta.html"&gt;http://docs.python.org/lib/datetime-timedelta.html&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;最後，執行畫面如下：&lt;br /&gt;&lt;br /&gt;&lt;a target="_blank" href="http://4.bp.blogspot.com/_HsFEtLMw5zU/SE4j9ZcaIBI/AAAAAAAAF30/WVATZE_r4SQ/s1600-h/Clipboard01.jpg"&gt;&lt;img style="cursor:pointer; cursor:hand;" src="http://4.bp.blogspot.com/_HsFEtLMw5zU/SE4j9ZcaIBI/AAAAAAAAF30/WVATZE_r4SQ/s320/Clipboard01.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5210141356623274002" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;完整程式碼如下：&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;import cgi&lt;br /&gt;import wsgiref.handlers&lt;br /&gt;from datetime import timedelta&lt;br /&gt;from google.appengine.api import users&lt;br /&gt;from google.appengine.ext import webapp&lt;br /&gt;from google.appengine.ext import db&lt;br /&gt;&lt;br /&gt;class MainPage(webapp.RequestHandler):&lt;br /&gt;    def get(self):&lt;br /&gt;        self.response.out.write("&amp;lt;html&amp;gt;&amp;lt;body&amp;gt;")&lt;br /&gt;&lt;br /&gt;        user = users.get_current_user()&lt;br /&gt;        if user:&lt;br /&gt;            self.response.out.write("welcome, " + user.nickname())&lt;br /&gt;            self.response.out.write("[&amp;lt;a href='" + users.create_logout_url(self.request.uri) + "'&amp;gt;logout&amp;lt;/a&amp;gt;]&amp;lt;p&amp;gt;")&lt;br /&gt;        else:&lt;br /&gt;            self.response.out.write("[&amp;lt;a href='" + users.create_login_url(self.request.uri) + "'&amp;gt;login&amp;lt;/a&amp;gt;]&amp;lt;p&amp;gt;")&lt;br /&gt;&lt;br /&gt;        self.response.out.write("""&lt;br /&gt;                    &amp;lt;form action="/sign" method="post"&amp;gt;&lt;br /&gt;                    &amp;lt;div&amp;gt;&amp;lt;textarea name="content"&amp;gt;&amp;lt;/textarea&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;                    &amp;lt;div&amp;gt;&amp;lt;input type="submit"&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;                    &amp;lt;/form&amp;gt;""")&lt;br /&gt;&lt;br /&gt;        #greetings = db.GqlQuery("select * from Greeting order by date desc limit 10")&lt;br /&gt;        greetings = Greeting.gql("order by date desc limit 10")&lt;br /&gt;        self.response.out.write("""&lt;br /&gt;                &amp;lt;table border="1"&amp;gt;&lt;br /&gt;                &amp;lt;tr&amp;gt;&lt;br /&gt;                &amp;lt;th&amp;gt;UTC&amp;lt;/th&amp;gt;&lt;br /&gt;                &amp;lt;th&amp;gt;+08:00&amp;lt;/th&amp;gt;&lt;br /&gt;                &amp;lt;th&amp;gt;user&amp;lt;/th&amp;gt;&lt;br /&gt;                &amp;lt;th&amp;gt;content&amp;lt;/th&amp;gt;&lt;br /&gt;                &amp;lt;/tr&amp;gt;""")&lt;br /&gt;        for greeting in greetings:&lt;br /&gt;            self.response.out.write("&amp;lt;tr&amp;gt;")&lt;br /&gt;            self.response.out.write("&amp;lt;td&amp;gt;" + greeting.date.strftime("%Y-%m-%d %H:%M:%S %Z%z") + "&amp;lt;/td&amp;gt;")&lt;br /&gt;            self.response.out.write("&amp;lt;td&amp;gt;" + (greeting.date + timedelta(hours=+8)).strftime("%Y-%m-%d %H:%M:%S %Z%z") + "&amp;lt;/td&amp;gt;")&lt;br /&gt;            self.response.out.write("&amp;lt;td&amp;gt;")&lt;br /&gt;            if greeting.author:&lt;br /&gt;                self.response.out.write("&amp;lt;b&amp;gt;%s&amp;lt;/b&amp;gt; wrote:" % greeting.author.nickname())&lt;br /&gt;            else:&lt;br /&gt;                self.response.out.write("an anonymous person wrote:")&lt;br /&gt;            self.response.out.write("&amp;lt;/td&amp;gt;")&lt;br /&gt;            self.response.out.write("&amp;lt;td&amp;gt;&amp;lt;pre&amp;gt;%s&amp;lt;/pre&amp;gt;&amp;lt;/td&amp;gt;" % cgi.escape(greeting.content))&lt;br /&gt;            self.response.out.write("&amp;lt;/tr&amp;gt;")&lt;br /&gt;        self.response.out.write("&amp;lt;/table&amp;gt;")&lt;br /&gt;&lt;br /&gt;        self.response.out.write("&amp;lt;/body&amp;gt;&amp;lt;/html&amp;gt;")        &lt;br /&gt;                &lt;br /&gt;class GuestBook(webapp.RequestHandler):&lt;br /&gt;    def post(self):&lt;br /&gt;        greeting = Greeting()&lt;br /&gt;        if users.get_current_user():&lt;br /&gt;            greeting.author = users.get_current_user()&lt;br /&gt;        greeting.content = self.request.get("content")&lt;br /&gt;        greeting.put()&lt;br /&gt;        self.redirect("/")&lt;br /&gt;&lt;br /&gt;class Greeting(db.Model):&lt;br /&gt;    author = db.UserProperty()&lt;br /&gt;    content = db.StringProperty(multiline=True)&lt;br /&gt;    date = db.DateTimeProperty(auto_now_add=True)&lt;br /&gt;    &lt;br /&gt;def main():&lt;br /&gt;    application = webapp.WSGIApplication(&lt;br /&gt;        [('/', MainPage)&lt;br /&gt;         , ('/sign', GuestBook)],&lt;br /&gt;        debug=True)&lt;br /&gt;    wsgiref.handlers.CGIHandler().run(application)&lt;br /&gt;&lt;br /&gt;if __name__ == "__main__":&lt;br /&gt;    main()&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4754237190569973724-492970928114844810?l=blog.ben.idv.tw' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.ben.idv.tw/feeds/492970928114844810/comments/default' title='張貼意見'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4754237190569973724&amp;postID=492970928114844810' title='1 個意見'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4754237190569973724/posts/default/492970928114844810'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4754237190569973724/posts/default/492970928114844810'/><link rel='alternate' type='text/html' href='http://blog.ben.idv.tw/2008/06/google-developer-day-google-app-engine.html' title='Python 的 datetime 轉時區'/><author><name>Ben Chang</name><uri>http://www.blogger.com/profile/01921640246111819069</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_HsFEtLMw5zU/SE4j9ZcaIBI/AAAAAAAAF30/WVATZE_r4SQ/s72-c/Clipboard01.jpg' height='72' width='72'/><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4754237190569973724.post-1542622918777581526</id><published>2008-05-30T12:31:00.006+08:00</published><updated>2011-08-02T16:05:40.428+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='.NET'/><category scheme='http://www.blogger.com/atom/ns#' term='Browser'/><title type='text'>開發 IE 瀏覽器的 Toolbar：開新視窗並做兩視窗間的互動</title><content type='html'>在研究如何在 toolbar 上，進行另開新視窗，然後還可以兩個 IE 視窗互相溝通，這個問題查了一天半，看了以下幾個屬性或方法：&lt;br /&gt;&lt;br /&gt;IHTMLWindow2::open Method&lt;br /&gt;http://msdn.microsoft.com/en-us/library/aa741489(VS.85).aspx&lt;br /&gt;可是得到的都一直是 null！&lt;br /&gt;&lt;br /&gt;IHTMLWindow2::opener Property&lt;br /&gt;http://msdn.microsoft.com/en-us/library/aa741490(VS.85).aspx&lt;br /&gt;說只適用於 frame 與 iframe，奇怪，怎麼跟我在 JavaScript 時的經驗不太一樣呢？&lt;br /&gt;&lt;br /&gt;IHTMLDocument2::parentWindow Property&lt;br /&gt;http://msdn.microsoft.com/en-us/library/aa752599(VS.85).aspx&lt;br /&gt;認識一下如何從 document 取得 window！&lt;br /&gt;&lt;br /&gt;IHTMLDocument2::frames Property&lt;br /&gt;http://msdn.microsoft.com/en-us/library/aa752592(VS.85).aspx&lt;br /&gt;想當然不是這個，因為現在是要處理 window 的互動，不是 frame 的！&lt;br /&gt;&lt;br /&gt;IWebBrowser2::Navigate Method&lt;br /&gt;http://msdn.microsoft.com/en-us/library/aa752133(VS.85).aspx&lt;br /&gt;IWebBrowser2::Navigate2 Method&lt;br /&gt;http://msdn.microsoft.com/en-us/library/aa752134(VS.85).aspx&lt;br /&gt;在 C# 的語法中，都得不到回傳值！&lt;br /&gt;&lt;br /&gt;最後，只好另外建立一個 InternetExplorer 介面的物件，用它來開啟新視窗，並且在舊視窗中繼續監聽新視窗的事件，這樣一來在視窗處理函式中就仍可存取到舊視窗的物件架構了。&lt;br /&gt;&lt;br /&gt;以下是我的 MyToolbar.cs 中的片段程式碼，第三個按鈕的程式：&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;  private InternetExplorer IE;&lt;br /&gt;  private DWebBrowserEvents2_DocumentCompleteEventHandler IE_DocumentCompleteEventHandler;&lt;br /&gt;&lt;br /&gt;  private void button3_Click(object sender, System.EventArgs e)&lt;br /&gt;  {&lt;br /&gt;   object o = new object();&lt;br /&gt;&lt;br /&gt;   try&lt;br /&gt;   {&lt;br /&gt;    IE.Visible = true;&lt;br /&gt;    IE.Navigate("http://www.google.com", ref o, ref o, ref o, ref o);&lt;br /&gt;   }&lt;br /&gt;   catch(Exception exp)&lt;br /&gt;   {&lt;br /&gt;    IE = new InternetExplorer();&lt;br /&gt;    IE.Visible = true;&lt;br /&gt;&lt;br /&gt;    IE_DocumentCompleteEventHandler = new DWebBrowserEvents2_DocumentCompleteEventHandler(IE_DocumentComplete);&lt;br /&gt;    IE.DocumentComplete += IE_DocumentCompleteEventHandler;&lt;br /&gt;&lt;br /&gt;    IE.Navigate("http://www.google.com", ref o, ref o, ref o, ref o);&lt;br /&gt;   }&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  private void IE_DocumentComplete(object pDisp, ref object URL)&lt;br /&gt;  {&lt;br /&gt;   IWebBrowser2 ie = pDisp as IWebBrowser2;&lt;br /&gt;   &lt;br /&gt;   MessageBox.Show("[Explorer]" + (this.Explorer.Document as HTMLDocumentClass).url&lt;br /&gt;       + "\n[IE]" + (IE.Document as IHTMLDocument2).url&lt;br /&gt;       + "\n[ie]" + (ie.Document as IHTMLDocument2).url);&lt;br /&gt;   &lt;br /&gt;   //IE.DocumentComplete -= IE_DocumentCompleteEventHandler;&lt;br /&gt;  }&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;按下按鈕後，會產生新的視窗，但是新視窗的 DocumentComplete 事件處理程式卻都放在舊視窗中，所以仍可存取到舊視窗的物件，像是在 IE_DocumentComplete() 中的訊息框，Explorer 就代表舊視窗，IE 就代表新視窗，ie 則代表在新視窗中發出事件的來源，因為新視窗的 html 頁面可能會有許多 frame / iframe，所以會發現 ie 會有所不同。&lt;br /&gt;&lt;br /&gt;下圖，按下 toolbar 上第三個按鈕，開啟新視窗到 google，並跳出訊息：&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_HsFEtLMw5zU/SD-IBnNsaHI/AAAAAAAAFZk/rVJFFISmQKw/s1600-h/Clipboard01.jpg"&gt;&lt;img style="cursor:pointer; cursor:hand;" src="http://4.bp.blogspot.com/_HsFEtLMw5zU/SD-IBnNsaHI/AAAAAAAAFZk/rVJFFISmQKw/s320/Clipboard01.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5206029255551248498" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;下圖，當舊視窗變更網址到 mmug，則當新視窗也變更網址到 yam 時，會看到訊息框中可以正確的得知舊視窗的資訊：&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_HsFEtLMw5zU/SD-IB3NsaII/AAAAAAAAFZs/-OMoBrREkIM/s1600-h/Clipboard02.jpg"&gt;&lt;img style="cursor:pointer; cursor:hand;" src="http://1.bp.blogspot.com/_HsFEtLMw5zU/SD-IB3NsaII/AAAAAAAAFZs/-OMoBrREkIM/s320/Clipboard02.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5206029259846215810" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;若是，將舊視窗關閉的話，則表示 Listener 已經不存在了，當新視窗在變更網址到其他位置時，將無人監聽事件，所以就不會再有訊息框了，我就不貼沒有訊息框的貼圖了！&lt;br /&gt;&lt;br /&gt;借此作法，我們就可以在舊視窗中完全掌控新視窗的事件處理、控制 HTML 物件等等，而且仍可拿到舊視窗的 HTML 物件，得以互動。&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4754237190569973724-1542622918777581526?l=blog.ben.idv.tw' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.ben.idv.tw/feeds/1542622918777581526/comments/default' title='張貼意見'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4754237190569973724&amp;postID=1542622918777581526' title='0 個意見'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4754237190569973724/posts/default/1542622918777581526'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4754237190569973724/posts/default/1542622918777581526'/><link rel='alternate' type='text/html' href='http://blog.ben.idv.tw/2008/05/ie-toolbar_30.html' title='開發 IE 瀏覽器的 Toolbar：開新視窗並做兩視窗間的互動'/><author><name>Ben Chang</name><uri>http://www.blogger.com/profile/01921640246111819069</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_HsFEtLMw5zU/SD-IBnNsaHI/AAAAAAAAFZk/rVJFFISmQKw/s72-c/Clipboard01.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4754237190569973724.post-1218599519785673584</id><published>2008-05-28T15:23:00.009+08:00</published><updated>2011-08-02T16:05:40.433+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='.NET'/><category scheme='http://www.blogger.com/atom/ns#' term='Browser'/><title type='text'>開發 IE 瀏覽器的 Toolbar：安裝程式</title><content type='html'>開發好 IE 瀏覽器的 Plug-in 後，接下來就是要知道如何製作安裝程式，在以下這篇文章中，有提到一些做法：&lt;br /&gt;&lt;br /&gt;Issues faced while extending IE with Band Objects using .NET and Windows Forms&lt;br /&gt;&lt;a href="http://www.codeproject.com/KB/cs/Issuewithbandobjects.aspx" target="_blank"&gt;http://www.codeproject.com/KB/cs/Issuewithbandobjects.aspx&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;這篇文章在提到安裝程式的那段中，主要是說我們可以為 MSI 設定 registration 為 vsdrpCOM，這樣安裝後就會進行註冊 dll 的動作，但是據說在 uninstall 時不會被移除。所以作者建議可以維持預設的 vsdrpNoDotRegister 不註冊，然後自己寫 Custom Actions。&lt;br /&gt;&lt;br /&gt;首先，先在 MyToolbar 的專案中，新增一個 MyToolbarInstaller 的 Installer Class：&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_HsFEtLMw5zU/SD0J8xo1N6I/AAAAAAAAFYk/5mOQ5GJ7RmE/s1600-h/Clipboard01.jpg"&gt;&lt;img style="cursor: pointer;" src="http://4.bp.blogspot.com/_HsFEtLMw5zU/SD0J8xo1N6I/AAAAAAAAFYk/5mOQ5GJ7RmE/s320/Clipboard01.jpg" alt="" id="BLOGGER_PHOTO_ID_5205327684031559586" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;完整程式碼如下，重點在於 override Install 與 Uninstall 的部份：&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;using System;&lt;br /&gt;using System.Collections;&lt;br /&gt;using System.ComponentModel;&lt;br /&gt;using System.Configuration.Install;&lt;br /&gt;&lt;br /&gt;namespace MyToolbar&lt;br /&gt;{&lt;br /&gt; /// &lt;summary&gt;&lt;br /&gt; /// Summary description for Installer1.&lt;br /&gt; /// &lt;/summary&gt;&lt;br /&gt; [RunInstaller(true)]&lt;br /&gt; public class MyToolbarInstaller : System.Configuration.Install.Installer&lt;br /&gt; {&lt;br /&gt;  /// &lt;summary&gt;&lt;br /&gt;  /// Required designer variable.&lt;br /&gt;  /// &lt;/summary&gt;&lt;br /&gt;  private System.ComponentModel.Container components = null;&lt;br /&gt;&lt;br /&gt;  public MyToolbarInstaller()&lt;br /&gt;  {&lt;br /&gt;   // This call is required by the Designer.&lt;br /&gt;   InitializeComponent();&lt;br /&gt;&lt;br /&gt;   // TODO: Add any initialization after the InitializeComponent call&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  public override void Install(IDictionary stateSaver)&lt;br /&gt;  {&lt;br /&gt;   base.Install (stateSaver);&lt;br /&gt;&lt;br /&gt;   System.Runtime.InteropServices.RegistrationServices r = new System.Runtime.InteropServices.RegistrationServices();&lt;br /&gt;   r.RegisterAssembly(this.GetType().Assembly, System.Runtime.InteropServices.AssemblyRegistrationFlags.SetCodeBase);&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  public override void Uninstall(IDictionary savedState)&lt;br /&gt;  {&lt;br /&gt;   base.Uninstall (savedState);&lt;br /&gt;&lt;br /&gt;   System.Runtime.InteropServices.RegistrationServices r = new System.Runtime.InteropServices.RegistrationServices();&lt;br /&gt;   r.UnregisterAssembly(this.GetType().Assembly);&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  /// &lt;summary&gt;&lt;br /&gt;  /// Clean up any resources being used.&lt;br /&gt;  /// &lt;/summary&gt;&lt;br /&gt;  protected override void Dispose( bool disposing )&lt;br /&gt;  {&lt;br /&gt;   if( disposing )&lt;br /&gt;   {&lt;br /&gt;    if(components != null)&lt;br /&gt;    {&lt;br /&gt;     components.Dispose();&lt;br /&gt;    }&lt;br /&gt;   }&lt;br /&gt;   base.Dispose( disposing );&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;  #region Component Designer generated code&lt;br /&gt;  /// &lt;summary&gt;&lt;br /&gt;  /// Required method for Designer support - do not modify&lt;br /&gt;  /// the contents of this method with the code editor.&lt;br /&gt;  /// &lt;/summary&gt;&lt;br /&gt;  private void InitializeComponent()&lt;br /&gt;  {&lt;br /&gt;   components = new System.ComponentModel.Container();&lt;br /&gt;  }&lt;br /&gt;  #endregion&lt;br /&gt; }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;這個 Installer Class 會一起被包進 MyToolbar.dll 中！&lt;br /&gt;&lt;br /&gt;接著，可以在 Solution 中新增一個 MyToolbarSetup 的 Setup Project：&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_HsFEtLMw5zU/SD0K4ho1N7I/AAAAAAAAFYs/IGIQy252jl8/s1600-h/Clipboard02.jpg"&gt;&lt;img style="cursor:pointer; cursor:hand;" src="http://3.bp.blogspot.com/_HsFEtLMw5zU/SD0K4ho1N7I/AAAAAAAAFYs/IGIQy252jl8/s320/Clipboard02.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5205328710528743346" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;然後在 Setup Project 的檔案總管中，在 Application Folder 中新增一個 Assembly，請選取 MyToolbar 專案所產出的 MyToolbar.dll，系統會自動將依賴的 dll 也都包進來，其中有一個 shdocvw.dll 因為是屬於 C:\WINDOWS\system32\shdocvw.dll 的共用 dll，所以可以將之排除，設定其 Exculde 設定為 True：&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_HsFEtLMw5zU/SD0LdRo1N8I/AAAAAAAAFY0/5_tvqOcx4Po/s1600-h/Clipboard03.jpg"&gt;&lt;img style="cursor:pointer; cursor:hand;" src="http://2.bp.blogspot.com/_HsFEtLMw5zU/SD0LdRo1N8I/AAAAAAAAFY0/5_tvqOcx4Po/s320/Clipboard03.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5205329341888935874" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;順利 build 完這個 Setup Project 並執行輸出的 \MyToolbarSetup\Release\MyToolbarSetup.msi 後，會發現當我們開啟 IE 時並不會看到我們開發的 Toolbar，這是因為我們在 Setup Project 中，並未設定 MyToolbar.dll 要進行註冊：&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_HsFEtLMw5zU/SD0Mvho1N9I/AAAAAAAAFY8/pZUYKhgqfx4/s1600-h/Clipboard04.jpg"&gt;&lt;img style="cursor:pointer; cursor:hand;" src="http://3.bp.blogspot.com/_HsFEtLMw5zU/SD0Mvho1N9I/AAAAAAAAFY8/pZUYKhgqfx4/s320/Clipboard04.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5205330754933176274" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;記得 Custom Actions 這件事情嗎？若是你跟我一樣對 Visual Studio .NET 2003 沒有那麼熟的話，可以參考以下的官方說明，教你如何在 Setup Project 中指定自己的 Custom Actions：&lt;br /&gt;&lt;br /&gt;&lt;a target="_blank" href="http://msdn.microsoft.com/en-us/library/d9k65z2d(VS.80).aspx"&gt;http://msdn.microsoft.com/en-us/library/d9k65z2d(VS.80).aspx&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;步驟如下：&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_HsFEtLMw5zU/SD0N4xo1N-I/AAAAAAAAFZE/VETkBxVd9Iw/s1600-h/Clipboard05.jpg"&gt;&lt;img style="cursor:pointer; cursor:hand;" src="http://4.bp.blogspot.com/_HsFEtLMw5zU/SD0N4xo1N-I/AAAAAAAAFZE/VETkBxVd9Iw/s320/Clipboard05.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5205332013358594018" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_HsFEtLMw5zU/SD0N5Ro1N_I/AAAAAAAAFZM/JcNNDuiFO7A/s1600-h/Clipboard06.jpg"&gt;&lt;img style="cursor:pointer; cursor:hand;" src="http://2.bp.blogspot.com/_HsFEtLMw5zU/SD0N5Ro1N_I/AAAAAAAAFZM/JcNNDuiFO7A/s320/Clipboard06.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5205332021948528626" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_HsFEtLMw5zU/SD0N5xo1OAI/AAAAAAAAFZU/U2rtSwufDEI/s1600-h/Clipboard07.jpg"&gt;&lt;img style="cursor:pointer; cursor:hand;" src="http://4.bp.blogspot.com/_HsFEtLMw5zU/SD0N5xo1OAI/AAAAAAAAFZU/U2rtSwufDEI/s320/Clipboard07.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5205332030538463234" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_HsFEtLMw5zU/SD0N6Bo1OBI/AAAAAAAAFZc/Jt9qE-Kz6uY/s1600-h/Clipboard08.jpg"&gt;&lt;img style="cursor:pointer; cursor:hand;" src="http://1.bp.blogspot.com/_HsFEtLMw5zU/SD0N6Bo1OBI/AAAAAAAAFZc/Jt9qE-Kz6uY/s320/Clipboard08.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5205332034833430546" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;在 Install 與 Uninstall 都指定到 MyToolbar.dll，因為在 MyToolbar.dll 中有 Install Class，所以會進行一些自訂的作業。&lt;br /&gt;&lt;br /&gt;重新 build 並執行 MyToolbarSetup.msi 安裝後，應該就可以在 IE 瀏覽器看到 Toolbar 了，記得測試一下 Uninstall 是否也會正常移除 IE 瀏覽器的 Toolbar 喔！&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4754237190569973724-1218599519785673584?l=blog.ben.idv.tw' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.ben.idv.tw/feeds/1218599519785673584/comments/default' title='張貼意見'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4754237190569973724&amp;postID=1218599519785673584' title='6 個意見'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4754237190569973724/posts/default/1218599519785673584'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4754237190569973724/posts/default/1218599519785673584'/><link rel='alternate' type='text/html' href='http://blog.ben.idv.tw/2008/05/ie-toolbar_28.html' title='開發 IE 瀏覽器的 Toolbar：安裝程式'/><author><name>Ben Chang</name><uri>http://www.blogger.com/profile/01921640246111819069</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_HsFEtLMw5zU/SD0J8xo1N6I/AAAAAAAAFYk/5mOQ5GJ7RmE/s72-c/Clipboard01.jpg' height='72' width='72'/><thr:total>6</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4754237190569973724.post-2690923395572290972</id><published>2008-05-27T18:18:00.003+08:00</published><updated>2011-08-02T16:05:40.439+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='.NET'/><category scheme='http://www.blogger.com/atom/ns#' term='Browser'/><title type='text'>開發 IE 瀏覽器的 Toolbar：半自動程式搭配人為挑選資料</title><content type='html'>若是在自動化作業中，有一些需要半自動 + 人為決定的話，譬如在 100 篇資料中只要複製其中幾篇，這時候就要考慮如何將人為因素加入。以下畫面中呈現 login 後，要從頁面二的表格中，挑選部分資料複製到頁面三的表格中：&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_HsFEtLMw5zU/SDvgrxo1N1I/AAAAAAAAFX8/Z-jXecErAno/s1600-h/Clipboard01.jpg"&gt;&lt;img style="cursor:pointer; cursor:hand;" src="http://2.bp.blogspot.com/_HsFEtLMw5zU/SDvgrxo1N1I/AAAAAAAAFX8/Z-jXecErAno/s320/Clipboard01.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5205000837020333906" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;login：&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_HsFEtLMw5zU/SDvgsBo1N2I/AAAAAAAAFYE/Hb485xj7WGc/s1600-h/Clipboard02.jpg"&gt;&lt;img style="cursor:pointer; cursor:hand;" src="http://3.bp.blogspot.com/_HsFEtLMw5zU/SDvgsBo1N2I/AAAAAAAAFYE/Hb485xj7WGc/s320/Clipboard02.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5205000841315301218" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;進入頁面二後，我會動態在 html table 中加入新的一欄，並在欄位標頭加一個按鈕，而其他列中則加入 checkbox 供勾選：&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_HsFEtLMw5zU/SDvgsRo1N3I/AAAAAAAAFYM/pk8cOfvAQ8A/s1600-h/Clipboard03.jpg"&gt;&lt;img style="cursor:pointer; cursor:hand;" src="http://4.bp.blogspot.com/_HsFEtLMw5zU/SDvgsRo1N3I/AAAAAAAAFYM/pk8cOfvAQ8A/s320/Clipboard03.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5205000845610268530" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;勾選完畢，按下欄位標頭的按鈕後，因為我會監聽此按鈕的 click 事件，所以可以在此重新分析 table 的資料，決定哪幾列因為有勾選而需要儲存資料，並且將瀏覽器跳至下一頁：&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_HsFEtLMw5zU/SDvgsho1N4I/AAAAAAAAFYU/4XuXdTSTclM/s1600-h/Clipboard05.jpg"&gt;&lt;img style="cursor:pointer; cursor:hand;" src="http://1.bp.blogspot.com/_HsFEtLMw5zU/SDvgsho1N4I/AAAAAAAAFYU/4XuXdTSTclM/s320/Clipboard05.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5205000849905235842" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;最後，將儲存的資料複製進頁面三的表格中即可：&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_HsFEtLMw5zU/SDvgsho1N5I/AAAAAAAAFYc/nJcwqeKFSnU/s1600-h/Clipboard06.jpg"&gt;&lt;img style="cursor:pointer; cursor:hand;" src="http://1.bp.blogspot.com/_HsFEtLMw5zU/SDvgsho1N5I/AAAAAAAAFYc/nJcwqeKFSnU/s320/Clipboard06.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5205000849905235858" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;完整 HTML 原始檔：&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&amp;lt;html&amp;gt;&lt;br /&gt;&amp;lt;head&amp;gt;&lt;br /&gt;&amp;lt;title&amp;gt;test page&amp;lt;/title&amp;gt;&lt;br /&gt;&amp;lt;/head&amp;gt;&lt;br /&gt;&amp;lt;body&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;table border="1"&amp;gt;&lt;br /&gt;&amp;lt;tr valign="top"&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;td&amp;gt;&lt;br /&gt;&amp;lt;h3&amp;gt;頁面一：登入&amp;lt;/h3&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;form&amp;gt;&lt;br /&gt;uid: &amp;lt;input type="text" name="uid"&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;pwd: &amp;lt;input type="text" name="pwd"&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;&amp;lt;input type="submit"&amp;gt;&lt;br /&gt;&amp;lt;/form&amp;gt;&lt;br /&gt;&amp;lt;/td&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;td&amp;gt;&lt;br /&gt;&amp;lt;h3&amp;gt;頁面二：複製資料&amp;lt;/h3&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;form&amp;gt;&lt;br /&gt;&amp;lt;table border="1"&amp;gt;&lt;br /&gt;&amp;lt;tr&amp;gt;&lt;br /&gt;&amp;lt;td&amp;gt;owner&amp;lt;/td&amp;gt;&lt;br /&gt;&amp;lt;td&amp;gt;status&amp;lt;/td&amp;gt;&lt;br /&gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;&amp;lt;tr&amp;gt;&lt;br /&gt;&amp;lt;td&amp;gt;owner 1&amp;lt;/td&amp;gt;&lt;br /&gt;&amp;lt;td&amp;gt;status 1&amp;lt;/td&amp;gt;&lt;br /&gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;&amp;lt;tr&amp;gt;&lt;br /&gt;&amp;lt;td&amp;gt;owner 2&amp;lt;/td&amp;gt;&lt;br /&gt;&amp;lt;td&amp;gt;status 2&amp;lt;/td&amp;gt;&lt;br /&gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;&amp;lt;tr&amp;gt;&lt;br /&gt;&amp;lt;td&amp;gt;owner 3&amp;lt;/td&amp;gt;&lt;br /&gt;&amp;lt;td&amp;gt;status 3&amp;lt;/td&amp;gt;&lt;br /&gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;&amp;lt;tr&amp;gt;&lt;br /&gt;&amp;lt;td&amp;gt;owner 4&amp;lt;/td&amp;gt;&lt;br /&gt;&amp;lt;td&amp;gt;status 4&amp;lt;/td&amp;gt;&lt;br /&gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;&amp;lt;tr&amp;gt;&lt;br /&gt;&amp;lt;td&amp;gt;owner 5&amp;lt;/td&amp;gt;&lt;br /&gt;&amp;lt;td&amp;gt;status 5&amp;lt;/td&amp;gt;&lt;br /&gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;&amp;lt;/table&amp;gt;&lt;br /&gt;&amp;lt;/form&amp;gt;&lt;br /&gt;&amp;lt;/td&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;td&amp;gt;&lt;br /&gt;&amp;lt;h3&amp;gt;頁面三：貼上資料&amp;lt;/h3&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;form&amp;gt;&lt;br /&gt;&amp;lt;table border="1"&amp;gt;&lt;br /&gt;&amp;lt;tr&amp;gt;&lt;br /&gt;&amp;lt;td&amp;gt;owner&amp;lt;/td&amp;gt;&lt;br /&gt;&amp;lt;td&amp;gt;status&amp;lt;/td&amp;gt;&lt;br /&gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;&amp;lt;/table&amp;gt;&lt;br /&gt;&amp;lt;/form&amp;gt;&lt;br /&gt;&amp;lt;/td&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;&amp;lt;/table&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;/body&amp;gt;&lt;br /&gt;&amp;lt;/html&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;C# 原始檔：&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;  /*&lt;br /&gt;   * override BandObjectLib 的 OnExplorerAttached，可於此處設定監聽 browser 的事件&lt;br /&gt;   */&lt;br /&gt;  protected override void OnExplorerAttached(EventArgs ea)&lt;br /&gt;  {&lt;br /&gt;   this.Explorer.DocumentComplete += new DWebBrowserEvents2_DocumentCompleteEventHandler(this.OnDocumentComplete);&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  /*&lt;br /&gt;   * 監聽網頁載入完成的事件&lt;br /&gt;   */&lt;br /&gt;  private void OnDocumentComplete(object frame, ref object urlObj)&lt;br /&gt;  {&lt;br /&gt;   string rooturl = ((this.Explorer as IWebBrowser2).Document as IHTMLDocument2).url;&lt;br /&gt;&lt;br /&gt;   IWebBrowser2 webBrowser = (IWebBrowser2)frame;&lt;br /&gt;   IHTMLDocument2 document = (IHTMLDocument2)webBrowser.Document;&lt;br /&gt;&lt;br /&gt;   //MessageBox.Show("[OnDocumentComplete]\n" + document.title + "\n" + document.url);&lt;br /&gt;&lt;br /&gt;   if(step!=-1)&lt;br /&gt;    startProcess();&lt;br /&gt;  }&lt;br /&gt; &lt;br /&gt;  /*&lt;br /&gt;   * 按鈕一，連到指定頁面&lt;br /&gt;   */&lt;br /&gt;  private void button1_Click(object sender, System.EventArgs e)&lt;br /&gt;  {&lt;br /&gt;   IWebBrowser2 webBrowser = (IWebBrowser2)this.Explorer;&lt;br /&gt;&lt;br /&gt;   object Null = System.Reflection.Missing.Value;&lt;br /&gt;   webBrowser.Navigate("http://127.0.0.1/temp/test.html", ref Null, ref Null, ref Null, ref Null);&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  private int step = -1;&lt;br /&gt;  private string data_owner = "";&lt;br /&gt;  private string data_status = "";&lt;br /&gt;&lt;br /&gt;  /*&lt;br /&gt;   * 按鈕二，開始自動化作業&lt;br /&gt;   */&lt;br /&gt;  private void button2_Click(object sender, System.EventArgs e)&lt;br /&gt;  {&lt;br /&gt;   step = 0;&lt;br /&gt;   startProcess();&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  /*&lt;br /&gt;   * 自動化作業程序&lt;br /&gt;   */&lt;br /&gt;  private void startProcess()&lt;br /&gt;  {&lt;br /&gt;   IWebBrowser2 webBrowser = (IWebBrowser2)this.Explorer;&lt;br /&gt;   IHTMLDocument2 document = (IHTMLDocument2)webBrowser.Document;&lt;br /&gt;&lt;br /&gt;   step++;&lt;br /&gt;&lt;br /&gt;   if(step==1)&lt;br /&gt;   {&lt;br /&gt;    /*&lt;br /&gt;    * 程序一，登入&lt;br /&gt;    */&lt;br /&gt;    HTMLFormElementClass loginForm = document.forms.item(0, 0) as HTMLFormElementClass;&lt;br /&gt;    HTMLInputTextElement uid = loginForm.item("uid", 0) as HTMLInputTextElement;&lt;br /&gt;    HTMLInputTextElement pwd = loginForm.item("pwd", 0) as HTMLInputTextElement;&lt;br /&gt;&lt;br /&gt;    uid.value = "username";&lt;br /&gt;    pwd.value = "password";&lt;br /&gt;&lt;br /&gt;    MessageBox.Show("填入帳密，自動送出！");&lt;br /&gt;    loginForm.submit();&lt;br /&gt;   }&lt;br /&gt;   else if(step==2)&lt;br /&gt;   {&lt;br /&gt;    /*&lt;br /&gt;    * 程序二，為表格建立勾選項目&lt;br /&gt;    */&lt;br /&gt;    HTMLTable sourceTable = (document.all.tags("table") as IHTMLElementCollection).item(1, 0) as HTMLTable;&lt;br /&gt;    for(int i=0; i&amp;lt;sourceTable.rows.length; i++)&lt;br /&gt;    {&lt;br /&gt;     HTMLTableRow row = sourceTable.rows.item(i, 0) as HTMLTableRow;&lt;br /&gt;     row.insertCell(0);&lt;br /&gt;&lt;br /&gt;     HTMLTableCell cell = row.cells.item(0, 0) as HTMLTableCell;&lt;br /&gt;&lt;br /&gt;     if(i==0)&lt;br /&gt;     {&lt;br /&gt;      cell.innerHTML = "&amp;lt;input type='button' name='btnSelected' value='選擇完畢'&amp;gt;";&lt;br /&gt;     }&lt;br /&gt;     else&lt;br /&gt;     {&lt;br /&gt;      cell.innerHTML = "&amp;lt;input type='checkbox'&amp;gt;";&lt;br /&gt;     }&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    HTMLButtonElement btnSelected = document.all.item("btnSelected", null) as HTMLButtonElement;&lt;br /&gt;    HtmlEventProxy.Create("onclick", btnSelected, new System.EventHandler(this.btnSelected_onclick));&lt;br /&gt;    &lt;br /&gt;    MessageBox.Show("請選擇欲複製的項目！");&lt;br /&gt;   }&lt;br /&gt;   else if(step==3)&lt;br /&gt;   {&lt;br /&gt;    /*&lt;br /&gt;    * 程序三，貼上資料&lt;br /&gt;    */&lt;br /&gt;    HTMLTable targetTable = (document.all.tags("table") as IHTMLElementCollection).item(2, 0) as HTMLTable;&lt;br /&gt;    if(copyData!=null){&lt;br /&gt;     for(int i=0; i&amp;lt;copyData.Count; i++){&lt;br /&gt;      &lt;br /&gt;      HTMLTableRow row = targetTable.insertRow(targetTable.rows.length) as HTMLTableRow;&lt;br /&gt;      row.insertCell(0);&lt;br /&gt;      row.insertCell(1);&lt;br /&gt;&lt;br /&gt;      System.Collections.Hashtable data = copyData[i] as System.Collections.Hashtable;&lt;br /&gt;      (row.cells.item(0, 0) as HTMLTableCell).innerText = data["owner"].ToString();&lt;br /&gt;      (row.cells.item(1, 0) as HTMLTableCell).innerText = data["status"].ToString();&lt;br /&gt;     }&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    MessageBox.Show("複製完成");&lt;br /&gt;   }&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  private System.Collections.ArrayList copyData;&lt;br /&gt;&lt;br /&gt;  private void btnSelected_onclick(object sender, EventArgs e)&lt;br /&gt;  {&lt;br /&gt;   /*&lt;br /&gt;   * 程序二，將勾選的項目儲存起來&lt;br /&gt;   */&lt;br /&gt;   IHTMLElement element = ((HtmlEventProxy)sender).HTMLElement as IHTMLElement;&lt;br /&gt;   &lt;br /&gt;   IWebBrowser2 webBrowser = (IWebBrowser2)this.Explorer;&lt;br /&gt;   IHTMLDocument2 document = (IHTMLDocument2)webBrowser.Document;&lt;br /&gt;&lt;br /&gt;   copyData = new System.Collections.ArrayList();&lt;br /&gt;   string msg = "";&lt;br /&gt;&lt;br /&gt;   HTMLTable sourceTable = (document.all.tags("table") as IHTMLElementCollection).item(1, 0) as HTMLTable;&lt;br /&gt;   for(int i=1; i&amp;lt;sourceTable.rows.length; i++)&lt;br /&gt;   {&lt;br /&gt;    HTMLTableRow row = sourceTable.rows.item(i, 0) as HTMLTableRow;&lt;br /&gt;    HTMLTableCell cell0 = row.cells.item(0, 0) as HTMLTableCell;&lt;br /&gt;    HTMLTableCell cell1 = row.cells.item(1, 0) as HTMLTableCell;&lt;br /&gt;    HTMLTableCell cell2 = row.cells.item(2, 0) as HTMLTableCell;&lt;br /&gt;&lt;br /&gt;    bool isChecked = (cell0.getElementsByTagName("input").item(0, 0) as HTMLOptionButtonElement).@checked;&lt;br /&gt;    string owner = cell1.innerText;&lt;br /&gt;    string status = cell2.innerText;&lt;br /&gt;&lt;br /&gt;    if(isChecked)&lt;br /&gt;    {&lt;br /&gt;     System.Collections.Hashtable data = new System.Collections.Hashtable();&lt;br /&gt;     data.Add("owner", owner);&lt;br /&gt;     data.Add("status", status);&lt;br /&gt;&lt;br /&gt;     copyData.Add(data);&lt;br /&gt;     msg += ("owner = " + owner + ", status = " + status + "\n");&lt;br /&gt;    }&lt;br /&gt;    &lt;br /&gt;   }&lt;br /&gt;&lt;br /&gt;   MessageBox.Show("勾選了：\n" + msg);&lt;br /&gt;&lt;br /&gt;   object Null = System.Reflection.Missing.Value;&lt;br /&gt;   webBrowser.Navigate("http://127.0.0.1/temp/test.html", ref Null, ref Null, ref Null, ref Null);&lt;br /&gt;&lt;br /&gt;   ((HtmlEventProxy)sender).Detach();&lt;br /&gt;  }&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4754237190569973724-2690923395572290972?l=blog.ben.idv.tw' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.ben.idv.tw/feeds/2690923395572290972/comments/default' title='張貼意見'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4754237190569973724&amp;postID=2690923395572290972' title='0 個意見'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4754237190569973724/posts/default/2690923395572290972'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4754237190569973724/posts/default/2690923395572290972'/><link rel='alternate' type='text/html' href='http://blog.ben.idv.tw/2008/05/ie-toolbar_8465.html' title='開發 IE 瀏覽器的 Toolbar：半自動程式搭配人為挑選資料'/><author><name>Ben Chang</name><uri>http://www.blogger.com/profile/01921640246111819069</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/_HsFEtLMw5zU/SDvgrxo1N1I/AAAAAAAAFX8/Z-jXecErAno/s72-c/Clipboard01.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4754237190569973724.post-5531822295861350068</id><published>2008-05-27T11:45:00.003+08:00</published><updated>2011-08-02T16:05:40.444+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='.NET'/><category scheme='http://www.blogger.com/atom/ns#' term='Browser'/><title type='text'>開發 IE 瀏覽器的 Toolbar：自動程式</title><content type='html'>經過前幾篇的學習後，已經足以製作一個自動化跨網頁執行的程式了。&lt;br /&gt;&lt;br /&gt;模擬畫面如下，假設有三階段的網頁，第一頁是 login 介面，第二頁是 login 後可以取得的資料來源，第三頁是要將資料複製到其他網站的介面：&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_HsFEtLMw5zU/SDuEPxo1NxI/AAAAAAAAFXc/vwbeT0mDX-s/s1600-h/Clipboard01.jpg"&gt;&lt;img style="cursor:pointer; cursor:hand;" src="http://2.bp.blogspot.com/_HsFEtLMw5zU/SDuEPxo1NxI/AAAAAAAAFXc/vwbeT0mDX-s/s320/Clipboard01.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5204899200914241298" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;HTML 內容如下：&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&amp;lt;html&amp;gt;&lt;br /&gt;&amp;lt;head&amp;gt;&lt;br /&gt;&amp;lt;title&amp;gt;test page&amp;lt;/title&amp;gt;&lt;br /&gt;&amp;lt;/head&amp;gt;&lt;br /&gt;&amp;lt;body&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;table&amp;gt;&lt;br /&gt;&amp;lt;tr valign="top"&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;td&amp;gt;&lt;br /&gt;&amp;lt;h3&amp;gt;頁面一：登入&amp;lt;/h3&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;form&amp;gt;&lt;br /&gt;uid: &amp;lt;input type="text" name="uid"&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;pwd: &amp;lt;input type="text" name="pwd"&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;&amp;lt;input type="submit"&amp;gt;&lt;br /&gt;&amp;lt;/form&amp;gt;&lt;br /&gt;&amp;lt;/td&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;td&amp;gt;&lt;br /&gt;&amp;lt;h3&amp;gt;頁面二：複製資料&amp;lt;/h3&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;form&amp;gt;&lt;br /&gt;owner:&amp;lt;br&amp;gt;&lt;br /&gt;&amp;lt;input type="text" name="owner" value="邦邦"&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;status:&amp;lt;br&amp;gt;&lt;br /&gt;&amp;lt;textarea name="status" rows="5" cols="20"&amp;gt;&lt;br /&gt;測試123&lt;br /&gt;測試456&lt;br /&gt;測試789&lt;br /&gt;&amp;lt;/textarea&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;&amp;lt;input type="submit"&amp;gt;&lt;br /&gt;&amp;lt;/form&amp;gt;&lt;br /&gt;&amp;lt;/td&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;td&amp;gt;&lt;br /&gt;&amp;lt;h3&amp;gt;頁面三：貼上資料&amp;lt;/h3&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;form&amp;gt;&lt;br /&gt;owner:&amp;lt;br&amp;gt;&lt;br /&gt;&amp;lt;input type="text" name="owner2"&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;status:&amp;lt;br&amp;gt;&lt;br /&gt;&amp;lt;textarea name="status2" rows="5" cols="20"&amp;gt;&amp;lt;/textarea&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;&amp;lt;input type="submit"&amp;gt;&lt;br /&gt;&amp;lt;/form&amp;gt;&lt;br /&gt;&amp;lt;/td&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;&amp;lt;/table&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;/body&amp;gt;&lt;br /&gt;&amp;lt;/html&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;C# 的原始碼如下：&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&lt;br /&gt;  /*&lt;br /&gt;   * override BandObjectLib 的 OnExplorerAttached，可於此處設定監聽 browser 的事件&lt;br /&gt;   */&lt;br /&gt;  protected override void OnExplorerAttached(EventArgs ea)&lt;br /&gt;  {&lt;br /&gt;   this.Explorer.DocumentComplete += new DWebBrowserEvents2_DocumentCompleteEventHandler(this.OnDocumentComplete);&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  /*&lt;br /&gt;   * 監聽網頁載入完成的事件&lt;br /&gt;   */&lt;br /&gt;  private void OnDocumentComplete(object frame, ref object urlObj)&lt;br /&gt;  {&lt;br /&gt;   string rooturl = ((this.Explorer as IWebBrowser2).Document as IHTMLDocument2).url;&lt;br /&gt;&lt;br /&gt;   IWebBrowser2 webBrowser = (IWebBrowser2)frame;&lt;br /&gt;   IHTMLDocument2 document = (IHTMLDocument2)webBrowser.Document;&lt;br /&gt;&lt;br /&gt;   //MessageBox.Show("[OnDocumentComplete]\n" + document.title + "\n" + document.url);&lt;br /&gt;&lt;br /&gt;   if(step!=-1)&lt;br /&gt;    startProcess();&lt;br /&gt;  }&lt;br /&gt; &lt;br /&gt;  /*&lt;br /&gt;   * 按鈕一，連到指定頁面&lt;br /&gt;   */&lt;br /&gt;  private void button1_Click(object sender, System.EventArgs e)&lt;br /&gt;  {&lt;br /&gt;   IWebBrowser2 webBrowser = (IWebBrowser2)this.Explorer;&lt;br /&gt;&lt;br /&gt;   object Null = System.Reflection.Missing.Value;&lt;br /&gt;   webBrowser.Navigate("http://127.0.0.1/temp/test.html", ref Null, ref Null, ref Null, ref Null);&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  private int step = -1;&lt;br /&gt;  private string data_owner = "";&lt;br /&gt;  private string data_status = "";&lt;br /&gt;&lt;br /&gt;  /*&lt;br /&gt;   * 按鈕二，開始自動化作業&lt;br /&gt;   */&lt;br /&gt;  private void button2_Click(object sender, System.EventArgs e)&lt;br /&gt;  {&lt;br /&gt;   step = 0;&lt;br /&gt;   startProcess();&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  /*&lt;br /&gt;   * 自動化作業程序&lt;br /&gt;   */&lt;br /&gt;  private void startProcess()&lt;br /&gt;  {&lt;br /&gt;   IWebBrowser2 webBrowser = (IWebBrowser2)this.Explorer;&lt;br /&gt;   IHTMLDocument2 document = (IHTMLDocument2)webBrowser.Document;&lt;br /&gt;&lt;br /&gt;   step++;&lt;br /&gt;&lt;br /&gt;   if(step==1)&lt;br /&gt;   {&lt;br /&gt;    /*&lt;br /&gt;    * 程序一，登入&lt;br /&gt;    */&lt;br /&gt;    HTMLFormElementClass loginForm = document.forms.item(0, 0) as HTMLFormElementClass;&lt;br /&gt;    HTMLInputTextElement uid = loginForm.item("uid", 0) as HTMLInputTextElement;&lt;br /&gt;    HTMLInputTextElement pwd = loginForm.item("pwd", 0) as HTMLInputTextElement;&lt;br /&gt;&lt;br /&gt;    uid.value = "username";&lt;br /&gt;    pwd.value = "password";&lt;br /&gt;&lt;br /&gt;    MessageBox.Show("填入帳密，自動送出！");&lt;br /&gt;    loginForm.submit();&lt;br /&gt;   }&lt;br /&gt;   else if(step==2)&lt;br /&gt;   {&lt;br /&gt;    /*&lt;br /&gt;    * 程序二，複製資料&lt;br /&gt;    */&lt;br /&gt;    HTMLFormElementClass sourceForm = document.forms.item(1, 0) as HTMLFormElementClass;&lt;br /&gt;    HTMLInputTextElement owner = sourceForm.item("owner", 0) as HTMLInputTextElement;&lt;br /&gt;    HTMLTextAreaElement status = sourceForm.item("status", 0) as HTMLTextAreaElement;&lt;br /&gt;&lt;br /&gt;    data_owner = owner.value;&lt;br /&gt;    data_status = status.value;&lt;br /&gt;&lt;br /&gt;    MessageBox.Show("複製資料：\nowner=" + data_owner + "\nstatus=" + data_status + "\n到目標網頁！");&lt;br /&gt;&lt;br /&gt;    object Null = System.Reflection.Missing.Value;&lt;br /&gt;    webBrowser.Navigate("http://127.0.0.1/temp/test.html", ref Null, ref Null,
