2006續約的考量

本來有想要把線路升級成 2M/256k,可是在仔細考量之後,發現我根本用不到那麼多,所以決定還是維持原樣:1M/64k。
然後把月繳改為年繳,預期可以更省下一些上網費用。
1M/64k:
月繳:219 x 12 = 2628
年繳:2292
2628 – 2292 = 336
電路費:410 x 12 = 4920
如果是用 2M/256k:
月繳:259 x 12 = 3108
年繳:2688
3108 – 2688 = 420
電路費:440 x 12 = 5280

Porting

也許移植一個 .Net application 到其他平台上,並不如想像中容易。
正如 Java application 並不是 100% 的 run anywhere。
Mono專案的頭頭最近把Paint.NET移植到 Linux 的Mono上,你可以看看這篇他的文章:Porting Paint.NET to Mono
看到這個標題,我是很高興的,可是看完以後,發現移植的過程曲折離奇,其中的過程頗值得玩味。

new之後,constructor之前

昨天在代碼裡面看到一個從沒看過的用法,如下列紅色標示部份:

#include <iostream>

class MyBase {
  protected:
    int _id;

  public:
    MyBase():_id(0) {}
    MyBase( int id ):_id(id) {}
    int getId() {return _id; }
};

class MyClass: public MyBase {
  public:
    MyClass() {}
    MyClass( int id ):MyBase( id ) {}
};

int myclass_mem[ sizeof(MyClass)/sizeof(int) ];

using namespace std;

MyBase* test()
{
  return new (myclass_mem)MyClass( 100 );// 這裡 (1)
  //return new MyClass( 100 ); // (2)
}

int
main( int argc, char* argv[] )
{
  int len = sizeof( myclass_mem );
  cout << "The size of myclass_mem is " << len << endl;
  cout << "content of myclass_mem" << endl;
  for( int i=0; i<len; i++ )
    cout << myclass_mem[i] << ” “;
  cout << endl;

  MyBase* base = ::test();
  cout << base->getId() << endl;

  cout << "content of myclass_mem" << endl;
  for( int i=0; i<len; i++ )
    cout << myclass_mem[i] << ” “;
  cout << endl;
}

以執行的結果來說,我實在是分辨不出來 (1) 與 (2) 有甚麼分別。
後來我用 gcc -S 去分別產生組合語言碼,總算是大致猜到了,原來以 (1) 的方法來寫,會把 new 以後的結果也複製到 myclass_mem 這個陣列裡面。
所以加上輸出 myclass_mem 內容的程式碼,再分別產生執行檔來看執行結果就很清楚了。
真是特別。

好人卡

沒事去參加團購,買了這個,準備當作禮物送人…
誰會是第一個好人?
好人卡拆箱照(1)
好人卡拆箱照(2)
好人卡拆箱照(3)

taglist的安裝與使用

自從使用 ctags 以後,看code方便多了。最近又看到taglist,心想或許可以讓看code的生活變得更美好,所以就來摸索看看。
首先到這裡下載最新版本。
解開以後,有兩個目錄,一個是 doc,另外一個是 plugin,把他們複製到你的 HOME 的 vimfiles 目錄下(舉例:c:\documents and settings\your_name\vimfiles\),然後在你的 _vimrc 裡面指定 Tlist_Ctags_Cmd 變數,這是用來讓 taglist 知道 ctags 的路徑。
我是把 ctags.exe 放在 c:\tools 下,所以是這樣寫:

let Tlist_Ctags_Cmd=’c:\tools\ctags.exe’

這樣就大功告成了。
使用的時候,

  • 用 :TlistOpen 指令把 taglist 視窗叫出來,用 :TlistClose 指令關閉 taglist 視窗
  • 用 :TListToggle 來打開或關閉 taglist 視窗
  • 可以用 ctrl-w h 與 ctrl-w l 來切換 taglist 視窗與編輯視窗
  • 開啟檔案以後,taglist會自動把 tag 資訊列在左邊視窗。


備註:
我沒在 Linux 下用過,安裝方法應該差不多;記得把 HOME 替換為 /home,vimfiles/ 替換為 .vim/。
Console 模式下,有比較特別,文件說,因為 terminal/console 不支援變動視窗寬度,所以要設置 Tlist_Inc_Winwidth 為 0。

快和星一樣笨

今天看到這則新聞,看完以後只有幾個感想:
1. 爛標題:快和星一樣笨,我很難聯想到”星”是指新加坡。看完以後,才發現原來說的是歷史教材,或許是說新加坡的歷史教材較差,但是不懂歷史等於笨?
2. 甚麼是”誰對民主政治毫無貢獻”的標準答案?一個爛題目再加上一個爛解答…
我輸了…Orz…
Yahoo!News1146216958992

資料繫結與巡覽

資料的繫結基本上都是靠 Controls.DataBindings,所以

text1.DataBindings.Add( new Binding(“Text”, ds, “customers.custNo”) );

就可以把 text1 這個控制項的 Text 屬性繫結到 ds.Tables[“customers”] 的 custNo 欄位上。
如果想要有一些處理與變化,那麼可以透過 Binding.Format 與 Binding.Parse:

Binding b=new Binding(“Text”, ds, “customers.custOrder.OrderAmount”);
b.Parse+=new ConvertEventHandler( currencyStringToDecimal); // currencyStringToDecimal 是自訂的
b.Format+=new ConvertEventHandler( DecimalToCurrencyString ); // DecimalToCurrencyString 也是…
text3.DataBindings.Add(b);

這表示在轉換控制項屬性到資料來源的時候,會透過這兩個事件作變化。
Parse 表示控制項到資料來源,而 Format 正好相反。
都繫結上了以後呢?我們可以透過 BindingManagerBase 來作巡覽。

BinderManagerBase bm = BindingContext[ dataset, “tablename” ];

此時可用 bm.Position 取得位置,bm.Current 取得當前的物件(如果資料來源是 datatable,那就是 DataRowView;若是陣列,那就是所指向的元素)
bm.Position+1 就是下一筆,反之則是上一筆。到了最後一筆的時候,bm.Position+1 以後仍然會是一樣。
那麼,位置移動的時候會觸發甚麼事件?PositionChanged。所以我們可以撰寫自己的處理事件,

PositionChanged+=new EventHandler( this.fmMain_PositionChanged )

不僅僅是 TextBox 可以作,只要有提供 DataBindings 屬性的控制項都可以。
把 Button 的 Text 屬性 Bind 到某資料來源的某欄,而 Enable 屬性又 Bind 到 某欄時,那麼當移動資料來源位置的時候,就可以讓 Button 的相關狀態自動改變了。
這讓我想到似乎可以作一些 state machine 的東西…

IDeserializationCallback.OnDeserialization()

在 deserialization 之後,需要做的一些處理可以寫在這裡。
.Net framework documentation 裡面的例子是以 Circle 類別作例子,圓的面積不 serialize,而是在 deserialize 之後再計算出來。

霍元甲

這部電影應該可以拍的更深沉,我想或許該拍的都拍了吧,只是沒剪出來。
這是蠻可惜的。
覺得裏面挺不錯的幾句話:

  • 人心裡不好受,就得哭,哭完了,你還得上路。
  • 人呀,要時常洗洗自己,這樣才能清爽地走在世上。
  • 秧苗也是有生命的,它們之間不能靠得太近,近了就會妨礙生長,就像我們人,生活中要懂得互相尊重,這樣大家才能活得平安快樂。
  • 茶品的上下高低,並不是由茶來對我們說,倒是由人來決定的,不同的人有不同的選擇。
  • 喝茶是一種心情,如果你心情中了,茶的高低還有這麼重要嗎?
  • 最可怕的競技在自己內心?

NAnt (2)

看完上一篇,你大概會想,要寫的 task 是如此之少,這真是太完美了。
但是對於笨Q來說,不幸的事情發生了…
笨Q 聽說 .Net 也移植到 Linux 上了,所以他想試試看把上篇的程式拿到 Linux 下編譯,於是笨 Q 安裝了 Mono。接著安裝 NAnt。
同樣他下載了 NAnt, 並且解開,放到 /opt/nant 下。
再把整個專案複製到 Linux 下,並且修改了一下 build 檔的內容,由

<property name=”nant.settings.currentframework” value=”net-1.1″/>

改為

<property name=”nant.settings.currentframework” value=”mono-1.0″/>

讓 NAnt 在建立專案前自動把編譯環境切換為 mono。
接著輸入
$mono /opt/nant/bin/NAnt.exe
這時只見 NAnt 很不爭氣的吐了一句:

Invalid element <solution>. Unknown task or datatype

笨Q 只能流淚默默接受這個事實,他知道必須自己學著寫 target。


一個 NAnt 的 build 檔案其實是一個 XML 檔案,最基本的元素是 project,project 則是由 target 與 property 組成的,而 target 則是由許多的 task 組成的。
所以一個空的 build 檔案是長這個樣子:
<?xml version="1.0"?>
<project name="dnsedu" default=“build”>
  <property name=“nant.settings.currentframework” value=“net-1.1″/>
  <target name=“build” description="Default build target" depends="dnsedu">
  </target>
</project>
那麼 target 裡面有哪些 task 可以用呢?你可以參考官方網站的這裡
裡面真的很多 task,除了基本編譯(csc, vbc, cl, al, ilasm, resgen)之外,他還有 copy, cvs, mail, nunit …等等的 task,絕對可以讓你組合出你想要的東西。
要改寫上篇的 build(我假設你用 c#),我們會用到 csc、mkdir 這兩個主要的 task。
以下是改寫好的 build 檔案
<project name="your_project" default="build">
  <property name="nant.settings.currentframework" value="mono-1.0"/>
  <property name="debug" value="false"/>
  <target name="build">
    <mkdir dir="bin" unless="${directory::exists(‘bin’)}" />
    <csc target="winexe" output="bin/your_project.exe" debug="${debug}">
      <sources>
        <include name="*.cs"/>
      </sources>
      <references>
        <include name="System.Drawing.dll" />
        <include name="System.Data.dll" />
        <include name="System.Windows.Forms.dll"/>
      </references>
      <resources>
        <include name="*.resx"/>
      </resources>
    </csc>
  </target>
</project>
mkdir task 這邊我使用了 unless,意思是 if not,所以意思就是當目錄不存在的時候,就建立一個。這裡判斷目錄是否存在的函數是 NAnt 內建的,想知道有哪些函數可用,可以參考NAnt官方網站的這邊
csc task 裡面,則需要指定輸出類型(target),輸出檔名(output)以及要不要包含除錯資訊(debug)。
夾在 <csc></csc> 裡面的,就是指定你 c# 程式,所引用(或參考)到的組件以及所使用的資源檔。
很簡單,對吧~
這就是最基本的囉,下次我們來談談 web 應用程式的部份。