Patrik Stridvall ps@leissner.se writes:
We can just do it like: #ifdef __GNUC__ extern inline void FORWARD_WM_COMMAND(HWND hwnd, int id,
HWND hwndCtl, UINT
codeNotify, WNDPROC fn) { fn(hwnd, WM_COMMAND, MAKEWPARAM(id, codeNotify), (LPARAM) hwnd); } #else #define FORWARD_WM_COMMAND(hwnd, id, hwndCtl, codeNotify, fn) \ (void)(fn)((hwnd), WM_COMMAND, MAKEWPARAM((UINT)(id),(UINT)(codeNotify)), (LPARAM)(HWND)(hwndCtl)) #endif
if you wish. And if you are worried about preprocessor abusing Winelib application we could do #if defined(__GNUC__) &&
defined(__WINE__)
instead or use some kind of macro wrap around protection of the kind that I proposed that you didn't like.
If you want to wrap WM_COMMAND, do something like:
inline void send_wm_command(HWND hwnd, int id, HWND hwndCtl, UINT codeNotify) { SendMessageW(hwnd, WM_COMMAND, MAKEWPARAM(id, codeNotify), (LPARAM)hwndCtl); }
This is a normal function, doing a normal SendMessage call, and it's perfectly all right with me. And if you want to do a PostMessage then write a separate post_wm_command() function. Of course this is not a standard Windows API so you cannot put it in the standard header files; but you can have it in some dll private headers, or even directly in the C files that need it.
Ironically that was approximately my original idea. But I didn't think you would accept it so I didn't bother investigating further. Then I realized that the windowsx.h macros did what I wanted so choosed that solution instead.
But sure we have a marshalling/unmarshalling API of our own, if that is what you want. Unless of course you prefer the hack below for PostMessage (not likely :-).
So to the details of the marshalling API (the unmarshalling API can wait). 1. Where should we put them? Suggestion: include/wine/messsage.h 2. What should we call them? Suggestion: {POST,SEND}_WM_COMMAND etc. We really should capitalize the message name because of people doing "grep WM_COMMAND". And not capitalizing the POST/SEND would look silly if the suffix is capitalized. Sure they look like macros but then they could easily be made to be as an alterative implemention like #define SEND_WM_COMMAND(hwnd, id, hwndCtl, codeNotify) \ FORWARD_WM_COMMAND(hwnd, id, hwndCtl, codeNotify, SendMessage) 3. Do you want the macro wrapper (against the FORWARD API) above for the non GNU C case? 4. Should have have {POST,SEND}_WM_COMMAND{A,W} for calling {Post,Send}Message{A,W} or should we always the W variant like in your example above.
To sum it up:
- The FORWARD_* API and the HANDLE_* API really are normal
functions not
macros (preprocessor abuses). The fact Micrsoft
implemented them as macros
because of lack of compiler support for inline functions
or because of
incompetence is irrelevant, we can do it right in a 100%
compatible way.
No we can't; SendMessage and PostMessage don't have the same prototype, so the preprocessor abuse is necessary to avoid warnings.
It seems you are right. PostMessage returns BOOL.
Anyway there are not so many PostMessage calls that can be converted.
$ find . -name *.c | xargs grep PostMessage | grep WM_ | wc -l 35
The type compatible ones on the other hand are
$ find . -name *.c | xargs egrep 'Def.*Proc' | grep WM_ | wc -l 33
$ find . -name *.c | xargs grep SendMessage | grep WM_ | wc -l 420
The Def.*Proc ones doesn't seem of closer examination to require marshalling of parameters so let skip them.
Total 420 compared to 35. So we either decide not to use the the FORWARD_ API for such cases or we do:
BOOL bResult = (BOOL) FORWARD_WM_COMMAND(/* ... */, (WNDPROC) PostMessageW);
The use above is type correct regardless of whether FORWARD_WM_COMMAND is a macro or a inline function. A little ugly yes, but then it isn't nessary to convert the few PostMessage that exists to the FORWARD_* API at all.