2008年12月30日 星期二

static vs. shared in VB.Net

在C++中stitic修飾詞有兩個主要功能

1)在fuction中修飾區域變數,讓這個變數的value不會在離開function後就從記憶體中消失
也就是可以保留前一次function留下的"痕跡"
2)在class定義中修飾class member,讓這個member由該class的所有instance共用

但是在VB.Net這兩個功能被拆成兩個修飾詞,分別是"Static"與"Shared"
以下簡述它的特性
Static:
MSDN說明:Normally, a local variable in a procedure ceases to exist as soon as the procedure stops. A static variable continues to exist and retains its most recent value. The next time your code calls the procedure, the variable is not reinitialized, and it still holds the latest value that you assigned to it. A static variable continues to exist for the lifetime of the class or module that it is defined in.
規則:
1.Static只能修飾Local Variable(函式內的變數)
2.不能修飾Struct的成員函式
3.不能與ReadOnly, Shadows, Shared同時使用
舉例:
Function updateSales(ByVal thisSale As Decimal) As Decimal
Static totalSales As Decimal = 0
totalSales += thisSale
Return totalSales
End Function

因為Satic所以只有第一次進來function才會初始化
所以totalSales不會被歸零
Shared:
MSDN說明:Sharing a member of a class or structure makes it available to every instance, rather than nonshared, where each instance keeps its own copy. This is useful, for example, if the value of a variable applies to the entire application. If you declare that variable to be Shared, then all instances access the same storage location, and if one instance changes the variable's value, all instances access the updated value.
Sharing does not alter the access level of a member. For example, a class member can be shared and private (accessible only from within the class), or nonshared and public.

規則:

1.Shared只能修飾Struct or Class的member(方法或變數)
2.不能與 Overrides, Overridable, NotOverridable, MustOverride, Static 同時使用
3.建議以Struct或Class名稱操作Shared變數,如:Class1.SharedVal1 += 3
(如果用instance操作也可以,不過會有warnning! 這個與C++不同)
4.Shared variable只會存有一份,不管物件有多少個,而Shared function的local variable也是!
(也就是Shared function的local variable隱含的是Shared)
5.不能修飾module與interface的成員、Constant變數,但是他們仍是Shared
6.Shared函式不能使用non-shared變數,只能用shared變數。
但是nonshared函式卻可以使用non-shared、shared變數
(因為non-shared變數是每個instance都有一份專屬的,Shared函式根本不知道你要使用誰的!)

舉例:

Sub main()
shareTotal.total = 10
' The preceding line is the preferred way to access total.
Dim instanceVar As New shareTotal
instanceVar.total += 100
' The preceding line generates a compiler warning message and
' accesses total through class shareTotal instead of through
' the variable instanceVar. This works as expected and adds
' 100 to total.
returnClass().total += 1000
' The preceding line generates a compiler warning message and
' accesses total through class shareTotal instead of calling
' returnClass(). This adds 1000 to total but does not work as
' expected, because the MsgBox in returnClass() does not run.
MsgBox("Value of total is " & CStr(shareTotal.total))
End Sub
Public Function returnClass() As shareTotal
MsgBox("Function returnClass() called")
Return New shareTotal
End Function
Public Class shareTotal
Public Shared total As Integer
End Class

注意:即使returnClass()會回傳shareTotal的物件
但是實際上complier遇到這類的shared操作手法
會直接用shareTotal.total+=1000來解讀
也就是他根本不會進去returnClass()!!!!

2008年12月22日 星期一

前端Script呼叫後端事件處理函式

__doPostBack(TargetObjID,EventArgs)是Asp.net轉成html code會自動加進來的script function
目的在於驅動後端處理函式動作
例如
__doPostBack("Btn1","");

就會馬上執行Btn1.Click的事件處理函式
事實上,Asp.Net元件幾乎都是利用這種方式postBack
我們可以這樣做:
拉一個DropDownList到畫面,
然後把AutoPostBack打開
執行網頁後再看看它的原始碼:


<form name="form1" method="post" action="testpage.aspx" id="form1">
<div>
<input type="hidden" name="__EVENTTARGET" id="__EVENTTARGET" value="" />
<input type="hidden" name="__EVENTARGUMENT" id="__EVENTARGUMENT" value="" />
<input type="hidden" name="__LASTFOCUS" id="__LASTFOCUS" value="" />
</div>
<script type="text/javascript">
//<![CDATA[
var theForm = document.forms['form1'];
if (!theForm) {
theForm = document.form1;
}

function __doPostBack(eventTarget, eventArgument) {
if (!theForm.onsubmit || (theForm.onsubmit() != false)) {
theForm.__EVENTTARGET.value = eventTarget;
theForm.__EVENTARGUMENT.value = eventArgument;
theForm.submit();
}
}
//]]>
</script>
<select name="DropDownList1" onchange="javascript:setTimeout('__doPostBack(\'DropDownList1\',\'\')', 0)" id="DropDownList1"></select>
</form>

提醒一下:doPostBack前面的底線是"兩條",只打一條會出錯的!
還有,如果兩個參數都是空字串""
那PostBack回去就只會做Page_Load()

Button's onClinetClick and onClick attribute

有時候我們需要在Button按下後先彈出一個對話框
詢問user是否確定要執行這個動作
如果user選擇"取消"則回到畫面什麼是也不做
在Asp.Net的Button裡有另外一個attribute===>onClientClick
這個可以指定Script function提供送出表單前的先行作業
例如:


.....


之前一直被一個問題困擾
那就是onClientClick="return false;"可以擋掉畫面postback
為什麼onClientClick="Validate()"
然後function Validate()中只有return false一行卻失敗!!
現在終於曉得了
因為onClientClick="Validate()"
而Validate()又return false時,等於OnClientClick="false"不等於OnClientClick="return false"

2008年12月17日 星期三

VBScript Event Handler

我們知道在Html元素中如果要加入事件
必須在html標籤中加入對應的事件屬性和事件處理函式的名稱
如:

<script language="VBScript">
function btnClick(){
alert("Hello!");
}
</script>

<intput type="button" onClick="btnClick()">
</pre>


但是如果要用VBScript的話,onClick屬性就可以省了!
如:

<script language="VBScript">
Sub btnGreeting_OnClick()
MsgBox("Hello!")
End Sub
</script>

<input type="button" name="btnGreeting">

但是html元素必須加上name屬性!
因為它是用來判斷要呼叫哪個事件處理函式
也就是在VBScript中事件處理函式必須定義成Sub name_event()

參考資料:VBScript vs JavaScript for Event

2008年12月10日 星期三

VB.Net 與 C++的Class 比較 (1)

題目定VB.Net與C++
其實應該說.Net Framework與標準C++ 不過因為大家只用VB所以就下這個標題

C++的Class與.Net的最大差別就是
C++的Class instance預設以Call By Value傳值
也就是說如果傳入一個物件給function
它實際上是"複製一份物件" (這個跟.net的struct變數相同)
但是如果class定的比較大時就會有效能上的問題
幸好c++也有Call By Reference
不過有資料被更改的風險
又幸好我們可以規定傳進去的是Constant
那嚜
就可以兼顧by value與 by reference的優點!!!
例如

void foo3(const String& s);

表示傳入的String s不會被foo3給竄改
這也說明了為什麼c++ 的STL裡面的function那嚜喜歡用const修飾字^^

2008年12月3日 星期三

Word 「樣式與格式」(章節自動編碼)操作心得

1. 樣式與格式工作窗格可由格式工具列最左方的AA圖示啟動,






或是最上方功能表中的格式→樣式與格式啟動。

























2. 在樣式與格式工作窗格中
每個樣式上按右鍵可以看到採用此樣式的地方有幾處,


如果是「目前並未使用」則可刪除,此一情形最容易發生在不是從頭開始寫文件,
或是拿另一份檔案來照其格式寫,通常裡面的樣式又多又雜且一堆無用的樣式。









<===同種階層的標題竟有多種樣式















3.如果你不幸用了一份手動章節編碼的檔案作為出發點,恭喜你,有得搞了, 以下步驟可以幫助你改為自動章節編碼,雖然不是自動的, 但是如果一定要照那份來源檔的格式去寫文件的話,那就乖乖改吧, 下列步驟需要專心與時間,可以泡杯咖啡來準備與word奮戰吧, (A)先將所有的樣式中標題n依階層去統一, 也就是說所有1.的都改為同一個樣式 標題1. 所有1.1.都改為標題2,以此類推,
<=====這才是優質的樣式設定

方法:在樣式與格式的工作窗格中所有名稱中有標題1(假設為1A)的地方按右鍵, 選取相同設定,然後再點選另一個有標題1(假設為1B)的樣式, 這樣會將所有原先使用先選的樣式(1A)的內容套用成後選的那個樣式(1B), 直到只剩一個標題1的樣式, 重複對標題2、3、4...操作以此類推。

(B)針對每個標題的樣式,逐一修改為想要的格式, 以下列格式作為例子
標題1:18pt 粗體 1.5倍行高 中文:新細明體 英文:Times New Roman
標題2:16pt 粗體 1.5倍行高 中文:新細明體 英文:Times New Roman
標題3:14pt 粗體 1.5倍行高 中文:新細明體 英文:Times New Roman
標題4:12pt 中文:新細明體 英文:Times New Roman

首先在樣式與格式工作窗格中的標題1上按右鍵→選取相同設定 (這一步不做有的時候會只改到部分格式,也不知道是為什麼,總之有選比較安全) 再次右鍵,按下修改,會跳出一個修改樣式的選單,


此選單中最上面的屬性,「供後續段落使用之樣式」請選擇你現在所在修改的樣式名稱,
這效果是某行已經套用A樣式時,行尾按下ENTER後下一行自動以A樣式開始,
若不想要這效果,則可設定「供後續段落使用之樣式」為內文,

接下來的格式設定可以分別設定,此樣式的「標題」文字的格式,
可以針對中英文分別設定,

左下角的格式可以調整各種細部設定,

段落:此選單中的「縮排與行距」標籤頁的「一般」中的「大綱階層」要選擇此樣式所應有的階層
通常還會設定「段落間距」與「行距」,1.5倍行高就是在此設定

定位點:段落左下角也有個定位點的按鈕,與此同,可以設定標題文字跟章節編碼之間的距離


編號方式:最重要的功能,要選「大綱編號」中的樣式,
然後找階層1配標題1,階層2配標題2,階層n配標題n的那個,
如果沒有找到想要的,沒關係,那就就「自訂」吧,
出現「自訂大綱編號清單」後,

按下右方的「更多」會出現較多的進階選項,
通常要檢查下列屬性「數字格式」下的「階層」、「字型」(章節自動編碼的字型),
還有下方的「將階層連結至樣式」、「在此層次之後重新編號」,
假設現在修改的是標題4,那麼「階層」、「將階層連結至樣式」、「在此層次之後重新編號」,
分別應該為4、標題4、階層3,

且要從階層1開始檢視並設定至階層4,
也就是先選階層1,然後「將階層連結至樣式」設為標題1,
選階層2,然後「將階層連結至樣式」設為標題2,「在此層次之後重新編號」設為標題1,
選階層3,然後「將階層連結至樣式」設為標題3,「在此層次之後重新編號」設為標題2,
選階層4,然後「將階層連結至樣式」設為標題4,「在此層次之後重新編號」設為標題3,
如果設定正確便可在右方的預覽視窗中看到下列效果
1.標題1
1.1標題2
1.1.1標題3
1.1.1.1標題4

最後 恭喜你,搞定了,Orz, 因為開新檔案的章節自動編碼竟然怪怪的,
只好跟他耗到底,也才有這篇文章的由來。