網頁

2009年5月11日星期一

Facebook for your Windows Mobile 6 phone

New from Windows Mobile: a Facebook application for your phone! Download the new Facebook application for Windows Mobile and:

* Send messages to any of the people in your Friends list.
* Take pictures and videos on your phone, then upload them right to Facebook.
* Send messages or call people in your Friends list.
* Manage your profile and post anytime, anywhere.

Keep up with the latest news and posts with Facebook on your phone. Now your status updates can be up-to-the moment accounts of what you’re doing. Photos and videos are about as close to live-action as you can get. Show your friends what you’re up to, while you’re out and about.


Download Facebook for Windows Mobile 6

WordPress PlugIn - Facebook Album on WordPress

如果你Hosting空間不太夠,或者Bandwidth不夠多而放棄在WordPress建立相簿的話,
可以試試這個WP PlugIn - FotoBook

它可以把你在Facebook上所建立的Album,放在你的WordPress上,最好的地方是Image Source直接用返FaceBook的,換句話說你不用擔心流量有多大。
雖然Facebook似乎可以無限量建立相簿和上傳圖片,但暫時依然限制一個相簿只可以存放60張圖。而且Facebook的Simple Image Uploader或者Java Image Uploader都非常唔方便。 所以如果真是大量圖片的話,可能就不太適合了。

FotoBook
http://wordpress.org/extend/plugins/fotobook/
FotoBook photo gallery demo:
http://www.aaronharp.com/photo-gallery/

jQuery + Visual Studio IntelliSense Error 解決方法

今天公司機的Visual Web Developer 2008出現:
"更新 JScript IntelliSense 時發生錯誤"

Documents\Visual Studio 2008\WebSites\{project}\js\jquery-1.3.2.min.js: 
Object doesn't support this property or method @ 18:9345..."

2009510_5.png

雖然我已經有安裝HotFix,但都沒有效。

jQuery + ASP.NET Web Service : data.d or not d?

之前講過,當使用jQuery CallBack ASP.NET Web Service後,假設Data部份,我用"response"做名稱的話,我便可以用each()方法去extract "response"的values.

ASP.NET 2.0的做法:
$.each(Sys.Serialization.JavaScriptSerializer.deserialize(response), function(key, item) {
alert(item.ProductModel + ' / ' + item.Description);
});

以上做法本應是沒有錯誤的,但如果是ASP.NET 3.5的情況下,便會出現錯誤 :
"Sys.ArgumentTypeException: Object of type 'Object' cannot be converted to type 'String'.
Parameter name: data"

即使你使用的不是deserialize()方法,而是eval(),都會出現undefined.
2009510_1.png

這問題搞了我兩天,因為我公司是用ASP.NET 2.0平台,而我家中是3.5平台。程式碼肯定就沒有問題,因為Web Service部份已經設定return成string,而一直都不為意3.5的Web Service會override return的DataType。幸好在Firebug發現了奇妙的"d" :

ASP.NET 2.0, 在Firebug顯示的return values (response) , 在IE8的Develper Tools顯示DataType為String。
2009510_2.png
2009510_3.png

ASP.NET 3.5, 在Firebug顯示的return values (response) , DataType為Object,底下還有"d"的member。
2009510_4.png

所以最後觸發到我用"response.d"去得出string的值。上網找找"d"是什麼東西,原來也有人遇到同樣問題。
A breaking change between versions of ASP.NET AJAX | Encosia
特別要看看這個comment,完美解釋"d"是什麼東西:

2009年5月10日星期日

最簡單的字幕校正工具-SubResync

我一向對影音編輯都很陌生,網上下載影片,用MPC觀看就每天都做的事。

但字幕製作就完全一曉不通,安裝Codec Pack後,基本上都不用再做其他事就播放,使用MPC或VLC的話,字幕檔都自動載入。
有時下載一些電影後,上射手網未必找到適合版本的字幕。

不同的影片來源或者不同的Frame Rate,字幕檔案都有不同。
使用不相容的字幕,時間軸就有機會與影片不同步,

一直以來我都唯有硬住頭皮去睇這些影音和字幕不同步的片,有想過校正字幕,但又覺得很煩,而且又要安裝其他軟件,今天的起心肝找找有沒有最簡單的軟件可以做到。
原來這軟件一直都在我的電腦,就是VobSub的SubResync,如果你有安裝如K-Lite Codec Pack , PureCodec等等Codec Pack的話,你的電腦幾乎是一定有SubResync的,因為這是VobSub Bundle的程式。

如果找不到,你可以試下搜尋你電腦的檔案,有沒有subresync.exe。
如果真的沒有就上Videohelp下載VobSub吧。

軟件支援字幕格式十分多,幾乎流行的如idx,srt,sub等等都支援。

使用方法

使用方法真的很簡易,正常地看影片,即使字幕不同步,找一句你明白的英文,再記住與它相對的對白,記住播放時間。
然後去SubResync打開字幕檔,在約莫時間找到相對的字幕。

看看Timeline時間,
如果字幕快10秒的話,就在第一行時間上單Click,加上10秒,SubResync會自動把之後的加上10秒 ;
如果是慢10秒的話,就在最後那一行時間上單Click,再減10秒。
再重新載入至影片中,看看是否同步,不是的話重覆以上步驟微調。


雖然是小小的程式,但真的解救萬民。
subresync.png

2009年5月9日星期六

jQuery教學(4) - jQuery 使用 ASP.NET Web Service 示範

上次講解jQuery如何對一些Web Service / API進行deserialize Json , 今次我會承接下去示範如何用jQuery去呼叫ASP.NET 3.5 Web Service,並利用jQuery UI做出很正的UI。其實除了官方的jQuery UI,還有很多不同的jQuery Plugin都是比原本ASP.NET的Web Control更漂亮。而且由於ASP.NET MVC沒有Server Control,所以學習使用一些JS Framework的UI以應付未來的Web開發是必須的。

Web Service方面是使用LINQ-to-SQL,並把DataTable Serialize後回傳給jQuery。
Database方面則使用AdventureWorks Sample DB。
下載:AdventureWorks Sample DB
下載:jQuery UI
下載:範例的Source Code

運行時的畫面:
20090905_jqueryui.png

程式碼方面其實不複雜,我還是直接貼上Source Code,註解一下比較重要的部份。

Web Service部份:
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.SqlClient;
using System.Web;
using System.Web.Services;

[WebService(Namespace = "http://tempuri.org/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
[System.Web.Script.Services.ScriptService]
public class getDataTable : System.Web.Services.WebService {
    [WebMethod]
    public string getProducts()
    {
        DataTable dt = new DataTable();
        using (SqlConnection MyConnection = new SqlConnection("Data Source=LocalHostSQLEXPRESS;Initial Catalog=AdventureWorks;Integrated Security=SSPI;"))
        {
            MyConnection.Open();
            string MySelect = "SELECT TOP 20 [ProductModel] , [Description] FROM Production.vProductAndDescription WHERE CultureID='en' GROUP BY [ProductModel] , [Description] ";
            SqlCommand MyCommand = new SqlCommand(MySelect, MyConnection);
            using (SqlDataAdapter da = new SqlDataAdapter(MyCommand))
            { da.Fill(dt); }
        }
        return GetJson(dt);
    }

    public string GetJson(DataTable dt)
    {
        System.Web.Script.Serialization.JavaScriptSerializer serializer = new System.Web.Script.Serialization.JavaScriptSerializer();
        List<Dictionary<string, object>> rows = new List<Dictionary<string, object>>();
        Dictionary<string, object> row;
        foreach (DataRow dr in dt.Rows)
        {
            row = new Dictionary<string, object>();
            foreach (DataColumn col in dt.Columns)
            { 
                row.Add(col.ColumnName, dr[col]);
            }
            rows.Add(row);
        }
        return serializer.Serialize(rows);
    }

}

頁面的jQuery 使用Ajax CallBack 部份:
    <script type="text/javascript">

        // Init jQuery UI
        $(function init() {
            // Initialize Accordion
            $("#accordion").accordion({ header: "h3" });
            // Initialize Slider
            $('#slider').slider({ min: 1, max: 20,
                slide: function (event, ui) { $('#limit').html(ui.value); }
            });
        });

        $(document).ready(function () {
            // jQuery Ajax CallBack
            $("#lnkGetProducts").click(function () {
                // Setup the Options for jQuery Ajax
                var Options = {
                    type: "POST",
                    url: "getDataTable.asmx/getProducts", // invoke web service
                    data: "{dummyKey: '" + "dummyVal" + "'}", // dummyKey and dummyVal can be remove.
                    contentType: "application/json; charset=utf-8",
                    dataType: "json",
                    success: function (response) {
                        if (response != "") {
                            var s = '<div id="accordion">';
                            var limit = $("#limit").html(); // the slider value to limit result output.
                            $.each(Sys.Serialization.JavaScriptSerializer.deserialize(response.d), function (key, item) {
                                s += '<div>';
                                s += '<h3><a href="#">' + item.ProductModel + '</a></h3>';
                                s += '<div>' + item.Description + '</div>';
                                s += '</div>';
                                if (key == limit - 1) return false; // if reach limit , return and exit.
                            });
                            s += '</div>';
                            $('#container').html(s); // fill s into container div
                            init(); // Initialize jQuery UI again when the DOM is changed.
                        }
                    }
                };
                $.ajax(Options); // Execute and CallBack
            });

        });
    </script>

就整份文件來說,比較難理解的或者是Javascipt中Line 27的"response.d",或者你會想問"d"這個member是什麼呢?
其實有"d"與否是關係到ASP.NET 2.0 和3.5之間的Web Service回傳的DataType問題。
將會在下一篇文章講解。
如果你是ASP.NET 2.0的話,就要刪除".d",相反是3.5的話就要保留。要不然會發生Object 和 String的DataType轉型錯誤。

對抗iPhone App Store - Windows Mobile也有Marketplace

Microsoft前日開設Marketplace,跟Apple App Store差不多,都是賣手機上的Game/Software。日前正式接受開發人員註冊,開發人員要支付99美元的年費,而分紅方面,MS會抽售價的3成。目前未正式開張,只是接受註冊。但WM都有好多年,現在才搞...其實真的有點遲....而且還要抽3成佣....

Windows Mobile Marketplace :
http://developer.windowsmobile.com/

如何設定 SQL Server 2005 Driver for PHP

節錄於 邊做邊學 如何設定 SQL Server 2005 Driver for PHP 執行環境
雖然 PHP 提供了 mssql_* 函式,可用來存取 Microsoft SQL Server 資料庫,但實際效果經常不盡理想,尤其對較新版本 SQL Server 的支援常常慢了半拍。這對各自擁有廣大使用族群、且又經常需要以 PHP 存取 SQL Server 的開發人員來說,實在很困擾--直到微軟自己開發 SQL Server 2005 Driver for PHP。
使用 PHP 內建的 mssql_* 函式存取 SQL Server 資料庫常有許多問題,可能是中文變亂碼或不支援某些資料型別,尤其只支援到 SQL Server 6.5 (MSSQL Library 7.0 ),無法善用 SQL Server 2005/2008 的新功能。
為了讓 PHP 環境能有更好的 SQL Server 存取方式,微軟在 2007 年開始發展 SQL Server 2005 Driver for PHP ,這是 PHP 5 的擴充程式(extension ),能讓 PHP 程式讀寫 SQL Server 裡的資料。值得一提的是,微軟不僅公開釋出 SQL Server 2005 Driver for PHP 的二進位檔,也以 Microsoft Publlic License (Ms-PL )釋出 SQL Server 2005 Driver for PHP 原始程式碼。

更多 : http://msdn.microsoft.com/zh-tw/windowsserver/dd794783.aspx

2009年5月6日星期三

jQuery教學(3) - Deserialization of Json

Json (讀音-Jason,不要讀做J-S-On啊...http://en.wikipedia.org/wiki/JSON)
如果要用jQuery以Ajax存取Database,以ASP.NET為例,無論是使用Page Method或者Web Service時,普遍都是Return Json格式的。與XML相比,Json格式沒有Tag,大大減小資料的大小。使用逗號分隔資料;冒號區分Keys/Values,可讀性不遜於XML。

Json格式的例子:
[
   {"Name":"Visual Studio Express","Type":"Dev IDE","License":"Free"},
   {"Name":"WordPress","Type":"Blog System","License":"Open Source"},
   {"Name":"WinRAR","Type":"Archive","License":"Commercial"},
   {"Name":"iTunes","Type":"Music Player","License":"Free"},
   {"Name":"FileZilla","Type":"FTP Tool","License":"Open Source"}
]

甚至部份網上服務的API,除XML格式外,還會直接提供CallBack Json格式。目的就是盡量減小Data的大小,而且可以直接讓很多不同的Javascript Framework讀取。
以Flickr相簿為例 :
API Service Url : http://api.flickr.com/services/feeds/photos_public.gne?tags=hongkong&tagmode=any&format=json

用Notepad打開photos_public.gne就可以見到是Json字串。

Deserialize
要解開Json格式資料,就要進行Deserialize把Json轉至類似C#的Enumeration Types,不同的是Json格式的Key是可以重複的。

可能你會發現jQuery有serialize() Method,但沒有deserialize(),原因不是作者懶...而是沒有需要。
因為要做Deserialize可以有三個方法(當然還有很多,不能盡錄),分別是:
Javascript本身的eval() / Json官方的json_parse() 以及 Microsoft ASP.NET AJAX Library下的Sys.Serialization.JavaScriptSerializer.deserialize

Eval()
<html>
<head>
    <title></title>
    <script type="text/javascript" src="http://code.jquery.com/jquery-latest.min.js"></script>
    <script type="text/javascript">
        $(document).ready(function () {
            var $strJson = '[';
            $strJson += '{"Name":"Visual Studio Express","Type":"Dev IDE","License":"Free"},';
            $strJson += '{"Name":"WordPress","Type":"Blog System","License":"Open Source"},';
            $strJson += '{"Name":"WinRAR","Type":"Archive","License":"Commercial"},';
            $strJson += '{"Name":"iTunes","Type":"Music Player","License":"Free"},';
            $strJson += '{"Name":"FileZilla","Type":"FTP Tool","License":"Open Source"}';
            $strJson += ']';
            $.each(eval($strJson), function (key, item) {
                $("body").append(item.Name + ' / ' + item.Type + ' / ' + item.License + '<br />');
            });
        });
    </script>
</head>
<body>
    <!--
Output Result:
Visual Studio Express / Dev IDE / Free
WordPress / Blog System / Open Source
WinRAR / Archive / Commercial
iTunes / Music Player / Free
FileZilla / FTP Tool / Open Source
-->
</body>
</html>

json_parse()
<html>
<head>
<title></title>
<script type="text/javascript" src="http://code.jquery.com/jquery-latest.min.js"></script>
<script type="text/javascript" src="http://www.json.org/json_parse.js"></script>
<script type="text/javascript">
    $(document).ready(function () {
        var $strJson = '[';
        $strJson += '{"Name":"Visual Studio Express","Type":"Dev IDE","License":"Free"},';
        $strJson += '{"Name":"WordPress","Type":"Blog System","License":"Open Source"},';
        $strJson += '{"Name":"WinRAR","Type":"Archive","License":"Commercial"},';
        $strJson += '{"Name":"iTunes","Type":"Music Player","License":"Free"},';
        $strJson += '{"Name":"FileZilla","Type":"FTP Tool","License":"Open Source"}';
        $strJson += ']';
        $.each(json_parse($strJson), function (key, item) {
            $("body").append(item.Name + ' / ' + item.Type + ' / ' + item.License + '<br />');
        });
    });
</script> 
</head>
<body>
<!--
Output Result:
Visual Studio Express / Dev IDE / Free
WordPress / Blog System / Open Source
WinRAR / Archive / Commercial
iTunes / Music Player / Free
FileZilla / FTP Tool / Open Source
-->
</body>
</html>

deserialize()
<%@ Page Language="VB" AutoEventWireup="false" CodeFile="Default.aspx.vb" Inherits="_Default" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head id="Head1" runat="server">
    <title></title>
    <script type="text/javascript" src="http://code.jquery.com/jquery-latest.min.js"></script>
    <script type="text/javascript">
        $(document).ready(function () {
            var $strJson = '[';
            $strJson += '{"Name":"Visual Studio Express","Type":"Dev IDE","License":"Free"},';
            $strJson += '{"Name":"WordPress","Type":"Blog System","License":"Open Source"},';
            $strJson += '{"Name":"WinRAR","Type":"Archive","License":"Commercial"},';
            $strJson += '{"Name":"iTunes","Type":"Music Player","License":"Free"},';
            $strJson += '{"Name":"FileZilla","Type":"FTP Tool","License":"Open Source"}';
            $strJson += ']';
            $.each(Sys.Serialization.JavaScriptSerializer.deserialize($strJson), function (key, item) {
                $("body").append(item.Name + ' / ' + item.Type + ' / ' + item.License + '<br />');
            });
        });
    </script>
</head>
<body>
    <form id="form1" runat="server">
    <div>
        <!--Place a ScriptManager for Sys NameSpace-->
        <asp:ScriptManager ID="ScriptManager1" runat="server" />
    </div>
    </form>
</body>
</html>

你可以見到其實三種方法使用上分別不大,唯一注意的是如果使用Microsoft的,緊記放上ScriptManager。它會自動load入ASP.NET AJAX library 和 script files。

如果要我說,會用那種方法。我想比較小的資料會直接用eval()就可以了。如果是很多資料的話,會用Microsoft的,因為Microsoft的Ajax library原本是給Webforms上的Ajax使用。而Ajax control Toolkit都是使用它,所以處理大量資料下的效能,應該會較優勝。

WP Plugin - SyntaxHighlighter Evolved

起初用WordPress時,Syntax Highlight Plugin是用SyntaxHighlighter Plus,都是用最好的SyntaxHighlighter Core(連Google / Microsoft都是用它),後來不知什麼原故,可能是和Theme相撞,走位情況十分嚴重。之後唯有轉用WP-Syntax,但WP-Syntax的高亮度其實很多錯誤,就Javascript來說,經常把Comment string和真正的Code混為一談。而且高亮度的顏色實在太怪,雖然有一些Hack如Wp-Syntax Hacktify,但都只是改變顏色而已,Syntax間的誤會解決不了。而且相信是GeSHi Core問題。

今日再次找找,原來SyntaxHighlighter已經更新到2.0,而且解決了之前的問題。
有兩個Plug-in都是用2.0 Core的,
一個是SyntaxHighlighter Plus ,另一個是SyntaxHighlighter Evolved
其實兩者分別不大,但似乎SyntaxHighlighter Evolved更新得較快,所以我選擇了它。

效果可以上上Demo Page睇睇 : http://alexgorbatchev.com/wiki/SyntaxHighlighter:Demo

2009年5月1日星期五

Avast : Standard shield provider not found

免費防毒軟件中我只考慮三隻 - Avast Home Edition / AVG Free / Avira AntiVir Personal ,之前用WinXP+Avast一直相安無事,但係自從2008-6月轉左行Vista 64Bit後,就再冇用Avast,原因就係呢個"Standard shield provider not found",Vista總是話我冇防毒,雖然Avast似乎都是正常運作,不過個Windows睇落就冇咁靚仔。記得當時我試過AVG Free都是一樣,Vista都是出Warning話Anti-Virus有問題。所以自2008-6月到今天,我都是使用AntiVir。今天心血來潮再試試Avast / AVG。

Avast依然唔得,但奇怪我上Google又Search唔到中文Vista+64Bit既人用Avast有呢個問題,不過好在AVG已經可以正常工作,而且之前果個Web Scan功能都冇再咁慢,可以一用。
順便貼埋AVG Free + Windows Live Messenger Scan File既Setting:
http://www.avg.com/us.90495
avast_error_onvista64bit.png