Sign in to follow this  
Brain

GetMessage: true, false, filenotfound!

Recommended Posts

Brain    18906

Hi all,

 

Whilst browsing MSDN to refresh my memory on the GetMessage function, i found some code (and documentation!) which appeared to have been written by someone who may or may not have been influenced by various illegal substances. Whatever he/she was on, I want some. It must make coding a lot of fun!

 

To summarise;

 

 

Return value

Type: BOOL

If the function retrieves a message other than WM_QUIT, the return value is nonzero.

If the function retrieves the WM_QUIT message, the return value is zero.

If there is an error, the return value is -1. For example, the function fails if hWnd is an invalid window handle or lpMsg is an invalid pointer. To get extended error information, call GetLastError.

Because the return value can be nonzero, zero, or -1, avoid code like this:

while (GetMessage( lpMsg, hWnd, 0, 0)) ...

The possibility of a -1 return value in the case that hWnd is an invalid parameter (such as referring to a window that has already been destroyed) means that such code can lead to fatal application errors. Instead, use code like this:

BOOL bRet;

while( (bRet = GetMessage( &msg, hWnd, 0, 0 )) != 0)
{ 
    if (bRet == -1)
    {
        // handle the error and possibly exit
    }
    else
    {
        TranslateMessage(&msg); 
        DispatchMessage(&msg); 
    }
}

 

... say wha?! blink.png

 

My head hurts :(

Share this post


Link to post
Share on other sites
slicer4ever    6769
as stated in the comments on that page:

Do not confuse the Windows BOOL with the primitive type bool. In Windows, BOOL is a typedef'd int. It is called BOOL because the integer it stores is to be used for logical operations and not arithmetic operations. The primitive bool type remains for regular true/false logic.

Share this post


Link to post
Share on other sites
Brain    18906

as stated in the comments on that page:
 

Do not confuse the Windows BOOL with the primitive type bool. In Windows, BOOL is a typedef'd int. It is called BOOL because the integer it stores is to be used for logical operations and not arithmetic operations. The primitive bool type remains for regular true/false logic.

 

 

A native bool is at least 8 bits wide, wasting 7 bits, does this mean that we should abuse it to hold other values than 0 or 1 too and place a sidenote in the C++ spec to say that this is expected behaviour? :)

 

</sarcasm>

Share this post


Link to post
Share on other sites
slicer4ever    6769

as stated in the comments on that page:
 

Do not confuse the Windows BOOL with the primitive type bool. In Windows, BOOL is a typedef'd int. It is called BOOL because the integer it stores is to be used for logical operations and not arithmetic operations. The primitive bool type remains for regular true/false logic.

 
A native bool is at least 8 bits wide, wasting 7 bits, does this mean that we should abuse it to hold other values than 0 or 1 too and place a sidenote in the C++ spec to say that this is expected behaviour? smile.png
 
</sarcasm>


not saying it's right, just what to expect =-P

Share this post


Link to post
Share on other sites
swiftcoder    18437

A native bool is at least 8 bits wide, wasting 7 bits, does this mean that we should abuse it to hold other values than 0 or 1 too and place a sidenote in the C++ spec to say that this is expected behaviour? smile.png

The fun part is that if you try to do this with the built-in bool type, it won't actually work:
#include <iostream>

int main() {
bool b = -1;

std::cout << b << ", " << (b == -1) << std::endl;

int *c = (int *)&b;
*c = -1;

std::cout << b << ", " << (b == -1) << std::endl;
}
Note that even in the second place, where I've coerced the pointer to an integer to ensure the bit-pattern is stored correctly, the boolean still ends up with a value of true, which is not equal to -1.

Share this post


Link to post
Share on other sites
Brain    18906

On a related note, BBC BASIC was even worse, because it only treated -1 as being TRUE, and 0 as being FALSE. Anything else wasn't either value at all.

 

This is because TRUE == -1 == 11111111 11111111 11111111 11111111b and FALSE == 0 == 00000000 00000000 00000000 0000000b.

 

Makes sense i guess, but ugh. That caused me all kinds of grief back in the 90s...

Share this post


Link to post
Share on other sites
SmkViper    5396

as stated in the comments on that page:


Do not confuse the Windows BOOL with the primitive type bool. In Windows, BOOL is a typedef'd int. It is called BOOL because the integer it stores is to be used for logical operations and not arithmetic operations. The primitive bool type remains for regular true/false logic.

 
A native bool is at least 8 bits wide, wasting 7 bits, does this mean that we should abuse it to hold other values than 0 or 1 too and place a sidenote in the C++ spec to say that this is expected behaviour? smile.png
 
</sarcasm>


You have to remember that Win32 is a C API, not a C++ one. While C99 added a bool type, at the time the Windows API was created there was no bool type, so they had to define one. They most likely picked int because that, by C definition, is always going to be the "native" size of the CPU being run on, so it was assured to be fast to return.

It doesn't necessarily excuse cramming more values then true/false into a "bool" - but you also have to remember that MS has to extend the API over time without breaking backwards compatibility. It's possible that originally it just returned true/false, but at a later date they needed a new return value and implemented it in this way so as not to break legacy code.

Share this post


Link to post
Share on other sites
mhagain    13430

Like everything else (well, almost everything else) in the Windows API that's looks weird on first sight, there's actually a valid historical reason for this.  http://blogs.msdn.com/b/oldnewthing/archive/2013/03/22/10404367.aspx

 

 

But you can calm down. The standard message loop is fine. All the parameters are hard-coded (and therefore valid by inspection), save for the &msg parameter, which is still valid by inspection. So that case is okay. It has to be, for compatibility.

The people who need to worry are people who pass a variable as the window handle filter (because that window handle may no longer be valid), or pass dynamically-allocated memory as the lpMsg (because the pointer may no longer be valid), or who pass a nontrivial message filter (because the filter parameters may be invalid).

Edited by mhagain

Share this post


Link to post
Share on other sites
SmkViper    5396

Like everything else (well, almost everything else) in the Windows API that's looks weird on first sight, there's actually a valid historical reason for this.  http://blogs.msdn.com/b/oldnewthing/archive/2013/03/22/10404367.aspx


But you can calm down. The standard message loop is fine. All the parameters are hard-coded (and therefore valid by inspection), save for the &msg parameter, which is still valid by inspection. So that case is okay. It has to be, for compatibility.

The people who need to worry are people who pass a variable as the window handle filter (because that window handle may no longer be valid), or pass dynamically-allocated memory as the lpMsg (because the pointer may no longer be valid), or who pass a nontrivial message filter (because the filter parameters may be invalid).


That's the post I was thinking of - your google-fu is best.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this