Preface
Four yeas ago, I made a program. Everything WTL originally had was useless except Win32 thin wrappers. As CUpdateUI
was the one of them, I made the replacement by macros. Later, I read the book, C++ Template Metaprogramming, and I was inspired by the sample code, the finite state machine. That could remove the macros and the result was named ketchup, intended to replace BEGIN_MSG_MAP
of ATL/WTL.
In time, the experience of making biscuit gave me the way of avoiding compile-time crashes. Now that ketchup is the type-safe synonym of BEGIN_MSG_MAP
to help WTL catch up the modern programming.
Introduction
Ketchup is a message map generator implemented using class templates. The templates allow us to write type-safe BEGIN_MSG_MAP
.
A simple BEGIN_MSG_MAP
macro snippet:
BEGIN_MSG_MAP(CMainFrame)
MESSAGE_HANDLER(WM_CREATE, OnCreate)
COMMAND_ID_HANDLER(ID_APP_EXIT, OnFileExit)
COMMAND_ID_HANDLER(ID_FILE_NEW, OnFileNew)
COMMAND_ID_HANDLER(ID_APP_ABOUT, OnAppAbout)
CHAIN_MSG_MAP(WTL::CFrameWindowImpl<CMainFrame>)
END_MSG_MAP()
is approximated using Ketchup's facilities as seen in this code snippet:
begin_msg_map
<
message_handler<WM_CREATE, &_::OnCreate>,
command_id_handler<ID_APP_EXIT, &_::OnFileExit>,
command_id_handler<ID_FILE_NEW, &_::OnFileNew>,
command_id_handler<ID_APP_ABOUT, &_::OnAppAbout>,
chain_msg_map< WTL::CFrameWindowImpl<CMainFrame> >
>
end_msg_map;
Requirements
Microsoft Visual C++ .NET version 7.1, WTL 7.5 and Boost C++ libraries (no build required). I did test the demo in Visual C++ .NET standard edition with Visual C++ toolkit 2003. Ketchup itself is a header-only template library.
Quick Start
- Include a header and derive from
ketchup::message_processor<CMainFrame>
: #include "ketchup/ketchup.hpp"
class CMainFrame :
public WTL::CFrameWindowImpl<CMainFrame>,
public WTL::CUpdateUI<CMainFrame>,
public WTL::CMessageFilter, public WTL::CIdleHandler,
public ketchup::message_processor<CMainFrame>
{
- Define message handlers:
private:
LRESULT OnCreate(UINT , WPARAM ,
LPARAM , BOOL& )
{
HWND hWndCmdBar = m_CmdBar.Create(m_hWnd, rcDefault,
NULL, ATL_SIMPLE_CMDBAR_PANE_STYLE);
m_CmdBar.AttachMenu(GetMenu());
}
- Let
CMainFrame
a message map: public:
begin_msg_map
<
message_handler<WM_CREATE, &_::OnCreate>,
command_id_handler<ID_APP_EXIT, &_::OnFileExit>,
command_id_handler<ID_FILE_NEW, &_::OnFileNew>,
command_id_handler<ID_VIEW_TOOLBAR, &_::OnViewToolBar>,
command_id_handler<ID_VIEW_STATUS_BAR, &_::OnViewStatusBar>,
command_id_handler<ID_APP_ABOUT, &_::OnAppAbout>,
chain_msg_map< WTL::CUpdateUI<CMainFrame> >,
chain_msg_map< WTL::CFrameWindowImpl<CMainFrame> >
>
end_msg_map;
- Finally, override
CMessageMap::ProcessWindowMessage
as BEGIN_MSG_MAP
insidiously does, using process_window_message
provided by ketchup::message_processor<CMainFrame>
: virtual BOOL ProcessWindowMessage(HWND hWnd, UINT uMsg,
WPARAM wParam, LPARAM lParam, LRESULT& lResult, DWORD dwMsgMapID = 0)
{
return process_window_message(hWnd, uMsg, wParam,
lParam, lResult, dwMsgMapID);
}
};
Bear in mind that declarations of message handlers should be placed before the entry and C++ Standard doesn't allow you to abbreviate the syntax of member function pointers.
Points of interest
The last point is the performance. The program size seems not to be a problem. VC++ 7.1 generates the same size program as the original one, because Ketchup's message map is almost same as BEGIN_MSG_MAP
. But VC++ 7.1 can't inline message handlers, unlike BEGIN_MSG_MAP
. Could this be a problem of the speed?
Well, I did not intend to emulate the appearance of BEGIN_MSG_MAP
. It is not just a syntax sugar but the coincidence as a result of naming consistency with ATL/WTL. It was an amazing discovery for me.
By the way, Ketchup must be the first application using Boost.Xpressive
for the implementation.
References
History
- 23rd May, 2005 - version 0.910 (Initial release).
- 27th May, 2005 - version 0.940.
- 30th May, 2005 - version 0.950 (
class_trace
and debugging_entry
added).
- 12th Jun, 2005 - version 0.951 (
debugging_entry
removed; empty_entry
and debug_entry
added).
- 20th Jul, 2005 - version 0.9992.