Entry

プログラミングメモ - システムに一意な文字列を取得する

2009年02月18日

C++ で Win32 API を使い始めると,必ずやりたくなるのが自前の CWnd 作りです(多分)。これはこれで面白いので,あたしも自前の CWnd を作っているんですけれど,ウィンドウクラスのクラス名をどうしようかなぁ,とかゴニョゴニョ。

クラス名はこれといってガリガリ使う文字列でもないので,内部で生成しようと思ってるんですけど,一意である必要はあるようです。幸い,Win32 API には GUID という一意の数値を作ってくれる仕組みがあります。COM プログラミングなんかで使うアレです。

これ,取得するときは複数の数値を持った構造体で,文字列に直す必要があります。で,Win32 API には,この数値を文字列にしてくれる StringFromGUID2 という関数も用意されています。これでシステムに一意な文字列を生成できるというわけです。

ただ,個人的に StringFromGUID2 は,関数の使い方があまりスマートにならない感じがするし(文字列長が決め打ちになってしまう),文字列のフォーマットがまんま COM っぽくてダサい。つことで,文字列は自前で作ることにしました。

#include <iostream>
#include <string>
#include <sstream>
// for using Windows API and macros
#include <windows.h>
#include <windowsx.h>
// for creating GUID
#ifndef INITGUID
#define INITGUID
#endif
#include <objbase.h>

std::string
StringFromGUID(const GUID& guid) {
    std::ostringstream tmp;
    std::ostringstream buf;
    DWORD dwData[4] = {0};

    dwData[0] = guid.Data1;
    dwData[1] = ((guid.Data2 << 16) | guid.Data3);
    for (int i = 0; i < 4; i++) {
        dwData[2] = (dwData[2] << 8) | guid.Data4[i];
        dwData[3] = (dwData[3] << 8) | guid.Data4[i + 4];
    }
    for (int j = 0; j < 4; j++) {
        tmp.flags(std::ios_base::hex | std::ios_base::uppercase);
        tmp.width(8);
        tmp.fill('0');
        tmp << dwData[j];
        if (j != 0) {
            buf << '-';
        }
        buf << tmp.str();
        tmp.str("");
    }
    return buf.str();
}

int main(int argc, char* argv[]) {
    std::string strGUID;
    GUID guid;

    if (::CoCreateGuid(&guid) == S_OK) {
        strGUID = StringFromGUID(guid);
        std::cout << strGUID << std::endl;
    }
    return 0;
}

こんな文字列を作ってくれます。

A47A31D4-DF8447CD-956EFDE1-3FA82ACE

ま,こっちも十分ダサいんですが。WNDCLASSEX.lpszClassName に渡すから,std::string で返してます(ワイド文字版は作らない)。それだけ。

Trackback
Trackback URL:
Ads
About
Search This Site
Ads
Categories
Recent Entries
Log Archive
Syndicate This Site
Info.
クリエイティブ・コモンズ・ライセンス
Movable Type 3.36
Valid XHTML 1.1!
Valid CSS!
ブログタイムズ

© 2003-2012 AIAN