Re[5]: CからVBに変換


[コメントツリー表示を見る] [発言時刻順表示を見る]

Posted by Uz on 2001/07/29 00:51:57

In Reply to: Re[4]: CからVBに変換 Posted by 今市 on 2001/07/28 18:14:00


    > 宜しければ、文法エラー部分を教えて下さい。
    まぁ、ちょっとしたことなんですが、
    > 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;
    > }


    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++;
    と書き換えできます。
    --------------------------------
    だけで、よかったかな。

    #長文・乱文失礼しました。


記事スレッド一覧