> 宜しければ、文法エラー部分を教えて下さい。 まぁ、ちょっとしたことなんですが、 > FormatMessage( > FORMAT_MESSAGE_ALLOCATE_BUFFER | > FORMAT_MESSAGE_FROM_SYSTEM | > FORMAT_MESSAGE_IGNORE_INSERTS, > NULL, > GetLastError(), > MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language > (LPTSTR) &lpMsgBuf, strlen((LPTSTR) &lpMsgBuf), > NULL ); > // Display the string. ここで、2行ほど足りない。 あと、hGlb = LoadResource(NULL, hRsrc); がNULLでいいのか?って感じ。 NULLでなく、hInstanceで動作確認しました。
> その後、下記についていろいろと調べてみたんですがCと > ポインタの理解不足のためか、謎が深まるばかりです。 > for(UINT i(0),nStrLen(0);i<(uID & 15);i++,nStrLen=lpwsz++[0]) { > lpwsz+=nStrLen; > } > 上記の nStrLen=lpwsz++[0] の意味について解説戴ければ幸いです。
nStrLen=lpwsz++[0]は nStrLen = lpwsz[0]; lpwsz++; と書き換えできます。
少し、全体を説明します。 まずはじめに、少しfor文のことはちょっとおいといて、 リソースの取得に関して、まとめておきます。 (詳しいことはよく知らないので、間違いがあるかもしれませんが、 元のソースを読んでの、僕の認識です。)
リソースは16個ずつのIDをまとめて、ブロックとして保存してます。 HRSRC hRsrc = FindResourceEx(hInstance, RT_STRING, MAKEINTRESOURCE((uID>>4 /* uID/16 と同意 */ )+1), wLanguage); これで、取得したいIDのブロックのリソースハンドルを取得する。
ブロックの中身は 文字数(2バイト) 文字(2バイトx文字数) 文字数(2バイト) 文字(2バイトx文字数) ; と16個並びます。 最初に2バイト文字数のデータが入っていて、 次にその文字数分、文字データが入っているという、繰り返しです。 ここの文字データはワイドキャラで入っているので、1文字2バイト になっています。
このことを頭において、for文の説明に入ります。
まず、lpwszという変数はポインタ(メモリの位置を示す)で あることをしっかり思えておきましょう。 lpwszはLPWSTRという型で宣言されています。 LPWSTRは、2バイトのWCHAR型を指す、ポインタと定義されているので、 lpwsz++; すなわち lpwsz = lpwsz + 1; で、2バイト進みます。 (大丈夫ですか?ついてこれます?)
HRSRC hRsrc = FindResourceEx(hInstance, RT_STRING, MAKEINTRESOURCE((uID>>4 /* uID/16 と同意 */ )+1), wLanguage); hGlb = LoadResource(hInstance, hRsrc); lpwsz = (LPWSTR)LockResource(hGlb); これで、目的のブロックを指すポインタを取得できます。 ブロックが取得できたら、目的のIDのデータまで、 間のデータを飛ばす必要があります。
で、肝心のfor文に入ります。 まず、for文をわかりやすく、書き換えます。 これは、Cの文法が理解できていれば、書き換えられます。
> for(UINT i(0),nStrLen(0);i<(uID & 15);i++,nStrLen=lpwsz++[0]) { > lpwsz+=nStrLen; > } | V UINT i; UINT nStrLen = 0; UINT nNum = uID & 15; // 下位4ビットマスク -> 16で割った余り // VB だと uID mod 15 for (i = 0; i < nNum; i++) { lpwsz += nStrLen; nStrLen = lpwsz[0]; lpwsz++; } // この時点で、目的のIDのデータの、文字数がnStrLenに、 // 文字へのポインタがlpwszとなっている。
では、もう少し、VBに近づけます。 少し、順番を変えてわかりやすく。 UINT i; UINT nStrLen = 0; UINT nNum = uID & 15; // 下位4ビットマスク -> 16で割った余り // VB だと uID mod 15 for (i = 0; i < nNum; i++) { nStrLen = lpwsz[0]; // 先頭2バイト読み込み lpwsz = lpwsz + 1; // 文字数データのあった2バイト分ポインタを進める lpwsz = lpwsz + nStrLen; // 取得した文字数分ポインタを進める } nStrLen = lpwsz[0]; // 先頭2バイト読み込み lpwsz = lpwsz + 1; // 文字数データのあった2バイト分ポインタを進める // この時点で、目的のIDのデータの、文字数がnStrLenに、 // 文字へのポインタがlpwszとなっている。
では、VBにしてみましょう。 Dim I As Long Dim nStrLen As Integer Dim nNum As Long nNum = uID And &HF& ' nNum = uID Mod 15 でもいい
For I = 0 To nNum - 1 Call CopyMemory(nStrLen, ByVal ptrVal, 2) ' 先頭2バイト読み込み ptrVal = ptrVal + 1 * 2 ' 文字数データのあった2バイト分ポインタを進める ptrVal = ptrVal + nStrLen * 2 ' 取得した文字数分ポインタを進める Next Call CopyMemory(nStrLen, ByVal ptrVal, 2) ' 先頭2バイト読み込み ptrVal = ptrVal + 2 ' 文字数データのあった2バイト分ポインタを進める ' この時点で、目的のIDのデータの、文字数がnStrLenに、 ' 文字へのポインタがptrValになっている。
これで、取得したブロックの、目的のIDのデータを指すところまで、 ptrValを移動することが出来ました。
以上、余り人に説明するのがうまくないので、きれいにまとまりませんでしたが、 極力考える手順に沿って書いたつもりです。 わかりましたでしょうか? わからないところがあれば、聞いてください。
-------------------------------- nStrLen=lpwsz++[0]は nStrLen = lpwsz[0]; lpwsz++; と書き換えできます。 -------------------------------- だけで、よかったかな。
#長文・乱文失礼しました。
|