Microsoft DirectX 8.1 (Visual Basic)

Using Flags

Many object methods in Microsoft® DirectX® for Microsoft Visual Basic® have a parameter with the Long data type named flags or something similar. Types may also have one or more flag members. These flag fields are a compact way to select from a variety of options and are often used to specify the exact behavior of a method. For example, the flags parameter of DirectInput8.GetDevicesBySemantics enables you to define the scope of the enumeration by selecting from one of several options.

A flag is a single yes-no bit of information. In a flag field, each bit of the integer corresponds to a separate flag that represents an independent piece of information. If the bit is set, the flag is enabled. If the bit is zero, the flag is disabled. Flag fields typically contain a set of related flags that are represented by an enumeration. Normally, the numerical value of each member of the enumeration represents a different bit in the flag field. However, some members may represent combinations of two or more flags.

A common use of flag fields is to enable you to select one option from a variety of options. You normally do so by assigning the appropriate enumerated value to the flag parameter. However, because each flag corresponds to a different bit, flag fields can also be used to select two or more options from a list. To do so, set all the relevant bits by combining the enumerated values of the selected flags with the Or operator. For example, the DirectInputDevice8.SetCooperativeLevel method has a flag field that is used to specify the device's cooperative level. The following code fragment selects a combination of foreground and exclusive cooperative levels by combining the DISCL_FOREGROUND and DISCL_EXCLUSIVE flags.

' diDevice is a DirectInputDevice8 object, and hwnd is a window handle
diDevice.SetCooperativeLevel(hwnd, _
    DISCL_FOREGROUND Or DISCL_EXCLUSIVE)

Note  Examine the reference page carefully to determine how the flag field is to be used. Setting multiple flags in a flag field that is designed to have only one flag set may have unpredictable results.

You should not use the addition operator instead of the Or operator to combine flags. While the two operations are often equivalent, using the addition operator will sometimes lead to incorrect results. In particular, the two operators are usually not equivalent if one of the flags represents a combination of two or more flags. The following example illustrates this case. The CF_PURPLE flag represents a combination of CF_RED and CF_BLUE.

Enum COLORFLAGS
    CF_RED    = 1
    CF_BLUE   = 2
    CF_PURPLE = 3
    CF_GREEN  = 4
End Enum
 
Dim Color As Integer
Color = CF_RED Or CF_PURPLE

The value of Color is now 3. Setting CF_RED has no effect, as that bit was already set by CF_PURPLE.

The following operation, on the other hand, sets an incorrect value:

' This is wrong!
Color = CF_RED + CF_PURPLE

Adding the two flag values sets Color to 4, which is equivalent to CF_GREEN.

When you retrieve a value for flags, you can determine whether an individual flag is set by combining the flag value with the flag field using the And operator. If the bit in the flag field represented by a flag constant is set, an And operation will return a nonzero value indicating that the flag is "on". If the And operation returns zero, the flag is "off". For example the caps parameter of DirectInputDevice8.GetCapabilities method is used to return a DIDEVCAPS type that contains the device capabilities. The lFlags member of this type is a flag field that may have one or more of the flags specified by the CONST_DIDEVCAPSFLAGS enumeration set. If the DIDC_ATTACHED flag is set, the device is physically attached to the system. The following code fragment illustrates how to check whether the device is attached by examining the value of an And operation that combines the lFlags member with DIDC_ATTACHED.

Dim IsAttached As Boolean
IsAttached = diDevCaps.lFlags And DIDC_ATTACHED 

Note that you should not simply test whether lFlags is equal to DIDC_ATTACHED. This flag field may have more than one flag set. If multiple flags are set, the following test will fail, even if DIDC_ATTACHED is set.

' This is wrong!
IsAttached = (diDevCaps.lFlags = DIDC_ATTACHED)