Style question - calling default from several places

P

Paul N

I have a style question. In my code, I have a function that receives
messages, and deals with some of them while passing others on to a
further function. For instance:

LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam,
LPARAM lParam)
{

switch (message) {
case WM_CREATE:
// stuff here
default:
return DefWindowProc(hWnd, message, wParam, lParam); } }

Now, some of the other messages require me, in some circumstances, to
also pass the message on to DefWindowProc either after, or instead of,
dealing with it in my function. Obviously one way to do this is to
simply call DefWindowProc there as well. But I was wondering if there
was a neater way. One way would be to use a goto; a second way would
be to set a flag if I want DefWindowProc to be called and then have

if (flag) DefWindowProc(...)

after the switch. Possibly there's also a way, like Duff's device,
using big "if"s that span the case labels... Anyhow, would anyone
recommend any of these techniques, or are there any other alternatives
I've missed?

Thanks for any thoughts.
Paul.
 
M

Marcel Müller

LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam,
LPARAM lParam)
{

switch (message) {
case WM_CREATE:
// stuff here
default:
return DefWindowProc(hWnd, message, wParam, lParam); } }

Now, some of the other messages require me, in some circumstances, to
also pass the message on to DefWindowProc either after, or instead of,
dealing with it in my function.

Typical problem of the old style window procedures with daisy chained
handlers.

Obviously one way to do this is to
simply call DefWindowProc there as well. But I was wondering if there
was a neater way.

switch (message) {
case WM_CREATE:
// stuff here
break;
case WM_COMMAND:
// stuff here
return 0;
}
return DefWindowProc(hWnd, message, wParam, lParam);


Marcel
 
J

Jorgen Grahn

I have a style question. In my code, I have a function that receives
messages, and deals with some of them while passing others on to a
further function. For instance:

LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam,
LPARAM lParam)
{

Speaking of style, one easy way of increasing readability would be to
give meaningful names to those types, those parameters, and that
function. They may not be under your control, but I have to say they
are among the worst I've seen.

/Jorgen
 
V

Victor Bazarov

Speaking of style, one easy way of increasing readability would be to
give meaningful names to those types, those parameters, and that
function. They may not be under your control, but I have to say they
are among the worst I've seen.

For those who don't dabble in Windows API and messaging: the meaning of
'wParam' and 'lParam' varies widely depending on the _value_ of
'message'. Hence the generic names. It's been like this for some
thirty years, and I have never seen anybody manage to improve on that
much, or even enough for a mention. Some frameworks, like MFC, attempt
to lay out some structure over that system, and not totally
unsuccessfully, methinks, but for a generic message handler like the one
described by the OP there is no real hope. Perhaps the OP should look
into using one of those frameworks...

V
 
P

Paul N

    switch (message) {
      case WM_CREATE:
        // stuff here
        break;
      case WM_COMMAND:
        // stuff here
        return 0;
    }
    return DefWindowProc(hWnd, message, wParam, lParam);

Thanks Marcel. This is indeed a different way of doing it. The snag is
that, at present, most of the cases end in "break" and then end up at
a "return 0;" after the switch. To make the change I would have to
change every one of them - and then remember to do the same for any
new cases I added later. Which seems a bit of a high risk of me
messing it up. But I'll give it a bit more consideration.

Paul.
 
J

Jorgen Grahn

For those who don't dabble in Windows API and messaging: the meaning of
'wParam' and 'lParam' varies widely depending on the _value_ of
'message'. Hence the generic names. It's been like this for some
thirty years, and I have never seen anybody manage to improve on that
much, or even enough for a mention. Some frameworks, like MFC, attempt
to lay out some structure over that system, and not totally
unsuccessfully, methinks, but for a generic message handler like the one
described by the OP there is no real hope. Perhaps the OP should look
into using one of those frameworks...

I've never used these APIs (obviously) but I think I would break out
of the crazy world of UINT and void* (if that is what's behind WPARAM
and LPARAM) as soon as possible. I.e. call my own functions with more
specific types as soon as I see what the callback is about.

The inner structure (or lack thereof) of WndProc() seems less important.

/Jorgen
 
M

Marcel Müller

Thanks Marcel. This is indeed a different way of doing it. The snag is
that, at present, most of the cases end in "break" and then end up at
a "return 0;" after the switch. To make the change I would have to
change every one of them - and then remember to do the same for any
new cases I added later. Which seems a bit of a high risk of me
messing it up. But I'll give it a bit more consideration.

It's your choice.

I prefer to pass any complicated message processing to a dedicated and
strongly typed, private member function. This keeps the message
procedure small and clear. Furthermore this often ends up with something
like
return MyXYHandler((int)mp1, (bool)mp2);

Of course, other handlers may return void and you still need the return
0 to keep the compiler happy.


Marcel
 
V

Victor Bazarov

I've never used these APIs (obviously) but I think I would break out
of the crazy world of UINT and void* (if that is what's behind WPARAM
and LPARAM) as soon as possible. I.e. call my own functions with more
specific types as soon as I see what the callback is about.

That's exactly what those (MFC et al.) frameworks do. They define their
own generic handler and inside they have a rather large and convoluted
switch statement to dispatch the message to specific handlers that are
all declared with more specific types of arguments with more meaningful
names and often re-wrapped into more specific values of more meaningful
types (both Windows-SDK-defined and newly introduced by those frameworks).
The inner structure (or lack thereof) of WndProc() seems less important.

Well, "WndProc" has been the workhorse of the Windows messaging API, and
it's how we all used to write Windows applications before those complete
frameworks came to be. It's primitive. It's simplistic. It gets the
job done. Keep in mind, Windows was running on a personal computer, in
real memory mode... As for programming, it was often recommended to
write your own class framework, but the basis was still the WndProc
functions (which you had to introduce in order to tie into Windows UI,
etc.) Absence of structure was not a concern at all because the purpose
was clear and the method was simple to grasp and easy to follow AFA
implementation goes. Besides, there were so many examples, and they all
looked very similar to what Charles Petzold put in his book^.

But I have digressed...

V

^ - Programming Windows by Charles Petzold, Microsoft Press, 1988.
 
J

Joe keane

int xxx(...)
{
...

switch (op)
{
case OP_A:
...
goto dontcallfunc;

case OP_B:
...
goto docallfunc;

case OP_C:
...
goto dontcallfunc;

case OP_D:
...
goto docallfunc;

default:
...
goto docallfunc;
}

abort();

dontcallfunc:
ret = ...;
goto done;

docallfunc:
ret = func(...);
goto done;

done:
...
return ret;
}
 
J

Jorgen Grahn

Well, "WndProc" has been the workhorse of the Windows messaging API, and
it's how we all used to write Windows applications before those complete
frameworks came to be. It's primitive. It's simplistic. It gets the
job done. ....
Absence of structure was not a concern at all because the purpose
was clear and the method was simple to grasp and easy to follow AFA
implementation goes. Besides, there were so many examples, and they all
looked very similar to what Charles Petzold put in his book^.

Fair enough. I didn't recognize this as a core Windows thing. The OP
didn't say, so I assumed it was forced upon him by some less
well-known API.

/Jorgen
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
474,262
Messages
2,571,048
Members
48,769
Latest member
Clifft

Latest Threads

Top