|
|||||||||||||||||||||||
|
|||||||||||||||||||||||
|
Announcements
Services
Chapters
Feature Zones
|
IntroductionI recently submitted a menu skinning article which used global Windows hooks to subclass all the menus in an application so that the standard Windows rendering of the menus could be overridden by the application. The code for implementing the Windows hooks was fairly standard boilerplate code which I'd also used elsewhere and which I cut and pasted into the menu project. It bugged me though that I still hadn't been able to see a solution whereby I didn't have to keep cutting and pasting the same code into new projects whenever I wanted a Windows hook. Then, a few days ago, I read Shog9's excellent Balloon Help
article about a replacement for What particularly caught my eye was the use of thunking to pass a class member function as a callback to a Windows function which would normally only accept a global callback function. (I suggest you read the article if you want to know more about thunking.) Note: the reason why this is so interesting is that many Windows global callback functions are a pain because there is often no facility to pass a user-defined piece of data (such as pointer to a class object) to allow the callback to be used in different contexts by different classes. So here was a way to get around the global callback problem, albeit (after the excitement had died down) a rather tricky way. You see, in this context, the thunk is effectively a piece of self-modifying code which, for someone who has always understood self-modifying code to be a big no-no, struck me as something I might want to avoid, since if it went wrong I wouldn't know how to fix it robustly. However, due credit; it pointed me in the right direction for how to solve the global callback problem: templates. I have to admit that I have been really tardy in getting to grips with templates. The principle issue is that without enough concrete experience of templates, I have tended to be unable to spot when they might be a useful solution to a given design problem, and without the benefit of implementing many template solutions I am unable to gain further insight into when best to use them, and so it goes on... But once the seed had been planted, it all seemed so obvious. By templatizing (is that a real word?) a base class, any class deriving from that base class could acquire its own set of static callback functions which would be entirely different to those of another derived class. Granted, separate instances of the same class would still have to share a single function 'instance' but my particular experience of Windows hooks is that the classes I've written have always been singleton classes for the purpose of providing application wide hooking. Note: if the base class was not templatized (there's that word again), then any static class functions would be the same, regardless of where you were in the class hierarchy, giving you no added benefit. The implementationWith the design figured out, this turned out to be a fairly trivial task.
Essentially, I implemented a fairly standard singleton class and then added
templates to it. (Note: as I understand it, there is no need to provide a
default copy constructor if the singleton
I also did the grunt work of adding the static functions for most of the Windows hooks, together with virtual equivalents that the derived class could override for the hooks it required. Note: if you request a specific type of hook and then do not provide a
handler for it, the base class will assert. This is similar to MFC's
implementation of ownerdraw where
Using the code
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. History
Notes
|
||||||||||||||||||||||