EternalWindows
グローバルアトム / ローカルアトム

アトムとは文字列を一意に識別する値のことですが、 この文字列は必ずしもグローバルアトムテーブルに格納されたものである必要はありません。 1つのアプリケーションはローカルアトムテーブルというものを持っており、 このテーブルに文字列を格納した場合は、 そのアプリケーション内で一意なローカルアトムが返ります。 もし、アプリケーションが複数の文字列を管理する必要がある場合は、 その文字列をローカルアトムテーブルに格納してみると面白いでしょう。 そうすると、ローカルアトムからいつでも関連する文字列を取得できますし、 特定の文字列がローカルアトムテーブルに存在するかを調べることもできます。

ローカルアトム系の関数の使い方は、グローバルアトム系の関数の使い方とよく似ています。 ローカルアトムテーブルに文字列を格納するには、AddAtomを呼び出します。

ATOM WINAPI AddAtom(
  LPCTSTR lpString
);

lpStringは、ローカルアトムに格納したい文字列を指定します。 戻り値は、格納された文字列を識別するローカルアトムです。

ローカルアトムテーブルから文字列を削除するには、DeleteAtomを呼び出します。

ATOM WINAPI DeleteAtom(
  ATOM nAtom
);

nAtomは、削除したい文字列を識別するローカルアトムを指定します。

ローカルアトムに関連する文字列を取得するには、GetAtomNameを呼び出します。

UINT WINAPI GetAtomName(
  ATOM nAtom,
  LPTSTR lpBuffer,
  int nSize
);

nAtomは、取得したい文字列を識別するローカルアトムを指定します。 lpBufferは、文字列を受け取るバッファを指定します。 nSize、lpBufferのサイズを指定します。

ローカルアトムテーブルから文字列を検索するには、FindAtomを呼び出します。

ATOM WINAPI FindAtom(
  LPCTSTR lpString
);

lpStringは、検索したい文字列を指定します。 戻り値は、文字列に関連するローカルアトムになります。

ATOM型の変数を返す関数としては、ウインドウクラスの登録に使用するRegisterClassExがあります。 しかし、この関数が返すATOMはシステム内部に存在するアトムテーブルで意味を持ため、 GetAtomNameやGlobalGetAtomNameに指定しても関連する文字列を取得することはできません。 RegisterClassExで登録したウインドウクラスは、アプリケーション内で意味を持つため、 当初はローカルアトムテーブルが使われていると考えていたのですが、そのようなことはないようです。 こうしたことからも分かるように、ローカルアトムテーブルに何からの文字列が既に格納されていることは基本的にないといえるでしょう。 ローカルアトムテーブルに格納できる文字列の数は既定で37とされていますが、これを変更するにはInitAtomTableを呼び出します。

今回のプログラムは、エディットコントロール上に入力された文字列が ローカルアトムテーブルに存在するかを調べます。

#include <windows.h>

#define ID_BUTTON 100

LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);

int WINAPI WinMain(HINSTANCE hinst, HINSTANCE hinstPrev, LPSTR lpszCmdLine, int nCmdShow)
{
	TCHAR      szAppName[] = TEXT("sample");
	HWND       hwnd;
	MSG        msg;
	WNDCLASSEX wc;

	wc.cbSize        = sizeof(WNDCLASSEX);
	wc.style         = 0;
	wc.lpfnWndProc   = WindowProc;
	wc.cbClsExtra    = 0;
	wc.cbWndExtra    = 0;
	wc.hInstance     = hinst;
	wc.hIcon         = (HICON)LoadImage(NULL, IDI_APPLICATION, IMAGE_ICON, 0, 0, LR_SHARED);
	wc.hCursor       = (HCURSOR)LoadImage(NULL, IDC_ARROW, IMAGE_CURSOR, 0, 0, LR_SHARED);
	wc.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
	wc.lpszMenuName  = NULL;
	wc.lpszClassName = szAppName;
	wc.hIconSm       = (HICON)LoadImage(NULL, IDI_APPLICATION, IMAGE_ICON, 0, 0, LR_SHARED);
	
	if (RegisterClassEx(&wc) == 0)
		return 0;

	hwnd = CreateWindowEx(0, szAppName, szAppName, WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, hinst, NULL);
	if (hwnd == NULL)
		return 0;

	ShowWindow(hwnd, nCmdShow);
	UpdateWindow(hwnd);
	
	while (GetMessage(&msg, NULL, 0, 0) > 0) {
		TranslateMessage(&msg);
		DispatchMessage(&msg);
	}

	return (int)msg.wParam;
}

LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
	static HWND hwndEdit = NULL;
	static ATOM atom = 0;

	switch (uMsg) {

	case WM_CREATE:
		hwndEdit = CreateWindowEx(0, TEXT("EDIT"), TEXT(""), WS_CHILD | WS_VISIBLE | WS_BORDER, 30, 30, 150, 25, hwnd, (HMENU)1, ((LPCREATESTRUCT)lParam)->hInstance, NULL);		
		CreateWindowEx(0, TEXT("BUTTON"), TEXT("確認"), WS_CHILD | WS_VISIBLE, 190, 25, 60, 30, hwnd, (HMENU)ID_BUTTON, ((LPCREATESTRUCT)lParam)->hInstance, NULL);
		SetFocus(hwndEdit);

		AddAtom(TEXT("abc"));
		return 0;

	case WM_COMMAND:
		if (LOWORD(wParam) == ID_BUTTON) {
			TCHAR szText[256], szBuf[512];
			
			GetWindowText(hwndEdit, szText, sizeof(szText) / sizeof(TCHAR));
			if (FindAtom(szText) != 0) {
				wsprintf(szBuf, TEXT("%sは存在します。"), szText);
				MessageBox(NULL, szBuf, TEXT("OK"), MB_OK);
			}
			else {
				wsprintf(szBuf, TEXT("%sは存在しません。"), szText);
				MessageBox(NULL, szBuf, NULL, MB_ICONWARNING);
			}
		}
		return 0;

	case WM_DESTROY:
		DeleteAtom(atom);
		PostQuitMessage(0);
		return 0;

	default:
		break;

	}

	return DefWindowProc(hwnd, uMsg, wParam, lParam);
}

WM_CREATEではコントロールを作成するだけでなく、AddAtomも呼び出しています。 これにより、abcという文字列がローカルアトムテーブルに格納されます。 ボタンが押されたらWM_COMMANDが送られ、GetWindowTextで入力された文字列を取得します。 この文字列がabcであるならば、FindAtomは文字列の検索に成功することになります。


戻る