|
|||||||||||||||||||||||
|
|||||||||||||||||||||||
|
Announcements
Services
Chapters
Feature Zones
|
Version 1.1IntroductionI've spent most of the last year developing and playing with a skinning system, two elements of which I have previously posted to CodeProject (see 'A Revolutionary New Approach to Custom Drawn Menus' and 'A template class for easy implementation of Windows hooks'). Achieving good results in window skinning requires an exacting knowledge of exactly what Windows messages are sent to whom and when. In the past, like many of you, I would reach for Spy++ and/or generate reams of TRACE statements and then stare for what seemed like hours trying to make sense of the output. Just recently though, a number of specific issues had really begun to bug me:
Out of this was born InterSpy, an integrated Windows message tracing utility, which solves all the problems I previously outlined and provided me with hours of enjoyment. Important NoteThis utility requires you to build some source code into your application and cannot therefore be applied to a 3rd party application (unless you also have the source code). The challengeBecause this solution requires the inclusion of source code, the greatest challenge was to create something simple and accessible; that could be used with the minimum of fuss but giving the maximum result. I happy to agree that I probably haven't reached that goal, but I find its always a useful place to aim for. The following positive attributes were sought:
The solutionThe first 'problem' to solve was how to get a handle on all the Windows messages flowing through an application. The simplest solution to this I've found is to use application-wide Windows hooks. Note: In the interest of those who do not care for Windows hooks I did spend sometime investigating the possible use of To implement this I used CHookMgr which removes the ugly hooking details and simply requires the overriding of a few virtual functions to handle the message hooks. As far as I can tell, the required Windows hooks to trap all Windows messages are The next step was to decide what to do with the messages. Coming from an engineering background, I always favor figuring out the larger elements of a project before doing too much detail. That way, if I stumble up against something nasty in the woodshed (joke requiring some knowledge of an English dramatized play called 'cold comfort farm') I will not have wasted too much hard work. It was already obvious that the messages would need to be sent to a separate window but the 'where, what and how' had not been decided. My first prototype created a window in the same process as the application that was being traced, but the biggest problem was that the window was destroyed when the application terminated, which was an unacceptable 'feature'. I was also interested in the possibility of outputting to a Visual Studio tool window, but not knowing the first thing about writing plug-ins for Visual Studio, rather put the dampeners on that idea. So I was left with creating a separate application with a specially registered class name so that the code built into the client application could find it easily. The only other architectural issue to resolve was the means of communicating between two, although strictly the communication is only one-way. I'd used Implementation detailsClient-side (code built into the application)One complication of having a sort-of client-server architecture is that the two sides do not share the same address space. What this means simply is that the message processing would have to be done on the client side and not in the logging window, as I had initially wanted (remember: my first prototype created the logging window in the same process as the application to take advantage of the shared address space). This was a nuisance because I had wanted to keep the source code to be compiled into the client application to be the absolute minimum necessary. Oh well, plans of mice and men and stuff ... All Windows messages essentially take the same form: that of the MSG structure. However, after that, every one is different in how the Some messages have no parameters, some use only one parameter and some use both parameters. Further, whilst most often the parameters are used to supply simple I therefore first decided to implement a simple base-class message handler, Then, taking a pointer from MFC, I wrote a message map of sorts (implemented using macros) to assign an instance of this class to all the possible Windows messages I could find (and then some). These include: all the standard messages, the MFC specific messages in afxpriv.h and a bunch I have come across during my searches of the news groups and my own debugging. Note: I am sure that some of the messages are obsolete but, since these will simply not be triggered if that is the case, I see little harm in leaving them in. The obvious and intended benefit of this default message handler is that it allowed me to get the message map working so that I could then build the 'server-side' logging window to receive the messages. Thereafter, it was plain old slog work to implement specific handlers for all the different message types. Fortunately, many messages such as In cracking the messages, you may also note that I have not always gone as far as I might have. e.g. where a parameter describes a window handle ( Server-side (Message logging window)There's not much more to say that cannot be gleaned from the screenshot above. The main output view is a I also like the specific implementation of custom-draw on trees and the fact that you can embolden items just by setting a flag. The logging window currently provides the following 'features' to simplify the output and navigation of messages:
Using the code
Further work
CopyrightThe code is supplied here for you to use and abuse without restriction, except that you may not modify it and pass it off as your own. The concept and design, however, remains my intellectual property. History
|
||||||||||||||||||||||