Introduction
I had the need to use the GlobalAddAtom
and GlobalDeleteAtom
functions and read in the MSDN description that the caller must remember to match the calls to these routines.
Whenever I read comments like that, I immediately think RAII. So here are the wrappers for those routines and all the rest as a bonus.
Background
My usage of these wrappers required a specific breaking of these rules, but I won't bore you with the details of my project. These wrapper classes handled the special case easily.
Using the Code
To use any of the wrapper classes, you may either call the static
functions directly, declare a typedef
of the particular kind you require, or simply use the base types as is.
The following code demonstrates all of the above described use cases and gives a hint as to the reason I wanted to break the rules outline in the MSDN regarding matching up pairs of those calls.
#include <stdio.h>
#include "win32Atom.hpp"
typedef win32::IntegerAtom<win32::GlobalAtom> GlobalIntegerAtom;
int main(int argc, CHAR* argv[])
{
static TCHAR const* atomName = _T("AtomTest");
static unsigned short int intAtomNum = 254;
win32::GlobalAtom ga;
if (argc > 1) {
GlobalIntegerAtom gia(intAtomNum);
switch (toupper(argv[1][0]))
{
case _T('A'):
ga.Increment(atomName);
if (ga) {
_tprintf(_T("Added %s\n"), atomName);
}
else {
_tprintf(_T("Failed to add %s\n"), atomName);
}
break;
case _T('D'):
ga = win32::GlobalAtom::Find(atomName);
if (ga) {
ga.Decrement();
if (!ga) {
_tprintf(_T("Deleted %s\n"), atomName);
}
else {
_tprintf(_T("Failed to delete %s\n"), atomName);
}
}
else {
_tprintf(_T("%s not found\n"), atomName);
}
break;
case _T('F'):
if (win32::GlobalAtom::Find(atomName)) {
_tprintf(_T("Found %s\n"), atomName);
}
else {
_tprintf(_T("%s not found\n"), atomName);
}
break;
case _T('I'):
if (gia.Find(intAtomNum)) {
_tprintf(_T("Found integer atom\n"));
}
else {
_tprintf(_T("Integer atom not found\n"));
}
if (++gia) {
_tprintf(_T("Added integer atom\n"));
}
if (GlobalIntegerAtom::Find(intAtomNum)) {
_tprintf(_T("Found integer atom\n"));
}
else {
_tprintf(_T("Integer atom not found\n"));
}
if (--gia) {
_tprintf(_T("Deleted integer atom\n"));
}
else {
_tprintf(_T("Failed to delete integer atom\n"));
}
break;
}
}
return 0;
}
Here is the win32Atom.hpp file in its entirety:
#if !defined(WIN32ATOM_HPP)
#include <windows.h>
#include <stdexcept>
#include <TCHAR.H>
namespace win32 {
class LocalAtom
{
private:
ATOM mAtom;
public:
LocalAtom(LocalAtom const& that)
: mAtom(that.mAtom)
{}
LocalAtom(ATOM a = 0)
: mAtom(a)
{}
ATOM Increment()
{
std::basic_string<TCHAR> atomName;
UINT len = GetName(mAtom, atomName);
return Increment(atomName.c_str());
}
ATOM Increment(LPCTSTR atomName)
{
ATOM a = Find(atomName);
if (a != mAtom)
{
Decrement();
}
mAtom = Add(atomName);
return mAtom;
}
ATOM Decrement()
{
if (mAtom)
{
mAtom = ::DeleteAtom(mAtom);
}
return mAtom;
}
operator bool() const
{
return mAtom != 0;
}
operator ATOM() const
{
return mAtom;
}
LocalAtom& operator=(LocalAtom const that)
{
if (this != &that)
{
mAtom = that.mAtom;
}
return *this;
}
LocalAtom& operator=(ATOM const a)
{
mAtom = a;
return *this;
}
static UINT GetName(ATOM const a, std::basic_string<TCHAR>& atomName)
{
TCHAR name[256];
UINT len = ::GetAtomName(a, name, sizeof(name)/sizeof(TCHAR));
atomName.assign(name, len);
return len;
}
static ATOM Find(LPCTSTR atomName)
{
return ::FindAtom(atomName);
}
static ATOM Add(LPCTSTR atomName)
{
ATOM a = 0;
if (atomName)
{
a = ::AddAtom(atomName);
}
return a;
}
static bool Initialise(DWORD n)
{
BOOL ok = ::InitAtomTable(n);
return FALSE != ok;
}
};
class GlobalAtom
{
private:
ATOM mAtom;
public:
GlobalAtom(ATOM a = 0)
: mAtom(a)
{}
GlobalAtom(GlobalAtom const& that)
: mAtom(that.mAtom)
{}
ATOM Increment()
{
std::basic_string<TCHAR> atomName;
UINT len = GetName(mAtom, atomName);
return Increment(atomName.c_str());
}
ATOM Increment(LPCTSTR atomName)
{
ATOM a = Find(atomName);
if (a != mAtom)
{
Decrement();
}
mAtom = Add(atomName);
return mAtom;
}
ATOM Decrement()
{
if (mAtom)
{
mAtom = ::GlobalDeleteAtom(mAtom);
}
return mAtom;
}
operator bool() const
{
return mAtom != 0;
}
operator ATOM() const
{
return mAtom;
}
GlobalAtom& operator=(GlobalAtom const that)
{
if (this != &that)
{
mAtom = that.mAtom;
}
return *this;
}
GlobalAtom& operator=(ATOM const a)
{
mAtom = a;
return *this;
}
static UINT GetName(ATOM const a, std::basic_string<TCHAR>& atomName)
{
TCHAR name[256];
UINT len = ::GlobalGetAtomName(a, name, sizeof(name)/sizeof(TCHAR));
atomName.assign(name, len);
return len;
}
static ATOM Find(LPCTSTR atomName)
{
return ::GlobalFindAtom(atomName);
}
static ATOM Add(LPCTSTR atomName)
{
ATOM a = 0;
if (atomName)
{
a = ::GlobalAddAtom(atomName);
}
return a;
}
};
template <typename AtomType>
class StringAtom : public AtomType
{
private:
std::basic_string<TCHAR> mAtomName;
public:
StringAtom(LPCTSTR atomName = NULL)
: mAtomName(atomName ? atomName : _T(""))
{
if (atomName && !mAtomName.empty())
{
Increment(mAtomName.c_str());
}
}
~StringAtom()
{
Decrement();
}
std::basic_string<TCHAR>& Name()
{
if (mAtom && mAtomName.empty())
{
AtomType::GetName(mAtom, mAtomName);
}
return mAtomName;
}
StringAtom& operator++()
{
if (!mAtomName.empty())
{
mAtomName = AtomType::Increment(mAtomName.c_str());
}
return *this;
}
StringAtom& operator--()
{
ATOM ret = 0;
if (AtomType::operator bool())
{
ret = AtomType::Decrement();
}
return *this;
}
};
template <typename AtomType>
class IntegerAtom : public AtomType
{
private:
unsigned short int mAtomInt;
public:
IntegerAtom(unsigned short int n)
: mAtomInt(n)
{
if (mAtomInt < MAXINTATOM)
{
Increment(MAKEINTATOM(mAtomInt));
}
else
{
throw std::range_error(std::string("Integer atom greater than 0xBFFF"));
}
}
~IntegerAtom()
{}
IntegerAtom& operator++()
{
return *this; }
IntegerAtom& operator--()
{
return *this; }
UINT Name(std::basic_string<TCHAR>& atomName)
{
UINT len = 0;
if (mAtom)
{
len = AtomType::GetName(mAtom, atomName);
}
return len;
}
operator bool() const
{
return AtomType::operator bool();
}
static ATOM Find(unsigned short int n)
{
return AtomType::Find(MAKEINTATOM(n));
}
};
}
#endif // WIN32ATOM_HPP
Points of Interest
The code throws a std::range_error
for integer
atoms higher than the maximum value allowed.
I have provided increment
and decrement
operators for both string
and integer
atom types. Even though the integer
ones don't do anything, they act as a form of documentation.
History
- 12th May, 2007: Version 1.0