Why I don't like hungarian notation - yes, this is my biased opinion.

1. It results in an unreadable mess - how do you pronounce pszMyString. Some of the longer ones take way too much time trying to work your way through them.
Personally, I prefer my code to be readable, this kind of cryptic crap just gets in the way of me reading code.

2. There are many bastardised variations - some code the type, some code the scope, some may add qualifers, others just mix and match. Unless you 'get' the particular flavour, the result is pretty meaningless.
Mostly, it seems to be the author's over-reaction to whatever previous bad experience they had, so they go overboard with the naming to try and address that prior issue.

3. There is no means to check the name, because there are so many variants.
Given pszMyString, what would your reaction be to actually finding
double pszMyString;
The compiler certainly isn't going to complain, it's just another symbol and so long as it makes sense it couldn't give a monkeys about the name.

4. Primitive types like int and double are first class types and everything else is lower class.
I mean, given struct coord { int x, int y }; one could argue that you should declare
coord structContaining_IntX_IntY_MyVariable;
rather than saying 'st' is the prefix for all structures eg.
coord stMyVariable;
Obviously that gets completely stupid for large and nested structures.

The st is of course meaningless, because all those .member and ->member references really give the game away.

5. Portability is lost.
Say during some maintenance phase you decide you want an unsigned long for something rather than an unsigned short. Instead of just changing the type, you have to hunt through all the code and change all the 'us' variables into 'ul' variables. How often is this done - not as often as you might imagine. Unless you have a really good editor, global replace of such short sequences is bound to come unglued, so few attempt it.

6. typedef unsigned long colour_t;
Now is this a 'ul' variable, or do you name it something else?
That is, do you smash your way through the abstraction to the core underlying type or do you name it something else?

7. If you have a class which is completely abstracted, that is you can only access it via it's published methods, then you simply have no information about its insides to even begin to give it some cryptic prefix.

8. Today, features such as intellisense are perfectly capable of giving you the actual information rather than you having to manually extract it from a possibly incorrect name.

You might be able to make it consistent in a short-lived personal project, but in a commercial environment, it just breaks down over time if there is no strong code review or enforced checking tools.