There isn't a reason that they
have to be used or anything of the sort. They're used for essentially two reasons:
- That using them expresses the intent of the value better (for example, this parameter isn't meant to be a number, but a certain bit sequence [in the case of a WORD/DWORD] or this is meant to be a pointer to a sequence of values in memory [that could be anything; in the case of a WORD */DWORD *]).
- That using them allows your code to be more easily ported to different architectures with different sizes for WORD's/DWORD's (which, of course, is likely something that's never going to happen with an average programmer's code, but it is a possibility nonetheless).
But, I basically just lied, they're mostly used because people see them in Microsoft's example code, in the tutorials for the WIN32 API, in the headers and in Intellisense™, so people use them just in case or to be consistent (or, once in a blue moon, for the bullets above).
And, they are interchangeable in general, but it's still a better idea to use the API's types when working with it (if just for consistency, assurance of correct types or superstition).