home ホーム search 検索 -  login ログイン  | reload edit datainfo version cmd icon diff delete  | help ヘルプ

日記/2010/04/12/XNResourceEditorで同じID, 異なる言語の文字列リソースがうまく取得出来ない。

日記/2010/04/12/XNResourceEditorで同じID, 異なる言語の文字列リソースがうまく取得出来ない。

日記 / 2010 / 04 / 12 / XNResourceEditorで同じID, 異なる言語の文字列リソースがうまく取得出来ない。
id: 642 所有者: msakamoto-sf    作成日: 2010-04-12 22:29:24
カテゴリ: Windows プログラミング 

すみません、勘違いしてました(;´Д`)。
文字列リソースの場合、16個の文字列を一組の文字列テーブルとして管理しています。FindResource()やFindResourceEx()で文字列リソースを取り出そうとする場合は、その文字列リソースのIDではなくて、文字列リソースが格納されているテーブルのIDを指定する必要があります。16個で一組になっており、Resource Compilerにより「先頭の文字列リソースID / 16 + 1」というIDが自動的に振られます。
その内容も、16個の文字列リソースがバイナリで格納されている為、一つ一つを取り出すには専用の処理を組む必要があります。

詳しくは次の記事を参照して下さい。

これを理解せずに試行錯誤していたため、以下の内容は誤りを含んでおり、無視して下さい。


"String Table"リソースを追加し、"Neutral"と"日本語"、二つのテーブルで同じIDで異なる文字列を用意した後、

  1. FindResourceEx()で、MAKELANGIDで日本語用の言語IDを指定
  2. LoadResource()でグローバルハンドル取得
  3. LockResource()でLPVOIDポインタ取得

すると、一応UNICODE文字列(WCHAR)のデータが取得出来たのだが、中身はNeutralで指定した文字列になっている。

XN Resource Editorの問題か、そもそもリソースデータのバイナリ表現上の制限でうまく区別出来ないか。

とりあえず、「一つのリソースファイル内の文字列リソースで、同じリソースID+異なる言語」は止めておいた方が余計なトラップに嵌らなくて済みそう。

MAKELANGIDで日本語のIDを作成し、FindResourceEx()で文字列リソースを取得するサンプル:

#include <windows.h>
#include <stdio.h>
 
void PrintErrorMsg(DWORD err)
{
    LPTSTR lpMsgBuf;
    FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER
        | FORMAT_MESSAGE_FROM_SYSTEM 
        | FORMAT_MESSAGE_IGNORE_INSERTS,
        NULL, err,
        MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
        (LPTSTR)&lpMsgBuf, 0, NULL);
    printf("%s\n", lpMsgBuf);
    LocalFree(lpMsgBuf);
}
 
int main(int argc, char *argv[])
{
    HINSTANCE hCurrentInst;
    HRSRC hResRc;
    HGLOBAL hGlobal;
    DWORD dwSizeofRes;
    char *buf = NULL;
 
    hCurrentInst = GetModuleHandle(NULL);
 
    hResRc = FindResourceEx(
        hCurrentInst, 
        RT_STRING, 
                // NG : 16個一組の文字列テーブルのブロックIDを指定する。
                // ブロックIDは、"(そのブロック中の適当な文字列ID) / 16 + 1"
        MAKEINTRESOURCE(1),
                // →正しくは MAKEINTRESOUCE( 1/16 + 1) (今回は偶々結果として同じ"1"になっただけ)
        MAKELANGID(LANG_JAPANESE, SUBLANG_JAPANESE_JAPAN)
    );
    if (NULL == hResRc) {
        PrintErrorMsg(GetLastError());
        return -1;
    }
 
    dwSizeofRes = SizeofResource(hCurrentInst, hResRc);
    if (0 == dwSizeofRes) {
        PrintErrorMsg(GetLastError());
        return -2;
    }
    printf("size = %d\n", dwSizeofRes);
    
    hGlobal = LoadResource(hCurrentInst, hResRc);
    if (NULL == hGlobal) {
        PrintErrorMsg(GetLastError());
        return -3;
    }
    
    buf = (char*)LockResource(hGlobal);
    if (NULL == buf) {
        PrintErrorMsg(GetLastError());
        return -4;
    }
 
    // NG:取得されるのは16個の文字列を一組にした文字列テーブルの「ブロック」データ。
    printf("string resource : [%s]\n", buf);
 
    return 0;
}

※なお、最後のprintf()は上手く動きません。本来ならtchar.hをincludeしてUNICODE対応させる必要があります。(参考: C言語系/memos/VC++/03, UNICODE対応とtchar.h
じゃぁどうやって中身を確認したの?ですが・・・OllyDbgで確認(爆)。


プレーンテキスト形式でダウンロード
現在のバージョン : 2
更新者: msakamoto-sf
更新日: 2010-04-13 12:54:31
md5:fd127745e5eedfbecffddd411a88e3a3
sha1:1b9688cc6ae19508924e66b85fbd81e8827332b5
コメント
コメントを投稿するにはログインして下さい。