站內搜尋

2008/8/5

WM API : LoadString() 另一種使用方式

說真的,英文不好看 Doc 真的吃力,連看 MSDN 都有很大的機會看不懂,
還好我們能用測的.. =.=+
也因此發現了下面這個 LoadString 的好玩用法。


最近在看一些要維護的程式,發現了類似下面的程式碼
Str = (LPCTSTR)LoadString( ID, UID, NULL, 0) ;
而其指向的 resource 定義如下:
UID "abc"
UID2 "123"
UID3 "456"
以下類推

當然,理想中的 Str 是希望它指向 "abc" ,但輸出的結果卻是

"abc123456....."

於是便開始了和 MSDN 拼鬥的一段時光....

最後,在 MSDN 中發現了以下的說明:
If lpBuffer is set to NULL, the return value is a pointer to the requested string. The caller should cast the return value to an LPCTSTR. This pointer points directly to the resource, so the string is read-only. The length of the string, not including any terminating null character, can be found in the word preceding the string.
因此對它的配制有了基本的認識,也準備寫一段 code 來專門取出每一段 str,但又在下面看到一段說明:
String resources are not null-terminated by default. When lpBuffer is set to NULL, verify whether the string resource represented by the pointer returned by LoadString is null-terminated, and if necessary, append a terminating null character to the resource before using it in your application.
突然心中幾個問號.. =.=+ 於事便動手開始寫 code 來進行測試。
才發現,除了大部份的參考資料及網路上大眾的做法外,LoadString還有另一種用法。

在 MSDN 中有規範到,假如 第三個參數為 NULL,則 LoadString 會 return 一個 potiner,指向這筆資源,而下面的說明則有一些有關於結束字元的說明。
String resources are not null-terminated by default.
要使用這個功能有二個做法,一個就是如它所說,在 resouce compiler 裡加入 -n 這個 option,則 resouce compiler 就不會把 terminating null character 給過瀘掉。

如此一來我上面的程式碼就可以正確執行。

另一個方法則是利用它文中提到的另一個特性:
The length of the string, not including any terminating null character, can be found in the word preceding the string.
以下是我測試用的 code:
HINSTANCE hd ;
LPCTSTR str1 ;
TCHAR *str3 ;
int len ;

hd = AfxGetInstanceHandle() ;
str1 = (LPCTSTR)LoadString(hd, IDS_STRING129, NULL, 0) ;
len = (int)*(str1-1) ;
str3 = new TCHAR[len+1] ;
memcpy((void *)str3, str1, (len+1)*sizeof(TCHAR) ) ;
*(str3+len)='\0' ;
MessageBox(NULL, (TCHAR *)str3 , NULL, MB_OK) ;
有興趣的人可以拿去研究看看。

熱門文章