第156章 ローカル・アトム


今回は、第154章で書いたように 「アトム」について解説します。アトムといっても「鉄腕アトム」の ことではありません。アトムとは文字列定数と対応した整数値です。 アトムを使うといろいろ便利なことがあります。アトムにはローカル・アトム とグローバル・アトムがあります。今回は前者について解説します。



ローカル・アトムは各アプリケーション(プロセス)で使用します。 他のプロセスからは参照できません。

1.AddAtom関数で文字列をローカル・アトム・テーブルに格納します。 2.GetAtomName関数でアトム・テーブルからアトム名(文字列)を取得します。

たったこれだけです。アトムをローカル・アトムテーブルから削除するには DeleteAtom関数を使います。アプリケーションを終了するときは 自動的に削除されます。

ATOM AddAtom( LPCTSTR lpString // 文字列 );

文字列をローカル・アトム・テーブルに格納します。 文字列の長さは255バイト以内です。 関数が成功したら新しく作られたアトムを返します。 失敗したら0を返します。もし、すでに存在する 文字列を格納しようとした場合はすでに存在するアトムを返します。 そして、参照カウントを1増やします。

UINT GetAtomName( ATOM nAtom, // アトム値 LPTSTR lpBuffer, // バッファのアドレス int nSize // バッファの大きさ );

指定されたローカル・アトムに関連した文字列のコピーをバッファに取得します。 成功したらバッファにコピーしたバイト数を返します。 失敗したら0を返します。

ATOM DeleteAtom( ATOM nAtom // 削除するアトム );

ローカル・アトムの参照カウントを1減らします。 参照カウントが0になるとローカル・アトム・テーブルからアトムを削除します。

さて、文字列の最初に「#」を指定してその後に整数を指定しAddAtom関数を実行すると、 整数アトムを取得することができます。整数はMAXINTATOMより小さいことが必要です。 この場合MAKEINTATOMマクロを使うと便利です。なお、MAXINTATOMは winbase.hのなかで
#define MAXINTATOM 0xC000
と定義されています。

LPTSTR MAKEINTATOM( WORD wInteger // 整数値 );

たとえば
nAtom = AddAtom(MAKEINTATOM(200));
のように使います。

WM_CREATEのところで文字列をAddAtomして、WM_PAINTメッセージが きたら、GetAtomName関数で文字列を取得して描画しています。 最後の「#7」はWM_TIMERメッセージの所で現在時刻を 取得してその「秒」のところを整数アトムにして使っています。 この場合整数が0の時は表示されません。



では、サンプルのプログラムを見てみましょう。 今回は簡単です。

// atom01.cpp #ifndef STRICT #define STRICT #endif #include <windows.h> #define ID_MYTIMER 1 LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); ATOM InitApp(HINSTANCE); BOOL InitInstance(HINSTANCE, int); char szClassName[] = "atom01"; //ウィンドウクラス int WINAPI WinMain(HINSTANCE hCurInst, HINSTANCE hPrevInst, LPSTR lpsCmdLine, int nCmdShow) { MSG msg; if (!InitApp(hCurInst)) return FALSE; if (!InitInstance(hCurInst, nCmdShow)) return FALSE; while (GetMessage(&msg, NULL, 0, 0)) { TranslateMessage(&msg); DispatchMessage(&msg); } return msg.wParam; }

いつもとたいして変わりません。

//ウィンドウ・クラスの登録 ATOM InitApp(HINSTANCE hInst) { WNDCLASSEX wc; wc.cbSize = sizeof(WNDCLASSEX); wc.style = CS_HREDRAW | CS_VREDRAW; wc.lpfnWndProc = WndProc; //プロシージャ名 wc.cbClsExtra = 0; wc.cbWndExtra = 0; wc.hInstance = hInst; //インスタンス wc.hIcon = LoadIcon(NULL, IDI_APPLICATION); wc.hCursor = LoadCursor(NULL, IDC_ARROW); wc.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH); wc.lpszMenuName = NULL; //メニュー名 wc.lpszClassName = (LPCSTR)szClassName; wc.hIconSm = LoadIcon(NULL, IDI_APPLICATION); return (RegisterClassEx(&wc)); }

この関数は登録するウィンドウクラスのアトム値を返します。 いつもと同じです。

//ウィンドウの生成 BOOL InitInstance(HINSTANCE hInst, int nCmdShow) { HWND hWnd; hWnd = CreateWindow(szClassName, "猫でもわかるアトム",//タイトルバーにこの名前が表示されます WS_OVERLAPPEDWINDOW, //ウィンドウの種類 CW_USEDEFAULT, //X座標 CW_USEDEFAULT, //Y座標 240, //幅 122, //高さ NULL, //親ウィンドウのハンドル、親を作るときはNULL NULL, //メニューハンドル、クラスメニューを使うときはNULL hInst, //インスタンスハンドル NULL); if (!hWnd) return FALSE; ShowWindow(hWnd, nCmdShow); UpdateWindow(hWnd); return TRUE; }

いつもと同じです。ウィンドウの大きさを適当な大きさにしています。

//ウィンドウプロシージャ LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp) { int id; static ATOM atom1, atom2, atom3, atomSecond; HDC hdc; PAINTSTRUCT ps; char szBuffer[256]; SYSTEMTIME st; switch (msg) { case WM_CREATE: atom1 = AddAtom("猫でもわかるプログラミング"); atom2 = AddAtom("粂井康孝"); atom3 = AddAtom("htttp://www.kumei.ne.jp/"); SetTimer(hWnd, ID_MYTIMER, 1000, NULL); break; case WM_TIMER: GetLocalTime(&st); atomSecond = AddAtom(MAKEINTATOM(st.wSecond)); InvalidateRect(hWnd, NULL, TRUE); DeleteAtom(atomSecond); break; case WM_CLOSE: id = MessageBox(hWnd, "終了してもよいですか", "終了確認", MB_YESNO | MB_ICONQUESTION); if (id == IDYES) { KillTimer(hWnd, ID_MYTIMER); DestroyWindow(hWnd); } break; case WM_PAINT: hdc = BeginPaint(hWnd, &ps); GetAtomName(atom1, szBuffer, sizeof(szBuffer)); TextOut(hdc, 5, 5, szBuffer, strlen(szBuffer)); GetAtomName(atom2, szBuffer, sizeof(szBuffer)); TextOut(hdc, 5, 25, szBuffer, strlen(szBuffer)); GetAtomName(atom3, szBuffer, sizeof(szBuffer)); TextOut(hdc, 30, 45, szBuffer, strlen(szBuffer)); GetAtomName(atomSecond, szBuffer, sizeof(szBuffer)); TextOut(hdc, 5, 65, szBuffer, strlen(szBuffer)); EndPaint(hWnd, &ps); break; case WM_DESTROY: PostQuitMessage(0); break; default: return (DefWindowProc(hWnd, msg, wp, lp)); } return 0; }

WM_CREATEのところで文字列のATOM値を取得してWM_PAINTのところで ATOM値から文字列を取得して描画してるだけです。

また、WM_TIMERメッセージが来たら現在時刻の秒の整数アトム値を 取得して、ウィンドウを再描画させています。


[SDK第2部 Index] [総合Index] [Previous Chapter] [Next Chapter]

Update 22/Nov/1998 By Y.Kumei
当ホーム・ページの一部または全部を無断で複写、複製、 転載あるいはコンピュータ等のファイルに保存することを禁じます。