f



Those dang window message dispatcher macros again, too unclean?

Typical usage in workgin toy program:

         auto on( winapi::Message const& m ) noexcept
             -> winapi::Lresult
             override
         {
         #define WINAPI_MESSAGE_HANDLER_CLASS Main_window
             switch( m.message_id )
             {
             WINAPI_DISPATCH( m, WM_COMMAND, on_wm_command );
             WINAPI_DISPATCH( m, WM_PAINT, on_wm_paint );
             WINAPI_DISPATCH( m, WM_SIZE, on_wm_size );
             }
             return subclassing_.original_processing( m );
         #undef WINAPI_MESSAGE_HANDLER_CLASS
         }

Definitions:

     // These macros dispatch a window message to a member function via 
the message
     // cracker macros in <windowsx.h>. For example, message name 
WM_PAINT yields
     // a call via the HANDLE_WM_PAINT message cracker macro. See 
<windows.h> for
     // the required signatures for handlers; remove the window handle 
argument.

     // #define WINAPI_CRACKER_MACRO( message_name ) HANDLE_ ## message_name

     #define WINAPI_DISPATCH_TO_MEMFN_VIA( message_cracker_macro, 
memfunc, m ) \
         message_cracker_macro ( \
             this, m.wparam, m.lparam, std::mem_fn( &memfunc ) \
             )
     #define WINAPI_DISPATCH_TO_MEMFN( message_name, memfunc, m ) \
         WINAPI_DISPATCH_TO_MEMFN_VIA( HANDLE_ ## message_name, memfunc, m )

     #define WINAPI_DISPATCH( m, message_name, handler ) \
         case message_name: return WINAPI_DISPATCH_TO_MEMFN_VIA( \
             HANDLE_ ## message_name, 
WINAPI_MESSAGE_HANDLER_CLASS::handler, m \
             )

I've done this so many times in the past, with C++03. But I feel that 
there must be some less unclean modern C++-ish way. Ideas?

Cheers!,

- Alf
0
Alf
12/22/2016 4:09:57 AM
comp.lang.c++ 49423 articles. 7 followers. Post Follow

9 Replies
478 Views

Similar Articles

[PageSpeed] 50

[Please do not mail me a copy of your followup]

"Alf P. Steinbach" <alf.p.steinbach+usenet@gmail.com> spake the secret code
<o3fjk8$c40$1@dont-email.me> thusly:

>I've done this so many times in the past, with C++03. But I feel that 
>there must be some less unclean modern C++-ish way. Ideas?

My question is:

Why are you reinventing the wheel?

These message cracker macros have already been done in the Windows
headers, MFC and ATL.

ATL is now available with Community Edition, so there is no longer a
dollar cost to selecting ATL for use in your program.
-- 
"The Direct3D Graphics Pipeline" free book <http://tinyurl.com/d3d-pipeline>
            The Terminals Wiki <http://terminals-wiki.org>
     The Computer Graphics Museum <http://computergraphicsmuseum.org>
  Legalize Adulthood! (my blog) <http://legalizeadulthood.wordpress.com>
0
legalize
12/22/2016 8:51:04 PM
On 22.12.2016 21:51, Richard wrote:
> [Please do not mail me a copy of your followup]
>
> "Alf P. Steinbach" <alf.p.steinbach+usenet@gmail.com> spake the secret code
> <o3fjk8$c40$1@dont-email.me> thusly:
>
>> I've done this so many times in the past, with C++03. But I feel that
>> there must be some less unclean modern C++-ish way. Ideas?
>
> My question is:
>
> Why are you reinventing the wheel?

Well I'm not, but I'm reimplementing my wheels from scratch for 
umpteen'th time.


> These message cracker macros have already been done in the Windows
> headers, MFC and ATL.

The macros above delegate the cracking (de-serialization, so to speak) 
to the Windows C API macros.

MFC and as I recall also ATL/WTL use message maps: they're ungood.

MFC and ATL do not really ease anything except the basic window 
creation, which is a single little job to put together. In exchange for 
providing a default implementation of window creation (and at one time, 
providing print preview and COM boiler plate code) they impose a steep 
programmers' time overhead: one has to do detective work for every other 
little detail. MFC suffered from being deliberately dumbed down from the 
original AFX framework goals, and from being a 1990's design, while 
ATL/WFC suffers from being designed by incompetents, including the goal 
of running ActiveX controls in a browser (imagine that idea! shudder!), 
even though there's some modern C++ stuff like templating.


> ATL is now available with Community Edition, so there is no longer a
> dollar cost to selecting ATL for use in your program.

I think maybe you mean WTL, which was derived from ATL.

Unless they've rebranded, which they sometimes do?


Cheers!,

- Alf

0
Alf
12/22/2016 10:22:35 PM
[Please do not mail me a copy of your followup]

"Alf P. Steinbach" <alf.p.steinbach+usenet@gmail.com> spake the secret code
<o3hjkv$966$1@dont-email.me> thusly:

>> ATL is now available with Community Edition, so there is no longer a
>> dollar cost to selecting ATL for use in your program.
>
>I think maybe you mean WTL, which was derived from ATL.

WTL was always free, but it built on ATL which wasn't free until the
recent versions of VS Community Edition.
-- 
"The Direct3D Graphics Pipeline" free book <http://tinyurl.com/d3d-pipeline>
            The Terminals Wiki <http://terminals-wiki.org>
     The Computer Graphics Museum <http://computergraphicsmuseum.org>
  Legalize Adulthood! (my blog) <http://legalizeadulthood.wordpress.com>
0
legalize
12/22/2016 11:59:47 PM
"Alf P. Steinbach" <alf.p.steinbach+usenet@gmail.com> writes:

> Typical usage in workgin toy program:
>
>         auto on( winapi::Message const& m ) noexcept
>             -> winapi::Lresult
>             override
>         {
>         #define WINAPI_MESSAGE_HANDLER_CLASS Main_window
>             switch( m.message_id )
>             {
>             WINAPI_DISPATCH( m, WM_COMMAND, on_wm_command );
>             WINAPI_DISPATCH( m, WM_PAINT, on_wm_paint );
>             WINAPI_DISPATCH( m, WM_SIZE, on_wm_size );
>             }
>             return subclassing_.original_processing( m );
>         #undef WINAPI_MESSAGE_HANDLER_CLASS
>         }
>
> Definitions:
>
>     // These macros dispatch a window message to a member function
>     // via the message cracker macros in <windowsx.h>.  [...]
>
> I've done this so many times in the past, with C++03.  But I feel
> that there must be some less unclean modern C++-ish way.  Ideas?

I share your reaction, but what is it you hope to accomplish?  The
definition for WINAPI_DISPATCH can be simplified fairly easily I
think (and get rid of the others), which also could make it possible
to write

    switch( m.message_id ){
        WINAPI_DISPATCH( m, WM_COMMAND, Main_window, on_wm_command );
        WINAPI_DISPATCH( m, WM_PAINT, Main_window, on_wm_paint );
        WINAPI_DISPATCH( m, WM_SIZE, Main_window, on_wm_size );
    }

so the surrounding #define/#undef would not be needed.  But what is
it you are looking for?
0
Tim
12/23/2016 7:02:01 AM
On 12/22/2016 11:22 PM, Alf P. Steinbach wrote:
>
> The macros above delegate the cracking (de-serialization, so to speak)
> to the Windows C API macros.
>
> MFC and as I recall also ATL/WTL use message maps: they're ungood.
>
> MFC and ATL do not really ease anything except the basic window
> creation, which is a single little job to put together. In exchange for
> providing a default implementation of window creation (and at one time,
> providing print preview and COM boiler plate code) they impose a steep
> programmers' time overhead: one has to do detective work for every other
> little detail. MFC suffered from being deliberately dumbed down from the
> original AFX framework goals, and from being a 1990's design, while
> ATL/WFC suffers from being designed by incompetents, including the goal
> of running ActiveX controls in a browser (imagine that idea! shudder!),
> even though there's some modern C++ stuff like templating.
>
>
I agree on all of your critics to MFC/ATL, but I haven't find a good 
dispatch method either.
Basically the problem is to map a (HWND, WM_PAINT) pair to a 
window->on_wm_paint() handler.
I am no fan of switch or maps for this, and it looks to me too that 
there should be a better way to accomplish this - in the end, it is what 
a virtual method call would be for.

If I remember correctly, from a long time ago, Borland's Turbo C++ used 
the extra window bytes to store the window object pointer, and used some 
tweaking of the vtable in place of the switch statement (at least this 
is what it looked like from the sintax I remember). Both of which were 
rather non-portable, but in my memory would be in the direction to a 
better dispatching - obviously if it were done with the facilities 
offered by nowadays's standard.

>
> Cheers!,
>
> - Alf
>

0
Manfred
12/23/2016 2:35:27 PM
On 23.12.2016 08:02, Tim Rentsch wrote:
> "Alf P. Steinbach" <alf.p.steinbach+usenet@gmail.com> writes:
>
>> Typical usage in workgin toy program:
>>
>>         auto on( winapi::Message const& m ) noexcept
>>             -> winapi::Lresult
>>             override
>>         {
>>         #define WINAPI_MESSAGE_HANDLER_CLASS Main_window
>>             switch( m.message_id )
>>             {
>>             WINAPI_DISPATCH( m, WM_COMMAND, on_wm_command );
>>             WINAPI_DISPATCH( m, WM_PAINT, on_wm_paint );
>>             WINAPI_DISPATCH( m, WM_SIZE, on_wm_size );
>>             }
>>             return subclassing_.original_processing( m );
>>         #undef WINAPI_MESSAGE_HANDLER_CLASS
>>         }
>>
>> Definitions:
>>
>>     // These macros dispatch a window message to a member function
>>     // via the message cracker macros in <windowsx.h>.  [...]
>>
>> I've done this so many times in the past, with C++03.  But I feel
>> that there must be some less unclean modern C++-ish way.  Ideas?
>
> I share your reaction, but what is it you hope to accomplish?

Something ... less macro-ish, I guess. :)

Or if you mean what these macros do (i.e. message cracking is not a 
familiar term to you, it is after all very Windows API-level specific), 
they take 64 bits of information in a specific packed message, unpacks 
that into 0 to about 4 argument values depending on the message, and 
calls a specified handler function with those unpacked arguments.

The problem is the knowledge of how to pack/unpack specific messages: it 
is of course documented, but the only API level support for packing, the 
only /code/ for that that can be leveraged, is as far as I know provided 
by the macros from <windowsx.h>.


>  The
> definition for WINAPI_DISPATCH can be simplified fairly easily I
> think (and get rid of the others), which also could make it possible
> to write
>
>     switch( m.message_id ){
>         WINAPI_DISPATCH( m, WM_COMMAND, Main_window, on_wm_command );
>         WINAPI_DISPATCH( m, WM_PAINT, Main_window, on_wm_paint );
>         WINAPI_DISPATCH( m, WM_SIZE, Main_window, on_wm_size );
>     }
>
> so the surrounding #define/#undef would not be needed.

Oh, thanks. :) But I added the #define/#undef mechanism to avoid having 
to repeat the class name. Mostly for convenience and the DRY principle, 
Don't Repeat Yourself, but also because conceivably the class name could 
in some instance be a template expression with commas in it.

(There is a simple workaround for comma in a macro argument, namely 
always enclose that argument in parentheses, and unpack it in the macro, 
but that adds some dirtyness again. Another workaround is to define a 
macro symbol as comma, but that's really dirty.)


>  But what is it you are looking for?

I don't know.

Some really out-of-the-box idea, I guess.

Or maybe there is a library somewhere that (just) provides unpacking of 
most all defined window messages, like that.

Hm, now you me thinking.


Cheers!,

- Alf

0
Alf
12/23/2016 2:50:17 PM
Manfred <noname@invalid.add> writes (sentence order modified):
>Basically the problem is to map a (HWND, WM_PAINT) pair to a
>window->on_wm_paint() handler.
....
>I agree on all of your critics to MFC/ATL, but I haven't find a good 
>dispatch method either.

  What is bothering you most about the dispatch methods that
  you have been using so far? 

0
ram
12/23/2016 3:30:15 PM
"Alf P. Steinbach" <alf.p.steinbach+usenet@gmail.com> writes:

> On 23.12.2016 08:02, Tim Rentsch wrote:
>> "Alf P.  Steinbach" <alf.p.steinbach+usenet@gmail.com> writes:
>>
>>> Typical usage in workgin toy program:
>>>
>>>         auto on( winapi::Message const& m ) noexcept
>>>             -> winapi::Lresult
>>>             override
>>>         {
>>>         #define WINAPI_MESSAGE_HANDLER_CLASS Main_window
>>>             switch( m.message_id )
>>>             {
>>>             WINAPI_DISPATCH( m, WM_COMMAND, on_wm_command );
>>>             WINAPI_DISPATCH( m, WM_PAINT, on_wm_paint );
>>>             WINAPI_DISPATCH( m, WM_SIZE, on_wm_size );
>>>             }
>>>             return subclassing_.original_processing( m );
>>>         #undef WINAPI_MESSAGE_HANDLER_CLASS
>>>         }
>>>
>>> Definitions:
>>>
>>>     // These macros dispatch a window message to a member function
>>>     // via the message cracker macros in <windowsx.h>.  [...]
>>>
>>> I've done this so many times in the past, with C++03.  But I feel
>>> that there must be some less unclean modern C++-ish way.  Ideas?
>>
>> I share your reaction, but what is it you hope to accomplish?
>
> Something ... less macro-ish, I guess. :)
>
> Or if you mean what these macros do (i.e. message cracking is not a
> familiar term to you, it is after all very Windows API-level
> specific), they take 64 bits of information in a specific packed
> message, unpacks that into 0 to about 4 argument values depending on
> the message, and calls a specified handler function with those
> unpacked arguments.

Yes, I read up on those and looked up the definitions in
windowsx.h.

> The problem is the knowledge of how to pack/unpack specific messages:
> it is of course documented, but the only API level support for
> packing, the only /code/ for that that can be leveraged, is as far as
> I know provided by the macros from <windowsx.h>.

If you want to use the supplied support for message cracking, and
that support exists only the form of macros, then I think you're
pretty much stuck with macros.  You can make your own macro
definitions prettier, and maybe do something so that you get
better flow for function/method calls, but unless you're willing
to re-implement (some of) the HANDLE_xxx macro functionality, it
seems like using macros is basically inevitable.


>>  The
>> definition for WINAPI_DISPATCH can be simplified fairly easily I
>> think (and get rid of the others), which also could make it possible
>> to write
>>
>>     switch( m.message_id ){
>>         WINAPI_DISPATCH( m, WM_COMMAND, Main_window, on_wm_command );
>>         WINAPI_DISPATCH( m, WM_PAINT, Main_window, on_wm_paint );
>>         WINAPI_DISPATCH( m, WM_SIZE, Main_window, on_wm_size );
>>     }
>>
>> so the surrounding #define/#undef would not be needed.
>
> Oh, thanks. :)  But I added the #define/#undef mechanism to avoid
> having to repeat the class name.  Mostly for convenience and the DRY
> principle, Don't Repeat Yourself, but also because conceivably the
> class name could in some instance be a template expression with commas
> in it.

Yes, I thought something like that might be true.  However a
similar comment still applies, as for example (disclaimer: not
compiled):

    switch( m.message_id ){
      #define TAKE( E, M ) WINAPI_DISPATCH( m, E, Main_window, M )
        TAKE( WM_COMMAND, on_wm_command );
        TAKE( WM_PAINT,   on_wm_paint );
        TAKE( WM_SIZE,    on_wm_size );
      #undef TAKE
    }

This way at least you won't have hidden dependencies in your
macro definitions.

> (There is a simple workaround for comma in a macro argument, namely
> always enclose that argument in parentheses, and unpack it in the
> macro, but that adds some dirtyness again.  Another workaround is to
> define a macro symbol as comma, but that's really dirty.)

Roger that.  I believe the above technique still applies, with a
parenthesized comma needed in only one macro call.


>>  But what is it you are looking for?
>
> I don't know.
>
> Some really out-of-the-box idea, I guess.  [...]

My sense is there is something to be done here, depending on what
it is you hope to achieve.

One idea (which I haven't worked out in any detail) is to re-do
the functionality of whatever HANDLE_xxx macros you need (and I
don't mean as macros necessarily), in such a way that you can
check your implementation against the macros in <windowsx.h>.
That would let you get away from using the HANDLE_xxx macros,
but not have to worry about some sort of version skew/drift.

One question I have is, what does the message flow look like,
and/or what would you like it to look like?  The idea of bundling
up pointer-to-member-functions (assuming I'm understanding that
right), and passing 'this' as a parameter, is one I find somewhat
repugnant.  But I'm hampered by not understanding what message
flow is being used, and what message flow is ultimately desired.
0
Tim
12/23/2016 8:29:41 PM
On 23.12.2016 21:29, Tim Rentsch wrote:
> "Alf P. Steinbach" <alf.p.steinbach+usenet@gmail.com> writes:
>
>> [snip]
>> Oh, thanks. :)  But I added the #define/#undef mechanism to avoid
>> having to repeat the class name.  Mostly for convenience and the DRY
>> principle, Don't Repeat Yourself, but also because conceivably the
>> class name could in some instance be a template expression with commas
>> in it.
>
> Yes, I thought something like that might be true.  However a
> similar comment still applies, as for example (disclaimer: not
> compiled):
>
>     switch( m.message_id ){
>       #define TAKE( E, M ) WINAPI_DISPATCH( m, E, Main_window, M )
>         TAKE( WM_COMMAND, on_wm_command );
>         TAKE( WM_PAINT,   on_wm_paint );
>         TAKE( WM_SIZE,    on_wm_size );
>       #undef TAKE
>     }
>
> This way at least you won't have hidden dependencies in your
> macro definitions.

I tried roughly that approach at first. But it turned out to be 
difficult to avoid macro expansion of a name like WM_PAINT. Each message 
name expands to some hex number, e.g. 0x000F for WM_PAINT, which would 
generate a macro invocation like HANDLE_0x000F instead of HANDLE_WM_PAINT.

As a language extension Visual C++ supports writing ##WM_PAINT as actual 
macro argument, which prevents expansion. However g++ will have none of 
that.


>> (There is a simple workaround for comma in a macro argument, namely
>> always enclose that argument in parentheses, and unpack it in the
>> macro, but that adds some dirtyness again.  Another workaround is to
>> define a macro symbol as comma, but that's really dirty.)
>
> Roger that.  I believe the above technique still applies, with a
> parenthesized comma needed in only one macro call.
>
>
>>>  But what is it you are looking for?
>>
>> I don't know.
>>
>> Some really out-of-the-box idea, I guess.  [...]
>
> My sense is there is something to be done here, depending on what
> it is you hope to achieve.
>
> One idea (which I haven't worked out in any detail) is to re-do
> the functionality of whatever HANDLE_xxx macros you need (and I
> don't mean as macros necessarily), in such a way that you can
> check your implementation against the macros in <windowsx.h>.
> That would let you get away from using the HANDLE_xxx macros,
> but not have to worry about some sort of version skew/drift.

I think I can maybe add a layer on top, like an extensible collection of 
message-specific dispatcher, starting with ones that can be expressed in 
terms of Microsoft's HANDLE_... macros.


> One question I have is, what does the message flow look like,
> and/or what would you like it to look like?  The idea of bundling
> up pointer-to-member-functions (assuming I'm understanding that
> right), and passing 'this' as a parameter, is one I find somewhat
> repugnant.  But I'm hampered by not understanding what message
> flow is being used, and what message flow is ultimately desired.

Oh, the flow.

The Windows API's support for windowing � GUI stuff � was a sort of 
early 1980's rewrite in C of the GUI ideas from the Xerox PARC Smalltalk 
project, I think (but I'd have to google it to be sure of this claim) at 
least in large part via Apple's participation in Xerox' technology 
transfer program. So it's like a dynamic language OO design, except 
everything is down at the nitty gritty C level, and with Microsoft 
�let's do the entirely unexpected and unpredictable� twists.

Each window object has a single C function that does its message 
processing; the first argument is a handle value that identifies the 
window object. This function is called its �window procedure� (I think 
this may be a terminology transfer from use of Pascal over at Apple). A 
call of a window's window procedure with a given message, corresponds to 
a call of virtual function on a C++ class type object � or a message in 
Smalltalk (I think definitely the �message� terminology here transferred 
from the use of Smalltalk at Xerox PARC and at first over at Apple, with 
Apple's Smalltalk-based Lisa machine, before the Mac).

The window procedure can be invoked directly by Windows, and by the 
application code for messages that it retrieves from a message queue.

The general problem that the API design doesn't directly support in a 
practical way, is to associate a window object with /state/. The design 
only supports uninterpreted raw bytes as state, then accessed in an 
inefficient way as bytes via OS calls. A C++ class type object is much 
more practical as state, then with processing of each message in a 
member function, so every C++ /GUI framework/ replaces the window 
procedure of each window, with one that forwards each call (message 
processing) to a corresponding general window-procedure like member 
function on a C++ object, where ideally the message is unpacked, and a 
corresponding message-specific member function is called with the args.

Cheers!,

- Alf

PS: I have wrapped this thing earlier and in many different ways, but 
it's all been based on re-implementing the message unpacking. I'd rather 
use Microsoft's macros, their own code, which in essence /defines/ the 
proper unpacking. Except it's so ugly. :)

0
Alf
12/23/2016 10:06:34 PM
Reply: