GetMessage: true, false, filenotfound!

Started by
7 comments, last by SmkViper 9 years, 2 months ago

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 :(

Advertisement
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.

Check out https://www.facebook.com/LiquidGames for some great games made by me on the Playstation Mobile market.

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>

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
Check out https://www.facebook.com/LiquidGames for some great games made by me on the Playstation Mobile market.

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.

Tristam MacDonald. Ex-BigTech Software Engineer. Future farmer. [https://trist.am]

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...

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.

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).

Direct3D has need of instancing, but we do not. We have plenty of glVertexAttrib calls.

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.

This topic is closed to new replies.

Advertisement