2009年6月30日 星期二

DIV垂直居中對齊

在DIV中,無法控制元素的垂直對齊方式。

垂直居中必須透過line-height:div的高度

在文章游標處插入文字

[JavaScript]在光标处插入文字

<HTML>

<HEAD> 

<SCRIPT> 

function storeCaret(textEl) {

if (textEl.createTextRange) 

textEl.caretPos = document.selection.createRange().duplicate(); 


}


function insertAtCaret (textEl, text) {

if (textEl.createTextRange && textEl.caretPos) {

var caretPos = textEl.caretPos;

caretPos.text =caretPos.text.charAt(caretPos.text.length - 1) == ' ' ?text + ' ' : text; 



else 


textEl.value = text;



</SCRIPT> 

</HEAD> 

<BODY> 

<FORM NAME="cForm">


<TEXTAREA NAME="aTextArea" ROWS="10" COLS="60" WRAP="soft" ONSELECT="storeCaret(this);" ONCLICK="storeCaret(this);" ONKEYUP="storeCaret(this);"> 这是例子,你可以在这里添加文字、插入文字。 </TEXTAREA> 

<BR> 

<INPUT TYPE="text" NAME="aText" SIZE="80" VALUE="我要在光标处插入这些文字"><BR>

<INPUT TYPE="button" VALUE="我要在光标处插入上面文本框里输入的文字!" ONCLICK="insertAtCaret(this.form.aTextArea, this.form.aText.value);">

</FORM>


</BODY>

</HTML>

2009年6月26日 星期五

防止長字串破壞畫面布局

CSS:
overflow:hidden; //給FF3.5之前的版本,超過的部份會隱藏
word-wrap:break-word; //FF3.5和IE6之後的版本都支援強制換行

可用於div或table之類

各種unicode編碼轉換

Unicode Code Converter v6

高性能的Ajax應用-Julien Lecomte

高性能的Ajax應用-Julien Lecomte


第1部分 高性能的開發

1.為高性能計劃和設計
-從每一天開始就要計劃高性能
-跟產品經理和設計師緊密的合作
-理解設計的基本原理
-設計和性能之前做解釋和權衡
-提供選擇和展示各種可能(原型)
-挑戰自己,實現有挑戰性的設計(不要只說「不」)
-為了簡化設計和交互,有時候需要妥協

2.高性能工程開發:一些基本規則
-少就是多。不要做任何不必要的事。直到變得絕對重要,否則不要做。
-打破規則。只能在迫不得以的情況下,才能妥協並打破最佳做法。
-在提升可以感覺到的性能上下功夫。

3.衡量性能
-使用用戶真實環境測試
-在開發中,profile你的代碼
-使用自動的profiling/性能測試
-保持功能執行的歷史數據
-在產品中考慮保留一些(少量的)profiling代碼

第2部分 高性能的頁面下載

1.Yahoo!的14條性能原則
一個頁面工作於3(有時是重疊的)個階段-下載,渲染,運行。14條原則大部分作用於第1個階段。

2.資源優化
-最小化CSS和Javascript文件。推薦使用YUI Compressor(http://developer.yahoo.com/yui/compressor)壓縮。遠離那些所謂的先進的壓縮方案,如Packer。
-合併CSS和Javascript文件。在發佈的時候合併(http://www.julienlecomte.net/blog/2007/09/16)或在運行的時候合併。
-優化圖片資源。如:PngCrush(http://pmt.sourceforge.net/pngcrush)、PngOptimizer(http://psydk.org/PngOptimizer.php)等。

3.減小非壓縮代碼的大小
-下載和解析HTML、CSS、Javascript代碼的成本是很高的。
-用簡練寫法和寫更少的代碼
-用好Javascript庫
-在考慮將大的Javascript文件拆成小的文件(bundle)時,解析和編譯腳本時要花費大量額外的時間
-按需下載代碼(HTML、CSS、Javascript),如,Lazy Loading
* 參見,http://ajaxpatterns.org/On-Demand_Javascript
* 使用 YUI Loader
* Dojo的package system
* JSAN的Import System

4.優化初始渲染(1):綜合技巧
-Consider rendering the first view on the server
-關閉你的HTML標籤提高解析速度。參見http://msdn2.microsoft.com/en-us/library/ms533020.aspx#Close_Your_Tags
-考慮儘早緩存。
-下載基本的資源,延遲或按需下載其他資源。使用YUI ImageLoader。

5.優化初始渲染(2):不要一直等onload
-大部分DOM操作可以在onload事件觸發前完成
-如果你需要控制你的初始化代碼,可以直接寫在<script>裡,並把它放在靠近</body>的位置
-否則,使用YUI事件組件中的onDOMReady方法
YAHOO.util.Event.onDOMReady(function () {
// Do something here...
// e.g., attach event handlers.
});

6.優化初始渲染(3):在頁面下載後,再下載腳本。
-一個好的網站應該在Javascript失效下功能也應該是完整的
-因此,你可以延遲下載腳本
-這樣做對下載其他資源(樣式表、圖片等)是有好處的
-這樣做使網站下載更快

7.優化初始渲染(4):有條件的預下載
-預下載潛在的資源(Javascript、CSS、圖片等)真的可以增強用戶體驗。
-可是,在什麼時候進行功妙的預下載是關鍵,否則,預下載會影響用戶體驗。
-參見http://www.sitepoint.com/article/web-site-optimization-steps/3
-參見http://search.yahoo.com


第3部分 高性能的Javascript

1.減少符號查尋(1):範圍鏈
-每次訪問變量時都會執行查尋
-變量從當前範圍向上執行查尋
-因此,無論何時都在相同範圍中聲明和使用變量
-完全不要使用with,它會阻止編譯器生成代碼時訪問本地變量的速度(因為首先要遍歷原型鏈,然後是範圍鏈等)
-緩存外部變量到本地變量。
不好的寫法:
var arr = ...;
var globalVar = 0;
(function () {
var i;
for (i = 0; i < arr.length; i++) {
globalVar++;
}
})();

好的寫法:
var arr = ...;
var globalVar = 0;
(function () {
var i, l, localVar;
l = arr.length;
localVar = globalVar;
for (i = 0; i < l; i++) {
localVar++;
}
globalVar = localVar;
})();


2.減少符號查尋(2):原型鏈
-訪問主對象上的成員的速度比訪問原型鏈上的成員的速度快25%
-原型鏈越長查尋越慢
function A () {}
A.prototype.prop1 = ...;

function B () {
this.prop2 = ...;
}

B.prototype = new A();
var b = new B();//(譯者:prop2為b的主對象成員,而prop1是原型鏈上的成員)

3.優化對象實例化
-如果你需要創建很多對象,可以考慮添加成員到原型中,而不添加到單個對象的構造器中。
-這樣會減少內存的消耗
-然而會拖慢查尋查尋對象成員的速度

4.不要使用eval
-傳字符串到eval中,需要編譯和解釋,相當的慢!
-完全不要傳一個字符串到setTimeout和setInterval中。可以使用匿名函數代替。
setTimeout(function () {
// Code to execute on a timeout
}, 50);
-完全不要eval做為方法的構造器。

5.優化字符串連接
-在IE(JScript)中,連接兩個字符串會導致一個新的字符串被重新分配資源,同時兩個原字符串被覆制:
var s = "xxx" + "yyy";
s += "zzz";
-因此在IE中,添加字符串到數組中然後再用Array.join連接比直接用+連接快很多(不要用在簡單的連接中)
-其他Javascript引擎(WebKit、SpiderMonkey)已經對字符串連接做了優化
-使用YUI Compressor!

6.優化正則表達式
-儘量不要用RegExp構造,除非你的正則表達式需要實時創建。
-使用test方法測試一個pattern(exec方法會有小的性能問題)
-使用非捕獲組(?:)
-保持pattern的簡單

7.緩存
-在下面情況下應用緩存是合理的:
* 更低成本的獲取一個值
* 值會被經常讀取
* 值不經常改變
-會增加內存消耗(權衡)
-Memoization:
Module Pattern:
var fn = (function () {
var b = false, v;
return function () {
if (!b) {
v = ...;
b = true;
}
return v;
};
})();

Store value in function object:
function fn () {
if (!fn.b) {
fn.v = ...;
fn.b = true;
}
return fn.v;
}

Lazy function definition:
var fn = function () {
var v = ...;
return (fn = function () {
return v;
})();
};

8.如何控制長時間運行處理的Javascript
-在Javascrit的長時間運行處理過程中,整個瀏覽器會被凍結
-因此為了維持好的用戶體驗,確保Javascript一個線程在約300兆秒內完成
-你可以通過用setTimeout將長運行處理拆成的更小處理單元串起來執行
-更多見http://www.julienlecomte.net/blog/2007/10/28/
-例子http://www.julienlecomte.net/blogfiles/javascript/long-running-js-process.html
function doSomething (callbackFn) {
// Initialize a few things here...
(function () {
// Do a little bit of work here...
if (termination condition) {
// We are done
callbackFn();
} else {
// Process next chunk
setTimeout(arguments.callee, 0);
}
})();
}

9.綜合技巧
-簡單的操作符往往比相應的方法要快
c = Math.min(a, b);
c = a < b ? a : b;//更快

myArray.push(value);
myArray[myArray.length] = value;//比上面快
myArray[idx++] = value;//比上面快

-避免使用try...catch在影響性能的部分:
不好的寫法:
var i;
for (i = 0; i < 100000; i++) {
try {
...
} catch (e) {
...
}
}
好的寫法:
var i;
try {
for (i = 0; i < 100000; i++) {
...
}
} catch (e) {
...
}
-If possible, avoid for...in in performance-critical sections
-無論何時分支條件都不改變的情況下,分支應該在外面,不要在裡面:
不好的寫法:
function fn () {
if (...) {
...
} else {
...
}
}

好的寫法:
var fn;
if (...) {
fn = function () {...};
} else {
fn = function () {...};
}


第4部分 高性能的動態HTML

1.文檔樹的修改:使用innerHTML
注意事項http://www.julienlecomte.net/blog/2007/12/38

2.文檔樹的修改:使用cloneNode
注意:expando屬性或附加的事件會丟失

3.文檔樹的修改:使用DocumentFragment
-DocumentFragment(DOM Level 1 Core)是一個輕量級的文檔對象
var i, j, el, table, tbody, row, cell, docFragment;
docFragment = document.createDocumentFragment();
el = document.createElement("div");
docFragment.appendChild(el);
table = document.createElement("table");
el.appendChild(table);
tbody = document.createElement("tbody");
table.appendChild(tbody);
for (i = 0; i < 1000; i++) {
...
}
document.body.appendChild(docFragment);
-它僅僅支持常規DOM方法和屬性的子集
-IE實現DocumentFragment不服從W3C規範

4.限制事件柄的個數
-附加事件到上百個元素上的成本很高
-多個事件柄會增加潛在的內存漏洞
-解決方案:使用事件委託機制,一種依靠事件冒泡的機制

5.限制回流(Reflow)


第5部分 高性能的佈局和CSS

綜合技巧
-使用CSS Sprites
-避免使用Javascript佈局
-避免使用IE表達式
-避免使用IE濾鏡(或儘可能少用)
-優化Table佈局
-優化CSS選擇器http://developer.mozilla.org/en/docs/Writing_Efficient_CSS


第6部分 高性能的Ajax

1.綜合技巧
-完全不要使用同步的XMLHttpRequest。參見http://yuiblog.com/blog/2006/04/04/synchronous-v-asynchronous
-編程處理網絡超時
-解決方案:使用YUI Connection Manager
var callback = {
success: function () { /* Do something */ },
failure: function () { /* Do something */ },
timeout: 5000
};
YAHOO.util.Connect.asyncRequest("GET", url, callback);

2.提升可以感覺到的網絡延遲體驗
-如果數據在提交到服務器端之前經過本地校驗,通常請求的成功率達99.9%
-因此,為了優化用戶體驗,我們可以採用下面的Pattern:
* 當請求發出時要更新UI
* Lock the UI/data structures with the finest possible granularity.
* 讓用戶知道發生了什麼事
* 讓用戶知道為什麼UI被鎖定
* 當成功返回結果後要及時解除鎖定
* 要用優雅的方式處理錯誤

3.綜合技巧
-知道並發HTTP/1.1連接的最大數量
-如果後端支持,支持多元的Ajax請求
-Piggyback unsollicited notifications in a response to an Ajax request.
-用JSON代替XML做為數據交換格式
-推送,不要輪詢。使用COMET向瀏覽器發送實時的通知
-考慮使用本地存儲器緩存數據。
* IE的userData
* Flash本地存儲
* DOM:Storage(WHATWG持久存儲API, 已在Firefox2中實現)
* Google Gears
* 其它


第7部分 性能工具

-YSlow? http://developer.yahoo.com/yslow
-Task Manager
-IE Leak Detector a.k.a Drip [ http://www.outofhanwell.com/ieleak/ ]
-Stopwatch profiling
* AjaxView [ http://research.microsoft.com/projects/ajaxview/ ]
* JsLex [ http://rockstarapps.com/pmwiki/pmwiki.php?n=JsLex.JsLex ]
* YUI profiler [ http://developer.yahoo.com/yui/profiler/ ]
-Venkman or Firebug Profiler [ http://www.getfirebug.com/ ]

(原文:http://yuiblog.com/blog/2007/12/20/video-lecomte/)

常用正規表達式

常用正則表達式
匹配中文字符的正則表達式: [\u4e00-\u9fa5]
匹配雙字節字符(包括漢字在內):[^\x00-\xff]
匹配空白行的正則表達式:\n\s*\r
匹配HTML標記的正則表達式:<(\S*?)[^>]*>.*?|<.*? />
匹配首尾空白字符的正則表達式:^\s*|\s*$
匹配Email地址的正則表達式:\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*
匹配網址URL的正則表達式:[a-zA-z]+://[^\s]*
匹配國內電話號碼:\d{3}-\d{8}|\d{4}-\d{7}
匹配騰訊QQ號:[1-9][0-9]{4,}
匹配中國郵政編碼:[1-9]\d{5}(?!\d)
匹配身份證:\d{15}|\d{18}
匹配ip地址:\d+\.\d+\.\d+\.\d+
匹配特定數字:
^[1-9]\d*$    //匹配正整數
^-[1-9]\d*$   //匹配負整數
^-?[1-9]\d*$   //匹配整數
^[1-9]\d*|0$  //匹配非負整數(正整數 + 0)
^-[1-9]\d*|0$   //匹配非正整數(負整數 + 0)
^[1-9]\d*\.\d*|0\.\d*[1-9]\d*$   //匹配正浮點數
^-([1-9]\d*\.\d*|0\.\d*[1-9]\d*)$  //匹配負浮點數
^-?([1-9]\d*\.\d*|0\.\d*[1-9]\d*|0?\.0+|0)$  //匹配浮點數
^[1-9]\d*\.\d*|0\.\d*[1-9]\d*|0?\.0+|0$   //匹配非負浮點數(正浮點數 + 0)
^(-([1-9]\d*\.\d*|0\.\d*[1-9]\d*))|0?\.0+|0$  //匹配非正浮點數(負浮點數 + 0)
匹配特定字符串:
^[A-Za-z]+$  //匹配由26個英文字母組成的字符串
^[A-Z]+$  //匹配由26個英文字母的大寫組成的字符串
^[a-z]+$  //匹配由26個英文字母的小寫組成的字符串
^[A-Za-z0-9]+$  //匹配由數字和26個英文字母組成的字符串
^\w+$  //匹配由數字、26個英文字母或者下劃線組成的字符串

防止誤刷新頁面

防止誤刷新頁面

window.onbeforeunload = function(){
return "您正要離開本頁面,您所做的所有的修改都會丟失,確定麼?";
};

正常提交時,還得屏掉。

frm.onsubmit = function(){

window.onbeforeunload = null;

}

css 更有效率的寫法

這邊介紹了許多css內定的縮寫語法
可將許多屬性寫在一起,不必分別指定

Efficient CSS with shorthand properties

直接用DataRead讀取DataTable

ADO.NET 2.0 的 DataTable可以直接從DataRead讀取

ADO.NET 1.1以前,要從資料庫中把要的資料讀取到DataTable需要經過以下的過程

  1. 建立Connection
  2. 建立Command
  3. 使用DataAdapter
  4. 將資料Fill到DataSet
  5. 從DataSet中讀取第0個DataTable

大致上的程式如下

Dim ConnStr As String = "Data Source=localhost;Initial Catalog=Northwind;User ID=sa"

Using Conn As New SqlConnection(ConnStr)
Dim Cmmd As New SqlCommand("SELECT * FROM Customer", Conn)
Dim Da As New SqlDataAdapter(Cmmd)
Dim Ds As New DataSet
Da.Fill(Ds)
Dim Dt As New DataTable
Dt = Ds.Tables(0)

End Using



然而我們經常需要的就只是一個DataTable而已,卻需要透過DataAdapter的Fill到DataSet中,然後再從DataSet中取出,這樣的過程感覺上繞了一大圈



所以2.0的時候,就讓DataTable可以單獨的去Load一個DataReader,就能夠將相關的資料讀入一個DataTable中,相關的程式碼如下:



Dim ConnStr As String = "Data Source=localhost;Initial Catalog=Northwind;User ID=sa"

Using Conn As New SqlConnection(ConnStr)
Dim Cmmd As New SqlCommand("SELECT * FROM Customer", Conn)
'Dim Da As New SqlDataAdapter(Cmmd)

'Dim Ds As New DataSet
'Da.Fill(Ds)
Dim Dt As New DataTable
Conn.Open() '這邊要特別注意,使用DataRead前,要先Conn.Open

Dt.Load(Cmmd.ExecuteReader)
Conn.Close() 'Conn用完記得關閉
End Using



有個地方要特別提醒,使用DataAdapter時候,Conn會自動的開啟、自動關閉;但是使用DataReader的話,使用前要記得先Open,使用後也要記得Close

2009年6月24日 星期三

繁簡體中文日文韓文的Unicode字元範圍

Unicode編碼編程的技巧大全

一、匹配Unicode字符的正則表達式

這裡是幾個主要非英文語系字符範圍(google上找到的):
2E80~33FFh:中日韓符號區。收容康熙字典部首、中日韓輔助部首、注音符號、日本假名、韓文音符,中日韓的符號、標點、帶圈或帶括符文數字、月份,以及日本的假名組合、單位、年號、月份、日期、時間等。
3400~4DFFh:中日韓認同表意文字擴充A區,總計收容6,582個中日韓漢字。
4E00~9FFFh:中日韓認同表意文字區,總計收容20,902個中日韓漢字。
A000~A4FFh:彝族文字區,收容中國南方彝族文字和字根。
AC00~D7FFh:韓文拼音組合字區,收容以韓文音符拼成的文字。
F900~FAFFh:中日韓兼容表意文字區,總計收容302個中日韓漢字。
FB00~FFFDh:文字表現形式區,收容組合拉丁文字、希伯來文、阿拉伯文、中日韓直式標點、小符號、半角符號、全角符號等。
比如需要匹配所有中日韓非符號字符,那麼正則表達式應該是^[\u3400-\u9FFF]+$
理論上沒錯, 可是我到msn.co.ko隨便複製了個韓文下來, 發現根本不對, 詭異
再到msn.co.jp複製了個'お', 也不得行..
然後把範圍擴大到^[\u2E80-\u9FFF]+$, 這樣倒是都通過了, 這個應該就是匹配中日韓文字的正則表達式了, 包括繁體中文
而關於中文的正則表達式, 應該是^[\u4E00-\u9FFF]+$, 和論壇裡常被人提起的^[\u4E00-\u9FA5]+$很接近
需要注意的是論壇裡說的^[\u4E00-\u9FA5]+$這是專門用於匹配簡體中文的正則表達式, 實際上繁體字也在裡面, 我用測試器測試了下'中華人民共和國', 也通過了, 當然, ^[\u4E00-\u9FFF]+$也是一樣的結果

二、利用漢字Unicode範圍來驗證是否為漢字的JavaScript函數

1、function checkchinese(str){
  var re1 = new RegExp("^[\u4E00-\\u9fa5]*$")     //漢字的範圍
  var re2 = new RegExp("^[\uE7C7-\uE7F3]*$")
  var str = str.replace(/(^\s*)|(\s*$)/g,'');
  if (str == ''){return false;}
  if (!(re1.test(str) && (! re2.test(str)))){
    return false;
  }
  return true;
}



3.怎麼判斷是否是字符
if(/[^\x00-\xff]/g.test(s))
  alert("含有漢字");
else
  alert("全是字符");

3.怎麼判斷是否含有漢字
if(escape(str).indexOf("%u")!=-1)
  alert("含有漢字");
else
  alert("全是字符");

4、

三、其他技巧

1、只能輸入漢字,數字,英文大小寫,符號只允許,。!的正則表達式

String.prototype.existChinese   =   function()  
{  
//[\u4E00-\u9FA5]為漢字﹐[\uFE30-\uFFA0]為全角符號  
return   /[\u4e00-\u9fa5]/.test(this);  
}


if(/[^\u4e00-\u9fa5\w,\.]/.test(obj.value)) obj.value="";return false;
function SpecChar(obj) { if(event.type=="keyup") { if(/[^\u4e00-\u9fa5\w,\.]/.test(obj.value)) obj.value=obj.value.substring(0,obj.value.length-1);return false; } }
四、Windows環境下Unicode編程總結
UNICODE環境設置
在安裝Visual Studio時,在選擇VC++時需要加入unicode選項,保證相關的庫文件可以拷貝到system32下。

UNICODE編譯設置:
C/C++, Preprocessor difinitions 去除_MBCS,加_UNICODE,UNICODE
在ProjectSetting/link/output 中設置Entry為wWinMainCRTStartup
反之為MBCS(ANSI)編譯。


Unicode :寬字節字符集

1. 如何取得一個既包含單字節字符又包含雙字節字符的字符串的字符個數?可以調用Microsoft Visual C++的運行期庫包含函數_mbslen來操作多字節(既包括單字節也包括雙字節)字符串。
調用strlen函數,無法真正瞭解字符串中究竟有多少字符,它只能告訴你到達結尾的0之前有多少個字節。



2. 如何對DBCS(雙字節字符集)字符串進行操作?函數 描述
PTSTR CharNext ( LPCTSTR ); 返回字符串中下一個字符的地址
PTSTR CharPrev ( LPCTSTR, LPCTSTR ); 返回字符串中上一個字符的地址
BOOL IsDBCSLeadByte( BYTE ); 如果該字節是DBCS字符的第一個字節,則返回非0值



3. 為什麼要使用Unicode?(1) 可以很容易地在不同語言之間進行數據交換。
(2) 使你能夠分配支持所有語言的單個二進制.exe文件或DLL文件。
(3) 提高應用程序的運行效率。
Windows 2000是使用Unicode從頭進行開發的,如果調用任何一個Windows函數並給它傳遞一個ANSI字符串,那幺系統首先要將字符串轉換成Unicode,然後將Unicode字符串傳遞給操作系統。如果希望函數返回ANSI字符串,系統就會首先將Unicode字符串轉換成ANSI字符串,然後將結果返回給你的應用程序。進行這些字符串的轉換需要佔用系統的時間和內存。通過從頭開始用Unicode來開發應用程序,就能夠使你的應用程序更加有效地運行。
Windows CE 本身就是使用Unicode的一種操作系統,完全不支持ANSI Windows函數
Windows 98 只支持ANSI,只能為ANSI開發應用程序。
Microsoft公司將COM從16位Windows轉換成Win32時,公司決定需要字符串的所有COM接口方法都只能接受Unicode字符串。



4. 如何編寫Unicode源代碼?Microsoft公司為Unicode設計了WindowsAPI,這樣,可以儘量減少代碼的影響。實際上,可以編寫單個源代碼文件,以便使用或者不使用Unicode來對它進行編譯。只需要定義兩個宏(UNICODE和_UNICODE),就可以修改然後重新編譯該源文件。
_UNICODE宏用於C運行期頭文件,而UNICODE宏則用於Windows頭文件。當編譯源代碼模塊時,通常必須同時定義這兩個宏。



5. Windows定義的Unicode數據類型有哪些?數據類型 說明
WCHAR Unicode字符
PWSTR 指向Unicode字符串的指針
PCWSTR 指向一個恆定的Unicode字符串的指針
對應的ANSI數據類型為CHAR,LPSTR和LPCSTR。
ANSI/Unicode通用數據類型為TCHAR,PTSTR,LPCTSTR。



6. 如何對Unicode進行操作?字符集 特性 實例
ANSI 操作函數以str開頭 strcpy
Unicode 操作函數以wcs開頭 wcscpy
MBCS 操作函數以_mbs開頭 _mbscpy
ANSI/Unicode 操作函數以_tcs開頭 _tcscpy(C運行期庫)
ANSI/Unicode 操作函數以lstr開頭 lstrcpy(Windows函數)
所有新的和未過時的函數在Windows2000中都同時擁有ANSI和Unicode兩個版本。ANSI版本函數結尾以A表示;Unicode版本函數結尾以W表示。Windows會如下定義:
#ifdef UNICODE
#define CreateWindowEx CreateWindowExW
#else
#define CreateWindowEx CreateWindowExA
#endif // !UNICODE



7. 如何表示Unicode字符串常量?字符集 實例
ANSI 「string」
Unicode L「string」
ANSI/Unicode T(「string」)或_TEXT(「string」)if( szError[0] == _TEXT(『J') ){ }



8. 為什麼應當儘量使用操作系統函數?這將有助於稍稍提高應用程序的運行性能,因為操作系統字符串函數常常被大型應用程序比如操作系統的外殼進程Explorer.exe所使用。由於這些函數使用得很多,因此,在應用程序運行時,它們可能已經被裝入RAM。
如:StrCat,StrChr,StrCmp和StrCpy等。



9. 如何編寫符合ANSI和Unicode的應用程序?(1) 將文本串視為字符數組,而不是chars數組或字節數組。
(2) 將通用數據類型(如TCHAR和PTSTR)用於文本字符和字符串。
(3) 將顯式數據類型(如BYTE和PBYTE)用於字節、字節指針和數據緩存。
(4) 將TEXT宏用於原義字符和字符串。
(5) 執行全局性替換(例如用PTSTR替換PSTR)。
(6) 修改字符串運算問題。例如函數通常希望在字符中傳遞一個緩存的大小,而不是字節。這意味著不應該傳遞sizeof(szBuffer),而應該傳遞(sizeof(szBuffer)/sizeof(TCHAR)。另外,如果需要為字符串分配一個內存塊,並且擁有該字符串中的字符數目,那幺請記住要按字節來分配內存。這就是說,應該調用
malloc(nCharacters *sizeof(TCHAR)),而不是調用malloc(nCharacters)。



10. 如何對字符串進行有選擇的比較?通過調用CompareString來實現。
標誌 含義
NORM_IGNORECASE 忽略字母的大小寫
NORM_IGNOREKANATYPE 不區分平假名與片假名字符
NORM_IGNORENONSPACE 忽略無間隔字符
NORM_IGNORESYMBOLS 忽略符號
NORM_IGNOREWIDTH 不區分單字節字符與作為雙字節字符的同一個字符
SORT_STRINGSORT 將標點符號作為普通符號來處理



11. 如何判斷一個文本文件是ANSI還是Unicode?判斷如果文本文件的開頭兩個字節是0xFF和0xFE,那幺就是Unicode,否則是ANSI。



12. 如何判斷一段字符串是ANSI還是Unicode?用IsTextUnicode進行判斷。IsTextUnicode使用一系列統計方法和定性方法,以便猜測緩存的內容。由於這不是一種確切的科學方法,因此 IsTextUnicode有可能返回不正確的結果。



13. 如何在Unicode與ANSI之間轉換字符串?Windows函數MultiByteToWideChar用於將多字節字符串轉換成寬字符串;函數WideCharToMultiByte將寬字符串轉換成等價的多字節字符串。



14. Unicode和DBCS之間的區別Unicode使用(特別在C程序設計語言環境裡)「寬字符集」。「Unicode中的每個字符都是16位寬而不是8位寬。」在Unicode中,沒有單單使用8位數值的意義存在。相比之下,在「雙位組字符集」中我們仍然處理8位數值。有些位組自身定義字符,而某些位組則顯示需要和另一個位組共同定義一個字符。
處理DBCS字符串非常雜亂,但是處理Unicode文字則像處理有秩序的文字。您也許會高興地知道前128個Unicode字符(16位代碼從0x0000到0x007F)就是ASCII字符,而接下來的128個Unicode字符(代碼從0x0080到0x00FF)是ISO 8859-1對ASCII的擴展。Unicode中不同部分的字符都同樣基於現有的標準。這是為了便於轉換。希臘字母表使用從0x0370到0x03FF的代碼,斯拉夫語使用從0x0400到0x04FF的代碼,美國使用從0x0530到0x058F的代碼,希伯來語使用從0x0590到0x05FF的代碼。中國、日本和韓國的象形文字(總稱為CJK)佔用了從0x3000到0x9FFF的代碼。Unicode的最大好處是這裡只有一個字符集,沒有一點含糊。



15.衍生標準Unicode是一個標準。UTF-8是其概念上的子集,UTF-8是具體的編碼標準。而UNICODE是所有想達到世界統一編碼標準的標準。UTF-8標準就是Unicode(ISO10646)標準的一種變形方式,
UTF的全稱是:Unicode/UCS Transformation Format,其實有兩種UTF,一種是UTF-8,一種是UTF-16,
不過UTF-16使用較少,其對應關係如下:
在Unicode中編碼為 0000 - 007F 的 UTF-8 中編碼形式為: 0xxxxxxx
在Unicode中編碼為 0080 - 07FF 的 UTF-8 中編碼形式為: 110xxxxx 10xxxxxx
在Unicode中編碼為 0000 - 007F 的 UTF-8 中編碼形式為: 1110xxxx 10xxxxxx 10xxxxxx



utf-8是unicode的一個新的編碼標準,其實unicode有過好幾個標準.我們知道一直以來使用的unicode字符內碼都是16位,它實際上還不能把全世界的所有字符編在一個平面系統,比如中國的藏文等小語種,所以utf-8擴展到了32位,也就是說理論在utf-8中可容納二的三十二次方個字符. UNICODE的思想就是想把所有的字符統一編碼,實現一個統一的標準.big5、gb都是獨立的字符集,這也叫做遠東字符集,把它拿到德文版的WINDOWS上可能將會引起字符編碼的衝突....早期的WINDOWS默認的字符集是ANSI.notepad中輸入的漢字是本地編碼,但在NT/2000內部是可以直接支持UNICODE的。notepad.exe在WIN95和98中都是ANSI字符,在NT中則是UNICODE.ANSI和UNICODE可以方便的實現對應映射,也就是轉換 ASCII是8位範圍內的字符集,對於範圍之外的字符如漢字它是無法表達的。unicode是16位範圍內的字符集,對於不同地區的字符分區分配,unicode是多個IT巨頭共同制定的字符編碼標準。如果在unicode環境下比如WINDOWS NT上,一個字符佔兩字節16位,而在ANSI環境下如WINDOWS98下一個字符佔一個字節8位.Unicode字符是16位寬,最多允許65,535字符,數據類型被稱為WCHAR。
對於已有的ANSI字符,unicode簡單的將其擴展為16位:比如ANSI"A"=0x43,則對應的UNICODE為
"A"= 0x0043
而ASCII用七存放128個字符,ASCII是一個真正的美國標準,所以它不能滿足其他國家的需要,例如斯拉夫語的字母和漢字於是出現了Windows ANSI字符集,是一種擴展的ASCII碼,用8位存放字符,低128位仍然存放原來的ASCII碼,
而高128位加入了希臘字母等
if def UNICODE
TCHAR = wchar
else
TCHAR = char
你需要在Project\Settings\C/C++\Preprocesser definitions中添加UNICODE和_UNICODE
UINCODE,_UNICODE都要定義。不定義_UNICODE的話,用SetText(HWND,LPCTSTR),將被解釋為SetTextA(HWND,LPTSTR),這時API將把你給的Unicode字符串看作ANSI字符串,顯示亂碼。因為windows API是已經編譯好存在於dll中的,由於不管UNICODE還是ANSI字符串,都被看作一段buffer,如"0B A3 00 35 24 3C 00 00"如果按ANSI讀,因為ANSI字串是以'\0'結束的,所以只能讀到兩字節"0B A3 \0",如果按UNICODE讀,將完整的讀到'\0\0'結束。
由於UNICODE沒有額外的指示位,所以系統必須知道你提供的字串是哪種格式。此外,UNICODE好像是ANSI C++規定的,_UNICODE是windows SDK提供的。如果不編寫windows程序,可以只定義UNICODE。



開發過程:圍繞著文件讀寫、字符串處理展開。文件主要有兩種:.txt和.ini文件
1. 在unicode和非unicode環境下字符串做不同處理的,那麼需要參考以上9,10兩條,以適應不同環境得字符串處理要求。
對文件讀寫也一樣。只要調用相關接口函數時,參數中的字符串前都加上_TEXT等相關宏。如果寫成的那個文件需要是unicode格式保存的,那麼在創建文件時需要加入一個字節頭。
CFile file;
WCHAR szwBuffer[128];

WCHAR *pszUnicode = L"Unicode string\n"; // unicode string
CHAR *pszAnsi = "Ansi string\n"; // ansi string
WORD wSignature = 0xFEFF;

file.Open(TEXT("Test.txt"), CFile::modeCreate|CFile::modeWrite);

file.Write(&wSignature, 2);

file.Write(pszUnicode, lstrlenW(pszUnicode) * sizeof(WCHAR));
// explicitly use lstrlenW function

MultiByteToWideChar(CP_ACP, 0, pszAnsi, -1, szwBuffer, 128);

file.Write(szwBuffer, lstrlenW(szwBuffer) * sizeof(WCHAR));

file.Close();
//以上這段代碼在unicode和非unicode環境下都有效。這裡顯式的指明用Unicode來進行操作。
2. 在非unicode環境下,缺省調用的都是ANSI格式的字符串,此時TCHAR轉換為CHAR類型的,除非顯式定義WCHAR。所以在這個環境下,如果讀取unicode文件,那麼首先需要移動2個字節,然後讀取得字符串需要用MultiByteToWideChar來轉換,轉換後字符串信息才代表unicode數據。
3. 在unicode環境下,缺省調用得都是unicode格式得字符串,也就是寬字符,此時TCHAR轉換為WCHAR,相關得API函數也都調用寬字符類型的函數。此時讀取unicode文件也和上面一樣,但是讀取得數據是WCHAR的,如果要轉換成ANSI格式,需要調用WideCharToMultiByte。如果讀取ANSI的,則不用移動兩個字節,直接讀取然後視需要轉換即可。



某些語言(如韓語)必須在unicode環境下才能顯示,這種情況下,在非unicode環境下開發,就算用字符串函數轉換也不能達到顯示文字的目的,因為此時調用得API函數是用ANSI的(雖然底層都是用UNICODE處理但是處理結果是按照程序員調用的API來顯示的)。所以必須用unicode來開發。

Javascript的延遲執行

Delaying Javascript Event Execution
If you're looking to execute javascript code whenever someone finishes (or stops temporary) scrolling, moving the mouse, or resizing the page, you may find the following code segment useful.
作者舉了幾個事件onScroll, onMouseMove, onResize,這些事件會被頻繁觸發。出於執行性能考慮,有些回調最好安排在事件結束之後,這時候就可以通過延時執行Javascript的方法實現,模擬onScrollEnd, onMouseMoveEnd和onResizeEnd。

 var onFooEndFunc = function() {
var delay = 50; /* milliseconds - vary as desired */
var executionTimer;
return function() {
if (executionTimer) {
clearTimeout(executionTimer);
}
executionTimer = setTimeout(function() {
// YOUR CODE HERE
}, delay);
};
}();

版面(元素)置中,居中布局

SimpleBits ~ CSS Centering 101

body {
text-align: center;
}

#container {
margin: 0 auto;
width: xxxpx;
}


<body>

  <div id="container">

    ...entire layout goes here...

  </div>

</body>

2009年6月23日 星期二

JavaScript 自訂 trim() 函式

<SCRIPT LANGUAGE="JavaScript">
<!--

//made by yaosansi 2005-12-02
//For more visit http://www.yaosansi.com
// Trim() , Ltrim() , RTrim()
 
String.prototype.Trim = function() 
{ 
return this.replace(/(^\s*)|(\s*$)/g, ""); 
} 
 
String.prototype.LTrim = function() 
{ 
return this.replace(/(^\s*)/g, ""); 
} 
 
String.prototype.RTrim = function() 
{ 
return this.replace(/(\s*$)/g, ""); 
} 
 
//-->
</SCRIPT>

2009年6月22日 星期一

網誌存檔