The first one uses the "new" operator and therefore uses dynamic memory on the "heap". This memory DOES NOT go out of scope when the line that created goes out of scope. You must free / deallocate that memory with the "delete" operator. This can be a good or bad thing. It's good because it gives you more control, bad because it gives you a lot of rope to hang yourself with if you aren't careful.
The second one is the regular old static allocation of a variable, just like creating any variable. No need to delete, less rope to hang yourself with. When to use which? That depends entirely on a lot of factors.
Google "dynamic vs. static memory C++" for some good tutorials.
I know that with the pointer you use the "->" operator to access the object methods, and with the other one you use the "." operator, but what exactly is the difference between them?
In the first declaration, rectangle is a reference to an address where a Shape object happens to be stored. rectangle is not a Shape, it's a container for an address that will be interpreted as a Shape object. This differs from the second declaration where rectangleis a Shape object.
I suspect you're confused by the type of the pointer, Shape*, which says "the address I hold, if not null, will represent an object of type Shape". It's necessary for both pointer arithmetic and type checking, but doesn't change the simple fact that a pointer holds an address, not an object.
For Each ctrl As Control In Me.Controls("pnlMainPanel").Controls
If ctrl.GetType Is GetType(System.Windows.Forms.Panel) Then
For Each subCtrl As Control In ctrl.Controls
If subCtrl.GetType Is GetType(System.Windows.Forms.TextBox) Then
If subCtrl.GetType Is ...