VB6 has a broken type system - in fact it has two type systems that are not totally compatible. Architecturally, VB4-6 are a fairly thin wrapper over COM, and use COM's type system. Previous versions of VB had their own type system, which was sort of a cross between traditional BASIC and C. The two can't be freely mixed and matched.
There is no inheritance and no real exception handling, so expect to write a lot of boilerplate code for error handling and basic form functions repeated over and over. This is where VB gets its reputation for cut-and-paste software engineering.
Some of the types you can declare in VB are not 'automation compatible', which means that they cannot be serialised over a COM boundary or stored in a Variant (more on those later). These types date back to pre-VB4-6 days when VB did not support COM.
One of these types is a record (like a c struct) type whose name escapes me, so an expandible collection or associative array of structs (which is a natural thing that one might want to do) is not possible. Defining a class (see below) is possible but somewhat clumsy.
VB does not support multi-threading, and the workarounds for this have many gotchas. The first of these will potentially bite you if you are doing 3-tier development using MTS or COM+. Creating VB module actually creates a singleton COM object behind the scenes. This will live in its own single-threaded apartment. Apartments are essentially lightweight running COM servers with a serialisation/deserialisation mechanism (called a Message Pump) where calls get serialised and queued for a single thread. If you do the (on the surface of it) sensible thing and try to modularise your code you will create hot-spots in your middle-tier. The solution: more cut and paste.
The second major gotcha is that COM's garbage collection is rather basic - a simple reference counting mechanism. This means that COM components that crash or for some reason don't tidy up after themselves leak memory. Remember how VB6 is just a thin layer over COM? This tight coupling means that you have to be fairly careful when using UI management code that holds references to controls, OLE automation on external applications (e.g. Excel) or anything else that sets up references. VB is quite good at doing hidden stuff behind your back and not knowing when to clean up after itself. It is also a source of circular references generated behind the scenes. Get this wrong and it will leak resources - you need to be careful about this.
The other major gotcha is Variants. The best description I've seen for a Variant type is a 'Spreadsheet Cell'. These can cause quite a lot of mischief, especially Variant Arrays. Many API's will only work with variants or have random parts that use variants (Excel does this a lot) so you won't always be able to avoid them. If you're serialising stuff over COM boundaries (for example multiple disconnected Recordsets) you will soon learn to loathe Variant Arrays.
You will probably find that VB's type system is so broken that the easiest way to maintain a non-trivially complex data structure is to do a library that encodes it in a string and essentially serialises and de-serialises it. Complex data structures in a VB6 app are almost a non-starter.
Finally, after using the GUI toolkit for VB6, you will come to learn just how much the team that did WinForms learned from the VB6 team's mistakes.
Although it was promoted as being simple and easy to use, building a non-trivial applicaiton in VB without making a mess was a lot harder than it looked due to all of the architectural flaws and little gotchas. It's quite a good example of Spolsky's Law of Leaky Abstractions..
Appleman's Developing COM/ActiveX Components in Visual BASIC 6 has quite a good treatment of the ins and outs of COM's interaction with VB6. He also did quite a good one on Win32 and VB programming..
P.S. (thanks for reminding me Daok), if you find someone's been using On Error Resume Next
, you have my permission to head-butt them.