However, if you are trying to paint the non-client areas of windows that are out of process, and that you do not own, you will need to resort to the good old Windows API. You will need to install a global system hook, like the WH_GETMESSAGE hook and capture the messages as they arrive at the target window, and handle them yourself with your own painting code. You will need to resort to the GDI Api functions, or create a managed library using .NET classes to handle your drawing functions. So in that regard, yes you could do it without completely relying on the unmanaged GDI functions, but at some level you will need unmanaged functions to get the hooks installed.
The default windowing system will handle painting of all non-client areas without any help from you, and they handle quite a good deal of rather complex drawing. This is not for the slight of heart, and will be prone to very difficult debugging sessions if you go the route of hooking other windows. System wide or global hooks are notoriously hard to debug, and have extremely adverse effects on the system as a whole if not implemented properly and in a safe fashion. A very good example of a program suite that does just this is the line of products by Stardock. The Object desktop and Object bar apps implement system wide hooks to "skin" the look and feel of your windows by drawing the non-client areas of all the windows in the system. If you've ever ran programs like this you will know that they are often bug ridden and prone to strange crashes and errors.
You should also note that in order to implement the needed system wide hooks you will have to use a language that supports function exporting, such as C/C++ or Delphi. C#, VB, and others are not capable of building unmanaged dlls that export the needed functions to interface with the hooking subsystem at a global level in certain cases. You may want to argue that point, and yes I have seen implementations of app wide hooks written in managed code like C#, but for system wide hooks, you will take a severe performance hit as the dll containing the hooking functions will be loaded into every process in the system. This is known as dll injection.
Dll injection can be no big deal if done properly, but loading a managed dll that brings with it other runtimes, or that needs further just in time compiling is simply going to bog down the system, and never perform as well as a properly written unmanaged C dll of the same nature.
If you are serious about trying to create a non-client drawing application, weigh these topics I've laid out before you very carefully as you consider your options. Get familiar with C/C++ or Delphi, and learn your window messages first. Also, start out by just trying to override the default non-client painting of windows in your own process, thereby eliminating the need for hooks to get at the messages. Trying to learn this stuff in small increments will eventually save you a large headache and keep you on track to your final goal.
This was first published in November 2004