This is a holdover from very early versions of the C language
where structure tags, union tags,
and typedefs were kept in the same namespace.
Consequently, you couldn't say
typedef struct XYZ { ... } XYZ;.
At the open brace, the compiler registers XYZ
as a structure tag name, and then when XYZ appears
a second time, you get a redeclaration error.
The standard workaround for this was to make the structure tag name
a minor modification of the typedef name,
most typically by putting the word tag in front.

The C language standardization process separated the structure
and typename name spaces, so this workaround is no longer necessary,
but it doesn't hurt either.
Besides, even if new structures followed the
typedef struct XYZ { ... } XYZ; pattern,
you would just have people asking,
"Why do some structures in winuser.h use
the tagXYZ pattern and others use the XYZ
pattern?
Why can't it just be consistent?"

Next time, why you also don't see the pattern
typedef struct { ... } XYZ very much either.

The more basic question is "why do we need the pattern typedef struct XYX { … } XYZ; at all" (Answer, so we can refer to "struct XYZ" as just "XYZ" is a C program — The designers of C++ wisely put that ability right into the language without needing the typedef"

Anonymous struct types (structs without a tag naming them: `struct {int a, double b} foo={42,3.14};’) have been legal since at least 1989 when ANSI standardized the language; I don’t have a K&R1 handy to check, but I suspect it goes even farther back than that.

You may be thinking of anonymous struct members of another struct: ‘struct foo { struct {int a; double b;}; char *c;};’. The common extension is to allow access to the members of the anonymous inner struct as ‘x.a’ (instead of x.inner.a), but the construct isn’t legal C.

One of the annoyances with this use of typedefs is that VC++ debugger doesn’t know whether to use a type’s real name (“tagXYZ”) or the typedef’d name (“XYZ”). Since a type can be typedef’d to multiple names, it makes sense for it to pick the canonical name, but as a user, that’s not what you usually want to see.

So, why bother typdef’ing at all? Why not just name the struct XYZ?

[Most people would have quickly tired of typing “struct” all the time. After about the tenth time of typing struct DRAWITEMSTRUCT *pdis = (struct DRAWITEMSTRUCT)lParam; you’re going to say “Why can’t we create a typedef for this structure?” -Raymond]

Struct and union field names used to live in the same global name-space too, and this is where tradition to prepend a unique prefix to struct fields is from. As a byproduct, fields weren’t bound to any particular struct type:

It’s an annoyance, actually, because in C++ you can’t derive a class from the the typedef you’re used to see.

In other words, you have to derive a c++ class from ‘tagPOINT’ instead of from "POINT".

I absolutely hate the ‘tag’ stuff in Windows header, because programmers have copied it into their code in many companies I’ve been at, without knowing why. Just like the "LP" typedefs for pointers, or capital VOID.

The reason why there are typedef at all was that in "C" we had to write "struct POINT pt;" when defining a variable. The typedef saves us from having to type the word ‘struct’. In C++, this isn’t necessary, and would be totally transparent for us if it wasn’t for that ‘tag’ prefix, which forces us to be aware that there is a type and a typedef.

C had one namespace for struct and union tags, but typedefs were in the same namespace as variables. C did not automatically define a typedef name when you defined a struct. It was C++ that introduced the implicit definition of a typedef name.

So in C people would write

typedef struct foo { … } foo;

and then they sould refer to the type without mentioning struct.

But when they tried compiling this in C++, the mention of "struct foo" would define the typedef name ‘foo’, and when the compiler got around to the ‘foo’ after then ‘}’, it would complain that ‘foo’ had already been defined.

So to use anything like this in C++ you had to change the structure tag.

I speak from memory – I was a C user in the 70’s, and a C++ implementer in the early nineties. C++ may hae chenged then, of course. I haven’t been tracking it since then.

I think the Windows 1.0 SDK came around the time of MS C 4.0, and the Windows 2.0 SDK came around the time of MS C 5.0. Visual C++ 2.0 was released around the time of NT 3.5 (I wonder how many people believed Win95 was the first version of Windows to run Win32 apps natively). Visual C++ 4.0 was released around the release of Win95. Visual C++ 4.2 was released around the release of NT 4.0 and contained the beta of several SDKs, including the ActiveX SDK. 4.2c was released to patch them up to released versions. Visual C++ 6.0 was released around the release of Win98, but still contained the NT 4.0 headers and libraries.