還好我們能用測的.. =.=+
也因此發現了下面這個 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.
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.
才發現,除了大部份的參考資料及網路上大眾的做法外,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.
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) ;有興趣的人可以拿去研究看看。
沒有留言:
張貼留言