Some things in Win32 development just doesn’t make sense

I have been aware of some of Win32 developments difficulties and seen other highlight things developers need to take into consideration. Many things are not intuitive and takes time to learn and get used to.

Any skilled Win32 developer already know this and tons more, but it might be interesting for some so here I go.

In programming you usually work with boolean expressions and store the results in a variable of datatype boolean. Booleans usually take the form of true and false, you can also see booleans that are not set and therefor undefined. That is a total of three values to keep track of.

In WinDef.h you have a defination that declares BOOL to be of int datatype and this new defined type is used a lot in the Win32 API. Something that looks like a boolean datatype can all of a sudden have all possible values of an int.

typedef int BOOL;

To help the developer there are two defines that are used with the BOOL datatype. FALSE and TRUE.

#define FALSE 0
#define TRUE 1

Beware that this does not mean that a BOOL return value from Win32 API will give either FALSE or TRUE. Take the TrackPopupMenuEx function that you can use to show a context menu, it returns BOOL. It is easy to assume that the returned BOOL will indicate if a selection was made of not and use the TRUE/FALSE defines to determine it. Don’t do that, check the note about the return value.

Return Value

If you specify TPM_RETURNCMD in the fuFlags parameter, the return value is the menu-item identifier of the item that the user selected. If the user cancels the menu without making a selection, or if an error occurs, then the return value is zero.

If you do not specify TPM_RETURNCMD in the fuFlags parameter, the return value is nonzero if the function succeeds and zero if it fails. To get extended error information, call GetLastError.

Depending on what flags you send in the return value will change meaning. Also note that it does not mention TRUE/FALSE but the meaning of zero and non-zero return values. This basically invalidates all comparisons with the TRUE define to see if a returned BOOL was not FALSE.

There is no general help on this, read the documentation carefully and use FALSE define to check for a non-zero return value when it is using BOOL.

if (FALSE != TrackPopupMenuEx(…))
   // Non-zero return value

if (TRUE == TrackPopupMenuEx(…))
   // Only where return value is TRUE (defined as 1)