Ok, I'm going to concentrate on the shared project part of your question, since I've just come from a workplace where we had multiple projects and multiple shared projects in subversion.
The first thing I'd suggest as being crucial is that you start working with the following idea: "Doing a checkout of the trunk of a project anywhere on the hard disk is all that's required to be able to build the solution"
Also remember that working copies with no changes have no value. It shouldn't matter where on disk you check things out and deleting a working copy shouldn't start you panicking as you can just checkout trunk again and start up straight away. I found at my previous places a great deal of care is taken "crafting" the development environment and getting everything in just the right place. This is absurd, and time spent doing this is never got back. Do it once, do it in a decent source control (like svn, or git, or TFS) and be happy that you can now through working copies around like yesterdays newspaper.
The only time a working copy has any value is if there are any modifications that haven't been committed. Any valuable working copy is vulnerable. Always get modifications committed as soon as is feasible. Any form of hard-drive failure (including working copy corruption), accidental deletions, changes from something that works to something that doesn't, etc will have the potential to loose a lot of your work - that's the valuable bit. If your half baked code isn't fit to be seen in the trunk of a project, make a branch and commit to that.
This means that you'll be able to checkout multiple versions of the same project in different locations on your drive and work on them (eg, development and live-bugfixing versions). It also means that checking out the trunk will bring down all dependant libraries underneath that working copy folder.
It also means that having IDE level definitions of where headers/libraries are located just won't work. This was a terrible idea that visual studio introduced, but they do also let you specify this stuff using relative folders in individual project settings - where it should be. Trust me, if you're using IDE level location definitions, at some point you're going to be building your app and trying to work out why your changes aren't appearing. Then you'll get that sinking feeling when you realise you've just built your last 3 releases against an old, buggy version of a library. At least I did.
To get to this utopian situation, you'll be a lot better off if you consider each project & library (eg, CoolApp, CFoo, ThisControl, CWidget) as separate projects with separate release cycles, trunks, et al. Move towards thinking of these things independantly, developing and releasing them separately.
This sounds like a lot of overhead, but if you want to make changes to a shared component without breaking other projects that use it - it's a necessity.
With that in mind, I'd suggest you structure your repository something like this:
/Projects
/CoolApp
/trunk
/branches
/tags
/Libraries
/CFoo
/trunk
/branches
/tags
/CWidget
/trunk
/branches
/tags
/ThisControl
/trunk
/branches
/tags
/Vendor
/NUnit
/current
/1.6
/1.7
If your repository isn't currently setup like that, you can use svncopy to structure it. You could use a tags/trunk/branches at the top level and everything underneath, but in my view doing that makes conceptually separating the projects more difficult.
Now checkout just the trunk of your main project (CoolApp). Of course - this won't build as is, because none of the dependant projects are there.
The next step is to add the other projects as externals. On the top level folder of your working copy using tortoisesvn right click and go to svn->properties. Add a new property named "svn:externals". Define properties in the format
/repository_location[@revision] working_copy_folder
So for coolapp, you might add the following svn:externals definition:
/Libraries/CFoo/trunk CFoo
/Libraries/CWidget/trunk CWidget
/Libraries/ThisControl/trunk ThisControl
When that's done, commit the changes, then do an "Update" and your externals will be brought down as well.
You can build any working copy folder structure you like using this form of externals definition. You will have to modify your solution file to look for the projects in their new location, but this isn't usually a big problem.
Once you're up and working this way, take note that it's generally a very bad idea to have externals pointing to a trunk. This is because when the library's trunk changes because of another project, when you do a new checkout of your solution (or an update), suddenly your perfect solution won't build - even though you didn't think you changed anything in it.
Start making tags for your libraries and point your externals at them instead. This is when you start thinking of your libraries as separate projects in their own right.
This is a situation for another principle: "Any changes to the project MUST have a corresponding revision in the trunk of the main project" Changing the externals location to point to a new library version is a perfect example of being able to say "Hey, I'm now using version 2 of foolib here". The problem in the previous paragraph was because the code changed "underneath" you.
To modify a library you'd ideally checkout a working copy of that library's trunk, modify it and tag it with a new version number. Then in the main project, change the external to point to the new tag and Update.
You can shortcut this process by "switching" your library location from the tag to trunk. That way, when you commit, you'll commit the library changes to trunk. Working this way, however, you'll need to remember that the external still points to the tag - you'll still need to tag your library up and change the project external or a new checkout won't build.
If your rely on any 3rd party tools, like nAnt or nUnit - add them to the repository as vendor branches and reference them through externals. VS allows you to reference dll's by browsing for them, which is more flexible than from the GAC. It might not sound like much of a problem for a single developer, but if you try to upgrade nUnit one project at a time, you'll see how much nicer it is to be able to checkout the trunk of your project and know that you've got the right version of nUnit along with it (rather than then having to uninstall nUnit and reinstall the right version).
Please also note that it's not necessary to have every project in your solution as a separate external. It's only the things that can or should be shared amongst different projects that should be separated out.
Finally, once you're up and running, I'd really suggest using a build engine, like CruiseControl.Net or Hudson(my favourite). This gives you rapid feedback of any problems before they get under the radar and bite you from behind.
Ok, I'll stop now, I didn't intend to go for a "Longest answer" badge.